from ..common.utils import (struct_parse, dwarf_assert, preserve_stream_pos)
from ..common.py3compat import iterkeys
from .structs import DWARFStructs
-from .constants import *
+from .constants import *
class CallFrameInfo(object):
""" DWARF CFI (Call Frame Info)
-
+
stream, size:
A stream holding the .debug_frame section, and the size of the
section in it.
entry_structs.Dwarf_offset(''), self.stream)
is_CIE = (
- (dwarf_format == 32 and CIE_id == 0xFFFFFFFF) or
+ (dwarf_format == 32 and CIE_id == 0xFFFFFFFF) or
CIE_id == 0xFFFFFFFFFFFFFFFF)
if is_CIE:
reg_order = []
else: # FDE
# For a FDE, we need to decode the attached CIE first, because its
- # decoded table is needed. Its "initial instructions" describe a
+ # decoded table is needed. Its "initial instructions" describe a
# line that serves as the base (first) line in the FDE's table.
cie = self.cie
cie_decoded_table = cie.get_decoded()
cur_line = last_line_in_CIE
cur_line['pc'] = self['initial_location']
reg_order = copy.copy(cie_decoded_table.reg_order)
-
+
table = []
# Keeps a stack for the use of DW_CFA_{remember|restore}_state
class ELFFile(object):
""" Creation: the constructor accepts a stream (file-like object) with the
contents of an ELF file.
-
+
Accessible attributes:
stream:
The stream holding the data of the file - must be a binary
stream (bytes, not string).
- elfclass:
+ elfclass:
32 or 64 - specifies the word size of the target machine
-
+
little_endian:
- boolean - specifies the target machine's endianness
+ boolean - specifies the target machine's endianness
header:
the complete ELF file header
self.stream.seek(0)
self.e_ident_raw = self.stream.read(16)
-
+
self._file_stringtable_section = self._get_file_stringtable()
self._section_name_map = None
-
+
def num_sections(self):
""" Number of sections in the file
"""
return self['e_shnum']
-
+
def get_section(self, n):
""" Get the section at index #n from the file (Section object or a
subclass)
"""
section_header = self._get_section_header(n)
return self._make_section(section_header)
-
+
def get_section_by_name(self, name):
- """ Get a section from the file, by name. Return None if no such
+ """ Get a section from the file, by name. Return None if no such
section exists.
"""
# The first time this method is called, construct a name to number
self._section_name_map[sec.name] = i
secnum = self._section_name_map.get(name, None)
return None if secnum is None else self.get_section(secnum)
-
+
def iter_sections(self):
""" Yield all the sections in the file
"""
for i in range(self.num_sections()):
yield self.get_section(i)
-
+
def num_segments(self):
""" Number of segments in the file
"""
return self['e_phnum']
-
+
def get_segment(self, n):
""" Get the segment at index #n from the file (Segment object)
"""
yield self.get_segment(i)
def has_dwarf_info(self):
- """ Check whether this file appears to have debugging information.
+ """ Check whether this file appears to have debugging information.
We assume that if it has the debug_info section, it has all theother
required sections as well.
"""
If relocate_dwarf_sections is True, relocations for DWARF sections
are looked up and applied.
"""
- # Expect that has_dwarf_info was called, so at least .debug_info is
- # present.
+ # Expect that has_dwarf_info was called, so at least .debug_info is
+ # present.
# Sections that aren't found will be passed as None to DWARFInfo.
#
debug_sections = {}
- for secname in (b'.debug_info', b'.debug_abbrev', b'.debug_str',
+ for secname in (b'.debug_info', b'.debug_abbrev', b'.debug_str',
b'.debug_line', b'.debug_frame', b'.debug_loc',
b'.debug_ranges'):
section = self.get_section_by_name(secname)
""" Verify the ELF file and identify its class and endianness.
"""
# Note: this code reads the stream directly, without using ELFStructs,
- # since we don't yet know its exact format. ELF was designed to be
+ # since we don't yet know its exact format. ELF was designed to be
# read like this - its e_ident field is word-size and endian agnostic.
#
self.stream.seek(0)
self.little_endian = False
else:
raise ELFError('Invalid EI_DATA %s' % repr(ei_data))
-
+
def _section_offset(self, n):
""" Compute the offset of section #n in the file
"""
return self['e_shoff'] + n * self['e_shentsize']
-
+
def _segment_offset(self, n):
""" Compute the offset of segment #n in the file
"""
return self['e_phoff'] + n * self['e_phentsize']
-
+
def _make_segment(self, segment_header):
""" Create a Segment object of the appropriate type
"""
return Segment(segment_header, self.stream)
def _get_section_header(self, n):
- """ Find the header of section #n, parse it and return the struct
+ """ Find the header of section #n, parse it and return the struct
"""
return struct_parse(
self.structs.Elf_Shdr,
self.stream,
stream_pos=self._section_offset(n))
-
+
def _get_section_name(self, section_header):
""" Given a section header, find this section's name in the file's
string table
"""
name = self._get_section_name(section_header)
sectype = section_header['sh_type']
-
+
if sectype == 'SHT_STRTAB':
return StringTableSection(section_header, name, self.stream)
elif sectype == 'SHT_NULL':
self.structs.Elf_Phdr,
self.stream,
stream_pos=self._segment_offset(n))
-
+
def _get_file_stringtable(self):
""" Find the file's string table section
"""
def __init__(self, header, stream):
self.header = header
self.stream = stream
-
+
def data(self):
""" The segment data from the file.
"""
def section_in_segment(self, section):
""" Is the given section contained in this segment?
- Note: this tries to reproduce the intricate rules of the
- ELF_SECTION_IN_SEGMENT_STRICT macro of the header
+ Note: this tries to reproduce the intricate rules of the
+ ELF_SECTION_IN_SEGMENT_STRICT macro of the header
elf/include/internal.h in the source of binutils.
"""
# Only the 'strict' checks from ELF_SECTION_IN_SEGMENT_1 are included
# Only PT_LOAD, PT_GNU_RELR0 and PT_TLS segments can contain SHF_TLS
# sections
- if ( secflags & SH_FLAGS.SHF_TLS and
+ if ( secflags & SH_FLAGS.SHF_TLS and
segtype in ('PT_TLS', 'PT_GNU_RELR0', 'PT_LOAD')):
return False
# PT_TLS segment contains only SHF_TLS sections, PT_PHDR no sections
# not match at the very end of the segment (unless the segment is
# also zero size, which is handled by the second condition).
if not (secaddr >= vaddr and
- secaddr - vaddr + section['sh_size'] <= self['p_memsz'] and
+ secaddr - vaddr + section['sh_size'] <= self['p_memsz'] and
secaddr - vaddr <= self['p_memsz'] - 1):
return False
# Same logic as with secaddr vs. vaddr checks above, just on offsets in
# the file
- return (secoffset >= poffset and
+ return (secoffset >= poffset and
secoffset - poffset + section['sh_size'] <= self['p_filesz'] and
secoffset - poffset <= self['p_filesz'] - 1)