From cf648174b0ee4bbc9f53deb4d4d67a3e010f534b Mon Sep 17 00:00:00 2001 From: Hui Zhu Date: Mon, 10 Aug 2009 03:02:39 +0000 Subject: [PATCH] 2009-08-10 Hui Zhu Add AMD64 process record instruction set support. * i386-tdep.h (gdbarch_tdep): Add record_regmap for registers because the AMD64's registers order in GDB is not same with I386 instructions. Add i386_syscall_record to be the syscall function handle interface. (record_i386_regnum): Number for record_regmap. * i386-tdep.c (OT_QUAD): For 64 bits. (i386_record_s): Add rex_x, rex_b, rip_offset and popl_esp_hack for AMD64 instruction set. And regmap for record_regmap. (i386_record_lea_modrm_addr): Support AMD64 instruction set 64 bits lea. (i386_record_lea_modrm): Ditto. (i386_record_push): New function. Record the execution log of push. (I386_RECORD_ARCH_LIST_ADD_REG): New macro to record the register. (i386_process_record): Support AMD64 instruction set. * amd64-tdep.c (amd64_record_regmap): For record_regmap. (amd64_init_abi): Set amd64_record_regmap to record_regmap. --- gdb/ChangeLog | 25 + gdb/amd64-tdep.c | 12 + gdb/i386-tdep.c | 1447 +++++++++++++++++++++++++++++------------------------- gdb/i386-tdep.h | 35 ++ 4 files changed, 859 insertions(+), 660 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fdbbe83..95c6bdd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,28 @@ +2009-08-10 Hui Zhu + + Add AMD64 process record instruction set support. + + * i386-tdep.h (gdbarch_tdep): Add record_regmap for registers + because the AMD64's registers order in GDB is not same with + I386 instructions. + Add i386_syscall_record to be the syscall function handle + interface. + (record_i386_regnum): Number for record_regmap. + * i386-tdep.c (OT_QUAD): For 64 bits. + (i386_record_s): Add rex_x, rex_b, rip_offset and + popl_esp_hack for AMD64 instruction set. And regmap for + record_regmap. + (i386_record_lea_modrm_addr): Support AMD64 instruction set + 64 bits lea. + (i386_record_lea_modrm): Ditto. + (i386_record_push): New function. Record the execution log + of push. + (I386_RECORD_ARCH_LIST_ADD_REG): New macro to record the + register. + (i386_process_record): Support AMD64 instruction set. + * amd64-tdep.c (amd64_record_regmap): For record_regmap. + (amd64_init_abi): Set amd64_record_regmap to record_regmap. + 2009-08-08 Pedro Alves * bfd-target.c (struct target_bfd_data): New. diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 258496a..187b9ce 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1989,6 +1989,16 @@ amd64_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) return 1; } +static const int amd64_record_regmap[] = +{ + AMD64_RAX_REGNUM, AMD64_RCX_REGNUM, AMD64_RDX_REGNUM, AMD64_RBX_REGNUM, + AMD64_RSP_REGNUM, AMD64_RBP_REGNUM, AMD64_RSI_REGNUM, AMD64_RDI_REGNUM, + AMD64_R8_REGNUM, AMD64_R9_REGNUM, AMD64_R10_REGNUM, AMD64_R11_REGNUM, + AMD64_R12_REGNUM, AMD64_R13_REGNUM, AMD64_R14_REGNUM, AMD64_R15_REGNUM, + AMD64_RIP_REGNUM, AMD64_EFLAGS_REGNUM, AMD64_CS_REGNUM, AMD64_SS_REGNUM, + AMD64_DS_REGNUM, AMD64_ES_REGNUM, AMD64_FS_REGNUM, AMD64_GS_REGNUM +}; + void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -2051,6 +2061,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_num_pseudo_regs (gdbarch, 0); tdep->mm0_regnum = -1; + tdep->record_regmap = amd64_record_regmap; + set_gdbarch_dummy_id (gdbarch, amd64_dummy_id); frame_unwind_append_unwinder (gdbarch, &amd64_sigtramp_frame_unwind); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 2d73785..836172b 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -2847,6 +2847,7 @@ enum OT_BYTE = 0, OT_WORD, OT_LONG, + OT_QUAD, }; /* i386 arith/logic operations */ @@ -2864,6 +2865,7 @@ enum struct i386_record_s { + struct gdbarch *gdbarch; struct regcache *regcache; CORE_ADDR addr; int aflag; @@ -2872,6 +2874,11 @@ struct i386_record_s uint8_t modrm; uint8_t mod, reg, rm; int ot; + uint8_t rex_x; + uint8_t rex_b; + int rip_offset; + int popl_esp_hack; + const int *regmap; }; /* Parse "modrm" part in current memory address that irp->addr point to @@ -2880,7 +2887,7 @@ struct i386_record_s static int i386_record_modrm (struct i386_record_s *irp) { - struct gdbarch *gdbarch = get_regcache_arch (irp->regcache); + struct gdbarch *gdbarch = irp->gdbarch; if (target_read_memory (irp->addr, &irp->modrm, 1)) { @@ -2903,12 +2910,13 @@ i386_record_modrm (struct i386_record_s *irp) Return -1 if something wrong. */ static int -i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) +i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr) { - struct gdbarch *gdbarch = get_regcache_arch (irp->regcache); + struct gdbarch *gdbarch = irp->gdbarch; uint8_t tmpu8; - uint16_t tmpu16; - uint32_t tmpu32; + int16_t tmpi16; + int32_t tmpi32; + ULONGEST tmpulongest; *addr = 0; if (irp->aflag) @@ -2932,9 +2940,10 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) } irp->addr++; scale = (tmpu8 >> 6) & 3; - index = ((tmpu8 >> 3) & 7); + index = ((tmpu8 >> 3) & 7) | irp->rex_x; base = (tmpu8 & 7); } + base |= irp->rex_b; switch (irp->mod) { @@ -2942,7 +2951,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) if ((base & 7) == 5) { base = 0xff; - if (target_read_memory (irp->addr, (gdb_byte *) addr, 4)) + if (target_read_memory (irp->addr, (gdb_byte *) &tmpi32, 4)) { if (record_debug) printf_unfiltered (_("Process record: error reading " @@ -2951,6 +2960,9 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) return -1; } irp->addr += 4; + *addr = tmpi32; + if (irp->regmap[X86_RECORD_R8_REGNUM] && !havesib) + *addr += irp->addr + irp->rip_offset; } else { @@ -2970,7 +2982,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) *addr = (int8_t) tmpu8; break; case 2: - if (target_read_memory (irp->addr, (gdb_byte *) addr, 4)) + if (target_read_memory (irp->addr, (gdb_byte *) &tmpi32, 4)) { if (record_debug) printf_unfiltered (_("Process record: error reading memory " @@ -2978,21 +2990,34 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) paddress (gdbarch, irp->addr)); return -1; } + *addr = tmpi32; irp->addr += 4; break; } + tmpulongest = 0; if (base != 0xff) - { - regcache_raw_read (irp->regcache, base, (gdb_byte *) & tmpu32); - *addr += tmpu32; + { + if (base == 4 && irp->popl_esp_hack) + *addr += irp->popl_esp_hack; + regcache_raw_read_unsigned (irp->regcache, irp->regmap[base], + &tmpulongest); } + if (irp->aflag == 2) + { + *addr += tmpulongest; + } + else + *addr = (uint32_t) (tmpulongest + *addr); - /* XXX: index == 4 is always invalid */ if (havesib && (index != 4 || scale != 0)) { - regcache_raw_read (irp->regcache, index, (gdb_byte *) & tmpu32); - *addr += tmpu32 << scale; + regcache_raw_read_unsigned (irp->regcache, irp->regmap[index], + &tmpulongest); + if (irp->aflag == 2) + *addr += tmpulongest << scale; + else + *addr = (uint32_t) (*addr + (tmpulongest << scale)); } } else @@ -3004,7 +3029,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) if (irp->rm == 6) { if (target_read_memory - (irp->addr, (gdb_byte *) & tmpu16, 2)) + (irp->addr, (gdb_byte *) &tmpi16, 2)) { if (record_debug) printf_unfiltered (_("Process record: error reading " @@ -3013,7 +3038,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) return -1; } irp->addr += 2; - *addr = (int16_t) tmpu16; + *addr = tmpi16; irp->rm = 0; goto no_rm; } @@ -3035,7 +3060,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) *addr = (int8_t) tmpu8; break; case 2: - if (target_read_memory (irp->addr, (gdb_byte *) & tmpu16, 2)) + if (target_read_memory (irp->addr, (gdb_byte *) &tmpi16, 2)) { if (record_debug) printf_unfiltered (_("Process record: error reading memory " @@ -3044,63 +3069,75 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint32_t * addr) return -1; } irp->addr += 2; - *addr = (int16_t) tmpu16; + *addr = tmpi16; break; } switch (irp->rm) { case 0: - regcache_raw_read (irp->regcache, I386_EBX_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; - regcache_raw_read (irp->regcache, I386_ESI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBX_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_RESI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 1: - regcache_raw_read (irp->regcache, I386_EBX_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; - regcache_raw_read (irp->regcache, I386_EDI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBX_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REDI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 2: - regcache_raw_read (irp->regcache, I386_EBP_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; - regcache_raw_read (irp->regcache, I386_ESI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBP_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_RESI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 3: - regcache_raw_read (irp->regcache, I386_EBP_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; - regcache_raw_read (irp->regcache, I386_EDI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBP_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REDI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 4: - regcache_raw_read (irp->regcache, I386_ESI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_RESI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 5: - regcache_raw_read (irp->regcache, I386_EDI_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REDI_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 6: - regcache_raw_read (irp->regcache, I386_EBP_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBP_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; case 7: - regcache_raw_read (irp->regcache, I386_EBX_REGNUM, - (gdb_byte *) & tmpu32); - *addr += tmpu32; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_REBX_REGNUM], + &tmpulongest); + *addr = (uint32_t) (*addr + tmpulongest); break; } *addr &= 0xffff; @@ -3117,10 +3154,10 @@ no_rm: static int i386_record_lea_modrm (struct i386_record_s *irp) { - struct gdbarch *gdbarch = get_regcache_arch (irp->regcache); - uint32_t addr; + struct gdbarch *gdbarch = irp->gdbarch; + uint64_t addr; - if (irp->override) + if (irp->override >= 0) { if (record_debug) printf_unfiltered (_("Process record ignores the memory change " @@ -3139,10 +3176,33 @@ i386_record_lea_modrm (struct i386_record_s *irp) return 0; } +/* Record the push operation to "record_arch_list". + Return -1 if something wrong. */ + +static int +i386_record_push (struct i386_record_s *irp, int size) +{ + ULONGEST tmpulongest; + + if (record_arch_list_add_reg (irp->regcache, + irp->regmap[X86_RECORD_RESP_REGNUM])) + return -1; + regcache_raw_read_unsigned (irp->regcache, + irp->regmap[X86_RECORD_RESP_REGNUM], + &tmpulongest); + if (record_arch_list_add_mem ((CORE_ADDR) tmpulongest - size, size)) + return -1; + + return 0; +} + /* Parse the current instruction and record the values of the registers and memory that will be changed in current instruction to "record_arch_list". Return -1 if something wrong. */ +#define I386_RECORD_ARCH_LIST_ADD_REG(regnum) \ + record_arch_list_add_reg (ir.regcache, ir.regmap[(regnum)]) + int i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr) @@ -3151,14 +3211,22 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, uint8_t tmpu8; uint16_t tmpu16; uint32_t tmpu32; + ULONGEST tmpulongest; uint32_t opcode; struct i386_record_s ir; + int rex = 0; + uint8_t rex_w = -1; + uint8_t rex_r = 0; memset (&ir, 0, sizeof (struct i386_record_s)); ir.regcache = regcache; ir.addr = addr; ir.aflag = 1; ir.dflag = 1; + ir.override = -1; + ir.popl_esp_hack = 0; + ir.regmap = gdbarch_tdep (gdbarch)->record_regmap; + ir.gdbarch = gdbarch; if (record_debug > 1) fprintf_unfiltered (gdb_stdlog, "Process record: i386_process_record " @@ -3189,22 +3257,22 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, prefixes |= PREFIX_LOCK; break; case 0x2e: - ir.override = I386_CS_REGNUM; + ir.override = X86_RECORD_CS_REGNUM; break; case 0x36: - ir.override = I386_SS_REGNUM; + ir.override = X86_RECORD_SS_REGNUM; break; case 0x3e: - ir.override = I386_DS_REGNUM; + ir.override = X86_RECORD_DS_REGNUM; break; case 0x26: - ir.override = I386_ES_REGNUM; + ir.override = X86_RECORD_ES_REGNUM; break; case 0x64: - ir.override = I386_FS_REGNUM; + ir.override = X86_RECORD_FS_REGNUM; break; case 0x65: - ir.override = I386_GS_REGNUM; + ir.override = X86_RECORD_GS_REGNUM; break; case 0x66: prefixes |= PREFIX_DATA; @@ -3212,16 +3280,51 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, case 0x67: prefixes |= PREFIX_ADDR; break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + /* REX */ + rex = 1; + rex_w = (tmpu8 >> 3) & 1; + rex_r = (tmpu8 & 0x4) << 1; + ir.rex_x = (tmpu8 & 0x2) << 2; + ir.rex_b = (tmpu8 & 0x1) << 3; + } + break; default: goto out_prefixes; break; } } out_prefixes: - if (prefixes & PREFIX_DATA) - ir.dflag ^= 1; + if (ir.regmap[X86_RECORD_R8_REGNUM] && rex_w == 1) + { + ir.dflag = 2; + } + else + { + if (prefixes & PREFIX_DATA) + ir.dflag ^= 1; + } if (prefixes & PREFIX_ADDR) ir.aflag ^= 1; + else if (ir.regmap[X86_RECORD_R8_REGNUM]) + ir.aflag = 2; /* now check op code */ opcode = (uint32_t) tmpu8; @@ -3311,30 +3414,28 @@ reswitch: } else { - if (ir.ot == OT_BYTE) + ir.rm |= ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } break; /* OP Gv, Ev */ case 1: if (i386_record_modrm (&ir)) return -1; - if (ir.ot == OT_BYTE) + ir.reg |= rex_r; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); break; /* OP A, Iv */ case 2: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); break; } } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* GRP1 */ @@ -3354,17 +3455,17 @@ reswitch: if (ir.mod != 3) { + if (opcode == 0x83) + ir.rip_offset = 1; + else + ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot); if (i386_record_lea_modrm (&ir)) return -1; } else - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* inv */ @@ -3385,10 +3486,8 @@ reswitch: case 0x4d: case 0x4e: case 0x4f: - if (record_arch_list_add_reg (ir.regcache, opcode & 7)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (opcode & 7); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* GRP3 */ @@ -3401,28 +3500,17 @@ reswitch: if (i386_record_modrm (&ir)) return -1; + if (ir.mod != 3 && ir.reg == 0) + ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot); + switch (ir.reg) { /* test */ case 0: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* not */ case 2: - if (ir.mod != 3) - { - if (i386_record_lea_modrm (&ir)) - return -1; - } - else - { - if (ir.ot == OT_BYTE) - ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } - break; /* neg */ case 3: if (ir.mod != 3) @@ -3432,13 +3520,14 @@ reswitch: } else { - if (ir.ot == OT_BYTE) + ir.rm |= ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + /* neg */ + if (ir.reg == 3) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* mul */ case 4: @@ -3448,15 +3537,10 @@ reswitch: case 6: /* idiv */ case 7: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); if (ir.ot != OT_BYTE) - { - if (record_arch_list_add_reg (ir.regcache, I386_EDX_REGNUM)) - return -1; - } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; default: ir.addr -= 2; @@ -3470,10 +3554,6 @@ reswitch: case 0xfe: /* GRP5 */ case 0xff: - if ((opcode & 1) == 0) - ir.ot = OT_BYTE; - else - ir.ot = ir.dflag + OT_WORD; if (i386_record_modrm (&ir)) return -1; if (ir.reg >= 2 && opcode == 0xfe) @@ -3482,13 +3562,16 @@ reswitch: opcode = opcode << 8 | ir.modrm; goto no_support; } - switch (ir.reg) { /* inc */ case 0: /* dec */ case 1: + if ((opcode & 1) == 0) + ir.ot = OT_BYTE; + else + ir.ot = ir.dflag + OT_WORD; if (ir.mod != 3) { if (i386_record_lea_modrm (&ir)) @@ -3496,42 +3579,40 @@ reswitch: } else { - if (ir.ot == OT_BYTE) + ir.rm |= ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* call */ case 2: - /* push */ - case 6: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 1)), (1 << (ir.dflag + 1)))) + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* lcall */ case 3: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_CS_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 2)), (1 << (ir.dflag + 2)))) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM); + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* jmp */ case 4: /* ljmp */ case 5: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + /* push */ + case 6: + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; break; default: ir.addr -= 2; @@ -3546,22 +3627,18 @@ reswitch: case 0x85: case 0xa8: case 0xa9: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* CWDE/CBW */ case 0x98: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); break; /* CDQ/CWD */ case 0x99: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EDX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM); break; /* imul */ @@ -3571,12 +3648,15 @@ reswitch: ir.ot = ir.dflag + OT_WORD; if (i386_record_modrm (&ir)) return -1; - if (ir.ot == OT_BYTE) + if (opcode == 0x69) + ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot); + else if (opcode == 0x6b) + ir.rip_offset = 1; + ir.reg |= rex_r; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* xadd */ @@ -3588,28 +3668,25 @@ reswitch: ir.ot = ir.dflag + OT_WORD; if (i386_record_modrm (&ir)) return -1; + ir.reg |= rex_r; if (ir.mod == 3) { - if (ir.ot == OT_BYTE) + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; - if (ir.ot == OT_BYTE) + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } else { if (i386_record_lea_modrm (&ir)) return -1; - if (ir.ot == OT_BYTE) + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* cmpxchg */ @@ -3623,22 +3700,19 @@ reswitch: return -1; if (ir.mod == 3) { - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (ir.ot == OT_BYTE) + ir.reg |= rex_r; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); } else { - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); if (i386_record_lea_modrm (&ir)) return -1; } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* cmpxchg8b */ @@ -3651,14 +3725,11 @@ reswitch: opcode = opcode << 8 | ir.modrm; goto no_support; } - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EDX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM); if (i386_record_lea_modrm (&ir)) return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* push */ @@ -3672,6 +3743,12 @@ reswitch: case 0x57: case 0x68: case 0x6a: + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; + break; + /* push es */ case 0x06: /* push cs */ @@ -3680,16 +3757,36 @@ reswitch: case 0x16: /* push ds */ case 0x1e: + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; + break; + /* push fs */ case 0x0fa0: /* push gs */ case 0x0fa8: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 2; + goto no_support; + } + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 1)), (1 << (ir.dflag + 1)))) + break; + + /* pusha */ + case 0x60: + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + if (i386_record_push (&ir, 1 << (ir.dflag + 4))) return -1; break; @@ -3702,113 +3799,104 @@ reswitch: case 0x5d: case 0x5e: case 0x5f: - ir.ot = ir.dflag + OT_WORD; - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (ir.ot == OT_BYTE) - opcode &= 0x3; - if (record_arch_list_add_reg (ir.regcache, opcode & 0x7)) - return -1; - break; - - /* pusha */ - case 0x60: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 4)), (1 << (ir.dflag + 4)))) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG ((opcode & 0x7) | ir.rex_b); break; /* popa */ case 0x61: - for (tmpu8 = I386_EAX_REGNUM; tmpu8 <= I386_EDI_REGNUM; tmpu8++) - { - if (record_arch_list_add_reg (ir.regcache, tmpu8)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; } + for (tmpu8 = X86_RECORD_REAX_REGNUM; tmpu8 <= X86_RECORD_REDI_REGNUM; + tmpu8++) + I386_RECORD_ARCH_LIST_ADD_REG (tmpu8); break; /* pop */ case 0x8f: - ir.ot = ir.dflag + OT_WORD; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + ir.ot = ir.dflag ? OT_QUAD : OT_WORD; + else + ir.ot = ir.dflag + OT_WORD; if (i386_record_modrm (&ir)) return -1; if (ir.mod == 3) - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); else { + ir.popl_esp_hack = 1 << ir.ot; if (i386_record_lea_modrm (&ir)) return -1; } - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); break; /* enter */ case 0xc8: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EBP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 1)), (1 << (ir.dflag + 1)))) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM); + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) return -1; break; /* leave */ case 0xc9: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EBP_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REBP_REGNUM); break; /* pop es */ case 0x07: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_ES_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_ES_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* pop ss */ case 0x17: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_SS_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_SS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* pop ds */ case 0x1f: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_DS_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_DS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* pop fs */ case 0x0fa1: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_FS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_FS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* pop gs */ case 0x0fa9: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_GS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_GS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* mov */ @@ -3826,19 +3914,21 @@ reswitch: if (ir.mod != 3) { + if (opcode == 0xc6 || opcode == 0xc7) + ir.rip_offset = (ir.ot > OT_LONG) ? 4 : (1 << ir.ot); if (i386_record_lea_modrm (&ir)) return -1; } else { - if (ir.ot == OT_BYTE) + if (opcode == 0xc6 || opcode == 0xc7) + ir.rm |= ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; break; + /* mov */ case 0x8a: case 0x8b: @@ -3846,40 +3936,55 @@ reswitch: ir.ot = OT_BYTE; else ir.ot = ir.dflag + OT_WORD; - if (i386_record_modrm (&ir)) return -1; - - if (ir.ot == OT_BYTE) + ir.reg |= rex_r; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); + break; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) + /* mov seg */ + case 0x8c: + if (i386_record_modrm (&ir)) return -1; + if (ir.reg > 5) + { + ir.addr -= 2; + opcode = opcode << 8 | ir.modrm; + goto no_support; + } + + if (ir.mod == 3) + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); + else + { + ir.ot = OT_WORD; + if (i386_record_lea_modrm (&ir)) + return -1; + } break; /* mov seg */ case 0x8e: if (i386_record_modrm (&ir)) return -1; - switch (ir.reg) { case 0: - tmpu8 = I386_ES_REGNUM; + tmpu8 = X86_RECORD_ES_REGNUM; break; case 2: - tmpu8 = I386_SS_REGNUM; + tmpu8 = X86_RECORD_SS_REGNUM; break; case 3: - tmpu8 = I386_DS_REGNUM; + tmpu8 = X86_RECORD_DS_REGNUM; break; case 4: - tmpu8 = I386_FS_REGNUM; + tmpu8 = X86_RECORD_FS_REGNUM; break; case 5: - tmpu8 = I386_GS_REGNUM; + tmpu8 = X86_RECORD_GS_REGNUM; break; default: ir.addr -= 2; @@ -3887,38 +3992,8 @@ reswitch: goto no_support; break; } - if (record_arch_list_add_reg (ir.regcache, tmpu8)) - return -1; - - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; - break; - - /* mov seg */ - case 0x8c: - if (i386_record_modrm (&ir)) - return -1; - if (ir.reg > 5) - { - ir.addr -= 2; - opcode = opcode << 8 | ir.modrm; - goto no_support; - } - - if (ir.mod == 3) - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } - else - { - ir.ot = OT_WORD; - if (i386_record_lea_modrm (&ir)) - return -1; - } - - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (tmpu8); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* movzbS */ @@ -3931,8 +4006,7 @@ reswitch: case 0x0fbf: if (i386_record_modrm (&ir)) return -1; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg | rex_r); break; /* lea */ @@ -3945,12 +4019,11 @@ reswitch: opcode = opcode << 8 | ir.modrm; goto no_support; } - ir.ot = ir.dflag; - if (ir.ot == OT_BYTE) + ir.reg |= rex_r; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); break; /* mov EAX */ @@ -3958,62 +4031,68 @@ reswitch: case 0xa1: /* xlat */ case 0xd7: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); break; /* mov EAX */ case 0xa2: case 0xa3: - { - uint32_t addr; - - if (ir.override) - { - if (record_debug) - printf_unfiltered (_("Process record ignores the memory change " - "of instruction at address %s because " - "it can't get the value of the segment " - "register.\n"), - paddress (gdbarch, ir.addr)); - } - else - { - if ((opcode & 1) == 0) - ir.ot = OT_BYTE; - else - ir.ot = ir.dflag + OT_WORD; - if (ir.aflag) - { - if (target_read_memory - (ir.addr, (gdb_byte *) & addr, 4)) - { - if (record_debug) - printf_unfiltered (_("Process record: error reading " - "memory at addr %s len = 4.\n"), - paddress (gdbarch, ir.addr)); - return -1; - } - ir.addr += 4; - } - else - { - if (target_read_memory - (ir.addr, (gdb_byte *) & tmpu16, 4)) - { - if (record_debug) - printf_unfiltered (_("Process record: error reading " - "memory at addr %s len = 4.\n"), - paddress (gdbarch, ir.addr)); - return -1; - } - ir.addr += 2; - addr = tmpu16; - } - if (record_arch_list_add_mem (addr, 1 << ir.ot)) - return -1; - } - } + if (ir.override >= 0) + { + if (record_debug) + printf_unfiltered (_("Process record ignores the memory change " + "of instruction at address 0x%s because " + "it can't get the value of the segment " + "register.\n"), + paddress (gdbarch, ir.addr)); + } + else + { + if ((opcode & 1) == 0) + ir.ot = OT_BYTE; + else + ir.ot = ir.dflag + OT_WORD; + if (ir.aflag == 2) + { + if (target_read_memory (ir.addr, (gdb_byte *) &addr, 8)) + { + if (record_debug) + printf_unfiltered (_("Process record: error reading " + "memory at addr 0x%s len = 8.\n"), + paddress (gdbarch, ir.addr)); + return -1; + } + ir.addr += 8; + } + else if (ir.aflag) + { + if (target_read_memory (ir.addr, (gdb_byte *) &tmpu32, 4)) + { + if (record_debug) + printf_unfiltered (_("Process record: error reading " + "memory at addr 0x%s len = 4.\n"), + paddress (gdbarch, ir.addr)); + return -1; + } + ir.addr += 4; + addr = tmpu32; + } + else + { + if (target_read_memory (ir.addr, (gdb_byte *) &tmpu16, 2)) + { + if (record_debug) + printf_unfiltered (_("Process record: error reading " + "memory at addr 0x%s len = 2.\n"), + paddress (gdbarch, ir.addr)); + return -1; + } + ir.addr += 2; + addr = tmpu16; + } + if (record_arch_list_add_mem (addr, 1 << ir.ot)) + return -1; + } break; /* mov R, Ib */ @@ -4025,8 +4104,9 @@ reswitch: case 0xb5: case 0xb6: case 0xb7: - if (record_arch_list_add_reg (ir.regcache, (opcode & 0x7) & 0x3)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG ((ir.regmap[X86_RECORD_R8_REGNUM]) + ? ((opcode & 0x7) | ir.rex_b) + : ((opcode & 0x7) & 0x3)); break; /* mov R, Iv */ @@ -4038,8 +4118,7 @@ reswitch: case 0xbd: case 0xbe: case 0xbf: - if (record_arch_list_add_reg (ir.regcache, opcode & 0x7)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG ((opcode & 0x7) | ir.rex_b); break; /* xchg R, EAX */ @@ -4050,10 +4129,8 @@ reswitch: case 0x95: case 0x96: case 0x97: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, opcode & 0x7)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (opcode & 0x7); break; /* xchg Ev, Gv */ @@ -4063,33 +4140,35 @@ reswitch: ir.ot = OT_BYTE; else ir.ot = ir.dflag + OT_WORD; - if (i386_record_modrm (&ir)) return -1; - if (ir.mod == 3) { - if (ir.ot == OT_BYTE) - ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + ir.rm != ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) + ir.rm &= 0x3; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } else { if (i386_record_lea_modrm (&ir)) return -1; } - - if (ir.ot == OT_BYTE) + ir.reg |= rex_r; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); break; /* les Gv */ case 0xc4: /* lds Gv */ case 0xc5: + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } /* lss Gv */ case 0x0fb2: /* lfs Gv */ @@ -4107,35 +4186,32 @@ reswitch: opcode = opcode << 8 | ir.modrm; goto no_support; } - switch (opcode) { /* les Gv */ case 0xc4: - tmpu8 = I386_ES_REGNUM; + tmpu8 = X86_RECORD_ES_REGNUM; break; /* lds Gv */ case 0xc5: - tmpu8 = I386_DS_REGNUM; + tmpu8 = X86_RECORD_DS_REGNUM; break; /* lss Gv */ case 0x0fb2: - tmpu8 = I386_SS_REGNUM; + tmpu8 = X86_RECORD_SS_REGNUM; break; /* lfs Gv */ case 0x0fb4: - tmpu8 = I386_FS_REGNUM; + tmpu8 = X86_RECORD_FS_REGNUM; break; /* lgs Gv */ case 0x0fb5: - tmpu8 = I386_GS_REGNUM; + tmpu8 = X86_RECORD_GS_REGNUM; break; } - if (record_arch_list_add_reg (ir.regcache, tmpu8)) - return -1; - - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (tmpu8); + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg | rex_r); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* shifts */ @@ -4149,10 +4225,8 @@ reswitch: ir.ot = OT_BYTE; else ir.ot = ir.dflag + OT_WORD; - if (i386_record_modrm (&ir)) return -1; - if (ir.mod != 3 && (opcode == 0xd2 || opcode == 0xd3)) { if (i386_record_lea_modrm (&ir)) @@ -4160,14 +4234,12 @@ reswitch: } else { - if (ir.ot == OT_BYTE) + ir.rm |= ir.rex_b; + if (ir.ot == OT_BYTE && !ir.regmap[X86_RECORD_R8_REGNUM]) ir.rm &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm); } - - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; case 0x0fa4: @@ -4204,9 +4276,9 @@ reswitch: if (ir.mod != 3) { /* memory */ - uint32_t addr; + uint64_t tmpu64; - if (i386_record_lea_modrm_addr (&ir, &addr)) + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) return -1; switch (ir.reg) { @@ -4266,16 +4338,16 @@ reswitch: switch (ir.reg >> 4) { case 0: - if (record_arch_list_add_mem (addr, 4)) + if (record_arch_list_add_mem (tmpu64, 4)) return -1; break; case 2: - if (record_arch_list_add_mem (addr, 8)) + if (record_arch_list_add_mem (tmpu64, 8)) return -1; break; case 3: default: - if (record_arch_list_add_mem (addr, 2)) + if (record_arch_list_add_mem (tmpu64, 2)) return -1; break; } @@ -4285,16 +4357,16 @@ reswitch: { case 0: case 1: - if (record_arch_list_add_mem (addr, 4)) + if (record_arch_list_add_mem (tmpu64, 4)) return -1; break; case 2: - if (record_arch_list_add_mem (addr, 8)) + if (record_arch_list_add_mem (tmpu64, 8)) return -1; break; case 3: default: - if (record_arch_list_add_mem (addr, 2)) + if (record_arch_list_add_mem (tmpu64, 2)) return -1; break; } @@ -4311,43 +4383,43 @@ reswitch: case 0x0e: if (ir.dflag) { - if (record_arch_list_add_mem (addr, 28)) + if (record_arch_list_add_mem (tmpu64, 28)) return -1; } else { - if (record_arch_list_add_mem (addr, 14)) + if (record_arch_list_add_mem (tmpu64, 14)) return -1; } break; case 0x0f: case 0x2f: - if (record_arch_list_add_mem (addr, 2)) + if (record_arch_list_add_mem (tmpu64, 2)) return -1; break; case 0x1f: case 0x3e: - if (record_arch_list_add_mem (addr, 10)) + if (record_arch_list_add_mem (tmpu64, 10)) return -1; break; case 0x2e: if (ir.dflag) { - if (record_arch_list_add_mem (addr, 28)) + if (record_arch_list_add_mem (tmpu64, 28)) return -1; - addr += 28; + tmpu64 += 28; } else { - if (record_arch_list_add_mem (addr, 14)) + if (record_arch_list_add_mem (tmpu64, 14)) return -1; - addr += 14; + tmpu64 += 14; } - if (record_arch_list_add_mem (addr, 80)) + if (record_arch_list_add_mem (tmpu64, 80)) return -1; break; case 0x3f: - if (record_arch_list_add_mem (addr, 8)) + if (record_arch_list_add_mem (tmpu64, 8)) return -1; break; default: @@ -4369,123 +4441,88 @@ reswitch: /* insS */ case 0x6c: case 0x6d: - { - uint32_t addr; - - if ((opcode & 1) == 0) - ir.ot = OT_BYTE; - else - ir.ot = ir.dflag + OT_WORD; - if (opcode == 0xa4 || opcode == 0xa5) - { - if (record_arch_list_add_reg (ir.regcache, I386_ESI_REGNUM)) - return -1; - } - if (record_arch_list_add_reg (ir.regcache, I386_EDI_REGNUM)) - return -1; - - regcache_raw_read (ir.regcache, I386_EDI_REGNUM, - (gdb_byte *) & addr); - if (!ir.aflag) - { - addr &= 0xffff; - /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */ - if (record_debug) - printf_unfiltered (_("Process record ignores the memory change " - "of instruction at address %s because " - "it can't get the value of the segment " - "register.\n"), - paddress (gdbarch, ir.addr)); - } - - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) - { - uint32_t count; - - regcache_raw_read (ir.regcache, I386_ECX_REGNUM, - (gdb_byte *) & count); - if (!ir.aflag) - count &= 0xffff; - - regcache_raw_read (ir.regcache, I386_EFLAGS_REGNUM, - (gdb_byte *) & tmpu32); - if ((tmpu32 >> 10) & 0x1) - addr -= (count - 1) * (1 << ir.ot); - - if (ir.aflag) - { - if (record_arch_list_add_mem (addr, count * (1 << ir.ot))) - return -1; - } + if ((opcode & 1) == 0) + ir.ot = OT_BYTE; + else + ir.ot = ir.dflag + OT_WORD; + regcache_raw_read_unsigned (ir.regcache, + ir.regmap[X86_RECORD_REDI_REGNUM], + &tmpulongest); + if (!ir.aflag) + { + tmpulongest &= 0xffff; + /* addr += ((uint32_t) read_register (I386_ES_REGNUM)) << 4; */ + if (record_debug) + printf_unfiltered (_("Process record ignores the memory change " + "of instruction at address 0x%s because " + "it can't get the value of the segment " + "register.\n"), + paddress (gdbarch, ir.addr)); + } + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) + { + ULONGEST count, eflags; + regcache_raw_read_unsigned (ir.regcache, + ir.regmap[X86_RECORD_REDI_REGNUM], + &count); + if (!ir.aflag) + count &= 0xffff; + regcache_raw_read_unsigned (ir.regcache, + ir.regmap[X86_RECORD_EFLAGS_REGNUM], + &eflags); + if ((eflags >> 10) & 0x1) + tmpulongest -= (count - 1) * (1 << ir.ot); + if (record_arch_list_add_mem (tmpulongest, count * (1 << ir.ot))) + return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + } + else + { + if (record_arch_list_add_mem (tmpulongest, 1 << ir.ot)) + return -1; + } + if (opcode == 0xa4 || opcode == 0xa5) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - } - else - { - if (ir.aflag) - { - if (record_arch_list_add_mem (addr, 1 << ir.ot)) - return -1; - } - } - } + /* cmpsS */ + case 0xa6: + case 0xa7: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM); + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* lodsS */ case 0xac: case 0xad: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_ESI_REGNUM)) - return -1; - if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) - { - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - } - break; - - /* outsS */ - case 0x6e: - case 0x6f: - if (record_arch_list_add_reg (ir.regcache, I386_ESI_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) - { - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* scasS */ case 0xae: case 0xaf: - if (record_arch_list_add_reg (ir.regcache, I386_EDI_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDI_REGNUM); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) - { - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; - /* cmpsS */ - case 0xa6: - case 0xa7: - if (record_arch_list_add_reg (ir.regcache, I386_EDI_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_ESI_REGNUM)) - return -1; + /* outsS */ + case 0x6e: + case 0x6f: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESI_REGNUM); if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) - { - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* port I/O */ @@ -4493,8 +4530,8 @@ reswitch: case 0xe5: case 0xec: case 0xed: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); break; case 0xe6: @@ -4508,48 +4545,39 @@ reswitch: case 0xc2: /* ret */ case 0xc3: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + /* lret im */ case 0xca: /* lret */ case 0xcb: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_CS_REGNUM)) - return -1; - break; - /* iret */ case 0xcf: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_CS_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* call im */ case 0xe8: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 1)), (1 << (ir.dflag + 1)))) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; break; /* lcall im */ case 0x9a: - if (record_arch_list_add_reg (ir.regcache, I386_CS_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 2)), (1 << (ir.dflag + 2)))) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_CS_REGNUM); + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; break; /* jmp im */ @@ -4611,14 +4639,13 @@ reswitch: case 0x0f9d: case 0x0f9e: case 0x0f9f: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); ir.ot = OT_BYTE; if (i386_record_modrm (&ir)) return -1; if (ir.mod == 3) - { - if (record_arch_list_add_reg (ir.regcache, ir.rm & 0x3)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rex_b ? (ir.rm | ir.rex_b) + : (ir.rm & 0x3)); else { if (i386_record_lea_modrm (&ir)) @@ -4645,34 +4672,35 @@ reswitch: case 0x0f4f: if (i386_record_modrm (&ir)) return -1; + ir.reg |= rex_r; if (ir.dflag == OT_BYTE) ir.reg &= 0x3; - if (record_arch_list_add_reg (ir.regcache, ir.reg & 0x3)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg); break; /* flags */ /* pushf */ case 0x9c: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - regcache_raw_read (ir.regcache, I386_ESP_REGNUM, - (gdb_byte *) & tmpu32); - if (record_arch_list_add_mem - ((CORE_ADDR) tmpu32 - (1 << (ir.dflag + 1)), (1 << (ir.dflag + 1)))) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + if (ir.regmap[X86_RECORD_R8_REGNUM] && ir.dflag) + ir.dflag = 2; + if (i386_record_push (&ir, 1 << (ir.dflag + 1))) + return -1; break; /* popf */ case 0x9d: - if (record_arch_list_add_reg (ir.regcache, I386_ESP_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RESP_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* sahf */ case 0x9e: + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } /* cmc */ case 0xf5: /* clc */ @@ -4683,66 +4711,95 @@ reswitch: case 0xfc: /* std */ case 0xfd: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* lahf */ case 0x9f: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); break; /* bit operations */ /* bt/bts/btr/btc Gv, im */ case 0x0fba: - /* bts */ - case 0x0fab: - /* btr */ - case 0x0fb3: - /* btc */ - case 0x0fbb: ir.ot = ir.dflag + OT_WORD; if (i386_record_modrm (&ir)) return -1; if (ir.reg < 4) { - ir.addr -= 3; + ir.addr -= 2; opcode = opcode << 8 | ir.modrm; goto no_support; } - ir.reg -= 4; - if (ir.reg != 0) + if (ir.reg != 4) { - if (ir.mod != 3) - { - if (i386_record_lea_modrm (&ir)) - return -1; - } + if (ir.mod == 3) + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); else { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) + if (i386_record_lea_modrm (&ir)) return -1; } } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* bt Gv, Ev */ case 0x0fa3: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + + /* bts */ + case 0x0fab: + /* btr */ + case 0x0fb3: + /* btc */ + case 0x0fbb: + ir.ot = ir.dflag + OT_WORD; + if (i386_record_modrm (&ir)) + return -1; + if (ir.mod == 3) + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); + else + { + uint64_t tmpu64; + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) + return -1; + regcache_raw_read_unsigned (ir.regcache, + ir.regmap[ir.reg | rex_r], + &tmpulongest); + switch (ir.dflag) + { + case 0: + tmpu64 += ((int16_t) tmpulongest >> 4) << 4; + break; + case 1: + tmpu64 += ((int32_t) tmpulongest >> 5) << 5; + break; + case 2: + tmpu64 += ((int64_t) tmpulongest >> 6) << 6; + break; + } + if (record_arch_list_add_mem (tmpu64, 1 << ir.ot)) + return -1; + if (i386_record_lea_modrm (&ir)) + return -1; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* bsf */ case 0x0fbc: /* bsr */ case 0x0fbd: - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg | rex_r); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* bcd */ @@ -4758,10 +4815,13 @@ reswitch: case 0xd4: /* aad */ case 0xd5: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* misc */ @@ -4853,16 +4913,18 @@ reswitch: case 0x0fcd: case 0x0fce: case 0x0fcf: - if (record_arch_list_add_reg (ir.regcache, opcode & 7)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG ((opcode & 7) | ir.rex_b); break; /* salc */ case 0xd6: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 1; + goto no_support; + } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* loopnz */ @@ -4873,8 +4935,8 @@ reswitch: case 0xe2: /* jecxz */ case 0xe3: - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* wrmsr */ @@ -4905,6 +4967,11 @@ reswitch: case 0x0f34: { int ret; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + ir.addr -= 2; + goto no_support; + } if (gdbarch_tdep (gdbarch)->i386_sysenter_record == NULL) { printf_unfiltered (_("Process record doesn't support " @@ -4926,16 +4993,37 @@ reswitch: goto no_support; break; + /* syscall */ + case 0x0f05: + { + int ret; + if (gdbarch_tdep (gdbarch)->i386_syscall_record == NULL) + { + printf_unfiltered (_("Process record doesn't support " + "instruction syscall.\n")); + ir.addr -= 2; + goto no_support; + } + ret = gdbarch_tdep (gdbarch)->i386_syscall_record (ir.regcache); + if (ret) + return ret; + } + break; + + /* sysret */ + case 0x0f07: + printf_unfiltered (_("Process record doesn't support " + "instruction sysret.\n")); + ir.addr -= 2; + goto no_support; + break; + /* cpuid */ case 0x0fa2: - if (record_arch_list_add_reg (ir.regcache, I386_EAX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_ECX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EDX_REGNUM)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EBX_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REAX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_RECX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REDX_REGNUM); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REBX_REGNUM); break; /* hlt */ @@ -4956,10 +5044,7 @@ reswitch: /* str */ case 1: if (ir.mod == 3) - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); else { ir.ot = OT_WORD; @@ -4976,8 +5061,7 @@ reswitch: case 4: /* verw */ case 5: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; default: ir.addr -= 3; @@ -4995,7 +5079,7 @@ reswitch: /* sgdt */ case 0: { - uint32_t addr; + uint64_t tmpu64; if (ir.mod == 3) { @@ -5003,8 +5087,7 @@ reswitch: opcode = opcode << 8 | ir.modrm; goto no_support; } - - if (ir.override) + if (ir.override >= 0) { if (record_debug) printf_unfiltered (_("Process record ignores the memory " @@ -5016,13 +5099,21 @@ reswitch: } else { - if (i386_record_lea_modrm_addr (&ir, &addr)) + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) return -1; - if (record_arch_list_add_mem (addr, 2)) - return -1; - addr += 2; - if (record_arch_list_add_mem (addr, 4)) + if (record_arch_list_add_mem (tmpu64, 2)) return -1; + tmpu64 += 2; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + if (record_arch_list_add_mem (tmpu64, 8)) + return -1; + } + else + { + if (record_arch_list_add_mem (tmpu64, 4)) + return -1; + } } } break; @@ -5036,8 +5127,7 @@ reswitch: break; /* mwait */ case 1: - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; default: ir.addr -= 3; @@ -5049,7 +5139,7 @@ reswitch: else { /* sidt */ - if (ir.override) + if (ir.override >= 0) { if (record_debug) printf_unfiltered (_("Process record ignores the memory " @@ -5061,15 +5151,23 @@ reswitch: } else { - uint32_t addr; + uint64_t tmpu64; - if (i386_record_lea_modrm_addr (&ir, &addr)) + if (i386_record_lea_modrm_addr (&ir, &tmpu64)) return -1; - if (record_arch_list_add_mem (addr, 2)) + if (record_arch_list_add_mem (tmpu64, 2)) return -1; addr += 2; - if (record_arch_list_add_mem (addr, 4)) - return -1; + if (ir.regmap[X86_RECORD_R8_REGNUM]) + { + if (record_arch_list_add_mem (tmpu64, 8)) + return -1; + } + else + { + if (record_arch_list_add_mem (tmpu64, 4)) + return -1; + } } } break; @@ -5077,9 +5175,6 @@ reswitch: case 2: /* lidt */ case 3: - /* invlpg */ - case 7: - default: if (ir.mod == 3) { ir.addr -= 3; @@ -5091,7 +5186,7 @@ reswitch: case 4: if (ir.mod == 3) { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) + if (record_arch_list_add_reg (ir.regcache, ir.rm | ir.rex_b)) return -1; } else @@ -5100,9 +5195,32 @@ reswitch: if (i386_record_lea_modrm (&ir)) return -1; } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* lmsw */ case 6: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + /* invlpg */ + case 7: + if (ir.mod == 3) + { + if (ir.rm == 0 && ir.regmap[X86_RECORD_R8_REGNUM]) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_GS_REGNUM); + else + { + ir.addr -= 3; + opcode = opcode << 8 | ir.modrm; + goto no_support; + } + } + else + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); + break; + default: + ir.addr -= 3; + opcode = opcode << 8 | ir.modrm; + goto no_support; break; } break; @@ -5115,21 +5233,21 @@ reswitch: /* arpl */ case 0x63: - ir.ot = ir.dflag ? OT_LONG : OT_WORD; if (i386_record_modrm (&ir)) return -1; - if (ir.mod != 3) - { - if (i386_record_lea_modrm (&ir)) - return -1; - } + if (ir.mod == 3 || ir.regmap[X86_RECORD_R8_REGNUM]) + { + I386_RECORD_ARCH_LIST_ADD_REG (ir.regmap[X86_RECORD_R8_REGNUM] + ? (ir.reg | rex_r) : ir.rm); + } else - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + { + ir.ot = ir.dflag ? OT_LONG : OT_WORD; + if (i386_record_lea_modrm (&ir)) + return -1; + } + if (!ir.regmap[X86_RECORD_R8_REGNUM]) + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* lar */ @@ -5138,13 +5256,19 @@ reswitch: case 0x0f03: if (i386_record_modrm (&ir)) return -1; - if (record_arch_list_add_reg (ir.regcache, ir.reg)) - return -1; - if (record_arch_list_add_reg (ir.regcache, I386_EFLAGS_REGNUM)) - return -1; + I386_RECORD_ARCH_LIST_ADD_REG (ir.reg | rex_r); + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; case 0x0f18: + if (i386_record_modrm (&ir)) + return -1; + if (ir.mod == 3 && ir.reg == 3) + { + ir.addr -= 3; + opcode = opcode << 8 | ir.modrm; + goto no_support; + } break; /* nop (multi byte) */ @@ -5165,7 +5289,7 @@ reswitch: return -1; if ((ir.modrm & 0xc0) != 0xc0) { - ir.addr -= 2; + ir.addr -= 3; opcode = opcode << 8 | ir.modrm; goto no_support; } @@ -5177,16 +5301,12 @@ reswitch: case 4: case 8: if (opcode & 2) - { - } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); else - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); break; default: - ir.addr -= 2; + ir.addr -= 3; opcode = opcode << 8 | ir.modrm; goto no_support; break; @@ -5202,22 +5322,19 @@ reswitch: if ((ir.modrm & 0xc0) != 0xc0 || ir.reg == 4 || ir.reg == 5 || ir.reg >= 8) { - ir.addr -= 2; + ir.addr -= 3; opcode = opcode << 8 | ir.modrm; goto no_support; } if (opcode & 2) - { - } + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); else - { - if (record_arch_list_add_reg (ir.regcache, ir.rm)) - return -1; - } + I386_RECORD_ARCH_LIST_ADD_REG (ir.rm | ir.rex_b); break; /* clts */ case 0x0f06: + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_EFLAGS_REGNUM); break; /* MMX/SSE/SSE2/PNI support */ @@ -5232,9 +5349,8 @@ reswitch: break; } -/* In the future, Maybe still need to deal with need_dasm */ - if (record_arch_list_add_reg (ir.regcache, I386_EIP_REGNUM)) - return -1; + /* In the future, maybe still need to deal with need_dasm. */ + I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REIP_REGNUM); if (record_arch_list_add_end ()) return -1; @@ -5247,6 +5363,15 @@ no_support: return -1; } +static const int i386_record_regmap[] = +{ + I386_EAX_REGNUM, I386_ECX_REGNUM, I386_EDX_REGNUM, I386_EBX_REGNUM, + I386_ESP_REGNUM, I386_EBP_REGNUM, I386_ESI_REGNUM, I386_EDI_REGNUM, + 0, 0, 0, 0, 0, 0, 0, 0, + I386_EIP_REGNUM, I386_EFLAGS_REGNUM, I386_CS_REGNUM, I386_SS_REGNUM, + I386_DS_REGNUM, I386_ES_REGNUM, I386_FS_REGNUM, I386_GS_REGNUM +}; + static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -5307,6 +5432,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->sc_pc_offset = -1; tdep->sc_sp_offset = -1; + tdep->record_regmap = i386_record_regmap; + /* The format used for `long double' on almost all i386 targets is the i387 extended floating-point format. In fact, of all targets in the GCC 2.95 tree, only OSF/1 does it different, and insists diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index b3fef43..b236532 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -111,10 +111,15 @@ struct gdbarch_tdep struct type *i387_ext_type; /* Process record/replay target. */ + /* The map for registers because the AMD64's registers order + in GDB is not same as I386 instructions. */ + const int *record_regmap; /* Parse intx80 args. */ int (*i386_intx80_record) (struct regcache *regcache); /* Parse sysenter args. */ int (*i386_sysenter_record) (struct regcache *regcache); + /* Parse syscall args. */ + int (*i386_syscall_record) (struct regcache *regcache); }; /* Floating-point registers. */ @@ -151,6 +156,36 @@ enum i386_regnum I386_ST0_REGNUM /* %st(0) */ }; +/* Register numbers of RECORD_REGMAP. */ + +enum record_i386_regnum +{ + X86_RECORD_REAX_REGNUM, + X86_RECORD_RECX_REGNUM, + X86_RECORD_REDX_REGNUM, + X86_RECORD_REBX_REGNUM, + X86_RECORD_RESP_REGNUM, + X86_RECORD_REBP_REGNUM, + X86_RECORD_RESI_REGNUM, + X86_RECORD_REDI_REGNUM, + X86_RECORD_R8_REGNUM, + X86_RECORD_R9_REGNUM, + X86_RECORD_R10_REGNUM, + X86_RECORD_R11_REGNUM, + X86_RECORD_R12_REGNUM, + X86_RECORD_R13_REGNUM, + X86_RECORD_R14_REGNUM, + X86_RECORD_R15_REGNUM, + X86_RECORD_REIP_REGNUM, + X86_RECORD_EFLAGS_REGNUM, + X86_RECORD_CS_REGNUM, + X86_RECORD_SS_REGNUM, + X86_RECORD_DS_REGNUM, + X86_RECORD_ES_REGNUM, + X86_RECORD_FS_REGNUM, + X86_RECORD_GS_REGNUM, +}; + #define I386_NUM_GREGS 16 #define I386_NUM_FREGS 16 #define I386_NUM_XREGS 9 -- 2.7.4