LIEF/tests/elf/test_static.py

163 lines
4.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python
import unittest
import logging
import os
import sys
import subprocess
import tempfile
import shutil
import lief
from lief import Logger
Logger.set_level(lief.LOGGING_LEVEL.INFO)
from subprocess import Popen
from unittest import TestCase
BINADD_C = """\
#include <stdio.h>
#include <stdlib.h>
int add(int a, int b);
int main(int argc, char **argv) {
if (argc != 3) {
printf("Usage: %s <a> <b>\\n", argv[0]);
exit(-1);
}
int res = add(atoi(argv[1]), atoi(argv[2]));
printf("From myLIb, a + b = %d\\n", res);
return 0;
}
"""
ADD_C = """\
int add(int a, int b) {
return a + b;
}
"""
class LibAddSample(object):
COUNT = 0
def __init__(self):
self.logger = logging.getLogger(__name__)
self.tmp_dir = tempfile.mkdtemp(suffix='_lief_sample_{:d}'.format(LibAddSample.COUNT))
self.logger.debug("temp dir: {}".format(self.tmp_dir))
LibAddSample.COUNT += 1
self.binadd_path = os.path.join(self.tmp_dir, "binadd.c")
self.add_c_path = os.path.join(self.tmp_dir, "add.c")
self.binadd_obj = os.path.join(self.tmp_dir, "binadd.o")
self.binadd_bin = os.path.join(self.tmp_dir, "binadd.exe")
self.compiler = '/usr/bin/cc'
if self.compiler is None:
self.logger.error("Unable to find a compiler")
sys.exit(0)
self.logger.debug("Compiler: {}".format(self.compiler))
with open(self.binadd_path, 'w') as f:
f.write(BINADD_C)
with open(self.add_c_path, 'w') as f:
f.write(ADD_C)
self._compile_objadd()
def _compile_objadd(self):
if os.path.isfile(self.binadd_obj):
os.remove(self.binadd_obj)
cmd = [self.compiler, '-c', '-o', self.binadd_obj, self.binadd_path]
self.logger.debug("Compile 'binadd' with: {}".format(" ".join(cmd)))
p = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
self.logger.debug(stdout)
def compile_object_to_bin(self):
if os.path.isfile(self.binadd_bin):
os.remove(self.binadd_bin)
cmd = [self.compiler, '-o', self.binadd_bin, self.binadd_obj, self.add_c_path]
self.logger.debug("Compile 'binadd' with: {}".format(" ".join(cmd)))
p = Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, _ = p.communicate()
self.logger.debug(stdout)
@property
def binadd(self):
return self.binadd_bin
@property
def objadd(self):
return self.binadd_obj
@property
def directory(self):
return self.tmp_dir
def remove(self):
if os.path.isdir(self.directory):
shutil.rmtree(self.directory)
def __del__(self):
self.remove()
class TestStatic(TestCase):
def setUp(self):
self.logger = logging.getLogger(__name__)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_write_object(self):
sample = LibAddSample()
tmp_file = os.path.join(sample.directory, "newfile.o")
binadd = lief.parse(sample.objadd)
init_obj = [str(o).strip() for o in binadd.object_relocations]
binadd.write(tmp_file)
binadd = lief.parse(tmp_file)
new_obj = [str(o).strip() for o in binadd.object_relocations]
self.assertEqual(len(init_obj), len(new_obj))
for new, old in zip(new_obj, init_obj):
self.assertEqual(new, old)
# Check it can still be compiled
sample.compile_object_to_bin()
self.assertEqual(subprocess.check_output([sample.binadd_bin, "2", "3"]).decode('ascii', 'ignore'),
'From myLIb, a + b = 5\n')
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_update_addend_object(self):
sample = LibAddSample()
tmp_file = os.path.join(sample.directory, "newfile.o")
binadd = lief.parse(sample.objadd)
reloc = next(o for o in binadd.object_relocations if o.symbol.name == "add")
reloc.addend = 0xABCD
binadd.write(tmp_file)
binadd = lief.parse(tmp_file)
reloc = next(o for o in binadd.object_relocations if o.symbol.name == "add")
self.assertEqual(reloc.addend, 0xABCD)
if __name__ == '__main__':
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
root_logger.addHandler(ch)
unittest.main(verbosity=2)