From adf707a0a76d7e0b54c447ed41afc12ae7d21e52 Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Fri, 23 Sep 2011 15:23:41 +0300 Subject: [PATCH] * added another test file (real-life object file borrowed from libelf) * print out notification about sections having relocations against them in the file * munge run_tests to ignore case when comparing lines --- elftools/elf/sections.py | 3 +++ scripts/readelf.py | 22 ++++++++++++++++++++-- tests/run_tests.py | 8 +++++--- tests/testfiles/update32.o.elf | Bin 0 -> 31800 bytes 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 tests/testfiles/update32.o.elf diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py index 10b99f9..d545ec2 100644 --- a/elftools/elf/sections.py +++ b/elftools/elf/sections.py @@ -39,6 +39,9 @@ class Section(object): """ return self.header[name] + def __eq__(self, other): + return self.header == other.header + class NullSection(Section): """ ELF NULL section diff --git a/scripts/readelf.py b/scripts/readelf.py index 8f1c27f..d90b5bf 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -302,12 +302,19 @@ class ReadElf(object): continue symbol = symtable.get_symbol(rel['r_info_sym']) + # Some symbols have zero 'st_name', so instead what's used is + # the name of the section they point at + if symbol['st_name'] == 0: + symsec = self.elffile.get_section(symbol['st_shndx']) + symbol_name = symsec.name + else: + symbol_name = symbol.name self._emit(' %s %s%s' % ( self._format_hex( symbol['st_value'], fullhex=True, lead0x=False), ' ' if self.elffile.elfclass == 32 else '', - symbol.name)) + symbol_name)) if section.is_RELA(): self._emit(' %s %x' % ( '+' if rel['r_addend'] >= 0 else '-', @@ -328,7 +335,7 @@ class ReadElf(object): return self._emitline("\nHex dump of section '%s':" % section.name) - + self._note_relocs_for_section(section) addr = section['sh_addr'] data = section.data() dataptr = 0 @@ -438,6 +445,17 @@ class ReadElf(object): # Not a number. Must be a name then return self.elffile.get_section_by_name(spec) + def _note_relocs_for_section(self, section): + """ If there are relocation sections pointing to the givne section, + emit a note about it. + """ + for relsec in self.elffile.iter_sections(): + if isinstance(relsec, RelocationSection): + info_idx = relsec['sh_info'] + if self.elffile.get_section(info_idx) == section: + self._emitline(' Note: This section has relocations against it, but these have NOT been applied to this dump.') + return + def _emit(self, s=''): """ Emit an object to output """ diff --git a/tests/run_tests.py b/tests/run_tests.py index fda2371..b0b24a0 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -84,10 +84,12 @@ def compare_output(s1, s2): Note: this function contains some rather horrible hacks to ignore differences which are not important for the verification of pyelftools. This is due to some intricacies of binutils's readelf which pyelftools - doesn't currently implement. Read the documentation for more details. + doesn't currently implement, or silly inconsistencies in the output of + readelf, which I was reluctant to replicate. + Read the documentation for more details. """ - lines1 = s1.splitlines() - lines2 = s2.splitlines() + lines1 = s1.lower().splitlines() + lines2 = s2.lower().splitlines() if len(lines1) != len(lines2): return False, 'Number of lines different: %s vs %s' % ( len(lines1), len(lines2)) diff --git a/tests/testfiles/update32.o.elf b/tests/testfiles/update32.o.elf new file mode 100644 index 0000000000000000000000000000000000000000..ae68ef98cabf37b17d83e009ba2286fe26007904 GIT binary patch literal 31800 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 G!v7DMKr;dW literal 0 HcmV?d00001 -- 2.30.2