[RFA] x86-64 segment registers handling

Michal Ludvig
2002-03-26T17:26:48Z

[-- Attachment #1: Type: text/plain, Size: 1327 bytes --]

Hi all,
this patch synces gdb with recent ABI changes in x86-64 kernel, which
added segment registers to user_regs_struct in corefile and ptrace()
call. Because it was hard to find all places which could depend on this
change I also did a cleanup. I joined most of registers information to
one structure at the beginning of x86-64-tdep.c to make it more readable
and maintainable and changed some "anonymous constants" (numbers) to
derivatives of #defines.
Can I commit?

Index: ChangeLog
* x86-64-tdep.h (X86_64_NUM_REGS)
(X86_64_NUM_GREGS): Delete #defines
(x86_64_num_regs)
(x86_64_num_gregs): Added extern variables.
* x86-64-linux-nat.c (x86_64_regmap): Swapped
RBX <> RDX, added DS, ES, FD, GS
(x86_64_linux_dr_get_status), (supply_gregset),
(fill_gregset): Changed X86_64_NUM_GREGS to
x86_64_num_gregs
* x86-64-tdep.c (x86_64_register_raw_size_table): Delete
(x86_64_register_info_table): Add
(X86_64_NUM_REGS, X86_64_NUM_GREGS): Add
(x86_64_register_raw_size),
(x86_64_register_virtual_type),
(x86_64_register_name),
(_initialize_x86_64_tdep): Changed to reflect new
general x86_64_register_info_table.
(i386_gdbarch_init): gdbarch_register_bytes is now set
dynamicaly during initialization.

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* +420 2 9654 5373 * http://www.suse.cz

[-- Attachment #2: x8664-05.diff --]
[-- Type: text/plain, Size: 14259 bytes --]

Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 x86-64-tdep.c
*** x86-64-tdep.c 2002/03/25 07:59:16 1.11
--- x86-64-tdep.c 2002/03/26 16:56:52
***************
*** 35,75 ****

/* Register numbers of various important registers. */
#define RAX_REGNUM 0
! #define RDX_REGNUM 1
#define RDI_REGNUM 5
#define EFLAGS_REGNUM 17
#define XMM1_REGNUM 35

/* x86_64_register_raw_size_table[i] is the number of bytes of storage in
GDB's register array occupied by register i. */
! int x86_64_register_raw_size_table[X86_64_NUM_REGS] = {
! 8, 8, 8, 8,
! 8, 8, 8, 8,
! 8, 8, 8, 8,
! 8, 8, 8, 8,
! 8, 4,
! 10, 10, 10, 10,
! 10, 10, 10, 10,
! 4, 4, 4, 4,
! 4, 4, 4, 4,
! 16, 16, 16, 16,
! 16, 16, 16, 16,
! 16, 16, 16, 16,
! 16, 16, 16, 16,
! 4
};

/* Number of bytes of storage in the actual machine representation for
register REGNO. */
int
x86_64_register_raw_size (int regno)
{
! return x86_64_register_raw_size_table[regno];
}

/* x86_64_register_byte_table[i] is the offset into the register file of the
start of register number i. We initialize this from
! x86_64_register_raw_size_table. */
int x86_64_register_byte_table[X86_64_NUM_REGS];

/* Index within `registers' of the first byte of the space for register REGNO. */
--- 35,132 ----

/* Register numbers of various important registers. */
#define RAX_REGNUM 0
! #define RDX_REGNUM 3
#define RDI_REGNUM 5
#define EFLAGS_REGNUM 17
#define XMM1_REGNUM 35

+ struct register_info {
+ int size;
+ char *name;
+ struct type **type;
+ };
+
/* x86_64_register_raw_size_table[i] is the number of bytes of storage in
GDB's register array occupied by register i. */
! static struct register_info x86_64_register_info_table[] = {
! { 8, "rax", &builtin_type_int64 },
! { 8, "rbx", &builtin_type_int64 },
! { 8, "rcx", &builtin_type_int64 },
! { 8, "rdx", &builtin_type_int64 },
! { 8, "rsi", &builtin_type_int64 },
! { 8, "rdi", &builtin_type_int64 },
! { 8, "rbp", &builtin_type_void_func_ptr },
! { 8, "rsp", &builtin_type_void_func_ptr },
! { 8, "r8", &builtin_type_int64 },
! { 8, "r9", &builtin_type_int64 },
! { 8, "r10", &builtin_type_int64 },
! { 8, "r11", &builtin_type_int64 },
! { 8, "r12", &builtin_type_int64 },
! { 8, "r13", &builtin_type_int64 },
! { 8, "r14", &builtin_type_int64 },
! { 8, "r15", &builtin_type_int64 },
! { 8, "rip", &builtin_type_void_func_ptr },
! { 4, "eflags", &builtin_type_int32 },
! { 4, "ds", &builtin_type_int32 },
! { 4, "es", &builtin_type_int32 },
! { 4, "fs", &builtin_type_int32 },
! { 4, "gs", &builtin_type_int32 },
! { 10, "st0", &builtin_type_i387_ext },
! { 10, "st1", &builtin_type_i387_ext },
! { 10, "st2", &builtin_type_i387_ext },
! { 10, "st3", &builtin_type_i387_ext },
! { 10, "st4", &builtin_type_i387_ext },
! { 10, "st5", &builtin_type_i387_ext },
! { 10, "st6", &builtin_type_i387_ext },
! { 10, "st7", &builtin_type_i387_ext },
! { 4, "fctrl", &builtin_type_int32 },
! { 4, "fstat", &builtin_type_int32 },
! { 4, "ftag", &builtin_type_int32 },
! { 4, "fiseg", &builtin_type_int32 },
! { 4, "fioff", &builtin_type_int32 },
! { 4, "foseg", &builtin_type_int32 },
! { 4, "fooff", &builtin_type_int32 },
! { 4, "fop", &builtin_type_int32 },
! { 16, "xmm0", &builtin_type_v4sf },
! { 16, "xmm1", &builtin_type_v4sf },
! { 16, "xmm2", &builtin_type_v4sf },
! { 16, "xmm3", &builtin_type_v4sf },
! { 16, "xmm4", &builtin_type_v4sf },
! { 16, "xmm5", &builtin_type_v4sf },
! { 16, "xmm6", &builtin_type_v4sf },
! { 16, "xmm7", &builtin_type_v4sf },
! { 16, "xmm8", &builtin_type_v4sf },
! { 16, "xmm9", &builtin_type_v4sf },
! { 16, "xmm10", &builtin_type_v4sf },
! { 16, "xmm11", &builtin_type_v4sf },
! { 16, "xmm12", &builtin_type_v4sf },
! { 16, "xmm13", &builtin_type_v4sf },
! { 16, "xmm14", &builtin_type_v4sf },
! { 16, "xmm15", &builtin_type_v4sf },
! { 4, "mxcsr", &builtin_type_int32 }
};

+ /* Number of all registers */
+ #define X86_64_NUM_REGS (sizeof (x86_64_register_info_table) / \
+ sizeof (x86_64_register_info_table[0]))
+
+ /* Number of general registers. */
+ #define X86_64_NUM_GREGS (22)
+
+ int x86_64_num_regs = X86_64_NUM_REGS;
+ int x86_64_num_gregs = X86_64_NUM_GREGS;
+
/* Number of bytes of storage in the actual machine representation for
register REGNO. */
int
x86_64_register_raw_size (int regno)
{
! return x86_64_register_info_table[regno].size;
}

/* x86_64_register_byte_table[i] is the offset into the register file of the
start of register number i. We initialize this from
! x86_64_register_info_table. */
int x86_64_register_byte_table[X86_64_NUM_REGS];

/* Index within `registers' of the first byte of the space for register REGNO. */
*************** x86_64_register_byte (int regno)
*** 84,99 ****
static struct type *
x86_64_register_virtual_type (int regno)
{
! if (regno == PC_REGNUM || regno == SP_REGNUM)
! return builtin_type_void_func_ptr;
! if (IS_FP_REGNUM (regno))
! return builtin_type_i387_ext;
! if (IS_SSE_REGNUM (regno))
! return builtin_type_v4sf;
! if (IS_FPU_CTRL_REGNUM (regno) || regno == MXCSR_REGNUM
! || regno == EFLAGS_REGNUM)
! return builtin_type_int32;
! return builtin_type_int64;
}

/* x86_64_register_convertible is true if register N's virtual format is
--- 141,147 ----
static struct type *
x86_64_register_virtual_type (int regno)
{
! return *x86_64_register_info_table[regno].type;
}

/* x86_64_register_convertible is true if register N's virtual format is
*************** x86_64_push_arguments (int nargs, struct
*** 557,571 ****
int i;
static int int_parameter_registers[INT_REGS] = {
5 /*RDI*/, 4 /*RSI*/,
! 1 /*RDX*/, 2 /*RCX*/,
! 8 /*R8 */ , 9 /*R9 */
};
/* XMM0 - XMM15 */
static int sse_parameter_registers[SSE_REGS] = {
! 34, 35, 36, 37,
! 38, 39, 40, 41,
! 42, 43, 44, 45,
! 46, 47, 48, 49
};
int stack_values_count = 0;
int *stack_values;
--- 605,619 ----
int i;
static int int_parameter_registers[INT_REGS] = {
5 /*RDI*/, 4 /*RSI*/,
! 3 /*RDX*/, 2 /*RCX*/,
! 8 /*R8 */, 9 /*R9 */
};
/* XMM0 - XMM15 */
static int sse_parameter_registers[SSE_REGS] = {
! XMM1_REGNUM-1, XMM1_REGNUM, XMM1_REGNUM+1, XMM1_REGNUM+2,
! XMM1_REGNUM+3, XMM1_REGNUM+4, XMM1_REGNUM+5, XMM1_REGNUM+6,
! XMM1_REGNUM+7, XMM1_REGNUM+8, XMM1_REGNUM+9, XMM1_REGNUM+10,
! XMM1_REGNUM+11, XMM1_REGNUM+12, XMM1_REGNUM+13, XMM1_REGNUM+14
};
int stack_values_count = 0;
int *stack_values;
*************** x86_64_store_return_value (struct type *
*** 704,730 ****
static char *
x86_64_register_name (int reg_nr)
{
! static char *register_names[] = {
! "rax", "rdx", "rcx", "rbx",
! "rsi", "rdi", "rbp", "rsp",
! "r8", "r9", "r10", "r11",
! "r12", "r13", "r14", "r15",
! "rip", "eflags",
! "st0", "st1", "st2", "st3",
! "st4", "st5", "st6", "st7",
! "fctrl", "fstat", "ftag", "fiseg",
! "fioff", "foseg", "fooff", "fop",
! "xmm0", "xmm1", "xmm2", "xmm3",
! "xmm4", "xmm5", "xmm6", "xmm7",
! "xmm8", "xmm9", "xmm10", "xmm11",
! "xmm12", "xmm13", "xmm14", "xmm15",
! "mxcsr"
! };
! if (reg_nr < 0)
return NULL;
! if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
! return NULL;
! return register_names[reg_nr];
}
\f

--- 752,760 ----
static char *
x86_64_register_name (int reg_nr)
{
! if (reg_nr < 0 || reg_nr >= X86_64_NUM_REGS)
return NULL;
! return x86_64_register_info_table[reg_nr].name;
}
\f

*************** i386_gdbarch_init (struct gdbarch_info i
*** 826,831 ****
--- 856,862 ----
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
+ int i, sum;

/* Find a candidate among the list of pre-declared architectures. */
for (arches = gdbarch_list_lookup_by_info (arches, &info);
*************** i386_gdbarch_init (struct gdbarch_info i
*** 904,913 ****
set_gdbarch_register_raw_size (gdbarch, x86_64_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, 16);
set_gdbarch_register_byte (gdbarch, x86_64_register_byte);
/* Total amount of space needed to store our copies of the machine's register
(SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS) */
! set_gdbarch_register_bytes (gdbarch,
! (18 * 8) + (8 * 10) + (8 * 4) + (16 * 16 + 4));
set_gdbarch_register_virtual_size (gdbarch, generic_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 16);

--- 935,946 ----
set_gdbarch_register_raw_size (gdbarch, x86_64_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, 16);
set_gdbarch_register_byte (gdbarch, x86_64_register_byte);
+
/* Total amount of space needed to store our copies of the machine's register
(SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS) */
! for (i=0, sum=0; i < X86_64_NUM_REGS; i++)
! sum += x86_64_register_info_table[i].size;
! set_gdbarch_register_bytes (gdbarch, sum);
set_gdbarch_register_virtual_size (gdbarch, generic_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 16);

*************** i386_gdbarch_init (struct gdbarch_info i
*** 924,930 ****
set_gdbarch_fp_regnum (gdbarch, 6); /* (rbp) */
set_gdbarch_pc_regnum (gdbarch, 16); /* (rip) Contains program counter. */

! set_gdbarch_fp0_regnum (gdbarch, 18); /* First FPU floating-point register. */

set_gdbarch_read_fp (gdbarch, cfi_read_fp);
set_gdbarch_write_fp (gdbarch, cfi_write_fp);
--- 957,963 ----
set_gdbarch_fp_regnum (gdbarch, 6); /* (rbp) */
set_gdbarch_pc_regnum (gdbarch, 16); /* (rip) Contains program counter. */

! set_gdbarch_fp0_regnum (gdbarch, X86_64_NUM_GREGS); /* First FPU floating-point register. */

set_gdbarch_read_fp (gdbarch, cfi_read_fp);
set_gdbarch_write_fp (gdbarch, cfi_write_fp);
*************** _initialize_x86_64_tdep (void)
*** 1042,1048 ****
for (i = 0; i < X86_64_NUM_REGS; i++)
{
x86_64_register_byte_table[i] = offset;
! offset += x86_64_register_raw_size_table[i];
}
}

--- 1075,1081 ----
for (i = 0; i < X86_64_NUM_REGS; i++)
{
x86_64_register_byte_table[i] = offset;
! offset += x86_64_register_info_table[i].size;
}
}

Index: x86-64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v
retrieving revision 1.2
diff -c -3 -p -r1.2 x86-64-tdep.h
*** x86-64-tdep.h 2002/03/10 18:16:26 1.2
--- x86-64-tdep.h 2002/03/26 16:56:52
***************
*** 25,35 ****

#include "i386-tdep.h"

! /* Number of all registers */
! #define X86_64_NUM_REGS (51)
!
! /* Number of general registers. */
! #define X86_64_NUM_GREGS (18)

gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;
--- 25,32 ----

#include "i386-tdep.h"

! extern int x86_64_num_regs;
! extern int x86_64_num_gregs;

gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;
Index: x86-64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-nat.c,v
retrieving revision 1.6
diff -c -3 -p -r1.6 x86-64-linux-nat.c
*** x86-64-linux-nat.c 2002/03/10 18:16:26 1.6
--- x86-64-linux-nat.c 2002/03/26 16:56:52
***************
*** 39,49 ****
format and GDB's register array layout. */

static int x86_64_regmap[] = {
! RAX, RDX, RCX, RBX,
RSI, RDI, RBP, RSP,
R8, R9, R10, R11,
R12, R13, R14, R15,
! RIP, EFLAGS
};

static unsigned long
--- 39,50 ----
format and GDB's register array layout. */

static int x86_64_regmap[] = {
! RAX, RBX, RCX, RDX,
RSI, RDI, RBP, RSP,
R8, R9, R10, R11,
R12, R13, R14, R15,
! RIP, EFLAGS,
! DS, ES, FS, GS
};

static unsigned long
*************** x86_64_linux_dr_get_status (void)
*** 125,131 ****
the register sets used by `ptrace'. */

#define GETREGS_SUPPLIES(regno) \
! (0 <= (regno) && (regno) <= 17)
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)

--- 126,132 ----
the register sets used by `ptrace'. */

#define GETREGS_SUPPLIES(regno) \
! (0 <= (regno) && (regno) < x86_64_num_gregs)
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)

*************** supply_gregset (elf_gregset_t * gregsetp
*** 144,150 ****
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;

! for (i = 0; i < X86_64_NUM_GREGS; i++)
supply_register (i, (char *) (regp + x86_64_regmap[i]));
}

--- 145,151 ----
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;

! for (i = 0; i < x86_64_num_gregs; i++)
supply_register (i, (char *) (regp + x86_64_regmap[i]));
}

*************** fill_gregset (elf_gregset_t * gregsetp,
*** 158,164 ****
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;

! for (i = 0; i < X86_64_NUM_GREGS; i++)
if ((regno == -1 || regno == i))
read_register_gen (i, regp + x86_64_regmap[i]);
}
--- 159,165 ----
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;

! for (i = 0; i < x86_64_num_gregs; i++)
if ((regno == -1 || regno == i))
read_register_gen (i, regp + x86_64_regmap[i]);
}