From d992b4ae5a35954d4fda460735f6dc861ae7bd26 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 19 Feb 2019 19:34:33 +0100 Subject: Ensured all natural links are well created. --- src/analysis/disass/links.c | 28 +++++++--------- tests/analysis/disass/Makefile | 5 ++- tests/analysis/disass/h1b.c | 25 +++++++++++++++ tests/analysis/disass/links.py | 72 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 tests/analysis/disass/h1b.c create mode 100644 tests/analysis/disass/links.py diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c index 26788db..4eba0d7 100644 --- a/src/analysis/disass/links.c +++ b/src/analysis/disass/links.c @@ -58,8 +58,7 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev) bool has_src; /* Présence de sources ? */ const instr_link_t *other; /* Instruction diverse liée */ size_t i; /* Boucle de parcours */ - bool no_natural; /* Aucun lien naturel présent */ - bool no_need; /* Pas de besoin pour ce lien */ + bool need; /* Besoin exprimé pour ce lien */ /** * Si rien ne vient séparer les deux instructions, @@ -108,29 +107,26 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev) count = g_arch_instruction_count_destinations(prev); - no_natural = true; - no_need = (count > 0); + need = true; - for (i = 0; i < count && no_natural; i++) + for (i = 0; i < count && need; i++) { other = g_arch_instruction_get_destination(prev, i); switch (other->type) { case ILT_EXEC_FLOW: - no_natural = false; + need = false; + break; + + case ILT_JUMP: + case ILT_CASE_JUMP: + need = false; break; case ILT_JUMP_IF_TRUE: case ILT_JUMP_IF_FALSE: - if (other->linked != instr) - no_need = false; - else - { - no_need = true; - unref_instr_link(other); - goto check_done; - } + need = (other->linked != instr); break; default: @@ -142,11 +138,9 @@ void establish_natural_link(GArchInstruction *instr, GArchInstruction *prev) } - check_done: - g_arch_instruction_unlock_dest(prev); - if (no_natural && !no_need) + if (need) { /* Vérification de la cohérence de l'ensemble */ #ifndef NDEBUG diff --git a/tests/analysis/disass/Makefile b/tests/analysis/disass/Makefile index 17df230..8359b5c 100644 --- a/tests/analysis/disass/Makefile +++ b/tests/analysis/disass/Makefile @@ -1,5 +1,5 @@ -EXECUTABLES=hello endofname irreducible selfloop evalcommand +EXECUTABLES=hello endofname irreducible selfloop evalcommand h1b all: $(EXECUTABLES) @@ -18,5 +18,8 @@ selfloop: selfloop.c evalcommand: evalcommand.c $(ARM_CROSS)gcc $< -o $@ +h1b: h1b.c + $(ARM_CROSS)gcc $< -o $@ + clean: rm -f $(EXECUTABLES) diff --git a/tests/analysis/disass/h1b.c b/tests/analysis/disass/h1b.c new file mode 100644 index 0000000..f29033f --- /dev/null +++ b/tests/analysis/disass/h1b.c @@ -0,0 +1,25 @@ + +#include + +int main(int argc, char **argv) +{ + int i; + + for (i = 0; i < argc; i++) + { + printf("arg[%d]: %s\n", i, argv[i]); + + if (argc > 2) + printf("!"); + else + printf("#"); + + printf("."); + + } + + printf("Hello\n"); + + return 0; + +} diff --git a/tests/analysis/disass/links.py b/tests/analysis/disass/links.py new file mode 100644 index 0000000..e0c9ec9 --- /dev/null +++ b/tests/analysis/disass/links.py @@ -0,0 +1,72 @@ +#!/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 TestDisassLinks(ChrysalideTestCase): + """TestCase for ARMv7.""" + + @classmethod + def setUpClass(cls): + + super(TestDisassLinks, cls).setUpClass() + + cls.log('Compile binary "h1b" if needed...') + + fullname = sys.modules[cls.__module__].__file__ + dirpath = os.path.dirname(fullname) + + os.system('make -C %s h1b > /dev/null 2>&1' % dirpath) + + + @classmethod + def tearDownClass(cls): + + super(TestDisassLinks, 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 testNaturalLinks(self): + """Ensure all natural links are well created.""" + + fullname = sys.modules[self.__class__.__module__].__file__ + filename = os.path.basename(fullname) + + baselen = len(fullname) - len(filename) + + cnt = FileContent(fullname[:baselen] + 'h1b') + self.assertIsNotNone(cnt) + + fmt = ElfFormat(cnt) + self.assertIsNotNone(fmt) + + binary = LoadedBinary(fmt) + self.assertIsNotNone(binary) + + binary.analyze_and_wait() + + nat_count = 0 + + for ins in binary.processor.instrs: + for _, dt in ins.destinations: + if dt == ArchInstruction.ILT_EXEC_FLOW: + nat_count += 1 + + self.assertEqual(nat_count, 3) -- cgit v0.11.2-87-g4458