instruction_length(): Extended to support some new Microsoft binaries.
authorlace <>
Sun, 25 Dec 2005 06:23:09 +0000 (06:23 +0000)
committerlace <>
Sun, 25 Dec 2005 06:23:09 +0000 (06:23 +0000)
instruction_length(): Improved error messages of unsupported opcodes.

src/libcaptive/ldr/loader.c

index 48fe811..51865ba 100644 (file)
@@ -352,9 +352,23 @@ err_g_free_ModuleObject:
        g_return_val_if_reached(FALSE);
 }
 
+static void instruction_fail(const guint8 *instr_base,gint offset_last,const gchar *location)
+{
+char instr_buf[4*3+1],*s;
+
+       g_return_if_fail(offset_last<=(gint)((sizeof(instr_buf)-1)/3));
+
+       s=instr_buf;
+       while (offset_last-->=0)
+               s+=sprintf(s," %02X",*instr_base++);
+       g_error("instruction_length(): Unhandled at %s:%s",location,instr_buf);
+       /* NOTREACHED */
+}
 
 static gsize instruction_length(const guint8 *instr)
 {
+#define INSTRUCTION_FAIL(offset_last) instruction_fail(instr,(offset_last),G_STRLOC)
+
        if ((instr[0] & 0xF8)==0x50)    /* push %regular-register */
                return 1;
        if ((instr[0] & 0xF8)==0x58)    /* pop  %regular-register */
@@ -378,7 +392,7 @@ static gsize instruction_length(const guint8 *instr)
                                        return 1+1+4+1; /* 80 3D immediate-quad-indirect byte */
                                case 0x7C:      /* cmpb $byte,#immediate(%reg,1) */
                                        return 1+1+1+1+1;       /* 80 7C address-mode immediate byte */
-                               default: g_assert_not_reached();
+                               default: INSTRUCTION_FAIL(1);
                                }
                case 0x83:
                        switch (instr[1]) {
@@ -388,7 +402,7 @@ static gsize instruction_length(const guint8 *instr)
                                        return 1+1+4+1; /* 83 3D immediate-quad-indirect byte */
                                case 0x7C:      /* cmpl $byte,#immediate(%reg,1) */
                                        return 1+1+1+1+1;       /* 80 7C address-mode immediate byte */
-                               default: g_assert_not_reached();
+                               default: INSTRUCTION_FAIL(1);
                                }
                case 0x8A:      /* mov ??,?? */
                case 0x8B:      /* mov Gb,Eb */
@@ -401,13 +415,17 @@ static gsize instruction_length(const guint8 *instr)
                                case 0x4C:      /* mov #offset(%reg,#mult),%reg */
                                case 0x54:      /* mov #offset(%reg,#mult),%reg */
                                        return 1+1+1+1; /* 8B 44 address-mode offset */
-                               default: g_assert_not_reached();
+                               case 0xC0:      /* mov %eax,%eax */
+                                       return 2;
+                               case 0xFF:      /* mov %edi,%edi */
+                                       return 2;
+                               default: INSTRUCTION_FAIL(1);
                                }
                case 0x8D:      /* lea Gb,M */
                        switch (instr[1]) {
                                case 0x44:      /* mov #offset(%reg,%reg,#mult),%reg */
                                        return 4;       /* 8B 44 address-mode offset */
-                               default: g_assert_not_reached();
+                               default: INSTRUCTION_FAIL(1);
                                }
                case 0x8F:      /* lea Gb,M */
                        switch (instr[1]) {
@@ -415,9 +433,9 @@ static gsize instruction_length(const guint8 *instr)
                                        switch (instr[2]) {
                                                case 0x24:      /* popl (%esp,1) */
                                                        return 3;
-                                               default: g_assert_not_reached();
+                                               default: INSTRUCTION_FAIL(2);
                                                }
-                               default: g_assert_not_reached();
+                               default: INSTRUCTION_FAIL(1);
                                }
                case 0x9C:      /* pushf */
                        return 1;
@@ -439,11 +457,13 @@ static gsize instruction_length(const guint8 *instr)
                        return 1;
                case 0xFF:      /* inc/dec Ev */
                        return 2;
-               default: g_assert_not_reached();
+               default: INSTRUCTION_FAIL(0);
                }
        g_assert_not_reached(); /* TODO:fill the table */
        /* NOTREACHED */
        return 0;
+
+#undef INSTRUCTION_FAIL
 }