#------------------------------------------------------------------------------- # 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('.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 '' % (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 '' % (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) @property 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 return n 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'])