From: PromyLOPh Date: Sat, 25 Feb 2017 15:50:52 +0000 (+0100) Subject: Add .stab section parser (#137) X-Git-Tag: v0.25~48 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d65ab038fa662f0d588f881a0733f365c43f365d;p=pyelftools.git Add .stab section parser (#137) * Add .stab section parser * Replace tabs with spaces * Add unit test for stabs parser --- diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py index 64fd479..20e070d 100644 --- a/elftools/elf/elffile.py +++ b/elftools/elf/elffile.py @@ -24,7 +24,8 @@ from ..common.utils import struct_parse, elf_assert from .structs import ELFStructs from .sections import ( Section, StringTableSection, SymbolTableSection, - SUNWSyminfoTableSection, NullSection, NoteSection) + SUNWSyminfoTableSection, NullSection, NoteSection, + StabSection) from .dynamic import DynamicSection, DynamicSegment from .relocation import RelocationSection, RelocationHandler from .gnuversions import ( @@ -308,6 +309,8 @@ class ELFFile(object): return DynamicSection(section_header, name, self.stream, self) elif sectype == 'SHT_NOTE': return NoteSection(section_header, name, self.stream, self) + elif sectype == 'SHT_PROGBITS' and name == '.stab': + return StabSection(section_header, name, self.stream, self) else: return Section(section_header, name, self.stream) diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 1bc1715..c772958 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -195,3 +195,28 @@ class NoteSection(Section): others. """ return iter_notes(self.elffile, self['sh_offset'], self['sh_size']) + +class StabSection(Section): + """ ELF stab section. + """ + def __init__(self, header, name, stream, elffile): + super(StabSection, self).__init__(header, name, stream) + self.elffile = elffile + + def iter_stabs(self): + """ Yield all stab entries. Result type is ELFStructs.Elf_Stabs. + """ + elffile = self.elffile + offset = self['sh_offset'] + size = self['sh_size'] + end = offset + size + while offset < end: + stabs = struct_parse( + elffile.structs.Elf_Stabs, + elffile.stream, + stream_pos=offset) + stabs['n_offset'] = offset + offset += elffile.structs.Elf_Stabs.sizeof() + elffile.stream.seek(offset) + yield stabs + diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index d2404ab..8cbeb5c 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -78,6 +78,7 @@ class ELFStructs(object): self._create_gnu_verdef() self._create_gnu_versym() self._create_note() + self._create_stabs() def _create_ehdr(self): self.Elf_Ehdr = Struct('Elf_Ehdr', @@ -269,3 +270,14 @@ class ELFStructs(object): self.Elf_word('abi_minor'), self.Elf_word('abi_tiny'), ) + + def _create_stabs(self): + # Structure of one stabs entry, see binutils/bfd/stabs.c + # Names taken from https://sourceware.org/gdb/current/onlinedocs/stabs.html#Overview + self.Elf_Stabs = Struct('Elf_Stabs', + self.Elf_word('n_strx'), + self.Elf_byte('n_type'), + self.Elf_byte('n_other'), + self.Elf_half('n_desc'), + self.Elf_word('n_value'), + ) diff --git a/test/test_stab.py b/test/test_stab.py new file mode 100644 index 0000000..83067b8 --- /dev/null +++ b/test/test_stab.py @@ -0,0 +1,38 @@ +try: + import unittest2 as unittest +except ImportError: + import unittest +import os + +from utils import setup_syspath; setup_syspath() +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import StabSection + +class TestStab(unittest.TestCase): + def test_stab(self): + expected = [ + ("obj_stabs.S", 0, 0, 0x2, 33), # generated by compiler + ("label", 0x95, 0xc8, 0x4072, 0xdeadbeef), + ("another label", 0x41, 0x66, 0xf9b1, 0xcafebabe), + ] + with open(os.path.join('test', 'testfiles_for_unittests', + 'obj_stabs.elf'), 'rb') as f: + elf = ELFFile(f) + + # using correct type? + for s in elf.iter_sections(): + if s.name == '.stab': + self.assertIsInstance (s, StabSection) + + # check section contents + stab = elf.get_section_by_name('.stab') + stabstr = elf.get_section_by_name('.stabstr') + for entry, golden in zip (stab.iter_stabs (), expected): + self.assertEqual(stabstr.get_string (entry.n_strx), golden[0]) + self.assertEqual(entry.n_type, golden[1]) + self.assertEqual(entry.n_other, golden[2]) + self.assertEqual(entry.n_desc, golden[3]) + self.assertEqual(entry.n_value, golden[4]) + +if __name__ == '__main__': + unittest.main() diff --git a/test/testfiles_for_unittests/obj_stabs.S b/test/testfiles_for_unittests/obj_stabs.S new file mode 100644 index 0000000..ecdc5b4 --- /dev/null +++ b/test/testfiles_for_unittests/obj_stabs.S @@ -0,0 +1,3 @@ +# gcc -c -o obj_stabs.o obj_stabs.S +.stabs "label", 0x95, 0xc8, 0x4072, 0xdeadbeef +.stabs "another label", 0x41, 0x66, 0xf9b1, 0xcafebabe diff --git a/test/testfiles_for_unittests/obj_stabs.elf b/test/testfiles_for_unittests/obj_stabs.elf new file mode 100644 index 0000000..8ee5422 Binary files /dev/null and b/test/testfiles_for_unittests/obj_stabs.elf differ