void riscv_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) { pid_t pid = get_ptrace_pid (regcache->ptid ()); struct gdbarch *gdbarch = regcache->arch (); if (regnum == -1 || regnum == RISCV_ZERO_REGNUM) regcache->raw_supply_zeroed (RISCV_ZERO_REGNUM); if (regnum == -1 || getregs_supplies (gdbarch, regnum)) { struct reg regs; if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); regcache->supply_regset (&riscv_fbsd_gregset, regnum, ®s, sizeof (regs)); } if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) { struct fpreg fpregs; if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); regcache->supply_regset (&riscv_fbsd_fpregset, regnum, &fpregs, sizeof (fpregs)); } }
static void mips_fbsd_store_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); struct gdbarch *gdbarch = regcache->arch (); if (regnum == -1 || getregs_supplies (gdbarch, regnum)) { struct reg regs; if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); mips_fbsd_collect_gregs (regcache, regnum, (char *) ®s, sizeof (register_t)); if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); } if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) { struct fpreg fpregs; if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); mips_fbsd_collect_fpregs (regcache, regnum, (char *) &fpregs, sizeof (f_register_t)); if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't write floating point status")); } }
static void i386bsd_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); if (regnum == -1 || GETREGS_SUPPLIES (regnum)) { struct reg regs; if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); i386bsd_supply_gregset (regcache, ®s); if (regnum != -1) return; } if (regnum == -1 || regnum >= I386_ST0_REGNUM) { struct fpreg fpregs; #ifdef HAVE_PT_GETXMMREGS char xmmregs[512]; #endif #ifdef PT_GETXSTATE_INFO if (x86bsd_xsave_len != 0) { void *xstateregs; xstateregs = alloca (x86bsd_xsave_len); if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); i387_supply_xsave (regcache, -1, xstateregs); return; } #endif #ifdef HAVE_PT_GETXMMREGS if (have_ptrace_xmmregs != 0 && ptrace(PT_GETXMMREGS, pid, (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) { have_ptrace_xmmregs = 1; i387_supply_fxsave (regcache, -1, xmmregs); } else { have_ptrace_xmmregs = 0; #endif if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); i387_supply_fsave (regcache, -1, &fpregs); #ifdef HAVE_PT_GETXMMREGS } #endif } }
void riscv_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum) { pid_t pid = get_ptrace_pid (regcache->ptid ()); struct gdbarch *gdbarch = regcache->arch (); if (regnum == -1 || getregs_supplies (gdbarch, regnum)) { struct reg regs; if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); regcache->collect_regset (&riscv_fbsd_gregset, regnum, ®s, sizeof (regs)); if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); } if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) { struct fpreg fpregs; if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); regcache->collect_regset (&riscv_fbsd_fpregset, regnum, &fpregs, sizeof (fpregs)); if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't write floating point status")); } }
/* wait for a ptraced child to get a certain signal */ static int waitpid_thread( struct thread *thread, int signal ) { int res, status; start_watchdog(); for (;;) { if ((res = waitpid( get_ptrace_pid(thread), &status, WUNTRACED | __WALL )) == -1) { if (errno == EINTR) { if (!watchdog_triggered()) continue; if (debug_level) fprintf( stderr, "%04x: *watchdog* waitpid aborted\n", thread->id ); } else if (errno == ECHILD) /* must have died */ { thread->unix_pid = -1; thread->unix_tid = -1; } else perror( "waitpid" ); stop_watchdog(); return 0; } res = handle_child_status( thread, res, status, signal ); if (!res || res == signal) break; } stop_watchdog(); return (thread->unix_pid != -1); }
/* resume a thread after we have used ptrace on it */ static void resume_after_ptrace( struct thread *thread ) { if (thread->unix_pid == -1) return; if (ptrace( PTRACE_DETACH, get_ptrace_pid(thread), (caddr_t)1, 0 ) == -1) { if (errno == ESRCH) thread->unix_pid = thread->unix_tid = -1; /* thread got killed */ } }
static void amd64bsd_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = get_regcache_arch (regcache); if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) { struct reg regs; if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) 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)) { struct fpreg fpregs; #ifdef PT_GETXSTATE_INFO void *xstateregs; if (x86bsd_xsave_len != 0) { xstateregs = alloca (x86bsd_xsave_len); if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); amd64_supply_xsave (regcache, -1, xstateregs); return; } #endif if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); amd64_supply_fxsave (regcache, -1, &fpregs); } }
void riscv_linux_nat_target::store_registers (struct regcache *regcache, int regnum) { int tid; tid = get_ptrace_pid (regcache->ptid ()); if ((regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_PC_REGNUM) || (regnum == -1)) { struct iovec iov; elf_gregset_t regs; iov.iov_base = ®s; iov.iov_len = sizeof (regs); if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't get registers")); else { fill_gregset (regcache, ®s, regnum); if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't set registers")); } } if ((regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) || (regnum == RISCV_CSR_FCSR_REGNUM) || (regnum == -1)) { struct iovec iov; elf_fpregset_t regs; iov.iov_base = ®s; iov.iov_len = sizeof (regs); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't get registers")); else { fill_fpregset (regcache, ®s, regnum); if (ptrace (PTRACE_SETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't set registers")); } } /* Access to CSRs has potential security issues, don't support them for now. */ }
/* read a long from a thread address space */ static long read_thread_long( struct thread *thread, long *addr, long *data ) { errno = 0; *data = ptrace( PTRACE_PEEKDATA, get_ptrace_pid(thread), (caddr_t)addr, 0 ); if ( *data == -1 && errno) { file_set_error(); return -1; } return 0; }
/* write a long to a thread address space */ static long write_thread_long( struct thread *thread, long *addr, long data, unsigned long mask ) { long res; if (mask != ~0ul) { if (read_thread_long( thread, addr, &res ) == -1) return -1; data = (data & mask) | (res & ~mask); } if ((res = ptrace( PTRACE_POKEDATA, get_ptrace_pid(thread), (caddr_t)addr, data )) == -1) file_set_error(); return res; }
static void fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { elf_gregset_t regs; pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache)); if (ptrace (PTRACE_GETREGS, tid, 0, (PTRACE_TYPE_ARG3) ®s) < 0) perror_with_name (_("Couldn't get registers")); supply_gregset (regcache, (const elf_gregset_t *)®s); }
/* resume a thread after we have used ptrace on it */ static void resume_after_ptrace( struct thread *thread ) { if (thread->unix_pid == -1) return; #ifdef CONFIG_UNIFIED_KERNEL if (thread->unix_pid == current->tgid) return; #endif if (ptrace( PTRACE_DETACH, get_ptrace_pid(thread), (caddr_t)1, 0 ) == -1) { if (errno == ESRCH) thread->unix_pid = thread->unix_tid = -1; /* thread got killed */ } }
void riscv_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum) { int tid; tid = get_ptrace_pid (regcache->ptid()); if ((regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_PC_REGNUM) || (regnum == -1)) { struct iovec iov; elf_gregset_t regs; iov.iov_base = ®s; iov.iov_len = sizeof (regs); if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't get registers")); else supply_gregset_regnum (regcache, ®s, regnum); } if ((regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) || (regnum == RISCV_CSR_FCSR_REGNUM) || (regnum == -1)) { struct iovec iov; elf_fpregset_t regs; iov.iov_base = ®s; iov.iov_len = sizeof (regs); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1) perror_with_name (_("Couldn't get registers")); else supply_fpregset_regnum (regcache, ®s, regnum); } if ((regnum == RISCV_CSR_MISA_REGNUM) || (regnum == -1)) { /* TODO: Need to add a ptrace call for this. */ regcache->raw_supply_zeroed (RISCV_CSR_MISA_REGNUM); } /* Access to other CSRs has potential security issues, don't support them for now. */ }
void sparc_fetch_inferior_registers (struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = regcache->arch (); pid_t pid; /* NOTE: cagney/2002-12-03: This code assumes that the currently selected light weight processes' registers can be written directly into the selected thread's register cache. This works fine when given an 1:1 LWP:thread model (such as found on GNU/Linux) but will, likely, have problems when used on an N:1 (userland threads) or N:M (userland multiple LWP) model. In the case of the latter two, the LWP's registers do not necessarily belong to the selected thread (the LWP could be in the middle of executing the thread switch code). These functions should instead be paramaterized with an explicit object (struct regcache, struct thread_info?) into which the LWPs registers can be written. */ pid = get_ptrace_pid (regcache->ptid ()); if (regnum == SPARC_G0_REGNUM) { gdb_byte zero[8] = { 0 }; regcache->raw_supply (SPARC_G0_REGNUM, &zero); return; } if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) { gregset_t regs; if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); sparc_supply_gregset (sparc_gregmap, regcache, -1, ®s); if (regnum != -1) return; } if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) { fpregset_t fpregs; if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); sparc_supply_fpregset (sparc_fpregmap, regcache, -1, &fpregs); } }
static void store_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { elf_gregset_t regs; pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache)); if (ptrace (PTRACE_GETREGS, tid, 0, (PTRACE_TYPE_ARG3) ®s) < 0) perror_with_name (_("Couldn't get registers")); fill_gregset (regcache, ®s, regnum); if (ptrace (PTRACE_SETREGS, tid, 0, (PTRACE_TYPE_ARG3) ®s) < 0) perror_with_name (_("Couldn't write registers")); }
/* you must do a resume_after_ptrace when finished with the thread */ static int suspend_for_ptrace( struct thread *thread ) { /* can't stop a thread while initialisation is in progress */ if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) goto error; /* this may fail if the client is already being debugged */ if (ptrace( PTRACE_ATTACH, get_ptrace_pid(thread), 0, 0 ) == -1) { if (errno == ESRCH) thread->unix_pid = thread->unix_tid = -1; /* thread got killed */ goto error; } if (waitpid_thread( thread, SIGSTOP )) return 1; resume_after_ptrace( thread ); error: set_error( STATUS_ACCESS_DENIED ); return 0; }
static void store_register (const struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); pid_t tid; int val; if (gdbarch_cannot_store_register (gdbarch, regno)) return; tid = get_ptrace_pid (regcache_get_ptid (regcache)); errno = 0; regcache_raw_collect (regcache, regno, &val); ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val); if (errno != 0) error (_("Couldn't write register %s (#%d): %s."), gdbarch_register_name (gdbarch, regno), regno, safe_strerror (errno)); }
static void inf_ptrace_resume (struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal signal) { pid_t pid; int request; if (ptid_equal (minus_one_ptid, ptid)) /* Resume all threads. Traditionally ptrace() only supports single-threaded processes, so simply resume the inferior. */ pid = ptid_get_pid (inferior_ptid); else pid = get_ptrace_pid (ptid); if (catch_syscall_enabled () > 0) request = PT_SYSCALL; else request = PT_CONTINUE; if (step) { /* If this system does not support PT_STEP, a higher level function will have called single_step() to transmute the step request into a continue request (by setting breakpoints on all possible successor instructions), so we don't have to worry about that here. */ request = PT_STEP; } /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from where it was. If GDB wanted it to start some other way, we have already written a new program counter value to the child. */ errno = 0; ptrace (request, pid, (PTRACE_TYPE_ARG3)1, gdb_signal_to_host (signal)); if (errno != 0) perror_with_name (("ptrace")); }
static void fetch_register (struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); pid_t tid; int val; if (gdbarch_cannot_fetch_register (gdbarch, regno)) { regcache_raw_supply (regcache, regno, NULL); return; } tid = get_ptrace_pid (regcache_get_ptid (regcache)); errno = 0; val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0); if (errno != 0) error (_("Couldn't read register %s (#%d): %s."), gdbarch_register_name (gdbarch, regno), regno, safe_strerror (errno)); regcache_raw_supply (regcache, regno, &val); }
static void ia64_linux_store_register (const struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = regcache->arch (); CORE_ADDR addr; size_t size; PTRACE_TYPE_RET *buf; pid_t pid; int i; if (ia64_cannot_store_register (gdbarch, regnum)) return; pid = get_ptrace_pid (regcache->ptid ()); /* This isn't really an address, but ptrace thinks of it as one. */ addr = ia64_register_addr (gdbarch, regnum); size = register_size (gdbarch, regnum); gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); buf = (PTRACE_TYPE_RET *) alloca (size); /* Write the register contents into the inferior a chunk at a time. */ regcache->raw_collect (regnum, buf); for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) { errno = 0; ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)addr, buf[i]); if (errno != 0) error (_("Couldn't write register %s (#%d): %s."), gdbarch_register_name (gdbarch, regnum), regnum, safe_strerror (errno)); addr += sizeof (PTRACE_TYPE_RET); } }
void amd64bsd_fetch_inferior_registers (struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = regcache->arch (); pid_t pid = get_ptrace_pid (regcache->ptid ()); if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) { struct reg regs; if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); amd64_supply_native_gregset (regcache, ®s, -1); if (regnum != -1) return; } #ifdef PT_GETFSBASE if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM) { register_t base; if (ptrace (PT_GETFSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1) perror_with_name (_("Couldn't get segment register fs_base")); regcache->raw_supply (AMD64_FSBASE_REGNUM, &base); if (regnum != -1) return; } #endif #ifdef PT_GETGSBASE if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM) { register_t base; if (ptrace (PT_GETGSBASE, pid, (PTRACE_TYPE_ARG3) &base, 0) == -1) perror_with_name (_("Couldn't get segment register gs_base")); regcache->raw_supply (AMD64_GSBASE_REGNUM, &base); if (regnum != -1) return; } #endif if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) { struct fpreg fpregs; #ifdef PT_GETXSTATE_INFO void *xstateregs; if (x86bsd_xsave_len != 0) { xstateregs = alloca (x86bsd_xsave_len); if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); amd64_supply_xsave (regcache, -1, xstateregs); return; } #endif if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); amd64_supply_fxsave (regcache, -1, &fpregs); } }
enum target_xfer_status inf_ptrace_target::xfer_partial (enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { pid_t pid = get_ptrace_pid (inferior_ptid); switch (object) { case TARGET_OBJECT_MEMORY: #ifdef PT_IO /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO request that promises to be much more efficient in reading and writing data in the traced process's address space. */ { struct ptrace_io_desc piod; /* NOTE: We assume that there are no distinct address spaces for instruction and data. However, on OpenBSD 3.9 and later, PIOD_WRITE_D doesn't allow changing memory that's mapped read-only. Since most code segments will be read-only, using PIOD_WRITE_D will prevent us from inserting breakpoints, so we use PIOD_WRITE_I instead. */ piod.piod_op = writebuf ? PIOD_WRITE_I : PIOD_READ_D; piod.piod_addr = writebuf ? (void *) writebuf : readbuf; piod.piod_offs = (void *) (long) offset; piod.piod_len = len; errno = 0; if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0) { /* Return the actual number of bytes read or written. */ *xfered_len = piod.piod_len; return (piod.piod_len == 0) ? TARGET_XFER_EOF : TARGET_XFER_OK; } /* If the PT_IO request is somehow not supported, fallback on using PT_WRITE_D/PT_READ_D. Otherwise we will return zero to indicate failure. */ if (errno != EINVAL) return TARGET_XFER_EOF; } #endif *xfered_len = inf_ptrace_peek_poke (pid, readbuf, writebuf, offset, len); return *xfered_len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF; case TARGET_OBJECT_UNWIND_TABLE: return TARGET_XFER_E_IO; case TARGET_OBJECT_AUXV: #if defined (PT_IO) && defined (PIOD_READ_AUXV) /* OpenBSD 4.5 has a new PIOD_READ_AUXV operation for the PT_IO request that allows us to read the auxilliary vector. Other BSD's may follow if they feel the need to support PIE. */ { struct ptrace_io_desc piod; if (writebuf) return TARGET_XFER_E_IO; piod.piod_op = PIOD_READ_AUXV; piod.piod_addr = readbuf; piod.piod_offs = (void *) (long) offset; piod.piod_len = len; errno = 0; if (ptrace (PT_IO, pid, (caddr_t)&piod, 0) == 0) { /* Return the actual number of bytes read or written. */ *xfered_len = piod.piod_len; return (piod.piod_len == 0) ? TARGET_XFER_EOF : TARGET_XFER_OK; } } #endif return TARGET_XFER_E_IO; case TARGET_OBJECT_WCOOKIE: return TARGET_XFER_E_IO; default: return TARGET_XFER_E_IO; } }
/* set a thread context */ static void set_thread_context_ptrace( struct thread *thread, unsigned int flags, const CONTEXT *context ) { int pid = get_ptrace_pid(thread); if (flags & CONTEXT_FULL) { if (flags & CONTEXT_INTEGER) { IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6); IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13); IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19); IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25); IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31); XREG(37,Xer); XREG(38,Cr); } if (flags & CONTEXT_CONTROL) { XREG(32,Iar); XREG(33,Msr); XREG(35,Ctr); XREG(36,Lr); } } if (flags & CONTEXT_FLOATING_POINT) { FREG(0); FREG(1); FREG(2); FREG(3); FREG(4); FREG(5); FREG(6); FREG(7); FREG(8); FREG(9); FREG(10); FREG(11); FREG(12); FREG(13); FREG(14); FREG(15); FREG(16); FREG(17); FREG(18); FREG(19); FREG(20); FREG(21); FREG(22); FREG(23); FREG(24); FREG(25); FREG(26); FREG(27); FREG(28); FREG(29); FREG(30); FREG(31); #undef FREG XREG((48+32*2),Fpscr); } return; error: file_set_error(); }
/* retrieve a thread context */ static void get_thread_context_ptrace( struct thread *thread, unsigned int flags, CONTEXT *context ) { int pid = get_ptrace_pid(thread); if (flags & CONTEXT_INTEGER) { #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error; #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error; IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6); IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13); IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19); IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25); IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31); #undef IREG XREG(37,Xer); XREG(38,Cr); context->ContextFlags |= CONTEXT_INTEGER; } if (flags & CONTEXT_CONTROL) { XREG(32,Iar); XREG(33,Msr); XREG(35,Ctr); XREG(36,Lr); /* 36 is LNK ... probably Lr ? */ context->ContextFlags |= CONTEXT_CONTROL; } if (flags & CONTEXT_FLOATING_POINT) { #define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error; FREG(0); FREG(1); FREG(2); FREG(3); FREG(4); FREG(5); FREG(6); FREG(7); FREG(8); FREG(9); FREG(10); FREG(11); FREG(12); FREG(13); FREG(14); FREG(15); FREG(16); FREG(17); FREG(18); FREG(19); FREG(20); FREG(21); FREG(22); FREG(23); FREG(24); FREG(25); FREG(26); FREG(27); FREG(28); FREG(29); FREG(30); FREG(31); XREG((48+32*2),Fpscr); context->ContextFlags |= CONTEXT_FLOATING_POINT; } return; error: file_set_error(); }
void sparc_store_inferior_registers (struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = regcache->arch (); pid_t pid; /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers about threaded assumptions. */ pid = get_ptrace_pid (regcache->ptid ()); if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) { gregset_t regs; if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); sparc_collect_gregset (sparc_gregmap, regcache, regnum, ®s); if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); /* Deal with the stack regs. */ if (regnum == -1 || regnum == SPARC_SP_REGNUM || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM)) { ULONGEST sp; regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); sparc_collect_rwindow (regcache, sp, regnum); } if (regnum != -1) return; } if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) { fpregset_t fpregs, saved_fpregs; if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating-point registers")); memcpy (&saved_fpregs, &fpregs, sizeof (fpregs)); sparc_collect_fpregset (sparc_fpregmap, regcache, regnum, &fpregs); /* Writing the floating-point registers will fail on NetBSD with EINVAL if the inferior process doesn't have an FPU state (i.e. if it didn't use the FPU yet). Therefore we don't try to write the registers if nothing changed. */ if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0) { if (ptrace (PTRACE_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't write floating-point registers")); } if (regnum != -1) return; } }
static void ia64_linux_fetch_register (struct regcache *regcache, int regnum) { struct gdbarch *gdbarch = regcache->arch (); CORE_ADDR addr; size_t size; PTRACE_TYPE_RET *buf; pid_t pid; int i; /* r0 cannot be fetched but is always zero. */ if (regnum == IA64_GR0_REGNUM) { const gdb_byte zero[8] = { 0 }; gdb_assert (sizeof (zero) == register_size (gdbarch, regnum)); regcache->raw_supply (regnum, zero); return; } /* fr0 cannot be fetched but is always zero. */ if (regnum == IA64_FR0_REGNUM) { const gdb_byte f_zero[16] = { 0 }; gdb_assert (sizeof (f_zero) == register_size (gdbarch, regnum)); regcache->raw_supply (regnum, f_zero); return; } /* fr1 cannot be fetched but is always one (1.0). */ if (regnum == IA64_FR1_REGNUM) { const gdb_byte f_one[16] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; gdb_assert (sizeof (f_one) == register_size (gdbarch, regnum)); regcache->raw_supply (regnum, f_one); return; } if (ia64_cannot_fetch_register (gdbarch, regnum)) { regcache->raw_supply (regnum, NULL); return; } pid = get_ptrace_pid (regcache->ptid ()); /* This isn't really an address, but ptrace thinks of it as one. */ addr = ia64_register_addr (gdbarch, regnum); size = register_size (gdbarch, regnum); gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0); buf = (PTRACE_TYPE_RET *) alloca (size); /* Read the register contents from the inferior a chunk at a time. */ for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) { errno = 0; buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)addr, 0); if (errno != 0) error (_("Couldn't read register %s (#%d): %s."), gdbarch_register_name (gdbarch, regnum), regnum, safe_strerror (errno)); addr += sizeof (PTRACE_TYPE_RET); } regcache->raw_supply (regnum, buf); }