From 570ae6b84ad1a17835da538ec3be9cf200cd1ebc Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 16 Oct 2016 11:16:30 +0200
Subject: Marked ARMv7 instructions which pop the PC register as return points.

---
 ChangeLog                           | 16 ++++++++++++++
 src/arch/arm/v7/link.c              | 43 +++++++++++++++++++++++++++++++++++++
 src/arch/arm/v7/link.h              |  3 +++
 src/arch/arm/v7/opdefs/pop_A88131.d | 20 ++++++++++++++++-
 src/arch/arm/v7/opdefs/pop_A88132.d | 14 +++++++++++-
 tools/d2c/args/grammar.y            |  7 +++---
 tools/d2c/args/manager.c            |  3 +++
 tools/d2c/args/manager.h            |  1 +
 tools/d2c/args/tokens.l             |  1 +
 9 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 82e3f2b..5da8f28 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+16-10-16  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/arm/v7/link.c:
+	* src/arch/arm/v7/link.h:
+	Mark ARMv7 instructions which pop the PC register as return points.
+
+	* src/arch/arm/v7/opdefs/pop_A88131.d:
+	* src/arch/arm/v7/opdefs/pop_A88132.d:
+	Update the definition of all 'pop' encodings.
+
+	* tools/d2c/args/grammar.y:
+	* tools/d2c/args/manager.c:
+	* tools/d2c/args/manager.h:
+	* tools/d2c/args/tokens.l:
+	Support left shift in conversion arguments.
+
 16-10-15  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/dragon.c:
diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c
index 4443fdb..9eb625f 100644
--- a/src/arch/arm/v7/link.c
+++ b/src/arch/arm/v7/link.c
@@ -27,6 +27,7 @@
 #include <assert.h>
 
 
+#include "operands/reglist.h"
 #include "../register.h"
 
 
@@ -63,3 +64,45 @@ void handle_armv7_conditional_branch_from_register(GArchInstruction *instr, GArc
         g_arch_instruction_set_flag(instr, AIF_RETURN_POINT);   /* FIXME : jump inconnu ! */
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr   = instruction ARM à traiter.                         *
+*                proc    = représentation de l'architecture utilisée.         *
+*                context = contexte associé à la phase de désassemblage.      *
+*                format  = acès aux données du binaire d'origine.             *
+*                                                                             *
+*  Description : Détecte les fins de procédures à base d'instructions 'pop'.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void handle_armv7_return_from_pop(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format)
+{
+    GArchOperand *op;                       /* Opérande numérique en place */
+    GArmV7RegListOperand *reglist;          /* Autre version de l'instance */
+    size_t count;                           /* Nombre de registres présents*/
+    size_t i;                               /* Boucle de parcours          */
+    GArmRegister *reg;                      /* Registre matériel manipulé  */
+
+    op = g_arch_instruction_get_operand(instr, 0);
+    assert(G_IS_ARMV7_REGLIST_OPERAND(op));
+
+    reglist = G_ARMV7_REGLIST_OPERAND(op);
+
+    count = g_armv7_reglist_count_registers(reglist);
+
+    for (i = 0; i < count; i++)
+    {
+        reg = G_ARM_REGISTER(g_armv7_reglist_operand_get_register(reglist, i));
+
+        if (g_arm_register_get_index(reg) == 15 /* pc */)
+            g_arch_instruction_set_flag(instr, AIF_RETURN_POINT);
+
+    }
+
+}
diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h
index 3251647..e5cc483 100644
--- a/src/arch/arm/v7/link.h
+++ b/src/arch/arm/v7/link.h
@@ -34,6 +34,9 @@
 /* Encadre les sauts à partir de registres ARMv7. */
 void handle_armv7_conditional_branch_from_register(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
 
+/* Détecte les fins de procédures à base d'instructions 'pop'. */
+void handle_armv7_return_from_pop(GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
+
 
 
 #endif  /* _ARCH_ARM_V7_LINK_H */
diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d
index 7de7ee4..2dee09a 100644
--- a/src/arch/arm/v7/opdefs/pop_A88131.d
+++ b/src/arch/arm/v7/opdefs/pop_A88131.d
@@ -37,6 +37,12 @@
 
 	}
 
+	@hooks {
+
+		link = handle_armv7_return_from_pop
+
+	}
+
 }
 
 @encoding (T2) {
@@ -51,6 +57,12 @@
 
 	}
 
+	@hooks {
+
+		link = handle_armv7_return_from_pop
+
+	}
+
 }
 
 @encoding (T3) {
@@ -61,7 +73,13 @@
 
 	@conv {
 
-		registers = Zeros(16)
+		registers = RegistersList(1 << Rt)
+
+	}
+
+	@hooks {
+
+		link = handle_armv7_return_from_pop
 
 	}
 
diff --git a/src/arch/arm/v7/opdefs/pop_A88132.d b/src/arch/arm/v7/opdefs/pop_A88132.d
index 692aecb..27bbf3b 100644
--- a/src/arch/arm/v7/opdefs/pop_A88132.d
+++ b/src/arch/arm/v7/opdefs/pop_A88132.d
@@ -43,6 +43,12 @@
 
 	}
 
+	@hooks {
+
+		link = handle_armv7_return_from_pop
+
+	}
+
 }
 
 @encoding (A2) {
@@ -53,7 +59,7 @@
 
 	@conv {
 
-		registers = Zeros(16)
+		registers = RegistersList(1 << Rt)
 
 	}
 
@@ -63,5 +69,11 @@
 
 	}
 
+	@hooks {
+
+		link = handle_armv7_return_from_pop
+
+	}
+
 }
 
diff --git a/tools/d2c/args/grammar.y b/tools/d2c/args/grammar.y
index f44a94b..41512a9 100644
--- a/tools/d2c/args/grammar.y
+++ b/tools/d2c/args/grammar.y
@@ -52,7 +52,7 @@ YY_DECL;
 %token NAME
 %token NUMBER BINVAL HEXVAL STRING
 %token COMMA COLON OP CP
-%token NOT AND_LOG EOR EQ NE
+%token NOT AND_LOG EOR LSHIFT EQ NE
 %token AND_BOOL OR_BOOL
 
 
@@ -96,8 +96,9 @@ arg_expr : NAME                                     { $$ = build_arg_expr_from_n
 
 arg_expr_un_op : NOT { $$ = CUO_NOT; }
 
-arg_expr_bin_op : AND_LOG { $$ = CBO_AND; }
-                | EOR { $$ = CBO_EOR; }
+arg_expr_bin_op : AND_LOG   { $$ = CBO_AND; }
+                | EOR       { $$ = CBO_EOR; }
+                | LSHIFT    { $$ = CBO_LSHIFT; }
 
 arg_logical_expr : arg_expr AND_BOOL arg_expr           { $$ = build_logical_arg_expr($1, $3, true); }
                  | arg_logical_expr AND_BOOL arg_expr   { $$ = build_logical_arg_expr($1, $3, true); }
diff --git a/tools/d2c/args/manager.c b/tools/d2c/args/manager.c
index 498dd5c..99c82ea 100644
--- a/tools/d2c/args/manager.c
+++ b/tools/d2c/args/manager.c
@@ -1171,6 +1171,9 @@ bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, co
                 case CBO_EOR:
                     dprintf(fd, " ^ ");
                     break;
+                case CBO_LSHIFT:
+                    dprintf(fd, " << ");
+                    break;
                 default:
                     result = false;
                     break;
diff --git a/tools/d2c/args/manager.h b/tools/d2c/args/manager.h
index 111b6db..e57a08d 100644
--- a/tools/d2c/args/manager.h
+++ b/tools/d2c/args/manager.h
@@ -51,6 +51,7 @@ typedef enum _ConvBinaryOperation
 {
     CBO_AND,                                /* Et logique                  */
     CBO_EOR,                                /* Ou exclusif (booléen)       */
+    CBO_LSHIFT,                             /* Décallage à gauche          */
 
     CBO_COUNT
 
diff --git a/tools/d2c/args/tokens.l b/tools/d2c/args/tokens.l
index 2a4ffb2..9851f62 100644
--- a/tools/d2c/args/tokens.l
+++ b/tools/d2c/args/tokens.l
@@ -59,6 +59,7 @@
 ","                         { return COMMA; }
 ":"                         { return COLON; }
 "&"                         { return AND_LOG; }
+"<<"                        { return LSHIFT; }
 "=="                        { return EQ; }
 "!="                        { return NE; }
 
-- 
cgit v0.11.2-87-g4458