From 0993276d6450919c6d178182c5fd26497b62d5fc Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 25 Jan 2015 01:12:54 +0000
Subject: Added a fixed address for the start of the '.plt' section and
 improved the disassembly process.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@460 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                                 | 37 +++++++++++++
 src/analysis/disass/area.c                |  2 +-
 src/analysis/disass/fetch.c               |  2 +
 src/analysis/disass/output.c              | 10 ++++
 src/arch/arm/v7/link.c                    | 90 ++++++++++++++++++++++++++++++-
 src/arch/arm/v7/link.h                    | 19 ++++++-
 src/arch/arm/v7/opcodes/opcodes_tmp_arm.h |  1 -
 src/arch/arm/v7/opdefs/Makefile.am        |  1 +
 src/arch/arm/v7/opdefs/bx_A8827.d         | 12 +++++
 src/arch/arm/v7/opdefs/ldr_A8863.d        |  2 +-
 src/arch/arm/v7/opdefs/str_A88204.d       | 77 ++++++++++++++++++++++++++
 src/arch/arm/v7/post.c                    | 16 +++++-
 src/format/symbol.c                       | 13 +++--
 13 files changed, 272 insertions(+), 10 deletions(-)
 create mode 100644 src/arch/arm/v7/opdefs/str_A88204.d

diff --git a/ChangeLog b/ChangeLog
index 68a0145..e752ace 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+15-01-25  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	Choose a finer-grained resolution for decoding instructions.
+
+	* src/analysis/disass/fetch.c:
+	Add a fixed address for the start of the '.plt' section.
+
+	* src/analysis/disass/output.c:
+	Keep track of symbols to insert.
+
+	* src/arch/arm/v7/link.c:
+	* src/arch/arm/v7/link.h:
+	Handle one more instructions: bx, when Rm == pc.
+
+	* src/arch/arm/v7/opcodes/opcodes_tmp_arm.h:
+	Update missing prototypes.
+
+	* src/arch/arm/v7/opdefs/bx_A8827.d:
+	Use the newly defined hooks.
+
+	* src/arch/arm/v7/opdefs/ldr_A8863.d:
+	Fix a mistake by flipping one bit.
+
+	* src/arch/arm/v7/opdefs/Makefile.am:
+	Add a new definition to ARMV7_DEFS.
+
+	* src/arch/arm/v7/opdefs/str_A88204.d:
+	New entry: support a new ARMv7 instruction.
+
+	* src/arch/arm/v7/post.c:
+	Fix the process of resolved addresses.
+
+	* src/format/symbol.c:
+	Avoid to use the 'extra.routine' field when the symbol type is not
+	STP_ROUTINE.
+
 15-01-24  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/area.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 7e3a9a8..8340095 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -648,7 +648,7 @@ static void fill_mem_area(mem_area *area, mem_area *list, size_t count, const GL
             copy_vmpa(&start, get_mrange_addr(&area->range));
             advance_vmpa(&start, i);
 
-            if (area->exec && get_virt_addr(&start) % 4 == 0)
+            if (area->exec && get_virt_addr(&start) % 2 == 0)
             {
                 load_code_from_mem_area(area, list, count, binary, ctx, &start, info);
 
diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c
index ffc653a..38ea8c0 100644
--- a/src/analysis/disass/fetch.c
+++ b/src/analysis/disass/fetch.c
@@ -140,6 +140,8 @@ GArchInstruction *disassemble_binary_content(const GLoadedBinary *binary, GtkExt
 
     virt = g_binary_format_get_entry_point(format);
 
+    follow_execution_flow(binary, ctx, areas, count, info, 0x84d0);
+
     follow_execution_flow(binary, ctx, areas, count, info, 0x84c5);
     follow_execution_flow(binary, ctx, areas, count, info, 0x8a65);
 
diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c
index eb53206..87d0407 100644
--- a/src/analysis/disass/output.c
+++ b/src/analysis/disass/output.c
@@ -177,6 +177,16 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form
             iaddr = get_mrange_addr(g_arch_instruction_get_range(iter));
             saddr = get_mrange_addr(g_binary_symbol_get_range(symbols[sym_index]));
 
+
+            printf("OUTPUT [%zu] :: 0x%08x - 0x%08x :: 0x%08x - 0x%08x   '%s'\n",
+                   sym_index,
+                   (unsigned int)get_phy_addr(iaddr),
+                   (unsigned int)get_virt_addr(iaddr),
+                   (unsigned int)get_phy_addr(saddr),
+                   (unsigned int)get_virt_addr(saddr),
+                   g_binary_symbol_to_string(symbols[sym_index]));
+
+
             if (cmp_vmpa_by_virt(iaddr, saddr) == 0)
             {
                 /* Etiquette ? */
diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c
index c1f83ac..da5e30e 100644
--- a/src/arch/arm/v7/link.c
+++ b/src/arch/arm/v7/link.c
@@ -28,6 +28,9 @@
 #include <operands/offset.h>
 
 
+#include "../register.h"
+
+
 
 /******************************************************************************
 *                                                                             *
@@ -56,7 +59,25 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *instr, GArmV7Co
 
     pc = get_virt_addr(get_mrange_addr(range));
 
-    pc += get_mrange_length(range);
+
+
+
+    switch (iset)
+    {
+        case AV7IS_ARM:
+            pc += 8;
+            break;
+        case AV7IS_THUMB:
+            pc += 4;
+            break;
+        default:
+            assert(0);
+            break;
+    }
+
+
+
+    //pc += get_mrange_length(range);
 
     op = g_arch_instruction_get_operand(instr, 0);
 
@@ -197,6 +218,68 @@ void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7
 *  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
 *                context = contexte associé à la phase de désassemblage.      *
 *                format  = acès aux données du binaire d'origine.             *
+*                iset    = type de jeu d'instructions courant à faire suivre. *
+*                                                                             *
+*  Description : Complète un désassemblage accompli pour une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void handle_links_with_instruction_bx_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    GArmRegister *reg;                      /* Registre matériel manipulé  */
+    const mrange_t *range;                  /* Emplacementt d'instruction  */
+    virt_t pc;                              /* Position dans l'exécution   */
+
+    op = g_arch_instruction_get_operand(instr, 0);
+    assert(G_IS_REGISTER_OPERAND(op));
+
+    reg = G_ARM_REGISTER(g_register_operand_get_register(G_REGISTER_OPERAND(op)));
+
+    /**
+     * On ne sait agir qu'avec le seul contenu facilement prédictible : pc !
+     */
+
+    if (g_arm_register_get_index(reg) != 15 /* pc */)
+        return;
+
+    /**
+     * On bascule alors le mode de décodage à cette adresse...
+     */
+
+    range = g_arch_instruction_get_range(instr);
+
+    pc = get_virt_addr(get_mrange_addr(range));
+
+    switch (iset)
+    {
+        case AV7IS_ARM:
+            pc += 8;
+            //g_armv7_context_define_encoding(context, 
+            g_armv7_context_push_drop_point_ext(context, pc, AV7IS_THUMB);
+            break;
+        case AV7IS_THUMB:
+            pc += 4;
+            //g_armv7_context_define_encoding(context, 
+            g_armv7_context_push_drop_point_ext(context, pc, AV7IS_ARM);
+            break;
+        default:
+            assert(0);
+            break;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARMv7 à traiter.                       *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
 *                                                                             *
 *  Description : Complète un désassemblage accompli pour une instruction.     *
 *                                                                             *
@@ -342,6 +425,11 @@ void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr
     //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target);
 
 
+
+    if (target < 0x8000) return;
+
+
+
     new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target);
     g_arch_instruction_replace_operand(instr, new, op);
 
diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h
index 87bef54..9e52fe6 100644
--- a/src/arch/arm/v7/link.h
+++ b/src/arch/arm/v7/link.h
@@ -37,12 +37,12 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context
 
 static inline void handle_links_with_instruction_b_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
 {
-    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB);
+    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM);
 }
 
 static inline void handle_links_with_instruction_b_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
 {
-    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM);
+    handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB);
 }
 
 
@@ -77,6 +77,21 @@ static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction
 
 
 /* Complète un désassemblage accompli pour une instruction. */
+void handle_links_with_instruction_bx_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet);
+
+
+static inline void handle_links_with_instruction_bx_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_ARM);
+}
+
+static inline void handle_links_with_instruction_bx_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt)
+{
+    handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_THUMB);
+}
+
+
+/* Complète un désassemblage accompli pour une instruction. */
 void handle_links_with_instruction_cb_n_z(GArchInstruction *, GArmV7Context *, GBinFormat *);
 
 /* Complète un désassemblage accompli pour une instruction. */
diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
index 36e2193..3a5e646 100644
--- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
+++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
@@ -15,7 +15,6 @@
 #define armv7_read_arm_instr_stmib_stmfa(r) NULL
 #define armv7_read_arm_instr_stm_stmia_stmea(r) NULL
 #define armv7_read_arm_instr_stm_user_registers(r) NULL
-#define armv7_read_arm_instr_str_immediate_arm(r) NULL
 #define armv7_read_arm_instr_str_register(r) NULL
 #define armv7_read_arm_instr_strt(r) NULL
 #endif
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index fa42230..36509b4 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -77,6 +77,7 @@ ARMV7_DEFS = 							\
 	smlal_A88178.d						\
 	smull_A88189.d						\
 	str_A88203.d						\
+	str_A88204.d						\
 	strb_A88206.d						\
 	sub_A88222.d						\
 	sub_A88223.d						\
diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d
index b8ab6f8..dd06901 100644
--- a/src/arch/arm/v7/opdefs/bx_A8827.d
+++ b/src/arch/arm/v7/opdefs/bx_A8827.d
@@ -36,6 +36,12 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_bx_from_thumb
+
+    }
+
     @rules {
 
         call DefineAsReturn(1)
@@ -57,6 +63,12 @@
 
     }
 
+    @hooks {
+
+        link = handle_links_with_instruction_bx_from_thumb
+
+    }
+
     @rules {
 
         call DefineAsReturn(1)
diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d
index 0158c3d..39b9079 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8863.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8863.d
@@ -54,7 +54,7 @@
 
 @encoding(A12) {
 
-    @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12)
+    @word cond(4) 0 1 0 0 U(1) 0 W(1) 1 Rn(4) Rt(4) imm12(12)
 
     @syntax <Rgt> <base> <offset>
 
diff --git a/src/arch/arm/v7/opdefs/str_A88204.d b/src/arch/arm/v7/opdefs/str_A88204.d
new file mode 100644
index 0000000..d4e9377
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/str_A88204.d
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ##FILE## - traduction d'instructions ARMv7
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  Chrysalide is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+@title STR (immediate, ARM)
+
+@encoding(A11) {
+
+    @word cond(4) 0 1 0 1 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12)
+
+    @syntax <Rgt> <access>
+
+    @conv {
+
+        Rgt = Register(Rt)
+        Rgn = Register(Rn)
+        imm32 = ZeroExtend(imm12, 12, 32);
+        access = MakeMemoryAccess(Rgn, imm32, U, 1)
+
+    }
+
+    @rules {
+
+        //if P == '0' && W == '1' then SEE STRT;
+        //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
+        //if wback && (n == 15 || n == t) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
+
+    }
+
+}
+
+@encoding(A12) {
+
+    @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12)
+
+    @syntax <Rgt> <base> <offset>
+
+    @conv {
+
+        Rgt = Register(Rt)
+        Rgn = Register(Rn)
+        imm32 = ZeroExtend(imm12, 12, 32);
+        base = MakeMemoryNotIndexed(Rgn, W)
+        offset = MakeAccessOffset(U, imm32)
+
+    }
+
+    @rules {
+
+        //if P == '0' && W == '1' then SEE STRT;
+        //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
+        //if wback && (n == 15 || n == t) then UNPREDICTABLE;
+        if (Rt == '1111'); call DefineAsReturn(1)
+
+    }
+
+}
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index 8895740..084fc84 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -24,6 +24,9 @@
 #include "post.h"
 
 
+#include <assert.h>
+
+
 #include "../../target.h"
 
 
@@ -245,17 +248,26 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex
 
     op = g_arch_instruction_get_operand(instr, 1);
 
+
+    if (!G_IS_IMM_OPERAND(op)) return;
+
+
     if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr))
     {
         new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr);
 
         if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format))
         {
+            addr &= ~0x1;
+
+
+            printf("RESOLVING FOR 0x%08x\n", (unsigned int)addr);
+
             init_vmpa(&target, VMPA_NO_PHYSICAL, addr);
             init_mrange(&trange, &target, 0);
 
             vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL);
-            snprintf(name, sizeof(name), "loc_%s", loc + 2);
+            snprintf(name, sizeof(name), "loccc_%s", loc + 2);
 
             routine = g_binary_routine_new();
             g_binary_routine_set_name(routine, strdup(name));
@@ -272,9 +284,11 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex
             g_target_operand_resolve(G_TARGET_OPERAND(new), format);
 
         }
+        else printf("RESOLVED FOR 0x%08x\n", (unsigned int)addr);
 
         g_arch_instruction_replace_operand(instr, new, op);
 
     }
+    else assert(0);
 
 }
diff --git a/src/format/symbol.c b/src/format/symbol.c
index 3a909b4..5e66c54 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -221,10 +221,17 @@ const char *g_binary_symbol_to_string(const GBinSymbol *symbol)
 {
     const char *result;                     /* Désignation à retourner     */
 
-    if (symbol->extra.routine != NULL)
-        result = g_binary_routine_get_name(symbol->extra.routine);
+    switch (symbol->type)
+    {
+        case STP_ROUTINE:
+            result = g_binary_routine_get_name(symbol->extra.routine);
+            break;
 
-    else result = (symbol->alt != NULL ? symbol->alt : symbol->name);
+        default:
+            result = (symbol->alt != NULL ? symbol->alt : symbol->name);
+            break;
+
+    }
 
     return result;
 
-- 
cgit v0.11.2-87-g4458