1130803Smarcel/* Low level DECstation interface to ptrace, for GDB when running native. 2130803Smarcel Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000, 2001 3130803Smarcel Free Software Foundation, Inc. 4130803Smarcel Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU 5130803Smarcel and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin. 6130803Smarcel 7130803Smarcel This file is part of GDB. 8130803Smarcel 9130803Smarcel This program is free software; you can redistribute it and/or modify 10130803Smarcel it under the terms of the GNU General Public License as published by 11130803Smarcel the Free Software Foundation; either version 2 of the License, or 12130803Smarcel (at your option) any later version. 13130803Smarcel 14130803Smarcel This program is distributed in the hope that it will be useful, 15130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 16130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17130803Smarcel GNU General Public License for more details. 18130803Smarcel 19130803Smarcel You should have received a copy of the GNU General Public License 20130803Smarcel along with this program; if not, write to the Free Software 21130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 22130803Smarcel Boston, MA 02111-1307, USA. */ 23130803Smarcel 24130803Smarcel#include "defs.h" 25130803Smarcel#include "inferior.h" 26130803Smarcel#include "gdbcore.h" 27130803Smarcel#include "regcache.h" 28130803Smarcel#include <sys/ptrace.h> 29130803Smarcel#include <sys/types.h> 30130803Smarcel#include <sys/param.h> 31130803Smarcel#include <sys/user.h> 32130803Smarcel#undef JB_S0 33130803Smarcel#undef JB_S1 34130803Smarcel#undef JB_S2 35130803Smarcel#undef JB_S3 36130803Smarcel#undef JB_S4 37130803Smarcel#undef JB_S5 38130803Smarcel#undef JB_S6 39130803Smarcel#undef JB_S7 40130803Smarcel#undef JB_SP 41130803Smarcel#undef JB_S8 42130803Smarcel#undef JB_PC 43130803Smarcel#undef JB_SR 44130803Smarcel#undef NJBREGS 45130803Smarcel#include <setjmp.h> /* For JB_XXX. */ 46130803Smarcel 47130803Smarcel/* Size of elements in jmpbuf */ 48130803Smarcel 49130803Smarcel#define JB_ELEMENT_SIZE 4 50130803Smarcel 51130803Smarcel/* Map gdb internal register number to ptrace ``address''. 52130803Smarcel These ``addresses'' are defined in DECstation <sys/ptrace.h> */ 53130803Smarcel 54130803Smarcelstatic int 55130803Smarcelregister_ptrace_addr (int regno) 56130803Smarcel{ 57130803Smarcel return (regno < 32 ? GPR_BASE + regno 58130803Smarcel : regno == mips_regnum (current_gdbarch)->pc ? PC 59130803Smarcel : regno == mips_regnum (current_gdbarch)->cause ? CAUSE 60130803Smarcel : regno == mips_regnum (current_gdbarch)->hi ? MMHI 61130803Smarcel : regno == mips_regnum (current_gdbarch)->lo ? MMLO 62130803Smarcel : regno == mips_regnum (current_gdbarch)->fp_control_status ? FPC_CSR 63130803Smarcel : regno == mips_regnum (current_gdbarch)->fp_implementation_revision ? FPC_EIR 64130803Smarcel : regno >= FP0_REGNUM ? FPR_BASE + (regno - FP0_REGNUM) 65130803Smarcel : 0); 66130803Smarcel} 67130803Smarcel 68130803Smarcelstatic void fetch_core_registers (char *, unsigned, int, CORE_ADDR); 69130803Smarcel 70130803Smarcel/* Get all registers from the inferior */ 71130803Smarcel 72130803Smarcelvoid 73130803Smarcelfetch_inferior_registers (int regno) 74130803Smarcel{ 75130803Smarcel unsigned int regaddr; 76130803Smarcel char buf[MAX_REGISTER_SIZE]; 77130803Smarcel int i; 78130803Smarcel char zerobuf[MAX_REGISTER_SIZE]; 79130803Smarcel memset (zerobuf, 0, MAX_REGISTER_SIZE); 80130803Smarcel 81130803Smarcel deprecated_registers_fetched (); 82130803Smarcel 83130803Smarcel for (regno = 1; regno < NUM_REGS; regno++) 84130803Smarcel { 85130803Smarcel regaddr = register_ptrace_addr (regno); 86130803Smarcel for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (int)) 87130803Smarcel { 88130803Smarcel *(int *) &buf[i] = ptrace (PT_READ_U, PIDGET (inferior_ptid), 89130803Smarcel (PTRACE_ARG3_TYPE) regaddr, 0); 90130803Smarcel regaddr += sizeof (int); 91130803Smarcel } 92130803Smarcel supply_register (regno, buf); 93130803Smarcel } 94130803Smarcel 95130803Smarcel supply_register (ZERO_REGNUM, zerobuf); 96130803Smarcel /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */ 97130803Smarcel supply_register (DEPRECATED_FP_REGNUM, zerobuf); 98130803Smarcel} 99130803Smarcel 100130803Smarcel/* Store our register values back into the inferior. 101130803Smarcel If REGNO is -1, do this for all registers. 102130803Smarcel Otherwise, REGNO specifies which register (so we can save time). */ 103130803Smarcel 104130803Smarcelvoid 105130803Smarcelstore_inferior_registers (int regno) 106130803Smarcel{ 107130803Smarcel unsigned int regaddr; 108130803Smarcel char buf[80]; 109130803Smarcel 110130803Smarcel if (regno > 0) 111130803Smarcel { 112130803Smarcel if (regno == ZERO_REGNUM || regno == PS_REGNUM 113130803Smarcel || regno == mips_regnum (current_gdbarch)->badvaddr 114130803Smarcel || regno == mips_regnum (current_gdbarch)->cause 115130803Smarcel || regno == mips_regnum (current_gdbarch)->fp_implementation_revision 116130803Smarcel || regno == DEPRECATED_FP_REGNUM 117130803Smarcel || (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM)) 118130803Smarcel return; 119130803Smarcel regaddr = register_ptrace_addr (regno); 120130803Smarcel errno = 0; 121130803Smarcel ptrace (PT_WRITE_U, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr, 122130803Smarcel read_register (regno)); 123130803Smarcel if (errno != 0) 124130803Smarcel { 125130803Smarcel sprintf (buf, "writing register number %d", regno); 126130803Smarcel perror_with_name (buf); 127130803Smarcel } 128130803Smarcel } 129130803Smarcel else 130130803Smarcel { 131130803Smarcel for (regno = 0; regno < NUM_REGS; regno++) 132130803Smarcel store_inferior_registers (regno); 133130803Smarcel } 134130803Smarcel} 135130803Smarcel 136130803Smarcel 137130803Smarcel/* Figure out where the longjmp will land. 138130803Smarcel We expect the first arg to be a pointer to the jmp_buf structure from which 139130803Smarcel we extract the pc (JB_PC) that we will land at. The pc is copied into PC. 140130803Smarcel This routine returns true on success. */ 141130803Smarcel 142130803Smarcelint 143130803Smarcelget_longjmp_target (CORE_ADDR *pc) 144130803Smarcel{ 145130803Smarcel CORE_ADDR jb_addr; 146130803Smarcel char *buf; 147130803Smarcel 148130803Smarcel buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT); 149130803Smarcel jb_addr = read_register (A0_REGNUM); 150130803Smarcel 151130803Smarcel if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf, 152130803Smarcel TARGET_PTR_BIT / TARGET_CHAR_BIT)) 153130803Smarcel return 0; 154130803Smarcel 155130803Smarcel *pc = extract_unsigned_integer (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT); 156130803Smarcel 157130803Smarcel return 1; 158130803Smarcel} 159130803Smarcel 160130803Smarcel/* Extract the register values out of the core file and store 161130803Smarcel them where `read_register' will find them. 162130803Smarcel 163130803Smarcel CORE_REG_SECT points to the register values themselves, read into memory. 164130803Smarcel CORE_REG_SIZE is the size of that area. 165130803Smarcel WHICH says which set of registers we are handling (0 = int, 2 = float 166130803Smarcel on machines where they are discontiguous). 167130803Smarcel REG_ADDR is the offset from u.u_ar0 to the register values relative to 168130803Smarcel core_reg_sect. This is used with old-fashioned core files to 169130803Smarcel locate the registers in a large upage-plus-stack ".reg" section. 170130803Smarcel Original upage address X is at location core_reg_sect+x+reg_addr. 171130803Smarcel */ 172130803Smarcel 173130803Smarcelstatic void 174130803Smarcelfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, 175130803Smarcel CORE_ADDR reg_addr) 176130803Smarcel{ 177130803Smarcel int regno; 178130803Smarcel unsigned int addr; 179130803Smarcel int bad_reg = -1; 180130803Smarcel reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */ 181130803Smarcel 182130803Smarcel char zerobuf[MAX_REGISTER_SIZE]; 183130803Smarcel memset (zerobuf, 0, MAX_REGISTER_SIZE); 184130803Smarcel 185130803Smarcel 186130803Smarcel /* If u.u_ar0 was an absolute address in the core file, relativize it now, 187130803Smarcel so we can use it as an offset into core_reg_sect. When we're done, 188130803Smarcel "register 0" will be at core_reg_sect+reg_ptr, and we can use 189130803Smarcel register_addr to offset to the other registers. If this is a modern 190130803Smarcel core file without a upage, reg_ptr will be zero and this is all a big 191130803Smarcel NOP. */ 192130803Smarcel if (reg_ptr > core_reg_size) 193130803Smarcel#ifdef KERNEL_U_ADDR 194130803Smarcel reg_ptr -= KERNEL_U_ADDR; 195130803Smarcel#else 196130803Smarcel error ("Old mips core file can't be processed on this machine."); 197130803Smarcel#endif 198130803Smarcel 199130803Smarcel for (regno = 0; regno < NUM_REGS; regno++) 200130803Smarcel { 201130803Smarcel addr = register_addr (regno, reg_ptr); 202130803Smarcel if (addr >= core_reg_size) 203130803Smarcel { 204130803Smarcel if (bad_reg < 0) 205130803Smarcel bad_reg = regno; 206130803Smarcel } 207130803Smarcel else 208130803Smarcel { 209130803Smarcel supply_register (regno, core_reg_sect + addr); 210130803Smarcel } 211130803Smarcel } 212130803Smarcel if (bad_reg >= 0) 213130803Smarcel { 214130803Smarcel error ("Register %s not found in core file.", REGISTER_NAME (bad_reg)); 215130803Smarcel } 216130803Smarcel supply_register (ZERO_REGNUM, zerobuf); 217130803Smarcel /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */ 218130803Smarcel supply_register (DEPRECATED_FP_REGNUM, zerobuf); 219130803Smarcel} 220130803Smarcel 221130803Smarcel/* Return the address in the core dump or inferior of register REGNO. 222130803Smarcel BLOCKEND is the address of the end of the user structure. */ 223130803Smarcel 224130803SmarcelCORE_ADDR 225130803Smarcelregister_addr (int regno, CORE_ADDR blockend) 226130803Smarcel{ 227130803Smarcel CORE_ADDR addr; 228130803Smarcel 229130803Smarcel if (regno < 0 || regno >= NUM_REGS) 230130803Smarcel error ("Invalid register number %d.", regno); 231130803Smarcel 232130803Smarcel REGISTER_U_ADDR (addr, blockend, regno); 233130803Smarcel 234130803Smarcel return addr; 235130803Smarcel} 236130803Smarcel 237130803Smarcel 238130803Smarcel/* Register that we are able to handle mips core file formats. 239130803Smarcel FIXME: is this really bfd_target_unknown_flavour? */ 240130803Smarcel 241130803Smarcelstatic struct core_fns mips_core_fns = 242130803Smarcel{ 243130803Smarcel bfd_target_unknown_flavour, /* core_flavour */ 244130803Smarcel default_check_format, /* check_format */ 245130803Smarcel default_core_sniffer, /* core_sniffer */ 246130803Smarcel fetch_core_registers, /* core_read_registers */ 247130803Smarcel NULL /* next */ 248130803Smarcel}; 249130803Smarcel 250130803Smarcelvoid 251130803Smarcel_initialize_core_mips (void) 252130803Smarcel{ 253130803Smarcel add_core_fns (&mips_core_fns); 254130803Smarcel} 255