X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fhppab-nat.c;h=29d22ebad4696afa3759bedd9672392f6e9a556c;hb=43841e9116d121fa81a351b66ec9e0821a1b4be8;hp=615b66567acfdf610ac193c64c95bf1da593d108;hpb=e835b5e7fa8a12d8da88917b038b30af9a39ec7d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/hppab-nat.c b/gdb/hppab-nat.c index 615b66567a..29d22ebad4 100644 --- a/gdb/hppab-nat.c +++ b/gdb/hppab-nat.c @@ -6,148 +6,34 @@ Contributed by the Center for Software Science at the University of Utah (pa-gdb-bugs@cs.utah.edu). -This file is part of GDB. + This file is part of GDB. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the 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 of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ #include "defs.h" #include "inferior.h" #include "target.h" #include -#ifdef FIVE_ARG_PTRACE +/* Use an extra level of indirection for ptrace calls. + This lets us breakpoint usefully on call_ptrace. It also + allows us to pass an extra argument to ptrace without + using an ANSI-C specific macro. */ -/* Deal with HPUX 8.0 braindamage. */ -#define ptrace(a,b,c,d) ptrace(a,b,c,d,0) - -#endif - -#ifndef PT_ATTACH -#define PT_ATTACH PTRACE_ATTACH -#endif - -#ifndef PT_DETACH -#define PT_DETACH PTRACE_DETACH -#endif - -/* This function simply calls ptrace with the given arguments. - It exists so that all calls to ptrace are isolated in this - machine-dependent file. */ - -int -call_ptrace (request, pid, addr, data) - int request, pid; - PTRACE_ARG3_TYPE addr; - int data; -{ - return ptrace (request, pid, addr, data); -} - -#ifdef DEBUG_PTRACE -/* For the rest of the file, use an extra level of indirection */ -/* This lets us breakpoint usefully on call_ptrace. */ #define ptrace call_ptrace -#endif - -void -kill_inferior () -{ - if (inferior_pid == 0) - return; - ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0); - wait ((int *)0); - target_mourn_inferior (); -} - -#ifdef ATTACH_DETACH - -/* Start debugging the process whose number is PID. */ -int -attach (pid) - int pid; -{ - errno = 0; - ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 1; - return pid; -} - -/* Stop debugging the process whose number is PID - and continue it with signal number SIGNAL. - SIGNAL = 0 means just continue it. */ - -void -detach (signal) - int signal; -{ - errno = 0; - ptrace (PT_DETACH, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 0; -} -#endif /* ATTACH_DETACH */ - - - -/* KERNEL_U_ADDR is the amount to subtract from u.u_ar0 - to get the offset in the core file of the register values. */ -#if defined (KERNEL_U_ADDR_BSD) -/* Get kernel_u_addr using BSD-style nlist(). */ -CORE_ADDR kernel_u_addr; - -#include /* For struct nlist */ - -void -_initialize_kernel_u_addr () -{ - struct nlist names[2]; - - names[0].n_un.n_name = "_u"; - names[1].n_un.n_name = NULL; - if (nlist ("/vmunix", names) == 0) - kernel_u_addr = names[0].n_value; - else - fatal ("Unable to get kernel u area address."); -} -#endif /* KERNEL_U_ADDR_BSD. */ - -#if defined (KERNEL_U_ADDR_HPUX) -/* Get kernel_u_addr using HPUX-style nlist(). */ -CORE_ADDR kernel_u_addr; - -struct hpnlist { - char * n_name; - long n_value; - unsigned char n_type; - unsigned char n_length; - short n_almod; - short n_unused; -}; -static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }}; - -/* read the value of the u area from the hp-ux kernel */ -void _initialize_kernel_u_addr () -{ - struct user u; - nlist ("/hp-ux", &nl); - kernel_u_addr = nl[0].n_value; -} -#endif /* KERNEL_U_ADDR_HPUX. */ #if !defined (offsetof) #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) @@ -169,7 +55,6 @@ fetch_register (regno) { register unsigned int regaddr; char buf[MAX_REGISTER_RAW_SIZE]; - char mess[128]; /* For messages */ register int i; /* Offset of registers within the u area. */ @@ -186,11 +71,17 @@ fetch_register (regno) regaddr += sizeof (int); if (errno != 0) { - sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno); - perror_with_name (mess); + /* Warning, not error, in case we are attached; sometimes the + kernel doesn't let us at the registers. */ + char *err = safe_strerror (errno); + char *msg = alloca (strlen (err) + 128); + sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err); + warning (msg); + goto error_exit; } } supply_register (regno, buf); +error_exit:; } /* Fetch all registers, or just one, from the child process. */ @@ -216,164 +107,109 @@ store_inferior_registers (regno) { register unsigned int regaddr; char buf[80]; - extern char registers[]; register int i; - unsigned int offset = U_REGS_OFFSET; + int scratch; if (regno >= 0) { + if (CANNOT_STORE_REGISTER (regno)) + return; regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + errno = 0; + if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM) { - errno = 0; + scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3; ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, - *(int *) ®isters[REGISTER_BYTE (regno) + i]); + scratch); if (errno != 0) { - sprintf (buf, "writing register number %d(%d)", regno, i); + /* Error, even if attached. Failing to write these two + registers is pretty serious. */ + sprintf (buf, "writing register number %d", regno); perror_with_name (buf); } - regaddr += sizeof(int); } + else + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) + { + errno = 0; + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i]); + if (errno != 0) + { + /* Warning, not error, in case we are attached; sometimes the + kernel doesn't let us at the registers. */ + char *err = safe_strerror (errno); + char *msg = alloca (strlen (err) + 128); + sprintf (msg, "writing register %s: %s", + REGISTER_NAME (regno), err); + warning (msg); + return; + } + regaddr += sizeof (int); + } } else - { - for (regno = 0; regno < NUM_REGS; regno++) - { - if (CANNOT_STORE_REGISTER (regno)) - continue; - regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) - { - errno = 0; - ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, - *(int *) ®isters[REGISTER_BYTE (regno) + i]); - if (errno != 0) - { - sprintf (buf, "writing register number %d(%d)", regno, i); - perror_with_name (buf); - } - regaddr += sizeof(int); - } - } - } - return; + for (regno = 0; regno < NUM_REGS; regno++) + store_inferior_registers (regno); } -/* Resume execution of the inferior process. - If STEP is nonzero, single-step it. - If SIGNAL is nonzero, give it that signal. */ +/* PT_PROT is specific to the PA BSD kernel and isn't documented + anywhere (except here). -void -child_resume (step, signal) - int step; - int signal; -{ - errno = 0; + PT_PROT allows one to enable/disable the data memory break bit + for pages of memory in an inferior process. This bit is used + to cause "Data memory break traps" to occur when the appropriate + page is written to. - /* An address of (PTRACE_ARG3_TYPE) 1 tells ptrace to continue from where - it was. (If GDB wanted it to start some other way, we have already - written a new PC value to the child.) */ + The arguments are as follows: - if (step) - ptrace (PT_STEP, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); - else - ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal); + PT_PROT -- The ptrace action to perform. - if (errno) - perror_with_name ("ptrace"); -} + INFERIOR_PID -- The pid of the process who's page table entries + will be modified. -/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory - in the NEW_SUN_PTRACE case. - It ought to be straightforward. But it appears that writing did - not write the data that I specified. I cannot understand where - it got the data that it actually did write. */ - -/* Copy LEN bytes to or from inferior's memory starting at MEMADDR - to debugger memory starting at MYADDR. Copy to inferior if - WRITE is nonzero. - - Returns the length copied, which is either the LEN argument or zero. - This xfer function does not do partial moves, since child_ops - doesn't allow memory operations to cross below us in the target stack - anyway. */ + PT_ARGS -- The *address* of a 3 word block of memory which has + additional information: -int -child_xfer_memory (memaddr, myaddr, len, write, target) - CORE_ADDR memaddr; - char *myaddr; - int len; - int write; - struct target_ops *target; /* ignored */ -{ - register int i; - /* Round starting address down to longword boundary. */ - register CORE_ADDR addr = memaddr & - sizeof (int); - /* Round ending address up; get number of longwords that makes. */ - register int count - = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); - /* Allocate buffer of that many longwords. */ - register int *buffer = (int *) alloca (count * sizeof (int)); - - if (write) - { - /* Fill start and end extra bytes of buffer with existing memory data. */ + word 0 -- The start address to watch. This should be a page-aligned + address. - if (addr != memaddr || len < (int)sizeof (int)) { - /* Need part of initial word -- fetch it. */ - buffer[0] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, - 0); - } + word 1 -- The ending address to watch. Again, this should be a + page aligned address. - if (count > 1) /* FIXME, avoid if even boundary */ - { - buffer[count - 1] - = ptrace (PT_READ_I, inferior_pid, - (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (int)), - 0); - } + word 2 -- Nonzero to enable the data memory break bit on the + given address range or zero to disable the data memory break + bit on the given address range. - /* Copy data to be written over corresponding part of buffer */ + This call may fail if the given addresses are not valid in the inferior + process. This most often happens when restarting a program which + as watchpoints inserted on heap or stack memory. */ - bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); +#define PT_PROT 21 - /* Write the entire buffer. */ +int +hppa_set_watchpoint (addr, len, flag) + int addr, len, flag; +{ + int pt_args[3]; + pt_args[0] = addr; + pt_args[1] = addr + len; + pt_args[2] = flag; - for (i = 0; i < count; i++, addr += sizeof (int)) - { - errno = 0; - ptrace (PT_WRITE_D, inferior_pid, (PTRACE_ARG3_TYPE) addr, - buffer[i]); - if (errno) - { - /* Using the appropriate one (I or D) is necessary for - Gould NP1, at least. */ - errno = 0; - ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, - buffer[i]); - } - if (errno) - return 0; - } - } - else - { - /* Read all the longwords */ - for (i = 0; i < count; i++, addr += sizeof (int)) - { - errno = 0; - buffer[i] = ptrace (PT_READ_I, inferior_pid, - (PTRACE_ARG3_TYPE) addr, 0); - if (errno) - return 0; - QUIT; - } + /* Mask off the lower 12 bits since we want to work on a page basis. */ + pt_args[0] >>= 12; + pt_args[1] >>= 12; - /* Copy appropriate bytes out of the buffer. */ - bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); - } - return len; -} + /* Rounding adjustments. */ + pt_args[1] -= pt_args[0]; + pt_args[1]++; + /* Put the lower 12 bits back as zero. */ + pt_args[0] <<= 12; + pt_args[1] <<= 12; + + /* Do it. */ + return ptrace (PT_PROT, inferior_pid, (PTRACE_ARG3_TYPE) pt_args, 0); +}