#!/usr/bin/python3 # -*- coding: utf-8 -*- # S'assure du bon fonctionnement des blocs basiques from chrysacase import ChrysalideTestCase from pychrysalide.analysis.contents import FileContent from pychrysalide.analysis import LoadedBinary from pychrysalide.arch import ArchInstruction from pychrysalide.format.elf import ElfFormat import os import sys class TestBasicBlocks(ChrysalideTestCase): """TestCase for basic blocks.""" @classmethod def setUpClass(cls): super(TestBasicBlocks, cls).setUpClass() cls.log('Compile binary "hello" if needed...') fullname = sys.modules[cls.__module__].__file__ dirpath = os.path.dirname(fullname) os.system('make -C %s hello > /dev/null 2>&1' % dirpath) os.system('make -C %s irreducible > /dev/null 2>&1' % dirpath) os.system('make -C %s selfloop > /dev/null 2>&1' % dirpath) @classmethod def tearDownClass(cls): super(TestBasicBlocks, cls).tearDownClass() cls.log('Delete built binaries...') fullname = sys.modules[cls.__module__].__file__ dirpath = os.path.dirname(fullname) os.system('make -C %s clean > /dev/null 2>&1' % dirpath) def testBlockList(self): """Check basic tests for basic block list.""" fullname = sys.modules[self.__class__.__module__].__file__ filename = os.path.basename(fullname) baselen = len(fullname) - len(filename) cnt = FileContent(fullname[:baselen] + 'hello') self.assertIsNotNone(cnt) fmt = ElfFormat(cnt) self.assertIsNotNone(fmt) binary = LoadedBinary(fmt) self.assertIsNotNone(binary) binary.analyze_and_wait() sym = fmt.find_symbol_by_label('main') self.assertIsNotNone(sym) found = sym.basic_blocks.find_by_starting_addr(sym.range.addr) self.assertIsNotNone(found) self.assertEqual(found, list(sym.basic_blocks)[0]) self.assertEqual(found.index, 0) self.assertEqual(found.rank, 0) def testIrreducible(self): """Validate support for irreducible loops.""" fullname = sys.modules[self.__class__.__module__].__file__ filename = os.path.basename(fullname) baselen = len(fullname) - len(filename) cnt = FileContent(fullname[:baselen] + 'irreducible') self.assertIsNotNone(cnt) fmt = ElfFormat(cnt) self.assertIsNotNone(fmt) binary = LoadedBinary(fmt) self.assertIsNotNone(binary) binary.analyze_and_wait() sym = fmt.find_symbol_by_label('argstr') self.assertIsNotNone(sym) found = sym.basic_blocks.find_by_starting_addr(sym.range.addr) self.assertIsNotNone(found) loop_count = 0 for blk in sym.basic_blocks: for _, dt in blk.destinations: if dt == ArchInstruction.ILT_LOOP: loop_count += 1 self.assertEqual(loop_count, 2) def testSelfLoopBlock(self): """Validate support for self loop blocks.""" fullname = sys.modules[self.__class__.__module__].__file__ filename = os.path.basename(fullname) baselen = len(fullname) - len(filename) cnt = FileContent(fullname[:baselen] + 'selfloop') self.assertIsNotNone(cnt) fmt = ElfFormat(cnt) self.assertIsNotNone(fmt) binary = LoadedBinary(fmt) self.assertIsNotNone(binary) binary.analyze_and_wait() sym = fmt.find_symbol_by_label('string_array_len') self.assertIsNotNone(sym) found = sym.basic_blocks.find_by_starting_addr(sym.range.addr) self.assertIsNotNone(found) loop_count = 0 for blk in sym.basic_blocks: for _, dt in blk.destinations: if dt == ArchInstruction.ILT_LOOP: loop_count += 1 self.assertEqual(loop_count, 1)