From: eliben Date: Thu, 8 Sep 2011 11:49:30 +0000 (+0300) Subject: * Added handling of segments X-Git-Tag: v0.10~137 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a6416fd4d6c24e29a4b781360a5f973aa4bfd363;p=pyelftools.git * Added handling of segments * Added iteration API for sections --- diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 11d3704..01be519 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -13,6 +13,7 @@ from ..exceptions import ELFError, ELFParseError from ..construct import ConstructError, CString from .structs import ELFStructs from .sections import Section +from .segments import Segment class ELFFile(object): @@ -37,7 +38,7 @@ class ELFFile(object): self._stringtable = self._get_stringtable() def num_sections(self): - """ Get the number of sections in the file + """ Number of sections in the file """ return self['e_shnum'] @@ -48,6 +49,29 @@ class ELFFile(object): name = self._get_section_name(section_header) return Section(section_header, name, self.stream) + 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) + """ + segment_header = self._get_segment_header(n) + return Segment(segment_header, self.stream) + + def iter_segments(self): + """ Yield all the segments in the file + """ + for i in range(self.num_segments()): + yield self.get_segment(i) + #-------------------------------- PRIVATE --------------------------------# def __getitem__(self, name): @@ -87,12 +111,23 @@ class ELFFile(object): """ 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 _get_section_header(self, n): """ Find the header of section #n, parse it and return the struct """ self.stream.seek(self._section_offset(n)) return self._struct_parse(self.structs.Elf_Shdr) + def _get_segment_header(self, n): + """ Find the header of segment #n, parse it and return the struct + """ + self.stream.seek(self._segment_offset(n)) + return self._struct_parse(self.structs.Elf_Phdr) + def _get_section_name(self, section_header): """ Given a section header, find this section's name in the file's string table, and return it as a normal Python string. diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py index 1217d74..cdaf316 100644 --- a/elftools/elf/enums.py +++ b/elftools/elf/enums.py @@ -89,6 +89,7 @@ ENUM_SH_TYPE = dict( ) # p_type in the program header +# some values scavenged from the ELF headers in binutils-2.21 ENUM_P_TYPE = dict( PT_NULL=0, PT_LOAD=1, @@ -99,5 +100,8 @@ ENUM_P_TYPE = dict( PT_PHDR=6, PT_LOPROC=0x70000000, PT_HIPROC=0x7fffffff, + PT_GNU_EH_FRAME=0x6474e550, + PT_GNU_STACK=0x6474e551, + PT_GNU_RELRO=0x6474e552, ) diff --git a/elftools/elf/segments.py b/elftools/elf/segments.py new file mode 100644 index 0000000..02a81ed --- /dev/null +++ b/elftools/elf/segments.py @@ -0,0 +1,25 @@ +#------------------------------------------------------------------------------- +# elftools: elf/segments.py +# +# ELF segments +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- + +class Segment(object): + def __init__(self, header, stream): + self.header = header + self.stream = stream + + def data(self): + """ The segment data from the file. + """ + self.stream.seek(self['p_offset']) + return self.stream.read(self['p_filesz']) + + def __getitem__(self, name): + """ Implement dict-like access to header entries + """ + return self.header[name] + diff --git a/z.py b/z.py index c74a4ff..9f208d3 100644 --- a/z.py +++ b/z.py @@ -9,12 +9,18 @@ stream = open('binfiles/z.elf', 'rb') efile = ELFFile(stream) -print 'num', efile.num_sections() -sec = efile.get_section(39) +for sec in efile.iter_sections(): + print sec.name + +for seg in efile.iter_segments(): + print seg['p_type'], seg['p_offset'] + +#~ print 'num', efile.num_sections() +#~ sec = efile.get_section(39) #~ print sec.header -print sec.name -print sec['sh_type'] -print map(ord, sec.data()) +#~ print sec.name +#~ print sec['sh_type'] +#~ print map(ord, sec.data()) #~ print sec.stream #~ print map(ord, efile._stringtable)