]>
Commit | Line | Data |
---|---|---|
fe8ab488 A |
1 | import lldb |
2 | from xnu import * | |
3 | ||
4 | def _showStructPacking(symbol, prefix, begin_offset=0): | |
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" | |
16 | outstr = "[%4d] (%s) %s { " % (symbol.GetByteSize(), ctype, symbol.GetName()) + "\n" | |
17 | numFields = symbol.GetNumberOfFields() | |
18 | _has_memory_hole = False | |
19 | _compact_size = 0 # asuming the struct is perfectly packed | |
20 | _compact_offset = begin_offset | |
21 | _previous_bit_offset = 0 | |
22 | for i in range(numFields): | |
23 | member = symbol.GetFieldAtIndex(i) | |
24 | m_offset = member.GetOffsetInBytes() + begin_offset | |
25 | m_offset_bits = member.GetOffsetInBits() | |
26 | m_type = member.GetType() | |
27 | m_name = member.GetName() | |
28 | m_size = m_type.GetByteSize() | |
29 | warningstr = "" | |
30 | debugstr = "" # + str((m_size, m_offset , m_offset_bits, _previous_bit_offset, _compact_offset, begin_offset)) | |
31 | if _compact_offset != m_offset and (m_offset_bits - _previous_bit_offset) > m_size*8 : | |
32 | _has_memory_hole = True | |
33 | warningstr = " *** Possible memory hole ***" | |
34 | _compact_offset = m_offset | |
35 | _compact_offset += m_size | |
36 | if m_type.GetTypeClass() == lldb.eTypeClassStruct or m_type.GetTypeClass() == lldb.eTypeClassUnion : | |
37 | outstr += prefix + ("*%4d," % m_offset) + _showStructPacking(m_type, prefix+" ", m_offset) + warningstr + debugstr + "\n" | |
38 | else: | |
39 | outstr += prefix + ("+%4d,[%4d] (%s) %s" % (m_offset, m_size, m_type.GetName(), m_name)) + warningstr + debugstr + "\n" | |
40 | if i > 0 : | |
41 | _previous_bit_offset = m_offset_bits | |
42 | outstr += prefix + "}" | |
43 | if _has_memory_hole == True : | |
44 | outstr += " *** Warning: Struct layout leaves memory hole *** " | |
45 | return outstr | |
46 | ||
47 | @lldb_command('showstructpacking') | |
48 | def showStructInfo(cmd_args=None): | |
49 | """Show how a structure is packed in the binary. The format is | |
50 | +<offset>, [<size_of_member>] (<type>) <name> | |
51 | For example: | |
52 | (lldb) script lldbmacros.showStructInfo("pollfd") | |
53 | [ 8] (struct) pollfd { | |
54 | + 0,[ 4] (int) fd | |
55 | + 4,[ 2] (short) events | |
56 | + 6,[ 2] (short) revents | |
57 | } | |
58 | syntax: showstructpacking task | |
59 | """ | |
60 | if not cmd_args: | |
61 | raise ArgumentError("Please provide a type name.") | |
62 | ||
63 | sym = gettype(cmd_args[0]) | |
64 | if sym == None: | |
65 | print "No such struct found" | |
66 | if sym.GetTypeClass() == lldb.eTypeClassTypedef: | |
67 | sym = sym.GetCanonicalType() | |
68 | if sym.GetTypeClass() != lldb.eTypeClassStruct: | |
69 | print "%s is not a structure" % cmd_args[0] | |
70 | else: | |
71 | print _showStructPacking(sym,"", 0) | |
72 | ||
73 | # EndMacro: showstructinto |