diff options
author | Jason Molenda <jmolenda@apple.com> | 1998-04-02 01:01:35 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 1998-04-02 01:01:35 +0000 |
commit | 3dcac15f1f3f940d7f5dad402155dec74291432b (patch) | |
tree | 82d8a2d785d10e447fc91edee7fa44d7e329c71f | |
parent | 775b60dd73051e3637a07c112da519c1bb193a06 (diff) | |
download | gdb-3dcac15f1f3f940d7f5dad402155dec74291432b.zip gdb-3dcac15f1f3f940d7f5dad402155dec74291432b.tar.gz gdb-3dcac15f1f3f940d7f5dad402155dec74291432b.tar.bz2 |
Wed Apr 1 16:30:49 1998 Ian Dall <Ian.Dall@dsto.defence.gov.au>
* ns32k-tdep.c (flip_bytes, ns32k_localcount,
ns32k_get_enter_addr, sign_extend): Restore functions mysteriously
deleted.
* ns32knbsd-nat.c: New (?) file to support fetching and storing
registers on NetBSD hosts.
* nbsd.mh (NATDEPFILES): put ns32knbsd-nat.o instead of
ns32k-nat.o
* ns32km3-nat.c (reg_offset): Get order of floating point
registers correct. Add extra 32382 register offsets.
(REG_ADDRESS): define to point at correct part of thread
state. Use calls to "warning" instead of "message".
* tm-nbsd.h, tm-ns32km3.h (REGISTER_NAMES, NUM_REGS,
REGISTER_BYTES, REGISTER_BYTE): redefine allowing for 32382
fpu registers.
-rw-r--r-- | gdb/ChangeLog | 21 | ||||
-rw-r--r-- | gdb/config/ns32k/nbsd.mh | 2 | ||||
-rw-r--r-- | gdb/config/ns32k/tm-nbsd.h | 38 | ||||
-rw-r--r-- | gdb/config/ns32k/tm-ns32km3.h | 22 | ||||
-rw-r--r-- | gdb/ns32k-tdep.c | 84 | ||||
-rw-r--r-- | gdb/ns32km3-nat.c | 16 | ||||
-rw-r--r-- | gdb/ns32knbsd-nat.c | 353 |
7 files changed, 528 insertions, 8 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 74b7fad..6abe18b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +Wed Apr 1 16:30:49 1998 Ian Dall <Ian.Dall@dsto.defence.gov.au> + + * ns32k-tdep.c (flip_bytes, ns32k_localcount, + ns32k_get_enter_addr, sign_extend): Restore functions mysteriously + deleted. + + * ns32knbsd-nat.c: New (?) file to support fetching and storing + registers on NetBSD hosts. + + * nbsd.mh (NATDEPFILES): put ns32knbsd-nat.o instead of + ns32k-nat.o + + * ns32km3-nat.c (reg_offset): Get order of floating point + registers correct. Add extra 32382 register offsets. + (REG_ADDRESS): define to point at correct part of thread + state. Use calls to "warning" instead of "message". + + * tm-nbsd.h, tm-ns32km3.h (REGISTER_NAMES, NUM_REGS, + REGISTER_BYTES, REGISTER_BYTE): redefine allowing for 32382 + fpu registers. + Wed Apr 1 13:43:07 1998 Philippe De Muyter <phdm@macqel.be> * NEWS: m68k-motorola-sysv host support added. diff --git a/gdb/config/ns32k/nbsd.mh b/gdb/config/ns32k/nbsd.mh index 96efec5..4a91ee7 100644 --- a/gdb/config/ns32k/nbsd.mh +++ b/gdb/config/ns32k/nbsd.mh @@ -1,4 +1,4 @@ # Host: PC532 running NetBSD XM_FILE= xm-nbsd.h NAT_FILE= nm-nbsd.h -NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o ns32k-nat.o +NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o ns32knbsd-nat.o diff --git a/gdb/config/ns32k/tm-nbsd.h b/gdb/config/ns32k/tm-nbsd.h index 5a0fa32..6e61de3 100644 --- a/gdb/config/ns32k/tm-nbsd.h +++ b/gdb/config/ns32k/tm-nbsd.h @@ -39,3 +39,41 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ? sigtramp_saved_pc (FRAME) \ : read_memory_integer ((FRAME)->frame + 4, 4)) \ ) + + +/* tm-umax.h assumes a 32082 fpu. We have a 32382 fpu. */ +#undef REGISTER_NAMES +#undef NUM_REGS +#undef REGISTER_BYTES +#undef REGISTER_BYTE +/* Initializer for an array of names of registers. + There should be NUM_REGS strings in this initializer. */ + +#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ + "sp", "fp", "pc", "ps", \ + "fsr", \ + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "xx", \ + } + +#define NUM_REGS 29 + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ +#define REGISTER_BYTES \ + ((NUM_REGS - 4) * REGISTER_RAW_SIZE(R0_REGNUM) \ + + 8 * REGISTER_RAW_SIZE(LP0_REGNUM)) + +/* Index within `registers' of the first byte of the space for + register N. */ + +/* This is a bit yuck. The even numbered double precision floating + point long registers occupy the same space as the even:odd numbered + single precision floating point registers, but the extra 32381 fpu + registers are at the end. Doing it this way is compatable for both + 32081 and 32381 equiped machines. */ + +#define REGISTER_BYTE(N) (((N) < LP0_REGNUM? (N)\ + : ((N) - LP0_REGNUM) & 1? (N) - 1 \ + : ((N) - LP0_REGNUM + FP0_REGNUM)) * 4) + diff --git a/gdb/config/ns32k/tm-ns32km3.h b/gdb/config/ns32k/tm-ns32km3.h index ab9065d..27d07d7 100644 --- a/gdb/config/ns32k/tm-ns32km3.h +++ b/gdb/config/ns32k/tm-ns32km3.h @@ -49,3 +49,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define STACK_END_ADDR USRSTACK #include "ns32k/tm-umax.h" + +/* tm-umax.h assumes a 32082 fpu. We have a 32382 fpu. */ +#undef REGISTER_NAMES +#undef NUM_REGS +#undef REGISTER_BYTES +/* Initializer for an array of names of registers. + There should be NUM_REGS strings in this initializer. */ + +#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ + "sp", "fp", "pc", "ps", \ + "fsr", \ + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "xx", \ + } + +#define NUM_REGS 29 + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ +#define REGISTER_BYTES \ + ((NUM_REGS - 4) * REGISTER_RAW_SIZE(R0_REGNUM) \ + + 8 * REGISTER_RAW_SIZE(LP0_REGNUM)) diff --git a/gdb/ns32k-tdep.c b/gdb/ns32k-tdep.c index 58a0860..395bf9b 100644 --- a/gdb/ns32k-tdep.c +++ b/gdb/ns32k-tdep.c @@ -25,3 +25,87 @@ _initialize_ns32k_tdep () { tm_print_insn = print_insn_ns32k; } + +sign_extend (value, bits) +{ + value = value & ((1 << bits) - 1); + return (value & (1 << (bits-1)) + ? value | (~((1 << bits) - 1)) + : value); +} + +void +flip_bytes (ptr, count) + char *ptr; + int count; +{ + char tmp; + + while (count > 0) + { + tmp = *ptr; + ptr[0] = ptr[count-1]; + ptr[count-1] = tmp; + ptr++; + count -= 2; + } +} + +/* Return the number of locals in the current frame given a pc + pointing to the enter instruction. This is used in the macro + FRAME_FIND_SAVED_REGS. */ + +int +ns32k_localcount (enter_pc) + CORE_ADDR enter_pc; +{ + unsigned char localtype; + int localcount; + + localtype = read_memory_integer (enter_pc+2, 1); + if ((localtype & 0x80) == 0) + localcount = localtype; + else if ((localtype & 0xc0) == 0x80) + localcount = (((localtype & 0x3f) << 8) + | (read_memory_integer (enter_pc+3, 1) & 0xff)); + else + localcount = (((localtype & 0x3f) << 24) + | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16) + | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 ) + | (read_memory_integer (enter_pc+5, 1) & 0xff)); + return localcount; +} + +/* + * Get the address of the enter opcode for the function + * containing PC, if there is an enter for the function, + * and if the pc is between the enter and exit. + * Returns positive address if pc is between enter/exit, + * 1 if pc before enter or after exit, 0 otherwise. + */ + +CORE_ADDR +ns32k_get_enter_addr (pc) + CORE_ADDR pc; +{ + CORE_ADDR enter_addr; + unsigned char op; + + if (pc == 0) + return 0; + + if (ABOUT_TO_RETURN (pc)) + return 1; /* after exit */ + + enter_addr = get_pc_function_start (pc); + + if (pc == enter_addr) + return 1; /* before enter */ + + op = read_memory_integer (enter_addr, 1); + + if (op != 0x82) + return 0; /* function has no enter/exit */ + + return enter_addr; /* pc is between enter and exit */ +} diff --git a/gdb/ns32km3-nat.c b/gdb/ns32km3-nat.c index 89696ba..cdafb9c 100644 --- a/gdb/ns32km3-nat.c +++ b/gdb/ns32km3-nat.c @@ -46,14 +46,16 @@ static int reg_offset[] = { REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3), REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7), - REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a), - REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a), + REG_F_OFFSET(l0a), REG_F_OFFSET(l0b),REG_F_OFFSET(l2a),REG_F_OFFSET(l2b), + REG_F_OFFSET(l4a), REG_F_OFFSET(l4b),REG_F_OFFSET(l6a),REG_F_OFFSET(l6b), REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr), REG_F_OFFSET(fsr), - REG_F_OFFSET(l0a), REG_F_OFFSET(l2a),REG_F_OFFSET(l4a),REG_F_OFFSET(l6a) - /* @@@ 532 has more double length floating point regs, not accessed currently */ + REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a), + REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a), }; +#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum]) + /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM * Caller knows that the regs handled in one transaction are of same size. */ @@ -94,7 +96,7 @@ fetch_inferior_registers (regno) &stateCnt); if (ret != KERN_SUCCESS) - message ("fetch_inferior_registers: %s ", + warning ("fetch_inferior_registers: %s ", mach_error_string (ret)); #if 0 /* It may be more effective to store validate all of them, @@ -142,7 +144,7 @@ store_inferior_registers (regno) if (ret != KERN_SUCCESS) { - message ("store_inferior_registers (get): %s", + warning ("store_inferior_registers (get): %s", mach_error_string (ret)); if (must_suspend_thread) setup_thread (current_thread, 0); @@ -173,7 +175,7 @@ store_inferior_registers (regno) NS532_COMBINED_STATE_COUNT); if (ret != KERN_SUCCESS) - message ("store_inferior_registers (set): %s", + warning ("store_inferior_registers (set): %s", mach_error_string (ret)); if (must_suspend_thread) diff --git a/gdb/ns32knbsd-nat.c b/gdb/ns32knbsd-nat.c new file mode 100644 index 0000000..c9f75ca --- /dev/null +++ b/gdb/ns32knbsd-nat.c @@ -0,0 +1,353 @@ +/* Functions specific to running gdb native on an ns32k running NetBSD + Copyright 1989, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <machine/reg.h> +#include <machine/frame.h> +#include <machine/pcb.h> + +#include "defs.h" +#include "inferior.h" +#include "target.h" +#include "gdbcore.h" + +#define RF(dst, src) \ + memcpy(®isters[REGISTER_BYTE(dst)], &src, sizeof(src)) + +#define RS(src, dst) \ + memcpy(&dst, ®isters[REGISTER_BYTE(src)], sizeof(dst)) + +void +fetch_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; + struct fpreg inferior_fpregisters; + + ptrace (PT_GETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); + ptrace (PT_GETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_fpregisters, 0); + + RF(R0_REGNUM + 0, inferior_registers.r_r0); + RF(R0_REGNUM + 1, inferior_registers.r_r1); + RF(R0_REGNUM + 2, inferior_registers.r_r2); + RF(R0_REGNUM + 3, inferior_registers.r_r3); + RF(R0_REGNUM + 4, inferior_registers.r_r4); + RF(R0_REGNUM + 5, inferior_registers.r_r5); + RF(R0_REGNUM + 6, inferior_registers.r_r6); + RF(R0_REGNUM + 7, inferior_registers.r_r7); + + RF(SP_REGNUM , inferior_registers.r_sp); + RF(FP_REGNUM , inferior_registers.r_fp); + RF(PC_REGNUM , inferior_registers.r_pc); + RF(PS_REGNUM , inferior_registers.r_psr); + + RF(FPS_REGNUM , inferior_fpregisters.r_fsr); + RF(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]); + RF(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]); + RF(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]); + RF(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]); + RF(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]); + RF(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]); + RF(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]); + RF(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]); + registers_fetched (); +} + +void +store_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; + struct fpreg inferior_fpregisters; + + RS(R0_REGNUM + 0, inferior_registers.r_r0); + RS(R0_REGNUM + 1, inferior_registers.r_r1); + RS(R0_REGNUM + 2, inferior_registers.r_r2); + RS(R0_REGNUM + 3, inferior_registers.r_r3); + RS(R0_REGNUM + 4, inferior_registers.r_r4); + RS(R0_REGNUM + 5, inferior_registers.r_r5); + RS(R0_REGNUM + 6, inferior_registers.r_r6); + RS(R0_REGNUM + 7, inferior_registers.r_r7); + + RS(SP_REGNUM , inferior_registers.r_sp); + RS(FP_REGNUM , inferior_registers.r_fp); + RS(PC_REGNUM , inferior_registers.r_pc); + RS(PS_REGNUM , inferior_registers.r_psr); + + RS(FPS_REGNUM , inferior_fpregisters.r_fsr); + RS(FP0_REGNUM +0, inferior_fpregisters.r_freg[0]); + RS(FP0_REGNUM +2, inferior_fpregisters.r_freg[2]); + RS(FP0_REGNUM +4, inferior_fpregisters.r_freg[4]); + RS(FP0_REGNUM +6, inferior_fpregisters.r_freg[6]); + RS(LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]); + RS(LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]); + RS(LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]); + RS(LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]); + + ptrace (PT_SETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); + ptrace (PT_SETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_fpregisters, 0); +} + + +/* XXX - Add this to machine/regs.h instead? */ +struct coreregs { + struct reg intreg; + struct fpreg freg; +}; + +/* Get registers from a core file. */ +static void +fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) + char *core_reg_sect; + unsigned core_reg_size; + int which; + unsigned int reg_addr; /* Unused in this version */ +{ + struct coreregs *core_reg; + + core_reg = (struct coreregs *)core_reg_sect; + + /* + * We have *all* registers + * in the first core section. + * Ignore which. + */ + + if (core_reg_size < sizeof(*core_reg)) { + fprintf_unfiltered (gdb_stderr, "Couldn't read regs from core file\n"); + return; + } + + /* Integer registers */ + RF(R0_REGNUM + 0, core_reg->intreg.r_r0); + RF(R0_REGNUM + 1, core_reg->intreg.r_r1); + RF(R0_REGNUM + 2, core_reg->intreg.r_r2); + RF(R0_REGNUM + 3, core_reg->intreg.r_r3); + RF(R0_REGNUM + 4, core_reg->intreg.r_r4); + RF(R0_REGNUM + 5, core_reg->intreg.r_r5); + RF(R0_REGNUM + 6, core_reg->intreg.r_r6); + RF(R0_REGNUM + 7, core_reg->intreg.r_r7); + + RF(SP_REGNUM , core_reg->intreg.r_sp); + RF(FP_REGNUM , core_reg->intreg.r_fp); + RF(PC_REGNUM , core_reg->intreg.r_pc); + RF(PS_REGNUM , core_reg->intreg.r_psr); + + /* Floating point registers */ + RF(FPS_REGNUM , core_reg->freg.r_fsr); + RF(FP0_REGNUM +0, core_reg->freg.r_freg[0]); + RF(FP0_REGNUM +2, core_reg->freg.r_freg[2]); + RF(FP0_REGNUM +4, core_reg->freg.r_freg[4]); + RF(FP0_REGNUM +6, core_reg->freg.r_freg[6]); + RF(LP0_REGNUM + 1, core_reg->freg.r_freg[1]); + RF(LP0_REGNUM + 3, core_reg->freg.r_freg[3]); + RF(LP0_REGNUM + 5, core_reg->freg.r_freg[5]); + RF(LP0_REGNUM + 7, core_reg->freg.r_freg[7]); + registers_fetched (); +} + +/* Register that we are able to handle ns32knbsd core file formats. + FIXME: is this really bfd_target_unknown_flavour? */ + +static struct core_fns nat_core_fns = +{ + bfd_target_unknown_flavour, + fetch_core_registers, + NULL +}; + +void +_initialize_ns32knbsd_nat () +{ + add_core_fns (&nat_core_fns); +} + + +/* + * kernel_u_size() is not helpful on NetBSD because + * the "u" struct is NOT in the core dump file. + */ + +#ifdef FETCH_KCORE_REGISTERS +/* + * Get registers from a kernel crash dump or live kernel. + * Called by kcore-nbsd.c:get_kcore_registers(). + */ +void +fetch_kcore_registers (pcb) + struct pcb *pcb; +{ + struct switchframe sf; + struct reg intreg; + int dummy; + + /* Integer registers */ + if (target_read_memory((CORE_ADDR)pcb->pcb_ksp, (char *)&sf, sizeof sf)) + error("Cannot read integer registers."); + + /* We use the psr at kernel entry */ + if (target_read_memory((CORE_ADDR)pcb->pcb_onstack, (char *)&intreg, sizeof intreg)) + error("Cannot read processor status register."); + + dummy = 0; + RF(R0_REGNUM + 0, dummy); + RF(R0_REGNUM + 1, dummy); + RF(R0_REGNUM + 2, dummy); + RF(R0_REGNUM + 3, sf.sf_r3); + RF(R0_REGNUM + 4, sf.sf_r4); + RF(R0_REGNUM + 5, sf.sf_r5); + RF(R0_REGNUM + 6, sf.sf_r6); + RF(R0_REGNUM + 7, sf.sf_r7); + + dummy = pcb->pcb_kfp + 8; + RF(SP_REGNUM , dummy); + RF(FP_REGNUM , sf.sf_fp); + RF(PC_REGNUM , sf.sf_pc); + RF(PS_REGNUM , intreg.r_psr); + + /* Floating point registers */ + RF(FPS_REGNUM , pcb->pcb_fsr); + RF(FP0_REGNUM +0, pcb->pcb_freg[0]); + RF(FP0_REGNUM +2, pcb->pcb_freg[2]); + RF(FP0_REGNUM +4, pcb->pcb_freg[4]); + RF(FP0_REGNUM +6, pcb->pcb_freg[6]); + RF(LP0_REGNUM + 1, pcb->pcb_freg[1]); + RF(LP0_REGNUM + 3, pcb->pcb_freg[3]); + RF(LP0_REGNUM + 5, pcb->pcb_freg[5]); + RF(LP0_REGNUM + 7, pcb->pcb_freg[7]); + registers_fetched (); +} +#endif /* FETCH_KCORE_REGISTERS */ + +void +clear_regs() +{ + double zero = 0.0; + int null = 0; + + /* Integer registers */ + RF(R0_REGNUM + 0, null); + RF(R0_REGNUM + 1, null); + RF(R0_REGNUM + 2, null); + RF(R0_REGNUM + 3, null); + RF(R0_REGNUM + 4, null); + RF(R0_REGNUM + 5, null); + RF(R0_REGNUM + 6, null); + RF(R0_REGNUM + 7, null); + + RF(SP_REGNUM , null); + RF(FP_REGNUM , null); + RF(PC_REGNUM , null); + RF(PS_REGNUM , null); + + /* Floating point registers */ + RF(FPS_REGNUM , zero); + RF(FP0_REGNUM +0, zero); + RF(FP0_REGNUM +2, zero); + RF(FP0_REGNUM +4, zero); + RF(FP0_REGNUM +6, zero); + RF(LP0_REGNUM + 0, zero); + RF(LP0_REGNUM + 1, zero); + RF(LP0_REGNUM + 2, zero); + RF(LP0_REGNUM + 3, zero); + return; +} + +/* Return number of args passed to a frame. + Can return -1, meaning no way to tell. */ + +int +frame_num_args(fi) +struct frame_info *fi; +{ + CORE_ADDR enter_addr; + CORE_ADDR argp; + int inst; + int args; + int i; + + if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000) { + /* main is always called with three args */ + return(3); + } + enter_addr = ns32k_get_enter_addr(fi->pc); + if (enter_addr = 0) + return(-1); + argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL(fi) : FRAME_SAVED_PC(fi); + for (i = 0; i < 16; i++) { + /* + * After a bsr gcc may emit the following instructions + * to remove the arguments from the stack: + * cmpqd 0,tos - to remove 4 bytes from the stack + * cmpd tos,tos - to remove 8 bytes from the stack + * adjsp[bwd] -n - to remove n bytes from the stack + * Gcc sometimes delays emitting these instructions and + * may even throw a branch between our feet. + */ + inst = read_memory_integer(argp , 4); + args = read_memory_integer(argp + 2, 4); + if ((inst & 0xff) == 0xea) { /* br */ + args = ((inst >> 8) & 0xffffff) | (args << 24); + if (args & 0x80) { + if (args & 0x40) { + args = ntohl(args); + } else { + args = ntohs(args & 0xffff); + if (args & 0x2000) + args |= 0xc000; + } + } else { + args = args & 0xff; + if (args & 0x40) + args |= 0x80; + } + argp += args; + continue; + } + if ((inst & 0xffff) == 0xb81f) /* cmpqd 0,tos */ + return(1); + else if ((inst & 0xffff) == 0xbdc7) /* cmpd tos,tos */ + return(2); + else if ((inst & 0xfffc) == 0xa57c) { /* adjsp[bwd] */ + switch (inst & 3) { + case 0: + args = ((args & 0xff) + 0x80); + break; + case 1: + args = ((ntohs(args) & 0xffff) + 0x8000); + break; + case 3: + args = -ntohl(args); + break; + default: + return(-1); + } + if (args / 4 > 10 || (args & 3) != 0) + continue; + return(args / 4); + } + argp += 1; + } + return(-1); +} |