From: Stu Grossman Date: Fri, 23 Apr 1993 23:43:18 +0000 (+0000) Subject: * Merge in HPPA/BSD patches from Utah: X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=66a1aa071ea2f7868b29a6c1e81febb12c88c12c;p=binutils-gdb.git * Merge in HPPA/BSD patches from Utah: * defs.h: Add const to 2nd arg of psignal prototype. * hppah-tdep.c: Renamed to hppa-tdep.c 'cuz it's common code with BSD now. * hppab-core.c: Deleted. No longer useful. * hppab-nat.c: #include more files. Use PT_WUREGS, not PT_WRITE_U. * hppab-tdep.c: Deleted. Supplanted by hppa-tdep.c. * config/pa/hppabsd.mh (NATDEPFILES): Remove hppab-core.o. * config/pa/hppabsd.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o * config/pa/hppahpux.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o * config/pa/xm-hppab.h: #define SET_STACK_LIMIT_HUGE. --- diff --git a/gdb/.Sanitize b/gdb/.Sanitize index cacb6a13028..0a7bd4db260 100644 --- a/gdb/.Sanitize +++ b/gdb/.Sanitize @@ -107,11 +107,9 @@ h8300-tdep.c h8500-tdep.c hp300ux-nat.c hppa-pinsn.c -hppab-core.c +hppa-tdep.c hppab-nat.c -hppab-tdep.c hppah-nat.c -hppah-tdep.c i386-pinsn.c i386-stub.c i386-tdep.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 55a5ec0e421..7fb3e5c1b71 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +Fri Apr 23 16:17:00 1993 Stu Grossman (grossman@cygnus.com) + + * Merge in HPPA/BSD patches from Utah: + * defs.h: Add const to 2nd arg of psignal prototype. + * hppah-tdep.c: Renamed to hppa-tdep.c 'cuz it's common code with + BSD now. + * hppab-core.c: Deleted. No longer useful. + * hppab-nat.c: #include more files. Use PT_WUREGS, not + PT_WRITE_U. + * hppab-tdep.c: Deleted. Supplanted by hppa-tdep.c. + * config/pa/hppabsd.mh (NATDEPFILES): Remove hppab-core.o. + * config/pa/hppabsd.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o + * config/pa/hppahpux.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o + * config/pa/xm-hppab.h: #define SET_STACK_LIMIT_HUGE. + Fri Apr 23 10:34:02 1993 Stu Grossman (grossman@cygnus.com) * Fix two bugs found by deja-gnu. One is the incorrect reporting diff --git a/gdb/config/pa/hppabsd.mh b/gdb/config/pa/hppabsd.mh index 2efde1ac5dd..2e5b76a750f 100644 --- a/gdb/config/pa/hppabsd.mh +++ b/gdb/config/pa/hppabsd.mh @@ -2,4 +2,4 @@ XDEPFILES= XM_FILE= xm-hppab.h NAT_FILE= nm-hppab.h -NATDEPFILES= hppab-nat.o coredep.o corelow.o exec.o hppab-core.o +NATDEPFILES= hppab-nat.o coredep.o corelow.o exec.o diff --git a/gdb/config/pa/hppabsd.mt b/gdb/config/pa/hppabsd.mt index 1260ab70df2..14fae960848 100644 --- a/gdb/config/pa/hppabsd.mt +++ b/gdb/config/pa/hppabsd.mt @@ -1,4 +1,4 @@ # TARGET: HP PA-RISC running bsd -TDEPFILES= hppa-pinsn.o hppab-tdep.o +TDEPFILES= hppa-pinsn.o hppa-tdep.o TM_FILE= tm-hppab.h diff --git a/gdb/config/pa/xm-hppab.h b/gdb/config/pa/xm-hppab.h index 22f67d7ecae..9ecfd4f7ce7 100644 --- a/gdb/config/pa/xm-hppab.h +++ b/gdb/config/pa/xm-hppab.h @@ -40,3 +40,5 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # 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 */ + +#define SET_STACK_LIMIT_HUGE diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c new file mode 100644 index 00000000000..4d2a38a2e11 --- /dev/null +++ b/gdb/hppa-tdep.c @@ -0,0 +1,938 @@ +/* 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, 1993 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 +#endif + +#include +#include +#include +#include + +#ifdef COFF_ENCAPSULATE +#include "a.out.encap.h" +#else +#include +#endif +#ifndef N_SET_MAGIC +#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) +#endif + +/*#include After a.out.h */ +#include +#include +#include +#include "wait.h" + +#include "gdbcore.h" +#include "gdbcmd.h" +#include "target.h" +#include "symfile.h" +#include "objfiles.h" + +static int restore_pc_queue PARAMS ((struct frame_saved_regs *fsr)); +static int hppa_alignof PARAMS ((struct type *arg)); + + +/* 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; +} + +static int use_unwind = 0; + +/* Lookup the unwind (stack backtrace) info for the given PC. We search all + of the objfiles seeking the unwind table entry for this PC. Each objfile + contains a sorted list of struct unwind_table_entry. Since we do a binary + search of the unwind tables, we depend upon them to be sorted. */ + +static struct unwind_table_entry * +find_unwind_entry(pc) + CORE_ADDR pc; +{ + int first, middle, last; + struct objfile *objfile; + + ALL_OBJFILES (objfile) + { + struct obj_unwind_info *ui; + + ui = OBJ_UNWIND_INFO (objfile); + + if (!ui) + continue; + + /* First, check the cache */ + + if (ui->cache + && pc >= ui->cache->region_start + && pc <= ui->cache->region_end) + return ui->cache; + + /* Not in the cache, do a binary search */ + + first = 0; + last = ui->last; + + while (first <= last) + { + middle = (first + last) / 2; + if (pc >= ui->table[middle].region_start + && pc <= ui->table[middle].region_end) + { + ui->cache = &ui->table[middle]; + return &ui->table[middle]; + } + + if (pc < ui->table[middle].region_start) + last = middle - 1; + else + first = middle + 1; + } + } /* ALL_OBJFILES() */ + return NULL; +} + +static int +find_return_regnum(pc) + CORE_ADDR pc; +{ + struct unwind_table_entry *u; + + u = find_unwind_entry (pc); + + if (!u) + return RP_REGNUM; + + if (u->Millicode) + return 31; + + return RP_REGNUM; +} + +int +find_proc_framesize(pc) + CORE_ADDR pc; +{ + struct unwind_table_entry *u; + + if (!use_unwind) + return -1; + + u = find_unwind_entry (pc); + + if (!u) + return -1; + + return u->Total_frame_size << 3; +} + +int +rp_saved(pc) +{ + struct unwind_table_entry *u; + + u = find_unwind_entry (pc); + + if (!u) + return 0; + + if (u->Save_RP) + return 1; + else + return 0; +} + +CORE_ADDR +saved_pc_after_call (frame) + FRAME frame; +{ + int ret_regnum; + + ret_regnum = find_return_regnum (get_frame_pc (frame)); + + return read_register (ret_regnum) & ~0x3; +} + +CORE_ADDR +frame_saved_pc (frame) + FRAME frame; +{ + CORE_ADDR pc = get_frame_pc (frame); + + if (frameless_look_for_prologue (frame)) + { + int ret_regnum; + + ret_regnum = find_return_regnum (pc); + + return read_register (ret_regnum) & ~0x3; + } + else if (rp_saved (pc)) + return read_memory_integer (frame->frame - 20, 4) & ~0x3; + else + return read_register (RP_REGNUM) & ~0x3; +} + +/* We need to correct the PC and the FP for the outermost frame when we are + in a system call. */ + +void +init_extra_frame_info (fromleaf, frame) + int fromleaf; + struct frame_info *frame; +{ + int flags; + int framesize; + + if (frame->next) /* Only do this for outermost frame */ + return; + + flags = read_register (FLAGS_REGNUM); + if (flags & 2) /* In system call? */ + frame->pc = read_register (31) & ~0x3; + + /* The outermost frame is always derived from PC-framesize */ + framesize = find_proc_framesize(frame->pc); + if (framesize == -1) + frame->frame = read_register (FP_REGNUM); + else + frame->frame = read_register (SP_REGNUM) - framesize; + + if (!frameless_look_for_prologue (frame)) /* Frameless? */ + return; /* No, quit now */ + + /* For frameless functions, we need to look at the caller's frame */ + framesize = find_proc_framesize(FRAME_SAVED_PC(frame)); + if (framesize != -1) + frame->frame -= framesize; +} + +FRAME_ADDR +frame_chain (frame) + struct frame_info *frame; +{ + int framesize; + + framesize = find_proc_framesize(FRAME_SAVED_PC(frame)); + + if (framesize != -1) + return frame->frame - framesize; + + return read_memory_integer (frame->frame, 4); +} + +/* 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; +{ + struct minimal_symbol *msym; + + if (!chain) + return 0; + + msym = lookup_minimal_symbol_by_pc (FRAME_SAVED_PC (thisframe)); + + if (msym + && (strcmp (SYMBOL_NAME (msym), "_start") == 0)) + return 0; + else + return 1; +} + +#if 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; +} +#endif + +/* + * 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; + register int regnum; + int int_buffer; + double freg_buffer; + + /* Space for "arguments"; the RP goes in here. */ + sp = read_register (SP_REGNUM) + 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 = 5; i < 32; fp += 4, i++) + frame_saved_regs->regs[i] = fp; + + fp += 4; + for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8) + frame_saved_regs->regs[i] = 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 +hppa_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 */ + 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. */ + +static int +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. */ + write_register (PCOQ_HEAD_REGNUM, pc + 4); + write_register (PCOQ_TAIL_REGNUM, pc + 8); + + /* + * 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 +hppa_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++) + { + /* Coerce chars to int & float to double if necessary */ + args[i] = value_arg_coerce (args[i]); + + cum += TYPE_LENGTH (VALUE_TYPE (args[i])); + + /* value must go at proper alignment. Assume alignment is a + power of two.*/ + alignment = hppa_alignof (VALUE_TYPE (args[i])); + if (cum % alignment) + cum = (cum + alignment) & -alignment; + offset[i] = -cum; + } + sp += min ((cum + 7) & -8, 16); + + for (i = 0; i < nargs; i++) + write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), + TYPE_LENGTH (VALUE_TYPE (args[i]))); + + if (struct_return) + write_register (28, struct_addr); + return sp + 32; +} + +/* + * 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. + */ + +CORE_ADDR +hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) + REGISTER_TYPE *dummy; + CORE_ADDR pc; + CORE_ADDR fun; + int nargs; + value *args; + struct type *type; + int gcc_p; +{ + CORE_ADDR dyncall_addr, sr4export_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"); + + dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol); + + msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL); + if (msymbol == NULL) + error ("Can't find an address for _sr4export trampoline"); + + sr4export_addr = SYMBOL_VALUE_ADDRESS (msymbol); + + dummy[9] = deposit_21 (fun >> 11, dummy[9]); + dummy[10] = deposit_14 (fun & MASK_11, dummy[10]); + dummy[12] = deposit_21 (sr4export_addr >> 11, dummy[12]); + dummy[13] = deposit_14 (sr4export_addr & MASK_11, dummy[13]); + + write_register (22, pc); + + return dyncall_addr; +} + +/* return the alignment of a type in bytes. Structures have the maximum + alignment required by their fields. */ + +static int +hppa_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 hppa_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 = hppa_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, fpregs); + 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, fpregs) + char *raw_regs; + int regnum; + int fpregs; +{ + 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))); + + if (fpregs) + 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"); +} + +/* 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. + + For computed calls, we just extract the new PC from r22. */ + +CORE_ADDR +skip_trampoline_code (pc, name) + CORE_ADDR pc; + char *name; +{ + long inst0, inst1; + static CORE_ADDR dyncall = 0; + struct minimal_symbol *msym; + +/* FIXME XXX - dyncall must be initialized whenever we get a new exec file */ + + if (!dyncall) + { + msym = lookup_minimal_symbol ("$$dyncall", NULL); + if (msym) + dyncall = SYMBOL_VALUE_ADDRESS (msym); + else + dyncall = -1; + } + + if (pc == dyncall) + return (CORE_ADDR)(read_register (22) & ~0x3); + + inst0 = read_memory_integer (pc, 4); + inst1 = read_memory_integer (pc+4, 4); + + if ( (inst0 & 0xffe00000) == 0x20200000 /* ldil xxx, r1 */ + && (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */ + pc = extract_21 (inst0) + extract_17 (inst1); + else + pc = (CORE_ADDR)NULL; + + return pc; +} + +/* Advance PC across any function entry prologue instructions + to reach some "real" code. */ + +/* skip (stw rp, -20(0,sp)); copy 4,1; copy sp, 4; stwm 1,framesize(sp) + for gcc, or (stw rp, -20(0,sp); stwm 1, framesize(sp) for hcc */ + +CORE_ADDR +skip_prologue(pc) + CORE_ADDR pc; +{ + int inst; + int status; + + status = target_read_memory (pc, (char *)&inst, 4); + SWAP_TARGET_AND_HOST (&inst, sizeof (inst)); + if (status != 0) + return pc; + + if (inst == 0x6BC23FD9) /* stw rp,-20(sp) */ + { + if (read_memory_integer (pc + 4, 4) == 0x8040241) /* copy r4,r1 */ + pc += 16; + else if ((read_memory_integer (pc + 4, 4) & ~MASK_14) == 0x68810000) /* stw r1,(r4) */ + pc += 8; + } + else if (read_memory_integer (pc, 4) == 0x8040241) /* copy r4,r1 */ + pc += 12; + else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000) /* stw r1,(r4) */ + pc += 4; + + return pc; +} + +static void +unwind_command (exp, from_tty) + char *exp; + int from_tty; +{ + CORE_ADDR address; + union + { + int *foo; + struct unwind_table_entry *u; + } xxx; + + /* If we have an expression, evaluate it and use it as the address. */ + + if (exp != 0 && *exp != 0) + address = parse_and_eval_address (exp); + else + return; + + xxx.u = find_unwind_entry (address); + + if (!xxx.u) + { + printf ("Can't find unwind table entry for PC 0x%x\n", address); + return; + } + + printf ("%08x\n%08X\n%08X\n%08X\n", xxx.foo[0], xxx.foo[1], xxx.foo[2], + xxx.foo[3]); +} + +void +_initialize_hppah_tdep () +{ + add_com ("unwind", class_obscure, unwind_command, "Print unwind info\n"); + add_show_from_set + (add_set_cmd ("use_unwind", class_obscure, var_boolean, + (char *)&use_unwind, + "Set the usage of unwind info", &setlist), + &showlist); +} diff --git a/gdb/hppab-core.c b/gdb/hppab-core.c index 5ca5f9b9fe7..e69de29bb2d 100644 --- a/gdb/hppab-core.c +++ b/gdb/hppab-core.c @@ -1,251 +0,0 @@ -/* 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 -#endif - -#include -#include -#include -#include -/* #include Can we live without this? */ - -#ifndef hpux -#include -#include -#include -#include "/usr/src/sys/hpux/hpux.h" -#define USRSTACK 0x68FF3000 -#else -#include /* After a.out.h */ -#endif - -#include -#include -#include - -#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-nat.c b/gdb/hppab-nat.c index c0c49b8c204..b066d641ee5 100644 --- a/gdb/hppab-nat.c +++ b/gdb/hppab-nat.c @@ -1,7 +1,7 @@ /* Machine-dependent hooks for the unix child process stratum. This code is for the HP PA-RISC cpu. - Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. Contributed by the Center for Software Science at the University of Utah (pa-gdb-bugs@cs.utah.edu). @@ -24,6 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "inferior.h" +#include "target.h" +#include #ifndef PT_ATTACH #define PT_ATTACH PTRACE_ATTACH @@ -239,7 +241,7 @@ store_inferior_registers (regno) for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) { errno = 0; - ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, *(int *) ®isters[REGISTER_BYTE (regno) + i]); if (errno != 0) { @@ -259,7 +261,7 @@ store_inferior_registers (regno) for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int)) { errno = 0; - ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, + ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, *(int *) ®isters[REGISTER_BYTE (regno) + i]); if (errno != 0) { diff --git a/gdb/hppab-tdep.c b/gdb/hppab-tdep.c index 39d01cb8ed6..e69de29bb2d 100644 --- a/gdb/hppab-tdep.c +++ b/gdb/hppab-tdep.c @@ -1,1421 +0,0 @@ -/* 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 -#endif - -#include -#include -#include -#include - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#else -#include -#endif -#ifndef N_SET_MAGIC -#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) -#endif - -/*#include After a.out.h */ -#include -#include -#include - -#ifdef KERNELDEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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("\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 -#include -#include -#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-tdep.c b/gdb/hppah-tdep.c index cd0d157e721..e69de29bb2d 100644 --- a/gdb/hppah-tdep.c +++ b/gdb/hppah-tdep.c @@ -1,938 +0,0 @@ -/* 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 -#endif - -#include -#include -#include -#include - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#else -#include -#endif -#ifndef N_SET_MAGIC -#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) -#endif - -/*#include After a.out.h */ -#include -#include -#include -#include "wait.h" - -#include "gdbcore.h" -#include "gdbcmd.h" -#include "target.h" -#include "symfile.h" -#include "objfiles.h" - -static int restore_pc_queue PARAMS ((struct frame_saved_regs *fsr)); -static int hppa_alignof PARAMS ((struct type *arg)); - - -/* 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; -} - -static int use_unwind = 0; - -/* Lookup the unwind (stack backtrace) info for the given PC. We search all - of the objfiles seeking the unwind table entry for this PC. Each objfile - contains a sorted list of struct unwind_table_entry. Since we do a binary - search of the unwind tables, we depend upon them to be sorted. */ - -static struct unwind_table_entry * -find_unwind_entry(pc) - CORE_ADDR pc; -{ - int first, middle, last; - struct objfile *objfile; - - ALL_OBJFILES (objfile) - { - struct obj_unwind_info *ui; - - ui = OBJ_UNWIND_INFO (objfile); - - if (!ui) - continue; - - /* First, check the cache */ - - if (ui->cache - && pc >= ui->cache->region_start - && pc <= ui->cache->region_end) - return ui->cache; - - /* Not in the cache, do a binary search */ - - first = 0; - last = ui->last; - - while (first <= last) - { - middle = (first + last) / 2; - if (pc >= ui->table[middle].region_start - && pc <= ui->table[middle].region_end) - { - ui->cache = &ui->table[middle]; - return &ui->table[middle]; - } - - if (pc < ui->table[middle].region_start) - last = middle - 1; - else - first = middle + 1; - } - } /* ALL_OBJFILES() */ - return NULL; -} - -static int -find_return_regnum(pc) - CORE_ADDR pc; -{ - struct unwind_table_entry *u; - - u = find_unwind_entry (pc); - - if (!u) - return RP_REGNUM; - - if (u->Millicode) - return 31; - - return RP_REGNUM; -} - -int -find_proc_framesize(pc) - CORE_ADDR pc; -{ - struct unwind_table_entry *u; - - if (!use_unwind) - return -1; - - u = find_unwind_entry (pc); - - if (!u) - return -1; - - return u->Total_frame_size << 3; -} - -int -rp_saved(pc) -{ - struct unwind_table_entry *u; - - u = find_unwind_entry (pc); - - if (!u) - return 0; - - if (u->Save_RP) - return 1; - else - return 0; -} - -CORE_ADDR -saved_pc_after_call (frame) - FRAME frame; -{ - int ret_regnum; - - ret_regnum = find_return_regnum (get_frame_pc (frame)); - - return read_register (ret_regnum) & ~0x3; -} - -CORE_ADDR -frame_saved_pc (frame) - FRAME frame; -{ - CORE_ADDR pc = get_frame_pc (frame); - - if (frameless_look_for_prologue (frame)) - { - int ret_regnum; - - ret_regnum = find_return_regnum (pc); - - return read_register (ret_regnum) & ~0x3; - } - else if (rp_saved (pc)) - return read_memory_integer (frame->frame - 20, 4) & ~0x3; - else - return read_register (RP_REGNUM) & ~0x3; -} - -/* We need to correct the PC and the FP for the outermost frame when we are - in a system call. */ - -void -init_extra_frame_info (fromleaf, frame) - int fromleaf; - struct frame_info *frame; -{ - int flags; - int framesize; - - if (frame->next) /* Only do this for outermost frame */ - return; - - flags = read_register (FLAGS_REGNUM); - if (flags & 2) /* In system call? */ - frame->pc = read_register (31) & ~0x3; - - /* The outermost frame is always derived from PC-framesize */ - framesize = find_proc_framesize(frame->pc); - if (framesize == -1) - frame->frame = read_register (FP_REGNUM); - else - frame->frame = read_register (SP_REGNUM) - framesize; - - if (!frameless_look_for_prologue (frame)) /* Frameless? */ - return; /* No, quit now */ - - /* For frameless functions, we need to look at the caller's frame */ - framesize = find_proc_framesize(FRAME_SAVED_PC(frame)); - if (framesize != -1) - frame->frame -= framesize; -} - -FRAME_ADDR -frame_chain (frame) - struct frame_info *frame; -{ - int framesize; - - framesize = find_proc_framesize(FRAME_SAVED_PC(frame)); - - if (framesize != -1) - return frame->frame - framesize; - - return read_memory_integer (frame->frame, 4); -} - -/* 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; -{ - struct minimal_symbol *msym; - - if (!chain) - return 0; - - msym = lookup_minimal_symbol_by_pc (FRAME_SAVED_PC (thisframe)); - - if (msym - && (strcmp (SYMBOL_NAME (msym), "_start") == 0)) - return 0; - else - return 1; -} - -#if 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; -} -#endif - -/* - * 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; - register int regnum; - int int_buffer; - double freg_buffer; - - /* Space for "arguments"; the RP goes in here. */ - sp = read_register (SP_REGNUM) + 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 = 5; i < 32; fp += 4, i++) - frame_saved_regs->regs[i] = fp; - - fp += 4; - for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8) - frame_saved_regs->regs[i] = 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 -hppa_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 */ - 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. */ - -static int -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. */ - write_register (PCOQ_HEAD_REGNUM, pc + 4); - write_register (PCOQ_TAIL_REGNUM, pc + 8); - - /* - * 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 -hppa_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++) - { - /* Coerce chars to int & float to double if necessary */ - args[i] = value_arg_coerce (args[i]); - - cum += TYPE_LENGTH (VALUE_TYPE (args[i])); - - /* value must go at proper alignment. Assume alignment is a - power of two.*/ - alignment = hppa_alignof (VALUE_TYPE (args[i])); - if (cum % alignment) - cum = (cum + alignment) & -alignment; - offset[i] = -cum; - } - sp += min ((cum + 7) & -8, 16); - - for (i = 0; i < nargs; i++) - write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), - TYPE_LENGTH (VALUE_TYPE (args[i]))); - - if (struct_return) - write_register (28, struct_addr); - return sp + 32; -} - -/* - * 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. - */ - -CORE_ADDR -hppa_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) - REGISTER_TYPE *dummy; - CORE_ADDR pc; - CORE_ADDR fun; - int nargs; - value *args; - struct type *type; - int gcc_p; -{ - CORE_ADDR dyncall_addr, sr4export_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"); - - dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol); - - msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL); - if (msymbol == NULL) - error ("Can't find an address for _sr4export trampoline"); - - sr4export_addr = SYMBOL_VALUE_ADDRESS (msymbol); - - dummy[9] = deposit_21 (fun >> 11, dummy[9]); - dummy[10] = deposit_14 (fun & MASK_11, dummy[10]); - dummy[12] = deposit_21 (sr4export_addr >> 11, dummy[12]); - dummy[13] = deposit_14 (sr4export_addr & MASK_11, dummy[13]); - - write_register (22, pc); - - return dyncall_addr; -} - -/* return the alignment of a type in bytes. Structures have the maximum - alignment required by their fields. */ - -static int -hppa_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 hppa_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 = hppa_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, fpregs); - 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, fpregs) - char *raw_regs; - int regnum; - int fpregs; -{ - 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))); - - if (fpregs) - 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"); -} - -/* 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. - - For computed calls, we just extract the new PC from r22. */ - -CORE_ADDR -skip_trampoline_code (pc, name) - CORE_ADDR pc; - char *name; -{ - long inst0, inst1; - static CORE_ADDR dyncall = 0; - struct minimal_symbol *msym; - -/* FIXME XXX - dyncall must be initialized whenever we get a new exec file */ - - if (!dyncall) - { - msym = lookup_minimal_symbol ("$$dyncall", NULL); - if (msym) - dyncall = SYMBOL_VALUE_ADDRESS (msym); - else - dyncall = -1; - } - - if (pc == dyncall) - return (CORE_ADDR)(read_register (22) & ~0x3); - - inst0 = read_memory_integer (pc, 4); - inst1 = read_memory_integer (pc+4, 4); - - if ( (inst0 & 0xffe00000) == 0x20200000 /* ldil xxx, r1 */ - && (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */ - pc = extract_21 (inst0) + extract_17 (inst1); - else - pc = (CORE_ADDR)NULL; - - return pc; -} - -/* Advance PC across any function entry prologue instructions - to reach some "real" code. */ - -/* skip (stw rp, -20(0,sp)); copy 4,1; copy sp, 4; stwm 1,framesize(sp) - for gcc, or (stw rp, -20(0,sp); stwm 1, framesize(sp) for hcc */ - -CORE_ADDR -skip_prologue(pc) - CORE_ADDR pc; -{ - int inst; - int status; - - status = target_read_memory (pc, (char *)&inst, 4); - SWAP_TARGET_AND_HOST (&inst, sizeof (inst)); - if (status != 0) - return pc; - - if (inst == 0x6BC23FD9) /* stw rp,-20(sp) */ - { - if (read_memory_integer (pc + 4, 4) == 0x8040241) /* copy r4,r1 */ - pc += 16; - else if ((read_memory_integer (pc + 4, 4) & ~MASK_14) == 0x68810000) /* stw r1,(r4) */ - pc += 8; - } - else if (read_memory_integer (pc, 4) == 0x8040241) /* copy r4,r1 */ - pc += 12; - else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000) /* stw r1,(r4) */ - pc += 4; - - return pc; -} - -static void -unwind_command (exp, from_tty) - char *exp; - int from_tty; -{ - CORE_ADDR address; - union - { - int *foo; - struct unwind_table_entry *u; - } xxx; - - /* If we have an expression, evaluate it and use it as the address. */ - - if (exp != 0 && *exp != 0) - address = parse_and_eval_address (exp); - else - return; - - xxx.u = find_unwind_entry (address); - - if (!xxx.u) - { - printf ("Can't find unwind table entry for PC 0x%x\n", address); - return; - } - - printf ("%08x\n%08X\n%08X\n%08X\n", xxx.foo[0], xxx.foo[1], xxx.foo[2], - xxx.foo[3]); -} - -void -_initialize_hppah_tdep () -{ - add_com ("unwind", class_obscure, unwind_command, "Print unwind info\n"); - add_show_from_set - (add_set_cmd ("use_unwind", class_obscure, var_boolean, - (char *)&use_unwind, - "Set the usage of unwind info", &setlist), - &showlist); -}