From a4fde950b940582a0e21a84c6c98a79f945fde02 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 14 Jan 2019 08:43:32 +0100 Subject: Detected self loops in basic blocks. --- src/analysis/disass/loop.c | 10 ++++++- tests/analysis/disass/Makefile | 5 +++- tests/analysis/disass/block.py | 37 +++++++++++++++++++++++ tests/analysis/disass/selfloop.c | 64 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100755 tests/analysis/disass/selfloop.c diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c index 9e964e5..b82d58e 100644 --- a/src/analysis/disass/loop.c +++ b/src/analysis/disass/loop.c @@ -408,7 +408,15 @@ static void define_basic_blocks_loops(GBlockList *list, bblock_info_t *info) links = get_block_successors(block, info, &count); for (k = 0; k < count; k++) - if (links[k].info == iter->iloop_header) + if (links[k].info == iter->iloop_header + /** + * Il se peut qu'un bloc fasse référence à lui même ! + * + * Cf. tests/analysis/disass/selfloop.c + * + * On évite ici une boucle sans fin en officialisant cette boucle. + */ + || links[k].info == iter) { g_basic_block_get_boundaries(G_BASIC_BLOCK(block), NULL, &last); g_basic_block_get_boundaries(G_BASIC_BLOCK(links[k].linked), &first, NULL); diff --git a/tests/analysis/disass/Makefile b/tests/analysis/disass/Makefile index 030e868..ef70dec 100644 --- a/tests/analysis/disass/Makefile +++ b/tests/analysis/disass/Makefile @@ -1,5 +1,5 @@ -EXECUTABLES=hello endofname irreducible +EXECUTABLES=hello endofname irreducible selfloop all: $(EXECUTABLES) @@ -12,5 +12,8 @@ endofname: endofname.c irreducible: irreducible.c $(ARM_CROSS)gcc $< -o $@ +selfloop: selfloop.c + $(ARM_CROSS)gcc $< -o $@ + clean: rm -f $(EXECUTABLES) diff --git a/tests/analysis/disass/block.py b/tests/analysis/disass/block.py index 84fa4c3..10a2c80 100644 --- a/tests/analysis/disass/block.py +++ b/tests/analysis/disass/block.py @@ -31,6 +31,8 @@ class TestBasicBlocks(ChrysalideTestCase): 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): @@ -110,3 +112,38 @@ class TestBasicBlocks(ChrysalideTestCase): 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) diff --git a/tests/analysis/disass/selfloop.c b/tests/analysis/disass/selfloop.c new file mode 100755 index 0000000..fe9cf21 --- /dev/null +++ b/tests/analysis/disass/selfloop.c @@ -0,0 +1,64 @@ + +#include + + +/** + * On reproduit un code similaire à celui d'un fichier de Busybox (busybox-1.30.0/libbb/appletlib.c). + * + * La commande de compilation est : + * + * arm-linux-gnueabi-gcc -Wp,-MD,libbb/.appletlib.o.d -std=gnu99 -Iinclude -Ilibbb -include include/autoconf.h -D_GNU_SOURCE -DNDEBUG -D"BB_VER=KBUILD_STR(1.30.0)" -Wall -Wshadow -Wwrite-strings -Wundef -Wstrict-prototypes -Wunused -Wunused-parameter -Wunused-function -Wunused-value -Wmissing-prototypes -Wmissing-declarations -Wno-format-security -Wdeclaration-after-statement -Wold-style-definition -fno-builtin-strlen -finline-limit=0 -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-guess-branch-probability -funsigned-char -static-libgcc -falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1 -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-builtin-printf -Os -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(appletlib)" -D"KBUILD_MODNAME=KBUILD_STR(appletlib)" -c -o libbb/appletlib.o libbb/appletlib.c + * + */ + + +/* +unsigned FAST_FUNC string_array_len(char **argv) +{ + char **start = argv; + + while (*argv) + argv++; + + return argv - start; +} +*/ + +unsigned __attribute__ ((naked)) string_array_len(char **argv) +{ + /* + 0x00009a0c <+0>: mov r2, r0 + 0x00009a10 <+4>: mov r3, r2 + 0x00009a14 <+8>: ldr r1, [r3] + 0x00009a18 <+12>: add r2, r2, #4 + 0x00009a1c <+16>: cmp r1, #0 + 0x00009a20 <+20>: bne 0x9a10 + 0x00009a24 <+24>: rsb r0, r0, r3 + 0x00009a28 <+28>: asr r0, r0, #2 + 0x00009a2c <+32>: bx lr + */ + +asm ( + + "mov r2, r0" "\n" + + ".Lbl_9a10%=:" "\n" + + "mov r3, r2" "\n" + "ldr r1, [r3]" "\n" + "add r2, r2, #4" "\n" + "cmp r1, #0" "\n" + "bne .Lbl_9a10%=" "\n" + "rsb r0, r0, r3" "\n" + "asr r0, r0, #2" "\n" + "bx lr" "\n" + + ::"r" (argv)); + +} + +int main(int argc, char **argv) +{ + return string_array_len(argv); + +} -- cgit v0.11.2-87-g4458