📄 rs6000-nat.c
字号:
/* IBM RS/6000 native-dependent code for GDB, the GNU debugger. Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "inferior.h"#include "target.h"#include "nm.h"#include <sys/ptrace.h>#include <sys/reg.h>#include <sys/param.h>#include <sys/dir.h>#include <sys/user.h>#include <signal.h>#include <sys/ioctl.h>#include <fcntl.h>#include <a.out.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/core.h>extern int errno;static voidexec_one_dummy_insn PARAMS ((void));/* Conversion from gdb-to-system special purpose register numbers.. */static int special_regs[] = { IAR, /* PC_REGNUM */ MSR, /* PS_REGNUM */ CR, /* CR_REGNUM */ LR, /* LR_REGNUM */ CTR, /* CTR_REGNUM */ XER, /* XER_REGNUM */ MQ /* MQ_REGNUM */};voidfetch_inferior_registers (regno) int regno;{ int ii; extern char registers[]; if (regno < 0) { /* for all registers */ /* read 32 general purpose registers. */ for (ii=0; ii < 32; ++ii) *(int*)®isters[REGISTER_BYTE (ii)] = ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0); /* read general purpose floating point registers. */ for (ii=0; ii < 32; ++ii) ptrace (PT_READ_FPR, inferior_pid, (PTRACE_ARG3_TYPE) ®isters [REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0); /* read special registers. */ for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] = ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii], 0, 0); registers_fetched (); return; } /* else an individual register is addressed. */ else if (regno < FP0_REGNUM) { /* a GPR */ *(int*)®isters[REGISTER_BYTE (regno)] = ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0); } else if (regno <= FPLAST_REGNUM) { /* a FPR */ ptrace (PT_READ_FPR, inferior_pid, (PTRACE_ARG3_TYPE) ®isters [REGISTER_BYTE (regno)], (regno-FP0_REGNUM+FPR0), 0); } else if (regno <= LAST_SP_REGNUM) { /* a special register */ *(int*)®isters[REGISTER_BYTE (regno)] = ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[regno-FIRST_SP_REGNUM], 0, 0); } else fprintf (stderr, "gdb error: register no %d not implemented.\n", regno); register_valid [regno] = 1;}/* Store our register values back into the inferior. If REGNO is -1, do this for all registers. Otherwise, REGNO specifies which register (so we can save time). */voidstore_inferior_registers (regno) int regno;{ extern char registers[]; errno = 0; if (regno == -1) { /* for all registers.. */ int ii; /* execute one dummy instruction (which is a breakpoint) in inferior process. So give kernel a chance to do internal house keeping. Otherwise the following ptrace(2) calls will mess up user stack since kernel will get confused about the bottom of the stack (%sp) */ exec_one_dummy_insn (); /* write general purpose registers first! */ for ( ii=GPR0; ii<=GPR31; ++ii) { ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, *(int*)®isters[REGISTER_BYTE (ii)], 0); if ( errno ) { perror ("ptrace write_gpr"); errno = 0; } } /* write floating point registers now. */ for ( ii=0; ii < 32; ++ii) { ptrace (PT_WRITE_FPR, inferior_pid, (PTRACE_ARG3_TYPE) ®isters[REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0); if ( errno ) { perror ("ptrace write_fpr"); errno = 0; } } /* write special registers. */ for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) { ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii], *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0); if ( errno ) { perror ("ptrace write_gpr"); errno = 0; } } } /* else, a specific register number is given... */ else if (regno < FP0_REGNUM) { /* a GPR */ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, *(int*)®isters[REGISTER_BYTE (regno)], 0); } else if (regno <= FPLAST_REGNUM) { /* a FPR */ ptrace (PT_WRITE_FPR, inferior_pid, (PTRACE_ARG3_TYPE) ®isters[REGISTER_BYTE (regno)], regno-FP0_REGNUM+FPR0, 0); } else if (regno <= LAST_SP_REGNUM) { /* a special register */ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM], *(int*)®isters[REGISTER_BYTE (regno)], 0); } else fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno); if ( errno ) { perror ("ptrace write"); errno = 0; }}/* Execute one dummy breakpoint instruction. This way we give the kernel a chance to do some housekeeping and update inferior's internal data, including u_area. */static voidexec_one_dummy_insn (){#define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200 unsigned long shadow; unsigned int status, pid; /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that this address will never be executed again by the real code. */ target_insert_breakpoint (DUMMY_INSN_ADDR, &shadow); errno = 0; ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) DUMMY_INSN_ADDR, 0, 0); if (errno) perror ("pt_continue"); do { pid = wait (&status); } while (pid != inferior_pid); target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);}voidfetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) char *core_reg_sect; unsigned core_reg_size; int which; unsigned int reg_addr; /* Unused in this version */{ /* fetch GPRs and special registers from the first register section in core bfd. */ if (which == 0) { /* copy GPRs first. */ bcopy (core_reg_sect, registers, 32 * 4); /* gdb's internal register template and bfd's register section layout should share a common include file. FIXMEmgo */ /* then comes special registes. They are supposed to be in the same order in gdb template and bfd `.reg' section. */ core_reg_sect += (32 * 4); bcopy (core_reg_sect, ®isters [REGISTER_BYTE (FIRST_SP_REGNUM)], (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4); } /* fetch floating point registers from register section 2 in core bfd. */ else if (which == 2) bcopy (core_reg_sect, ®isters [REGISTER_BYTE (FP0_REGNUM)], 32 * 8); else fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -