]>
Commit | Line | Data |
---|---|---|
39236c6e A |
1 | """ |
2 | Defines a class value which encapsulates the basic lldb Scripting Bridge APIs. This provides an easy | |
f427ee49 | 3 | wrapper to extract information from C based constructs. |
39236c6e A |
4 | |------- core.value------------| |
5 | | |--lldb Scripting Bridge--| | | |
f427ee49 | 6 | | | |--lldb core--| | | |
39236c6e A |
7 | | |-------------------------| | |
8 | |------------------------------| | |
9 | Use the member function GetSBValue() to access the base Scripting Bridge value. | |
10 | """ | |
11 | import lldb | |
12 | import re | |
13 | from lazytarget import * | |
14 | ||
15 | _cstring_rex = re.compile("((?:\s*|const\s+)\s*char(?:\s+\*|\s+[A-Za-z_0-9]*\s*\[|)\s*)",re.MULTILINE|re.DOTALL) | |
16 | ||
17 | class value(object): | |
18 | '''A class designed to wrap lldb.SBValue() objects so the resulting object | |
19 | can be used as a variable would be in code. So if you have a Point structure | |
20 | variable in your code in the current frame named "pt", you can initialize an instance | |
21 | of this class with it: | |
f427ee49 | 22 | |
39236c6e A |
23 | pt = lldb.value(lldb.frame.FindVariable("pt")) |
24 | print pt | |
25 | print pt.x | |
26 | print pt.y | |
27 | ||
28 | pt = lldb.value(lldb.frame.FindVariable("rectangle_array")) | |
29 | print rectangle_array[12] | |
30 | print rectangle_array[5].origin.x''' | |
31 | def __init__(self, sbvalue): | |
f427ee49 | 32 | #_sbval19k84obscure747 is specifically chosen to be obscure. |
39236c6e A |
33 | #This avoids conflicts when attributes could mean any field value in code |
34 | self._sbval19k84obscure747 = sbvalue | |
35 | self._sbval19k84obscure747_type = sbvalue.GetType() | |
36 | self._sbval19k84obscure747_is_ptr = sbvalue.GetType().IsPointerType() | |
37 | self.sbvalue = sbvalue | |
38 | ||
39 | def __nonzero__(self): | |
40 | return ( self._sbval19k84obscure747.__nonzero__() and self._GetValueAsUnsigned() != 0 ) | |
41 | ||
42 | def __repr__(self): | |
43 | return self._sbval19k84obscure747.__str__() | |
f427ee49 | 44 | |
39236c6e | 45 | def __cmp__(self, other): |
5ba3f43e | 46 | if type(other) is int or type(other) is long: |
39236c6e A |
47 | me = int(self) |
48 | if type(me) is long: | |
49 | other = long(other) | |
50 | return me.__cmp__(other) | |
51 | if type(other) is value: | |
94ff46dc A |
52 | try: |
53 | return int(self).__cmp__(int(other)) | |
54 | except TypeError: # Try promoting to long | |
55 | return long(self).__cmp__(long(other)) | |
5ba3f43e | 56 | raise TypeError("Cannot compare value with type {}".format(type(other))) |
f427ee49 | 57 | |
39236c6e A |
58 | def __str__(self): |
59 | global _cstring_rex | |
60 | type_name = self._sbval19k84obscure747_type.GetName() | |
61 | if len(_cstring_rex.findall(type_name)) > 0 : | |
62 | return self._GetValueAsString() | |
63 | summary = self._sbval19k84obscure747.GetSummary() | |
64 | if summary: | |
65 | return summary.strip('"') | |
66 | return self._sbval19k84obscure747.__str__() | |
67 | ||
68 | def __getitem__(self, key): | |
69 | # Allow array access if this value has children... | |
70 | if type(key) is slice: | |
71 | _start = int(key.start) | |
72 | _end = int(key.stop) | |
73 | _step = 1 | |
74 | if key.step != None: | |
75 | _step = int(key.step) | |
76 | retval = [] | |
77 | while _start < _end: | |
78 | retval.append(self[_start]) | |
79 | _start += _step | |
80 | return retval | |
81 | if type(key) in (int, long): | |
82 | return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % key)) | |
83 | if type(key) is value: | |
84 | return value(self._sbval19k84obscure747.GetValueForExpressionPath("[%i]" % int(key))) | |
85 | raise TypeError("Cannot fetch Array item for this type") | |
86 | ||
87 | def __getattr__(self, name): | |
88 | child_sbvalue = self._sbval19k84obscure747.GetChildMemberWithName (name) | |
89 | if child_sbvalue: | |
90 | return value(child_sbvalue) | |
91 | raise AttributeError("No field by name: "+name ) | |
92 | ||
93 | def __add__(self, other): | |
94 | return int(self) + int(other) | |
f427ee49 | 95 | |
39236c6e A |
96 | def __radd__(self, other): |
97 | return int(self) + int(other) | |
f427ee49 | 98 | |
39236c6e A |
99 | def __sub__(self, other): |
100 | return int(self) - int(other) | |
f427ee49 | 101 | |
39236c6e A |
102 | def __rsub__(self, other): |
103 | return int(other) - int(self) | |
f427ee49 | 104 | |
39236c6e A |
105 | def __mul__(self, other): |
106 | return int(self) * int(other) | |
f427ee49 | 107 | |
39236c6e A |
108 | def __rmul__(self, other): |
109 | return int(self) * int(other) | |
f427ee49 | 110 | |
39236c6e A |
111 | def __floordiv__(self, other): |
112 | return int(self) // int(other) | |
f427ee49 | 113 | |
39236c6e A |
114 | def __mod__(self, other): |
115 | return int(self) % int(other) | |
f427ee49 | 116 | |
39236c6e A |
117 | def __rmod__(self, other): |
118 | return int(other) % int(self) | |
f427ee49 | 119 | |
39236c6e A |
120 | def __divmod__(self, other): |
121 | return int(self) % int(other) | |
f427ee49 | 122 | |
39236c6e A |
123 | def __rdivmod__(self, other): |
124 | return int(other) % int(self) | |
f427ee49 | 125 | |
39236c6e A |
126 | def __pow__(self, other): |
127 | return int(self) ** int(other) | |
f427ee49 | 128 | |
39236c6e A |
129 | def __lshift__(self, other): |
130 | return int(self) << int(other) | |
f427ee49 | 131 | |
39236c6e A |
132 | def __rshift__(self, other): |
133 | return int(self) >> int(other) | |
f427ee49 | 134 | |
39236c6e A |
135 | def __and__(self, other): |
136 | return int(self) & int(other) | |
f427ee49 | 137 | |
39236c6e A |
138 | def __rand(self, other): |
139 | return int(self) & int(other) | |
f427ee49 | 140 | |
39236c6e A |
141 | def __xor__(self, other): |
142 | return int(self) ^ int(other) | |
f427ee49 | 143 | |
39236c6e A |
144 | def __or__(self, other): |
145 | return int(self) | int(other) | |
f427ee49 | 146 | |
39236c6e A |
147 | def __div__(self, other): |
148 | return int(self) / int(other) | |
f427ee49 | 149 | |
39236c6e A |
150 | def __rdiv__(self, other): |
151 | return int(other)/int(self) | |
f427ee49 | 152 | |
39236c6e A |
153 | def __truediv__(self, other): |
154 | return int(self) / int(other) | |
f427ee49 | 155 | |
39236c6e A |
156 | def __iadd__(self, other): |
157 | result = self.__add__(other) | |
158 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
159 | return result | |
f427ee49 | 160 | |
39236c6e A |
161 | def __isub__(self, other): |
162 | result = self.__sub__(other) | |
163 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
164 | return result | |
f427ee49 | 165 | |
39236c6e A |
166 | def __imul__(self, other): |
167 | result = self.__mul__(other) | |
168 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
169 | return result | |
f427ee49 | 170 | |
39236c6e A |
171 | def __idiv__(self, other): |
172 | result = self.__div__(other) | |
173 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
174 | return result | |
f427ee49 | 175 | |
39236c6e A |
176 | def __itruediv__(self, other): |
177 | result = self.__truediv__(other) | |
178 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
179 | return result | |
f427ee49 | 180 | |
39236c6e A |
181 | def __ifloordiv__(self, other): |
182 | result = self.__floordiv__(self, other) | |
183 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
184 | return result | |
f427ee49 | 185 | |
39236c6e A |
186 | def __imod__(self, other): |
187 | result = self.__and__(self, other) | |
188 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
189 | return result | |
f427ee49 | 190 | |
39236c6e A |
191 | def __ipow__(self, other): |
192 | result = self.__pow__(self, other) | |
193 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
194 | return result | |
f427ee49 | 195 | |
39236c6e A |
196 | def __ipow__(self, other, modulo): |
197 | result = self.__pow__(self, other, modulo) | |
198 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
199 | return result | |
f427ee49 | 200 | |
39236c6e A |
201 | def __ilshift__(self, other): |
202 | result = self.__lshift__(other) | |
203 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
204 | return result | |
f427ee49 | 205 | |
39236c6e A |
206 | def __irshift__(self, other): |
207 | result = self.__rshift__(other) | |
208 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
209 | return result | |
f427ee49 | 210 | |
39236c6e A |
211 | def __iand__(self, other): |
212 | result = self.__and__(self, other) | |
213 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
214 | return result | |
f427ee49 | 215 | |
39236c6e A |
216 | def __ixor__(self, other): |
217 | result = self.__xor__(self, other) | |
218 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
219 | return result | |
f427ee49 | 220 | |
39236c6e A |
221 | def __ior__(self, other): |
222 | result = self.__ior__(self, other) | |
223 | self._sbval19k84obscure747.SetValueFromCString (str(result)) | |
224 | return result | |
f427ee49 | 225 | |
39236c6e A |
226 | def __neg__(self): |
227 | return -int(self) | |
f427ee49 | 228 | |
39236c6e A |
229 | def __pos__(self): |
230 | return +int(self) | |
f427ee49 | 231 | |
39236c6e A |
232 | def __abs__(self): |
233 | return abs(int(self)) | |
f427ee49 | 234 | |
39236c6e A |
235 | def __invert__(self): |
236 | return ~int(self) | |
f427ee49 | 237 | |
39236c6e A |
238 | def __complex__(self): |
239 | return complex (int(self)) | |
f427ee49 | 240 | |
39236c6e A |
241 | def __int__(self): |
242 | if self._sbval19k84obscure747_is_ptr: | |
243 | return self._GetValueAsUnsigned() | |
244 | tname= self._sbval19k84obscure747_type.GetName() | |
245 | if tname.find('uint') >= 0 or tname.find('unsigned') >= 0: | |
246 | return self._GetValueAsUnsigned() | |
247 | retval = self._sbval19k84obscure747.GetValueAsSigned() | |
248 | # <rdar://problem/12481949> lldb python: GetValueAsSigned does not return the correct value | |
249 | if (retval & 0x80000000): | |
250 | retval = retval - 0x100000000 | |
251 | return retval | |
f427ee49 | 252 | |
39236c6e A |
253 | def __long__(self): |
254 | return self._sbval19k84obscure747.GetValueAsSigned() | |
f427ee49 | 255 | |
39236c6e A |
256 | def __float__(self): |
257 | return float (self._sbval19k84obscure747.GetValueAsSigned()) | |
f427ee49 | 258 | |
39236c6e A |
259 | def __oct__(self): |
260 | return '0%o' % self._GetValueAsUnsigned() | |
f427ee49 | 261 | |
39236c6e A |
262 | def __hex__(self): |
263 | return '0x%x' % self._GetValueAsUnsigned() | |
264 | ||
265 | def __eq__(self, other): | |
f427ee49 | 266 | self_val = self._GetValueAsUnsigned() |
39236c6e | 267 | if type(other) is value: |
f427ee49 | 268 | other_val = other._GetValueAsUnsigned() |
39236c6e A |
269 | return self_val == other_val |
270 | if type(other) is int: | |
271 | return int(self) == other | |
272 | raise TypeError("Equality operation is not defined for this type.") | |
f427ee49 | 273 | |
39236c6e A |
274 | def __neq__(self, other): |
275 | return not self.__eq__(other) | |
f427ee49 | 276 | |
39236c6e A |
277 | def GetSBValue(self): |
278 | return self._sbval19k84obscure747 | |
f427ee49 | 279 | |
fe8ab488 A |
280 | def __getstate__(self): |
281 | err = lldb.SBError() | |
282 | if self._sbval19k84obscure747_is_ptr: | |
f427ee49 | 283 | addr = self._sbval19k84obscure747.GetValueAsAddress() |
fe8ab488 A |
284 | size = self._sbval19k84obscure747_type.GetPointeeType().GetByteSize() |
285 | else: | |
f427ee49 | 286 | addr = self._sbval19k84obscure747.AddressOf().GetValueAsAddress() |
fe8ab488 | 287 | size = self._sbval19k84obscure747_type.GetByteSize() |
f427ee49 | 288 | |
fe8ab488 A |
289 | content = LazyTarget.GetProcess().ReadMemory(addr, size, err) |
290 | if err.fail: | |
291 | content = '' | |
292 | return content | |
293 | ||
39236c6e | 294 | def _GetValueAsSigned(self): |
cb323159 A |
295 | if self._sbval19k84obscure747_is_ptr: |
296 | print "ERROR: You cannot get 'int' from pointer type %s, please use unsigned(obj) for such purposes." % str(self._sbval19k84obscure747_type) | |
297 | raise ValueError("Cannot get signed int for pointer data.") | |
39236c6e A |
298 | serr = lldb.SBError() |
299 | retval = self._sbval19k84obscure747.GetValueAsSigned(serr) | |
300 | if serr.success: | |
301 | return retval | |
302 | raise ValueError("Failed to read signed data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString()) | |
cb323159 A |
303 | |
304 | def _GetValueAsCast(self, dest_type): | |
305 | if type(dest_type) is not lldb.SBType: | |
306 | raise ValueError("Invalid type for dest_type: {}".format(type(dest_type))) | |
307 | addr = self._GetValueAsUnsigned() | |
308 | sbval = self._sbval19k84obscure747.target.CreateValueFromExpression("newname", "(void *)"+str(addr)) | |
309 | val = value(sbval.Cast(dest_type)) | |
310 | return val | |
311 | ||
39236c6e A |
312 | def _GetValueAsUnsigned(self): |
313 | serr = lldb.SBError() | |
cb323159 A |
314 | if self._sbval19k84obscure747_is_ptr: |
315 | retval = self._sbval19k84obscure747.GetValueAsAddress() | |
316 | else: | |
317 | retval = self._sbval19k84obscure747.GetValueAsUnsigned(serr) | |
39236c6e A |
318 | if serr.success: |
319 | return retval | |
320 | raise ValueError("Failed to read unsigned data. "+ str(self._sbval19k84obscure747) +"(type =" + str(self._sbval19k84obscure747_type) + ") Error description: " + serr.GetCString()) | |
f427ee49 | 321 | |
39236c6e A |
322 | def _GetValueAsString(self, offset = 0, maxlen = 1024): |
323 | serr = lldb.SBError() | |
324 | sbdata = None | |
cb323159 | 325 | if self._sbval19k84obscure747_is_ptr: |
39236c6e A |
326 | sbdata = self._sbval19k84obscure747.GetPointeeData(offset, maxlen) |
327 | else: | |
328 | sbdata = self._sbval19k84obscure747.GetData() | |
f427ee49 | 329 | |
39236c6e A |
330 | retval = '' |
331 | bytesize = sbdata.GetByteSize() | |
332 | if bytesize == 0 : | |
333 | #raise ValueError('Unable to read value as string') | |
334 | return '' | |
335 | for i in range(0, bytesize) : | |
336 | serr.Clear() | |
337 | ch = chr(sbdata.GetUnsignedInt8(serr, i)) | |
338 | if serr.fail : | |
339 | raise ValueError("Unable to read string data: " + serr.GetCString()) | |
340 | if ch == '\0': | |
341 | break | |
342 | retval += ch | |
f427ee49 A |
343 | return retval |
344 | ||
39236c6e A |
345 | def __format__(self, format_spec): |
346 | ret_format = "{0:"+format_spec+"}" | |
347 | # typechar is last char. see http://www.python.org/dev/peps/pep-3101/ | |
348 | type_spec=format_spec.strip().lower()[-1] | |
349 | if type_spec == 'x': | |
350 | return ret_format.format(self._GetValueAsUnsigned()) | |
351 | if type_spec == 'd': | |
352 | return ret_format.format(int(self)) | |
353 | if type_spec == 's': | |
354 | return ret_format.format(str(self)) | |
355 | if type_spec == 'o': | |
356 | return ret_format.format(int(oct(self))) | |
357 | if type_spec == 'c': | |
358 | return ret_format.format(int(self)) | |
f427ee49 | 359 | |
39236c6e | 360 | return "unknown format " + format_spec + str(self) |
f427ee49 A |
361 | |
362 | ||
39236c6e A |
363 | def unsigned(val): |
364 | """ Helper function to get unsigned value from core.value | |
365 | params: val - value (see value class above) representation of an integer type | |
f427ee49 | 366 | returns: int which is unsigned. |
39236c6e A |
367 | raises : ValueError if the type cannot be represented as unsigned int. |
368 | """ | |
369 | if type(val) is value: | |
370 | return val._GetValueAsUnsigned() | |
371 | return int(val) | |
372 | ||
373 | def sizeof(t): | |
f427ee49 | 374 | """ Find the byte size of a type. |
39236c6e A |
375 | params: t - str : ex 'time_spec' returns equivalent of sizeof(time_spec) in C |
376 | t - value: ex a value object. returns size of the object | |
f427ee49 | 377 | returns: int - byte size length |
39236c6e A |
378 | """ |
379 | if type(t) is value : | |
380 | return t.GetSBValue().GetByteSize() | |
381 | if type(t) is str: | |
382 | return gettype(t).GetByteSize() | |
383 | raise ValueError("Cannot get sizeof. Invalid argument") | |
f427ee49 A |
384 | |
385 | ||
39236c6e A |
386 | def dereference(val): |
387 | """ Get a dereferenced obj for a pointer type obj | |
388 | params: val - value object representing a pointer type C construct in lldb | |
389 | returns: value - value | |
390 | ex. val = dereference(ptr_obj) #python | |
391 | is same as | |
392 | obj_ptr = (int *)0x1234 #C | |
393 | val = *obj_ptr #C | |
394 | """ | |
cb323159 | 395 | if type(val) is value and val._sbval19k84obscure747_is_ptr: |
39236c6e A |
396 | return value(val.GetSBValue().Dereference()) |
397 | raise TypeError('Cannot dereference this type.') | |
f427ee49 | 398 | |
39236c6e | 399 | def addressof(val): |
f427ee49 | 400 | """ Get address of a core.value object. |
39236c6e A |
401 | params: val - value object representing a C construct in lldb |
402 | returns: value - value object referring to 'type(val) *' type | |
f427ee49 | 403 | ex. addr = addressof(hello_obj) #python |
39236c6e A |
404 | is same as |
405 | uintptr_t addr = (uintptr_t)&hello_obj #C | |
406 | """ | |
407 | if type(val) is value: | |
408 | return value(val.GetSBValue().AddressOf()) | |
409 | raise TypeError("Cannot do addressof for non-value type objects") | |
410 | ||
411 | def cast(obj, target_type): | |
412 | """ Type cast an object to another C type. | |
413 | params: | |
414 | obj - core.value object representing some C construct in lldb | |
415 | target_type - str : ex 'char *' | |
416 | - lldb.SBType : | |
417 | """ | |
418 | dest_type = target_type | |
419 | if type(target_type) is str: | |
420 | dest_type = gettype(target_type) | |
421 | elif type(target_type) is value: | |
422 | dest_type = target_type.GetSBValue().GetType() | |
423 | ||
cb323159 A |
424 | if type(obj) is value: |
425 | return obj._GetValueAsCast(dest_type) | |
39236c6e | 426 | elif type(obj) is int: |
f427ee49 | 427 | print "ERROR: You cannot cast an 'int' to %s, please use kern.GetValueFromAddress() for such purposes." % str(target_type) |
39236c6e A |
428 | raise TypeError("object of type %s cannot be casted to %s" % (str(type(obj)), str(target_type))) |
429 | ||
d9a64523 A |
430 | def containerof(obj, target_type, field_name): |
431 | """ Type cast an object to another C type from a pointer to a field. | |
432 | params: | |
433 | obj - core.value object representing some C construct in lldb | |
434 | target_type - str : ex 'struct thread' | |
435 | - lldb.SBType : | |
436 | field_name - the field name within the target_type obj is a pointer to | |
437 | """ | |
438 | addr = int(obj) - getfieldoffset(target_type, field_name) | |
439 | obj = value(obj.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr))) | |
440 | return cast(obj, target_type + " *") | |
441 | ||
813fb2f6 | 442 | |
39236c6e A |
443 | _value_types_cache={} |
444 | ||
445 | def gettype(target_type): | |
446 | """ Returns lldb.SBType of the given target_type | |
447 | params: | |
448 | target_type - str, ex. 'char', 'uint32_t' etc | |
449 | returns: | |
450 | lldb.SBType - SBType corresponding to the given target_type | |
451 | raises: | |
452 | NameError - Incase the type is not identified | |
453 | """ | |
454 | global _value_types_cache | |
39236c6e | 455 | target_type = str(target_type).strip() |
813fb2f6 A |
456 | if target_type in _value_types_cache: |
457 | return _value_types_cache[target_type] | |
458 | ||
5ba3f43e A |
459 | target_type = target_type.strip() |
460 | ||
461 | requested_type_is_struct = False | |
462 | m = re.match(r'\s*struct\s*(.*)$', target_type) | |
463 | if m: | |
464 | requested_type_is_struct = True | |
465 | target_type = m.group(1) | |
466 | ||
813fb2f6 A |
467 | tmp_type = None |
468 | requested_type_is_pointer = False | |
469 | if target_type.endswith('*') : | |
470 | requested_type_is_pointer = True | |
471 | ||
472 | # tmp_type = LazyTarget.GetTarget().FindFirstType(target_type.rstrip('*').strip()) | |
473 | search_type = target_type.rstrip('*').strip() | |
474 | type_arr = [t for t in LazyTarget.GetTarget().FindTypes(search_type)] | |
475 | ||
5ba3f43e A |
476 | if requested_type_is_struct: |
477 | type_arr = [t for t in type_arr if t.type == lldb.eTypeClassStruct] | |
478 | ||
813fb2f6 A |
479 | # After the sort, the struct type with more fields will be at index [0]. |
480 | # This hueristic helps selecting struct type with more fields compared to ones with "opaque" members | |
481 | type_arr.sort(reverse=True, key=lambda x: x.GetNumberOfFields()) | |
482 | if len(type_arr) > 0: | |
483 | tmp_type = type_arr[0] | |
484 | else: | |
485 | raise NameError('Unable to find type '+target_type) | |
486 | ||
487 | if not tmp_type.IsValid(): | |
488 | raise NameError('Unable to Cast to type '+target_type) | |
489 | ||
490 | if requested_type_is_pointer: | |
491 | tmp_type = tmp_type.GetPointerType() | |
492 | _value_types_cache[target_type] = tmp_type | |
493 | ||
39236c6e A |
494 | return _value_types_cache[target_type] |
495 | ||
813fb2f6 | 496 | |
39236c6e A |
497 | def getfieldoffset(struct_type, field_name): |
498 | """ Returns the byte offset of a field inside a given struct | |
5ba3f43e | 499 | Understands anonymous unions and field names in sub-structs |
39236c6e A |
500 | params: |
501 | struct_type - str or lldb.SBType, ex. 'struct ipc_port *' or port.gettype() | |
502 | field_name - str, name of the field inside the struct ex. 'ip_messages' | |
503 | returns: | |
504 | int - byte offset of the field_name inside the struct_type | |
505 | raises: | |
506 | TypeError - - In case the struct_type has no field with the name field_name | |
507 | """ | |
5ba3f43e | 508 | |
39236c6e A |
509 | if type(struct_type) == str: |
510 | struct_type = gettype(struct_type) | |
5ba3f43e A |
511 | |
512 | if '.' in field_name : | |
513 | # Handle recursive fields in sub-structs | |
514 | components = field_name.split('.', 1) | |
515 | for field in struct_type.get_fields_array(): | |
516 | if str(field.GetName()) == components[0]: | |
517 | return getfieldoffset(struct_type, components[0]) + getfieldoffset(field.GetType(), components[1]) | |
518 | raise TypeError('Field name "%s" not found in type "%s"' % (components[0], str(struct_type))) | |
519 | ||
39236c6e A |
520 | offset = 0 |
521 | for field in struct_type.get_fields_array(): | |
522 | if str(field.GetName()) == field_name: | |
523 | return field.GetOffsetInBytes() | |
5ba3f43e | 524 | |
39037602 A |
525 | # Hack for anonymous unions - the compiler does this, so cvalue should too |
526 | if field.GetName() is None and field.GetType().GetTypeClass() == lldb.eTypeClassUnion : | |
527 | for union_field in field.GetType().get_fields_array(): | |
528 | if str(union_field.GetName()) == field_name: | |
529 | return union_field.GetOffsetInBytes() + field.GetOffsetInBytes() | |
39236c6e A |
530 | raise TypeError('Field name "%s" not found in type "%s"' % (field_name, str(struct_type))) |
531 | ||
532 | def islong(x): | |
533 | """ Returns True if a string represents a long integer, False otherwise | |
534 | """ | |
535 | try: | |
536 | long(x,16) | |
537 | except ValueError: | |
538 | try: | |
539 | long(x) | |
540 | except ValueError: | |
541 | return False | |
542 | return True | |
fe8ab488 A |
543 | |
544 | def readmemory(val): | |
545 | """ Returns a string of hex data that is referenced by the value. | |
f427ee49 A |
546 | params: val - a value object. |
547 | return: str - string of hex bytes. | |
fe8ab488 A |
548 | raises: TypeError if val is not a valid type |
549 | """ | |
550 | if not type(val) is value: | |
551 | raise TypeError('%s is not of type value' % str(type(val))) | |
552 | return val.__getstate__() | |
f427ee49 A |
553 | |
554 | def getOSPtr(cpp_obj): | |
555 | """ Returns a core.value created from an intrusive_shared_ptr or itself, cpp_obj | |
556 | params: cpp_obj - core.value object representing a C construct in lldb | |
557 | return: core.value - newly created core.value or cpp_obj | |
558 | """ | |
559 | child = cpp_obj._sbval19k84obscure747.GetChildAtIndex(0) | |
560 | if 'intrusive_shared_ptr' in str(child): | |
561 | return value(child.GetChildMemberWithName('ptr_')) | |
562 | return cpp_obj |