aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Gilmore <gnu@cygnus>1992-09-26 10:27:10 +0000
committerJohn Gilmore <gnu@cygnus>1992-09-26 10:27:10 +0000
commitfb1415aebefaf9091dc268a47045c832a8778622 (patch)
treece0a3fb902212aa79749d7c674bda552ee4e8048
parente0ba1d1427d48b62a92a475ffe15eca42376b49a (diff)
downloadgdb-fb1415aebefaf9091dc268a47045c832a8778622.zip
gdb-fb1415aebefaf9091dc268a47045c832a8778622.tar.gz
gdb-fb1415aebefaf9091dc268a47045c832a8778622.tar.bz2
Rename all HPPA files to fit into unique DOS filenames:
*hppabsd* => *hppab* *hppahpux* => *hppah*
-rw-r--r--gdb/hppab-core.c251
-rw-r--r--gdb/hppab-tdep.c1422
-rw-r--r--gdb/hppab-xdep.c406
-rw-r--r--gdb/hppah-tdep.c1427
-rw-r--r--gdb/hppah-xdep.c417
-rw-r--r--gdb/tm-hppab.h6
-rw-r--r--gdb/tm-hppah.h39
-rw-r--r--gdb/xm-hppab.h48
-rw-r--r--gdb/xm-hppah.h52
9 files changed, 4068 insertions, 0 deletions
diff --git a/gdb/hppab-core.c b/gdb/hppab-core.c
new file mode 100644
index 0000000..5ca5f9b
--- /dev/null
+++ b/gdb/hppab-core.c
@@ -0,0 +1,251 @@
+/* Machine-dependent code which would otherwise be in core.c
+ for GDB, the GNU debugger. This code is for the HP PA-RISC cpu.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#ifndef hpux
+#include <a.out.h>
+#include <machine/pcb.h>
+#include <sys/time.h>
+#include "/usr/src/sys/hpux/hpux.h"
+#define USRSTACK 0x68FF3000
+#else
+#include <sys/user.h> /* After a.out.h */
+#endif
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+
+#ifndef hpux
+#undef USIZE
+#undef UPAGES
+
+#define USIZE 3
+#define UPAGES 7
+#endif
+
+extern int errno;
+
+/* File names of core file and executable file. */
+
+extern char *corefile;
+extern char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+ Note that the execchan is closed when an inferior is created
+ and reopened if the inferior dies or is killed. */
+
+extern int corechan;
+extern int execchan;
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+extern CORE_ADDR data_start;
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+extern struct header file_hdr;
+extern struct som_exec_auxhdr exec_hdr;
+
+extern int (*core_file_hook)();
+
+#ifdef KERNELDEBUG
+
+extern int kernel_debugging;
+extern int kernel_core_file_hook();
+
+#endif
+
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+#ifdef KERNELDEBUG
+ struct stat stb;
+#endif
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+ core_file_hook = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+
+#ifdef KERNELDEBUG
+ fstat(corechan, &stb);
+
+ if (kernel_debugging) {
+ setup_kernel_debugging();
+ core_file_hook = kernel_core_file_hook;
+ set_kernel_boundaries();
+ } else if ((stb.st_mode & S_IFMT) == S_IFCHR &&
+ stb.st_rdev == makedev(2, 1)) {
+ /* looking at /dev/kmem */
+ data_offset = data_start = KERNBASE;
+ data_end = ~0; /* XXX */
+ stack_end = stack_start = data_end;
+ set_kernel_boundaries();
+ } else
+#endif
+ {
+ /* HP PA-RISC style corefile. */
+#ifndef hpux
+ struct hpuxuser u;
+#else
+ struct user u;
+#endif
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+
+ /* We are depending on exec_file_command having been called
+ previously to set exec_data_start. Since the executable
+ and the core file share the same text segment, the address
+ of the data segment will be the same in both. */
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = USRSTACK; /* from sys/param.h */
+ stack_end = stack_start + NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = NBPG * USIZE;
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ unsigned char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ buf[3] &= ~0x3;
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
diff --git a/gdb/hppab-tdep.c b/gdb/hppab-tdep.c
new file mode 100644
index 0000000..8fe6d28
--- /dev/null
+++ b/gdb/hppab-tdep.c
@@ -0,0 +1,1422 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+ for GDB, the GNU debugger. This code is for the HP PA-RISC cpu.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+
+/* For argument passing to the inferior */
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+/*#include <sys/user.h> After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+
+#ifdef KERNELDEBUG
+#include <sys/vmmac.h>
+#include <machine/machparam.h>
+#include <machine/vmparam.h>
+#include <machine/pde.h>
+#include <machine/cpu.h>
+#include <machine/iomod.h>
+#include <machine/pcb.h>
+#include <machine/rpb.h>
+#include <ctype.h>
+
+extern int kernel_debugging;
+extern CORE_ADDR startup_file_start;
+extern CORE_ADDR startup_file_end;
+
+#define KERNOFF ((unsigned)KERNBASE)
+#define INKERNEL(x) ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
+
+static int ok_to_cache();
+static void set_kernel_boundaries();
+
+int devmem = 0;
+int vtophys_ready = 0;
+int kerneltype;
+#define OS_BSD 1
+#define OS_MACH 2
+#endif
+
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+extern int errno;
+
+
+
+
+
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+/* extern CORE_ADDR data_start; */
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+struct header file_hdr;
+struct som_exec_auxhdr exec_hdr;
+
+#ifdef KERNELDEBUG
+/*
+ * Kernel debugging routines.
+ */
+
+static struct pcb pcb;
+static struct pde *pdir;
+static struct hte *htbl;
+static u_int npdir, nhtbl;
+
+static CORE_ADDR
+ksym_lookup(name)
+ char *name;
+{
+ struct symbol *sym;
+ int i;
+
+ if ((i = lookup_misc_func(name)) < 0)
+ error("kernel symbol `%s' not found.", name);
+
+ return (misc_function_vector[i].address);
+}
+
+/*
+ * (re-)set the variables that tell "inside_entry_file" where to end
+ * a stack backtrace.
+ */
+void
+set_kernel_boundaries()
+{
+ switch (kerneltype) {
+ case OS_MACH:
+ startup_file_start = ksym_lookup("$syscall");
+ startup_file_end = ksym_lookup("trap");
+ break;
+ case OS_BSD:
+ startup_file_start = ksym_lookup("syscallinit");
+ startup_file_end = ksym_lookup("$syscallexit");
+ break;
+ }
+}
+
+/*
+ * return true if 'len' bytes starting at 'addr' can be read out as
+ * longwords and/or locally cached (this is mostly for memory mapped
+ * i/o register access when debugging remote kernels).
+ */
+static int
+ok_to_cache(addr, len)
+{
+ static CORE_ADDR ioptr;
+
+ if (! ioptr)
+ ioptr = ksym_lookup("ioptr");
+
+ if (addr >= ioptr && addr < SPA_HIGH)
+ return (0);
+
+ return (1);
+}
+
+static
+physrd(addr, dat, len)
+ u_int addr;
+ char *dat;
+{
+ if (lseek(corechan, addr, L_SET) == -1)
+ return (-1);
+ if (read(corechan, dat, len) != len)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * When looking at kernel data space through /dev/mem or with a core file, do
+ * virtual memory mapping.
+ */
+static CORE_ADDR
+vtophys(space, addr)
+ unsigned space;
+ CORE_ADDR addr;
+{
+ struct pde *pptr;
+ u_int hindx, vpageno, ppageno;
+ CORE_ADDR phys = ~0;
+
+ if (!vtophys_ready) {
+ phys = addr; /* XXX for kvread */
+ } else if (kerneltype == OS_BSD) {
+ /* make offset into a virtual page no */
+ vpageno = btop(addr);
+ /*
+ * Determine index into hash table, initialize pptr to this
+ * entry (since first word of pte & hte are same), and set
+ * physical page number for first entry in chain.
+ */
+ hindx = pdirhash(space, addr) & (nhtbl-1);
+ pptr = (struct pde *) &htbl[hindx];
+ ppageno = pptr->pde_next;
+ while (1) {
+ if (pptr->pde_end)
+ break;
+ pptr = &pdir[ppageno];
+ /*
+ * If space id & virtual page number match, return
+ * "next PDIR entry of previous PDIR entry" as the
+ * physical page or'd with offset into page.
+ */
+ if (pptr->pde_space == space &&
+ pptr->pde_page == vpageno) {
+ phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
+ (addr & PGOFSET));
+ break;
+ }
+ ppageno = pptr->pde_next;
+ }
+ }
+#ifdef MACHKERNELDEBUG
+ else if (kerneltype == OS_MACH) {
+ mach_vtophys(space, addr, &phys);
+ }
+#endif
+#if 0
+ printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
+#endif
+ return (phys);
+}
+
+static
+kvread(addr)
+ CORE_ADDR addr;
+{
+ CORE_ADDR paddr;
+
+ paddr = vtophys(0, addr);
+ if (paddr != ~0)
+ if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
+ return (addr);
+
+ return (~0);
+}
+
+static void
+read_pcb(addr)
+ u_int addr;
+{
+ int i, off;
+ extern char registers[];
+ static int reg2pcb[] = {
+ /* RPB */
+ -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
+ 71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /* BSD */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
+ 36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100,
+ /* Mach */
+ -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
+ 25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
+ 21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
+ 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 44, 46, 48
+ };
+ static struct rpb *rpbaddr = (struct rpb *) 0;
+ static u_int rpbpcbaddr = 0;
+
+ if (!remote_debugging) {
+ /*
+ * If we are debugging a post-mortem and this is the first
+ * call of read_pcb, read the RPB. Also assoicate the
+ * thread/proc running at the time with the RPB.
+ */
+ if (!devmem && rpbpcbaddr == 0) {
+ CORE_ADDR raddr = ksym_lookup("rpb");
+ int usepcb = 1;
+
+ if (raddr != ~0) {
+ rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
+ if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
+ rpbpcbaddr = addr;
+ usepcb = 0;
+ }
+ }
+ if (usepcb) {
+ error("cannot read rpb, using pcb for registers\n");
+ if (rpbaddr)
+ free((char *)rpbaddr);
+ rpbpcbaddr = ~0;
+ }
+ }
+ if (physrd (addr, (char *)&pcb, sizeof pcb))
+ error ("cannot read pcb at %x.\n", addr);
+ } else {
+ if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
+ error ("cannot read pcb at %x.\n", addr);
+ }
+
+ if (kerneltype == OS_BSD) {
+ printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
+ pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
+ off = NUM_REGS;
+ } else {
+ printf("pcb %lx psw %lx ksp %lx\n",
+ addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
+ off = NUM_REGS * 2;
+ }
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ bzero(registers, REGISTER_BYTES);
+ for (i = 0; i < NUM_REGS; ++i)
+ if (reg2pcb[i+off] != -1)
+ supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
+ /*
+ * If the RPB is valid for this thread/proc use the register values
+ * contained there.
+ */
+ if (addr == rpbpcbaddr) {
+ off = 0;
+ for (i = 0; i < NUM_REGS; ++i)
+ if (reg2pcb[i+off] != -1)
+ supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
+ }
+}
+
+void
+setup_kernel_debugging()
+{
+ struct stat stb;
+ CORE_ADDR addr;
+
+ fstat(corechan, &stb);
+ devmem = 0;
+ if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
+ devmem = 1;
+
+ /* XXX */
+ if (lookup_misc_func("Sysmap") < 0)
+ kerneltype = OS_MACH;
+ else
+ kerneltype = OS_BSD;
+
+ if (kerneltype == OS_BSD) {
+ int len, err = 0;
+
+ /*
+ * Hash table and PDIR are equivalently mapped
+ */
+ nhtbl = kvread(ksym_lookup("nhtbl"));
+ if (nhtbl != ~0) {
+ len = nhtbl * sizeof(*htbl);
+ htbl = (struct hte *) malloc(len);
+ if (htbl) {
+ addr = kvread(ksym_lookup("htbl"));
+ if (physrd(addr, (char *)htbl, len))
+ err++;
+ } else
+ err++;
+ } else
+ err++;
+ npdir = kvread(ksym_lookup("npdir"));
+ if (npdir != ~0) {
+ len = npdir * sizeof(*pdir);
+ pdir = (struct pde *) malloc(len);
+ if (pdir) {
+ addr = kvread(ksym_lookup("pdir"));
+ if (physrd(addr, (char *)pdir, len))
+ err++;
+ } else
+ err++;
+ } else
+ err++;
+ if (err) {
+ error("cannot read PDIR/HTBL");
+ return;
+ }
+ vtophys_ready = 1;
+
+ /*
+ * pcb where "panic" saved registers in first thing in
+ * current u-area. The current u-area is pointed to by
+ * "uptr".
+ */
+ addr = kvread(ksym_lookup("uptr"));
+ if (addr == ~0) {
+ error("cannot read current u-area address");
+ return;
+ }
+ read_pcb(vtophys(0, addr)); /* XXX space */
+ if (!devmem) {
+ /* find stack frame */
+ CORE_ADDR panicstr;
+ char buf[256];
+ register char *cp;
+
+ panicstr = kvread(ksym_lookup("panicstr"));
+ if (panicstr == ~0)
+ return;
+ kernel_core_file_hook(panicstr, buf, sizeof(buf));
+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+ if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+ *cp = '?';
+ if (*cp)
+ *cp = '\0';
+ printf("panic: %s\n", buf);
+ }
+ }
+#ifdef MACHKERNELDEBUG
+ else {
+ int *thread;
+
+ /*
+ * Set up address translation
+ */
+ if (mach_vtophys_init() == 0) {
+ error("cannot initialize vtophys for Mach");
+ return;
+ }
+ vtophys_ready = 1;
+
+ /*
+ * Locate active thread and read PCB
+ * XXX MAJOR HACK
+ * - assumes uni-processor
+ * - assumes position of pcb to avoid mach includes
+ */
+ thread = (int *)kvread(ksym_lookup("active_threads"));
+ addr = kvread(&thread[9]); /* XXX: pcb addr */
+ read_pcb(vtophys(0, addr));
+ }
+#endif
+}
+
+vtop_command(arg)
+ char *arg;
+{
+ u_int sp, off, pa;
+
+ if (!arg)
+ error_no_arg("kernel virtual address");
+ if (!kernel_debugging)
+ error("not debugging kernel");
+
+ sp = 0; /* XXX */
+ off = (u_int) parse_and_eval_address(arg);
+ pa = vtophys(sp, off);
+ printf("%lx.%lx -> ", sp, off);
+ if (pa == ~0)
+ printf("<invalid>\n");
+ else
+ printf("%lx\n", pa);
+}
+
+set_paddr_command(arg)
+ char *arg;
+{
+ u_int addr;
+
+ if (!arg) {
+ if (kerneltype == OS_BSD)
+ error_no_arg("ps-style address for new process");
+ else
+ error_no_arg("thread structure virtual address");
+ }
+ if (!kernel_debugging)
+ error("not debugging kernel");
+
+ addr = (u_int) parse_and_eval_address(arg);
+ if (kerneltype == OS_BSD)
+ addr = ctob(addr);
+ else {
+ addr = kvread(&(((int *)addr)[9])); /* XXX: pcb addr */
+ addr = vtophys(0, addr); /* XXX space */
+ }
+ read_pcb(addr);
+
+ flush_cached_frames();
+ set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
+ select_frame(get_current_frame(), 0);
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+kernel_core_file_hook(addr, buf, len)
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+
+ while (len > 0) {
+ paddr = vtophys(0, addr); /* XXX space */
+ if (paddr == ~0) {
+ bzero(buf, len);
+ return (1);
+ }
+ /* we can't read across a page boundary */
+ i = min(len, NBPG - (addr & PGOFSET));
+ if (physrd(paddr, buf, i)) {
+ bzero(buf, len);
+ return (1);
+ }
+ buf += i;
+ addr += i;
+ len -= i;
+ }
+ return (0);
+}
+#endif
+
+
+
+
+
+/* Routines to extract various sized constants out of hppa
+ instructions. */
+
+/* This assumes that no garbage lies outside of the lower bits of
+ value. */
+
+int
+sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)(val >> bits - 1 ? (-1 << bits) | val : val);
+}
+
+/* For many immediate values the sign bit is the low bit! */
+
+int
+low_sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
+}
+/* extract the immediate field from a ld{bhw}s instruction */
+
+
+
+unsigned
+get_field (val, from, to)
+ unsigned val, from, to;
+{
+ val = val >> 31 - to;
+ return val & ((1 << 32 - from) - 1);
+}
+
+unsigned
+set_field (val, from, to, new_val)
+ unsigned *val, from, to;
+{
+ unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
+ return *val = *val & mask | (new_val << (31 - from));
+}
+
+/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
+
+extract_3 (word)
+ unsigned word;
+{
+ return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+
+extract_5_load (word)
+ unsigned word;
+{
+ return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* extract the immediate field from a st{bhw}s instruction */
+
+int
+extract_5_store (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_5, 5);
+}
+
+/* extract an 11 bit immediate field */
+
+int
+extract_11 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_11, 11);
+}
+
+/* extract a 14 bit immediate field */
+
+int
+extract_14 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_14, 14);
+}
+
+/* deposit a 14 bit constant in a word */
+
+unsigned
+deposit_14 (opnd, word)
+ int opnd;
+ unsigned word;
+{
+ unsigned sign = (opnd < 0 ? 1 : 0);
+
+ return word | ((unsigned)opnd << 1 & MASK_14) | sign;
+}
+
+/* extract a 21 bit constant */
+
+int
+extract_21 (word)
+ unsigned word;
+{
+ int val;
+
+ word &= MASK_21;
+ word <<= 11;
+ val = GET_FIELD (word, 20, 20);
+ val <<= 11;
+ val |= GET_FIELD (word, 9, 19);
+ val <<= 2;
+ val |= GET_FIELD (word, 5, 6);
+ val <<= 5;
+ val |= GET_FIELD (word, 0, 4);
+ val <<= 2;
+ val |= GET_FIELD (word, 7, 8);
+ return sign_extend (val, 21) << 11;
+}
+
+/* deposit a 21 bit constant in a word. Although 21 bit constants are
+ usually the top 21 bits of a 32 bit constant, we assume that only
+ the low 21 bits of opnd are relevant */
+
+unsigned
+deposit_21 (opnd, word)
+ unsigned opnd, word;
+{
+ unsigned val = 0;
+
+ val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+ val <<= 11;
+ val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+ val <<= 1;
+ val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+ return word | val;
+}
+
+/* extract a 12 bit constant from branch instructions */
+
+int
+extract_12 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ (word & 0x1) << 11, 12) << 2;
+}
+
+/* extract a 17 bit constant from branch instructions, returning the
+ 19 bit signed value. */
+
+int
+extract_17 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ GET_FIELD (word, 11, 15) << 11 |
+ (word & 0x1) << 16, 17) << 2;
+}
+
+
+CORE_ADDR
+frame_saved_pc (frame)
+ FRAME frame;
+{
+ if (get_current_frame () == frame)
+ {
+ struct frame_saved_regs saved_regs;
+
+ get_frame_saved_regs (frame, &saved_regs);
+ if (saved_regs.regs[RP_REGNUM])
+ return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+ else
+ return read_register (RP_REGNUM);
+ }
+ return read_memory_integer (frame->frame - 20, 4) & ~0x3;
+}
+
+/* To see if a frame chain is valid, see if the caller looks like it
+ was compiled with gcc. */
+
+int frame_chain_valid (chain, thisframe)
+ FRAME_ADDR chain;
+ FRAME thisframe;
+{
+ if (chain && (chain > 0x60000000
+ /* || remote_debugging -this is no longer used */
+#ifdef KERNELDEBUG
+ || kernel_debugging
+#endif
+ ))
+ {
+ CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
+
+ if (!inside_entry_file (pc))
+ return 0;
+ /* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
+ if (read_memory_integer (pc, 4) == 0x6BC23FD9)
+ pc = pc + 4;
+
+ if (read_memory_integer (pc, 4) == 0x8040241 &&
+ read_memory_integer (pc + 4, 4) == 0x81E0244)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+/* Some helper functions. gcc_p returns 1 if the function beginning at
+ pc appears to have been compiled with gcc. hpux_cc_p returns 1 if
+ fn was compiled with hpux cc. gcc functions look like :
+
+ stw rp,-0x14(sp) ; optional
+ or r4,r0,r1
+ or sp,r0,r4
+ stwm r1,framesize(sp)
+
+ hpux cc functions look like:
+
+ stw rp,-0x14(sp) ; optional.
+ stwm r3,framesiz(sp)
+ */
+
+gcc_p (pc)
+ CORE_ADDR pc;
+{
+ if (read_memory_integer (pc, 4) == 0x6BC23FD9)
+ pc = pc + 4;
+
+ if (read_memory_integer (pc, 4) == 0x8040241 &&
+ read_memory_integer (pc + 4, 4) == 0x81E0244)
+ return 1;
+ return 0;
+}
+
+
+find_dummy_frame_regs (frame, frame_saved_regs)
+ struct frame_info *frame;
+ struct frame_saved_regs *frame_saved_regs;
+{
+ CORE_ADDR fp = frame->frame;
+ int i;
+
+ frame_saved_regs->regs[RP_REGNUM] = fp - 20 & ~0x3;
+ frame_saved_regs->regs[FP_REGNUM] = fp;
+ frame_saved_regs->regs[1] = fp + 8;
+ frame_saved_regs->regs[3] = fp + 12;
+ for (fp += 16, i = 3; i < 30; fp += 4, i++)
+ frame_saved_regs->regs[i] = fp;
+ frame_saved_regs->regs[31] = fp;
+ fp += 4;
+ for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+ frame_saved_regs->regs[i] = fp;
+ /* depend on last increment of fp */
+ frame_saved_regs->regs[IPSW_REGNUM] = fp - 4;
+ frame_saved_regs->regs[SAR_REGNUM] = fp;
+ fp += 4;
+ frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp;
+ frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp;
+}
+
+CORE_ADDR
+hp_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ /* array of arguments' offsets */
+ int *offset = (int *)alloca(nargs);
+ int cum = 0;
+ int i, alignment;
+
+ for (i = 0; i < nargs; i++)
+ {
+ cum += TYPE_LENGTH (VALUE_TYPE (args[i]));
+ /* value must go at proper alignment. Assume alignment is a
+ power of two.*/
+ alignment = hp_alignof (VALUE_TYPE (args[i]));
+ if (cum % alignment)
+ cum = (cum + alignment) & -alignment;
+ offset[i] = -cum;
+ }
+ for (i == 0; i < nargs; i++)
+ {
+ write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int));
+ }
+ sp += min ((cum + 7) & -8, 48);
+ if (struct_return)
+ write_register (28, struct_addr);
+ return sp + 48;
+}
+
+/* return the alignment of a type in bytes. Structures have the maximum
+ alignment required by their fields. */
+
+int
+hp_alignof (arg)
+ struct type *arg;
+{
+ int max_align, align, i;
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ return TYPE_LENGTH (arg);
+ case TYPE_CODE_ARRAY:
+ return hp_alignof (TYPE_FIELD_TYPE (arg, 0));
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ max_align = 2;
+ for (i = 0; i < TYPE_NFIELDS (arg); i++)
+ {
+ /* Bit fields have no real alignment. */
+ if (!TYPE_FIELD_BITPOS (arg, i))
+ {
+ align = hp_alignof (TYPE_FIELD_TYPE (arg, i));
+ max_align = max (max_align, align);
+ }
+ }
+ return max_align;
+ default:
+ return 4;
+ }
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+pa_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ char raw_regs [REGISTER_BYTES];
+ int i;
+
+ for (i = 0; i < NUM_REGS; i++)
+ read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+ if (regnum = -1)
+ pa_print_registers (raw_regs, regnum);
+ else if (regnum < FP0_REGNUM)
+ {
+ printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs +
+ REGISTER_BYTE (regnum)));
+ }
+ else
+ pa_print_fp_reg (regnum);
+}
+
+pa_print_registers (raw_regs, regnum)
+ char *raw_regs;
+ int regnum;
+{
+ int i;
+
+ for (i = 0; i < 18; i++)
+ printf ("%8.8s: %8x %8.8s: %8x %8.8s: %8x %8.8s: %8x\n",
+ reg_names[i],
+ *(int *)(raw_regs + REGISTER_BYTE (i)),
+ reg_names[i + 18],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 18)),
+ reg_names[i + 36],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 36)),
+ reg_names[i + 54],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 54)));
+ for (i = 72; i < NUM_REGS; i++)
+ pa_print_fp_reg (i);
+}
+
+pa_print_fp_reg (i)
+ int i;
+{
+ unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ REGISTER_TYPE val;
+
+ /* Get the data in raw format, then convert also to virtual format. */
+ read_relative_register_raw_bytes (i, raw_buffer);
+ REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
+
+ fputs_filtered (reg_names[i], stdout);
+ print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0,
+ 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+
+}
+
+/*
+ * Virtual to physical translation routines for Utah's Mach 3.0
+ */
+#ifdef MACHKERNELDEBUG
+
+#define STATIC
+
+#if 0 /* too many includes to resolve, too much crap */
+#include <kern/queue.h>
+#include <vm/pmap.h>
+#include <mach/vm_prot.h>
+#else
+/* queue.h */
+struct queue_entry {
+ struct queue_entry *next; /* next element */
+ struct queue_entry *prev; /* previous element */
+};
+
+typedef struct queue_entry *queue_t;
+typedef struct queue_entry queue_head_t;
+typedef struct queue_entry queue_chain_t;
+typedef struct queue_entry *queue_entry_t;
+
+/* pmap.h */
+#define HP800_HASHSIZE 1024
+#define HP800_HASHSIZE_LOG2 10
+
+#define pmap_hash(space, offset) \
+ (((unsigned) (space) << 5 ^ \
+ ((unsigned) (offset) >> 19 | (unsigned) (space) << 13) ^ \
+ (unsigned) (offset) >> 11) & (HP800_HASHSIZE-1))
+
+struct mapping {
+ queue_head_t hash_link; /* hash table links */
+ queue_head_t phys_link; /* for mappings of a given PA */
+ space_t space; /* virtual space */
+ unsigned offset; /* virtual page number */
+ unsigned tlbpage; /* physical page (for TLB load) */
+ unsigned tlbprot; /* prot/access rights (for TLB load) */
+ struct pmap *pmap; /* pmap mapping belongs to */
+};
+
+struct phys_entry {
+ queue_head_t phys_link; /* head of mappings of a given PA */
+ struct mapping *writer; /* mapping with R/W access */
+ unsigned tlbprot; /* TLB format protection */
+};
+
+#endif
+
+#define atop(a) ((unsigned)(a) >> 11)
+#define ptoa(p) ((unsigned)(p) << 11)
+#define trunc_page(a) ((unsigned)(a) & ~2047)
+
+STATIC long equiv_end;
+STATIC queue_head_t *Ovtop_table, *vtop_table, *Ofree_mapping, free_mapping;
+STATIC struct phys_entry *Ophys_table, *phys_table;
+STATIC long vm_last_phys, vm_first_phys;
+STATIC struct mapping *firstmap, *lastmap, *Omap_table, *map_table;
+STATIC unsigned Omlow, Omhigh, Omhead, Ovlow, Ovhigh, Oplow, Ophigh;
+STATIC unsigned mlow, mhigh, mhead, vlow, vhigh, plow, phigh;
+STATIC int vtopsize, physsize, mapsize;
+STATIC int kmemfd;
+
+#define IS_OVTOPPTR(p) ((unsigned)(p) >= Ovlow && (unsigned)(p) < Ovhigh)
+#define IS_OMAPPTR(p) ((unsigned)(p) >= Omlow && (unsigned)(p) < Omhigh)
+#define IS_OPHYSPTR(p) ((unsigned)(p) >= Oplow && (unsigned)(p) < Ophigh)
+#define IS_VTOPPTR(p) ((unsigned)(p) >= vlow && (unsigned)(p) < vhigh)
+#define IS_MAPPTR(p) ((unsigned)(p) >= mlow && (unsigned)(p) < mhigh)
+#define IS_PHYSPTR(p) ((unsigned)(p) >= plow && (unsigned)(p) < phigh)
+
+struct mapstate {
+ char unused;
+ char flags;
+ short hashix;
+ short physix;
+} *mapstate;
+
+/* flags */
+#define M_ISFREE 1
+#define M_ISHASH 2
+#define M_ISPHYS 4
+
+mach_vtophys_init()
+{
+ int errors = 0;
+
+ if (!readdata())
+ errors++;
+ if (!verifydata())
+ errors++;
+ if (!errors)
+ return(1);
+ fflush(stdout);
+ fprintf(stderr,
+ "translate: may not be able to translate all addresses\n");
+ return(0);
+}
+
+mach_vtophys(space, off, pa)
+ unsigned space, off, *pa;
+{
+ register int i;
+ register queue_t qp;
+ register struct mapping *mp;
+ int poff;
+
+ /*
+ * Kernel IO or equivilently mapped, one to one.
+ */
+ if (space == 0 && (long)off < equiv_end) {
+ *pa = off;
+ return(1);
+ }
+ /*
+ * Else look it up in specified space
+ */
+ poff = off - trunc_page(off);
+ off = trunc_page(off);
+ qp = &vtop_table[pmap_hash(space, off)];
+ for (mp = (struct mapping *)qp->next;
+ qp != (queue_entry_t)mp;
+ mp = (struct mapping *)mp->hash_link.next) {
+ if (mp->space == space && mp->offset == off) {
+ *pa = (mp->tlbpage << 7) | poff;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+STATIC
+readdata()
+{
+ char *tmp, *mach_malloc();
+ long size;
+
+ /* easy scalars */
+ mach_read("equiv_end", ~0, (char *)&equiv_end, sizeof equiv_end);
+ mach_read("vm_first_phys", ~0,
+ (char *)&vm_first_phys, sizeof vm_first_phys);
+ mach_read("vm_last_phys", ~0,
+ (char *)&vm_last_phys, sizeof vm_last_phys);
+ mach_read("firstmap", ~0, (char *)&firstmap, sizeof firstmap);
+ mach_read("lastmap", ~0, (char *)&lastmap, sizeof lastmap);
+
+ /* virtual to physical hash table */
+ vtopsize = HP800_HASHSIZE;
+ size = vtopsize * sizeof(queue_head_t);
+ tmp = mach_malloc("vtop table", size);
+ mach_read("vtop_table", ~0, (char *)&Ovtop_table, sizeof Ovtop_table);
+ mach_read("vtop table", (CORE_ADDR)Ovtop_table, tmp, size);
+ vtop_table = (queue_head_t *) tmp;
+
+ /* inverted page table */
+ physsize = atop(vm_last_phys - vm_first_phys);
+ size = physsize * sizeof(struct phys_entry);
+ tmp = mach_malloc("phys table", size);
+ mach_read("phys_table", ~0, (char *)&Ophys_table, sizeof Ophys_table);
+ mach_read("phys table", (CORE_ADDR)Ophys_table, tmp, size);
+ phys_table = (struct phys_entry *) tmp;
+
+ /* mapping structures */
+ Ofree_mapping = (queue_head_t *) ksym_lookup("free_mapping");
+ mach_read("free mapping", (CORE_ADDR)Ofree_mapping,
+ (char *) &free_mapping, sizeof free_mapping);
+ Omap_table = firstmap;
+ mapsize = lastmap - firstmap;
+ size = mapsize * sizeof(struct mapping);
+ tmp = mach_malloc("mapping table", size);
+ mach_read("mapping table", (CORE_ADDR)Omap_table, tmp, size);
+ map_table = (struct mapping *) tmp;
+
+ /* set limits */
+ Ovlow = (unsigned) Ovtop_table;
+ Ovhigh = (unsigned) &Ovtop_table[vtopsize];
+ Oplow = (unsigned) Ophys_table;
+ Ophigh = (unsigned) &Ophys_table[physsize];
+ Omhead = (unsigned) Ofree_mapping;
+ Omlow = (unsigned) firstmap;
+ Omhigh = (unsigned) lastmap;
+ mlow = (unsigned) map_table;
+ mhigh = (unsigned) &map_table[mapsize];
+ mhead = (unsigned) &free_mapping;
+ vlow = (unsigned) vtop_table;
+ vhigh = (unsigned) &vtop_table[vtopsize];
+ plow = (unsigned) phys_table;
+ phigh = (unsigned) &phys_table[physsize];
+
+#if 0
+ fprintf(stderr, "Ovtop [%#x-%#x) Ophys [%#x-%#x) Omap %#x [%#x-%#x)\n",
+ Ovlow, Ovhigh, Oplow, Ophigh, Omhead, Omlow, Omhigh);
+ fprintf(stderr, "vtop [%#x-%#x) phys [%#x-%#x) map %#x [%#x-%#x)\n",
+ vlow, vhigh, plow, phigh, mhead, mlow, mhigh);
+#endif
+ return(adjustdata());
+}
+
+STATIC unsigned
+ptrcvt(ptr)
+ unsigned ptr;
+{
+ unsigned ret;
+ char *str;
+
+ if (ptr == 0) {
+ ret = ptr;
+ str = "null";
+ } else if (IS_OVTOPPTR(ptr)) {
+ ret = vlow + (ptr - Ovlow);
+ str = "vtop";
+ } else if (IS_OPHYSPTR(ptr)) {
+ ret = plow + (ptr - Oplow);
+ str = "phys";
+ } else if (IS_OMAPPTR(ptr)) {
+ ret = mlow + (ptr - Omlow);
+ str = "map";
+ } else if (ptr == Omhead) {
+ ret = mhead;
+ str = "maphead";
+ } else {
+ error("bogus pointer %#x", ptr);
+ str = "wild";
+ ret = ptr;
+ }
+#if 0
+ fprintf(stderr, "%x (%s) -> %x\n", ptr, str, ret);
+#endif
+ return(ret);
+}
+
+STATIC int
+adjustdata()
+{
+ register int i, lim;
+ queue_head_t *nq;
+ struct phys_entry *np;
+ struct mapping *nm;
+
+ /* hash table */
+ lim = vtopsize;
+ for (nq = vtop_table; nq < &vtop_table[lim]; nq++) {
+ nq->next = (queue_entry_t) ptrcvt((unsigned)nq->next);
+ nq->prev = (queue_entry_t) ptrcvt((unsigned)nq->prev);
+ }
+
+ /* IPT */
+ lim = physsize;
+ for (np = phys_table; np < &phys_table[lim]; np++) {
+ np->phys_link.next = (queue_entry_t)
+ ptrcvt((unsigned)np->phys_link.next);
+ np->phys_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)np->phys_link.prev);
+ np->writer = (struct mapping *) ptrcvt((unsigned)np->writer);
+ }
+
+ /* mapping table */
+ free_mapping.next = (queue_entry_t)ptrcvt((unsigned)free_mapping.next);
+ free_mapping.prev = (queue_entry_t)ptrcvt((unsigned)free_mapping.prev);
+ lim = mapsize;
+ for (nm = map_table; nm < &map_table[lim]; nm++) {
+ nm->hash_link.next = (queue_entry_t)
+ ptrcvt((unsigned)nm->hash_link.next);
+ nm->hash_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)nm->hash_link.prev);
+ nm->phys_link.next = (queue_entry_t)
+ ptrcvt((unsigned)nm->phys_link.next);
+ nm->phys_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)nm->phys_link.prev);
+ }
+ return(1);
+}
+
+/*
+ * Consistency checks, make sure:
+ *
+ * 1. all mappings are accounted for
+ * 2. no cycles
+ * 3. no wild pointers
+ * 4. consisent TLB state
+ */
+STATIC int
+verifydata()
+{
+ register struct mapstate *ms;
+ register int i;
+ int errors = 0;
+
+ mapstate = (struct mapstate *)
+ mach_malloc("map state", mapsize * sizeof(struct mapstate));
+ for (ms = mapstate; ms < &mapstate[mapsize]; ms++) {
+ ms->flags = 0;
+ ms->hashix = ms->physix = -2;
+ }
+
+ /*
+ * Check the free list
+ */
+ checkhashchain(&free_mapping, M_ISFREE, -1);
+ /*
+ * Check every hash chain
+ */
+ for (i = 0; i < vtopsize; i++)
+ checkhashchain(&vtop_table[i], M_ISHASH, i);
+ /*
+ * Check every phys chain
+ */
+ for (i = 0; i < physsize; i++)
+ checkphyschain(&phys_table[i].phys_link, M_ISPHYS, i);
+ /*
+ * Cycle through mapstate looking for anomolies
+ */
+ ms = mapstate;
+ for (i = 0; i < mapsize; i++) {
+ switch (ms->flags) {
+ case M_ISFREE:
+ case M_ISHASH|M_ISPHYS:
+ break;
+ case 0:
+ merror(ms, "not found");
+ errors++;
+ break;
+ case M_ISHASH:
+ merror(ms, "in vtop but not phys");
+ errors++;
+ break;
+ case M_ISPHYS:
+ merror(ms, "in phys but not vtop");
+ errors++;
+ break;
+ default:
+ merror(ms, "totally bogus");
+ errors++;
+ break;
+ }
+ ms++;
+ }
+ return(errors ? 0 : 1);
+}
+
+STATIC void
+checkhashchain(qhp, flag, ix)
+ queue_entry_t qhp;
+{
+ register queue_entry_t qp, pqp;
+ register struct mapping *mp;
+ struct mapstate *ms;
+
+ qp = qhp->next;
+ /*
+ * First element is not a mapping structure,
+ * chain must be empty.
+ */
+ if (!IS_MAPPTR(qp)) {
+ if (qp != qhp || qp != qhp->prev)
+ fatal("bad vtop_table header pointer");
+ } else {
+ pqp = qhp;
+ do {
+ mp = (struct mapping *) qp;
+ qp = &mp->hash_link;
+ if (qp->prev != pqp)
+ fatal("bad hash_link prev pointer");
+ ms = &mapstate[mp-map_table];
+ ms->flags |= flag;
+ ms->hashix = ix;
+ pqp = (queue_entry_t) mp;
+ qp = qp->next;
+ } while (IS_MAPPTR(qp));
+ if (qp != qhp)
+ fatal("bad hash_link next pointer");
+ }
+}
+
+STATIC void
+checkphyschain(qhp, flag, ix)
+ queue_entry_t qhp;
+{
+ register queue_entry_t qp, pqp;
+ register struct mapping *mp;
+ struct mapstate *ms;
+
+ qp = qhp->next;
+ /*
+ * First element is not a mapping structure,
+ * chain must be empty.
+ */
+ if (!IS_MAPPTR(qp)) {
+ if (qp != qhp || qp != qhp->prev)
+ fatal("bad phys_table header pointer");
+ } else {
+ pqp = qhp;
+ do {
+ mp = (struct mapping *) qp;
+ qp = &mp->phys_link;
+ if (qp->prev != pqp)
+ fatal("bad phys_link prev pointer");
+ ms = &mapstate[mp-map_table];
+ ms->flags |= flag;
+ ms->physix = ix;
+ pqp = (queue_entry_t) mp;
+ qp = qp->next;
+ } while (IS_MAPPTR(qp));
+ if (qp != qhp)
+ fatal("bad phys_link next pointer");
+ }
+}
+
+STATIC void
+merror(ms, str)
+ struct mapstate *ms;
+ char *str;
+{
+ terminal_ours();
+ fflush(stdout);
+ fprintf(stderr,
+ "vtophys: %s: %c%c%c, hashix %d, physix %d, mapping %x\n",
+ str,
+ (ms->flags & M_ISFREE) ? 'F' : '-',
+ (ms->flags & M_ISHASH) ? 'H' : '-',
+ (ms->flags & M_ISPHYS) ? 'P' : '-',
+ ms->hashix, ms->physix, &map_table[ms-mapstate]);
+ return_to_top_level();
+}
+
+STATIC int
+mach_read(str, from, top, size)
+ char *str;
+ CORE_ADDR from;
+ char *top;
+ int size;
+{
+ CORE_ADDR paddr;
+
+ if (from == ~0)
+ from = ksym_lookup(str);
+ paddr = vtophys(0, from);
+ if (paddr == ~0 || physrd(paddr, top, size) != 0)
+ fatal("cannot read %s", str);
+}
+
+STATIC char *
+mach_malloc(str, size)
+ char *str;
+ int size;
+{
+ char *ptr = (char *) malloc(size);
+
+ if (ptr == 0)
+ fatal("no memory for %s", str);
+ return(ptr);
+}
+#endif
+
+#ifdef KERNELDEBUG
+void
+_initialize_hp9k8_dep()
+{
+ add_com ("process-address", class_obscure, set_paddr_command,
+"The process identified by (ps-style) ADDR becomes the\n\
+\"current\" process context for kernel debugging.");
+ add_com_alias ("paddr", "process-address", class_obscure, 0);
+ add_com ("virtual-to-physical", class_obscure, vtop_command,
+"Translates the kernel virtual address ADDR into a physical address.");
+ add_com_alias ("vtop", "virtual-to-physical", class_obscure, 0);
+}
+#endif
diff --git a/gdb/hppab-xdep.c b/gdb/hppab-xdep.c
new file mode 100644
index 0000000..01d7404
--- /dev/null
+++ b/gdb/hppab-xdep.c
@@ -0,0 +1,406 @@
+/* Host-dependent code for HP PA-RISC running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ 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 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.
+
+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. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#ifndef USG
+#include <sys/ptrace.h>
+#endif
+
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* 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 ();
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+child_resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+
+ /* 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.) */
+
+ if (step)
+ ptrace (PT_STEP, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal);
+ else
+ ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal);
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#ifdef ATTACH_DETACH
+/* Nonzero if we are debugging an attached process rather than
+ an inferior. */
+extern int attach_flag;
+
+/* 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 */
+
+#if !defined (FETCH_INFERIOR_REGISTERS)
+
+/* 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 <a.out.gnu.h> /* 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)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area. */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+ - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch. */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int 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. */
+ unsigned int offset;
+
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ bzero (buf, REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* 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). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+
+ unsigned int offset = U_REGS_OFFSET;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ 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_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ }
+ return;
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS). */
+
+/* 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. */
+
+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. */
+
+ 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);
+ }
+
+ 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);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ 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;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+ }
+ return len;
+}
diff --git a/gdb/hppah-tdep.c b/gdb/hppah-tdep.c
new file mode 100644
index 0000000..27bf9e9
--- /dev/null
+++ b/gdb/hppah-tdep.c
@@ -0,0 +1,1427 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+ for GDB, the GNU debugger. This code is for the HP PA-RISC cpu.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+
+/* For argument passing to the inferior */
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+/*#include <sys/user.h> After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+
+#ifdef KERNELDEBUG
+#include <sys/vmmac.h>
+#include <machine/machparam.h>
+#include <machine/vmparam.h>
+#include <machine/pde.h>
+#include <machine/cpu.h>
+#include <machine/iomod.h>
+#include <machine/pcb.h>
+#include <machine/rpb.h>
+#include <ctype.h>
+
+extern int kernel_debugging;
+extern CORE_ADDR startup_file_start;
+extern CORE_ADDR startup_file_end;
+
+#define KERNOFF ((unsigned)KERNBASE)
+#define INKERNEL(x) ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
+
+static int ok_to_cache();
+static void set_kernel_boundaries();
+
+int devmem = 0;
+int vtophys_ready = 0;
+int kerneltype;
+#define OS_BSD 1
+#define OS_MACH 2
+#endif
+
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+extern int errno;
+
+
+
+
+
+
+/* Last modification time of executable file.
+ Also used in source.c to compare against mtime of a source file. */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file. */
+
+/* extern CORE_ADDR data_start; */
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+ Note that the data area in the exec file is used only when there is no core file. */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data. */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data. */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data. */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data. */
+
+extern int stack_offset;
+
+struct header file_hdr;
+struct som_exec_auxhdr exec_hdr;
+
+#ifdef KERNELDEBUG
+/*
+ * Kernel debugging routines.
+ */
+
+static struct pcb pcb;
+static struct pde *pdir;
+static struct hte *htbl;
+static u_int npdir, nhtbl;
+
+static CORE_ADDR
+ksym_lookup(name)
+ char *name;
+{
+ struct symbol *sym;
+ int i;
+
+ if ((i = lookup_misc_func(name)) < 0)
+ error("kernel symbol `%s' not found.", name);
+
+ return (misc_function_vector[i].address);
+}
+
+/*
+ * (re-)set the variables that tell "inside_entry_file" where to end
+ * a stack backtrace.
+ */
+void
+set_kernel_boundaries()
+{
+ switch (kerneltype) {
+ case OS_MACH:
+ startup_file_start = ksym_lookup("$syscall");
+ startup_file_end = ksym_lookup("trap");
+ break;
+ case OS_BSD:
+ startup_file_start = ksym_lookup("syscallinit");
+ startup_file_end = ksym_lookup("$syscallexit");
+ break;
+ }
+}
+
+/*
+ * return true if 'len' bytes starting at 'addr' can be read out as
+ * longwords and/or locally cached (this is mostly for memory mapped
+ * i/o register access when debugging remote kernels).
+ */
+static int
+ok_to_cache(addr, len)
+{
+ static CORE_ADDR ioptr;
+
+ if (! ioptr)
+ ioptr = ksym_lookup("ioptr");
+
+ if (addr >= ioptr && addr < SPA_HIGH)
+ return (0);
+
+ return (1);
+}
+
+static
+physrd(addr, dat, len)
+ u_int addr;
+ char *dat;
+{
+ if (lseek(corechan, addr, L_SET) == -1)
+ return (-1);
+ if (read(corechan, dat, len) != len)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * When looking at kernel data space through /dev/mem or with a core file, do
+ * virtual memory mapping.
+ */
+static CORE_ADDR
+vtophys(space, addr)
+ unsigned space;
+ CORE_ADDR addr;
+{
+ struct pde *pptr;
+ u_int hindx, vpageno, ppageno;
+ CORE_ADDR phys = ~0;
+
+ if (!vtophys_ready) {
+ phys = addr; /* XXX for kvread */
+ } else if (kerneltype == OS_BSD) {
+ /* make offset into a virtual page no */
+ vpageno = btop(addr);
+ /*
+ * Determine index into hash table, initialize pptr to this
+ * entry (since first word of pte & hte are same), and set
+ * physical page number for first entry in chain.
+ */
+ hindx = pdirhash(space, addr) & (nhtbl-1);
+ pptr = (struct pde *) &htbl[hindx];
+ ppageno = pptr->pde_next;
+ while (1) {
+ if (pptr->pde_end)
+ break;
+ pptr = &pdir[ppageno];
+ /*
+ * If space id & virtual page number match, return
+ * "next PDIR entry of previous PDIR entry" as the
+ * physical page or'd with offset into page.
+ */
+ if (pptr->pde_space == space &&
+ pptr->pde_page == vpageno) {
+ phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
+ (addr & PGOFSET));
+ break;
+ }
+ ppageno = pptr->pde_next;
+ }
+ }
+#ifdef MACHKERNELDEBUG
+ else if (kerneltype == OS_MACH) {
+ mach_vtophys(space, addr, &phys);
+ }
+#endif
+#if 0
+ printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
+#endif
+ return (phys);
+}
+
+static
+kvread(addr)
+ CORE_ADDR addr;
+{
+ CORE_ADDR paddr;
+
+ paddr = vtophys(0, addr);
+ if (paddr != ~0)
+ if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
+ return (addr);
+
+ return (~0);
+}
+
+static void
+read_pcb(addr)
+ u_int addr;
+{
+ int i, off;
+ extern char registers[];
+ static int reg2pcb[] = {
+ /* RPB */
+ -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
+ 71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /* BSD */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
+ 36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100,
+ /* Mach */
+ -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
+ 25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
+ 21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
+ 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
+ 42, 44, 46, 48
+ };
+ static struct rpb *rpbaddr = (struct rpb *) 0;
+ static u_int rpbpcbaddr = 0;
+
+ if (!remote_debugging) {
+ /*
+ * If we are debugging a post-mortem and this is the first
+ * call of read_pcb, read the RPB. Also assoicate the
+ * thread/proc running at the time with the RPB.
+ */
+ if (!devmem && rpbpcbaddr == 0) {
+ CORE_ADDR raddr = ksym_lookup("rpb");
+ int usepcb = 1;
+
+ if (raddr != ~0) {
+ rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
+ if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
+ rpbpcbaddr = addr;
+ usepcb = 0;
+ }
+ }
+ if (usepcb) {
+ error("cannot read rpb, using pcb for registers\n");
+ if (rpbaddr)
+ free((char *)rpbaddr);
+ rpbpcbaddr = ~0;
+ }
+ }
+ if (physrd (addr, (char *)&pcb, sizeof pcb))
+ error ("cannot read pcb at %x.\n", addr);
+ } else {
+ if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
+ error ("cannot read pcb at %x.\n", addr);
+ }
+
+ if (kerneltype == OS_BSD) {
+ printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
+ pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
+ off = NUM_REGS;
+ } else {
+ printf("pcb %lx psw %lx ksp %lx\n",
+ addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
+ off = NUM_REGS * 2;
+ }
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ bzero(registers, REGISTER_BYTES);
+ for (i = 0; i < NUM_REGS; ++i)
+ if (reg2pcb[i+off] != -1)
+ supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
+ /*
+ * If the RPB is valid for this thread/proc use the register values
+ * contained there.
+ */
+ if (addr == rpbpcbaddr) {
+ off = 0;
+ for (i = 0; i < NUM_REGS; ++i)
+ if (reg2pcb[i+off] != -1)
+ supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
+ }
+}
+
+void
+setup_kernel_debugging()
+{
+ struct stat stb;
+ CORE_ADDR addr;
+
+ fstat(corechan, &stb);
+ devmem = 0;
+ if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
+ devmem = 1;
+
+ /* XXX */
+ if (lookup_misc_func("Sysmap") < 0)
+ kerneltype = OS_MACH;
+ else
+ kerneltype = OS_BSD;
+
+ if (kerneltype == OS_BSD) {
+ int len, err = 0;
+
+ /*
+ * Hash table and PDIR are equivalently mapped
+ */
+ nhtbl = kvread(ksym_lookup("nhtbl"));
+ if (nhtbl != ~0) {
+ len = nhtbl * sizeof(*htbl);
+ htbl = (struct hte *) malloc(len);
+ if (htbl) {
+ addr = kvread(ksym_lookup("htbl"));
+ if (physrd(addr, (char *)htbl, len))
+ err++;
+ } else
+ err++;
+ } else
+ err++;
+ npdir = kvread(ksym_lookup("npdir"));
+ if (npdir != ~0) {
+ len = npdir * sizeof(*pdir);
+ pdir = (struct pde *) malloc(len);
+ if (pdir) {
+ addr = kvread(ksym_lookup("pdir"));
+ if (physrd(addr, (char *)pdir, len))
+ err++;
+ } else
+ err++;
+ } else
+ err++;
+ if (err) {
+ error("cannot read PDIR/HTBL");
+ return;
+ }
+ vtophys_ready = 1;
+
+ /*
+ * pcb where "panic" saved registers in first thing in
+ * current u-area. The current u-area is pointed to by
+ * "uptr".
+ */
+ addr = kvread(ksym_lookup("uptr"));
+ if (addr == ~0) {
+ error("cannot read current u-area address");
+ return;
+ }
+ read_pcb(vtophys(0, addr)); /* XXX space */
+ if (!devmem) {
+ /* find stack frame */
+ CORE_ADDR panicstr;
+ char buf[256];
+ register char *cp;
+
+ panicstr = kvread(ksym_lookup("panicstr"));
+ if (panicstr == ~0)
+ return;
+ kernel_core_file_hook(panicstr, buf, sizeof(buf));
+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+ if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+ *cp = '?';
+ if (*cp)
+ *cp = '\0';
+ printf("panic: %s\n", buf);
+ }
+ }
+#ifdef MACHKERNELDEBUG
+ else {
+ int *thread;
+
+ /*
+ * Set up address translation
+ */
+ if (mach_vtophys_init() == 0) {
+ error("cannot initialize vtophys for Mach");
+ return;
+ }
+ vtophys_ready = 1;
+
+ /*
+ * Locate active thread and read PCB
+ * XXX MAJOR HACK
+ * - assumes uni-processor
+ * - assumes position of pcb to avoid mach includes
+ */
+ thread = (int *)kvread(ksym_lookup("active_threads"));
+ addr = kvread(&thread[9]); /* XXX: pcb addr */
+ read_pcb(vtophys(0, addr));
+ }
+#endif
+}
+
+vtop_command(arg)
+ char *arg;
+{
+ u_int sp, off, pa;
+
+ if (!arg)
+ error_no_arg("kernel virtual address");
+ if (!kernel_debugging)
+ error("not debugging kernel");
+
+ sp = 0; /* XXX */
+ off = (u_int) parse_and_eval_address(arg);
+ pa = vtophys(sp, off);
+ printf("%lx.%lx -> ", sp, off);
+ if (pa == ~0)
+ printf("<invalid>\n");
+ else
+ printf("%lx\n", pa);
+}
+
+set_paddr_command(arg)
+ char *arg;
+{
+ u_int addr;
+
+ if (!arg) {
+ if (kerneltype == OS_BSD)
+ error_no_arg("ps-style address for new process");
+ else
+ error_no_arg("thread structure virtual address");
+ }
+ if (!kernel_debugging)
+ error("not debugging kernel");
+
+ addr = (u_int) parse_and_eval_address(arg);
+ if (kerneltype == OS_BSD)
+ addr = ctob(addr);
+ else {
+ addr = kvread(&(((int *)addr)[9])); /* XXX: pcb addr */
+ addr = vtophys(0, addr); /* XXX space */
+ }
+ read_pcb(addr);
+
+ flush_cached_frames();
+ set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
+ select_frame(get_current_frame(), 0);
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+kernel_core_file_hook(addr, buf, len)
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+
+ while (len > 0) {
+ paddr = vtophys(0, addr); /* XXX space */
+ if (paddr == ~0) {
+ bzero(buf, len);
+ return (1);
+ }
+ /* we can't read across a page boundary */
+ i = min(len, NBPG - (addr & PGOFSET));
+ if (physrd(paddr, buf, i)) {
+ bzero(buf, len);
+ return (1);
+ }
+ buf += i;
+ addr += i;
+ len -= i;
+ }
+ return (0);
+}
+#endif
+
+
+
+
+
+
+/* Routines to extract various sized constants out of hppa
+ instructions. */
+
+/* This assumes that no garbage lies outside of the lower bits of
+ value. */
+
+int
+sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)(val >> bits - 1 ? (-1 << bits) | val : val);
+}
+
+/* For many immediate values the sign bit is the low bit! */
+
+int
+low_sign_extend (val, bits)
+ unsigned val, bits;
+{
+ return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
+}
+/* extract the immediate field from a ld{bhw}s instruction */
+
+
+
+unsigned
+get_field (val, from, to)
+ unsigned val, from, to;
+{
+ val = val >> 31 - to;
+ return val & ((1 << 32 - from) - 1);
+}
+
+unsigned
+set_field (val, from, to, new_val)
+ unsigned *val, from, to;
+{
+ unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
+ return *val = *val & mask | (new_val << (31 - from));
+}
+
+/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
+
+extract_3 (word)
+ unsigned word;
+{
+ return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+
+extract_5_load (word)
+ unsigned word;
+{
+ return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* extract the immediate field from a st{bhw}s instruction */
+
+int
+extract_5_store (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_5, 5);
+}
+
+/* extract an 11 bit immediate field */
+
+int
+extract_11 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_11, 11);
+}
+
+/* extract a 14 bit immediate field */
+
+int
+extract_14 (word)
+ unsigned word;
+{
+ return low_sign_extend (word & MASK_14, 14);
+}
+
+/* deposit a 14 bit constant in a word */
+
+unsigned
+deposit_14 (opnd, word)
+ int opnd;
+ unsigned word;
+{
+ unsigned sign = (opnd < 0 ? 1 : 0);
+
+ return word | ((unsigned)opnd << 1 & MASK_14) | sign;
+}
+
+/* extract a 21 bit constant */
+
+int
+extract_21 (word)
+ unsigned word;
+{
+ int val;
+
+ word &= MASK_21;
+ word <<= 11;
+ val = GET_FIELD (word, 20, 20);
+ val <<= 11;
+ val |= GET_FIELD (word, 9, 19);
+ val <<= 2;
+ val |= GET_FIELD (word, 5, 6);
+ val <<= 5;
+ val |= GET_FIELD (word, 0, 4);
+ val <<= 2;
+ val |= GET_FIELD (word, 7, 8);
+ return sign_extend (val, 21) << 11;
+}
+
+/* deposit a 21 bit constant in a word. Although 21 bit constants are
+ usually the top 21 bits of a 32 bit constant, we assume that only
+ the low 21 bits of opnd are relevant */
+
+unsigned
+deposit_21 (opnd, word)
+ unsigned opnd, word;
+{
+ unsigned val = 0;
+
+ val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+ val <<= 2;
+ val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+ val <<= 11;
+ val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+ val <<= 1;
+ val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+ return word | val;
+}
+
+/* extract a 12 bit constant from branch instructions */
+
+int
+extract_12 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ (word & 0x1) << 11, 12) << 2;
+}
+
+/* extract a 17 bit constant from branch instructions, returning the
+ 19 bit signed value. */
+
+int
+extract_17 (word)
+ unsigned word;
+{
+ return sign_extend (GET_FIELD (word, 19, 28) |
+ GET_FIELD (word, 29, 29) << 10 |
+ GET_FIELD (word, 11, 15) << 11 |
+ (word & 0x1) << 16, 17) << 2;
+}
+
+
+CORE_ADDR
+frame_saved_pc (frame)
+ FRAME frame;
+{
+ if (get_current_frame () == frame)
+ {
+ struct frame_saved_regs saved_regs;
+ CORE_ADDR pc = get_frame_pc (frame);
+
+ get_frame_saved_regs (frame, &saved_regs);
+ if (pc >= millicode_start && pc < millicode_end)
+ return read_register (31);
+ else if (saved_regs.regs[RP_REGNUM])
+ return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+ else
+ return read_register (RP_REGNUM);
+ }
+ return read_memory_integer (frame->frame - 20, 4) & ~0x3;
+}
+
+
+/* To see if a frame chain is valid, see if the caller looks like it
+ was compiled with gcc. */
+
+int frame_chain_valid (chain, thisframe)
+ FRAME_ADDR chain;
+ FRAME thisframe;
+{
+ if (chain && (chain > 0x60000000
+ /* || remote_debugging -this is no longer used */
+#ifdef KERNELDEBUG
+ || kernel_debugging
+#endif
+ ))
+ {
+ CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
+
+ if (!inside_entry_file (pc))
+ return 0;
+ /* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
+ if (read_memory_integer (pc, 4) == 0x6BC23FD9)
+ pc = pc + 4;
+
+ if (read_memory_integer (pc, 4) == 0x8040241 &&
+ read_memory_integer (pc + 4, 4) == 0x81E0244)
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+/* Some helper functions. gcc_p returns 1 if the function beginning at
+ pc appears to have been compiled with gcc. hpux_cc_p returns 1 if
+ fn was compiled with hpux cc. gcc functions look like :
+
+ stw rp,-0x14(sp) ; optional
+ or r4,r0,r1
+ or sp,r0,r4
+ stwm r1,framesize(sp)
+
+ hpux cc functions look like:
+
+ stw rp,-0x14(sp) ; optional.
+ stwm r3,framesiz(sp)
+ */
+
+gcc_p (pc)
+ CORE_ADDR pc;
+{
+ if (read_memory_integer (pc, 4) == 0x6BC23FD9)
+ pc = pc + 4;
+
+ if (read_memory_integer (pc, 4) == 0x8040241 &&
+ read_memory_integer (pc + 4, 4) == 0x81E0244)
+ return 1;
+ return 0;
+}
+
+
+find_dummy_frame_regs (frame, frame_saved_regs)
+ struct frame_info *frame;
+ struct frame_saved_regs *frame_saved_regs;
+{
+ CORE_ADDR fp = frame->frame;
+ int i;
+
+ frame_saved_regs->regs[RP_REGNUM] = fp - 20 & ~0x3;
+ frame_saved_regs->regs[FP_REGNUM] = fp;
+ frame_saved_regs->regs[1] = fp + 8;
+ frame_saved_regs->regs[3] = fp + 12;
+ for (fp += 16, i = 3; i < 30; fp += 4, i++)
+ frame_saved_regs->regs[i] = fp;
+ frame_saved_regs->regs[31] = fp;
+ fp += 4;
+ for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+ frame_saved_regs->regs[i] = fp;
+ /* depend on last increment of fp */
+ frame_saved_regs->regs[IPSW_REGNUM] = fp - 4;
+ frame_saved_regs->regs[SAR_REGNUM] = fp;
+ fp += 4;
+ frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp;
+ frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp;
+}
+
+CORE_ADDR
+hp_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ /* array of arguments' offsets */
+ int *offset = (int *)alloca(nargs);
+ int cum = 0;
+ int i, alignment;
+
+ for (i = 0; i < nargs; i++)
+ {
+ cum += TYPE_LENGTH (VALUE_TYPE (args[i]));
+ /* value must go at proper alignment. Assume alignment is a
+ power of two.*/
+ alignment = hp_alignof (VALUE_TYPE (args[i]));
+ if (cum % alignment)
+ cum = (cum + alignment) & -alignment;
+ offset[i] = -cum;
+ }
+ for (i == 0; i < nargs; i++)
+ {
+ write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int));
+ }
+ sp += min ((cum + 7) & -8, 48);
+ if (struct_return)
+ write_register (28, struct_addr);
+ return sp + 48;
+}
+
+/* return the alignment of a type in bytes. Structures have the maximum
+ alignment required by their fields. */
+
+int
+hp_alignof (arg)
+ struct type *arg;
+{
+ int max_align, align, i;
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ return TYPE_LENGTH (arg);
+ case TYPE_CODE_ARRAY:
+ return hp_alignof (TYPE_FIELD_TYPE (arg, 0));
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ max_align = 2;
+ for (i = 0; i < TYPE_NFIELDS (arg); i++)
+ {
+ /* Bit fields have no real alignment. */
+ if (!TYPE_FIELD_BITPOS (arg, i))
+ {
+ align = hp_alignof (TYPE_FIELD_TYPE (arg, i));
+ max_align = max (max_align, align);
+ }
+ }
+ return max_align;
+ default:
+ return 4;
+ }
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+pa_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ char raw_regs [REGISTER_BYTES];
+ int i;
+
+ for (i = 0; i < NUM_REGS; i++)
+ read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+ if (regnum = -1)
+ pa_print_registers (raw_regs, regnum);
+ else if (regnum < FP0_REGNUM)
+ {
+ printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs +
+ REGISTER_BYTE (regnum)));
+ }
+ else
+ pa_print_fp_reg (regnum);
+}
+
+pa_print_registers (raw_regs, regnum)
+ char *raw_regs;
+ int regnum;
+{
+ int i;
+
+ for (i = 0; i < 18; i++)
+ printf ("%8.8s: %8x %8.8s: %8x %8.8s: %8x %8.8s: %8x\n",
+ reg_names[i],
+ *(int *)(raw_regs + REGISTER_BYTE (i)),
+ reg_names[i + 18],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 18)),
+ reg_names[i + 36],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 36)),
+ reg_names[i + 54],
+ *(int *)(raw_regs + REGISTER_BYTE (i + 54)));
+ for (i = 72; i < NUM_REGS; i++)
+ pa_print_fp_reg (i);
+}
+
+pa_print_fp_reg (i)
+ int i;
+{
+ unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+ REGISTER_TYPE val;
+
+ /* Get the data in raw format, then convert also to virtual format. */
+ read_relative_register_raw_bytes (i, raw_buffer);
+ REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
+
+ fputs_filtered (reg_names[i], stdout);
+ print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0,
+ 1, 0, Val_pretty_default);
+ printf_filtered ("\n");
+
+}
+
+/*
+ * Virtual to physical translation routines for Utah's Mach 3.0
+ */
+#ifdef MACHKERNELDEBUG
+
+#define STATIC
+
+#if 0 /* too many includes to resolve, too much crap */
+#include <kern/queue.h>
+#include <vm/pmap.h>
+#include <mach/vm_prot.h>
+#else
+/* queue.h */
+struct queue_entry {
+ struct queue_entry *next; /* next element */
+ struct queue_entry *prev; /* previous element */
+};
+
+typedef struct queue_entry *queue_t;
+typedef struct queue_entry queue_head_t;
+typedef struct queue_entry queue_chain_t;
+typedef struct queue_entry *queue_entry_t;
+
+/* pmap.h */
+#define HP800_HASHSIZE 1024
+#define HP800_HASHSIZE_LOG2 10
+
+#define pmap_hash(space, offset) \
+ (((unsigned) (space) << 5 ^ \
+ ((unsigned) (offset) >> 19 | (unsigned) (space) << 13) ^ \
+ (unsigned) (offset) >> 11) & (HP800_HASHSIZE-1))
+
+struct mapping {
+ queue_head_t hash_link; /* hash table links */
+ queue_head_t phys_link; /* for mappings of a given PA */
+ space_t space; /* virtual space */
+ unsigned offset; /* virtual page number */
+ unsigned tlbpage; /* physical page (for TLB load) */
+ unsigned tlbprot; /* prot/access rights (for TLB load) */
+ struct pmap *pmap; /* pmap mapping belongs to */
+};
+
+struct phys_entry {
+ queue_head_t phys_link; /* head of mappings of a given PA */
+ struct mapping *writer; /* mapping with R/W access */
+ unsigned tlbprot; /* TLB format protection */
+};
+
+#endif
+
+#define atop(a) ((unsigned)(a) >> 11)
+#define ptoa(p) ((unsigned)(p) << 11)
+#define trunc_page(a) ((unsigned)(a) & ~2047)
+
+STATIC long equiv_end;
+STATIC queue_head_t *Ovtop_table, *vtop_table, *Ofree_mapping, free_mapping;
+STATIC struct phys_entry *Ophys_table, *phys_table;
+STATIC long vm_last_phys, vm_first_phys;
+STATIC struct mapping *firstmap, *lastmap, *Omap_table, *map_table;
+STATIC unsigned Omlow, Omhigh, Omhead, Ovlow, Ovhigh, Oplow, Ophigh;
+STATIC unsigned mlow, mhigh, mhead, vlow, vhigh, plow, phigh;
+STATIC int vtopsize, physsize, mapsize;
+STATIC int kmemfd;
+
+#define IS_OVTOPPTR(p) ((unsigned)(p) >= Ovlow && (unsigned)(p) < Ovhigh)
+#define IS_OMAPPTR(p) ((unsigned)(p) >= Omlow && (unsigned)(p) < Omhigh)
+#define IS_OPHYSPTR(p) ((unsigned)(p) >= Oplow && (unsigned)(p) < Ophigh)
+#define IS_VTOPPTR(p) ((unsigned)(p) >= vlow && (unsigned)(p) < vhigh)
+#define IS_MAPPTR(p) ((unsigned)(p) >= mlow && (unsigned)(p) < mhigh)
+#define IS_PHYSPTR(p) ((unsigned)(p) >= plow && (unsigned)(p) < phigh)
+
+struct mapstate {
+ char unused;
+ char flags;
+ short hashix;
+ short physix;
+} *mapstate;
+
+/* flags */
+#define M_ISFREE 1
+#define M_ISHASH 2
+#define M_ISPHYS 4
+
+mach_vtophys_init()
+{
+ int errors = 0;
+
+ if (!readdata())
+ errors++;
+ if (!verifydata())
+ errors++;
+ if (!errors)
+ return(1);
+ fflush(stdout);
+ fprintf(stderr,
+ "translate: may not be able to translate all addresses\n");
+ return(0);
+}
+
+mach_vtophys(space, off, pa)
+ unsigned space, off, *pa;
+{
+ register int i;
+ register queue_t qp;
+ register struct mapping *mp;
+ int poff;
+
+ /*
+ * Kernel IO or equivilently mapped, one to one.
+ */
+ if (space == 0 && (long)off < equiv_end) {
+ *pa = off;
+ return(1);
+ }
+ /*
+ * Else look it up in specified space
+ */
+ poff = off - trunc_page(off);
+ off = trunc_page(off);
+ qp = &vtop_table[pmap_hash(space, off)];
+ for (mp = (struct mapping *)qp->next;
+ qp != (queue_entry_t)mp;
+ mp = (struct mapping *)mp->hash_link.next) {
+ if (mp->space == space && mp->offset == off) {
+ *pa = (mp->tlbpage << 7) | poff;
+ return(1);
+ }
+ }
+ return(0);
+}
+
+STATIC
+readdata()
+{
+ char *tmp, *mach_malloc();
+ long size;
+
+ /* easy scalars */
+ mach_read("equiv_end", ~0, (char *)&equiv_end, sizeof equiv_end);
+ mach_read("vm_first_phys", ~0,
+ (char *)&vm_first_phys, sizeof vm_first_phys);
+ mach_read("vm_last_phys", ~0,
+ (char *)&vm_last_phys, sizeof vm_last_phys);
+ mach_read("firstmap", ~0, (char *)&firstmap, sizeof firstmap);
+ mach_read("lastmap", ~0, (char *)&lastmap, sizeof lastmap);
+
+ /* virtual to physical hash table */
+ vtopsize = HP800_HASHSIZE;
+ size = vtopsize * sizeof(queue_head_t);
+ tmp = mach_malloc("vtop table", size);
+ mach_read("vtop_table", ~0, (char *)&Ovtop_table, sizeof Ovtop_table);
+ mach_read("vtop table", (CORE_ADDR)Ovtop_table, tmp, size);
+ vtop_table = (queue_head_t *) tmp;
+
+ /* inverted page table */
+ physsize = atop(vm_last_phys - vm_first_phys);
+ size = physsize * sizeof(struct phys_entry);
+ tmp = mach_malloc("phys table", size);
+ mach_read("phys_table", ~0, (char *)&Ophys_table, sizeof Ophys_table);
+ mach_read("phys table", (CORE_ADDR)Ophys_table, tmp, size);
+ phys_table = (struct phys_entry *) tmp;
+
+ /* mapping structures */
+ Ofree_mapping = (queue_head_t *) ksym_lookup("free_mapping");
+ mach_read("free mapping", (CORE_ADDR)Ofree_mapping,
+ (char *) &free_mapping, sizeof free_mapping);
+ Omap_table = firstmap;
+ mapsize = lastmap - firstmap;
+ size = mapsize * sizeof(struct mapping);
+ tmp = mach_malloc("mapping table", size);
+ mach_read("mapping table", (CORE_ADDR)Omap_table, tmp, size);
+ map_table = (struct mapping *) tmp;
+
+ /* set limits */
+ Ovlow = (unsigned) Ovtop_table;
+ Ovhigh = (unsigned) &Ovtop_table[vtopsize];
+ Oplow = (unsigned) Ophys_table;
+ Ophigh = (unsigned) &Ophys_table[physsize];
+ Omhead = (unsigned) Ofree_mapping;
+ Omlow = (unsigned) firstmap;
+ Omhigh = (unsigned) lastmap;
+ mlow = (unsigned) map_table;
+ mhigh = (unsigned) &map_table[mapsize];
+ mhead = (unsigned) &free_mapping;
+ vlow = (unsigned) vtop_table;
+ vhigh = (unsigned) &vtop_table[vtopsize];
+ plow = (unsigned) phys_table;
+ phigh = (unsigned) &phys_table[physsize];
+
+#if 0
+ fprintf(stderr, "Ovtop [%#x-%#x) Ophys [%#x-%#x) Omap %#x [%#x-%#x)\n",
+ Ovlow, Ovhigh, Oplow, Ophigh, Omhead, Omlow, Omhigh);
+ fprintf(stderr, "vtop [%#x-%#x) phys [%#x-%#x) map %#x [%#x-%#x)\n",
+ vlow, vhigh, plow, phigh, mhead, mlow, mhigh);
+#endif
+ return(adjustdata());
+}
+
+STATIC unsigned
+ptrcvt(ptr)
+ unsigned ptr;
+{
+ unsigned ret;
+ char *str;
+
+ if (ptr == 0) {
+ ret = ptr;
+ str = "null";
+ } else if (IS_OVTOPPTR(ptr)) {
+ ret = vlow + (ptr - Ovlow);
+ str = "vtop";
+ } else if (IS_OPHYSPTR(ptr)) {
+ ret = plow + (ptr - Oplow);
+ str = "phys";
+ } else if (IS_OMAPPTR(ptr)) {
+ ret = mlow + (ptr - Omlow);
+ str = "map";
+ } else if (ptr == Omhead) {
+ ret = mhead;
+ str = "maphead";
+ } else {
+ error("bogus pointer %#x", ptr);
+ str = "wild";
+ ret = ptr;
+ }
+#if 0
+ fprintf(stderr, "%x (%s) -> %x\n", ptr, str, ret);
+#endif
+ return(ret);
+}
+
+STATIC int
+adjustdata()
+{
+ register int i, lim;
+ queue_head_t *nq;
+ struct phys_entry *np;
+ struct mapping *nm;
+
+ /* hash table */
+ lim = vtopsize;
+ for (nq = vtop_table; nq < &vtop_table[lim]; nq++) {
+ nq->next = (queue_entry_t) ptrcvt((unsigned)nq->next);
+ nq->prev = (queue_entry_t) ptrcvt((unsigned)nq->prev);
+ }
+
+ /* IPT */
+ lim = physsize;
+ for (np = phys_table; np < &phys_table[lim]; np++) {
+ np->phys_link.next = (queue_entry_t)
+ ptrcvt((unsigned)np->phys_link.next);
+ np->phys_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)np->phys_link.prev);
+ np->writer = (struct mapping *) ptrcvt((unsigned)np->writer);
+ }
+
+ /* mapping table */
+ free_mapping.next = (queue_entry_t)ptrcvt((unsigned)free_mapping.next);
+ free_mapping.prev = (queue_entry_t)ptrcvt((unsigned)free_mapping.prev);
+ lim = mapsize;
+ for (nm = map_table; nm < &map_table[lim]; nm++) {
+ nm->hash_link.next = (queue_entry_t)
+ ptrcvt((unsigned)nm->hash_link.next);
+ nm->hash_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)nm->hash_link.prev);
+ nm->phys_link.next = (queue_entry_t)
+ ptrcvt((unsigned)nm->phys_link.next);
+ nm->phys_link.prev = (queue_entry_t)
+ ptrcvt((unsigned)nm->phys_link.prev);
+ }
+ return(1);
+}
+
+/*
+ * Consistency checks, make sure:
+ *
+ * 1. all mappings are accounted for
+ * 2. no cycles
+ * 3. no wild pointers
+ * 4. consisent TLB state
+ */
+STATIC int
+verifydata()
+{
+ register struct mapstate *ms;
+ register int i;
+ int errors = 0;
+
+ mapstate = (struct mapstate *)
+ mach_malloc("map state", mapsize * sizeof(struct mapstate));
+ for (ms = mapstate; ms < &mapstate[mapsize]; ms++) {
+ ms->flags = 0;
+ ms->hashix = ms->physix = -2;
+ }
+
+ /*
+ * Check the free list
+ */
+ checkhashchain(&free_mapping, M_ISFREE, -1);
+ /*
+ * Check every hash chain
+ */
+ for (i = 0; i < vtopsize; i++)
+ checkhashchain(&vtop_table[i], M_ISHASH, i);
+ /*
+ * Check every phys chain
+ */
+ for (i = 0; i < physsize; i++)
+ checkphyschain(&phys_table[i].phys_link, M_ISPHYS, i);
+ /*
+ * Cycle through mapstate looking for anomolies
+ */
+ ms = mapstate;
+ for (i = 0; i < mapsize; i++) {
+ switch (ms->flags) {
+ case M_ISFREE:
+ case M_ISHASH|M_ISPHYS:
+ break;
+ case 0:
+ merror(ms, "not found");
+ errors++;
+ break;
+ case M_ISHASH:
+ merror(ms, "in vtop but not phys");
+ errors++;
+ break;
+ case M_ISPHYS:
+ merror(ms, "in phys but not vtop");
+ errors++;
+ break;
+ default:
+ merror(ms, "totally bogus");
+ errors++;
+ break;
+ }
+ ms++;
+ }
+ return(errors ? 0 : 1);
+}
+
+STATIC void
+checkhashchain(qhp, flag, ix)
+ queue_entry_t qhp;
+{
+ register queue_entry_t qp, pqp;
+ register struct mapping *mp;
+ struct mapstate *ms;
+
+ qp = qhp->next;
+ /*
+ * First element is not a mapping structure,
+ * chain must be empty.
+ */
+ if (!IS_MAPPTR(qp)) {
+ if (qp != qhp || qp != qhp->prev)
+ fatal("bad vtop_table header pointer");
+ } else {
+ pqp = qhp;
+ do {
+ mp = (struct mapping *) qp;
+ qp = &mp->hash_link;
+ if (qp->prev != pqp)
+ fatal("bad hash_link prev pointer");
+ ms = &mapstate[mp-map_table];
+ ms->flags |= flag;
+ ms->hashix = ix;
+ pqp = (queue_entry_t) mp;
+ qp = qp->next;
+ } while (IS_MAPPTR(qp));
+ if (qp != qhp)
+ fatal("bad hash_link next pointer");
+ }
+}
+
+STATIC void
+checkphyschain(qhp, flag, ix)
+ queue_entry_t qhp;
+{
+ register queue_entry_t qp, pqp;
+ register struct mapping *mp;
+ struct mapstate *ms;
+
+ qp = qhp->next;
+ /*
+ * First element is not a mapping structure,
+ * chain must be empty.
+ */
+ if (!IS_MAPPTR(qp)) {
+ if (qp != qhp || qp != qhp->prev)
+ fatal("bad phys_table header pointer");
+ } else {
+ pqp = qhp;
+ do {
+ mp = (struct mapping *) qp;
+ qp = &mp->phys_link;
+ if (qp->prev != pqp)
+ fatal("bad phys_link prev pointer");
+ ms = &mapstate[mp-map_table];
+ ms->flags |= flag;
+ ms->physix = ix;
+ pqp = (queue_entry_t) mp;
+ qp = qp->next;
+ } while (IS_MAPPTR(qp));
+ if (qp != qhp)
+ fatal("bad phys_link next pointer");
+ }
+}
+
+STATIC void
+merror(ms, str)
+ struct mapstate *ms;
+ char *str;
+{
+ terminal_ours();
+ fflush(stdout);
+ fprintf(stderr,
+ "vtophys: %s: %c%c%c, hashix %d, physix %d, mapping %x\n",
+ str,
+ (ms->flags & M_ISFREE) ? 'F' : '-',
+ (ms->flags & M_ISHASH) ? 'H' : '-',
+ (ms->flags & M_ISPHYS) ? 'P' : '-',
+ ms->hashix, ms->physix, &map_table[ms-mapstate]);
+ return_to_top_level();
+}
+
+STATIC int
+mach_read(str, from, top, size)
+ char *str;
+ CORE_ADDR from;
+ char *top;
+ int size;
+{
+ CORE_ADDR paddr;
+
+ if (from == ~0)
+ from = ksym_lookup(str);
+ paddr = vtophys(0, from);
+ if (paddr == ~0 || physrd(paddr, top, size) != 0)
+ fatal("cannot read %s", str);
+}
+
+STATIC char *
+mach_malloc(str, size)
+ char *str;
+ int size;
+{
+ char *ptr = (char *) malloc(size);
+
+ if (ptr == 0)
+ fatal("no memory for %s", str);
+ return(ptr);
+}
+#endif
+
+#ifdef KERNELDEBUG
+void
+_initialize_hp9k8_dep()
+{
+ add_com ("process-address", class_obscure, set_paddr_command,
+"The process identified by (ps-style) ADDR becomes the\n\
+\"current\" process context for kernel debugging.");
+ add_com_alias ("paddr", "process-address", class_obscure, 0);
+ add_com ("virtual-to-physical", class_obscure, vtop_command,
+"Translates the kernel virtual address ADDR into a physical address.");
+ add_com_alias ("vtop", "virtual-to-physical", class_obscure, 0);
+}
+#endif
diff --git a/gdb/hppah-xdep.c b/gdb/hppah-xdep.c
new file mode 100644
index 0000000..a556998
--- /dev/null
+++ b/gdb/hppah-xdep.c
@@ -0,0 +1,417 @@
+/* Host-dependent code for HP PA-RISC runing HP/UX, for GDB.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ 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 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.
+
+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. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#include <sys/ptrace.h>
+
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+
+/* 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, 0);
+}
+
+#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_EXIT, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0, 0); /* PT_EXIT = PT_KILL ? */
+ wait ((int *)0);
+ target_mourn_inferior ();
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+child_resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+
+ /* 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.) */
+
+ if (step)
+ ptrace (PT_SINGLE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal, 0);
+ else
+ ptrace (PT_CONTIN, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal, 0);
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#ifdef ATTACH_DETACH
+/* Nonzero if we are debugging an attached process rather than
+ an inferior. */
+extern int attach_flag;
+
+/* Start debugging the process whose number is PID. */
+int
+attach (pid)
+ int pid;
+{
+ errno = 0;
+ ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 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, 0);
+ if (errno)
+ perror_with_name ("ptrace");
+ attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+
+#if !defined (FETCH_INFERIOR_REGISTERS)
+
+/* 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 <a.out.gnu.h> /* 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)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area. */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0, 0) \
+ - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch. */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int 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. */
+ unsigned int offset;
+
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ bzero (buf, REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* 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). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+
+ unsigned int offset = U_REGS_OFFSET;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ 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_WUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ }
+ return;
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS). */
+
+/* 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. */
+
+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. */
+
+ if (addr != memaddr || len < (int)sizeof (int)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = ptrace (PT_RIUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0, 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = ptrace (PT_RIUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (int)),
+ 0, 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+#if 0
+/* The HP-UX kernel crashes if you use PT_WDUSER to write into the text
+ segment. FIXME -- does it work to write into the data segment using
+ WIUSER, or do these idiots really expect us to figure out which segment
+ the address is in, so we can use a separate system call for it??! */
+ errno = 0;
+ ptrace (PT_WDUSER, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i], 0);
+ if (errno)
+#endif
+ {
+ /* Using the appropriate one (I or D) is necessary for
+ Gould NP1, at least. */
+ errno = 0;
+ ptrace (PT_WIUSER, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i], 0);
+ }
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = ptrace (PT_RIUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0, 0);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+ }
+ return len;
+}
+
+
+
+
+int
+getpagesize()
+{
+ return(4096);
+}
diff --git a/gdb/tm-hppab.h b/gdb/tm-hppab.h
new file mode 100644
index 0000000..577bb9b
--- /dev/null
+++ b/gdb/tm-hppab.h
@@ -0,0 +1,6 @@
+/* Parameters for execution on an HP PA-RISC machine running BSD, for GDB.
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu). */
+
+/* It's all just the common stuff. */
+#include "tm-hppa.h"
diff --git a/gdb/tm-hppah.h b/gdb/tm-hppah.h
new file mode 100644
index 0000000..130365d
--- /dev/null
+++ b/gdb/tm-hppah.h
@@ -0,0 +1,39 @@
+/* Parameters for execution on an HP PA-RISC machine, running HPUX, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+/* Mostly it's common to all HPPA's. */
+#include "tm-hppa.h"
+
+/* Saved PC's are different, since there is millicode. */
+extern CORE_ADDR millicode_start, millicode_end;
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#undef SAVED_PC_AFTER_CALL
+#define SAVED_PC_AFTER_CALL(frame) \
+ ((get_frame_pc (frame) >= millicode_start \
+ && get_frame_pc (frame) < millicode_end) ? \
+ read_register (31) & ~3 \
+ : read_register (RP_REGNUM) & ~3)
diff --git a/gdb/xm-hppab.h b/gdb/xm-hppab.h
new file mode 100644
index 0000000..f326876
--- /dev/null
+++ b/gdb/xm-hppab.h
@@ -0,0 +1,48 @@
+/* Parameters for hosting on an HPPA PA-RISC machine, running BSD, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+/* This is a big-endian host. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+ the same as in the system <machine/machtypes.h> file. */
+#undef INT_MIN
+#define INT_MIN 0x80000000
+
+#ifndef hp800
+#define USG
+#endif
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+#define U_REGS_OFFSET 0
+
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Set file pointer to "offset" */
+# define SEEK_CUR 1 /* Set file pointer to current plus "offset" */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif /* SEEK_SET */
diff --git a/gdb/xm-hppah.h b/gdb/xm-hppah.h
new file mode 100644
index 0000000..bdb0b95
--- /dev/null
+++ b/gdb/xm-hppah.h
@@ -0,0 +1,52 @@
+/* Parameters for hosting on an HPPA-RISC machine running HPUX, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+ 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 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.
+
+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. */
+
+/* Host is big-endian. */
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+ the same as in the system <machine/machtypes.h> file. */
+#undef INT_MIN
+#define INT_MIN 0x80000000
+
+#ifndef hp800
+#define USG
+#endif
+
+#define HAVE_TERMIO
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+#define U_REGS_OFFSET 0
+
+/* HP uses non-ANSI definitions, but with void * results. */
+#define MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */
+extern void *
+memcpy PARAMS ((void *, const void *, size_t)); /* 4.11.2.1 */
+
+extern void *
+memset PARAMS ((void *, int, size_t)); /* 4.11.6.1 */
+