nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | import gdb |
2 | import sys |
||
3 | |||
4 | if sys.version_info[0] >= 3: |
||
5 | long = int |
||
6 | |||
7 | # This is not quite right, as local vars may override symname |
||
8 | def read_global_var (symname): |
||
9 | return gdb.selected_frame().read_var(symname) |
||
10 | |||
11 | def g_quark_to_string (quark): |
||
12 | if quark == None: |
||
13 | return None |
||
14 | quark = long(quark) |
||
15 | if quark == 0: |
||
16 | return None |
||
17 | try: |
||
18 | val = read_global_var ("quarks") |
||
19 | max_q = long(read_global_var ("quark_seq_id")) |
||
20 | except: |
||
21 | try: |
||
22 | val = read_global_var ("g_quarks") |
||
23 | max_q = long(read_global_var ("g_quark_seq_id")) |
||
24 | except: |
||
25 | return None; |
||
26 | if quark < max_q: |
||
27 | return val[quark].string() |
||
28 | return None |
||
29 | |||
30 | # We override the node printers too, so that node->next is not expanded |
||
31 | class GListNodePrinter: |
||
32 | "Prints a GList node" |
||
33 | |||
34 | def __init__ (self, val): |
||
35 | self.val = val |
||
36 | |||
37 | def to_string (self): |
||
38 | return "{data=%s, next=0x%x, prev=0x%x}" % (str(self.val["data"]), long(self.val["next"]), long(self.val["prev"])) |
||
39 | |||
40 | class GSListNodePrinter: |
||
41 | "Prints a GSList node" |
||
42 | |||
43 | def __init__ (self, val): |
||
44 | self.val = val |
||
45 | |||
46 | def to_string (self): |
||
47 | return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"])) |
||
48 | |||
49 | class GListPrinter: |
||
50 | "Prints a GList" |
||
51 | |||
52 | class _iterator: |
||
53 | def __init__(self, head, listtype): |
||
54 | self.link = head |
||
55 | self.listtype = listtype |
||
56 | self.count = 0 |
||
57 | |||
58 | def __iter__(self): |
||
59 | return self |
||
60 | |||
61 | def next(self): |
||
62 | if self.link == 0: |
||
63 | raise StopIteration |
||
64 | data = self.link['data'] |
||
65 | self.link = self.link['next'] |
||
66 | count = self.count |
||
67 | self.count = self.count + 1 |
||
68 | return ('[%d]' % count, data) |
||
69 | |||
70 | __next__ = next |
||
71 | |||
72 | def __init__ (self, val, listtype): |
||
73 | self.val = val |
||
74 | self.listtype = listtype |
||
75 | |||
76 | def children(self): |
||
77 | return self._iterator(self.val, self.listtype) |
||
78 | |||
79 | def to_string (self): |
||
80 | return "0x%x" % (long(self.val)) |
||
81 | |||
82 | def display_hint (self): |
||
83 | return "array" |
||
84 | |||
85 | class GHashPrinter: |
||
86 | "Prints a GHashTable" |
||
87 | |||
88 | class _iterator: |
||
89 | def __init__(self, ht, keys_are_strings): |
||
90 | self.ht = ht |
||
91 | if ht != 0: |
||
92 | self.keys = ht["keys"] |
||
93 | self.values = ht["values"] |
||
94 | self.hashes = ht["hashes"] |
||
95 | self.size = ht["size"] |
||
96 | self.pos = 0 |
||
97 | self.keys_are_strings = keys_are_strings |
||
98 | self.value = None |
||
99 | |||
100 | def __iter__(self): |
||
101 | return self |
||
102 | |||
103 | def next(self): |
||
104 | if self.ht == 0: |
||
105 | raise StopIteration |
||
106 | if self.value != None: |
||
107 | v = self.value |
||
108 | self.value = None |
||
109 | return v |
||
110 | while long(self.pos) < long(self.size): |
||
111 | self.pos = self.pos + 1 |
||
112 | if long (self.hashes[self.pos]) >= 2: |
||
113 | key = self.keys[self.pos] |
||
114 | val = self.values[self.pos] |
||
115 | |||
116 | if self.keys_are_strings: |
||
117 | key = key.cast (gdb.lookup_type("char").pointer()) |
||
118 | |||
119 | # Queue value for next result |
||
120 | self.value = ('[%dv]'% (self.pos), val) |
||
121 | |||
122 | # Return key |
||
123 | return ('[%dk]'% (self.pos), key) |
||
124 | raise StopIteration |
||
125 | |||
126 | __next__ = next |
||
127 | |||
128 | def __init__ (self, val): |
||
129 | self.val = val |
||
130 | self.keys_are_strings = False |
||
131 | try: |
||
132 | string_hash = read_global_var ("g_str_hash") |
||
133 | except: |
||
134 | string_hash = None |
||
135 | if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash: |
||
136 | self.keys_are_strings = True |
||
137 | |||
138 | def children(self): |
||
139 | return self._iterator(self.val, self.keys_are_strings) |
||
140 | |||
141 | def to_string (self): |
||
142 | return "0x%x" % (long(self.val)) |
||
143 | |||
144 | def display_hint (self): |
||
145 | return "map" |
||
146 | |||
147 | def pretty_printer_lookup (val): |
||
148 | # None yet, want things like hash table and list |
||
149 | |||
150 | type = val.type.unqualified() |
||
151 | |||
152 | # If it points to a reference, get the reference. |
||
153 | if type.code == gdb.TYPE_CODE_REF: |
||
154 | type = type.target () |
||
155 | |||
156 | if type.code == gdb.TYPE_CODE_PTR: |
||
157 | type = type.target().unqualified() |
||
158 | t = str(type) |
||
159 | if t == "GList": |
||
160 | return GListPrinter(val, "GList") |
||
161 | if t == "GSList": |
||
162 | return GListPrinter(val, "GSList") |
||
163 | if t == "GHashTable": |
||
164 | return GHashPrinter(val) |
||
165 | else: |
||
166 | t = str(type) |
||
167 | if t == "GList": |
||
168 | return GListNodePrinter(val) |
||
169 | if t == "GSList *": |
||
170 | return GListPrinter(val, "GSList") |
||
171 | return None |
||
172 | |||
173 | def register (obj): |
||
174 | if obj == None: |
||
175 | obj = gdb |
||
176 | |||
177 | obj.pretty_printers.append(pretty_printer_lookup) |
||
178 | |||
179 | class ForeachCommand (gdb.Command): |
||
180 | """Foreach on list""" |
||
181 | |||
182 | def __init__ (self): |
||
183 | super (ForeachCommand, self).__init__ ("gforeach", |
||
184 | gdb.COMMAND_DATA, |
||
185 | gdb.COMPLETE_SYMBOL) |
||
186 | |||
187 | def valid_name (self, name): |
||
188 | if not name[0].isalpha(): |
||
189 | return False |
||
190 | return True |
||
191 | |||
192 | def parse_args (self, arg): |
||
193 | i = arg.find(" ") |
||
194 | if i <= 0: |
||
195 | raise Exception ("No var specified") |
||
196 | var = arg[:i] |
||
197 | if not self.valid_name(var): |
||
198 | raise Exception ("Invalid variable name") |
||
199 | |||
200 | while i < len (arg) and arg[i].isspace(): |
||
201 | i = i + 1 |
||
202 | |||
203 | if arg[i:i+2] != "in": |
||
204 | raise Exception ("Invalid syntax, missing in") |
||
205 | |||
206 | i = i + 2 |
||
207 | |||
208 | while i < len (arg) and arg[i].isspace(): |
||
209 | i = i + 1 |
||
210 | |||
211 | colon = arg.find (":", i) |
||
212 | if colon == -1: |
||
213 | raise Exception ("Invalid syntax, missing colon") |
||
214 | |||
215 | val = arg[i:colon] |
||
216 | |||
217 | colon = colon + 1 |
||
218 | while colon < len (arg) and arg[colon].isspace(): |
||
219 | colon = colon + 1 |
||
220 | |||
221 | command = arg[colon:] |
||
222 | |||
223 | return (var, val, command) |
||
224 | |||
225 | def do_iter(self, arg, item, command): |
||
226 | item = item.cast (gdb.lookup_type("void").pointer()) |
||
227 | item = long(item) |
||
228 | to_eval = "set $%s = (void *)0x%x\n"%(arg, item) |
||
229 | gdb.execute(to_eval) |
||
230 | gdb.execute(command) |
||
231 | |||
232 | def slist_iterator (self, arg, container, command): |
||
233 | l = container.cast (gdb.lookup_type("GSList").pointer()) |
||
234 | while long(l) != 0: |
||
235 | self.do_iter (arg, l["data"], command) |
||
236 | l = l["next"] |
||
237 | |||
238 | def list_iterator (self, arg, container, command): |
||
239 | l = container.cast (gdb.lookup_type("GList").pointer()) |
||
240 | while long(l) != 0: |
||
241 | self.do_iter (arg, l["data"], command) |
||
242 | l = l["next"] |
||
243 | |||
244 | def pick_iterator (self, container): |
||
245 | t = container.type.unqualified() |
||
246 | if t.code == gdb.TYPE_CODE_PTR: |
||
247 | t = t.target().unqualified() |
||
248 | t = str(t) |
||
249 | if t == "GSList": |
||
250 | return self.slist_iterator |
||
251 | if t == "GList": |
||
252 | return self.list_iterator |
||
253 | raise Exception("Invalid container type %s"%(str(container.type))) |
||
254 | |||
255 | def invoke (self, arg, from_tty): |
||
256 | (var, container, command) = self.parse_args(arg) |
||
257 | container = gdb.parse_and_eval (container) |
||
258 | func = self.pick_iterator(container) |
||
259 | func(var, container, command) |
||
260 | |||
261 | ForeachCommand () |