Eventually, each entry gets its own structs based on the initial
length field it starts with. The address_size, however, is taken
from base_structs. This appears to be a limitation of the DWARFv3
- standard, fixed in v4 (where an address_size field exists for each
- CFI. A discussion I had on dwarf-discuss confirms this.
- Currently for base_structs I simply use the elfclass of the
- containing file, but more sophisticated methods are used by
- libdwarf and others, such as guessing which CU contains which FDEs
- (based on their address ranges) and taking the address_size from
- those CUs.
+ standard, fixed in v4.
+ A discussion I had on dwarf-discuss confirms this.
+ So for DWARFv4 we'll take the address size from the CIE header,
+ but for earlier versions will use the elfclass of the containing
+ file; more sophisticated methods are used by libdwarf and others,
+ such as guessing which CU contains which FDEs (based on their
+ address ranges) and taking the address_size from those CUs.
"""
def __init__(self, stream, size, base_structs):
self.stream = stream
header = struct_parse(
header_struct, self.stream, offset)
+ # If this is DWARF version 4 or later, we can have a more precise
+ # address size, read from the CIE header.
+ if entry_structs.dwarf_version >= 4:
+ entry_structs = DWARFStructs(
+ little_endian=entry_structs.little_endian,
+ dwarf_format=entry_structs.dwarf_format,
+ address_size=header.address_size)
+
# For convenience, compute the end offset for this entry
end_offset = (
offset + header.length +
debug_info_sec,
debug_abbrev_sec,
debug_frame_sec,
+ eh_frame_sec,
debug_str_sec,
debug_loc_sec,
debug_ranges_sec,
self.debug_info_sec = debug_info_sec
self.debug_abbrev_sec = debug_abbrev_sec
self.debug_frame_sec = debug_frame_sec
+ self.eh_frame_sec = eh_frame_sec
self.debug_str_sec = debug_str_sec
self.debug_loc_sec = debug_loc_sec
self.debug_ranges_sec = debug_ranges_sec
return None
def has_CFI(self):
- """ Does this dwarf info has a CFI section?
+ """ Does this dwarf info have a dwarf_frame CFI section?
"""
return self.debug_frame_sec is not None
def CFI_entries(self):
- """ Get a list of CFI entries from the .debug_frame section.
+ """ Get a list of dwarf_frame CFI entries from the .debug_frame section.
"""
cfi = CallFrameInfo(
stream=self.debug_frame_sec.stream,
base_structs=self.structs)
return cfi.get_entries()
+ def has_EH_CFI(self):
+ """ Does this dwarf info have a eh_frame CFI section?
+ """
+ return self.eh_frame_sec is not None
+
+ def EH_CFI_entries(self):
+ """ Get a list of eh_frame CFI entries from the .eh_frame section.
+ """
+ cfi = CallFrameInfo(
+ stream=self.eh_frame_sec.stream,
+ size=self.eh_frame_sec.size,
+ base_structs=self.structs)
+ return cfi.get_entries()
+
def location_lists(self):
""" Get a LocationLists object representing the .debug_loc section of
the DWARF data, or None if this section doesn't exist.
cu_structs = DWARFStructs(
little_endian=self.config.little_endian,
dwarf_format=dwarf_format,
- address_size=8)
+ address_size=8)
cu_die_offset = self.debug_info_sec.stream.tell()
dwarf_assert(
See also the documentation of public methods.
"""
- def __init__(self, little_endian, dwarf_format, address_size):
- """ little_endian:
+ def __init__(self,
+ little_endian, dwarf_format, address_size, dwarf_version=2):
+ """ dwarf_version:
+ Numeric DWARF version
+
+ little_endian:
True if the file is little endian, False if big
dwarf_format:
self.little_endian = little_endian
self.dwarf_format = dwarf_format
self.address_size = address_size
+ self.dwarf_version = dwarf_version
self._create_structs()
def initial_length_field_size(self):
)
def _create_callframe_entry_headers(self):
- self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
- self.Dwarf_initial_length('length'),
- self.Dwarf_offset('CIE_id'),
- self.Dwarf_uint8('version'),
- CString('augmentation'),
- self.Dwarf_uleb128('code_alignment_factor'),
- self.Dwarf_sleb128('data_alignment_factor'),
- self.Dwarf_uleb128('return_address_register'))
+ # The CIE header was modified in DWARFv4.
+ if self.dwarf_version == 4:
+ self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
+ self.Dwarf_initial_length('length'),
+ self.Dwarf_offset('CIE_id'),
+ self.Dwarf_uint8('version'),
+ CString('augmentation'),
+ self.Dwarf_uint8('address_size'),
+ self.Dwarf_uint8('segment_size'),
+ self.Dwarf_uleb128('code_alignment_factor'),
+ self.Dwarf_sleb128('data_alignment_factor'),
+ self.Dwarf_uleb128('return_address_register'))
+ else:
+ self.Dwarf_CIE_header = Struct('Dwarf_CIE_header',
+ self.Dwarf_initial_length('length'),
+ self.Dwarf_offset('CIE_id'),
+ self.Dwarf_uint8('version'),
+ CString('augmentation'),
+ self.Dwarf_uleb128('code_alignment_factor'),
+ self.Dwarf_sleb128('data_alignment_factor'),
+ self.Dwarf_uleb128('return_address_register'))
self.Dwarf_FDE_header = Struct('Dwarf_FDE_header',
self.Dwarf_initial_length('length'),
#
debug_sections = {}
for secname in (b'.debug_info', b'.debug_abbrev', b'.debug_str',
- b'.debug_line', b'.debug_frame', b'.debug_loc',
- b'.debug_ranges'):
+ b'.debug_line', b'.debug_frame',
+ b'.debug_loc', b'.debug_ranges'):
section = self.get_section_by_name(secname)
if section is None:
debug_sections[secname] = None
else:
debug_sections[secname] = self._read_dwarf_section(
- section,
- relocate_dwarf_sections)
+ section,
+ relocate_dwarf_sections)
return DWARFInfo(
config=DwarfConfig(
debug_info_sec=debug_sections[b'.debug_info'],
debug_abbrev_sec=debug_sections[b'.debug_abbrev'],
debug_frame_sec=debug_sections[b'.debug_frame'],
+ # TODO(eliben): reading of eh_frame is not hooked up yet
+ eh_frame_sec=None,
debug_str_sec=debug_sections[b'.debug_str'],
debug_loc_sec=debug_sections[b'.debug_loc'],
debug_ranges_sec=debug_sections[b'.debug_ranges'],
def _reloc_calc_sym_plus_addend(value, sym_value, offset, addend=0):
return sym_value + addend
+ def _reloc_calc_sym_plus_addend_pcrel(value, sym_value, offset, addend=0):
+ return sym_value + addend - offset
+
_RELOCATION_RECIPES_X86 = {
ENUM_RELOC_TYPE_i386['R_386_NONE']: _RELOCATION_RECIPE_TYPE(
bytesize=4, has_addend=False, calc_func=_reloc_calc_identity),
bytesize=8, has_addend=True, calc_func=_reloc_calc_identity),
ENUM_RELOC_TYPE_x64['R_X86_64_64']: _RELOCATION_RECIPE_TYPE(
bytesize=8, has_addend=True, calc_func=_reloc_calc_sym_plus_addend),
+ ENUM_RELOC_TYPE_x64['R_X86_64_PC32']: _RELOCATION_RECIPE_TYPE(
+ bytesize=8, has_addend=True,
+ calc_func=_reloc_calc_sym_plus_addend_pcrel),
ENUM_RELOC_TYPE_x64['R_X86_64_32']: _RELOCATION_RECIPE_TYPE(
bytesize=4, has_addend=True, calc_func=_reloc_calc_sym_plus_addend),
ENUM_RELOC_TYPE_x64['R_X86_64_32S']: _RELOCATION_RECIPE_TYPE(
--- /dev/null
+/* Generated by compiling with gcc 4.8 as follows:
+**
+** gcc-4.8 -O0 -g -fno-dwarf2-cfi-asm -c dwarf4_simple.c -o gcc48-simple.
+**
+** Note: -fno-dwarf2-cfi-asm to tell gcc to generate .dwarf_frames as well
+** as the .eh_frames it generates by default.
+**
+*/
+
+extern int bar(int);
+extern int baz(int);
+
+int foo(int v) {
+ int x = bar(v);
+ int i;
+ for (i = 0; i < v; ++i)
+ x += bar(i) + bar(v) * baz(i);
+ return x;
+}