From: Eli Bendersky Date: Sat, 17 Dec 2011 12:34:02 +0000 (+0200) Subject: renamed 'tests' dir to 'test' X-Git-Tag: v0.10~25 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=203b87047541c1b8b25f397cb2149810f1a9f4ab;p=pyelftools.git renamed 'tests' dir to 'test' --- diff --git a/test/run_all_unittests.py b/test/run_all_unittests.py new file mode 100755 index 0000000..555b0d2 --- /dev/null +++ b/test/run_all_unittests.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +# tests/run_all_unittests.py +# +# Run all unit tests (alternative to running 'python -m unittest discover ...') +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from unittest import TestLoader, TextTestRunner + + +if __name__ == '__main__': + try: + tests = TestLoader().discover('tests', 'test*.py', 'tests') + TextTestRunner().run(tests) + except ImportError as err: + print err + print '!! Please execute from the root directory of pyelfutils' + diff --git a/test/run_readelf_tests.py b/test/run_readelf_tests.py new file mode 100755 index 0000000..3592f40 --- /dev/null +++ b/test/run_readelf_tests.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python +#------------------------------------------------------------------------------- +# tests/run_readelf_tests.py +# +# Automatic test runner for elftools & readelf +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +import os, sys +import re +from difflib import SequenceMatcher +import logging +import subprocess +import tempfile +import platform + + +# Create a global logger object +# +testlog = logging.getLogger('run_tests') +testlog.setLevel(logging.DEBUG) +testlog.addHandler(logging.StreamHandler(sys.stdout)) + + +def discover_testfiles(rootdir): + """ Discover test files in the given directory. Yield them one by one. + """ + for filename in os.listdir(rootdir): + _, ext = os.path.splitext(filename) + if ext == '.elf': + 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. Return True if all test + runs succeeded. + """ + success = True + testlog.info("Running test on file '%s'" % filename) + for option in [ + '-e', '-s', '-r', '-x.text', '-p.shstrtab', + '--debug-dump=info', '--debug-dump=decodedline', + '--debug-dump=frames', '--debug-dump=frames-interp']: + 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)) + return False + stdouts.append(stdout) + testlog.info('....comparing output...') + rc, errmsg = compare_output(*stdouts) + if rc: + testlog.info('.......................SUCCESS') + else: + success = False + testlog.info('.......................FAIL') + testlog.info('@@ ' + errmsg) + dump_output_to_temp_files(*stdouts) + return success + + +def compare_output(s1, s2): + """ Compare stdout strings s1 and s2. + s1 is from readelf, s2 from elftools readelf.py + 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. + + 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, or silly inconsistencies in the output of + readelf, which I was reluctant to replicate. + Read the documentation for more details. + """ + def prepare_lines(s): + return [line for line in s.lower().splitlines() if line.strip() != ''] + def filter_readelf_lines(lines): + filter_out = False + for line in lines: + if 'of the .eh_frame section' in line: + filter_out = True + elif 'of the .debug_frame section' in line: + filter_out = False + if not filter_out: + if not line.startswith('unknown: length'): + yield line + + lines1 = prepare_lines(s1) + lines2 = prepare_lines(s2) + + lines1 = list(filter_readelf_lines(lines1)) + + flag_after_symtable = False + + 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 'symbol table' in lines1[i]: + flag_after_symtable = True + + # Compare ignoring whitespace + lines1_parts = lines1[i].split() + lines2_parts = lines2[i].split() + if ''.join(lines1_parts) != ''.join(lines2_parts): + ok = False + sm = SequenceMatcher() + sm.set_seqs(lines1[i], lines2[i]) + changes = sm.get_opcodes() + if flag_after_symtable: + # Detect readelf's adding @ with lib and version after + # symbol name. + if ( len(changes) == 2 and changes[1][0] == 'delete' and + lines1[i][changes[1][1]] == '@'): + ok = True + elif 'at_const_value' in lines1[i]: + # On 32-bit machines, readelf doesn't correctly represent + # some boundary LEB128 numbers + num2 = int(lines2_parts[-1]) + if num2 <= -2**31 and '32' in platform.architecture()[0]: + ok = True + elif 'os/abi' in lines1[i]: + if 'unix - gnu' in lines1[i] and 'unix - linux' in lines2[i]: + ok = True + else: + for s in ('t (tls)', 'l (large)'): + if s in lines1[i] or s in lines2[i]: + ok = True + break + if not ok: + 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): + testlog.error('Error: %s' % msg) + sys.exit(1) + + +def is_in_rootdir(): + """ Check whether the current dir is the root dir of pyelftools + """ + dirstuff = os.listdir('.') + return 'test' in dirstuff and 'elftools' in dirstuff + + +def main(): + if not is_in_rootdir(): + die('Please run me from the root dir of pyelftools!') + + # If file names are given as command-line arguments, only these files + # are taken as inputs. Otherwise, autodiscovery is performed. + # + if len(sys.argv) > 1: + filenames = sys.argv[1:] + else: + filenames = list(discover_testfiles('test/testfiles')) + + success = True + for filename in filenames: + success = success and run_test_on_file(filename) + + if success: + testlog.info('\nConclusion: SUCCESS') + else: + testlog.info('\nConclusion: FAIL') + + +if __name__ == '__main__': + main() + + + + diff --git a/test/test_callframe.py b/test/test_callframe.py new file mode 100644 index 0000000..30e405b --- /dev/null +++ b/test/test_callframe.py @@ -0,0 +1,147 @@ +import sys, unittest +from cStringIO import StringIO + +sys.path.extend(['.', '..']) +from elftools.dwarf.callframe import ( + CallFrameInfo, CIE, FDE, instruction_name, CallFrameInstruction, + RegisterRule) +from elftools.dwarf.structs import DWARFStructs +from elftools.dwarf.descriptions import (describe_CFI_instructions, + set_global_machine_arch) + + +class TestCallFrame(unittest.TestCase): + def assertInstruction(self, instr, name, args): + self.assertIsInstance(instr, CallFrameInstruction) + self.assertEqual(instruction_name(instr.opcode), name) + self.assertEqual(instr.args, args) + + def test_spec_sample_d6(self): + # D.6 sample in DWARFv3 + s = StringIO() + data = ('' + + # first comes the CIE + '\x20\x00\x00\x00' + # length + '\xff\xff\xff\xff' + # CIE_id + '\x03\x00\x04\x7c' + # version, augmentation, caf, daf + '\x08' + # return address + '\x0c\x07\x00' + + '\x08\x00' + + '\x07\x01' + + '\x07\x02' + + '\x07\x03' + + '\x08\x04' + + '\x08\x05' + + '\x08\x06' + + '\x08\x07' + + '\x09\x08\x01' + + '\x00' + + + # then comes the FDE + '\x28\x00\x00\x00' + # length + '\x00\x00\x00\x00' + # CIE_pointer (to CIE at 0) + '\x44\x33\x22\x11' + # initial_location + '\x54\x00\x00\x00' + # address range + '\x41' + + '\x0e\x0c' + '\x41' + + '\x88\x01' + '\x41' + + '\x86\x02' + '\x41' + + '\x0d\x06' + '\x41' + + '\x84\x03' + '\x4b' + + '\xc4' + '\x41' + + '\xc6' + + '\x0d\x07' + '\x41' + + '\xc8' + '\x41' + + '\x0e\x00' + + '\x00\x00' + ) + s.write(data) + + structs = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) + cfi = CallFrameInfo(s, len(data), structs) + entries = cfi.get_entries() + + self.assertEqual(len(entries), 2) + self.assertIsInstance(entries[0], CIE) + self.assertEqual(entries[0]['length'], 32) + self.assertEqual(entries[0]['data_alignment_factor'], -4) + self.assertEqual(entries[0]['return_address_register'], 8) + self.assertEqual(len(entries[0].instructions), 11) + self.assertInstruction(entries[0].instructions[0], + 'DW_CFA_def_cfa', [7, 0]) + self.assertInstruction(entries[0].instructions[8], + 'DW_CFA_same_value', [7]) + self.assertInstruction(entries[0].instructions[9], + 'DW_CFA_register', [8, 1]) + + self.assertTrue(isinstance(entries[1], FDE)) + self.assertEqual(entries[1]['length'], 40) + self.assertEqual(entries[1]['CIE_pointer'], 0) + self.assertEqual(entries[1]['address_range'], 84) + self.assertIs(entries[1].cie, entries[0]) + self.assertEqual(len(entries[1].instructions), 21) + self.assertInstruction(entries[1].instructions[0], + 'DW_CFA_advance_loc', [1]) + self.assertInstruction(entries[1].instructions[1], + 'DW_CFA_def_cfa_offset', [12]) + self.assertInstruction(entries[1].instructions[9], + 'DW_CFA_offset', [4, 3]) + self.assertInstruction(entries[1].instructions[18], + 'DW_CFA_def_cfa_offset', [0]) + self.assertInstruction(entries[1].instructions[20], + 'DW_CFA_nop', []) + + # Now let's decode it... + decoded_CIE = entries[0].get_decoded() + self.assertEqual(decoded_CIE.reg_order, list(range(9))) + self.assertEqual(len(decoded_CIE.table), 1) + self.assertEqual(decoded_CIE.table[0]['cfa'].reg, 7) + self.assertEqual(decoded_CIE.table[0]['pc'], 0) + self.assertEqual(decoded_CIE.table[0]['cfa'].offset, 0) + self.assertEqual(decoded_CIE.table[0][4].type, RegisterRule.SAME_VALUE) + self.assertEqual(decoded_CIE.table[0][8].type, RegisterRule.REGISTER) + self.assertEqual(decoded_CIE.table[0][8].arg, 1) + + decoded_FDE = entries[1].get_decoded() + self.assertEqual(decoded_FDE.reg_order, list(range(9))) + self.assertEqual(decoded_FDE.table[0]['cfa'].reg, 7) + self.assertEqual(decoded_FDE.table[0]['cfa'].offset, 0) + self.assertEqual(decoded_FDE.table[0]['pc'], 0x11223344) + self.assertEqual(decoded_FDE.table[0][8].type, RegisterRule.REGISTER) + self.assertEqual(decoded_FDE.table[0][8].arg, 1) + self.assertEqual(decoded_FDE.table[1]['cfa'].reg, 7) + self.assertEqual(decoded_FDE.table[1]['cfa'].offset, 12) + self.assertEqual(decoded_FDE.table[2][8].type, RegisterRule.OFFSET) + self.assertEqual(decoded_FDE.table[2][8].arg, -4) + self.assertEqual(decoded_FDE.table[2][4].type, RegisterRule.SAME_VALUE) + self.assertEqual(decoded_FDE.table[5]['pc'], 0x11223344 + 20) + self.assertEqual(decoded_FDE.table[5][4].type, RegisterRule.OFFSET) + self.assertEqual(decoded_FDE.table[5][4].arg, -12) + self.assertEqual(decoded_FDE.table[6]['pc'], 0x11223344 + 64) + self.assertEqual(decoded_FDE.table[9]['pc'], 0x11223344 + 76) + + def test_describe_CFI_instructions(self): + # The data here represents a single CIE + data = ('' + + '\x16\x00\x00\x00' + # length + '\xff\xff\xff\xff' + # CIE_id + '\x03\x00\x04\x7c' + # version, augmentation, caf, daf + '\x08' + # return address + '\x0c\x07\x02' + + '\x10\x02\x07\x03\x01\x02\x00\x00\x06\x06') + s = StringIO(data) + + structs = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) + cfi = CallFrameInfo(s, len(data), structs) + entries = cfi.get_entries() + + set_global_machine_arch('x86') + self.assertEqual(describe_CFI_instructions(entries[0]), + ( ' DW_CFA_def_cfa: r7 (edi) ofs 2\n' + + ' DW_CFA_expression: r2 (edx) (DW_OP_addr: 201; DW_OP_deref; DW_OP_deref)\n')) + + +if __name__ == '__main__': + unittest.main() + + diff --git a/test/test_dwarf_expr.py b/test/test_dwarf_expr.py new file mode 100644 index 0000000..8e293db --- /dev/null +++ b/test/test_dwarf_expr.py @@ -0,0 +1,68 @@ +import sys, unittest +from cStringIO import StringIO + +sys.path.extend(('..', '.')) +from elftools.dwarf.descriptions import ExprDumper, set_global_machine_arch +from elftools.dwarf.structs import DWARFStructs + + +class TestExprDumper(unittest.TestCase): + structs32 = DWARFStructs( + little_endian=True, + dwarf_format=32, + address_size=4) + + def setUp(self): + self.visitor = ExprDumper(self.structs32) + set_global_machine_arch('x64') + + def test_basic_single(self): + self.visitor.process_expr([0x1b]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_div') + + self.setUp() + self.visitor.process_expr([0x74, 0x82, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_breg4 (rsi): 130') + + self.setUp() + self.visitor.process_expr([0x91, 0x82, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_fbreg: 130') + + self.setUp() + self.visitor.process_expr([0x51]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_reg1 (rdx)') + + self.setUp() + self.visitor.process_expr([0x90, 16]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_regx: 16 (rip)') + + self.setUp() + self.visitor.process_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_bit_piece: 1295 144') + + def test_basic_sequence(self): + self.visitor.process_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref') + + self.setUp() + self.visitor.process_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_pick: 255; DW_OP_const2s: -15') + + self.setUp() + self.visitor.process_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]) + self.assertEqual(self.visitor.get_str(), + 'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul') + + +if __name__ == '__main__': + unittest.main() + + diff --git a/test/test_dwarf_lineprogram.py b/test/test_dwarf_lineprogram.py new file mode 100644 index 0000000..56d96c3 --- /dev/null +++ b/test/test_dwarf_lineprogram.py @@ -0,0 +1,101 @@ +import sys, unittest +from cStringIO import StringIO + +sys.path.extend(['.', '..']) +from elftools.dwarf.lineprogram import LineProgram, LineState, LineProgramEntry +from elftools.dwarf.structs import DWARFStructs +from elftools.dwarf.constants import * + + +class TestLineProgram(unittest.TestCase): + def _make_program_in_stream(self, stream): + """ Create a LineProgram from the given program encoded in a stream + """ + ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) + header = ds.Dwarf_lineprog_header.parse( + '\x04\x10\x00\x00' + # initial lenght + '\x03\x00' + # version + '\x20\x00\x00\x00' + # header length + '\x01\x01\x01\x0F' + # flags + '\x0A' + # opcode_base + '\x00\x01\x04\x08\x0C\x01\x01\x01\x00' + # standard_opcode_lengths + # 2 dir names followed by a NULL + '\x61\x62\x00\x70\x00\x00' + + # a file entry + '\x61\x72\x00\x0C\x0D\x0F' + + # and another entry + '\x45\x50\x51\x00\x86\x12\x07\x08' + + # followed by NULL + '\x00') + + lp = LineProgram(header, stream, ds, 0, len(stream.getvalue())) + return lp + + def assertLineState(self, state, **kwargs): + """ Assert that the state attributes specified in kwargs have the given + values (the rest are default). + """ + for k, v in kwargs.iteritems(): + self.assertEqual(getattr(state, k), v) + + def test_spec_sample_59(self): + # Sample in figure 59 of DWARFv3 + s = StringIO() + s.write( + '\x02\xb9\x04' + + '\x0b' + + '\x38' + + '\x82' + + '\x73' + + '\x02\x02' + + '\x00\x01\x01') + + lp = self._make_program_in_stream(s) + linetable = lp.get_entries() + + self.assertEqual(len(linetable), 7) + self.assertIs(linetable[0].state, None) # doesn't modify state + self.assertEqual(linetable[0].command, DW_LNS_advance_pc) + self.assertEqual(linetable[0].args, [0x239]) + self.assertLineState(linetable[1].state, address=0x239, line=3) + self.assertEqual(linetable[1].command, 0xb) + self.assertEqual(linetable[1].args, [2, 0]) + self.assertLineState(linetable[2].state, address=0x23c, line=5) + self.assertLineState(linetable[3].state, address=0x244, line=6) + self.assertLineState(linetable[4].state, address=0x24b, line=7, end_sequence=False) + self.assertEqual(linetable[5].command, DW_LNS_advance_pc) + self.assertEqual(linetable[5].args, [2]) + self.assertLineState(linetable[6].state, address=0x24d, line=7, end_sequence=True) + + def test_spec_sample_60(self): + # Sample in figure 60 of DWARFv3 + s = StringIO() + s.write( + '\x09\x39\x02' + + '\x0b' + + '\x09\x03\x00' + + '\x0b' + + '\x09\x08\x00' + + '\x0a' + + '\x09\x07\x00' + + '\x0a' + + '\x09\x02\x00' + + '\x00\x01\x01') + + lp = self._make_program_in_stream(s) + linetable = lp.get_entries() + + self.assertEqual(len(linetable), 10) + self.assertIs(linetable[0].state, None) # doesn't modify state + self.assertEqual(linetable[0].command, DW_LNS_fixed_advance_pc) + self.assertEqual(linetable[0].args, [0x239]) + self.assertLineState(linetable[1].state, address=0x239, line=3) + self.assertLineState(linetable[3].state, address=0x23c, line=5) + self.assertLineState(linetable[5].state, address=0x244, line=6) + self.assertLineState(linetable[7].state, address=0x24b, line=7, end_sequence=False) + self.assertLineState(linetable[9].state, address=0x24d, line=7, end_sequence=True) + + +if __name__ == '__main__': + unittest.main() + diff --git a/test/test_dwarf_structs.py b/test/test_dwarf_structs.py new file mode 100644 index 0000000..a1e30d7 --- /dev/null +++ b/test/test_dwarf_structs.py @@ -0,0 +1,39 @@ +import sys, unittest + +sys.path.extend(['.', '..']) +from elftools.dwarf.structs import DWARFStructs + + +class TestDWARFStructs(unittest.TestCase): + def test_lineprog_header(self): + ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) + + c = ds.Dwarf_lineprog_header.parse( + '\x04\x10\x00\x00' + # initial lenght + '\x05\x02' + # version + '\x20\x00\x00\x00' + # header length + '\x05\x10\x40\x50' + # until and including line_range + '\x06' + # opcode_base + '\x00\x01\x04\x08\x0C' + # standard_opcode_lengths + # 2 dir names followed by a NULL + '\x61\x62\x00\x70\x00\x00' + + # a file entry + '\x61\x72\x00\x0C\x0D\x0F' + + # and another entry + '\x45\x50\x51\x00\x86\x12\x07\x08' + + # followed by NULL + '\x00') + + self.assertEqual(c.version, 0x205) + self.assertEqual(c.opcode_base, 6) + self.assertEqual(c.standard_opcode_lengths, [0, 1, 4, 8, 12]) + self.assertEqual(c.include_directory, ['ab', 'p']) + self.assertEqual(len(c.file_entry), 2) + self.assertEqual(c.file_entry[0].name, 'ar') + self.assertEqual(c.file_entry[1].name, 'EPQ') + self.assertEqual(c.file_entry[1].dir_index, 0x12 * 128 + 6) + + +if __name__ == '__main__': + unittest.main() + diff --git a/test/test_utils.py b/test/test_utils.py new file mode 100644 index 0000000..54a09bb --- /dev/null +++ b/test/test_utils.py @@ -0,0 +1,56 @@ +import sys, unittest +from cStringIO import StringIO +from random import randint + +sys.path.extend(['.', '..']) +from elftools.common.utils import (parse_cstring_from_stream, + preserve_stream_pos) + + +class Test_parse_cstring_from_stream(unittest.TestCase): + def _make_random_string(self, n): + return ''.join(chr(randint(32, 127)) for i in range(n)) + + def test_small1(self): + sio = StringIO('abcdefgh\x0012345') + self.assertEqual(parse_cstring_from_stream(sio), 'abcdefgh') + self.assertEqual(parse_cstring_from_stream(sio, 2), 'cdefgh') + self.assertEqual(parse_cstring_from_stream(sio, 8), '') + + def test_small2(self): + sio = StringIO('12345\x006789\x00abcdefg\x00iii') + self.assertEqual(parse_cstring_from_stream(sio), '12345') + self.assertEqual(parse_cstring_from_stream(sio, 5), '') + self.assertEqual(parse_cstring_from_stream(sio, 6), '6789') + + def test_large1(self): + text = 'i' * 400 + '\x00' + 'bb' + sio = StringIO(text) + self.assertEqual(parse_cstring_from_stream(sio), 'i' * 400) + self.assertEqual(parse_cstring_from_stream(sio, 150), 'i' * 250) + + def test_large2(self): + text = self._make_random_string(5000) + '\x00' + 'jujajaja' + sio = StringIO(text) + self.assertEqual(parse_cstring_from_stream(sio), text[:5000]) + self.assertEqual(parse_cstring_from_stream(sio, 2348), text[2348:5000]) + + +class Test_preserve_stream_pos(object): + def test_basic(self): + sio = StringIO('abcdef') + with preserve_stream_pos(sio): + sio.seek(4) + self.assertEqual(stream.tell(), 0) + + sio.seek(5) + with preserve_stream_pos(sio): + sio.seek(0) + self.assertEqual(stream.tell(), 5) + + +if __name__ == '__main__': + unittest.main() + + + diff --git a/test/testfiles/exe_simple32.elf b/test/testfiles/exe_simple32.elf new file mode 100644 index 0000000..d6b3cd1 Binary files /dev/null and b/test/testfiles/exe_simple32.elf differ diff --git a/test/testfiles/exe_simple64.elf b/test/testfiles/exe_simple64.elf new file mode 100644 index 0000000..ccfa6ae Binary files /dev/null and b/test/testfiles/exe_simple64.elf differ diff --git a/test/testfiles/exe_stripped64.elf b/test/testfiles/exe_stripped64.elf new file mode 100644 index 0000000..841b3f8 Binary files /dev/null and b/test/testfiles/exe_stripped64.elf differ diff --git a/test/testfiles/libelf0_8_13_32bit.so.elf b/test/testfiles/libelf0_8_13_32bit.so.elf new file mode 100644 index 0000000..c236625 Binary files /dev/null and b/test/testfiles/libelf0_8_13_32bit.so.elf differ diff --git a/test/testfiles/obj_simple32.o.elf b/test/testfiles/obj_simple32.o.elf new file mode 100644 index 0000000..5ce4182 Binary files /dev/null and b/test/testfiles/obj_simple32.o.elf differ diff --git a/test/testfiles/penalty_32_gcc.o.elf b/test/testfiles/penalty_32_gcc.o.elf new file mode 100644 index 0000000..4c5c5de Binary files /dev/null and b/test/testfiles/penalty_32_gcc.o.elf differ diff --git a/test/testfiles/penalty_64_clang.o.elf b/test/testfiles/penalty_64_clang.o.elf new file mode 100644 index 0000000..91d207d Binary files /dev/null and b/test/testfiles/penalty_64_clang.o.elf differ diff --git a/test/testfiles/penalty_64_gcc.o.elf b/test/testfiles/penalty_64_gcc.o.elf new file mode 100644 index 0000000..aca100b Binary files /dev/null and b/test/testfiles/penalty_64_gcc.o.elf differ diff --git a/test/testfiles/update32.o.elf b/test/testfiles/update32.o.elf new file mode 100644 index 0000000..ae68ef9 Binary files /dev/null and b/test/testfiles/update32.o.elf differ diff --git a/test/utils/Makefile b/test/utils/Makefile new file mode 100644 index 0000000..fd44b8e --- /dev/null +++ b/test/utils/Makefile @@ -0,0 +1,18 @@ +CFLAGS = -Wall --std=c99 +# This is where `make install` from libelf places its stuff +LIBELF_HEADERS = /usr/local/include/libelf/ +LIBELF_LIBS = /usr/local/lib/ + +all: elf_creator + +elf_creator: elf_creator.c + gcc $(CFLAGS) -o elf_creator elf_creator.c \ + -I$(LIBELF_HEADERS) -L$(LIBELF_LIBS) -Wl,-rpath,$(LIBELF_LIBS) -lelf + +clean: + rm -f *.o + rm -f *.so + rm -f *.a + rm -f elf_creator + + diff --git a/test/utils/README.txt b/test/utils/README.txt new file mode 100644 index 0000000..a6c496a --- /dev/null +++ b/test/utils/README.txt @@ -0,0 +1,2 @@ +Some utilities that use libelf to create synthetic ELF files + diff --git a/test/utils/elf_creator.c b/test/utils/elf_creator.c new file mode 100644 index 0000000..1fd1b56 --- /dev/null +++ b/test/utils/elf_creator.c @@ -0,0 +1,204 @@ +/* Loosely based on the code in a Knol by Roberto Garcia Lopez: +** +** http://knol.google.com/k/roberto-garca-lpez/creating-elf-relocatable-object-files/1ohwel4gqkcn2/3# +** +** Note: This file is released under the terms of the LGPL2 license. +*/ +#include +#include +#include +#include +#include +#include +#include + + +const char* OUTFILE = "generated.o"; + +// Definition of the default string table section ".shstrtab" +const char defaultStrTable[] = +{ + /* offset 00 */ '\0', // The NULL section + /* offset 01 */ '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0', + /* offset 11 */ '.', 's', 't', 'r', 't', 'a', 'b', '\0', + /* offset 19 */ '.', 's', 'y', 'm', 't', 'a', 'b', '\0', + /* offset 27 */ '.', 'c', 'o', 'm', 'm', 'e', 'n', 't', '\0', + /* offset 36 */ '.', 'b', 's', 's', '\0', + /* offset 41 */ '.', 'd', 'a', 't', 'a', '\0', + /* offset 47 */ '.', 'r', 'e', 'l', '.', 't', 'e', 'x', 't', '\0', + /* offset 57 */ '.', 't', 'e', 'x', 't', '\0' +}; + +const char defaultStrTableLen = sizeof(defaultStrTable); + +// Offsets of section names in the string table +const char _shstrtab_offset = 1; +const char _strtab_offset = 11; +const char _symtab_offset = 19; +const char _text_offset = 57; + +// Position of sections within the object file +const char _shstrtab = 1; +const char _strtab = 2; +const char _symtab = 3; +const char _text = 4; + +const char TEXT_CONTENTS[] = {0x91, 0x92, 0x93, 0x94}; + + +//---------------------------------------------------------------------------- + +int main() +{ + int FileDes; + Elf *pElf; + Elf32_Ehdr *pEhdr; + Elf32_Shdr *pShdr; + Elf_Scn *pScn; + Elf_Data *pData; + + // Create the ELF header + if (elf_version(EV_CURRENT) == EV_NONE) // It must appear before "elf_begin()" + errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1)); + + if ((FileDes = open(OUTFILE, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0) + errx(EX_OSERR, "open \"%s\" failed", "compiled.o"); + + if ((pElf = elf_begin(FileDes, ELF_C_WRITE, NULL)) == NULL) // 3rd argument is ignored for "ELF_C_WRITE" + errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); + + if ((pEhdr = elf32_newehdr(pElf)) == NULL) + errx(EX_SOFTWARE, "elf32_newehdr() failed: %s", elf_errmsg(-1)); + + pEhdr->e_ident[EI_CLASS] = ELFCLASS32; // Defined by Intel architecture + pEhdr->e_ident[EI_DATA] = ELFDATA2LSB; // Defined by Intel architecture + pEhdr->e_machine = EM_386; // Intel architecture + pEhdr->e_type = ET_REL; // Relocatable file (object file) + pEhdr->e_shstrndx = _shstrtab; // Point to the shstrtab section + + // Create the section "default section header string table (.shstrtab)" + if ((pScn = elf_newscn(pElf)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + if ((pData = elf_newdata(pScn)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + + pData->d_align = 1; + pData->d_buf = (void *) defaultStrTable; + pData->d_type = ELF_T_BYTE; + pData->d_size = defaultStrTableLen; + + if ((pShdr = elf32_getshdr(pScn)) == NULL) + errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); + + pShdr->sh_name = _shstrtab_offset; // Point to the name of the section + pShdr->sh_type = SHT_STRTAB; + pShdr->sh_flags = 0; + + // Create the section ".strtab" + if ((pScn = elf_newscn(pElf)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + if ((pData = elf_newdata(pScn)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + + const char strtab[] = {0, 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', '.','x', 0, '_', 's', 't', 'a', 'r', 't', 0}; + + pData->d_align = 1; + pData->d_buf = (void *) strtab; + pData->d_type = ELF_T_BYTE; + pData->d_size = sizeof(strtab); + + if ((pShdr = elf32_getshdr(pScn)) == NULL) + errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); + + pShdr->sh_name = _strtab_offset; + pShdr->sh_type = SHT_STRTAB; + pShdr->sh_flags = 0; + + // Create the section ".symtab" + if ((pScn = elf_newscn(pElf)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + if ((pData = elf_newdata(pScn)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + + Elf32_Sym x[4]; + + // Definition of the undefined section (this must be the first item by the definition of TIS ELF) + x[0].st_name = 0; + x[0].st_value = 0; + x[0].st_size = 0; + x[0].st_info = 0; + x[0].st_other = 0; + x[0].st_shndx = SHN_UNDEF; + + // Definition of the name of the source file (this must be the second item by the definition in TIS ELF) + x[1].st_name = 1; + x[1].st_value = 0; + x[1].st_size = 0; + x[1].st_info = ELF32_ST_INFO(STB_LOCAL, STT_FILE); // This is the value that st_info must have (because of TIS ELF) + x[1].st_other = 0; + x[1].st_shndx = SHN_ABS; // The section where the symbol is + + // Definition of the ".text" section as a section in the ".symtab" section + x[2].st_name = 0; + x[2].st_value = 0; + x[2].st_size = 0; + x[2].st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION); + x[2].st_other = 0; + x[2].st_shndx = _text; // The section where the symbol is + + // Definition of the "_start" symbol + x[3].st_name = 13; // Offset in the "strtab" section where the name start + x[3].st_value = 0; + x[3].st_size = 0; + x[3].st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE); + x[3].st_other = 0; + x[3].st_shndx = _text; // The section where the symbol is + + pData->d_align = 4; + pData->d_buf = (void *) x; + pData->d_type = ELF_T_BYTE; + pData->d_size = sizeof(x); + + if ((pShdr = elf32_getshdr(pScn)) == NULL) + errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); + + pShdr->sh_name = _symtab_offset; // Point to the name of the section + pShdr->sh_type = SHT_SYMTAB; + pShdr->sh_flags = 0; + pShdr->sh_link = _strtab; // point to the section .strtab (the section that contain the strings) + pShdr->sh_info = ELF32_ST_INFO(STB_LOCAL, 3); // the second argument is beause of TIS ELF (One greater than the symbol table index of the last local symbol (binding STB_LOCAL)) + + // Create many sections named .text + for (int i = 0; i < 70000; ++i) { + if ((pScn = elf_newscn(pElf)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + if ((pData = elf_newdata(pScn)) == NULL) + errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); + + pData->d_align = 4; + pData->d_buf = (void *)TEXT_CONTENTS; + pData->d_type = ELF_T_BYTE; + pData->d_size = sizeof(TEXT_CONTENTS); + + if ((pShdr = elf32_getshdr(pScn)) == NULL) + errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); + + pShdr->sh_name = _text_offset; + pShdr->sh_type = SHT_PROGBITS; + pShdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR; + } + + // Update the sections internally + if (elf_update(pElf, ELF_C_NULL) < 0) + errx(EX_SOFTWARE, "elf_update(NULL) failed: %s.", elf_errmsg(-1)); + // Write the object file + if (elf_update(pElf, ELF_C_WRITE) < 0) + errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1)); + // Close all handles + elf_end(pElf); + close(FileDes); + printf("Generated file: %s\n", OUTFILE); + + return 0; +} + diff --git a/tests/run_all_unittests.py b/tests/run_all_unittests.py deleted file mode 100755 index 555b0d2..0000000 --- a/tests/run_all_unittests.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -#------------------------------------------------------------------------------- -# tests/run_all_unittests.py -# -# Run all unit tests (alternative to running 'python -m unittest discover ...') -# -# Eli Bendersky (eliben@gmail.com) -# This code is in the public domain -#------------------------------------------------------------------------------- -from unittest import TestLoader, TextTestRunner - - -if __name__ == '__main__': - try: - tests = TestLoader().discover('tests', 'test*.py', 'tests') - TextTestRunner().run(tests) - except ImportError as err: - print err - print '!! Please execute from the root directory of pyelfutils' - diff --git a/tests/run_readelf_tests.py b/tests/run_readelf_tests.py deleted file mode 100755 index 61cfbee..0000000 --- a/tests/run_readelf_tests.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python -#------------------------------------------------------------------------------- -# tests/run_readelf_tests.py -# -# Automatic test runner for elftools & readelf -# -# Eli Bendersky (eliben@gmail.com) -# This code is in the public domain -#------------------------------------------------------------------------------- -import os, sys -import re -from difflib import SequenceMatcher -import logging -import subprocess -import tempfile -import platform - - -# Create a global logger object -# -testlog = logging.getLogger('run_tests') -testlog.setLevel(logging.DEBUG) -testlog.addHandler(logging.StreamHandler(sys.stdout)) - - -def discover_testfiles(rootdir): - """ Discover test files in the given directory. Yield them one by one. - """ - for filename in os.listdir(rootdir): - _, ext = os.path.splitext(filename) - if ext == '.elf': - 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. Return True if all test - runs succeeded. - """ - success = True - testlog.info("Running test on file '%s'" % filename) - for option in [ - '-e', '-s', '-r', '-x.text', '-p.shstrtab', - '--debug-dump=info', '--debug-dump=decodedline', - '--debug-dump=frames', '--debug-dump=frames-interp']: - 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)) - return False - stdouts.append(stdout) - testlog.info('....comparing output...') - rc, errmsg = compare_output(*stdouts) - if rc: - testlog.info('.......................SUCCESS') - else: - success = False - testlog.info('.......................FAIL') - testlog.info('@@ ' + errmsg) - dump_output_to_temp_files(*stdouts) - return success - - -def compare_output(s1, s2): - """ Compare stdout strings s1 and s2. - s1 is from readelf, s2 from elftools readelf.py - 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. - - 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, or silly inconsistencies in the output of - readelf, which I was reluctant to replicate. - Read the documentation for more details. - """ - def prepare_lines(s): - return [line for line in s.lower().splitlines() if line.strip() != ''] - def filter_readelf_lines(lines): - filter_out = False - for line in lines: - if 'of the .eh_frame section' in line: - filter_out = True - elif 'of the .debug_frame section' in line: - filter_out = False - if not filter_out: - if not line.startswith('unknown: length'): - yield line - - lines1 = prepare_lines(s1) - lines2 = prepare_lines(s2) - - lines1 = list(filter_readelf_lines(lines1)) - - flag_after_symtable = False - - 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 'symbol table' in lines1[i]: - flag_after_symtable = True - - # Compare ignoring whitespace - lines1_parts = lines1[i].split() - lines2_parts = lines2[i].split() - if ''.join(lines1_parts) != ''.join(lines2_parts): - ok = False - sm = SequenceMatcher() - sm.set_seqs(lines1[i], lines2[i]) - changes = sm.get_opcodes() - if flag_after_symtable: - # Detect readelf's adding @ with lib and version after - # symbol name. - if ( len(changes) == 2 and changes[1][0] == 'delete' and - lines1[i][changes[1][1]] == '@'): - ok = True - elif 'at_const_value' in lines1[i]: - # On 32-bit machines, readelf doesn't correctly represent - # some boundary LEB128 numbers - num2 = int(lines2_parts[-1]) - if num2 <= -2**31 and '32' in platform.architecture()[0]: - ok = True - elif 'os/abi' in lines1[i]: - if 'unix - gnu' in lines1[i] and 'unix - linux' in lines2[i]: - ok = True - else: - for s in ('t (tls)', 'l (large)'): - if s in lines1[i] or s in lines2[i]: - ok = True - break - if not ok: - 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): - testlog.error('Error: %s' % msg) - sys.exit(1) - - -def is_in_rootdir(): - """ Check whether the current dir is the root dir of pyelftools - """ - dirstuff = os.listdir('.') - return 'tests' in dirstuff and 'elftools' in dirstuff - - -def main(): - if not is_in_rootdir(): - die('Please run me from the root dir of pyelftools!') - - # If file names are given as command-line arguments, only these files - # are taken as inputs. Otherwise, autodiscovery is performed. - # - if len(sys.argv) > 1: - filenames = sys.argv[1:] - else: - filenames = list(discover_testfiles('tests/testfiles')) - - success = True - for filename in filenames: - success = success and run_test_on_file(filename) - - if success: - testlog.info('\nConclusion: SUCCESS') - else: - testlog.info('\nConclusion: FAIL') - - -if __name__ == '__main__': - #import os - #os.chdir('..') - main() - #testlog.info(list(discover_testfiles('tests/testfiles'))) - #print run_exe('scripts/readelf.py', ['-h', 'tests/testfiles/z32.o.elf']) - - - - diff --git a/tests/test_callframe.py b/tests/test_callframe.py deleted file mode 100644 index 30e405b..0000000 --- a/tests/test_callframe.py +++ /dev/null @@ -1,147 +0,0 @@ -import sys, unittest -from cStringIO import StringIO - -sys.path.extend(['.', '..']) -from elftools.dwarf.callframe import ( - CallFrameInfo, CIE, FDE, instruction_name, CallFrameInstruction, - RegisterRule) -from elftools.dwarf.structs import DWARFStructs -from elftools.dwarf.descriptions import (describe_CFI_instructions, - set_global_machine_arch) - - -class TestCallFrame(unittest.TestCase): - def assertInstruction(self, instr, name, args): - self.assertIsInstance(instr, CallFrameInstruction) - self.assertEqual(instruction_name(instr.opcode), name) - self.assertEqual(instr.args, args) - - def test_spec_sample_d6(self): - # D.6 sample in DWARFv3 - s = StringIO() - data = ('' + - # first comes the CIE - '\x20\x00\x00\x00' + # length - '\xff\xff\xff\xff' + # CIE_id - '\x03\x00\x04\x7c' + # version, augmentation, caf, daf - '\x08' + # return address - '\x0c\x07\x00' + - '\x08\x00' + - '\x07\x01' + - '\x07\x02' + - '\x07\x03' + - '\x08\x04' + - '\x08\x05' + - '\x08\x06' + - '\x08\x07' + - '\x09\x08\x01' + - '\x00' + - - # then comes the FDE - '\x28\x00\x00\x00' + # length - '\x00\x00\x00\x00' + # CIE_pointer (to CIE at 0) - '\x44\x33\x22\x11' + # initial_location - '\x54\x00\x00\x00' + # address range - '\x41' + - '\x0e\x0c' + '\x41' + - '\x88\x01' + '\x41' + - '\x86\x02' + '\x41' + - '\x0d\x06' + '\x41' + - '\x84\x03' + '\x4b' + - '\xc4' + '\x41' + - '\xc6' + - '\x0d\x07' + '\x41' + - '\xc8' + '\x41' + - '\x0e\x00' + - '\x00\x00' - ) - s.write(data) - - structs = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) - cfi = CallFrameInfo(s, len(data), structs) - entries = cfi.get_entries() - - self.assertEqual(len(entries), 2) - self.assertIsInstance(entries[0], CIE) - self.assertEqual(entries[0]['length'], 32) - self.assertEqual(entries[0]['data_alignment_factor'], -4) - self.assertEqual(entries[0]['return_address_register'], 8) - self.assertEqual(len(entries[0].instructions), 11) - self.assertInstruction(entries[0].instructions[0], - 'DW_CFA_def_cfa', [7, 0]) - self.assertInstruction(entries[0].instructions[8], - 'DW_CFA_same_value', [7]) - self.assertInstruction(entries[0].instructions[9], - 'DW_CFA_register', [8, 1]) - - self.assertTrue(isinstance(entries[1], FDE)) - self.assertEqual(entries[1]['length'], 40) - self.assertEqual(entries[1]['CIE_pointer'], 0) - self.assertEqual(entries[1]['address_range'], 84) - self.assertIs(entries[1].cie, entries[0]) - self.assertEqual(len(entries[1].instructions), 21) - self.assertInstruction(entries[1].instructions[0], - 'DW_CFA_advance_loc', [1]) - self.assertInstruction(entries[1].instructions[1], - 'DW_CFA_def_cfa_offset', [12]) - self.assertInstruction(entries[1].instructions[9], - 'DW_CFA_offset', [4, 3]) - self.assertInstruction(entries[1].instructions[18], - 'DW_CFA_def_cfa_offset', [0]) - self.assertInstruction(entries[1].instructions[20], - 'DW_CFA_nop', []) - - # Now let's decode it... - decoded_CIE = entries[0].get_decoded() - self.assertEqual(decoded_CIE.reg_order, list(range(9))) - self.assertEqual(len(decoded_CIE.table), 1) - self.assertEqual(decoded_CIE.table[0]['cfa'].reg, 7) - self.assertEqual(decoded_CIE.table[0]['pc'], 0) - self.assertEqual(decoded_CIE.table[0]['cfa'].offset, 0) - self.assertEqual(decoded_CIE.table[0][4].type, RegisterRule.SAME_VALUE) - self.assertEqual(decoded_CIE.table[0][8].type, RegisterRule.REGISTER) - self.assertEqual(decoded_CIE.table[0][8].arg, 1) - - decoded_FDE = entries[1].get_decoded() - self.assertEqual(decoded_FDE.reg_order, list(range(9))) - self.assertEqual(decoded_FDE.table[0]['cfa'].reg, 7) - self.assertEqual(decoded_FDE.table[0]['cfa'].offset, 0) - self.assertEqual(decoded_FDE.table[0]['pc'], 0x11223344) - self.assertEqual(decoded_FDE.table[0][8].type, RegisterRule.REGISTER) - self.assertEqual(decoded_FDE.table[0][8].arg, 1) - self.assertEqual(decoded_FDE.table[1]['cfa'].reg, 7) - self.assertEqual(decoded_FDE.table[1]['cfa'].offset, 12) - self.assertEqual(decoded_FDE.table[2][8].type, RegisterRule.OFFSET) - self.assertEqual(decoded_FDE.table[2][8].arg, -4) - self.assertEqual(decoded_FDE.table[2][4].type, RegisterRule.SAME_VALUE) - self.assertEqual(decoded_FDE.table[5]['pc'], 0x11223344 + 20) - self.assertEqual(decoded_FDE.table[5][4].type, RegisterRule.OFFSET) - self.assertEqual(decoded_FDE.table[5][4].arg, -12) - self.assertEqual(decoded_FDE.table[6]['pc'], 0x11223344 + 64) - self.assertEqual(decoded_FDE.table[9]['pc'], 0x11223344 + 76) - - def test_describe_CFI_instructions(self): - # The data here represents a single CIE - data = ('' + - '\x16\x00\x00\x00' + # length - '\xff\xff\xff\xff' + # CIE_id - '\x03\x00\x04\x7c' + # version, augmentation, caf, daf - '\x08' + # return address - '\x0c\x07\x02' + - '\x10\x02\x07\x03\x01\x02\x00\x00\x06\x06') - s = StringIO(data) - - structs = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) - cfi = CallFrameInfo(s, len(data), structs) - entries = cfi.get_entries() - - set_global_machine_arch('x86') - self.assertEqual(describe_CFI_instructions(entries[0]), - ( ' DW_CFA_def_cfa: r7 (edi) ofs 2\n' + - ' DW_CFA_expression: r2 (edx) (DW_OP_addr: 201; DW_OP_deref; DW_OP_deref)\n')) - - -if __name__ == '__main__': - unittest.main() - - diff --git a/tests/test_dwarf_expr.py b/tests/test_dwarf_expr.py deleted file mode 100644 index 8e293db..0000000 --- a/tests/test_dwarf_expr.py +++ /dev/null @@ -1,68 +0,0 @@ -import sys, unittest -from cStringIO import StringIO - -sys.path.extend(('..', '.')) -from elftools.dwarf.descriptions import ExprDumper, set_global_machine_arch -from elftools.dwarf.structs import DWARFStructs - - -class TestExprDumper(unittest.TestCase): - structs32 = DWARFStructs( - little_endian=True, - dwarf_format=32, - address_size=4) - - def setUp(self): - self.visitor = ExprDumper(self.structs32) - set_global_machine_arch('x64') - - def test_basic_single(self): - self.visitor.process_expr([0x1b]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_div') - - self.setUp() - self.visitor.process_expr([0x74, 0x82, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_breg4 (rsi): 130') - - self.setUp() - self.visitor.process_expr([0x91, 0x82, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_fbreg: 130') - - self.setUp() - self.visitor.process_expr([0x51]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_reg1 (rdx)') - - self.setUp() - self.visitor.process_expr([0x90, 16]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_regx: 16 (rip)') - - self.setUp() - self.visitor.process_expr([0x9d, 0x8f, 0x0A, 0x90, 0x01]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_bit_piece: 1295 144') - - def test_basic_sequence(self): - self.visitor.process_expr([0x03, 0x01, 0x02, 0, 0, 0x06, 0x06]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_addr: 201; DW_OP_deref; DW_OP_deref') - - self.setUp() - self.visitor.process_expr([0x15, 0xFF, 0x0b, 0xf1, 0xff]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_pick: 255; DW_OP_const2s: -15') - - self.setUp() - self.visitor.process_expr([0x1d, 0x1e, 0x1d, 0x1e, 0x1d, 0x1e]) - self.assertEqual(self.visitor.get_str(), - 'DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul; DW_OP_mod; DW_OP_mul') - - -if __name__ == '__main__': - unittest.main() - - diff --git a/tests/test_dwarf_lineprogram.py b/tests/test_dwarf_lineprogram.py deleted file mode 100644 index 56d96c3..0000000 --- a/tests/test_dwarf_lineprogram.py +++ /dev/null @@ -1,101 +0,0 @@ -import sys, unittest -from cStringIO import StringIO - -sys.path.extend(['.', '..']) -from elftools.dwarf.lineprogram import LineProgram, LineState, LineProgramEntry -from elftools.dwarf.structs import DWARFStructs -from elftools.dwarf.constants import * - - -class TestLineProgram(unittest.TestCase): - def _make_program_in_stream(self, stream): - """ Create a LineProgram from the given program encoded in a stream - """ - ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) - header = ds.Dwarf_lineprog_header.parse( - '\x04\x10\x00\x00' + # initial lenght - '\x03\x00' + # version - '\x20\x00\x00\x00' + # header length - '\x01\x01\x01\x0F' + # flags - '\x0A' + # opcode_base - '\x00\x01\x04\x08\x0C\x01\x01\x01\x00' + # standard_opcode_lengths - # 2 dir names followed by a NULL - '\x61\x62\x00\x70\x00\x00' + - # a file entry - '\x61\x72\x00\x0C\x0D\x0F' + - # and another entry - '\x45\x50\x51\x00\x86\x12\x07\x08' + - # followed by NULL - '\x00') - - lp = LineProgram(header, stream, ds, 0, len(stream.getvalue())) - return lp - - def assertLineState(self, state, **kwargs): - """ Assert that the state attributes specified in kwargs have the given - values (the rest are default). - """ - for k, v in kwargs.iteritems(): - self.assertEqual(getattr(state, k), v) - - def test_spec_sample_59(self): - # Sample in figure 59 of DWARFv3 - s = StringIO() - s.write( - '\x02\xb9\x04' + - '\x0b' + - '\x38' + - '\x82' + - '\x73' + - '\x02\x02' + - '\x00\x01\x01') - - lp = self._make_program_in_stream(s) - linetable = lp.get_entries() - - self.assertEqual(len(linetable), 7) - self.assertIs(linetable[0].state, None) # doesn't modify state - self.assertEqual(linetable[0].command, DW_LNS_advance_pc) - self.assertEqual(linetable[0].args, [0x239]) - self.assertLineState(linetable[1].state, address=0x239, line=3) - self.assertEqual(linetable[1].command, 0xb) - self.assertEqual(linetable[1].args, [2, 0]) - self.assertLineState(linetable[2].state, address=0x23c, line=5) - self.assertLineState(linetable[3].state, address=0x244, line=6) - self.assertLineState(linetable[4].state, address=0x24b, line=7, end_sequence=False) - self.assertEqual(linetable[5].command, DW_LNS_advance_pc) - self.assertEqual(linetable[5].args, [2]) - self.assertLineState(linetable[6].state, address=0x24d, line=7, end_sequence=True) - - def test_spec_sample_60(self): - # Sample in figure 60 of DWARFv3 - s = StringIO() - s.write( - '\x09\x39\x02' + - '\x0b' + - '\x09\x03\x00' + - '\x0b' + - '\x09\x08\x00' + - '\x0a' + - '\x09\x07\x00' + - '\x0a' + - '\x09\x02\x00' + - '\x00\x01\x01') - - lp = self._make_program_in_stream(s) - linetable = lp.get_entries() - - self.assertEqual(len(linetable), 10) - self.assertIs(linetable[0].state, None) # doesn't modify state - self.assertEqual(linetable[0].command, DW_LNS_fixed_advance_pc) - self.assertEqual(linetable[0].args, [0x239]) - self.assertLineState(linetable[1].state, address=0x239, line=3) - self.assertLineState(linetable[3].state, address=0x23c, line=5) - self.assertLineState(linetable[5].state, address=0x244, line=6) - self.assertLineState(linetable[7].state, address=0x24b, line=7, end_sequence=False) - self.assertLineState(linetable[9].state, address=0x24d, line=7, end_sequence=True) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/test_dwarf_structs.py b/tests/test_dwarf_structs.py deleted file mode 100644 index a1e30d7..0000000 --- a/tests/test_dwarf_structs.py +++ /dev/null @@ -1,39 +0,0 @@ -import sys, unittest - -sys.path.extend(['.', '..']) -from elftools.dwarf.structs import DWARFStructs - - -class TestDWARFStructs(unittest.TestCase): - def test_lineprog_header(self): - ds = DWARFStructs(little_endian=True, dwarf_format=32, address_size=4) - - c = ds.Dwarf_lineprog_header.parse( - '\x04\x10\x00\x00' + # initial lenght - '\x05\x02' + # version - '\x20\x00\x00\x00' + # header length - '\x05\x10\x40\x50' + # until and including line_range - '\x06' + # opcode_base - '\x00\x01\x04\x08\x0C' + # standard_opcode_lengths - # 2 dir names followed by a NULL - '\x61\x62\x00\x70\x00\x00' + - # a file entry - '\x61\x72\x00\x0C\x0D\x0F' + - # and another entry - '\x45\x50\x51\x00\x86\x12\x07\x08' + - # followed by NULL - '\x00') - - self.assertEqual(c.version, 0x205) - self.assertEqual(c.opcode_base, 6) - self.assertEqual(c.standard_opcode_lengths, [0, 1, 4, 8, 12]) - self.assertEqual(c.include_directory, ['ab', 'p']) - self.assertEqual(len(c.file_entry), 2) - self.assertEqual(c.file_entry[0].name, 'ar') - self.assertEqual(c.file_entry[1].name, 'EPQ') - self.assertEqual(c.file_entry[1].dir_index, 0x12 * 128 + 6) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/test_utils.py b/tests/test_utils.py deleted file mode 100644 index 54a09bb..0000000 --- a/tests/test_utils.py +++ /dev/null @@ -1,56 +0,0 @@ -import sys, unittest -from cStringIO import StringIO -from random import randint - -sys.path.extend(['.', '..']) -from elftools.common.utils import (parse_cstring_from_stream, - preserve_stream_pos) - - -class Test_parse_cstring_from_stream(unittest.TestCase): - def _make_random_string(self, n): - return ''.join(chr(randint(32, 127)) for i in range(n)) - - def test_small1(self): - sio = StringIO('abcdefgh\x0012345') - self.assertEqual(parse_cstring_from_stream(sio), 'abcdefgh') - self.assertEqual(parse_cstring_from_stream(sio, 2), 'cdefgh') - self.assertEqual(parse_cstring_from_stream(sio, 8), '') - - def test_small2(self): - sio = StringIO('12345\x006789\x00abcdefg\x00iii') - self.assertEqual(parse_cstring_from_stream(sio), '12345') - self.assertEqual(parse_cstring_from_stream(sio, 5), '') - self.assertEqual(parse_cstring_from_stream(sio, 6), '6789') - - def test_large1(self): - text = 'i' * 400 + '\x00' + 'bb' - sio = StringIO(text) - self.assertEqual(parse_cstring_from_stream(sio), 'i' * 400) - self.assertEqual(parse_cstring_from_stream(sio, 150), 'i' * 250) - - def test_large2(self): - text = self._make_random_string(5000) + '\x00' + 'jujajaja' - sio = StringIO(text) - self.assertEqual(parse_cstring_from_stream(sio), text[:5000]) - self.assertEqual(parse_cstring_from_stream(sio, 2348), text[2348:5000]) - - -class Test_preserve_stream_pos(object): - def test_basic(self): - sio = StringIO('abcdef') - with preserve_stream_pos(sio): - sio.seek(4) - self.assertEqual(stream.tell(), 0) - - sio.seek(5) - with preserve_stream_pos(sio): - sio.seek(0) - self.assertEqual(stream.tell(), 5) - - -if __name__ == '__main__': - unittest.main() - - - diff --git a/tests/testfiles/exe_simple32.elf b/tests/testfiles/exe_simple32.elf deleted file mode 100644 index d6b3cd1..0000000 Binary files a/tests/testfiles/exe_simple32.elf and /dev/null differ diff --git a/tests/testfiles/exe_simple64.elf b/tests/testfiles/exe_simple64.elf deleted file mode 100644 index ccfa6ae..0000000 Binary files a/tests/testfiles/exe_simple64.elf and /dev/null differ diff --git a/tests/testfiles/exe_stripped64.elf b/tests/testfiles/exe_stripped64.elf deleted file mode 100644 index 841b3f8..0000000 Binary files a/tests/testfiles/exe_stripped64.elf and /dev/null differ diff --git a/tests/testfiles/libelf0_8_13_32bit.so.elf b/tests/testfiles/libelf0_8_13_32bit.so.elf deleted file mode 100644 index c236625..0000000 Binary files a/tests/testfiles/libelf0_8_13_32bit.so.elf and /dev/null differ diff --git a/tests/testfiles/obj_simple32.o.elf b/tests/testfiles/obj_simple32.o.elf deleted file mode 100644 index 5ce4182..0000000 Binary files a/tests/testfiles/obj_simple32.o.elf and /dev/null differ diff --git a/tests/testfiles/penalty_32_gcc.o.elf b/tests/testfiles/penalty_32_gcc.o.elf deleted file mode 100644 index 4c5c5de..0000000 Binary files a/tests/testfiles/penalty_32_gcc.o.elf and /dev/null differ diff --git a/tests/testfiles/penalty_64_clang.o.elf b/tests/testfiles/penalty_64_clang.o.elf deleted file mode 100644 index 91d207d..0000000 Binary files a/tests/testfiles/penalty_64_clang.o.elf and /dev/null differ diff --git a/tests/testfiles/penalty_64_gcc.o.elf b/tests/testfiles/penalty_64_gcc.o.elf deleted file mode 100644 index aca100b..0000000 Binary files a/tests/testfiles/penalty_64_gcc.o.elf and /dev/null differ diff --git a/tests/testfiles/update32.o.elf b/tests/testfiles/update32.o.elf deleted file mode 100644 index ae68ef9..0000000 Binary files a/tests/testfiles/update32.o.elf and /dev/null differ diff --git a/tests/utils/Makefile b/tests/utils/Makefile deleted file mode 100644 index fd44b8e..0000000 --- a/tests/utils/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -CFLAGS = -Wall --std=c99 -# This is where `make install` from libelf places its stuff -LIBELF_HEADERS = /usr/local/include/libelf/ -LIBELF_LIBS = /usr/local/lib/ - -all: elf_creator - -elf_creator: elf_creator.c - gcc $(CFLAGS) -o elf_creator elf_creator.c \ - -I$(LIBELF_HEADERS) -L$(LIBELF_LIBS) -Wl,-rpath,$(LIBELF_LIBS) -lelf - -clean: - rm -f *.o - rm -f *.so - rm -f *.a - rm -f elf_creator - - diff --git a/tests/utils/README.txt b/tests/utils/README.txt deleted file mode 100644 index a6c496a..0000000 --- a/tests/utils/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -Some utilities that use libelf to create synthetic ELF files - diff --git a/tests/utils/elf_creator.c b/tests/utils/elf_creator.c deleted file mode 100644 index 1fd1b56..0000000 --- a/tests/utils/elf_creator.c +++ /dev/null @@ -1,204 +0,0 @@ -/* Loosely based on the code in a Knol by Roberto Garcia Lopez: -** -** http://knol.google.com/k/roberto-garca-lpez/creating-elf-relocatable-object-files/1ohwel4gqkcn2/3# -** -** Note: This file is released under the terms of the LGPL2 license. -*/ -#include -#include -#include -#include -#include -#include -#include - - -const char* OUTFILE = "generated.o"; - -// Definition of the default string table section ".shstrtab" -const char defaultStrTable[] = -{ - /* offset 00 */ '\0', // The NULL section - /* offset 01 */ '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0', - /* offset 11 */ '.', 's', 't', 'r', 't', 'a', 'b', '\0', - /* offset 19 */ '.', 's', 'y', 'm', 't', 'a', 'b', '\0', - /* offset 27 */ '.', 'c', 'o', 'm', 'm', 'e', 'n', 't', '\0', - /* offset 36 */ '.', 'b', 's', 's', '\0', - /* offset 41 */ '.', 'd', 'a', 't', 'a', '\0', - /* offset 47 */ '.', 'r', 'e', 'l', '.', 't', 'e', 'x', 't', '\0', - /* offset 57 */ '.', 't', 'e', 'x', 't', '\0' -}; - -const char defaultStrTableLen = sizeof(defaultStrTable); - -// Offsets of section names in the string table -const char _shstrtab_offset = 1; -const char _strtab_offset = 11; -const char _symtab_offset = 19; -const char _text_offset = 57; - -// Position of sections within the object file -const char _shstrtab = 1; -const char _strtab = 2; -const char _symtab = 3; -const char _text = 4; - -const char TEXT_CONTENTS[] = {0x91, 0x92, 0x93, 0x94}; - - -//---------------------------------------------------------------------------- - -int main() -{ - int FileDes; - Elf *pElf; - Elf32_Ehdr *pEhdr; - Elf32_Shdr *pShdr; - Elf_Scn *pScn; - Elf_Data *pData; - - // Create the ELF header - if (elf_version(EV_CURRENT) == EV_NONE) // It must appear before "elf_begin()" - errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1)); - - if ((FileDes = open(OUTFILE, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0) - errx(EX_OSERR, "open \"%s\" failed", "compiled.o"); - - if ((pElf = elf_begin(FileDes, ELF_C_WRITE, NULL)) == NULL) // 3rd argument is ignored for "ELF_C_WRITE" - errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); - - if ((pEhdr = elf32_newehdr(pElf)) == NULL) - errx(EX_SOFTWARE, "elf32_newehdr() failed: %s", elf_errmsg(-1)); - - pEhdr->e_ident[EI_CLASS] = ELFCLASS32; // Defined by Intel architecture - pEhdr->e_ident[EI_DATA] = ELFDATA2LSB; // Defined by Intel architecture - pEhdr->e_machine = EM_386; // Intel architecture - pEhdr->e_type = ET_REL; // Relocatable file (object file) - pEhdr->e_shstrndx = _shstrtab; // Point to the shstrtab section - - // Create the section "default section header string table (.shstrtab)" - if ((pScn = elf_newscn(pElf)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - if ((pData = elf_newdata(pScn)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - - pData->d_align = 1; - pData->d_buf = (void *) defaultStrTable; - pData->d_type = ELF_T_BYTE; - pData->d_size = defaultStrTableLen; - - if ((pShdr = elf32_getshdr(pScn)) == NULL) - errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); - - pShdr->sh_name = _shstrtab_offset; // Point to the name of the section - pShdr->sh_type = SHT_STRTAB; - pShdr->sh_flags = 0; - - // Create the section ".strtab" - if ((pScn = elf_newscn(pElf)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - if ((pData = elf_newdata(pScn)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - - const char strtab[] = {0, 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', '.','x', 0, '_', 's', 't', 'a', 'r', 't', 0}; - - pData->d_align = 1; - pData->d_buf = (void *) strtab; - pData->d_type = ELF_T_BYTE; - pData->d_size = sizeof(strtab); - - if ((pShdr = elf32_getshdr(pScn)) == NULL) - errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); - - pShdr->sh_name = _strtab_offset; - pShdr->sh_type = SHT_STRTAB; - pShdr->sh_flags = 0; - - // Create the section ".symtab" - if ((pScn = elf_newscn(pElf)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - if ((pData = elf_newdata(pScn)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - - Elf32_Sym x[4]; - - // Definition of the undefined section (this must be the first item by the definition of TIS ELF) - x[0].st_name = 0; - x[0].st_value = 0; - x[0].st_size = 0; - x[0].st_info = 0; - x[0].st_other = 0; - x[0].st_shndx = SHN_UNDEF; - - // Definition of the name of the source file (this must be the second item by the definition in TIS ELF) - x[1].st_name = 1; - x[1].st_value = 0; - x[1].st_size = 0; - x[1].st_info = ELF32_ST_INFO(STB_LOCAL, STT_FILE); // This is the value that st_info must have (because of TIS ELF) - x[1].st_other = 0; - x[1].st_shndx = SHN_ABS; // The section where the symbol is - - // Definition of the ".text" section as a section in the ".symtab" section - x[2].st_name = 0; - x[2].st_value = 0; - x[2].st_size = 0; - x[2].st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION); - x[2].st_other = 0; - x[2].st_shndx = _text; // The section where the symbol is - - // Definition of the "_start" symbol - x[3].st_name = 13; // Offset in the "strtab" section where the name start - x[3].st_value = 0; - x[3].st_size = 0; - x[3].st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE); - x[3].st_other = 0; - x[3].st_shndx = _text; // The section where the symbol is - - pData->d_align = 4; - pData->d_buf = (void *) x; - pData->d_type = ELF_T_BYTE; - pData->d_size = sizeof(x); - - if ((pShdr = elf32_getshdr(pScn)) == NULL) - errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); - - pShdr->sh_name = _symtab_offset; // Point to the name of the section - pShdr->sh_type = SHT_SYMTAB; - pShdr->sh_flags = 0; - pShdr->sh_link = _strtab; // point to the section .strtab (the section that contain the strings) - pShdr->sh_info = ELF32_ST_INFO(STB_LOCAL, 3); // the second argument is beause of TIS ELF (One greater than the symbol table index of the last local symbol (binding STB_LOCAL)) - - // Create many sections named .text - for (int i = 0; i < 70000; ++i) { - if ((pScn = elf_newscn(pElf)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - if ((pData = elf_newdata(pScn)) == NULL) - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - - pData->d_align = 4; - pData->d_buf = (void *)TEXT_CONTENTS; - pData->d_type = ELF_T_BYTE; - pData->d_size = sizeof(TEXT_CONTENTS); - - if ((pShdr = elf32_getshdr(pScn)) == NULL) - errx(EX_SOFTWARE, "elf32_etshdr() failed: %s.", elf_errmsg(-1)); - - pShdr->sh_name = _text_offset; - pShdr->sh_type = SHT_PROGBITS; - pShdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR; - } - - // Update the sections internally - if (elf_update(pElf, ELF_C_NULL) < 0) - errx(EX_SOFTWARE, "elf_update(NULL) failed: %s.", elf_errmsg(-1)); - // Write the object file - if (elf_update(pElf, ELF_C_WRITE) < 0) - errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1)); - // Close all handles - elf_end(pElf); - close(FileDes); - printf("Generated file: %s\n", OUTFILE); - - return 0; -} -