gdb/amd64-linux-nat.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "inferior.h"
- #include "regcache.h"
- #include "elf/common.h"
- #include <sys/uio.h>
- #include <sys/ptrace.h>
- #include <asm/prctl.h>
- #include <sys/reg.h>
- #include "gregset.h"
- #include "gdb_proc_service.h"
- #include "amd64-nat.h"
- #include "linux-nat.h"
- #include "amd64-tdep.h"
- #include "amd64-linux-tdep.h"
- #include "i386-linux-tdep.h"
- #include "x86-xstate.h"
- #include "x86-linux-nat.h"
- static int amd64_linux_gregset32_reg_offset[] =
- {
- RAX * 8, RCX * 8,
- RDX * 8, RBX * 8,
- RSP * 8, RBP * 8,
- RSI * 8, RDI * 8,
- RIP * 8, EFLAGS * 8,
- CS * 8, SS * 8,
- DS * 8, ES * 8,
- FS * 8, GS * 8,
- -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,
- -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, -1, -1, -1, -1, -1,
- ORIG_RAX * 8
- };
- void
- supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
- {
- amd64_supply_native_gregset (regcache, gregsetp, -1);
- }
- void
- fill_gregset (const struct regcache *regcache,
- elf_gregset_t *gregsetp, int regnum)
- {
- amd64_collect_native_gregset (regcache, gregsetp, regnum);
- }
- void
- supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
- {
- amd64_supply_fxsave (regcache, -1, fpregsetp);
- }
- void
- fill_fpregset (const struct regcache *regcache,
- elf_fpregset_t *fpregsetp, int regnum)
- {
- amd64_collect_fxsave (regcache, regnum, fpregsetp);
- }
- static void
- amd64_linux_fetch_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int tid;
-
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid);
- if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
- {
- elf_gregset_t regs;
- if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name (_("Couldn't get registers"));
- amd64_supply_native_gregset (regcache, ®s, -1);
- if (regnum != -1)
- return;
- }
- if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
- {
- elf_fpregset_t fpregs;
- if (have_ptrace_getregset)
- {
- char xstateregs[X86_XSTATE_MAX_SIZE];
- struct iovec iov;
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof (xstateregs);
- if (ptrace (PTRACE_GETREGSET, tid,
- (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
- perror_with_name (_("Couldn't get extended state status"));
- amd64_supply_xsave (regcache, -1, xstateregs);
- }
- else
- {
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name (_("Couldn't get floating point status"));
- amd64_supply_fxsave (regcache, -1, &fpregs);
- }
- }
- }
- static void
- amd64_linux_store_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- int tid;
-
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid);
- if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
- {
- elf_gregset_t regs;
- if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name (_("Couldn't get registers"));
- amd64_collect_native_gregset (regcache, ®s, regnum);
- if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0)
- perror_with_name (_("Couldn't write registers"));
- if (regnum != -1)
- return;
- }
- if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum))
- {
- elf_fpregset_t fpregs;
- if (have_ptrace_getregset)
- {
- char xstateregs[X86_XSTATE_MAX_SIZE];
- struct iovec iov;
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof (xstateregs);
- if (ptrace (PTRACE_GETREGSET, tid,
- (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
- perror_with_name (_("Couldn't get extended state status"));
- amd64_collect_xsave (regcache, regnum, xstateregs, 0);
- if (ptrace (PTRACE_SETREGSET, tid,
- (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
- perror_with_name (_("Couldn't write extended state status"));
- }
- else
- {
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name (_("Couldn't get floating point status"));
- amd64_collect_fxsave (regcache, regnum, &fpregs);
- if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
- perror_with_name (_("Couldn't write floating point status"));
- }
- }
- }
- ps_err_e
- ps_get_thread_area (const struct ps_prochandle *ph,
- lwpid_t lwpid, int idx, void **base)
- {
- if (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 32)
- {
- unsigned int base_addr;
- ps_err_e result;
- result = x86_linux_get_thread_area (lwpid, (void *) (long) idx,
- &base_addr);
- if (result == PS_OK)
- {
-
- (*base) = (void *) (long) base_addr;
- }
- return result;
- }
- else
- {
-
- #ifndef PTRACE_ARCH_PRCTL
- #define PTRACE_ARCH_PRCTL 30
- #endif
- FIXME
- gdb_assert (FS < ELF_NGREG);
- gdb_assert (GS < ELF_NGREG);
- switch (idx)
- {
- case FS:
- #ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
- {
-
- unsigned long fs;
- errno = 0;
- fs = ptrace (PTRACE_PEEKUSER, lwpid,
- offsetof (struct user_regs_struct, fs_base), 0);
- if (errno == 0)
- {
- *base = (void *) fs;
- return PS_OK;
- }
- }
- #endif
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
- return PS_OK;
- break;
- case GS:
- #ifdef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
- {
- unsigned long gs;
- errno = 0;
- gs = ptrace (PTRACE_PEEKUSER, lwpid,
- offsetof (struct user_regs_struct, gs_base), 0);
- if (errno == 0)
- {
- *base = (void *) gs;
- return PS_OK;
- }
- }
- #endif
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
- return PS_OK;
- break;
- default:
- return PS_BADADDR;
- }
- }
- return PS_ERR;
- }
- typedef int compat_int_t;
- typedef unsigned int compat_uptr_t;
- typedef int compat_time_t;
- typedef int compat_timer_t;
- typedef int compat_clock_t;
- struct compat_timeval
- {
- compat_time_t tv_sec;
- int tv_usec;
- };
- typedef union compat_sigval
- {
- compat_int_t sival_int;
- compat_uptr_t sival_ptr;
- } compat_sigval_t;
- typedef struct compat_siginfo
- {
- int si_signo;
- int si_errno;
- int si_code;
- union
- {
- int _pad[((128 / sizeof (int)) - 3)];
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- } _kill;
-
- struct
- {
- compat_timer_t _tid;
- int _overrun;
- compat_sigval_t _sigval;
- } _timer;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- compat_sigval_t _sigval;
- } _rt;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- int _status;
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- struct
- {
- unsigned int _addr;
- } _sigfault;
-
- struct
- {
- int _band;
- int _fd;
- } _sigpoll;
- } _sifields;
- } compat_siginfo_t;
- typedef struct compat_x32_clock
- {
- int lower;
- int upper;
- } compat_x32_clock_t;
- typedef struct compat_x32_siginfo
- {
- int si_signo;
- int si_errno;
- int si_code;
- union
- {
- int _pad[((128 / sizeof (int)) - 3)];
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- } _kill;
-
- struct
- {
- compat_timer_t _tid;
- int _overrun;
- compat_sigval_t _sigval;
- } _timer;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- compat_sigval_t _sigval;
- } _rt;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- int _status;
- compat_x32_clock_t _utime;
- compat_x32_clock_t _stime;
- } _sigchld;
-
- struct
- {
- unsigned int _addr;
- } _sigfault;
-
- struct
- {
- int _band;
- int _fd;
- } _sigpoll;
- } _sifields;
- } compat_x32_siginfo_t;
- #define cpt_si_pid _sifields._kill._pid
- #define cpt_si_uid _sifields._kill._uid
- #define cpt_si_timerid _sifields._timer._tid
- #define cpt_si_overrun _sifields._timer._overrun
- #define cpt_si_status _sifields._sigchld._status
- #define cpt_si_utime _sifields._sigchld._utime
- #define cpt_si_stime _sifields._sigchld._stime
- #define cpt_si_ptr _sifields._rt._sigval.sival_ptr
- #define cpt_si_addr _sifields._sigfault._addr
- #define cpt_si_band _sifields._sigpoll._band
- #define cpt_si_fd _sifields._sigpoll._fd
- #ifndef si_timerid
- #define si_timerid si_timer1
- #endif
- #ifndef si_overrun
- #define si_overrun si_timer2
- #endif
- static void
- compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->cpt_si_timerid = from->si_timerid;
- to->cpt_si_overrun = from->si_overrun;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- }
- else if (to->si_code < 0)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_status = from->si_status;
- to->cpt_si_utime = from->si_utime;
- to->cpt_si_stime = from->si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->cpt_si_addr = (intptr_t) from->si_addr;
- break;
- case SIGPOLL:
- to->cpt_si_band = from->si_band;
- to->cpt_si_fd = from->si_fd;
- break;
- default:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- break;
- }
- }
- }
- static void
- siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->si_timerid = from->cpt_si_timerid;
- to->si_overrun = from->cpt_si_overrun;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- }
- if (to->si_code < 0)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_status = from->cpt_si_status;
- to->si_utime = from->cpt_si_utime;
- to->si_stime = from->cpt_si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
- break;
- case SIGPOLL:
- to->si_band = from->cpt_si_band;
- to->si_fd = from->cpt_si_fd;
- break;
- default:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
- break;
- }
- }
- }
- static void
- compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
- siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->cpt_si_timerid = from->si_timerid;
- to->cpt_si_overrun = from->si_overrun;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- }
- else if (to->si_code < 0)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_status = from->si_status;
- memcpy (&to->cpt_si_utime, &from->si_utime,
- sizeof (to->cpt_si_utime));
- memcpy (&to->cpt_si_stime, &from->si_stime,
- sizeof (to->cpt_si_stime));
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->cpt_si_addr = (intptr_t) from->si_addr;
- break;
- case SIGPOLL:
- to->cpt_si_band = from->si_band;
- to->cpt_si_fd = from->si_fd;
- break;
- default:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- break;
- }
- }
- }
- static void
- siginfo_from_compat_x32_siginfo (siginfo_t *to,
- compat_x32_siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->si_timerid = from->cpt_si_timerid;
- to->si_overrun = from->cpt_si_overrun;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- }
- if (to->si_code < 0)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_status = from->cpt_si_status;
- memcpy (&to->si_utime, &from->cpt_si_utime,
- sizeof (to->si_utime));
- memcpy (&to->si_stime, &from->cpt_si_stime,
- sizeof (to->si_stime));
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
- break;
- case SIGPOLL:
- to->si_band = from->cpt_si_band;
- to->si_fd = from->cpt_si_fd;
- break;
- default:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
- break;
- }
- }
- }
- static int
- amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
- {
- struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
-
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
- {
- gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
- if (direction == 0)
- compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
- else
- siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
- return 1;
- }
-
- else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8)
- {
- gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t));
- if (direction == 0)
- compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
- native);
- else
- siginfo_from_compat_x32_siginfo (native,
- (struct compat_x32_siginfo *) inf);
- return 1;
- }
- else
- return 0;
- }
- void _initialize_amd64_linux_nat (void);
- void
- _initialize_amd64_linux_nat (void)
- {
- struct target_ops *t;
- amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
- amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
- amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
- amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
- gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
- == amd64_native_gregset32_num_regs);
-
- t = x86_linux_create_target ();
-
- t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
- t->to_store_registers = amd64_linux_store_inferior_registers;
-
- x86_linux_add_target (t);
-
- linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
- }