]>
Commit | Line | Data |
---|---|---|
fe8ab488 A |
1 | import lldb |
2 | from xnu import * | |
3 | ||
39037602 | 4 | def _showStructPacking(symbol, prefix, begin_offset=0, typedef=None): |
fe8ab488 A |
5 | """ |
6 | recursively parse the field members of structure. | |
7 | params : symbol (lldb.SBType) reference to symbol in binary | |
8 | prefix (string) string to be prefixed for each line of output. Useful for recursive struct parsing. | |
9 | returns: string containing lines of output. | |
10 | """ | |
11 | ctype = "unknown type" | |
12 | if symbol.GetTypeClass() == lldb.eTypeClassUnion : | |
13 | ctype = "union" | |
14 | if symbol.GetTypeClass() == lldb.eTypeClassStruct : | |
15 | ctype = "struct" | |
39037602 A |
16 | |
17 | if typedef: | |
18 | outstr = "[%4d] (%s) (%s) %s { " % (symbol.GetByteSize(), typedef, ctype, symbol.GetName()) + "\n" | |
19 | else : | |
20 | outstr = "[%4d] (%s) %s { " % (symbol.GetByteSize(), ctype, symbol.GetName()) + "\n" | |
fe8ab488 A |
21 | numFields = symbol.GetNumberOfFields() |
22 | _has_memory_hole = False | |
23 | _compact_size = 0 # asuming the struct is perfectly packed | |
24 | _compact_offset = begin_offset | |
25 | _previous_bit_offset = 0 | |
26 | for i in range(numFields): | |
27 | member = symbol.GetFieldAtIndex(i) | |
28 | m_offset = member.GetOffsetInBytes() + begin_offset | |
29 | m_offset_bits = member.GetOffsetInBits() | |
30 | m_type = member.GetType() | |
31 | m_name = member.GetName() | |
32 | m_size = m_type.GetByteSize() | |
33 | warningstr = "" | |
34 | debugstr = "" # + str((m_size, m_offset , m_offset_bits, _previous_bit_offset, _compact_offset, begin_offset)) | |
35 | if _compact_offset != m_offset and (m_offset_bits - _previous_bit_offset) > m_size*8 : | |
36 | _has_memory_hole = True | |
37 | warningstr = " *** Possible memory hole ***" | |
38 | _compact_offset = m_offset | |
39 | _compact_offset += m_size | |
39037602 A |
40 | |
41 | _type_class = m_type.GetTypeClass() | |
42 | _canonical_type = m_type.GetCanonicalType() | |
43 | _canonical_type_class = m_type.GetCanonicalType().GetTypeClass() | |
44 | ||
45 | if _type_class == lldb.eTypeClassTypedef and (_canonical_type_class == lldb.eTypeClassStruct or _canonical_type_class == lldb.eTypeClassUnion) : | |
46 | outstr += prefix + ("*%4d," % m_offset) + _showStructPacking(_canonical_type, prefix+" ", m_offset, str(m_type)) + warningstr + debugstr + "\n" | |
47 | elif _type_class == lldb.eTypeClassStruct or _type_class == lldb.eTypeClassUnion : | |
fe8ab488 A |
48 | outstr += prefix + ("*%4d," % m_offset) + _showStructPacking(m_type, prefix+" ", m_offset) + warningstr + debugstr + "\n" |
49 | else: | |
50 | outstr += prefix + ("+%4d,[%4d] (%s) %s" % (m_offset, m_size, m_type.GetName(), m_name)) + warningstr + debugstr + "\n" | |
51 | if i > 0 : | |
52 | _previous_bit_offset = m_offset_bits | |
53 | outstr += prefix + "}" | |
54 | if _has_memory_hole == True : | |
55 | outstr += " *** Warning: Struct layout leaves memory hole *** " | |
56 | return outstr | |
57 | ||
58 | @lldb_command('showstructpacking') | |
59 | def showStructInfo(cmd_args=None): | |
60 | """Show how a structure is packed in the binary. The format is | |
61 | +<offset>, [<size_of_member>] (<type>) <name> | |
62 | For example: | |
63 | (lldb) script lldbmacros.showStructInfo("pollfd") | |
64 | [ 8] (struct) pollfd { | |
65 | + 0,[ 4] (int) fd | |
66 | + 4,[ 2] (short) events | |
67 | + 6,[ 2] (short) revents | |
68 | } | |
69 | syntax: showstructpacking task | |
70 | """ | |
71 | if not cmd_args: | |
72 | raise ArgumentError("Please provide a type name.") | |
73 | ||
74 | sym = gettype(cmd_args[0]) | |
75 | if sym == None: | |
76 | print "No such struct found" | |
77 | if sym.GetTypeClass() == lldb.eTypeClassTypedef: | |
78 | sym = sym.GetCanonicalType() | |
79 | if sym.GetTypeClass() != lldb.eTypeClassStruct: | |
80 | print "%s is not a structure" % cmd_args[0] | |
81 | else: | |
82 | print _showStructPacking(sym,"", 0) | |
83 | ||
84 | # EndMacro: showstructinto |