diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 53 | ||||
-rw-r--r-- | gdb/hppa-pinsn.c | 42 | ||||
-rw-r--r-- | gdb/hppah-nat.c | 110 | ||||
-rw-r--r-- | gdb/hppah-tdep.c | 1133 | ||||
-rw-r--r-- | gdb/i860-tdep.c | 1 | ||||
-rw-r--r-- | gdb/infrun.c | 21 | ||||
-rw-r--r-- | gdb/tm-hppa.h | 236 | ||||
-rw-r--r-- | gdb/valops.c | 13 |
8 files changed, 490 insertions, 1119 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4f66053..f050aa9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,56 @@ +Mon Dec 21 18:02:35 1992 Stu Grossman (grossman at cygnus.com) + + * hppa-pinsn.c (print_insn): Improve handling of be and ble + branch targets to compute target address using const from previous + instruction if necessary. + * Add `Q' operator to print out bit position field various + instructions. + * hppah-nat.c: #include sys/param.h, and sys/user.h. General + cleanups, use new code from Utah. + * (store_inferior_registers): Update to new code from Utah. + * (initialize_kernel_u_addr): Re-enable decl of struct user u. + * (fetch_register): Clear out priv level when reading PCs. + * hppah-tdep.c: Get rid of gobs of KERNELDEBUG stuff. + * Remove decl of errno, #include wait.h and target.h. + * (frame_saved_pc): Check `flags' pseudo-register to see if we + were inside of a kernel call. If so, then PC is in a different + register. Also, mask out bottom two bits of all PCs so as not to + confuse higher level code. + * (push_dummy_frame): Create from #define in tm-hppa.h. + * (find_dummy_frame_regs): Update from Utah. + * (hp_pop_frame): Create from #define in tm-hppa.h. + * (hp_restore_pc_queue): New, from Utah. + * (hp_push_arguments): Big fixes from Utah. + * (pa_do_registers_info, pa_print_registers): Only print out fp + regs upon request. + * (skip_trampoline_code): New routine to deal with stubs that + live in nowhereland between callers and callees. + * i860-tdep.c: Remove decl of attach_flag. + * infrun.c (wait_for_inferior): Add new macro + INSTRUCTION_NULLIFIED, which can tell if the instruction pointed + at by PC will be nullified. If so, then step the target once more + so as to avoid confusing the user. + * (just before step_over_function:): Use stop_func_start, not + stop_pc when checking for the existance of line number info. + stop_func_start will reflect the proper address of the target + routine, not of the stub that we may be traversing to get there. + * tm-hppa.h: define SKIP_TRAMPOLINE_CODE and IN_SOLIB_TRAMPOLINE + to deal with the stubs that PA compilers sometimes stick between + callers and callees. Also, define FLAGS_REGNUM for access to the + `flags' pseudo-reg. + * (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Use + memcpy, not bcopy. + * (CANNOT_STORE_REGISTER): New from Utah. Says that we can't + write gr0, PC regs, and PSW! + * (FRAME_FIND_SAVED_REGS): Bug fixes from Utah. + * (PUSH_DUMMY_FRAME, POP_FRAME): Make into real routines in + hppah-nat.c. + * (CALL_DUMMY, FIX_CALL_DUMMY): Fixes from Utah. + * Define struct unwind_table_entry. + * valops.c (call_function_by_hand): Add another arg to + FIX_CALL_DUMMY (under #ifdef GDB_TARGET_IS_HPPA). Why is this + necessary? + Mon Dec 21 02:17:57 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * remote-vx.c: remove include of "symfile.h", replace it with "complaints.h" diff --git a/gdb/hppa-pinsn.c b/gdb/hppa-pinsn.c index 12df5f3..0f0fec1 100644 --- a/gdb/hppa-pinsn.c +++ b/gdb/hppa-pinsn.c @@ -233,13 +233,13 @@ print_insn (memaddr, stream) print_address (memaddr + 8 + extract_12 (insn), stream); break; case 'W': - /* don't interpret an address if it's an external branch - instruction. */ op = GET_FIELD (insn, 0, 5); - if (op != 0x38 /* be */ && op != 0x39 /* ble */) - print_address (memaddr + 8 + extract_17 (insn), stream); - else + + if (op == 0x38 /* be */ || op == 0x39 /* ble */) fput_const (extract_17 (insn), stream); + else + print_address (memaddr + 8 + extract_17 (insn), stream); + break; case 'B': { @@ -257,6 +257,10 @@ print_insn (memaddr, stream) fprintf_filtered (stream, "%d", GET_FIELD (insn, 22, 26)); break; + case 'Q': + fprintf_filtered (stream, "%d", + GET_FIELD (insn, 11, 15)); + break; case 'T': fprintf_filtered (stream, "%d", 32 - GET_FIELD (insn, 27, 31)); @@ -340,6 +344,34 @@ print_insn (memaddr, stream) break; } } + +/* If this is an external branch, examine the previous instruction and see if + it was an ldil that loaded something into the same base reg. If so, then + calculate the branch target from the constants in both instructions, and + print it out. */ + + op = GET_FIELD (insn, 0, 5); + if (op == 0x38 /* be */ || op == 0x39 /* ble */) + { + CORE_ADDR target_address; + unsigned int prev_insn; + int basereg, basereg_prev; + + target_address = extract_17 (insn); + basereg = GET_FIELD (insn, 6, 10); + if (basereg != 0) + { + read_memory (memaddr - 4, &prev_insn, sizeof(prev_insn)); + basereg_prev = GET_FIELD (prev_insn, 6, 10); + + if ((prev_insn & 0xfc000000) == 0x20000000 /* ldil */ + && basereg == basereg_prev) + target_address += extract_21 (prev_insn); + } + fprintf_filtered (stream, "\t! "); + print_address (target_address, stream); + } + return sizeof(insn); } } diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c index afdb14c..bef53e9 100644 --- a/gdb/hppah-nat.c +++ b/gdb/hppah-nat.c @@ -27,6 +27,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "inferior.h" #include "target.h" #include <sys/ptrace.h> +#include <sys/param.h> +#include <sys/user.h> + +extern CORE_ADDR text_end; static void fetch_register (); @@ -105,42 +109,70 @@ store_inferior_registers (regno) char buf[80]; extern char registers[]; register int i; - unsigned int offset = U_REGS_OFFSET; + int scratch; 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 *) ®isters[REGISTER_BYTE (regno) + i], 0); - if (errno != 0) - { - sprintf (buf, "writing register number %d(%d)", regno, i); - perror_with_name (buf); - } - regaddr += sizeof(int); - } + errno = 0; + if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM) + { + scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3; + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + scratch, 0); + if (errno != 0) + { + sprintf (buf, "writing register number %d(%d)", regno, i); + perror_with_name (buf); + } + } + else + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + { + errno = 0; + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i], 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 *) ®isters[REGISTER_BYTE (regno) + i], 0); - if (errno != 0) - { - sprintf (buf, "writing register number %d(%d)", regno, i); - perror_with_name (buf); - } - regaddr += sizeof(int); - } + errno = 0; + if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM) + { + scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3; + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + scratch, 0); + if (errno != 0) + { + sprintf (buf, "writing register number %d(%d)", regno, i); + perror_with_name (buf); + } + } + else + for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) + { + errno = 0; + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + *(int *) ®isters[REGISTER_BYTE (regno) + i], 0); + if (errno != 0) + { + sprintf (buf, "writing register number %d(%d)", regno, i); + perror_with_name (buf); + } + regaddr += sizeof(int); + } } } return; @@ -165,9 +197,7 @@ 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 () { -#if 0 struct user u; -#endif nlist ("/hp-ux", &nl); kernel_u_addr = nl[0].n_value; } @@ -213,6 +243,8 @@ fetch_register (regno) perror_with_name (mess); } } + if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM) + buf[3] &= ~0x3; supply_register (regno, buf); } @@ -280,14 +312,14 @@ child_xfer_memory (memaddr, myaddr, len, write, target) 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); + buffer[0] = ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER, + 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 (addr < text_end ? PT_RIUSER : PT_RDUSER, inferior_pid, (PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (int)), 0, 0); } @@ -300,24 +332,15 @@ child_xfer_memory (memaddr, myaddr, len, write, target) 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, + ptrace (addr < text_end ? PT_WIUSER : 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; } } @@ -327,8 +350,8 @@ child_xfer_memory (memaddr, myaddr, len, write, target) for (i = 0; i < count; i++, addr += sizeof (int)) { errno = 0; - buffer[i] = ptrace (PT_RIUSER, inferior_pid, - (PTRACE_ARG3_TYPE) addr, 0, 0); + buffer[i] = ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER, + inferior_pid, (PTRACE_ARG3_TYPE) addr, 0, 0); if (errno) return 0; QUIT; @@ -339,4 +362,3 @@ child_xfer_memory (memaddr, myaddr, len, write, target) } return len; } - diff --git a/gdb/hppah-tdep.c b/gdb/hppah-tdep.c index 9473400..67aae83 100644 --- a/gdb/hppah-tdep.c +++ b/gdb/hppah-tdep.c @@ -51,45 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <sys/file.h> #include <sys/stat.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 "wait.h" #include "gdbcore.h" #include "gdbcmd.h" +#include "target.h" -extern int errno; - - - - - /* Last modification time of executable file. Also used in source.c to compare against mtime of a source file. */ @@ -130,435 +98,6 @@ 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. */ @@ -720,8 +259,7 @@ extract_17 (word) GET_FIELD (word, 11, 15) << 11 | (word & 0x1) << 16, 17) << 2; } - - + CORE_ADDR frame_saved_pc (frame) FRAME frame; @@ -730,19 +268,21 @@ frame_saved_pc (frame) { struct frame_saved_regs saved_regs; CORE_ADDR pc = get_frame_pc (frame); + int flags; + flags = read_register (FLAGS_REGNUM); get_frame_saved_regs (frame, &saved_regs); - if (pc >= millicode_start && pc < millicode_end) - return read_register (31); + if (pc >= millicode_start && pc < millicode_end + || (flags & 2)) /* In system call? */ + return read_register (31) & ~3; else if (saved_regs.regs[RP_REGNUM]) - return read_memory_integer (saved_regs.regs[RP_REGNUM], 4); + return read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~3; else - return read_register (RP_REGNUM); + return read_register (RP_REGNUM) & ~3; } 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. */ @@ -750,12 +290,7 @@ 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 - )) + if (chain && (chain > 0x60000000)) { CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe)); @@ -802,31 +337,161 @@ gcc_p (pc) return 0; } +/* + * These functions deal with saving and restoring register state + * around a function call in the inferior. They keep the stack + * double-word aligned; eventually, on an hp700, the stack will have + * to be aligned to a 64-byte boundary. + */ + +int +push_dummy_frame () +{ + register CORE_ADDR sp = read_register (SP_REGNUM); + register int regnum; + int int_buffer; + double freg_buffer; + /* Space for "arguments"; the RP goes in here. */ + sp += 48; + int_buffer = read_register (RP_REGNUM) | 0x3; + write_memory (sp - 20, (char *)&int_buffer, 4); + int_buffer = read_register (FP_REGNUM); + write_memory (sp, (char *)&int_buffer, 4); + write_register (FP_REGNUM, sp); + sp += 8; + for (regnum = 1; regnum < 32; regnum++) + if (regnum != RP_REGNUM && regnum != FP_REGNUM) + sp = push_word (sp, read_register (regnum)); + sp += 4; + for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++) + { read_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8); + sp = push_bytes (sp, (char *)&freg_buffer, 8);} + sp = push_word (sp, read_register (IPSW_REGNUM)); + sp = push_word (sp, read_register (SAR_REGNUM)); + sp = push_word (sp, read_register (PCOQ_HEAD_REGNUM)); + sp = push_word (sp, read_register (PCSQ_HEAD_REGNUM)); + sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM)); + sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM)); + write_register (SP_REGNUM, sp); +} + 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++) + for (fp += 16, i = 5; i < 32; 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[IPSW_REGNUM] = fp; fp += 4; + frame_saved_regs->regs[SAR_REGNUM] = fp; fp += 4; + frame_saved_regs->regs[PCOQ_HEAD_REGNUM] = fp; fp +=4; + frame_saved_regs->regs[PCSQ_HEAD_REGNUM] = fp; fp +=4; + frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp; fp +=4; frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp; } +int +hp_pop_frame () +{ + register FRAME frame = get_current_frame (); + register CORE_ADDR fp; + register int regnum; + struct frame_saved_regs fsr; + struct frame_info *fi; + double freg_buffer; + fi = get_frame_info (frame); + fp = fi->frame; + get_frame_saved_regs (fi, &fsr); + if (fsr.regs[IPSW_REGNUM]) /* Restoring a call dummy frame */ + hp_restore_pc_queue (&fsr); + for (regnum = 31; regnum > 0; regnum--) + if (fsr.regs[regnum]) + write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--) + if (fsr.regs[regnum]) + { read_memory (fsr.regs[regnum], (char *)&freg_buffer, 8); + write_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8); + } + if (fsr.regs[IPSW_REGNUM]) + write_register (IPSW_REGNUM, + read_memory_integer (fsr.regs[IPSW_REGNUM], 4)); + if (fsr.regs[SAR_REGNUM]) + write_register (SAR_REGNUM, + read_memory_integer (fsr.regs[SAR_REGNUM], 4)); + if (fsr.regs[PCOQ_TAIL_REGNUM]) + write_register (PCOQ_TAIL_REGNUM, + read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4)); + write_register (FP_REGNUM, read_memory_integer (fp, 4)); + if (fsr.regs[IPSW_REGNUM]) /* call dummy */ + write_register (SP_REGNUM, fp - 48); + else + write_register (SP_REGNUM, fp); + flush_cached_frames (); + set_current_frame (create_new_frame (read_register (FP_REGNUM), + read_pc ())); +} + +/* + * After returning to a dummy on the stack, restore the instruction + * queue space registers. */ + +int +hp_restore_pc_queue (fsr) + struct frame_saved_regs *fsr; +{ + CORE_ADDR pc = read_pc (); + CORE_ADDR new_pc = read_memory_integer (fsr->regs[PCOQ_HEAD_REGNUM], 4); + int pid; + WAITTYPE w; + int insn_count; + + /* Advance past break instruction in the call dummy. */ + pc += 4; write_register (PCOQ_HEAD_REGNUM, pc); + pc += 4; write_register (PCOQ_TAIL_REGNUM, pc); + + /* + * HPUX doesn't let us set the space registers or the space + * registers of the PC queue through ptrace. Boo, hiss. + * Conveniently, the call dummy has this sequence of instructions + * after the break: + * mtsp r21, sr0 + * ble,n 0(sr0, r22) + * + * So, load up the registers and single step until we are in the + * right place. + */ + + write_register (21, read_memory_integer (fsr->regs[PCSQ_HEAD_REGNUM], 4)); + write_register (22, new_pc); + + for (insn_count = 0; insn_count < 3; insn_count++) + { + resume (1, 0); + target_wait(&w); + + if (!WIFSTOPPED (w)) + { + stop_signal = WTERMSIG (w); + terminal_ours_for_output (); + printf ("\nProgram terminated with signal %d, %s\n", + stop_signal, safe_strsignal (stop_signal)); + fflush (stdout); + return 0; + } + } + fetch_inferior_registers (-1); + return 1; +} + CORE_ADDR hp_push_arguments (nargs, args, sp, struct_return, struct_addr) int nargs; @@ -850,14 +515,15 @@ hp_push_arguments (nargs, args, sp, struct_return, struct_addr) cum = (cum + alignment) & -alignment; offset[i] = -cum; } - for (i == 0; i < nargs; i++) + sp += min ((cum + 7) & -8, 16); + for (i = 0; i < nargs; i++) { - write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int)); + write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), + TYPE_LENGTH (VALUE_TYPE (args[i]))); } - sp += min ((cum + 7) & -8, 48); if (struct_return) write_register (28, struct_addr); - return sp + 48; + return sp + 32; } /* return the alignment of a type in bytes. Structures have the maximum @@ -905,8 +571,8 @@ pa_do_registers_info (regnum, fpregs) 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); + if (regnum == -1) + pa_print_registers (raw_regs, regnum, fpregs); else if (regnum < FP0_REGNUM) { printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs + @@ -916,9 +582,10 @@ pa_do_registers_info (regnum, fpregs) pa_print_fp_reg (regnum); } -pa_print_registers (raw_regs, regnum) +pa_print_registers (raw_regs, regnum, fpregs) char *raw_regs; int regnum; + int fpregs; { int i; @@ -932,8 +599,10 @@ pa_print_registers (raw_regs, regnum) *(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); + + if (fpregs) + for (i = 72; i < NUM_REGS; i++) + pa_print_fp_reg (i); } pa_print_fp_reg (i) @@ -956,470 +625,26 @@ pa_print_fp_reg (i) } -/* - * 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); -} +/* Function calls that pass into a new compilation unit must pass through a + small piece of code that does long format (`external' in HPPA parlance) + jumps. We figure out where the trampoline is going to end up, and return + the PC of the final destination. If we aren't in a trampoline, we just + return NULL. */ -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 +skip_trampoline_code (pc) + CORE_ADDR pc; { - CORE_ADDR paddr; + long inst0, inst1; - 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); + inst0 = read_memory_integer (pc, 4); + inst1 = read_memory_integer (pc+4, 4); - if (ptr == 0) - fatal("no memory for %s", str); - return(ptr); -} -#endif + if ( (inst0 & 0xffe00000) == 0x20200000 /* ldil xxx, r1 */ + && (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */ + pc = extract_21 (inst0) + extract_17 (inst1); + else + pc = NULL; -#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); + return pc; } -#endif diff --git a/gdb/i860-tdep.c b/gdb/i860-tdep.c index 4919866..702afaf 100644 --- a/gdb/i860-tdep.c +++ b/gdb/i860-tdep.c @@ -76,7 +76,6 @@ int ansi_conformant; #define BTDEBUG if (btdebug) btdebug_message extern int errno; -extern int attach_flag; extern char registers[]; CORE_ADDR get_saved_basereg(); diff --git a/gdb/infrun.c b/gdb/infrun.c index 16404f3..ab4e3e0 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -186,6 +186,16 @@ hook_stop_stub PARAMS ((char *)); #define IN_SOLIB_TRAMPOLINE(pc,name) 0 #endif +/* On some systems, the PC may be left pointing at an instruction that won't + actually be executed. This is usually indicated by a bit in the PSW. If + we find ourselves in such a state, then we step the target beyond the + nullified instruction before returning control to the user so as to avoid + confusion. */ + +#ifndef INSTRUCTION_NULLIFIED +#define INSTRUCTION_NULLIFIED 0 +#endif + #ifdef TDESC #include "tdesc.h" int safe_to_init_tdesc_context = 0; @@ -576,6 +586,15 @@ wait_for_inferior () single_step (0); /* This actually cleans up the ss */ #endif /* NO_SINGLE_STEP */ +/* If PC is pointing at a nullified instruction, then step beyond it so that + the user won't be confused when GDB appears to be ready to execute it. */ + + if (INSTRUCTION_NULLIFIED) + { + resume (1, 0); + continue; + } + stop_pc = read_pc (); set_current_frame ( create_new_frame (read_register (FP_REGNUM), read_pc ())); @@ -973,7 +992,7 @@ wait_for_inferior () if (tmp != 0) stop_func_start = tmp; - symtab = find_pc_symtab (stop_pc); + symtab = find_pc_symtab (stop_func_start); if (symtab && LINETABLE (symtab)) goto step_into_function; diff --git a/gdb/tm-hppa.h b/gdb/tm-hppa.h index b374a8b..285e932 100644 --- a/gdb/tm-hppa.h +++ b/gdb/tm-hppa.h @@ -1,4 +1,5 @@ -/* Parameters for execution on a Hewlett-Packard PA-RISC machine. +/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running + HPUX or BSD. Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Contributed by the Center for Software Science at the @@ -71,6 +72,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000) \ (pc) += 4;} +/* If PC is in some function-call trampoline code, return the PC + where the function itself actually starts. If not, return NULL. */ + +#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc) + +/* Return non-zero if we are in some sort of a trampoline. */ + +#define IN_SOLIB_TRAMPOLINE(pc,name) skip_trampoline_code (pc) + /* 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 @@ -150,6 +160,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ to be actual register numbers as far as the user is concerned but do serve to get the desired values when passed to read_register. */ +#define FLAGS_REGNUM 0 /* Various status flags */ #define RP_REGNUM 2 /* return pointer */ #define FP_REGNUM 4 /* Contains address of executing stack */ /* frame */ @@ -222,14 +233,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Convert data from raw format for register REGNUM to virtual format for register REGNUM. */ -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ -{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); } +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM, FROM, TO) \ +{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); } /* Convert data from virtual format for register REGNUM to raw format for register REGNUM. */ -#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \ -{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); } +#define REGISTER_CONVERT_TO_RAW(REGNUM, FROM, TO) \ +{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); } /* Return the GDB type object for the "standard" data type of data in register N. */ @@ -263,6 +274,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)((REGBUF) + 28)) +/* + * This macro defines the register numbers (from REGISTER_NAMES) that + * are effectively unavailable to the user through ptrace(). It allows + * us to include the whole register set in REGISTER_NAMES (inorder to + * better support remote debugging). If it is used in + * fetch/store_inferior_registers() gdb will not complain about I/O errors + * on fetching these registers. If all registers in REGISTER_NAMES + * are available, then return false (0). + */ + +#define CANNOT_STORE_REGISTER(regno) \ + ((regno) == 0) || \ + ((regno) == PCSQ_HEAD_REGNUM) || \ + ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \ + ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM) + /* This is a piece of magic that is given a register number REGNO and as BLOCKEND the address in the system of the end of the user structure and stores in ADDR the address in the kernel or core dump @@ -332,7 +359,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000) #define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000) - #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ { register int regnum; \ register CORE_ADDR next_addr; \ @@ -341,9 +367,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ unsigned address; \ \ bzero (&frame_saved_regs, sizeof frame_saved_regs); \ - if ((frame_info)->pc <= ((frame_info)->frame - CALL_DUMMY_LENGTH - \ - FP_REGNUM * 4 - 16 * 8) \ - && (frame_info)->pc > (frame_info)->frame) \ + if ((frame_info->pc >= (frame_info)->frame \ + && (frame_info)->pc <= ((frame_info)->frame + CALL_DUMMY_LENGTH \ + + 32 * 4 + (NUM_REGS - FP0_REGNUM) * 8 \ + + 6 * 4))) \ find_dummy_frame_regs ((frame_info), &(frame_saved_regs)); \ else \ { pc = get_pc_function_start ((frame_info)->pc); \ @@ -402,6 +429,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ { regnum = GET_FIELD (this_insn, 27, 31); \ (frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \ next_addr += 8; \ + pc += 4; \ } \ else \ break; \ @@ -415,67 +443,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Push an empty stack frame, to record the current PC, etc. */ -#define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ - register int regnum; \ - int int_buffer; \ - char freg_buffer[8]; \ - /* Space for "arguments"; the RP goes in here. */ \ - sp += 48; \ - int_buffer = read_register (RP_REGNUM) | 0x3; \ - write_memory (sp - 20, (char *)&int_buffer, 4); \ - int_buffer = read_register (FP_REGNUM); \ - write_memory (sp, (char *)&int_buffer, 4); \ - write_register (FP_REGNUM, sp); \ - sp += 4; \ - for (regnum = 1; regnum < 31; regnum++) \ - if (regnum != RP_REGNUM && regnum != FP_REGNUM) \ - sp = push_word (sp, read_register (regnum)); \ - for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++) \ - { read_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); \ - sp = push_bytes (sp, freg_buffer, 8);} \ - sp = push_word (sp, read_register (IPSW_REGNUM)); \ - sp = push_word (sp, read_register (SAR_REGNUM)); \ - sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM)); \ - sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM)); \ - write_register (SP_REGNUM, sp);} +#define PUSH_DUMMY_FRAME push_dummy_frame () /* Discard from the stack the innermost frame, restoring all saved registers. */ -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char freg_buffer[8]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = 31; regnum > 0; regnum--) \ - if (fsr.regs[regnum]) \ - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], freg_buffer, 8); \ - write_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); }\ - if (fsr.regs[IPSW_REGNUM]) \ - write_register (IPSW_REGNUM, \ - read_memory_integer (fsr.regs[IPSW_REGNUM], 4)); \ - if (fsr.regs[SAR_REGNUM]) \ - write_register (SAR_REGNUM, \ - read_memory_integer (fsr.regs[SAR_REGNUM], 4)); \ - if (fsr.regs[PCOQ_TAIL_REGNUM]) \ - write_register (PCOQ_TAIL_REGNUM, \ - read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));\ - if (fsr.regs[PCSQ_TAIL_REGNUM]) \ - write_register (PCSQ_TAIL_REGNUM, \ - read_memory_integer (fsr.regs[PCSQ_TAIL_REGNUM], 4));\ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ())); } +#define POP_FRAME hp_pop_frame () /* This sequence of words is the instructions @@ -498,15 +470,19 @@ call_dummy ldsid (0,r22), r3 ldil 0, r1 ; _sr4export will be placed here. ldo 0(r1), r1 - ldsid (0,r1), r4 - combt,=,n r3, r4, text_space ; If target is in data space, do a + ldsid (0,r1), r19 + combt,=,n r3, r19, text_space ; If target is in data space, do a ble 0(sr5, r22) ; "normal" procedure call copy r31, r2 break 4, 8 + mtsp r21, sr0 + ble,n 0(sr0, r22) text_space ; Otherwise, go through _sr4export, ble (sr4, r1) ; which will return back here. stw 31,-24(r30) break 4, 8 + mtsp r21, sr0 + ble,n 0(sr0, r22) The dummy decides if the target is in text space or data space. If it's in data space, there's no problem because the target can @@ -517,60 +493,98 @@ text_space ; Otherwise, go through _sr4export, know that the frame is associated with the call dummy and treat it specially. */ -#define CALL_DUMMY { 0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1, \ - 0x37c13fb9, 0x24201004, 0x2c391005, 0x24311006, \ - 0x2c291007, 0x22c00000, 0x36d60000, 0x02c010a3, \ - 0x20200000, 0x34210000, 0x002010a4, 0x80832012, \ - 0xe6c06000, 0x081f0242, 0x00010004, 0xe4202000, \ - 0x6bdf3fd1, 0x00010004} +#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\ + 0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\ + 0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A3,\ + 0x20200000, 0x34210000, 0x002010b3, 0x82632022,\ + 0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\ + 0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\ + 0x00151820, 0xe6c00002} -#define CALL_DUMMY_LENGTH 88 +#define CALL_DUMMY_LENGTH 104 #define CALL_DUMMY_START_OFFSET 0 -/* Insert the specified number of args and function address - into a call sequence of the above form stored at DUMMYNAME. */ -#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \ -{ static CORE_ADDR sr4export_address = 0; \ - \ - if (!sr4export_address) \ - { \ + +/* + * Insert the specified number of args and function address + * into a call sequence of the above form stored at DUMMYNAME. + * + * On the hppa we need to call the stack dummy through $$dyncall. + * Therefore our version of FIX_CALL_DUMMY takes an extra argument, + * real_pc, which is the location where gdb should start up the + * inferior to do the function call. + */ + +#define FIX_CALL_DUMMY(dummyname, pc, real_pc, fun, nargs, args, type, gcc_p) \ +{ \ + CORE_ADDR dyncall_addr = 0, sr4export_addr = 0; \ + \ + if (!dyncall_addr) \ + { \ struct minimal_symbol *msymbol; \ + msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL);\ + if (msymbol == NULL) \ + error ("Can't find an address for $$dyncall trampoline"); \ + else \ + dyncall_addr = msymbol -> address; \ msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\ - if (msymbol = NULL) \ - error ("Can't find an address for _sr4export trampoline"); \ - else \ - sr4export_address = msymbol -> address; \ - } \ - dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \ - dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \ - dummyname[12] = deposit_21 (sr4export_address >> 11, dummyname[12]); \ - dummyname[13] = deposit_14 (sr4export_address & MASK_11, dummyname[13]);\ + if (msymbol == NULL) \ + error ("Can't find an address for _sr4export trampoline"); \ + else \ + sr4export_addr = msymbol -> address; \ + } \ + dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \ + dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \ + dummyname[12] = deposit_21 (sr4export_addr >> 11, \ + dummyname[12]); \ + dummyname[13] = deposit_14 (sr4export_addr & MASK_11, \ + dummyname[13]); \ + write_register (22, pc); \ + real_pc = dyncall_addr; \ } - #define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \ sp = hp_push_arguments(nargs, args, sp, struct_return, struct_addr) -/* Write the PC to a random value. - On PA-RISC, we need to be sure that the PC space queue is correct. */ - -#define WRITE_PC(addr) \ -{ int space_reg, space = ((addr) >> 30); \ - int space_val; \ - if (space == 0) \ - space_reg = 43; /* Space reg sr4 */ \ - else if (space == 1) \ - space_reg = 48; /* Space reg sr5*/ \ - else \ - error ("pc = %x is in illegal space.", addr); \ - space_val = read_register (space_reg); \ - write_register (PCOQ_HEAD_REGNUM, addr); \ - write_register (PCSQ_HEAD_REGNUM, space_val); \ - write_register (PCOQ_TAIL_REGNUM, addr); \ - write_register (PCSQ_TAIL_REGNUM, space_val);} - /* Symbol files have two symbol tables. Rather than do this right, like the ELF symbol reading code, massive hackery was added to dbxread.c and partial-stab.h. This flag turns on that hackery, which should all go away FIXME FIXME FIXME FIXME now. */ #define GDB_TARGET_IS_HPPA + +/* + * Unwind table and descriptor. + */ + +struct unwind_table_entry { + unsigned int region_start; + unsigned int region_end; + + unsigned int Cannot_unwind : 1; + unsigned int Millicode : 1; + unsigned int Millicode_save_sr0 : 1; + unsigned int Region_description : 2; + unsigned int reserverd1 : 1; + unsigned int Entry_SR : 1; + unsigned int Entry_FR : 4; /* number saved */ + unsigned int Entry_GR : 5; /* number saved */ + unsigned int Args_stored : 1; + unsigned int Variable_Frame : 1; + unsigned int Separate_Package_Body : 1; + unsigned int Frame_Extension_Millicode:1; + unsigned int Stack_Overflow_Check : 1; + unsigned int Two_Instruction_SP_Increment:1; + unsigned int Ada_Region : 1; + unsigned int reserved2 : 4; + unsigned int Save_SP : 1; + unsigned int Save_RP : 1; + unsigned int Save_MRP_in_frame : 1; + unsigned int extn_ptr_defined : 1; + unsigned int Cleanup_defined : 1; + + unsigned int MPE_XL_interrupt_marker: 1; + unsigned int HP_UX_interrupt_marker: 1; + unsigned int Large_frame : 1; + unsigned int reserved4 : 2; + unsigned int Total_frame_size : 27; +}; diff --git a/gdb/valops.c b/gdb/valops.c index d29b1d8..b72669e 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -704,6 +704,7 @@ call_function_by_hand (function, nargs, args) struct cleanup *old_chain; CORE_ADDR funaddr; int using_gcc; + CORE_ADDR real_pc; if (!target_has_execution) noprocess(); @@ -745,8 +746,15 @@ call_function_by_hand (function, nargs, args) memcpy (dummy1, dummy, sizeof dummy); for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++) SWAP_TARGET_AND_HOST (&dummy1[i], sizeof (REGISTER_TYPE)); + +#ifdef GDB_TARGET_IS_HPPA + FIX_CALL_DUMMY (dummy1, start_sp, real_pc, funaddr, nargs, args, + value_type, using_gcc); +#else FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args, value_type, using_gcc); + real_pc = start_sp; +#endif #if CALL_DUMMY_LOCATION == ON_STACK write_memory (start_sp, (char *)dummy1, sizeof dummy); @@ -891,7 +899,7 @@ call_function_by_hand (function, nargs, args) /* Execute the stack dummy routine, calling FUNCTION. When it is done, discard the empty frame after storing the contents of all regs into retbuf. */ - run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf); + run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf); do_cleanups (old_chain); @@ -1086,8 +1094,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type) if (BASETYPE_VIA_VIRTUAL (type, i)) { - base_offset = - baseclass_offset (type, i, *arg1p, offset); + base_offset = baseclass_offset (type, i, *arg1p, offset); if (base_offset == -1) error ("virtual baseclass botch"); } |