@ -50,13 +50,56 @@
# include "x86-64-tdep.h"
# include "x86-64-linux-tdep.h"
# include "i386-linux-tdep.h"
# include "amd64-nat.h"
/* Mapping between the general-purpose registers in GNU/Linux x86-64
` struct user ' format and GDB ' s register cache layout . */
static int x86_64_linux_gregset64_reg_offset [ ] =
{
RAX * 8 , RBX * 8 , /* %rax, %rbx */
RCX * 8 , RDX * 8 , /* %rcx, %rdx */
RSI * 8 , RDI * 8 , /* %rsi, %rdi */
RBP * 8 , RSP * 8 , /* %rbp, %rsp */
R8 * 8 , R9 * 8 , /* %r8 ... */
R10 * 8 , R11 * 8 ,
R12 * 8 , R13 * 8 ,
R14 * 8 , R15 * 8 , /* ... %r15 */
RIP * 8 , EFLAGS * 8 , /* %rip, %eflags */
DS * 8 , ES * 8 , /* %ds, %es */
FS * 8 , GS * 8 /* %fs, %gs */
} ;
/* Mapping between the general-purpose registers in GNU/Linux x86-64
` struct user ' format and GDB ' s register cache layout for GNU / Linux
i386 .
Note that most GNU / Linux x86 - 64 registers are 64 - bit , while the
GNU / Linux i386 registers are all 32 - bit , but since we ' re
little - endian we get away with that . */
/* From <sys/reg.h> on GNU/Linux i386. */
static int x86_64_linux_gregset32_reg_offset [ ] =
{
10 * 8 , 11 * 8 , /* %eax, %ecx */
12 * 8 , 13 * 8 , /* %edx, %ebx */
19 * 8 , 4 * 8 , /* %esp, %ebp */
13 * 8 , 14 * 8 , /* %esi, %edi */
16 * 8 , 18 * 8 , /* %eip, %eflags */
17 * 8 , 20 * 8 , /* %cs, %ss */
23 * 8 , 24 * 8 , /* %ds, %es */
25 * 4 , 26 * 4 , /* %fs, %gs */
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
15 * 8 /* "orig_eax" */
} ;
/* 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 )
@ -64,27 +107,27 @@
/* Transfering the general-purpose registers between GDB, inferiors
and core files . */
/* Fill GDB's register array with the general-purpose register values
/* Fill GDB's register cache with the general-purpose register values
in * GREGSETP . */
void
supply_gregset ( elf_gregset_t * gregsetp )
{
x86_64_linux_supply_gregset ( ( char * ) gregsetp ) ;
amd64_supply_native_gregset ( current_regcache , gregsetp , - 1 ) ;
}
/* Fill register REGNO (if it is a general-purpose register) in
* GREGSETPS with the value in GDB ' s register array . If REGNO is - 1 ,
/* Fill register REGNUM (if it is a general-purpose register) in
* GREGSETP with the value in GDB ' s register cache . If REGNUM is - 1 ,
do this for all registers . */
void
fill_gregset ( elf_gregset_t * gregsetp , int regno )
fill_gregset ( elf_gregset_t * gregsetp , int regnum )
{
x86_64_linux_fill_gregset ( ( char * ) gregsetp , regno ) ;
amd64_collect_native_gregset ( current_regcache , gregsetp , regnum ) ;
}
/* Fetch all general-purpose registers from process/thread TID and
store their values in GDB ' s register array . */
store their values in GDB ' s register cache . */
static void
fetch_regs ( int tid )
@ -97,18 +140,18 @@ fetch_regs (int tid)
supply_gregset ( & regs ) ;
}
/* Store all valid general-purpose registers in GDB's register array
/* Store all valid general-purpose registers in GDB's register cache
into the process / thread specified by TID . */
static void
store_regs ( int tid , int regno )
store_regs ( int tid , int regnum )
{
elf_gregset_t regs ;
if ( ptrace ( PTRACE_GETREGS , tid , 0 , ( long ) & regs ) < 0 )
perror_with_name ( " Couldn't get registers " ) ;
fill_gregset ( & regs , regno ) ;
fill_gregset ( & regs , regnum ) ;
if ( ptrace ( PTRACE_SETREGS , tid , 0 , ( long ) & regs ) < 0 )
perror_with_name ( " Couldn't write registers " ) ;
@ -117,7 +160,7 @@ store_regs (int tid, int regno)
/* Transfering floating-point registers between GDB, inferiors and cores. */
/* Fill GDB's register array with the floating-point and SSE register
/* Fill GDB's register cache with the floating-point and SSE register
values in * FPREGSETP . */
void
@ -127,7 +170,7 @@ supply_fpregset (elf_fpregset_t *fpregsetp)
}
/* Fill register REGNUM (if it is a floating-point or SSE register) in
* FPREGSETP with the value in GDB ' s register array . If REGNUM is
* FPREGSETP with the value in GDB ' s register cache . If REGNUM is
- 1 , do this for all registers . */
void
@ -137,7 +180,7 @@ fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
}
/* Fetch all floating-point registers from process/thread TID and store
thier values in GDB ' s register array . */
thier values in GDB ' s register cache . */
static void
fetch_fpregs ( int tid )
@ -150,18 +193,18 @@ fetch_fpregs (int tid)
supply_fpregset ( & fpregs ) ;
}
/* Store all valid floating-point registers in GDB's register array
/* Store all valid floating-point registers in GDB's register cache
into the process / thread specified by TID . */
static void
store_fpregs ( int tid , int regno )
store_fpregs ( int tid , int regnum )
{
elf_fpregset_t fpregs ;
if ( ptrace ( PTRACE_GETFPREGS , tid , 0 , ( long ) & fpregs ) < 0 )
perror_with_name ( " Couldn't get floating point status " ) ;
fill_fpregset ( & fpregs , regno ) ;
fill_fpregset ( & fpregs , regnum ) ;
if ( ptrace ( PTRACE_SETFPREGS , tid , 0 , ( long ) & fpregs ) < 0 )
perror_with_name ( " Couldn't write floating point status " ) ;
@ -170,12 +213,12 @@ store_fpregs (int tid, int regno)
/* Transferring arbitrary registers between GDB and inferior. */
/* Fetch register REGNO from the child process. If REGNO is -1, do
/* Fetch register REGNUM from the child process. If REGNUM is -1, do
this for all registers ( including the floating point and SSE
registers ) . */
void
fetch_inferior_registers ( int regno )
fetch_inferior_registers ( int regnum )
{
int tid ;
@ -184,35 +227,29 @@ fetch_inferior_registers (int regno)
if ( tid = = 0 )
tid = PIDGET ( inferior_ptid ) ; /* Not a threaded program. */
if ( regno = = - 1 )
if ( regnum = = - 1 | | amd64_native_gregset_supplies_p ( regnum ) )
{
fetch_regs ( tid ) ;
fetch_fpregs ( tid ) ;
return ;
if ( regnum ! = - 1 )
return ;
}
if ( GETREGS_SUPPLIES ( regno ) )
{
fetch_regs ( tid ) ;
return ;
}
if ( GETFPREGS_SUPPLIES ( regno ) )
if ( regnum = = - 1 | | GETFPREGS_SUPPLIES ( regnum ) )
{
fetch_fpregs ( tid ) ;
return ;
}
internal_error ( __FILE__ , __LINE__ ,
" Got request for bad register number %d. " , regno ) ;
" Got request for bad register number %d. " , regnum ) ;
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers ( including the floating - point and SSE
/* Store register REGNUM back into the child process. If REGNUM is
- 1 , do this for all registers ( including the floating - point and SSE
registers ) . */
void
store_inferior_registers ( int regno )
store_inferior_registers ( int regnum )
{
int tid ;
@ -221,27 +258,21 @@ store_inferior_registers (int regno)
if ( tid = = 0 )
tid = PIDGET ( inferior_ptid ) ; /* Not a threaded program. */
if ( regno = = - 1 )
if ( regnum = = - 1 | | amd64_native_gregset_supplies_p ( regnum ) )
{
store_regs ( tid , regno ) ;
store_fpregs ( tid , regno ) ;
return ;
}
if ( GETREGS_SUPPLIES ( regno ) )
{
store_regs ( tid , regno ) ;
return ;
store_regs ( tid , regnum ) ;
if ( regnum ! = - 1 )
return ;
}
if ( GETFPREGS_SUPPLIES ( regno ) )
if ( regnum = = - 1 | | GETFPREGS_SUPPLIES ( regnum ) )
{
store_fpregs ( tid , regno ) ;
store_fpregs ( tid , regnum ) ;
return ;
}
internal_error ( __FILE__ , __LINE__ ,
" Got request to store bad register number %d. " , regno ) ;
" Got request to store bad register number %d. " , regnum ) ;
}
@ -354,3 +385,20 @@ child_post_startup_inferior (ptid_t ptid)
i386_cleanup_dregs ( ) ;
linux_child_post_startup_inferior ( ptid ) ;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
void _initialize_x86_64_linux_nat ( void ) ;
void
_initialize_x86_64_linux_nat ( void )
{
amd64_native_gregset32_reg_offset = x86_64_linux_gregset32_reg_offset ;
amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS ;
amd64_native_gregset64_reg_offset = x86_64_linux_gregset64_reg_offset ;
gdb_assert ( ARRAY_SIZE ( x86_64_linux_gregset32_reg_offset )
= = amd64_native_gregset32_num_regs ) ;
gdb_assert ( ARRAY_SIZE ( x86_64_linux_gregset64_reg_offset )
= = amd64_native_gregset64_num_regs ) ;
}