1 #-------------------------------------------------------------------------------
2 # elftools: dwarf/compileunit.py
6 # Eli Bendersky (eliben@gmail.com)
7 # This code is in the public domain
8 #-------------------------------------------------------------------------------
12 class CompileUnit(object):
13 """ A DWARF compilation unit (CU).
15 A normal compilation unit typically represents the text and data
16 contributed to an executable by a single relocatable object file.
17 It may be derived from several source files,
18 including pre-processed "include files"
20 Serves as a container and context to DIEs that describe objects and code
21 belonging to a compilation unit.
23 CU header entries can be accessed as dict keys from this object, i.e.
25 cu['version'] # version field of the CU header
27 To get the top-level DIE describing the compilation unit, call the
30 def __init__(self
, header
, dwarfinfo
, structs
, cu_offset
, cu_die_offset
):
32 CU header for this compile unit
35 The DWARFInfo context object which created this one
38 A DWARFStructs instance suitable for this compile unit
41 Offset in the stream to the beginning of this CU (its header)
44 Offset in the stream of the top DIE of this CU
46 self
.dwarfinfo
= dwarfinfo
48 self
.structs
= structs
49 self
.cu_offset
= cu_offset
50 self
.cu_die_offset
= cu_die_offset
52 # The abbreviation table for this CU. Filled lazily when DIEs are
54 self
._abbrev
_table
= None
56 # A list of DIEs belonging to this CU. Lazily parsed.
59 def dwarf_format(self
):
60 """ Get the DWARF format (32 or 64) for this CU
62 return self
.structs
.dwarf_format
64 def get_abbrev_table(self
):
65 """ Get the abbreviation table (AbbrevTable object) for this CU
67 if self
._abbrev
_table
is None:
68 self
._abbrev
_table
= self
.dwarfinfo
.get_abbrev_table(
69 self
['debug_abbrev_offset'])
70 return self
._abbrev
_table
72 def get_top_DIE(self
):
73 """ Get the top DIE (which is either a DW_TAG_compile_unit or
74 DW_TAG_partial_unit) of this CU
76 return self
._get
_DIE
(0)
79 """ Iterate over all the DIEs in the CU, in order of their appearance.
80 Note that null DIEs will also be returned.
83 return iter(self
._dielist
)
85 #------ PRIVATE ------#
87 def __getitem__(self
, name
):
88 """ Implement dict-like access to header entries
90 return self
.header
[name
]
92 def _get_DIE(self
, index
):
93 """ Get the DIE at the given index
96 return self
._dielist
[index
]
98 def _parse_DIEs(self
):
99 """ Parse all the DIEs pertaining to this CU from the stream and shove
100 them sequentially into self._dielist.
101 Also set the child/sibling/parent links in the DIEs according
102 (unflattening the prefix-order of the DIE tree).
104 if len(self
._dielist
) > 0:
107 # Compute the boundary (one byte past the bounds) of this CU in the
109 cu_boundary
= ( self
.cu_offset
+
110 self
['unit_length'] +
111 self
.structs
.initial_length_field_size())
113 # First pass: parse all DIEs and place them into self._dielist
114 die_offset
= self
.cu_die_offset
115 while die_offset
< cu_boundary
:
118 stream
=self
.dwarfinfo
.debug_info_sec
.stream
,
120 self
._dielist
.append(die
)
121 die_offset
+= die
.size
123 # Second pass - unflatten the DIE tree
124 self
._unflatten
_tree
()
126 def _unflatten_tree(self
):
127 """ "Unflatten" the DIE tree from it serial representation, by setting
128 the child/sibling/parent links of DIEs.
130 Assumes self._dielist was already populated by a linear list of DIEs
131 read from the stream section
133 # the first DIE in the list is the root node
134 root
= self
._dielist
[0]
137 for die
in self
._dielist
[1:]:
138 if not die
.is_null():
139 cur_parent
= parentstack
[-1]
140 # This DIE is a child of the current parent
141 cur_parent
.add_child(die
)
142 die
.set_parent(cur_parent
)
144 parentstack
.append(die
)
146 # parentstack should not be really empty here. However, some
147 # compilers generate DWARF that has extra NULLs in the end and
148 # we don't want pyelftools to fail parsing them just because of
150 if len(parentstack
) > 0:
151 # end of children for the current parent