# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------------
-from .enums import ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
+from .enums import (
+ ENUM_D_TAG, ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
+ )
from .constants import P_FLAGS, SH_FLAGS
from ..common.py3compat import iteritems
else:
return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
+def describe_dyn_tag(x):
+ return _DESCR_D_TAG.get(x, _unknown)
+
#-------------------------------------------------------------------------------
_unknown = '<unknown>'
_DESCR_RELOC_TYPE_x64 = dict(
(v, k) for k, v in iteritems(ENUM_RELOC_TYPE_x64))
-
+_DESCR_D_TAG = dict(
+ (v, k) for k, v in iteritems(ENUM_D_TAG))
--- /dev/null
+#-------------------------------------------------------------------------------
+# elftools: elf/dynamic.py
+#
+# ELF Dynamic Tags
+#
+# Mike Frysinger (vapier@gentoo.org)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+import itertools
+
+from .sections import Section
+from .segments import Segment
+from ..common.utils import struct_parse
+
+from .enums import ENUM_D_TAG
+
+
+class DynamicTag(object):
+ """ Dynamic Tag object - representing a single dynamic tag entry from a
+ dynamic section.
+
+ Similarly to Section objects, allows dictionary-like access to the
+ dynamic tag.
+ """
+
+ _HANDLED_TAGS = frozenset(['DT_NEEDED', 'DT_RPATH', 'DT_RUNPATH'])
+
+ def __init__(self, entry, elffile):
+ self.entry = entry
+ if entry.d_tag in self._HANDLED_TAGS:
+ dynstr = elffile.get_section_by_name(b'.dynstr')
+ setattr(self, entry.d_tag[3:].lower(), dynstr.get_string(self.entry.d_val))
+
+ def __getitem__(self, name):
+ """ Implement dict-like access to entries
+ """
+ return self.entry[name]
+
+ def __repr__(self):
+ return '<DynamicTag (%s): %r>' % (self.entry.d_tag, self.entry)
+
+ def __str__(self):
+ if self.entry.d_tag in self._HANDLED_TAGS:
+ s = '"%s"' % getattr(self, self.entry.d_tag[3:].lower())
+ else:
+ s = '%#x' % self.entry.d_ptr
+ return '<DynamicTag (%s) %s>' % (self.entry.d_tag, s)
+
+
+class Dynamic(object):
+ def __init__(self, stream, elffile, position):
+ self._stream = stream
+ self._elffile = elffile
+ self._elfstructs = elffile.structs
+ self._num_tags = -1;
+ self._offset = position
+ self._tagsize = self._elfstructs.Elf_Dyn.sizeof()
+
+ def iter_tags(self, type=None):
+ """ Yield all tags (limit to |type| if specified)
+ """
+ for n in itertools.count():
+ tag = self.get_tag(n)
+ if type is None or tag.entry.d_tag == type:
+ yield tag
+ if tag.entry.d_tag == 'DT_NULL':
+ break
+
+ def get_tag(self, n):
+ """ Get the tag at index #n from the file (DynamicTag object)
+ """
+ offset = self._offset + n * self._tagsize
+ entry = struct_parse(
+ self._elfstructs.Elf_Dyn,
+ self._stream,
+ stream_pos=offset)
+ return DynamicTag(entry, self._elffile)
+
+ def num_tags(self):
+ """ Number of dynamic tags in the file
+ """
+ if self._num_tags != -1:
+ return self._num_tags
+
+ for n in itertools.count():
+ tag = self.get_tag(n)
+ if tag.entry.d_tag == 'DT_NULL':
+ self._num_tags = n + 1
+ return self._num_tags
+
+
+class DynamicSection(Section, Dynamic):
+ """ ELF dynamic table section. Knows how to process the list of tags.
+ """
+ def __init__(self, header, name, stream, elffile):
+ Section.__init__(self, header, name, stream)
+ Dynamic.__init__(self, stream, elffile, self['sh_offset'])
+
+
+class DynamicSegment(Segment, Dynamic):
+ """ ELF dynamic table segment. Knows how to process the list of tags.
+ """
+ def __init__(self, header, stream, elffile):
+ Segment.__init__(self, header, stream)
+ Dynamic.__init__(self, stream, elffile, self['p_offset'])
from .structs import ELFStructs
from .sections import (
Section, StringTableSection, SymbolTableSection, NullSection)
+from .dynamic import DynamicSection, DynamicSegment
from .relocation import RelocationSection, RelocationHandler
from .segments import Segment, InterpSegment
from .enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
segtype = segment_header['p_type']
if segtype == 'PT_INTERP':
return InterpSegment(segment_header, self.stream)
+ elif segtype == 'PT_DYNAMIC':
+ return DynamicSegment(segment_header, self.stream, self)
else:
return Segment(segment_header, self.stream)
elif sectype in ('SHT_REL', 'SHT_RELA'):
return RelocationSection(
section_header, name, self.stream, self)
+ elif sectype == 'SHT_DYNAMIC':
+ return DynamicSection(section_header, name, self.stream, self)
else:
return Section(section_header, name, self.stream)
_default_=Pass,
)
+# d_tag
+ENUM_D_TAG = dict(
+ DT_NULL=0,
+ DT_NEEDED=1,
+ DT_PLTRELSZ=2,
+ DT_PLTGOT=3,
+ DT_HASH=4,
+ DT_STRTAB=5,
+ DT_SYMTAB=6,
+ DT_RELA=7,
+ DT_RELASZ=8,
+ DT_RELAENT=9,
+ DT_STRSZ=10,
+ DT_SYMENT=11,
+ DT_INIT=12,
+ DT_FINI=13,
+ DT_SONAME=14,
+ DT_RPATH=15,
+ DT_SYMBOLIC=16,
+ DT_REL=17,
+ DT_RELSZ=18,
+ DT_RELENT=19,
+ DT_PLTREL=20,
+ DT_DEBUG=21,
+ DT_TEXTREL=22,
+ DT_JMPREL=23,
+ DT_BIND_NOW=24,
+ DT_INIT_ARRAY=25,
+ DT_FINI_ARRAY=26,
+ DT_INIT_ARRAYSZ=27,
+ DT_FINI_ARRAYSZ=28,
+ DT_RUNPATH=29,
+ DT_FLAGS=30,
+ DT_ENCODING=32,
+ DT_PREINIT_ARRAY=32,
+ DT_PREINIT_ARRAYSZ=33,
+ DT_NUM=34,
+ DT_LOOS=0x6000000d,
+ DT_HIOS=0x6ffff000,
+ DT_LOPROC=0x70000000,
+ DT_HIPROC=0x7fffffff,
+ DT_PROCNUM=0x35,
+ DT_VALRNGLO=0x6ffffd00,
+ DT_GNU_PRELINKED=0x6ffffdf5,
+ DT_GNU_CONFLICTSZ=0x6ffffdf6,
+ DT_GNU_LIBLISTSZ=0x6ffffdf7,
+ DT_CHECKSUM=0x6ffffdf8,
+ DT_PLTPADSZ=0x6ffffdf9,
+ DT_MOVEENT=0x6ffffdfa,
+ DT_MOVESZ=0x6ffffdfb,
+ DT_SYMINSZ=0x6ffffdfe,
+ DT_SYMINENT=0x6ffffdff,
+ DT_GNU_HASH=0x6ffffef5,
+ DT_TLSDESC_PLT=0x6ffffef6,
+ DT_TLSDESC_GOT=0x6ffffef7,
+ DT_GNU_CONFLICT=0x6ffffef8,
+ DT_GNU_LIBLIST=0x6ffffef9,
+ DT_CONFIG=0x6ffffefa,
+ DT_DEPAUDIT=0x6ffffefb,
+ DT_AUDIT=0x6ffffefc,
+ DT_PLTPAD=0x6ffffefd,
+ DT_MOVETAB=0x6ffffefe,
+ DT_SYMINFO=0x6ffffeff,
+ DT_VERSYM=0x6ffffff0,
+ DT_RELACOUNT=0x6ffffff9,
+ DT_RELCOUNT=0x6ffffffa,
+ DT_FLAGS_1=0x6ffffffb,
+ DT_VERDEF=0x6ffffffc,
+ DT_VERDEFNUM=0x6ffffffd,
+ DT_VERNEED=0x6ffffffe,
+ DT_VERNEEDNUM=0x6fffffff,
+ DT_AUXILIARY=0x7ffffffd,
+ DT_FILTER=0x7fffffff,
+ _default_=Pass,
+)
+
ENUM_RELOC_TYPE_i386 = dict(
R_386_NONE=0,
R_386_32=1,
self._create_shdr()
self._create_sym()
self._create_rel()
+ self._create_dyn()
def _create_ehdr(self):
self.Elf_Ehdr = Struct('Elf_Ehdr',
self.Elf_sxword('r_addend'),
)
+ def _create_dyn(self):
+ self.Elf_Dyn = Struct('Elf_Dyn',
+ Enum(self.Elf_sxword('d_tag'), **ENUM_D_TAG),
+ self.Elf_xword('d_val'),
+ Value('d_ptr', lambda ctx: ctx['d_val']),
+ )
+
def _create_sym(self):
# st_info is hierarchical. To access the type, use
# container['st_info']['type']
from elftools.common.py3compat import (
ifilter, byte2int, bytes2str, itervalues, str2bytes)
from elftools.elf.elffile import ELFFile
+from elftools.elf.dynamic import DynamicSection, DynamicSegment
+from elftools.elf.enums import ENUM_D_TAG
from elftools.elf.segments import InterpSegment
from elftools.elf.sections import SymbolTableSection
from elftools.elf.relocation import RelocationSection
describe_e_version_numeric, describe_p_type, describe_p_flags,
describe_sh_type, describe_sh_flags,
describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
- describe_symbol_shndx, describe_reloc_type,
+ describe_symbol_shndx, describe_reloc_type, describe_dyn_tag,
)
from elftools.dwarf.dwarfinfo import DWARFInfo
from elftools.dwarf.descriptions import (
describe_symbol_shndx(symbol['st_shndx']),
bytes2str(symbol.name)))
+ def display_dynamic_tags(self):
+ """ Display the dynamic tags contained in the file
+ """
+ has_dynamic_section = False
+ for section in self.elffile.iter_sections():
+ if not isinstance(section, DynamicSection):
+ continue
+
+ has_relocation_sections = True
+ self._emitline("\nDynamic section at offset %s contains %s entries:" % (
+ self._format_hex(section['sh_offset']),
+ section.num_tags()))
+ self._emitline(" Tag Type Name/Value")
+
+ hexwidth = 8 if self.elffile.elfclass == 32 else 16
+ padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
+ for tag in section.iter_tags():
+ if tag.entry.d_tag == 'DT_NEEDED':
+ parsed = 'Shared library: [%s]' % tag.needed
+ elif tag.entry.d_tag == 'DT_RPATH':
+ parsed = 'Library rpath: [%s]' % tag.rpath
+ elif tag.entry.d_tag == 'DT_RUNPATH':
+ parsed = 'Library runpath: [%s]' % tag.runpath
+ elif (tag.entry.d_tag.endswith('SZ') or
+ tag.entry.d_tag.endswith('ENT')):
+ parsed = '%i (bytes)' % tag['d_val']
+ elif tag.entry.d_tag.endswith('NUM'):
+ parsed = '%i' % tag['d_val']
+ elif tag.entry.d_tag == 'DT_PLTREL':
+ s = describe_dyn_tag(tag.entry.d_val)
+ if s.startswith('DT_'):
+ s = s[3:]
+ parsed = '%s' % s
+ else:
+ parsed = '%#x' % tag['d_val']
+
+ self._emitline(" %s %-*s %s" % (
+ self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
+ fieldsize=hexwidth, lead0x=True),
+ padding,
+ '(%s)' % (tag.entry.d_tag[3:],),
+ parsed))
+
def display_relocations(self):
""" Display the relocations contained in the file
"""
add_help_option=False, # -h is a real option of readelf
prog='readelf.py',
version=VERSION_STRING)
+ optparser.add_option('-d', '--dynamic',
+ action='store_true', dest='show_dynamic_tags',
+ help='Display the dynamic section')
optparser.add_option('-H', '--help',
action='store_true', dest='help',
help='Display this information')
if do_program_header:
readelf.display_program_headers(
show_heading=not do_file_header)
+ if options.show_dynamic_tags:
+ readelf.display_dynamic_tags()
if options.show_symbols:
readelf.display_symbol_tables()
if options.show_relocs:
success = True
testlog.info("Test file '%s'" % filename)
for option in [
- '-e', '-s', '-r', '-x.text', '-p.shstrtab',
+ '-e', '-d', '-s', '-r', '-x.text', '-p.shstrtab',
'--debug-dump=info', '--debug-dump=decodedline',
'--debug-dump=frames', '--debug-dump=frames-interp']:
if verbose: testlog.info("..option='%s'" % option)