diff options
-rw-r--r-- | gdb/ChangeLog | 28 | ||||
-rw-r--r-- | gdb/x86-64-linux-nat.c | 8 | ||||
-rw-r--r-- | gdb/x86-64-linux-tdep.c | 234 | ||||
-rw-r--r-- | gdb/x86-64-linux-tdep.h | 6 | ||||
-rw-r--r-- | gdb/x86-64-tdep.h | 72 |
5 files changed, 289 insertions, 59 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2939178..1fe2dc5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,33 @@ 2003-08-21 Andrew Cagney <cagney@redhat.com> + * x86-64-tdep.h (enum x86_64_regnums): Replace #define of + X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM, + X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM, + X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM, + X86_64_XMM1_REGNUM. + * x86-64-linux-tdep.h (x86_64_linux_greg_offset): Declare. + (x86_64_linux_supply_gregset): Add "sizeof_gregs" param. + (x86_64_linux_fill_gregset): Add "sizeof_gregs" param. + * x86-64-linux-tdep.c: Include "gdb_assert.h" and + "i386-linux-tdep.h". + (enum user_regs): Replace user reg #defines, add USER_ORIG_RAX, + USER_FS_BASE and USER_GS_BASE. + (struct regnum_map, struct regnum_to_user): Define. + (x86_64_linux_greg_offset): New function. + (user_to_gdb_regmap): Delete. + (x86_64_linux_supply_gregset, x86_64_linux_fill_gregset): Use + x86_64_linux_greg_offset. + (x86_64_core_sniffer): New function + (x86_64_core_fns): Set the sniffer to x86_64_core_sniffer. + (fetch_core_registers): Pass "core_reg_size" to the supply + functions. + * x86-64-linux-nat.c (GETREGS_SUPPLIES): Delete macro. + (fetch_inferior_registers): Use x86_64_linux_greg_offset. + (store_inferior_registers): Ditto. + * Makefile.in (x86-64-linux-tdep.o): Update dependencies. + +2003-08-21 Andrew Cagney <cagney@redhat.com> + * i386-tdep.h (i386_regnums): Replace I386_EAX_REGNUM, I386_EDX_REGNUM, I386_ESP_REGNUM, I386_EBP_REGNUM, I386_EIP_REGNUM, I386_EFLAGS_REGNUM, I386_ST0_REGNUM. diff --git a/gdb/x86-64-linux-nat.c b/gdb/x86-64-linux-nat.c index 66a1b68..f589463 100644 --- a/gdb/x86-64-linux-nat.c +++ b/gdb/x86-64-linux-nat.c @@ -54,12 +54,8 @@ /* Which ptrace request retrieves which registers? These apply to the corresponding SET requests as well. */ -#define GETREGS_SUPPLIES(regno) \ - (0 <= (regno) && (regno) < X86_64_NUM_GREGS) - #define GETFPREGS_SUPPLIES(regno) \ (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM) - /* Transfering the general-purpose registers between GDB, inferiors and core files. */ @@ -191,7 +187,7 @@ fetch_inferior_registers (int regno) return; } - if (GETREGS_SUPPLIES (regno)) + if (x86_64_linux_greg_offset (regno) >= 0) { fetch_regs (tid); return; @@ -228,7 +224,7 @@ store_inferior_registers (int regno) return; } - if (GETREGS_SUPPLIES (regno)) + if (x86_64_linux_greg_offset (regno) >= 0) { store_regs (tid, regno); return; diff --git a/gdb/x86-64-linux-tdep.c b/gdb/x86-64-linux-tdep.c index 7aab1d4..d01f542 100644 --- a/gdb/x86-64-linux-tdep.c +++ b/gdb/x86-64-linux-tdep.c @@ -28,50 +28,173 @@ #include "osabi.h" #include "gdb_string.h" +#include "gdb_assert.h" #include "x86-64-tdep.h" #include "x86-64-linux-tdep.h" +#include "i386-linux-tdep.h" /* For I386_LINUX_ORIG_EAX_REGNUM. */ /* Register indexes to 'struct user' come from <sys/reg.h>. */ -#define USER_R15 0 -#define USER_R14 1 -#define USER_R13 2 -#define USER_R12 3 -#define USER_RBP 4 -#define USER_RBX 5 -#define USER_R11 6 -#define USER_R10 7 -#define USER_R9 8 -#define USER_R8 9 -#define USER_RAX 10 -#define USER_RCX 11 -#define USER_RDX 12 -#define USER_RSI 13 -#define USER_RDI 14 -#define USER_RIP 16 -#define USER_CS 17 -#define USER_EFLAGS 18 -#define USER_RSP 19 -#define USER_SS 20 -#define USER_DS 23 -#define USER_ES 24 -#define USER_FS 25 -#define USER_GS 26 - -/* Mapping between the general-purpose registers in `struct user' - format and GDB's register array layout. */ - -static int user_to_gdb_regmap[] = +enum user_regs { - USER_RAX, USER_RBX, USER_RCX, USER_RDX, - USER_RSI, USER_RDI, USER_RBP, USER_RSP, - USER_R8, USER_R9, USER_R10, USER_R11, - USER_R12, USER_R13, USER_R14, USER_R15, - USER_RIP, USER_EFLAGS, USER_CS, USER_SS, - USER_DS, USER_ES, USER_FS, USER_GS + USER_R15, + USER_R14, + USER_R13, + USER_R12, + USER_RBP, + USER_RBX, + USER_R11, + USER_R10, + USER_R9, + USER_R8, + USER_RAX, + USER_RCX, + USER_RDX, + USER_RSI, + USER_RDI, + USER_ORIG_RAX, + USER_RIP, + USER_CS, + USER_EFLAGS, + USER_RSP, + USER_SS, + USER_FS_BASE, + USER_GS_BASE, + USER_DS, + USER_ES, + USER_FS, + USER_GS, + USER_MAX }; +/* Map from GDB's i386/x86-64 REGNUM indexed general-purpose registers + to a `struct user' array of registers.. */ + +struct regnum_map +{ + int regnum; + int user; +}; + +struct regnum_to_user +{ + long nr; + const struct regnum_map *map; +}; + +long +x86_64_linux_greg_offset (int regnum) +{ + const static struct regnum_map i386_regnum_map[] = + { + { I386_EAX_REGNUM, USER_RAX }, + { I386_ECX_REGNUM, USER_RCX }, + { I386_EDX_REGNUM, USER_RDX }, + { I386_EBX_REGNUM, USER_RBX }, + { I386_ESP_REGNUM, USER_RSP }, + { I386_EBP_REGNUM, USER_RBP }, + { I386_ESI_REGNUM, USER_RSI }, + { I386_EDI_REGNUM, USER_RDI }, + { I386_EIP_REGNUM, USER_RIP }, + { I386_EFLAGS_REGNUM, USER_EFLAGS }, + { I386_CS_REGNUM, USER_CS }, + { I386_SS_REGNUM, USER_SS }, + { I386_DS_REGNUM, USER_DS }, + { I386_ES_REGNUM, USER_ES }, + { I386_FS_REGNUM, USER_FS }, + { I386_GS_REGNUM, USER_GS }, + { I386_ST0_REGNUM, -1 }, + { I386_ST1_REGNUM, -1 }, + { I386_ST2_REGNUM, -1 }, + { I386_ST3_REGNUM, -1 }, + { I386_ST4_REGNUM, -1 }, + { I386_ST5_REGNUM, -1 }, + { I386_ST6_REGNUM, -1 }, + { I386_ST7_REGNUM, -1 }, + { I386_FCTRL_REGNUM, -1 }, + { I386_FSTAT_REGNUM, -1 }, + { I386_FTAG_REGNUM, -1 }, + { I386_FISEG_REGNUM, -1 }, + { I386_FIOFF_REGNUM, -1 }, + { I386_FOSEG_REGNUM, -1 }, + { I386_FOOFF_REGNUM, -1 }, + { I386_FOP_REGNUM, -1 }, + { I386_XMM0_REGNUM, -1 }, + { I386_XMM1_REGNUM, -1 }, + { I386_XMM2_REGNUM, -1 }, + { I386_XMM3_REGNUM, -1 }, + { I386_XMM4_REGNUM, -1 }, + { I386_XMM5_REGNUM, -1 }, + { I386_XMM6_REGNUM, -1 }, + { I386_XMM7_REGNUM, -1 }, + { I386_MXCSR_REGNUM, -1 }, + { I386_LINUX_ORIG_EAX_REGNUM, USER_ORIG_RAX }, + }; + const static struct regnum_to_user i386_regnum_to_user = + { + ARRAY_SIZE (i386_regnum_map), i386_regnum_map + }; + const static struct regnum_map x86_64_regnum_map[] = + { + { X86_64_RAX_REGNUM, USER_RAX }, + { X86_64_RBX_REGNUM, USER_RBX }, + { X86_64_RCX_REGNUM, USER_RCX }, + { X86_64_RDX_REGNUM, USER_RDX }, + { X86_64_RSI_REGNUM, USER_RSI }, + { X86_64_RDI_REGNUM, USER_RDI }, + { X86_64_RBP_REGNUM, USER_RBP }, + { X86_64_RSP_REGNUM, USER_RSP }, + { X86_64_R8_REGNUM, USER_R8 }, + { X86_64_R9_REGNUM, USER_R9 }, + { X86_64_R10_REGNUM, USER_R10 }, + { X86_64_R11_REGNUM, USER_R11 }, + { X86_64_R12_REGNUM, USER_R12 }, + { X86_64_R13_REGNUM, USER_R13 }, + { X86_64_R14_REGNUM, USER_R14 }, + { X86_64_R15_REGNUM, USER_R15 }, + { X86_64_RIP_REGNUM, USER_RIP }, + { X86_64_EFLAGS_REGNUM, USER_EFLAGS }, + /* { X86_64_CS_REGNUM, USER_CS }, */ + /* { X86_64_SS_REGNUM, USER_SS }, */ + { X86_64_DS_REGNUM, USER_DS }, + { X86_64_ES_REGNUM, USER_ES }, + { X86_64_FS_REGNUM, USER_FS }, + { X86_64_GS_REGNUM, USER_GS }, + }; + const static struct regnum_to_user x86_64_regnum_to_user = + { + ARRAY_SIZE (x86_64_regnum_map), x86_64_regnum_map + }; + const struct regnum_to_user *regnum_to_user; + + gdb_assert (TARGET_ARCHITECTURE->arch == bfd_arch_i386); + switch (TARGET_ARCHITECTURE->mach) + { + case bfd_mach_i386_i386: + case bfd_mach_i386_i386_intel_syntax: + regnum_to_user = &i386_regnum_to_user; + break; + case bfd_mach_x86_64: + case bfd_mach_x86_64_intel_syntax: + regnum_to_user = &x86_64_regnum_to_user; + break; + case bfd_mach_i386_i8086: + /* Better suggestion? */ + return -1; + default: + internal_error (__FILE__, __LINE__, "bad_switch"); + } + if (regnum < 0) + return USER_MAX * 8; + if (regnum >= regnum_to_user->nr) + return -1; + gdb_assert (regnum_to_user->map[regnum].regnum == regnum); + if (regnum_to_user->map[regnum].user < 0) + return -1; + return regnum_to_user->map[regnum].user * 8; +} + /* Fill GDB's register array with the general-purpose register values in *GREGSETP. */ @@ -79,9 +202,15 @@ void x86_64_linux_supply_gregset (char *regp) { int i; + char buf[MAX_REGISTER_SIZE]; + int bad = 0; - for (i = 0; i < X86_64_NUM_GREGS; i++) - supply_register (i, regp + (user_to_gdb_regmap[i] * 8)); + for (i = 0; i < NUM_REGS; i++) + { + long offset = x86_64_linux_greg_offset (i); + if (offset >= 0) + supply_register (i, regp + offset); + } } /* Fill register REGNO (if it is a general-purpose register) in @@ -93,9 +222,20 @@ x86_64_linux_fill_gregset (char *regp, int regno) { int i; - for (i = 0; i < X86_64_NUM_GREGS; i++) + for (i = 0; i < NUM_REGS; i++) if (regno == -1 || regno == i) - regcache_collect (i, regp + (user_to_gdb_regmap[i] * 8)); + { + long offset = x86_64_linux_greg_offset (i); + if (offset >= 0) + { + char buf[MAX_REGISTER_SIZE]; + memset (buf, 0, sizeof buf); + /* Assume little endian - LHS of buffer is the correct + place to put the collected bytes. */ + regcache_collect (i, buf); + memcpy (regp + offset, buf, 8); + } + } } /* The register sets used in GNU/Linux ELF core-dumps are identical to @@ -111,7 +251,7 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, switch (which) { case 0: /* Integer registers. */ - if (core_reg_size != 216) + if (x86_64_linux_greg_offset (-1) > core_reg_size) warning ("Wrong size register set in core file."); else x86_64_linux_supply_gregset (core_reg_sect); @@ -132,11 +272,23 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, } } +static int +x86_64_core_sniffer (struct core_fns *our_fns, bfd *abfd) +{ + int result; + + result = ((bfd_get_flavour (abfd) == our_fns -> core_flavour) + && bfd_get_arch (abfd) == bfd_arch_i386 + && (bfd_get_mach (abfd) == bfd_mach_x86_64 + || bfd_get_mach (abfd) == bfd_mach_x86_64_intel_syntax)); + return (result); +} + static struct core_fns x86_64_core_fns = { bfd_target_elf_flavour, /* core_flavour */ default_check_format, /* check_format */ - default_core_sniffer, /* core_sniffer */ + x86_64_core_sniffer, /* core_sniffer */ fetch_core_registers, /* core_read_registers */ NULL /* next */ }; diff --git a/gdb/x86-64-linux-tdep.h b/gdb/x86-64-linux-tdep.h index a135cfa..c8324c8 100644 --- a/gdb/x86-64-linux-tdep.h +++ b/gdb/x86-64-linux-tdep.h @@ -36,4 +36,10 @@ void x86_64_linux_supply_gregset (char *regp); void x86_64_linux_fill_gregset (char *regp, int regno); +/* Given a GDB REGNUM, return the byte offset in the target's GREGs + buffer, or -1 if there is no corresponding GREGSET / FPREGSET + entry. Given a -ve REGNUM, returns the GREG's upper bound. */ + +extern long x86_64_linux_greg_offset (int regnum); + #endif /* x86-64-linux-tdep.h */ diff --git a/gdb/x86-64-tdep.h b/gdb/x86-64-tdep.h index 608219c..4e013f8 100644 --- a/gdb/x86-64-tdep.h +++ b/gdb/x86-64-tdep.h @@ -30,18 +30,66 @@ struct frame_info; #include "i386-tdep.h" -/* Register numbers of various important registers. */ - -#define X86_64_RAX_REGNUM 0 /* %rax */ -#define X86_64_RDX_REGNUM 3 /* %rdx */ -#define X86_64_RDI_REGNUM 5 /* %rdi */ -#define X86_64_RBP_REGNUM 6 /* %rbp */ -#define X86_64_RSP_REGNUM 7 /* %rsp */ -#define X86_64_RIP_REGNUM 16 /* %rip */ -#define X86_64_EFLAGS_REGNUM 17 /* %eflags */ -#define X86_64_ST0_REGNUM 22 /* %st0 */ -#define X86_64_XMM0_REGNUM 38 /* %xmm0 */ -#define X86_64_XMM1_REGNUM 39 /* %xmm1 */ +/* Register numbers of x86-64 registers. */ + +enum x86_64_regnums +{ + X86_64_RAX_REGNUM, + X86_64_RBX_REGNUM, + X86_64_RCX_REGNUM, + X86_64_RDX_REGNUM, + X86_64_RSI_REGNUM, + X86_64_RDI_REGNUM, + X86_64_RBP_REGNUM, + X86_64_RSP_REGNUM, + X86_64_R8_REGNUM, + X86_64_R9_REGNUM, + X86_64_R10_REGNUM, + X86_64_R11_REGNUM, + X86_64_R12_REGNUM, + X86_64_R13_REGNUM, + X86_64_R14_REGNUM, + X86_64_R15_REGNUM, + X86_64_RIP_REGNUM, + X86_64_EFLAGS_REGNUM, + X86_64_DS_REGNUM, + X86_64_ES_REGNUM, + X86_64_FS_REGNUM, + X86_64_GS_REGNUM, + X86_64_ST0_REGNUM, + X86_64_ST1_REGNUM, + X86_64_ST2_REGNUM, + X86_64_ST3_REGNUM, + X86_64_ST4_REGNUM, + X86_64_ST5_REGNUM, + X86_64_ST6_REGNUM, + X86_64_ST7_REGNUM, + X86_64_FCTRL_REGNUM, + X86_64_FSTAT_REGNUM, + X86_64_FTAG_REGNUM, + X86_64_FISEG_REGNUM, + X86_64_FIOFF_REGNUM, + X86_64_FOSEG_REGNUM, + X86_64_FOOFF_REGNUM, + X86_64_FOP_REGNUM, + X86_64_XMM0_REGNUM, + X86_64_XMM1_REGNUM, + X86_64_XMM2_REGNUM, + X86_64_XMM3_REGNUM, + X86_64_XMM4_REGNUM, + X86_64_XMM5_REGNUM, + X86_64_XMM6_REGNUM, + X86_64_XMM7_REGNUM, + X86_64_XMM8_REGNUM, + X86_64_XMM9_REGNUM, + X86_64_XMM10_REGNUM, + X86_64_XMM11_REGNUM, + X86_64_XMM12_REGNUM, + X86_64_XMM13_REGNUM, + X86_64_XMM14_REGNUM, + X86_64_XMM15_REGNUM, + X86_64_MXCSR_REGNUM +}; /* Number of general purpose registers. */ #define X86_64_NUM_GREGS 22 |