]> git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/structanalyze.py
xnu-4570.71.2.tar.gz
[apple/xnu.git] / tools / lldbmacros / structanalyze.py
1 import lldb
2 from xnu import *
3
4 def _showStructPacking(symbol, prefix, begin_offset=0, typedef=None):
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
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"
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
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 :
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