From 10deb6bbbeeaacfec577f5b24c5f821492af77f3 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 19 Oct 2008 15:05:04 +0000
Subject: Registered symbols found in the PLT.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@35 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                  |  39 ++++++
 src/arch/instruction-int.h |  22 ++++
 src/arch/instruction.c     |   2 +
 src/arch/operand.c         | 118 ++++++++++++++++++
 src/arch/operand.h         |   3 +
 src/arch/processor.c       |   5 +
 src/arch/x86/instruction.h |   4 +
 src/arch/x86/op_add.c      |  35 ++++++
 src/arch/x86/op_jump.c     |  86 +++++++++++++
 src/arch/x86/op_push.c     |   6 +
 src/arch/x86/opcodes.h     |   9 ++
 src/arch/x86/operand.c     |  26 +++-
 src/arch/x86/processor.c   |  18 ++-
 src/format/elf/e_elf.c     |  12 ++
 src/format/elf/elf-int.h   |  33 +++++
 src/format/elf/symbol.c    | 305 +++++++++++++++++++++++++++++++++++++++++++--
 16 files changed, 703 insertions(+), 20 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 917afe6..48ea906 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2008-10-19  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/instruction.c:
+	Define a type for the 'db' instruction.
+
+	* src/arch/instruction-int.h:
+	Add more information about instructions: virtual address and type.
+
+	* src/arch/operand.c:
+	* src/arch/operand.h:
+	Add a function to get the immediate value of an operand.
+
+	* src/arch/processor.c:
+	Save the virtual address of a decoded instruction.
+
+	* src/arch/x86/instruction.h:
+	* src/arch/x86/op_add.c:
+	* src/arch/x86/opcodes.h:
+	Register some new instructions.
+
+	* src/arch/x86/operand.c:
+	Fix a bug when reading relative addresses (16/32 bits).
+
+	* src/arch/x86/op_jump.c:
+	* src/arch/x86/op_push.c:
+	Register some new instructions and define their type.
+
+	* src/arch/x86/processor.c:
+	Register some new instructions. Fix the case of the 0x00 opcode (add).
+
+	* src/format/elf/e_elf.c:
+	Load .plt as executable section.
+
+	* src/format/elf/elf-int.h:
+	Try to support both 32 and 64 bits architectures (Elf_Rel and Elf_Sym).
+
+	* src/format/elf/symbol.c:
+	Register symbols found in the PLT.
+
 2008-10-12  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/binary.c:
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index 72c7914..895c29f 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -40,11 +40,33 @@
 #define DB_OPCODE   0x00
 
 
+
+/* Typage des instructions rencontrées */
+typedef enum _AsmInstrType
+{
+    AIT_OTHER,                              /* Instruction inintéressante  */
+
+    AIT_DB,                                 /* Instruction non décodée     */
+
+    AIT_PUSH,                               /* Empilement de valeur        */
+    AIT_POP,                                /* Dépilement de valeur        */
+    AIT_JUMP,                               /* Saut à une adresse          */
+
+    AIT_CALL                                /* Appel d'une fonction        */
+
+} AsmInstrType;
+
+
+
 /* Définition générique d'une instruction */
 struct _asm_instr
 {
     uint8_t opcode;
 
+    uint64_t vaddress;                      /* Adresse virtuelle associée  */
+
+    AsmInstrType type;                      /* Type d'instruction          */
+
     asm_operand **operands;                 /* Liste des opérandes         */
     size_t operands_count;                  /* Nbre. d'opérandes utilisées */
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index e199dc5..ada3d58 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -53,6 +53,8 @@ asm_instr *create_db_instruction(const uint8_t *data, off_t *pos, off_t len)
 
     result->opcode = DB_OPCODE;
 
+    result->type = AIT_DB;
+
     /* TODO: check result */
     result->operands = (asm_operand **)calloc(1, sizeof(asm_operand *));
     result->operands[0] = (asm_operand *)calloc(1, sizeof(asm_operand));
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 53e652c..fa43416 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -367,6 +367,124 @@ bool fill_relimm_operand(asm_operand *operand, AsmOperandSize size, const uint8_
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : operand = structure dont le contenu est à définir.           *
+*                size    = taille de l'opérande souhaitée.                    *
+*                ...     = zone d'enregistrement prévue.                      *
+*                                                                             *
+*  Description : Récupère la valeur d'une opérande sur x bits.                *
+*                                                                             *
+*  Retour      : true si l'opération s'est effectuée avec succès, false sinon.*
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool get_imm_operand_value(asm_operand *operand, AsmOperandSize size, ...)
+{
+    bool result;                            /* Bilan à retourner           */
+    va_list ap;                             /* Récupération d'argument     */
+    uint8_t *val8;                          /* Valeur sur 8 bits           */
+    uint16_t *val16;                        /* Valeur sur 16 bits          */
+    uint32_t *val32;                        /* Valeur sur 32 bits          */
+    uint64_t *val64;                        /* Valeur sur 64 bits          */
+
+    result = true;
+
+    va_start(ap, size);
+
+    switch (size)
+    {
+        case AOS_8_BITS:
+            val8 = va_arg(ap, uint8_t *);
+            switch (operand->size)
+            {
+                case AOS_8_BITS:
+                    *val8 = operand->value.val8;
+                    break;
+                case AOS_16_BITS:
+                    result = false;
+                    break;
+                case AOS_32_BITS:
+                    result = false;
+                    break;
+                case AOS_64_BITS:
+                    result = false;
+                    break;
+            }
+            break;
+
+        case AOS_16_BITS:
+            val16 = va_arg(ap, uint16_t *);
+            switch (operand->size)
+            {
+                case AOS_8_BITS:
+                    *val16 = operand->value.val8;
+                    break;
+                case AOS_16_BITS:
+                    *val16 = operand->value.val16;
+                    break;
+                case AOS_32_BITS:
+                    result = false;
+                    break;
+                case AOS_64_BITS:
+                    result = false;
+                    break;
+            }
+            break;
+
+        case AOS_32_BITS:
+            val32 = va_arg(ap, uint32_t *);
+            switch (operand->size)
+            {
+                case AOS_8_BITS:
+                    *val32 = operand->value.val8;
+                    break;
+                case AOS_16_BITS:
+                    *val32 = operand->value.val16;
+                    break;
+                case AOS_32_BITS:
+                    *val32 = operand->value.val32;
+                    break;
+                case AOS_64_BITS:
+                    result = false;
+                    break;
+            }
+            break;
+
+        case AOS_64_BITS:
+            val64 = va_arg(ap, uint64_t *);
+            switch (operand->size)
+            {
+                case AOS_8_BITS:
+                    *val64 = operand->value.val8;
+                    break;
+                case AOS_16_BITS:
+                    *val64 = operand->value.val16;
+                    break;
+                case AOS_32_BITS:
+                    *val64 = operand->value.val32;
+                    break;
+                case AOS_64_BITS:
+                    *val64 = operand->value.val64;
+                    break;
+            }
+            break;
+
+        default:
+            result = false;
+            break;
+
+    }
+
+    va_end(ap);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : operand = instruction à traiter.                             *
 *                buffer  = tampon de sortie mis à disposition. [OUT]          *
 *                len     = taille de ce tampon.                               *
diff --git a/src/arch/operand.h b/src/arch/operand.h
index a05f819..0a00d9f 100644
--- a/src/arch/operand.h
+++ b/src/arch/operand.h
@@ -76,6 +76,9 @@ bool fill_imm_operand_with_value(asm_operand *, AsmOperandSize, ...);
 /* Crée une opérande contenant une valeur relative sur x bits. */
 bool fill_relimm_operand(asm_operand *, AsmOperandSize, const uint8_t *, off_t *, off_t, uint64_t);
 
+/* Récupère la valeur d'une opérande sur x bits. */
+bool get_imm_operand_value(asm_operand *, AsmOperandSize, ...);
+
 /* Traduit une opérande de valeur immédiate en texte. */
 void print_imm_operand(const asm_operand *, char *, size_t, AsmSyntax);
 
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 373222f..fc9f773 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -24,12 +24,14 @@
 #include "processor.h"
 
 
+#include "instruction-int.h"
 #include "processor-int.h"
 
 
 
 
 
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : proc   = architecture visée par la procédure.                *
@@ -66,6 +68,9 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of
     }
 
 
+    result->vaddress = offset;
+
+
 
     return result;
 
diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h
index 8ef603f..baf911d 100644
--- a/src/arch/x86/instruction.h
+++ b/src/arch/x86/instruction.h
@@ -38,6 +38,8 @@ typedef struct _asm_x86_instr asm_x86_instr;
 /* Enumération de tous les opcodes */
 typedef enum _X86Opcodes
 {
+    X86_OP_ADD_RM8_R8,                      /* add (0x00)                  */
+
     X86_OP_SUB_R1632_RM1632,                /* sub ([0x66] 0x29)           */
 
     X86_OP_XOR_RM8_R8,                      /* xor (0x30)                  */
@@ -145,12 +147,14 @@ typedef enum _X86Opcodes
     X86_OP_INT,                             /* int (0xcd)                  */
 
     X86_OP_CALL_REL1632,                    /* call ([0x66] 0xe8)          */
+    X86_OP_JMP_REL1632,                     /* jmp ([0x66] 0xe9)           */
 
     X86_OP_JMP_8,                           /* jmp (0xeb)                  */
 
     X86_OP_HLT,                             /* hlt (0xf4)                  */
 
     X86_OP_CALL_RM1632,                     /* call ([0x66] 0xff 2)        */
+    X86_OP_JMP_RM1632,                      /* jmp ([0x66] 0xff 4)         */
     X86_OP_PUSH_RM1632,                     /* push ([0x66] 0xff 6)        */
 
     X86_OP_COUNT
diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c
index 52b998f..f42c8f9 100644
--- a/src/arch/x86/op_add.c
+++ b/src/arch/x86/op_add.c
@@ -104,3 +104,38 @@ asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *data, off_t *
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data   = flux de données à analyser.                         *
+*                pos    = position courante dans ce flux. [OUT]               *
+*                len    = taille totale des données à analyser.               *
+*                offset = adresse virtuelle de l'instruction.                 *
+*                proc   = architecture ciblée par le désassemblage.           *
+*                                                                             *
+*  Description : Décode une instruction de type 'add' (8 bits).               *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+    asm_x86_instr *result;                  /* Instruction à retourner     */
+
+    result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+    ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+    if (!x86_read_two_operands(result, data, pos, len, X86_OTP_RM8, X86_OTP_R8))
+    {
+        free(result);
+        return NULL;
+    }
+
+    return result;
+
+}
diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c
index b301b10..3739b24 100644
--- a/src/arch/x86/op_jump.c
+++ b/src/arch/x86/op_jump.c
@@ -54,6 +54,8 @@ asm_x86_instr *x86_read_instr_je_8(const uint8_t *data, off_t *pos, off_t len, u
 
     ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
 
+    ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
     {
         free(result);
@@ -89,6 +91,8 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *data, off_t *pos, off_t len,
 
     ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
 
+    ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
     {
         free(result);
@@ -124,6 +128,8 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len,
 
     ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
 
+    ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL8, offset))
     {
         free(result);
@@ -133,3 +139,83 @@ asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *data, off_t *pos, off_t len,
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data   = flux de données à analyser.                         *
+*                pos    = position courante dans ce flux. [OUT]               *
+*                len    = taille totale des données à analyser.               *
+*                offset = adresse virtuelle de l'instruction.                 *
+*                proc   = architecture ciblée par le désassemblage.           *
+*                                                                             *
+*  Description : Décode une instruction de type 'jmp' (grand saut relatif).   *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+    asm_x86_instr *result;                  /* Instruction à retourner     */
+    AsmOperandSize oprsize;                 /* Taille des opérandes        */
+
+    result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+    oprsize = switch_x86_operand_size_if_needed(proc, data, pos);
+
+    ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+    ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
+    if (!x86_read_one_operand(result, data, pos, len, X86_OTP_REL1632, oprsize, offset))
+    {
+        free(result);
+        return NULL;
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : data   = flux de données à analyser.                         *
+*                pos    = position courante dans ce flux. [OUT]               *
+*                len    = taille totale des données à analyser.               *
+*                offset = adresse virtuelle de l'instruction.                 *
+*                proc   = architecture ciblée par le désassemblage.           *
+*                                                                             *
+*  Description : Décode une instruction de type 'jmp' (saut en mémoire).      *
+*                                                                             *
+*  Retour      : Instruction mise en place ou NULL.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+    asm_x86_instr *result;                  /* Instruction à retourner     */
+    AsmOperandSize oprsize;                 /* Taille des opérandes        */
+
+    result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+    oprsize = switch_x86_operand_size_if_needed(proc, data, pos);
+
+    ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+    ASM_INSTRUCTION(result)->type = AIT_JUMP;
+
+    if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize))
+    {
+        free(result);
+        return NULL;
+    }
+
+    return result;
+
+}
diff --git a/src/arch/x86/op_push.c b/src/arch/x86/op_push.c
index ce76919..f51bd6f 100644
--- a/src/arch/x86/op_push.c
+++ b/src/arch/x86/op_push.c
@@ -58,6 +58,8 @@ asm_x86_instr *x86_read_instr_push_imm1632(const uint8_t *data, off_t *pos, off_
 
     ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
 
+    ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_IMM1632, oprsize))
     {
         free(result);
@@ -96,6 +98,8 @@ asm_x86_instr *x86_read_instr_push_r1632(const uint8_t *data, off_t *pos, off_t
 
     ASM_INSTRUCTION(result)->opcode = data[*pos];
 
+    ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_OP_R1632, oprsize, 0x50))
     {
         free(result);
@@ -134,6 +138,8 @@ asm_x86_instr *x86_read_instr_push_rm1632(const uint8_t *data, off_t *pos, off_t
 
     ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
 
+    ASM_INSTRUCTION(result)->type = AIT_PUSH;
+
     if (!x86_read_one_operand(result, data, pos, len, X86_OTP_RM1632, oprsize))
     {
         free(result);
diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h
index cbadcf5..70d41b8 100644
--- a/src/arch/x86/opcodes.h
+++ b/src/arch/x86/opcodes.h
@@ -43,6 +43,9 @@ asm_x86_instr *x86_read_instr_add_imm8_to_rm1632(const uint8_t *, off_t *, off_t
 /* Décode une instruction de type 'add' (16 ou 32 bits). */
 asm_x86_instr *x86_read_instr_add_imm1632_to_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
 
+/* Décode une instruction de type 'add' (8 bits). */
+asm_x86_instr *x86_read_instr_add_rm8_r8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
 /* Décode une instruction de type 'and' (16 ou 32 bits). */
 asm_x86_instr *x86_read_instr_and_rm1632_with_imm8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
 
@@ -82,6 +85,12 @@ asm_x86_instr *x86_read_instr_jne_8(const uint8_t *, off_t *, off_t, uint64_t, c
 /* Décode une instruction de type 'jump' (petit saut). */
 asm_x86_instr *x86_read_instr_jmp_8(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
 
+/* Décode une instruction de type 'jmp' (grand saut relatif). */
+asm_x86_instr *x86_read_instr_jmp_rel1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'jmp' (saut en mémoire). */
+asm_x86_instr *x86_read_instr_jmp_rm1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
 /* Décode une instruction de type 'lea' (16 ou 32 bits). */
 asm_x86_instr *x86_read_instr_lea(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
 
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 375b0a5..e13c793 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -1300,7 +1300,8 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t
 {
     asm_x86_operand *result;                /* Emplacement à retourner     */
     off_t init_pos;                         /* Position avant lecture      */
-    int8_t offset;                          /* Décallage à appliquer       */
+    int32_t offset32;                       /* Décallage 32b à appliquer   */
+    int16_t offset16;                       /* Décallage 16b à appliquer   */
     uint32_t address;                       /* Adresse finale visée        */
 
     result = create_new_x86_operand();
@@ -1308,13 +1309,28 @@ asm_x86_operand *x86_create_rel1632_operand_in_32b(uint64_t base, const uint8_t
     init_pos = *pos;
     address = base;
 
-    if (!read_imm_value(is_reg32 ? AOS_32_BITS : AOS_16_BITS, data, pos, len, &offset))
+    if (is_reg32)
     {
-        free(result);
-        return NULL;
+        if (!read_imm_value(AOS_32_BITS, data, pos, len, &offset32))
+        {
+            free(result);
+            return NULL;
+        }
+
+        address = base + (*pos - init_pos) + offset32;
+
     }
+    else
+    {
+        if (!read_imm_value(AOS_16_BITS, data, pos, len, &offset16))
+        {
+            free(result);
+            return NULL;
+        }
 
-    address = base + (*pos - init_pos) + offset;
+        address = base + (*pos - init_pos) + offset16;
+
+    }
 
     if (!fill_imm_operand_with_value(ASM_OPERAND(result), AOS_32_BITS, &address))
     {
diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c
index 0b81a8c..5694d9e 100644
--- a/src/arch/x86/processor.c
+++ b/src/arch/x86/processor.c
@@ -61,7 +61,7 @@ typedef struct _x86_opcode
     do {                                                                        \
         target.prefix = _prefix;                                                \
         target.opcode = _opcode;                                                \
-        target.opt_prefix = true;                                               \
+        target.opt_prefix = (_prefix != 0x00);                                  \
         target.has_op_ext = false;                                              \
         target.name = _name;                                                    \
         target.read = _read;                                                    \
@@ -72,7 +72,7 @@ typedef struct _x86_opcode
         target.prefix = _prefix;                                                \
         target.opcode = _opcode;                                                \
         target.op_ext = _ext << 3;                                              \
-        target.opt_prefix = true;                                               \
+        target.opt_prefix = (_prefix != 0x00);                                  \
         target.has_op_ext = true;                                               \
         target.name = _name;                                                    \
         target.read = _read;                                                    \
@@ -205,6 +205,8 @@ AsmOperandSize switch_x86_operand_size_if_needed(const asm_x86_processor *proc,
 
 void x86_register_instructions(asm_x86_processor *proc)
 {
+    register_opcode(proc->opcodes[X86_OP_ADD_RM8_R8], 0x00, 0x00, "add", x86_read_instr_add_rm8_r8);
+
     register_opcode(proc->opcodes[X86_OP_SUB_R1632_RM1632], 0x66, 0x29, "sub", x86_read_instr_sub_r1632_from_rm1632);
 
     register_opcode(proc->opcodes[X86_OP_XOR_RM8_R8], 0x00, 0x30, "xor", x86_read_instr_xor_rm8_with_r8);
@@ -314,12 +316,14 @@ void x86_register_instructions(asm_x86_processor *proc)
 
 
     register_opcode(proc->opcodes[X86_OP_CALL_REL1632], 0x66, 0xe8, "call", x86_read_instr_call_rel1632);
+    register_opcode(proc->opcodes[X86_OP_JMP_REL1632], 0x66, 0xe9, "jmp", x86_read_instr_jmp_rel1632);
 
     register_opcode(proc->opcodes[X86_OP_JMP_8], 0x00, 0xeb, "jmp", x86_read_instr_jmp_8);
 
     register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", x86_read_instr_hlt);
 
     register_opcode_with_ext(proc->opcodes[X86_OP_CALL_RM1632], 0x66, 0xff, 2, "call", x86_read_instr_call_rm1632);
+    register_opcode_with_ext(proc->opcodes[X86_OP_JMP_RM1632], 0x66, 0xff, 4, "jmp", x86_read_instr_jmp_rm1632);
     register_opcode_with_ext(proc->opcodes[X86_OP_PUSH_RM1632], 0x66, 0xff, 6, "push", x86_read_instr_push_rm1632);
 
 
@@ -367,6 +371,12 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d
             goto find_instr;
         }
 
+        if (proc->opcodes[i].prefix == 0x00 && data[*pos] == proc->opcodes[i].opcode)
+        {
+            tmp = *pos + 1;
+            goto find_instr;
+        }
+
         continue;
 
  find_instr:
@@ -381,7 +391,7 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d
         else
         {
             *pos = old_pos;
-            printf("err while decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode);
+            printf("err while x86 decoding at 0x%08llx :: [0x%02hhx] 0x%02hhx\n", offset, proc->opcodes[i].prefix, proc->opcodes[i].opcode);
         }
         break;
 
@@ -456,7 +466,7 @@ void x86_print_instruction(const asm_x86_processor *proc, const exe_format *form
 
     /* Impression globale finale */
 
-    if (ASM_INSTRUCTION(instr)->opcode == DB_OPCODE)
+    if (ASM_INSTRUCTION(instr)->type == AIT_DB)
         snprintf(buffer, len, "db\t%s", opbuffer[0]);
 
     else
diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c
index 3aa9394..03b2e82 100644
--- a/src/format/elf/e_elf.c
+++ b/src/format/elf/e_elf.c
@@ -137,6 +137,18 @@ bin_part **get_elf_default_code_parts(const elf_format *format, size_t *count)
 
     if (format->sec_size > 0)
     {
+        if (find_elf_section(format, ".plt", &offset, &size, &voffset))
+        {
+            part = create_bin_part();
+
+            set_bin_part_name(part, ".plt");
+            set_bin_part_values(part, offset, size, voffset);
+
+            result = (bin_part **)realloc(result, ++(*count) * sizeof(bin_part *));
+            result[*count - 1] = part;
+
+        }
+
         if (find_elf_section(format, ".init", &offset, &size, &voffset))
         {
             part = create_bin_part();
diff --git a/src/format/elf/elf-int.h b/src/format/elf/elf-int.h
index f366c71..6e7bca1 100644
--- a/src/format/elf/elf-int.h
+++ b/src/format/elf/elf-int.h
@@ -84,6 +84,39 @@ typedef union _Elf_Phdr
 #define ELF_PHDR(fmt, hdr, fld) (fmt->is_32b ? hdr.header32.fld : hdr.header64.fld)
 
 
+/* Entrée de la table de relocalisation */
+
+typedef union _Elf_Rel
+{
+    Elf32_Rel rel32;                        /* Version 32 bits             */
+    Elf64_Rel rel64;                        /* Version 64 bits             */
+
+} Elf_Rel;
+
+#define ELF_SIZEOF_REL(fmt) (fmt->is_32b ? sizeof(Elf32_Rel) : sizeof(Elf64_Rel))
+
+#define ELF_REL(fmt, rl, fld) (fmt->is_32b ? rl.rel32.fld : rl.rel64.fld)
+
+#define ELF_REL_SYM(fmt, rl) (fmt->is_32b ? ELF32_R_SYM(rl.rel32.r_info) : ELF64_R_SYM(rl.rel64.r_info))
+#define ELF_REL_TYPE(fmt, rl) (fmt->is_32b ? ELF32_R_TYPE(rl.rel32.r_info) : ELF64_R_TYPE(rl.rel64.r_info))
+
+
+/* Information sur un symbole */
+
+typedef union _Elf_Sym
+{
+    Elf32_Sym sym32;                        /* Version 32 bits             */
+    Elf64_Sym sym64;                        /* Version 64 bits             */
+
+} Elf_Sym;
+
+#define ELF_SIZEOF_SYM(fmt) (fmt->is_32b ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym))
+
+#define ELF_SYM(fmt, sb, fld) (fmt->is_32b ? sb.sym32.fld : sb.sym64.fld)
+
+
+
+
 
 
 #endif  /* _FORMAT_ELF_ELF_INT_H */
diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c
index 729c154..8fa5690 100644
--- a/src/format/elf/symbol.c
+++ b/src/format/elf/symbol.c
@@ -26,9 +26,14 @@
 
 #include <malloc.h>
 #include <elf.h>
+#include <stdio.h>
 #include <string.h>
 
 
+#include "../../arch/processor.h" /* FIXME : remove me ! */
+#include "../../arch/instruction.h" /* FIXME : remove me ! */
+#include "../../arch/instruction-int.h" /* FIXME : remove me ! */
+
 
 #include "elf-int.h"
 #include "section.h"
@@ -37,6 +42,24 @@
 
 
 
+/* -------------------------- DETAIL DES SYMBOLES EXTERNES -------------------------- */
+
+
+/* Charge en mémoire la liste des symboles dynamiques. */
+bool load_elf_relocation_table(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *);
+
+/* Récupère les informations d'un symbole dynamique donné. */
+char *get_elf_dynamic_symbol_info(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *, const off_t *);
+
+/* Décode les instructions liées à la relocalisation. */
+asm_instr **decode_elf_relocations(elf_format *, size_t *);
+
+/* Déduit les adresses effectives des relocalisations. */
+void translate_elf_relocations(elf_format *, asm_instr **, size_t);
+
+
+
+
 /* Charge en mémoire la liste humaine des symboles (32 bits). */
 bool load_elf_symbol_table_32(elf_format *, const off_t *, const off_t *, const off_t *, const off_t *);
 
@@ -69,6 +92,16 @@ bool load_elf_symbols(elf_format *format)
     off_t str_size;                         /* Taille de section           */
 
 
+    off_t plt_start;                        /* Début de section            */
+    off_t plt_size;                         /* Taille de section           */
+    off_t dyn_start;                        /* Début de section            */
+    off_t dyn_size;                         /* Taille de section           */
+
+
+    asm_instr **instructions;               /* Instructions décodées       */
+    size_t count;                           /* Quantité d'instructions     */
+
+
     result = find_elf_section(format, ".symtab", &sym_start, &sym_size, NULL);
 
     result &= find_elf_section(format, ".strtab", &str_start, &str_size, NULL);
@@ -79,12 +112,46 @@ bool load_elf_symbols(elf_format *format)
 
 
 
-        result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_start);
+        result = load_elf_symbol_table_32(format, &sym_start, &sym_size, &str_start, &str_size);
 
 
 
     }
 
+
+
+
+
+
+
+    result = find_elf_section(format, ".rel.plt", &plt_start, &plt_size, NULL);
+
+    result &= find_elf_section(format, ".dynsym", &dyn_start, &dyn_size, NULL);
+
+    result &= find_elf_section(format, ".dynstr", &str_start, &str_size, NULL);
+
+
+
+    if (result)
+    {
+
+
+
+        result = load_elf_relocation_table(format, &plt_start, &plt_size, &dyn_start, &dyn_size, &str_start, &str_size);
+
+        if (result)
+        {
+            instructions = decode_elf_relocations(format, &count);
+
+            translate_elf_relocations(format, instructions, count);
+
+            /* TODO : free instructions */
+
+        }
+
+
+    }
+
     return result;
 
 }
@@ -96,11 +163,11 @@ bool load_elf_symbols(elf_format *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format     = description de l'exécutable à compléter.        *
-*                sym_start  = début de la zone à traiter.                     *
-*                sym_size   = taille de la zone à traiter.                    *
-*                str_start  = début de la zone de chaîne de caractères.       *
-*                str_size   = taille de la zone de chaînes de caractères.     *
+*  Paramètres  : format    = description de l'exécutable à compléter.         *
+*                sym_start = début de la zone à traiter.                      *
+*                sym_size  = taille de la zone à traiter.                     *
+*                str_start = début de la zone de chaîne de caractères.        *
+*                str_size  = taille de la zone de chaînes de caractères.      *
 *                                                                             *
 *  Description : Charge en mémoire la liste humaine des symboles (32 bits).   *
 *                                                                             *
@@ -149,11 +216,11 @@ bool load_elf_symbol_table_32(elf_format *format, const off_t *sym_start, const
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format     = description de l'exécutable à compléter.        *
-*                sym_start  = début de la zone à traiter.                     *
-*                sym_size   = taille de la zone à traiter.                    *
-*                str_start  = début de la zone de chaîne de caractères.       *
-*                str_size   = taille de la zone de chaînes de caractères.     *
+*  Paramètres  : format    = description de l'exécutable à compléter.         *
+*                sym_start = début de la zone à traiter.                      *
+*                sym_size  = taille de la zone à traiter.                     *
+*                str_start = début de la zone de chaîne de caractères.        *
+*                str_size  = taille de la zone de chaînes de caractères.      *
 *                                                                             *
 *  Description : Charge en mémoire la liste humaine des symboles (64 bits).   *
 *                                                                             *
@@ -241,3 +308,219 @@ void get_elf_symbol_comments(const elf_format *format, char ***comments, uint64_
     }
 
 }
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                            DETAIL DES SYMBOLES EXTERNES                            */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format    = description de l'exécutable à compléter.         *
+*                plt_start = début de la zone à traiter.                      *
+*                plt_size  = taille de la zone à traiter.                     *
+*                dyn_start = début des informations dynamiques associées.     *
+*                dyn_size  = taille de la zone associée.                      *
+*                str_start = début de la zone de chaîne de caractères.        *
+*                str_size  = taille de la zone de chaînes de caractères.      *
+*                                                                             *
+*  Description : Charge en mémoire la liste des symboles dynamiques.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool load_elf_relocation_table(elf_format *format, const off_t *plt_start, const off_t *plt_size, const off_t *dyn_start, const off_t *dyn_size, const off_t *str_start, const off_t *str_size)
+{
+    off_t iter;                             /* Boucle de parcours          */
+    Elf_Rel reloc;                          /* Infos de relocalisation     */
+    off_t index;                            /* Indice de la portion visée  */
+    char *name;                             /* Nom du symbole trouvé       */
+
+    for (iter = *plt_start; iter < (*plt_start + *plt_size); iter += ELF_SIZEOF_REL(format))
+    {
+        memcpy(&reloc, &EXE_FORMAT(format)->content[iter], ELF_SIZEOF_REL(format));
+
+        switch (format->header.e_machine)
+        {
+            case EM_386:
+                switch (ELF32_R_TYPE(ELF_REL_TYPE(format, reloc)))
+                {
+                    case R_386_JMP_SLOT:
+
+                        index = ELF_REL_SYM(format, reloc);
+                        name = get_elf_dynamic_symbol_info(format, dyn_start, dyn_size, &index, str_start, str_size);
+
+                        if (name != NULL)
+                        {
+                            format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+
+                            format->symbols[format->sym_count - 1].name = name;
+                            format->symbols[format->sym_count - 1].address = ELF_REL(format, reloc, r_offset);
+
+                        }
+
+                        break;
+
+                    default:
+                        printf("Relocation not supported (%lld) !\n", ELF_REL_TYPE(format, reloc));
+                        break;
+
+                }
+                break;
+
+            default:
+                printf("Machine not recognized !\n");
+                return false;
+                break;
+
+        }
+
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format    = description de l'exécutable à compléter.         *
+*                dyn_start = début des informations dynamiques associées.     *
+*                dyn_size  = taille de la zone associée.                      *
+*                index     = indice de l'entrée à venir lire.                 *
+*                str_start = début de la zone de chaîne de caractères.        *
+*                str_size  = taille de la zone de chaînes de caractères.      *
+*                                                                             *
+*  Description : Récupère les informations d'un symbole dynamique donné.      *
+*                                                                             *
+*  Retour      : Nom du symbole trouvé, ou NULL si erreur ou non adapté.      *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *get_elf_dynamic_symbol_info(elf_format *format, const off_t *dyn_start, const off_t *dyn_size, const off_t *index, const off_t *str_start, const off_t *str_size)
+{
+    off_t offset;                           /* Emplacement à venir lire    */
+    Elf_Sym symbol;                         /* Symbole aux infos visées    */
+
+    offset = *dyn_start + *index * ELF_SIZEOF_SYM(format);
+    if ((offset + ELF_SIZEOF_SYM(format)) > (*dyn_start + *dyn_size)) return NULL;
+
+    memcpy(&symbol, &EXE_FORMAT(format)->content[offset], ELF_SIZEOF_SYM(format));
+
+    if (ELF_SYM(format, symbol, st_name) >= *str_size) return NULL;
+
+    return (char *)&EXE_FORMAT(format)->content[*str_start + ELF_SYM(format, symbol, st_name)];
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à compléter.            *
+*                count  = nombre d'instructions lues. [OUT]                   *
+*                                                                             *
+*  Description : Décode les instructions liées à la relocalisation.           *
+*                                                                             *
+*  Retour      : Liste des instructions décodées ou NULL.                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+asm_instr **decode_elf_relocations(elf_format *format, size_t *count)
+{
+    asm_instr **result;                     /* Liste à renvoyer            */
+    off_t rel_start;                        /* Début de section            */
+    off_t rel_size;                         /* Taille de section           */
+    uint64_t rel_vaddress;                  /* Adresse virtuelle associée  */
+    off_t pos;                              /* Tête de lecture             */
+    uint64_t offset;                        /* Adresse virtuelle courante  */
+    asm_instr *instr;                       /* Instruction décodée         */
+
+    asm_processor *proc;    /* TODO : remove me ! */
+    proc = create_x86_processor();
+
+    result = NULL;
+    *count = 0;
+
+    if (find_elf_section(format, ".plt", &rel_start, &rel_size, &rel_vaddress))
+        for (pos = 0; pos < rel_size; )
+        {
+            offset = rel_vaddress + pos;
+
+            instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset);
+
+            result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *));
+            result[*count - 1] = instr;
+
+        }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format       = description de l'exécutable à compléter.      *
+*                instructions = listes des instructions à interpréter.        *
+*                count        = nombre d'instructions lues.                   *
+*                                                                             *
+*  Description : Déduit les adresses effectives des relocalisations.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void translate_elf_relocations(elf_format *format, asm_instr **instructions, size_t count)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    uint64_t address;                       /* Adresse virtuelle finale    */
+    size_t j;                               /* Boucle de parcours #2       */
+    size_t new_len;                         /* Taille du nouveau nom       */
+    char *new_name;                         /* Nom avec suffixe @plt       */
+
+    for (i = 0; (i + 2) < count; )
+    {
+        if (instructions[i]->type == AIT_JUMP
+            && instructions[i + 1]->type == AIT_PUSH
+            && instructions[i + 2]->type == AIT_JUMP)
+        {
+            if (get_imm_operand_value(instructions[i]->operands[0], AOS_64_BITS, &address))
+                for (j = 0; j < format->sym_count; j++)
+                    if (format->symbols[j].address == address)
+                    {
+                        new_len = strlen(format->symbols[j].name) + 4 + 1;
+                        new_name = calloc(new_len, sizeof(char));
+                        snprintf(new_name, new_len, "%s@plt", format->symbols[j].name);
+
+                        format->symbols = (elf_symbol *)realloc(format->symbols, ++format->sym_count * sizeof(elf_symbol));
+
+                        format->symbols[format->sym_count - 1].name = new_name;
+                        format->symbols[format->sym_count - 1].address = instructions[i]->vaddress;
+
+                    }
+
+            i += 3;
+
+        }
+        else i++;
+
+    }
+
+}
-- 
cgit v0.11.2-87-g4458