|
|
|
# HG changeset patch
|
|
|
|
# User Mike Frysinger <vapier@gentoo.org>
|
|
|
|
# Date 1352755639 18000
|
|
|
|
# Node ID a9c9b2f9ec964e6750dd6f9a96767fe2e9201d85
|
|
|
|
# Parent f3408c7b954910aa3a58e88196efba4954c0cc55
|
|
|
|
add support for parsing of the dynamic section/segment and its tags
|
|
|
|
|
|
|
|
diff -r f3408c7b9549 -r a9c9b2f9ec96 elftools/elf/dynamic.py
|
|
|
|
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
|
|
|
|
+++ b/elftools/elf/dynamic.py Mon Nov 12 16:27:19 2012 -0500
|
|
|
|
@@ -0,0 +1,115 @@
|
|
|
|
+#-------------------------------------------------------------------------------
|
|
|
|
+# elftools: elf/dynamic.py
|
|
|
|
+#
|
|
|
|
+# ELF Dynamic Tags
|
|
|
|
+#
|
|
|
|
+# Mike Frysinger (vapier@gentoo.org)
|
|
|
|
+# This code is in the public domain
|
|
|
|
+#-------------------------------------------------------------------------------
|
|
|
|
+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.
|
|
|
|
+ """
|
|
|
|
+ def __init__(self, entry, elffile):
|
|
|
|
+ self.entry = entry
|
|
|
|
+ if entry.d_tag == 'DT_NEEDED' or \
|
|
|
|
+ entry.d_tag == 'DT_RPATH' or \
|
|
|
|
+ entry.d_tag == 'DT_RUNPATH':
|
|
|
|
+ dynstr = elffile.get_section_by_name('.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 == 'DT_NEEDED' or \
|
|
|
|
+ self.entry.d_tag == 'DT_RPATH' or \
|
|
|
|
+ self.entry.d_tag == 'DT_RUNPATH':
|
|
|
|
+ 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)
|
|
|
|
+ """
|
|
|
|
+ offset = self._offset - self._tagsize
|
|
|
|
+ for i in range(self.num_tags):
|
|
|
|
+ offset += self._tagsize
|
|
|
|
+ entry = struct_parse(
|
|
|
|
+ self._elfstructs.Elf_Dyn,
|
|
|
|
+ self._stream,
|
|
|
|
+ stream_pos=offset)
|
|
|
|
+ if type is not None and entry.d_tag != type:
|
|
|
|
+ continue
|
|
|
|
+ yield DynamicTag(entry, self._elffile)
|
|
|
|
+
|
|
|
|
+ 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)
|
|
|
|
+
|
|
|
|
+ @property
|
|
|
|
+ def num_tags(self):
|
|
|
|
+ """ Number of dynamic tags in the file
|
|
|
|
+ """
|
|
|
|
+ if self._num_tags != -1:
|
|
|
|
+ return self._num_tags
|
|
|
|
+
|
|
|
|
+ offset = self._offset
|
|
|
|
+ while True:
|
|
|
|
+ entry = struct_parse(
|
|
|
|
+ self._elfstructs.Elf_Dyn,
|
|
|
|
+ self._stream,
|
|
|
|
+ stream_pos=offset)
|
|
|
|
+ if entry.d_tag == 'DT_NULL':
|
|
|
|
+ self._num_tags = ((offset - self._offset) // self._tagsize) + 1
|
|
|
|
+ break
|
|
|
|
+ offset += self._tagsize
|
|
|
|
+ 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'])
|
|
|
|
diff -r f3408c7b9549 -r a9c9b2f9ec96 elftools/elf/elffile.py
|
|
|
|
--- a/elftools/elf/elffile.py Thu Jul 05 06:32:09 2012 +0300
|
|
|
|
+++ b/elftools/elf/elffile.py Mon Nov 12 16:27:19 2012 -0500
|
|
|
|
@@ -13,6 +13,7 @@
|
|
|
|
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
|
|
|
|
@@ -208,6 +209,8 @@
|
|
|
|
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)
|
|
|
|
|
|
|
|
@@ -241,6 +244,8 @@
|
|
|
|
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)
|
|
|
|
|
|
|
|
diff -r f3408c7b9549 -r a9c9b2f9ec96 elftools/elf/enums.py
|
|
|
|
--- a/elftools/elf/enums.py Thu Jul 05 06:32:09 2012 +0300
|
|
|
|
+++ b/elftools/elf/enums.py Mon Nov 12 16:27:19 2012 -0500
|
|
|
|
@@ -186,6 +186,82 @@
|
|
|
|
_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,
|
|
|
|
diff -r f3408c7b9549 -r a9c9b2f9ec96 elftools/elf/structs.py
|
|
|
|
--- a/elftools/elf/structs.py Thu Jul 05 06:32:09 2012 +0300
|
|
|
|
+++ b/elftools/elf/structs.py Mon Nov 12 16:27:19 2012 -0500
|
|
|
|
@@ -72,6 +72,7 @@
|
|
|
|
self._create_shdr()
|
|
|
|
self._create_sym()
|
|
|
|
self._create_rel()
|
|
|
|
+ self._create_dyn()
|
|
|
|
|
|
|
|
def _create_ehdr(self):
|
|
|
|
self.Elf_Ehdr = Struct('Elf_Ehdr',
|
|
|
|
@@ -165,6 +166,13 @@
|
|
|
|
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']
|