From: Eli Bendersky Date: Sat, 17 Sep 2011 07:39:29 +0000 (+0300) Subject: test suite implemented. fixing some problems in elftools and readelf X-Git-Tag: v0.10~116 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2fc0f2a5ee029522e91285d46634de0b0679cb54;p=pyelftools.git test suite implemented. fixing some problems in elftools and readelf --- diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py index 23e789d..35232b9 100644 --- a/elftools/elf/descriptions.py +++ b/elftools/elf/descriptions.py @@ -142,7 +142,7 @@ _DESCR_P_TYPE = dict( PT_PHDR='PHDR', PT_GNU_EH_FRAME='GNU_EH_FRAME', PT_GNU_STACK='GNU_STACK', - PT_GNU_RELRO='GNU_RELR0', + PT_GNU_RELRO='GNU_RELRO', ) _DESCR_P_FLAGS = { diff --git a/scripts/readelf.py b/scripts/readelf.py index 7b3cc96..c284edc 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -1,6 +1,6 @@ #!/usr/bin/env python #------------------------------------------------------------------------------- -# readelf.py +# scripts/readelf.py # # A clone of 'readelf' in Python, based on the pyelftools library # @@ -73,10 +73,10 @@ class ReadElf(object): describe_e_version_numeric(header['e_version'])) self._emitline(' Entry point address: %s' % self._format_hex(header['e_entry'])) - self._emit(' Start of program headers %s' % + self._emit(' Start of program headers: %s' % header['e_phoff']) self._emitline(' (bytes into file)') - self._emit(' Start of section headers %s' % + self._emit(' Start of section headers: %s' % header['e_shoff']) self._emitline(' (bytes into file)') self._emitline(' Flags: %s' % @@ -100,6 +100,10 @@ class ReadElf(object): (Elf file type is...) """ self._emitline() + if self.elffile.num_segments() == 0: + self._emitline('There are no program headers in this file.') + return + elfheader = self.elffile.header if show_heading: self._emitline('Elf file type is %s' % @@ -112,7 +116,7 @@ class ReadElf(object): elfheader['e_phnum'], elfheader['e_phoff'])) self._emitline() - self._emitline('Program headers:') + self._emitline('Program Headers:') # Now comes the table of program headers with their attributes. Note # that due to different formatting constraints of 32-bit and 64-bit @@ -164,10 +168,10 @@ class ReadElf(object): return self._emitline('\n Section to Segment mapping:') - self._emitline(' Segment Sections...\n') + self._emitline(' Segment Sections...') for nseg, segment in enumerate(self.elffile.iter_segments()): - self._emit(' %2.2d ' % nseg) + self._emit(' %2.2d ' % nseg) for section in self.elffile.iter_sections(): if ( not section.is_null() and @@ -184,7 +188,7 @@ class ReadElf(object): self._emitline('There are %s section headers, starting at offset %s' % ( elfheader['e_shnum'], self._format_hex(elfheader['e_shoff']))) - self._emitline('\nSection header%s:' % ( + self._emitline('\nSection Header%s:' % ( 's' if elfheader['e_shnum'] > 1 else '')) # Different formatting constraints of 32-bit and 64-bit addresses @@ -344,12 +348,12 @@ def main(): readelf = ReadElf(file, sys.stdout) if do_file_header: readelf.display_file_header() - if do_program_header: - readelf.display_program_headers( - show_heading=not do_file_header) if do_section_header: readelf.display_section_headers( show_heading=not do_file_header) + if do_program_header: + readelf.display_program_headers( + show_heading=not do_file_header) if options.show_symbols: readelf.display_symbol_tables() except ELFError as ex: diff --git a/tests/run_tests.py b/tests/run_tests.py index b86b3bf..f916978 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -8,7 +8,16 @@ # This code is in the public domain #------------------------------------------------------------------------------- import os, sys +import logging import subprocess +import tempfile + + +# Create a global logger object +# +testlog = logging.getLogger('run_tests') +testlog.setLevel(logging.DEBUG) +testlog.addHandler(logging.StreamHandler(sys.stdout)) def discover_testfiles(rootdir): @@ -20,8 +29,82 @@ def discover_testfiles(rootdir): yield os.path.join(rootdir, filename) +def run_exe(exe_path, args): + """ Runs the given executable as a subprocess, given the + list of arguments. Captures its return code (rc) and stdout and + returns a pair: rc, stdout_str + """ + popen_cmd = [exe_path] + args + if os.path.splitext(exe_path)[1] == '.py': + popen_cmd.insert(0, 'python') + proc = subprocess.Popen(popen_cmd, stdout=subprocess.PIPE) + proc_stdout = proc.communicate()[0] + return proc.returncode, proc_stdout + + +def run_test_on_file(filename): + """ Runs a test on the given input filename + """ + testlog.info("Running test on file '%s'" % filename) + for option in ['-e', '-s']: + testlog.info("..option='%s'" % option) + # stdouts will be a 2-element list: output of readelf and output + # of scripts/readelf.py + stdouts = [] + for exe_path in ['readelf', 'scripts/readelf.py']: + args = [option, filename] + testlog.info("....executing: '%s %s'" % ( + exe_path, ' '.join(args))) + rc, stdout = run_exe(exe_path, args) + if rc != 0: + testlog.error("@@ aborting - '%s' returned '%s'" % (exe_path, rc)) + break + stdouts.append(stdout) + testlog.info('....comparing output...') + success, errmsg = compare_output(*stdouts) + if success: + testlog.info('.......................SUCCESS') + else: + testlog.info('.......................FAIL') + testlog.info('@@ ' + errmsg) + dump_output_to_temp_files(*stdouts) + + +def compare_output(s1, s2): + """ Compare stdout strings s1 and s2. + Return pair success, errmsg. If comparison succeeds, success is True + and errmsg is empty. Otherwise success is False and errmsg holds a + description of the mismatch. + """ + lines1 = s1.splitlines() + lines2 = s2.splitlines() + if len(lines1) != len(lines2): + return False, 'Number of lines different: %s vs %s' % ( + len(lines1), len(lines2)) + for i in range(len(lines1)): + if lines1[i].split() != lines2[i].split(): + errmsg = 'Mismatch on line #%s:\n>>%s<<\n>>%s<<\n' % ( + i, lines1[i], lines2[i]) + return False, errmsg + return True, '' + + +def dump_output_to_temp_files(*args): + """ Dumps the output strings given in 'args' to temp files: one for each + arg. + """ + for i, s in enumerate(args): + fd, path = tempfile.mkstemp( + prefix='out' + str(i + 1) + '_', + suffix='.stdout') + file = os.fdopen(fd, 'w') + file.write(s) + file.close() + testlog.info('@@ Output #%s dumped to file: %s' % (i + 1, path)) + + def die(msg): - print 'Error:', msg + testlog.error('Error: %s' % msg) sys.exit(1) @@ -36,10 +119,15 @@ def main(): if not is_in_rootdir(): die('Please run me from the root dir of pyelftools!') + for filename in discover_testfiles('tests/testfiles'): + run_test_on_file(filename) + if __name__ == '__main__': main() - print list(discover_testfiles('tests/testfiles')) + #testlog.info(list(discover_testfiles('tests/testfiles'))) + #print run_exe('scripts/readelf.py', ['-h', 'tests/testfiles/z32.o.elf']) +