GDB, Gnu debugger for Ultrix 4.0
Kenstir
kenc at madmax.Viewlogic.COM
Tue Nov 6 08:07:27 AEST 1990
Here is a patch to get GDB 3.5 running under Ultrix 4.0.
For those not familiar with GDB:
+ You need to run it inside Emacs to really get the full effect.
+ 10,000x better than dxdb and look-alikes.
This patch includes in one shot:
+ Per Bothner's diffs (alpha version)
+ Bruce Bauman's (boot at donald.osf.org) post of 27 Sep 90 (gnu.gdb.bug)
+ Garrett Lau's (lau at efi.com) post of 26 Oct 90 (gnu.gdb.bug),
his suggested change to the mipscoff.c:read_type function,
and his post of 3 Nov 90 (gnu.gdb.bug)
+ Mark Reinhold's (mbr at larch.lcs.mit.edu) of 23 Oct 90 (gnu.gdb.bug)
--
Kenneth H. Cox
Viewlogic Systems, Inc.
kenstir at viewlogic.com
...!harvard!cg-atla!viewlog!kenstir
--------------------------- cut here ----------------------------
=====================================
= Diffs for GDB 3.5, Ultrix 4.0
=====================================
= IMPORTANT:
= Before running patch, you need to create some new files:
= touch MIPS-NOTES m-decstatn.h m-mips.h mips-dep.c
= touch mips-opcode.h mips-pinsn.c mipscoff.c
= After running patch, you need to configure:
= config.gdb decstatn
= make
= enjoy
=
= This patch includes in one shot:
= + Per Bothner's diffs (alpha version)
= + Bruce Bauman's (boot at donald.osf.org) post of 27 Sep 90 (gnu.gdb.bug)
= + Garrett Lau's (lau at efi.com) post of 26 Oct 90 (gnu.gdb.bug),
= his suggested change to the mipscoff.c:read_type function,
= and his post of 3 Nov 90 (gnu.gdb.bug)
= + Mark Reinhold's (mbr at larch.lcs.mit.edu) of 23 Oct 90 (gnu.gdb.bug)
=====================================
*** MIPS-NOTES.orig Mon Nov 5 10:27:49 1990
--- MIPS-NOTES Mon Nov 5 10:28:25 1990
***************
*** 0 ****
--- 1,21 ----
+ This is the alpha release of the gdb port to MIPS-based machines.
+ Only the (little-endian) DECstation3100 has been tested.
+
+ Here I will try to list known problems:
+
+ Calling a function in the debugger (as in 'print f(x)') normally
+ works correctly. One known exception is if you pass a structure
+ argument whose sizeof > 4. Currently, gdb will align it on
+ an 8-byte boundary, while the compiler while depend on
+ the alignment needed by the fields. (Unfortunately, the
+ distributed varargs.h and stdarg.h are inconsistent with
+ mips' compiler!)
+
+ Fortran debugging could be made nicer, but a lot of that is a
+ problem with the implementation-independent gdb.
+
+ Code in include files is handled poorly (missing line numbers).
+
+ Lots of testing is needed.
+ E.g. is IN_SIGTRAMP (in infrun.c) correct?
+
*** Makefile.dist.orig Tue Jan 30 21:42:57 1990
--- Makefile.dist Mon Nov 5 10:28:26 1990
***************
*** 328,338 ****
cpp -M). It does not include dependencies of .o files on .c files. */
/* All files which depend on config.status also depend on param.h in case
someone reconfigures gdb out from under an already compiled gdb. */
blockframe.o : defs.h param.h config.status symtab.h obstack.h
symseg.h frame.h
breakpoint.o : defs.h param.h config.status symtab.h obstack.h
symseg.h frame.h
! coffread.o : defs.h param.h config.status
command.o : command.h defs.h
core.o : defs.h param.h config.status a.out.encap.h
dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h
a.out.encap.h \
stab.gnu.h
environ.o : environ.h
--- 328,338 ----
cpp -M). It does not include dependencies of .o files on .c files.
*/
/* All files which depend on config.status also depend on param.h in
case
someone reconfigures gdb out from under an already compiled gdb.
*/
blockframe.o : defs.h param.h config.status symtab.h obstack.h
symseg.h frame.h
breakpoint.o : defs.h param.h config.status symtab.h obstack.h
symseg.h frame.h
! coffread.o : defs.h param.h mipscoff.c config.status
command.o : command.h defs.h
core.o : defs.h param.h config.status a.out.encap.h
dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h
a.out.encap.h \
stab.gnu.h
environ.o : environ.h
*** blockframe.c.orig Sat Jan 6 15:34:14 1990
--- blockframe.c Mon Nov 5 10:28:26 1990
***************
*** 261,279 ****
prev->next = next_frame;
prev->prev = (struct frame_info *) 0;
prev->frame = address;
prev->next_frame = prev->next ? prev->next->frame : 0;
- #ifdef INIT_EXTRA_FRAME_INFO
- INIT_EXTRA_FRAME_INFO(prev);
- #endif
-
/* This entry is in the frame queue now, which is good since
FRAME_SAVED_PC may use that queue to figure out it's value
(see m-sparc.h). We want the pc saved in the inferior frame. */
prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
return prev;
}
CORE_ADDR
--- 261,279 ----
prev->next = next_frame;
prev->prev = (struct frame_info *) 0;
prev->frame = address;
prev->next_frame = prev->next ? prev->next->frame : 0;
/* This entry is in the frame queue now, which is good since
FRAME_SAVED_PC may use that queue to figure out it's value
(see m-sparc.h). We want the pc saved in the inferior frame. */
prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
+
+ #ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO(prev);
+ #endif
return prev;
}
CORE_ADDR
*** breakpoint.c.orig Wed Jan 10 18:49:07 1990
--- breakpoint.c Mon Nov 5 10:28:27 1990
***************
*** 438,463 ****
last_addr = b->address;
if (b->symtab)
{
sym = find_pc_function (b->address);
if (sym)
! printf_filtered (" in %s (%s line %d)", SYMBOL_NAME (sym),
b->symtab->filename, b->line_number);
else
! printf_filtered ("%s line %d", b->symtab->filename,
b->line_number);
}
else
{
char *name;
int addr;
if (find_pc_partial_function (b->address, &name, &addr))
{
if (b->address - addr)
! printf_filtered ("<%s+%d>", name, b->address - addr);
else
! printf_filtered ("<%s>", name);
}
}
printf_filtered ("\n");
--- 438,464 ----
last_addr = b->address;
if (b->symtab)
{
sym = find_pc_function (b->address);
if (sym)
! printf_filtered (" in %.100s (%.100s line %d)",
! SYMBOL_NAME (sym),
b->symtab->filename, b->line_number);
else
! printf_filtered ("%.100s line %d", b->symtab->filename,
b->line_number);
}
else
{
char *name;
int addr;
if (find_pc_partial_function (b->address, &name, &addr))
{
if (b->address - addr)
! printf_filtered ("<%.200s+%d>", name, b->address - addr);
else
! printf_filtered ("<%.200s>", name);
}
}
printf_filtered ("\n");
***************
*** 472,482 ****
printf_filtered ("\n");
}
if (l = b->commands)
while (l)
{
! printf_filtered ("\t%s\n", l->line);
l = l->next;
}
}
/* Compare against (CORE_ADDR)-1 in case some compiler decides
--- 473,485 ----
printf_filtered ("\n");
}
if (l = b->commands)
while (l)
{
! fputs_filtered (stdout, "\t");
! fputs_filtered (stdout, l->line);
! fputs_filtered (stdout, "\n");
l = l->next;
}
}
/* Compare against (CORE_ADDR)-1 in case some compiler decides
*** coffread.c.orig Wed Jan 10 18:54:43 1990
--- coffread.c Mon Nov 5 10:28:28 1990
***************
*** 22,31 ****
--- 22,34 ----
#include <stdio.h>
#include "defs.h"
#include "param.h"
#ifdef COFF_FORMAT
+ #ifdef THIRD_EYE_FORMAT
+ #include "mipscoff.c"
+ #else /* !THIRD_EYE_FORMAT */
#include "symtab.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
***************
*** 2000,2009 ****
--- 2003,2014 ----
}
/* These will stay zero all the time */
struct psymbol_allocation_list global_psymbols, static_psymbols;
+ #endif /* !THIRD_EYE_FORMAT */
+
_initialize_coff ()
{
symfile = 0;
bzero (&global_psymbols, sizeof (global_psymbols));
***************
*** 2011,2018 ****
add_com ("symbol-file", class_files, symbol_file_command,
"Load symbol table (in coff format) from executable file FILE.");
}
-
#endif /* COFF_FORMAT */
-
--- 2016,2021 ----
*** config.gdb.orig Tue Jan 30 15:35:46 1990
--- config.gdb Mon Nov 5 10:28:28 1990
***************
*** 319,328 ****
--- 319,341 ----
opcodefile=sparc-opcode.h
depfile=sparc-dep.c
;;
convex)
;;
+ iris|mips)
+ echo "[Big-endian mips-based machines have not been tested]"
+ paramfile=m-mips.h
+ pinsnfile=mips-pinsn.c
+ opcodefile=mips-opcode.h
+ depfile=mips-dep.c
+ ;;
+ dec-3100|decstatn) # DECstation 3100 (alias PMAX) or DECstation 2100
+ paramfile=m-decstatn.h
+ pinsnfile=mips-pinsn.c
+ opcodefile=mips-opcode.h
+ depfile=mips-dep.c
+ ;;
test)
paramfile=one
pinsnfile=three
opcodefile=four
;;
*** eval.c.orig Sun Nov 5 13:01:52 1989
--- eval.c Mon Nov 5 10:28:29 1990
***************
*** 961,977 ****
op = exp->elts[pc].opcode;
switch (op)
{
case OP_VAR_VALUE:
! if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) ==
TYPE_CODE_ARRAY)
! {
! (*pos) += 3;
! val = locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
! return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE
(SYMBOL_TYPE (exp->elts[pc + 1].symbol))),
! val);
! }
}
return evaluate_subexp (0, exp, pos, noside);
}
--- 961,988 ----
op = exp->elts[pc].opcode;
switch (op)
{
case OP_VAR_VALUE:
! {
! struct symbol *sym = exp->elts[pc + 1].symbol;
! struct type *sym_type = SYMBOL_TYPE (sym);
! if (TYPE_CODE (sym_type) == TYPE_CODE_ARRAY)
! {
! value val;
! long low_bound=
! TYPE_FIELD_BITPOS(TYPE_FIELD_TYPE (sym_type, 0), 0);
! (*pos) += 3;
! val = locate_var_value (sym, (CORE_ADDR) 0);
! val = value_cast (lookup_pointer_type
(TYPE_TARGET_TYPE(sym_type)),
! val);
! if (low_bound)
! val = value_sub (val,
! value_from_long(builtin_type_long, low_bound));
! return val;
! }
! }
}
return evaluate_subexp (0, exp, pos, noside);
}
*** infrun.c.orig Tue Jan 23 18:10:35 1990
--- infrun.c Mon Nov 5 10:28:30 1990
***************
*** 173,183 ****
static char signal_print[NSIG];
static char signal_program[NSIG];
/* Nonzero if breakpoints are now inserted in the inferior. */
! static int breakpoints_inserted;
/* Function inferior was in as of last step command. */
static struct symbol *step_start_function;
--- 173,183 ----
static char signal_print[NSIG];
static char signal_program[NSIG];
/* Nonzero if breakpoints are now inserted in the inferior. */
! int breakpoints_inserted;
/* Function inferior was in as of last step command. */
static struct symbol *step_start_function;
*** m-decstatn.h.orig Mon Nov 5 10:27:50 1990
--- m-decstatn.h Mon Nov 5 10:56:26 1990
***************
*** 0 ****
--- 1,3 ----
+ #define DECSTATION
+ #define HAVE_VPRINTF
+ #include "m-mips.h"
*** m-mips.h.orig Mon Nov 5 10:27:50 1990
--- m-mips.h Mon Nov 5 10:28:30 1990
***************
*** 0 ****
--- 1,432 ----
+ /* Definitions to make GDB run on a MIPS-based machines.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ GDB 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 1, or (at your option)
+ any later version.
+
+ GDB 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 GDB; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+ /* Define the bit, byte, and word ordering of the machine. */
+ #ifndef DECSTATION
+ #define BITS_BIG_ENDIAN
+ #define BYTES_BIG_ENDIAN
+ #define WORDS_BIG_ENDIAN
+ #endif
+
+ #define IEEE_FLOAT
+
+ #define FLOAT_INFO { printf("FPA coprocessor available.\n"); }
+
+ /* Get rid of any system-imposed stack limit if possible. */
+
+ #define SET_STACK_LIMIT_HUGE
+
+ /* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+ #undef NAMES_HAVE_UNDERSCORE
+
+ /* Debugger information will be a variant of COFF */
+
+ /*#define READ_DBX_FORMAT*/
+ #define COFF_FORMAT
+ #define THIRD_EYE_FORMAT
+
+ /* We need to remember some procedure-specific values
+ to do stack traversal. Use the mips_proc_info type. */
+
+ #define mips_proc_info PDR
+ #define PROC_LOW_ADDR(proc) ((proc)->lnLow) /* least address */
+ #define PROC_HIGH_ADDR(proc) ((proc)->lnHigh) /* upper address bound
*/
+ #define PROC_FRAME_OFFSET(proc) ((proc)->frameoffset)
+ #define PROC_FRAME_REG(proc) ((proc)->framereg)
+ #define PROC_REG_MASK(proc) ((proc)->regmask)
+ #define PROC_FREG_MASK(proc) ((proc)->fregmask)
+ #define PROC_REG_OFFSET(proc) ((proc)->regoffset)
+ #define PROC_FREG_OFFSET(proc) ((proc)->fregoffset)
+ #define PROC_PC_REG(proc) ((proc)->pcreg)
+ #define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->isym)
+ #define _PROC_MAGIC_ 0x0F0F0F0F
+ #define PROC_DESC_IS_DUMMY(proc) ((proc)->isym == _PROC_MAGIC_)
+ #define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->isym = _PROC_MAGIC_)
+
+ /* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+ #define FUNCTION_START_OFFSET 0
+
+ /* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+ #define SKIP_PROLOGUE(pc) \
+ { register int op = read_memory_integer (pc, 4); \
+ if ((op & 0xffff0000) == 0x27bd0000) \
+ pc += 4; /* Skip addiu $sp,$sp,offset */ \
+ }
+
+ /* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some
machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+ #define SAVED_PC_AFTER_CALL(frame)
(CORE_ADDR)read_register(RA_REGNUM)
+
+ /* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+ #define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+ /* Address of end of stack space. */
+
+ #define STACK_END_ADDR 0x7ffff000
+
+ /* Stack grows downward. */
+
+ #define INNER_THAN <
+
+ /* Stack has strict alignment. However, use PUSH_ARGUMENTS
+ to take care of it. */
+ /*#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)*/
+
+ #define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = mips_push_arguments(nargs, args, sp, struct_return,
struct_addr)
+
+ /* Sequence of bytes for breakpoint instruction. */
+
+ #ifdef BYTES_BIG_ENDIAN
+ #define BREAKPOINT {0, 0, 0, 13}
+ #else
+ #define BREAKPOINT {13, 0, 0, 0}
+ #endif
+
+ /* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+ #define DECR_PC_AFTER_BREAK 0
+
+ /* Nonzero if instruction at PC is a return instruction. */
+ /* For Mips, this is jr $ra */
+
+ #define ABOUT_TO_RETURN(pc) \
+ (read_memory_integer (pc, 4) == 0x03e00008)
+
+ /* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the Vax. */
+
+ #define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+ /* Largest integer type */
+ #define LONGEST long
+
+ /* Name of the builtin type for the LONGEST type above. */
+ #define BUILTIN_TYPE_LONGEST builtin_type_long
+
+ /* Say how long (ordinary) registers are. */
+
+ #define REGISTER_TYPE long
+
+ /* Number of machine registers */
+
+ #define NUM_REGS 71
+
+ /* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+ /* Note that the symbol table parsing of scRegister symbols
+ * assumes r0=0, ..., r3=31, and f0=32, ... f31=32+31 */
+
+ #ifdef NUMERIC_REG_NAMES
+ #define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6",
"r7",\
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",\
+ "r24", "r25", "r26", "r27", "gp", "sp", "r30", "ra", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "pc", "cause", "hi", "lo", "fcrcs", "fcrir", "fp" };
+ #else /* !NUMERIC_REG_NAMES */
+ #define REGISTER_NAMES {"zero", "at", "v0", "v1", "a0", "a1", "a2",
"a3",\
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",\
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",\
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "pc", "cause", "hi", "lo", "fcrcs", "fcrir", "fp" };
+ #endif /* !NUMERIC_REG_NAMES */
+
+ /* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to
read_register. */
+
+ /* Note the FP is a "virtual" register */
+ #define SP_REGNUM 29 /* Contains address of top of stack */
+ #define RA_REGNUM 31 /* Contains return address value */
+ #define FP0_REGNUM 32 /* Floating point register 0 (single float) */
+ #define PC_REGNUM 64 /* Contains program counter */
+ #define CAUSE_REGNUM 65
+ #define HI_REGNUM 66 /* Multiple/divide temp */
+ #define LO_REGNUM 67 /* ... */
+ #define FCRCS_REGNUM 68 /* FP control/status */
+ #define FCRIR_REGNUM 69 /* FP implementation/revision */
+ #define FP_REGNUM 70 /* Pseudo register that contains true address of
executing stack frame */
+
+ /* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+ #define DO_REGISTERS_INFO(_regnum) mips_do_registers_info(_regnum)
+
+ /* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+ #define REGISTER_BYTES (4*NUM_REGS)
+
+ /* Index within `registers' of the first byte of the space for
+ register N. */
+
+ #define REGISTER_BYTE(N) ((N) * 4)
+
+ /* Number of bytes of storage in the actual machine representation
+ for register N.*/
+
+ #define REGISTER_RAW_SIZE(N) 4
+
+ /* Number of bytes of storage in the program's representation
+ for register N.*/
+
+ #define REGISTER_VIRTUAL_SIZE(N) 4
+
+ /* Largest value REGISTER_RAW_SIZE can have. */
+
+ #define MAX_REGISTER_RAW_SIZE 4
+
+ /* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+ #define MAX_REGISTER_VIRTUAL_SIZE 4
+
+ /* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+ #define REGISTER_CONVERTIBLE(N) 0
+
+ /* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+ #define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ { bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM)); }
+
+ /* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+ #define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ { bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM)); }
+
+ /* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+ #define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < FP0_REGNUM ? builtin_type_int : (N) < PC_REGNUM ? \
+ builtin_type_float : builtin_type_int)
+
+ /* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+ #define STORE_STRUCT_RETURN(ADDR, SP) SP = push_word(SP, ADDR)
+
+ /* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual
format,
+ into VALBUF. */
+
+ #define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ?
FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+ /* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+ #define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) ==
TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+ /* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+ #define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)((REGBUF)+16))
+
+ /* Compensate for lack of `vprintf' function. */
+ #ifndef HAVE_VPRINTF
+ #define vprintf(format, ap) _doprnt (format, ap, stdout)
+ #endif /* not HAVE_VPRINTF */
+
+ /* Describe the pointer in each stack frame to the previous stack
frame
+ (its caller). */
+
+ /* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal
address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+ /* In the case of the Vax, the frame's nominal address is the FP
value,
+ and 12 bytes later comes the saved previous FP value as a 4-byte
word. */
+
+ #define EXTRA_FRAME_INFO \
+ char *proc_desc; /* actually, a PDR* */\
+ int num_args;\
+ struct frame_saved_regs *saved_regs;
+ #define INIT_EXTRA_FRAME_INFO(fci) init_extra_frame_info(fci)
+
+ #define FRAME_CHAIN(thisframe) (FRAME_ADDR)frame_chain(thisframe)
+
+ #define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
+
+ #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+ /* Define other aspects of the stack frame. */
+
+ /* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If
it
+ does not, FRAMELESS is set to 1, else 0. */
+ #define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) =
0;}
+
+ /* Saved Pc. */
+
+ #define FRAME_SAVED_PC(FRAME) frame_saved_pc(FRAME)
+
+ /* If the argument is on the stack, it will be here. */
+ #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+ #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+ /* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+ #define FRAME_NUM_ARGS(numargs, fi) (numargs = (fi)->num_args)
+
+ /* Return number of bytes at start of arglist that are not really
args. */
+
+ #define FRAME_ARGS_SKIP 0
+
+ /* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by
FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+ #define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) ( \
+ (frame_saved_regs) = *(frame_info)->saved_regs, \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame)
+
+ /* Things needed for making the inferior call functions. */
+
+ /* Push an empty stack frame, to record the current PC, etc. */
+
+ #define PUSH_DUMMY_FRAME {push_dummy_frame();}
+ #if 0
+ { register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, 0); /* arglist */ \
+ for (regnum = 11; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ sp = push_word (sp, 0); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); }
+ #endif
+
+ /* Discard from the stack the innermost frame, restoring all
registers. */
+
+ #define POP_FRAME {pop_frame();}
+
+ #define MK_OP(op,rs,rt,offset)
(((op)<<26)|((rs)<<21)|((rt)<<16)|(offset))
+ #define CALL_DUMMY_SIZE 48
+ #define Dest_Reg 2
+ #define CALL_DUMMY {\
+ (017<<26)| (Dest_Reg << 16), /*lui $r31,<target upper 16 bits>*/ \
+ MK_OP(13,Dest_Reg,Dest_Reg,0), /*ori $r31,$r31,<lower 16 bits>*/ \
+ MK_OP(061,SP_REGNUM,12,0), /* lwc1 $f12,0(sp) */\
+ MK_OP(061,SP_REGNUM,13,4), /* lwc1 $f13,4(sp) */\
+ MK_OP(061,SP_REGNUM,14,8), /* lwc1 $f14,8(sp) */\
+ MK_OP(061,SP_REGNUM,15,12), /* lwc1 $f15,12(sp) */\
+ MK_OP(043,SP_REGNUM,4,0), /* lw $r4,0(sp) */\
+ MK_OP(043,SP_REGNUM,5,4), /* lw $r5,4(sp) */\
+ MK_OP(043,SP_REGNUM,6,8), /* lw $r6,8(sp) */\
+ (Dest_Reg<<21) | (31<<11) | 9, /* jalr $r31 */\
+ MK_OP(043,SP_REGNUM,7,12), /* lw $r7,12(sp) */\
+ 13, /* bpt */\
+ }
+
+ #define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of
dummy */
+
+ /* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+ #define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
+ (*(int *)dummyname |= (((unsigned long)(fun)) >> 16), \
+ ((int*)dummyname)[1] |= (unsigned short)(fun))
+
+
+ /* Interface definitions for kernel debugger KDB. */
+
+ /* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+ #define FAULT_CODE_ORIGIN 0
+ #define FAULT_CODE_UNITS 4
+ #define FAULT_TABLE \
+ { 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+ /* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+ #define INIT_STACK(beg, end) \
+ { asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+ /* Push the frame pointer register on the stack. */
+ #define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+ /* Copy the top-of-stack to the frame pointer register. */
+ #define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+ /* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+ #define PUSH_REGISTERS { abort(); }
+
+ /* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register.
*/
+
+ #define POP_REGISTERS { abort(); }
*** mips-dep.c.orig Mon Nov 5 10:27:50 1990
--- mips-dep.c Mon Nov 5 10:28:31 1990
***************
*** 0 ****
--- 1,1151 ----
+ /* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ GDB 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 1, or (at your option)
+ any later version.
+
+ GDB 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 GDB; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+ /*
+ * The port to MIPS-based machines was mostly done
+ * by Per Bothner, bothner at cs.wisc.edu.
+ * The inspiration for the heuristics to deal with missing
+ * symbol tables, as well as many of the specific ideas for doing so,
+ * comes from Alessando Forin (Alessando.Forin at spice.cs.cmu.edu).
+ */
+ #include "defs.h"
+ #include "param.h"
+ #include "frame.h"
+ #include "inferior.h"
+ #include "value.h"
+
+ #ifdef USG
+ #include <sys/types.h>
+ #endif
+
+ #include <stdio.h>
+ #include <sys/param.h>
+ #include <sys/ptrace.h>
+ #include <sys/dir.h>
+ #include <signal.h>
+ #include <sys/ioctl.h>
+ /* #include <fcntl.h> Can we live without this? */
+
+ #ifdef COFF_ENCAPSULATE
+ #include "a.out.encap.h"
+ #else
+ #include <a.out.h>
+ #endif
+ #ifndef N_SET_MAGIC
+ #define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+ #endif
+ #define VM_MIN_ADDRESS (unsigned)0x400000
+ #include <sys/user.h> /* After a.out.h */
+ #include <sys/file.h>
+ #include <sys/stat.h>
+ #include <machine/reg.h>
+
+ #ifdef COFF_FORMAT
+ #include "symtab.h"
+
+ #ifdef USG
+ #include <sys/types.h>
+ #include <fcntl.h>
+ #endif
+
+ #include <obstack.h>
+ /*#include <sys/param.h>*/
+ /*#include <sys/file.h>*/
+
+ extern void close ();
+
+ extern PDR *proc_desc_table;
+ extern long proc_desc_length;
+
+ struct linked_proc_info
+ {
+ mips_proc_info info;
+ struct linked_proc_info *next;
+ } * linked_proc_desc_table = NULL;
+
+ extern int errno;
+
+ /* This function simply calls ptrace with the given arguments.
+ It exists so that all calls to ptrace are isolated in this
+ machine-dependent file. */
+ int
+ call_ptrace (request, pid, arg3, arg4)
+ int request, pid, arg3, arg4;
+ {
+ return ptrace (request, pid, arg3, arg4);
+ }
+
+ kill_inferior ()
+ {
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ inferior_died ();
+ }
+
+ /* This is used when GDB is exiting. It gives less chance of
error.*/
+
+ kill_inferior_fast ()
+ {
+ if (remote_debugging)
+ return;
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ }
+
+ /* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+ void
+ resume (step, signal)
+ int step;
+ int signal;
+ {
+ errno = 0;
+ if (remote_debugging)
+ remote_resume (step, signal);
+ else
+ {
+ ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ }
+ }
+
+ static char register_ptrace_map[NUM_REGS] = {
+ /* general registers */
+ 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, 31,
+ /* floating-point registers */
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ /* special registers */
+ PC, /* 96, pc */
+ CAUSE, /* 97,cause */
+ MMHI, /* 98,mdhi */
+ MMLO, /* 99,mdlow */
+ FPC_CSR,/* 100,fpc_csr */
+ FPC_EIR,/* 101,fpc_eir */
+ -1 /* fp */
+ };
+
+ void
+ fetch_inferior_registers ()
+ {
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_ptrace_map[regno];
+ if (regaddr < 0) continue;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+ regaddr++;
+ }
+ supply_register (regno, buf);
+ }
+ /* for now, make FP = SP */
+ *(long*)buf = read_register(SP_REGNUM);
+ supply_register(FP_REGNUM, buf);
+ }
+
+ /* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time).
*/
+
+ store_inferior_registers (regno)
+ int regno;
+ {
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ unsigned int i;
+
+ if (regno > FP_REGNUM)
+ return;
+ if (regno >= 0)
+ {
+ regaddr = register_ptrace_map[regno];
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, regaddr,
+ *(int *) ®isters[REGISTER_BYTE (regno) + i]);
+ if (errno != 0 && regno != CAUSE_REGNUM)
+ {
+ sprintf (buf, "writing register number %d(ptrace#%d)",
+ regno, regaddr);
+ perror_with_name (buf);
+ }
+ regaddr++;
+ }
+ return;
+ }
+
+ if (read_register (0) != 0)
+ {
+ int zero = 0;
+ error ("Cannot change register 0.");
+ supply_register (regno, &zero);
+ }
+ for (regno = 1; regno < FP_REGNUM; regno++)
+ {
+ regaddr = register_ptrace_map[regno];
+ if (regaddr < 0) continue;
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, regaddr,
+ *(int *) ®isters[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d(ptrace#%d)",
+ regno, regaddr);
+ perror_with_name (buf);
+ }
+ regaddr++;
+ }
+ }
+ }
+
+ /* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR.
+ On failure (cannot read from inferior, usually because address is
out
+ of bounds) returns the value of errno. */
+
+ int
+ read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ {
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ #if 0
+ This is now done by read_memory, because when this function did it,
+ reading a byte or short int hardware port read whole longs, causing
+ serious side effects
+ such as bus errors and unexpected hardware operation. This would
+ also be a problem with ptrace if the inferior process could read
+ or write hardware registers, but that's not usually the case.
+ if (remote_debugging)
+ buffer[i] = remote_fetch_word (addr);
+ else
+ #endif
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ if (errno)
+ return errno;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr,
len);
+ return 0;
+ }
+
+ /* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+ int
+ write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ {
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory
data. */
+
+ if (remote_debugging)
+ buffer[0] = remote_fetch_word (addr);
+ else
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ if (remote_debugging)
+ buffer[count - 1]
+ = remote_fetch_word (addr + (count - 1) * sizeof (int));
+ else
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)),
len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ if (remote_debugging)
+ remote_store_word (addr, buffer[i]);
+ else
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+ }
+
+ /* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+ #ifndef N_TXTADDR
+ #define N_TXTADDR(hdr) 0
+ #endif /* no N_TXTADDR */
+
+ #ifndef N_DATADDR
+ #define N_DATADDR(hdr) hdr.a_text
+ #endif /* no N_DATADDR */
+
+ /* Make COFF and non-COFF names for things a little more compatible
+ to reduce conditionals later. */
+
+ #ifdef COFF_FORMAT
+ #define a_magic magic
+ #endif
+
+ #ifndef COFF_FORMAT
+ #ifndef AOUTHDR
+ #define AOUTHDR struct exec
+ #endif
+ #endif
+
+ extern char *sys_siglist[];
+
+
+ /* Hook for `exec_file_command' command to call. */
+
+ extern void (*exec_file_display_hook) ();
+
+ /* 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;
+
+ /* various coff data structures */
+
+ extern FILHDR file_hdr;
+ extern SCNHDR text_hdr;
+ extern SCNHDR data_hdr;
+
+ #endif /* not COFF_FORMAT */
+
+ /* a.out header saved in core file. */
+
+ extern AOUTHDR core_aouthdr;
+
+ /* a.out header of exec file. */
+
+ extern AOUTHDR exec_aouthdr;
+
+ extern void validate_files ();
+
+ core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+ {
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 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);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ 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);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - 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 = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ *(long*)buf = 0;
+ supply_register (regno, buf);
+
+ for (regno = 1; regno < NUM_REGS; regno++)
+ {
+ int offset;
+
+ #define PCB_OFFSET(FIELD) ((int)&((struct user*)0)->u_pcb.FIELD)
+ if (regno < FP0_REGNUM)
+ offset = UPAGES*NBPG-EF_SIZE+4*((regno)+EF_AT-1);
+ else if (regno < PC_REGNUM)
+ offset = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM);
+ else if (regno == LO_REGNUM)
+ offset = UPAGES*NBPG-EF_SIZE+4*EF_MDLO;
+ else if (regno == HI_REGNUM)
+ offset = UPAGES*NBPG-EF_SIZE+4*EF_MDHI;
+ else if (regno == PC_REGNUM)
+ offset = UPAGES*NBPG-EF_SIZE+4*EF_EPC;
+ else if (regno == CAUSE_REGNUM)
+ offset = UPAGES*NBPG-EF_SIZE+4*EF_CAUSE;
+ else if (regno == FCRIR_REGNUM)
+ offset = PCB_OFFSET(pcb_fpc_eir);
+ else if (regno == FCRCS_REGNUM)
+ offset = PCB_OFFSET(pcb_fpc_csr);
+ else
+ continue;
+
+ val = lseek (corechan, 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);
+ }
+
+ 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");
+ }
+
+ exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+ {
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+ {
+ int aout_hdrsize;
+ int num_sections;
+
+ if (read_file_hdr (execchan, &file_hdr) < 0)
+ error ("\"%s\": not in executable format.", execfile);
+
+ aout_hdrsize = file_hdr.f_opthdr;
+ num_sections = file_hdr.f_nscns;
+
+ if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+ error ("\"%s\": can't read optional aouthdr", execfile);
+
+ if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections) < 0)
+ error ("\"%s\": can't read text section header", execfile);
+
+ if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 0)
+ error ("\"%s\": can't read data section header", execfile);
+
+ text_start = exec_aouthdr.text_start;
+ text_end = text_start + exec_aouthdr.tsize;
+ text_offset = 0; /* text_hdr.s_scnptr */
+ exec_data_start = exec_aouthdr.data_start;
+ exec_data_end = exec_data_start + exec_aouthdr.dsize;
+ exec_data_offset = exec_aouthdr.tsize; /*data_hdr.s_scnptr;*/
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+ exec_mtime = file_hdr.f_timdat;
+ }
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+ }
+
+ #define READ_FRAME_REG(fi, regno) read_next_frame_reg((fi)->next,
regno)
+
+ int
+ read_next_frame_reg(fi, regno)
+ FRAME fi;
+ int regno;
+ {
+ for (; fi; fi = fi->next)
+ if (regno == SP_REGNUM) return fi->frame;
+ else if (fi->saved_regs->regs[regno])
+ return read_memory_integer(fi->saved_regs->regs[regno], 4);
+ return read_register(regno);
+ }
+
+ int
+ frame_saved_pc(frame)
+ FRAME frame;
+ {
+ mips_proc_info *proc_desc = (mips_proc_info*)frame->proc_desc;
+ int pcreg = proc_desc ? PROC_PC_REG(proc_desc) : RA_REGNUM;
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ return read_memory_integer(frame->frame - 4, 4);
+ #if 0
+ /* If in the procedure prologue, RA_REGNUM might not have been saved
yet.
+ * Assume non-leaf functions start with:
+ * addiu $sp,$sp,-frame_size
+ * sw $ra,ra_offset($sp)
+ * This if the pc is pointing at either of these instructions,
+ * then $ra hasn't been trashed.
+ * If the pc has advanced beyond these two instructions,
+ * then $ra has been saved.
+ * critical, and much more complex. Handling $ra is enough to get
+ * a stack trace, but some register values with be wrong.
+ */
+ if (frame->proc_desc && frame->pc < PROC_LOW_ADDR(proc_desc) + 8)
+ return read_register(pcreg);
+ #endif
+ return read_next_frame_reg(frame, pcreg);
+ }
+
+ static PDR temp_proc_desc;
+ static struct frame_saved_regs temp_saved_regs;
+
+ CORE_ADDR heuristic_proc_start(pc)
+ CORE_ADDR pc;
+ {
+
+ CORE_ADDR start_pc = pc;
+ CORE_ADDR fence = start_pc - 10000;
+ if (fence < VM_MIN_ADDRESS) fence = VM_MIN_ADDRESS;
+ /* search back for previous return */
+ for (start_pc -= 4; ; start_pc -= 4)
+ if (start_pc < fence) return 0;
+ else if (ABOUT_TO_RETURN(start_pc))
+ break;
+
+ start_pc += 8; /* skip return, and iys delay slot */
+ #if 0
+ /* skip nops (usually 1) 0 - is this */
+ while (start_pc < pc && read_memory_integer (start_pc, 4) == 0)
+ start_pc += 4;
+ #endif
+ return start_pc;
+ }
+
+ PDR *heuristic_proc_desc(start_pc, limit_pc, next_frame)
+ CORE_ADDR start_pc, limit_pc;
+ FRAME next_frame;
+ {
+ CORE_ADDR sp = next_frame ? next_frame->frame : read_register
(SP_REGNUM);
+ CORE_ADDR cur_pc;
+ extern int breakpoints_inserted;
+ int frame_size;
+ int has_frame_reg = 0;
+ int reg30; /* Value of $r30. Used by gcc for frame-pointer */
+ unsigned long reg_mask = 0;
+ if (start_pc == 0) return NULL;
+ bzero(&temp_proc_desc, sizeof(PDR));
+ bzero(&temp_saved_regs, sizeof(struct frame_saved_regs));
+ if (start_pc + 200 < limit_pc) limit_pc = start_pc + 200;
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ restart:
+ frame_size = 0;
+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4) {
+ unsigned long word = read_memory_integer(cur_pc, 4);
+ if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
+ frame_size += (-word) & 0xFFFF;
+ else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
+ frame_size += (-word) & 0xFFFF;
+ else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp)
*/
+ int reg = (word & 0x001F0000) >> 16;
+ reg_mask |= 1 << reg;
+ temp_saved_regs.regs[reg] = sp + (short)word;
+ }
+ else if ((word & 0xFFFF0000) == 0x27be0000) { /* addiu $30,$sp,size
*/
+ if ((unsigned short)word != frame_size)
+ reg30 = sp + (unsigned short)word;
+ else if (!has_frame_reg) {
+ int alloca_adjust;
+ has_frame_reg = 1;
+ reg30 = read_next_frame_reg(next_frame, 30);
+ alloca_adjust = reg30 - (sp + (unsigned short)word);
+ if (alloca_adjust > 0) {
+ /* FP > SP + frame_size. This may be because
+ /* of an alloca or somethings similar.
+ * Fix sp to "pre-alloca" value, and try again.
+ */
+ sp += alloca_adjust;
+ goto restart;
+ }
+ }
+ }
+ else if ((word & 0xFFE00000) == 0xafc00000) { /* sw reg,offset($30)
*/
+ int reg = (word & 0x001F0000) >> 16;
+ reg_mask |= 1 << reg;
+ temp_saved_regs.regs[reg] = reg30 + (short)word;
+ }
+ }
+ if (has_frame_reg) {
+ PROC_FRAME_REG(&temp_proc_desc) = 30;
+ PROC_FRAME_OFFSET(&temp_proc_desc) = 0;
+ }
+ else {
+ PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
+ PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
+ }
+ PROC_REG_MASK(&temp_proc_desc) = reg_mask;
+ PROC_PC_REG(&temp_proc_desc) = RA_REGNUM;
+ return &temp_proc_desc;
+ }
+
+ mips_proc_info *
+ find_proc_desc(pc, next_frame)
+ CORE_ADDR pc;
+ FRAME next_frame;
+ {
+ mips_proc_info *proc_desc;
+
+ int lo = 0;
+ int hi = proc_desc_length-1;
+ if (hi >= 0 && PROC_LOW_ADDR(&proc_desc_table[0]) <= pc
+ && PROC_HIGH_ADDR(&proc_desc_table[hi]) > pc)
+ {
+ for (;;) {
+ int new = (lo + hi) >> 1;
+ proc_desc = &proc_desc_table[new];
+ if (PROC_LOW_ADDR(proc_desc) > pc) hi = new;
+ else if (PROC_HIGH_ADDR(proc_desc) <= pc) lo = new;
+ else {
+ /* IF this is the topmost frame AND
+ * (this proc does not have debugging information OR
+ * the PC is in the procedure prologue)
+ * THEN create a "hueristic" proc_desc (by analyzing
+ * the actual code) to replace the "official" proc_desc.
+ */
+ if (next_frame == NULL) {
+ struct symtab_and_line val;
+ struct symbol *proc_symbol = PROC_SYMBOL(proc_desc);
+ if (proc_symbol) {
+ val = find_pc_line (BLOCK_START
+ (SYMBOL_BLOCK_VALUE(proc_symbol)),
+ 0);
+ val.pc = val.end ? val.end : pc;
+ }
+ if (!proc_symbol || pc < val.pc) {
+ mips_proc_info *found_heuristic =
+ heuristic_proc_desc(PROC_LOW_ADDR(proc_desc),
+ pc, next_frame);
+ if (found_heuristic) proc_desc = found_heuristic;
+ }
+ }
+ break;
+ }
+ if (hi-lo <= 1) { proc_desc = 0; break; }
+ }
+ }
+ else
+ {
+ register struct linked_proc_info *link;
+ for (link = linked_proc_desc_table; link; link = link->next)
+ if (PROC_LOW_ADDR(&link->info) <= pc
+ && PROC_HIGH_ADDR(&link->info) > pc)
+ return &link->info;
+ proc_desc =
+ heuristic_proc_desc(heuristic_proc_start(pc), pc, next_frame);
+ }
+ return proc_desc;
+ }
+
+ PDR *cached_proc_desc;
+
+ FRAME_ADDR frame_chain(frame)
+ FRAME frame;
+ {
+ extern CORE_ADDR startup_file_start; /* From blockframe.c */
+ mips_proc_info *proc_desc;
+ CORE_ADDR saved_pc = frame_saved_pc(frame);
+ if (startup_file_start)
+ { /* has at least the __start symbol */
+ if (saved_pc == 0 || !outside_startup_file (saved_pc)) return 0;
+ }
+ else
+ { /* This hack depends on the internals of __start. */
+ /* We also assume the breakpoints are *not* inserted */
+ if (read_memory_integer (saved_pc + 8, 4) == 0xd) /* break */
+ return 0;
+ }
+ proc_desc = find_proc_desc(saved_pc, frame);
+ if (!proc_desc) return 0;
+ cached_proc_desc = proc_desc;
+ return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
+ + PROC_FRAME_OFFSET(proc_desc);
+ }
+
+ void
+ init_extra_frame_info(fci)
+ struct frame_info *fci;
+ {
+ extern struct obstack frame_cache_obstack;
+ /* Use proc_desc calculated in frame_chain */
+ PDR *proc_desc = fci->next ? cached_proc_desc :
+ find_proc_desc(fci->pc, fci->next);
+ fci->saved_regs = (struct frame_saved_regs*)
+ obstack_alloc (&frame_cache_obstack, sizeof(struct
frame_saved_regs));
+ bzero(fci->saved_regs, sizeof(struct frame_saved_regs));
+ fci->proc_desc =
+ proc_desc == &temp_proc_desc ? (char*)NULL : (char*)proc_desc;
+ if (proc_desc)
+ {
+ int ireg;
+ CORE_ADDR reg_position;
+ unsigned long mask;
+ /* r0 bit means kernel trap */
+ int kernel_trap = PROC_REG_MASK(proc_desc) & 1;
+
+ /* Fixup frame-pointer - only needed for top frame */
+ /* This may not be quite right, if procedure has a real frame
register */
+ if (fci->pc == PROC_LOW_ADDR(proc_desc))
+ fci->frame = read_register (SP_REGNUM);
+ else
+ fci->frame = READ_FRAME_REG(fci, PROC_FRAME_REG(proc_desc))
+ + PROC_FRAME_OFFSET(proc_desc);
+
+ if (proc_desc == &temp_proc_desc)
+ *fci->saved_regs = temp_saved_regs;
+ else
+ {
+ /* find which general-purpose registers were saved */
+ reg_position = fci->frame + PROC_REG_OFFSET(proc_desc);
+ mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc);
+ for (ireg= 31; mask; --ireg, mask <<= 1)
+ if (mask & 0x80000000)
+ {
+ fci->saved_regs->regs[ireg] = reg_position;
+ reg_position -= 4;
+ }
+ /* find which floating-point registers were saved */
+ reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc);
+ /* The freg_offset points to where the first *double* register is
saved.
+ * So skip to the high-order word. */
+ reg_position += 4;
+ mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc);
+ for (ireg = 31; mask; --ireg, mask <<= 1)
+ if (mask & 0x80000000)
+ {
+ fci->saved_regs->regs[32+ireg] = reg_position;
+ reg_position -= 4;
+ }
+ }
+
+ /* hack: if argument regs are saved, guess these contain args
*/
+ if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
+ else if ((PROC_REG_MASK(proc_desc) & 0x80) == 0) fci->num_args =
4;
+ else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args =
3;
+ else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args =
2;
+ else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args =
1;
+
+ fci->saved_regs->regs[PC_REGNUM] =
fci->saved_regs->regs[RA_REGNUM];
+ }
+ if (fci->next == 0)
+ supply_register(FP_REGNUM, &fci->frame);
+ }
+
+
+ CORE_ADDR mips_push_arguments(nargs, args, sp, struct_return,
struct_addr)
+ int nargs;
+ value *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+ {
+ CORE_ADDR buf;
+ register i;
+ int accumulate_size = struct_return ? 4 : 0;
+ struct mips_arg { char *contents; int len; int offset; };
+ struct mips_arg *mips_args =
+ (struct mips_arg*)alloca(nargs * sizeof(struct mips_arg));
+ register struct mips_arg *m_arg;
+ for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {
+ extern value value_arg_coerce();
+ value arg = value_arg_coerce (args[i]);
+ m_arg->len = TYPE_LENGTH (VALUE_TYPE (arg));
+ /* This entire mips-specific routine is because doubles must be
aligned
+ * on 8-byte boundaries. It still isn't quite right, because MIPS
decided
+ * to align 'struct {int a, b}' on 4-byte boundaries (even though
this
+ * breaks their varargs implementation...). A correct solution
+ * requires an simulation of gcc's 'alignof' (and use of
'alignof'
+ * in stdarg.h/varargs.h).
+ */
+ if (m_arg->len > 4) accumulate_size = (accumulate_size + 7) & -8;
+ m_arg->offset = accumulate_size;
+ accumulate_size = (accumulate_size + m_arg->len + 3) & -4;
+ m_arg->contents = VALUE_CONTENTS(arg);
+ }
+ accumulate_size = (accumulate_size + 7) & (-8);
+ if (accumulate_size < 16) accumulate_size = 16;
+ sp -= accumulate_size;
+ for (i = nargs; m_arg--, --i >= 0; )
+ write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+ if (struct_return) {
+ buf = struct_addr;
+ write_memory(sp, &buf, sizeof(CORE_ADDR));
+ }
+ return sp;
+ }
+
+ /* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31.
*/
+ #define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1)
+
+ void
+ push_dummy_frame()
+ {
+ int ireg;
+ struct linked_proc_info *link = (struct linked_proc_info*)
+ xmalloc(sizeof(struct linked_proc_info));
+ mips_proc_info *proc_desc = &link->info;
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ CORE_ADDR save_address;
+ REGISTER_TYPE buffer;
+ link->next = linked_proc_desc_table;
+ linked_proc_desc_table = link;
+ #define PUSH_FP_REGNUM 16 /* must be a register preserved across calls
*/
+ #define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<31)
+ #define GEN_REG_SAVE_COUNT 22
+ #define FLOAT_REG_SAVE_MASK MASK(0,19)
+ #define FLOAT_REG_SAVE_COUNT 20
+ #define SPECIAL_REG_SAVE_COUNT 4
+ /*
+ * The registers we must save are all those not preserved across
+ * procedure calls. Dest_Reg (see m-mips.h) must also be saved.
+ * In addition, we must save the PC, and PUSH_FP_REGNUM.
+ * (Ideally, we should also save MDLO/-HI and FP Control/Status
reg.)
+ *
+ * Dummy frame layout:
+ * (high memory)
+ * Saved PC
+ * Saved MMHI, MMLO, FPC_CSR
+ * Saved R31
+ * Saved R28
+ * ...
+ * Saved R1
+ * Saved D18 (i.e. F19, F18)
+ * ...
+ * Saved D0 (i.e. F1, F0)
+ * CALL_DUMMY (subroutine stub; see m-mips.h)
+ * Parameter build area (not yet implemented)
+ * (low memory)
+ */
+ PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
+ PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
+ PROC_REG_OFFSET(proc_desc) = /* offset of (Saved R31) from FP */
+ -sizeof(long) - 4 * SPECIAL_REG_SAVE_COUNT;
+ PROC_FREG_OFFSET(proc_desc) = /* offset of (Saved D18) from FP */
+ -sizeof(double) - 4 * (SPECIAL_REG_SAVE_COUNT +
GEN_REG_SAVE_COUNT);
+ /* save general registers */
+ save_address = sp + PROC_REG_OFFSET(proc_desc);
+ for (ireg = 32; --ireg >= 0; )
+ if (PROC_REG_MASK(proc_desc) & (1 << ireg))
+ {
+ buffer = read_register (ireg);
+ write_memory (save_address, &buffer, sizeof(REGISTER_TYPE));
+ save_address -= 4;
+ }
+ /* save floating-points registers */
+ save_address = sp + PROC_FREG_OFFSET(proc_desc);
+ for (ireg = 32; --ireg >= 0; )
+ if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
+ {
+ buffer = read_register (ireg);
+ write_memory (save_address, &buffer, 4);
+ save_address -= 4;
+ }
+ write_register (PUSH_FP_REGNUM, sp);
+ PROC_FRAME_REG(proc_desc) = PUSH_FP_REGNUM;
+ PROC_FRAME_OFFSET(proc_desc) = 0;
+ buffer = read_register (PC_REGNUM);
+ write_memory (sp - 4, &buffer, sizeof(REGISTER_TYPE));
+ buffer = read_register (HI_REGNUM);
+ write_memory (sp - 8, &buffer, sizeof(REGISTER_TYPE));
+ buffer = read_register (LO_REGNUM);
+ write_memory (sp - 12, &buffer, sizeof(REGISTER_TYPE));
+ buffer = read_register (FCRCS_REGNUM);
+ write_memory (sp - 16, &buffer, sizeof(REGISTER_TYPE));
+ sp -= 4 *
(GEN_REG_SAVE_COUNT+FLOAT_REG_SAVE_COUNT+SPECIAL_REG_SAVE_COUNT);
+ write_register (SP_REGNUM, sp);
+ PROC_HIGH_ADDR(proc_desc) = sp;
+ PROC_LOW_ADDR(proc_desc) = sp - CALL_DUMMY_SIZE;
+ SET_PROC_DESC_IS_DUMMY(proc_desc);
+ PROC_PC_REG(proc_desc) = RA_REGNUM;
+ }
+
+ void
+ pop_frame()
+ { register int regnum;
+ FRAME frame = get_current_frame ();
+ CORE_ADDR new_sp = frame->frame;
+ mips_proc_info *proc_desc = (PDR*)frame->proc_desc;
+ if (PROC_DESC_IS_DUMMY(proc_desc))
+ {
+ struct linked_proc_info **ptr = &linked_proc_desc_table;;
+ for (; &ptr[0]->info != proc_desc; ptr = &ptr[0]->next )
+ if (ptr[0] == NULL) abort();
+ *ptr = ptr[0]->next;
+ free (ptr[0]);
+ write_register (HI_REGNUM, read_memory_integer(new_sp - 8, 4));
+ write_register (LO_REGNUM, read_memory_integer(new_sp - 12,
4));
+ write_register (FCRCS_REGNUM, read_memory_integer(new_sp - 16,
4));
+ }
+ write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+ if (frame->proc_desc) {
+ for (regnum = 32; --regnum >= 0; )
+ if (PROC_REG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs->regs[regnum], 4));
+ for (regnum = 64; --regnum >= 32; )
+ if (PROC_FREG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs->regs[regnum], 4));
+ }
+ write_register (SP_REGNUM, new_sp);
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (new_sp, read_pc ()));
+ }
+
+ static mips_print_register(regnum, all)
+ int regnum, all;
+ {
+ unsigned char raw_buffer[8];
+ REGISTER_TYPE val;
+
+ read_relative_register_raw_bytes (regnum, raw_buffer);
+
+ if (!(regnum & 1) && regnum >= FP0_REGNUM && regnum <
FP0_REGNUM+32) {
+ read_relative_register_raw_bytes (regnum+1, raw_buffer+4);
+ printf_filtered ("(d%d: ", regnum&31);
+ val_print (builtin_type_double, raw_buffer, 0,
+ stdout, 0, 1, 0, Val_pretty_default);
+ printf_filtered ("); ", regnum&31);
+ }
+ fputs_filtered (reg_names[regnum], stdout);
+ #ifndef NUMERIC_REG_NAMES
+ if (regnum < 32)
+ printf_filtered ("(r%d): ", regnum);
+ else
+ #endif
+ printf_filtered (": ");
+
+ /* If virtual format is floating, print it that way. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
+ && ! INVALID_FLOAT (raw_buffer, REGISTER_VIRTUAL_SIZE(regnum))) {
+ val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
+ stdout, 0, 1, 0, Val_pretty_default);
+ }
+ /* Else print as integer in hex. */
+ else
+ {
+ long val;
+
+ bcopy (raw_buffer, &val, sizeof (long));
+ if (val == 0)
+ printf_filtered ("0");
+ else if (all)
+ printf_filtered ("0x%x", val);
+ else
+ printf_filtered ("0x%x=%d", val, val);
+ }
+ }
+
+ mips_do_registers_info(regnum)
+ int regnum;
+ {
+ if (regnum != -1) {
+ mips_print_register (regnum, 0);
+ printf_filtered ("\n");
+ }
+ else {
+ for (regnum = 0; regnum < NUM_REGS; ) {
+ mips_print_register (regnum, 1);
+ regnum++;
+ if ((regnum & 3) == 0 || regnum == NUM_REGS)
+ printf_filtered (";\n");
+ else
+ printf_filtered ("; ");
+ }
+ }
+ }
*** mips-opcode.h.orig Mon Nov 5 10:27:50 1990
--- mips-opcode.h Mon Nov 5 11:12:55 1990
***************
*** 0 ****
--- 1,367 ----
+ /* Mips opcde list for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Contributed by Nobuyuki Hikichi(hikichi at sra.junet)
+ Made to work for little-endian machines, and debugged
+ by Per Bothner (bothner at cs.wisc.edu).
+ Many fixes contributed by Frank Yellin (fy at lucid.com).
+
+ This file is part of GDB.
+
+ GDB 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 1, or (at your option)
+ any later version.
+
+ GDB 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 GDB; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+ #ifdef BITS_BIG_ENDIAN
+ #define BIT_FIELDS_2(a,b) a;b;
+ #define BIT_FIELDS_4(a,b,c,d) a;b;c;d;
+ #define BIT_FIELDS_6(a,b,c,d,e,f) a;b;c;d;e;f;
+ #else
+ #define BIT_FIELDS_2(a,b) b;a;
+ #define BIT_FIELDS_4(a,b,c,d) d;c;b;a;
+ #define BIT_FIELDS_6(a,b,c,d,e,f) f;e;d;c;b;a;
+ #endif
+
+ struct op_i_fmt
+ {
+ BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+ };
+
+ struct op_j_fmt
+ {
+ BIT_FIELDS_2(
+ unsigned op : 6,
+ unsigned target : 26)
+ };
+
+ struct op_r_fmt
+ {
+ BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned rd : 5,
+ unsigned shamt : 5,
+ unsigned funct : 6)
+ };
+
+
+ struct fop_i_fmt
+ {
+ BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+ };
+
+ struct op_b_fmt
+ {
+ BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ short delta : 16)
+ };
+
+ struct fop_r_fmt
+ {
+ BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned fmt : 5,
+ unsigned ft : 5,
+ unsigned fs : 5,
+ unsigned fd : 5,
+ unsigned funct : 6)
+ };
+
+ struct mips_opcode
+ {
+ char *name;
+ unsigned long opcode;
+ unsigned long match;
+ char *args;
+ };
+
+ /* args format;
+
+ "s" rs: source register specifier
+ "t" rt: target register
+ "i" immediate
+ "a" target address
+ "c" branch condition
+ "d" rd: destination register specifier
+ "h" shamt: shift amount
+ "f" funct: function field
+
+ for fpu
+ "S" fs source 1 register
+ "T" ft source 2 register
+ "D" destination register
+ */
+
+ #define one(x) (x << 26)
+ #define op_func(x, y) ((x << 26) | y)
+ #define op_cond(x, y) ((x << 26) | (y << 16))
+ #define op_rs_func(x, y, z) ((x << 26) | (y << 21) | z)
+ #define op_rs_b11(x, y, z) ((x << 26) | (y << 21) | z)
+ #define op_o16(x, y) ((x << 26) | (y << 16))
+ #define op_bc(x, y, z) ((x << 26) | (y << 21) | (z << 16))
+
+ struct mips_opcode mips_opcodes[] =
+ {
+ /* These first opcodes are special cases of the ones in the comments
*/
+ {"nop", 0, 0xffffffff, /*li*/ ""},
+ {"li", op_bc(9,0,0), op_bc(0x3f,31,0), /*addiu*/ "t,j"},
+ {"b", one(4), 0xffff0000, /*beq*/ "b"},
+ {"move", op_func(0, 33), op_cond(0x3f,31)|0x7ff,/*addu*/ "d,s"},
+
+ {"sll", op_func(0, 0), op_func(0x3f, 0x3f), "d,t,h"},
+ {"srl", op_func(0, 2), op_func(0x3f, 0x3f), "d,t,h"},
+ {"sra", op_func(0, 3), op_func(0x3f, 0x3f), "d,t,h"},
+ {"sllv", op_func(0, 4), op_func(0x3f, 0x7ff), "d,t,s"},
+ {"srlv", op_func(0, 6), op_func(0x3f, 0x7ff), "d,t,s"},
+ {"srav", op_func(0, 7), op_func(0x3f, 0x7ff), "d,t,s"},
+ {"jr", op_func(0, 8), op_func(0x3f, 0x1fffff), "s"},
+ {"jalr", op_func(0, 9), op_func(0x3f, 0x1f07ff), "d,s"},
+ {"syscall", op_func(0, 12), op_func(0x3f, 0x3f), ""},
+ {"break", op_func(0, 13), op_func(0x3f, 0x3f), ""},
+ {"mfhi", op_func(0, 16), op_func(0x3f, 0x03ff07ff), "d"},
+ {"mthi", op_func(0, 17), op_func(0x3f, 0x1fffff), "s"},
+ {"mflo", op_func(0, 18), op_func(0x3f, 0x03ff07ff), "d"},
+ {"mtlo", op_func(0, 19), op_func(0x3f, 0x1fffff), "s"},
+ {"mult", op_func(0, 24), op_func(0x3f, 0xffff), "s,t"},
+ {"multu", op_func(0, 25), op_func(0x3f, 0xffff), "s,t"},
+ {"div", op_func(0, 26), op_func(0x3f, 0xffff), "s,t"},
+ {"divu", op_func(0, 27), op_func(0x3f, 0xffff), "s,t"},
+ {"add", op_func(0, 32), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"addu", op_func(0, 33), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"sub", op_func(0, 34), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"subu", op_func(0, 35), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"and", op_func(0, 36), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"or", op_func(0, 37), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"xor", op_func(0, 38), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"nor", op_func(0, 39), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"slt", op_func(0, 42), op_func(0x3f, 0x7ff), "d,s,t"},
+ {"sltu", op_func(0, 43), op_func(0x3f, 0x7ff), "d,s,t"},
+
+ {"bltz", op_cond (1, 0), op_cond(0x3f, 0x1f), "s,b"},
+ {"bgez", op_cond (1, 1), op_cond(0x3f, 0x1f), "s,b"},
+ {"bltzal", op_cond (1, 16),op_cond(0x3f, 0x1f), "s,b"},
+ {"bgezal", op_cond (1, 17),op_cond(0x3f, 0x1f), "s,b"},
+
+
+ {"j", one(2), one(0x3f), "a"},
+ {"jal", one(3), one(0x3f), "a"},
+ {"beq", one(4), one(0x3f), "s,t,b"},
+ {"bne", one(5), one(0x3f), "s,t,b"},
+ {"blez", one(6), one(0x3f) | 0x1f0000, "s,b"},
+ {"bgtz", one(7), one(0x3f) | 0x1f0000, "s,b"},
+ {"addi", one(8), one(0x3f), "t,s,j"},
+ {"addiu", one(9), one(0x3f), "t,s,j"},
+ {"slti", one(10), one(0x3f), "t,s,j"},
+ {"sltiu", one(11), one(0x3f), "t,s,j"},
+ {"andi", one(12), one(0x3f), "t,s,i"},
+ {"ori", one(13), one(0x3f), "t,s,i"},
+ {"xori", one(14), one(0x3f), "t,s,i"},
+ /* rs field is don't care field? */
+ {"lui", one(15), one(0x3f), "t,i"},
+
+ /* co processor 0 instruction */
+ {"mfc0", op_rs_b11 (16, 0, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"cfc0", op_rs_b11 (16, 2, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"mtc0", op_rs_b11 (16, 4, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"ctc0", op_rs_b11 (16, 6, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+
+ {"bc0f", op_o16(16, 0x100), op_o16(0x3f, 0x3ff), "b"},
+ {"bc0f", op_o16(16, 0x180), op_o16(0x3f, 0x3ff), "b"},
+ {"bc0t", op_o16(16, 0x101), op_o16(0x3f, 0x3ff), "b"},
+ {"bc0t", op_o16(16, 0x181), op_o16(0x3f, 0x3ff), "b"},
+
+ {"tlbr", op_rs_func(16, 0x10, 1),
+ op_rs_func(0x3f, 0x1f, 0x1f), ""},
+ {"tlbwi", op_rs_func(16, 0x10, 2),
+ op_rs_func(0x3f, 0x1f, 0x1f), ""},
+ {"tlbwr", op_rs_func(16, 0x10, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f), ""},
+ {"tlbp", op_rs_func(16, 0x10, 8),
+ op_rs_func(0x3f, 0x1f, 0x1f), ""},
+ {"rfe", op_rs_func(16, 0x10, 16),
+ op_rs_func(0x3f, 0x1f, 0x1f), ""},
+
+ {"mfc1", op_rs_b11 (17, 0, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,S"},
+ {"cfc1", op_rs_b11 (17, 2, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,S"},
+ {"mtc1", op_rs_b11 (17, 4, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,S"},
+ {"ctc1", op_rs_b11 (17, 6, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,S"},
+
+ {"bc1f", op_o16(17, 0x100), op_o16(0x3f, 0x3ff), "b"},
+ {"bc1f", op_o16(17, 0x180), op_o16(0x3f, 0x3ff), "b"},
+ {"bc1t", op_o16(17, 0x101), op_o16(0x3f, 0x3ff), "b"},
+ {"bc1t", op_o16(17, 0x181), op_o16(0x3f, 0x3ff), "b"},
+
+ /* fpu instruction */
+ {"add.s", op_rs_func(17, 0x10, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"add.d", op_rs_func(17, 0x11, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"sub.s", op_rs_func(17, 0x10, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"sub.d", op_rs_func(17, 0x11, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"mul.s", op_rs_func(17, 0x10, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"mul.d", op_rs_func(17, 0x11, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"div.s", op_rs_func(17, 0x10, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"div.d", op_rs_func(17, 0x11, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T"},
+ {"abs.s", op_rs_func(17, 0x10, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"abs.d", op_rs_func(17, 0x11, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"mov.s", op_rs_func(17, 0x10, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"mov.d", op_rs_func(17, 0x11, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"neg.s", op_rs_func(17, 0x10, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"neg.d", op_rs_func(17, 0x11, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.s.s", op_rs_func(17, 0x10, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.s.d", op_rs_func(17, 0x11, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.s.w", op_rs_func(17, 0x14, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.d.s", op_rs_func(17, 0x10, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.d.d", op_rs_func(17, 0x11, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.d.w", op_rs_func(17, 0x14, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.w.s", op_rs_func(17, 0x10, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"cvt.w.d", op_rs_func(17, 0x11, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S"},
+ {"c.f.s", op_rs_func(17, 0x10, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.f.d", op_rs_func(17, 0x11, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.un.s", op_rs_func(17, 0x10, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.un.d", op_rs_func(17, 0x11, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.eq.s", op_rs_func(17, 0x10, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.eq.d", op_rs_func(17, 0x11, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ueq.s", op_rs_func(17, 0x10, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ueq.d", op_rs_func(17, 0x11, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.olt.s", op_rs_func(17, 0x10, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.olt.d", op_rs_func(17, 0x11, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ult.s", op_rs_func(17, 0x10, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ult.d", op_rs_func(17, 0x11, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ole.s", op_rs_func(17, 0x10, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ole.d", op_rs_func(17, 0x11, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ule.s", op_rs_func(17, 0x10, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ule.d", op_rs_func(17, 0x11, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.sf.s", op_rs_func(17, 0x10, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.sf.d", op_rs_func(17, 0x11, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngle.s", op_rs_func(17, 0x10, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngle.d", op_rs_func(17, 0x11, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.seq.s", op_rs_func(17, 0x10, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.seq.d", op_rs_func(17, 0x11, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngl.s", op_rs_func(17, 0x10, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngl.d", op_rs_func(17, 0x11, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.lt.s", op_rs_func(17, 0x10, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.lt.d", op_rs_func(17, 0x11, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.nge.s", op_rs_func(17, 0x10, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.nge.d", op_rs_func(17, 0x11, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.le.s", op_rs_func(17, 0x10, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.le.d", op_rs_func(17, 0x11, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngt.s", op_rs_func(17, 0x10, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+ {"c.ngt.d", op_rs_func(17, 0x11, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T"},
+
+ /* co processor 2 instruction */
+ {"mfc2", op_rs_b11 (18, 0, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"cfc2", op_rs_b11 (18, 2, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"mtc2", op_rs_b11 (18, 4, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"ctc2", op_rs_b11 (18, 6, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"bc2f", op_o16(18, 0x100), op_o16(0x3f, 0x3ff), "b"},
+ {"bc2f", op_o16(18, 0x180), op_o16(0x3f, 0x3ff), "b"},
+ {"bc2t", op_o16(18, 0x101), op_o16(0x3f, 0x3ff), "b"},
+ {"bc2t", op_o16(18, 0x181), op_o16(0x3f, 0x3ff), "b"},
+
+ /* co processor 3 instruction */
+ {"mtc3", op_rs_b11 (19, 0, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"cfc3", op_rs_b11 (19, 2, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"mtc3", op_rs_b11 (19, 4, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"ctc3", op_rs_b11 (19, 6, 0), op_rs_b11(0x3f, 0x1f, 0x7ff),
"t,d"},
+ {"bc3f", op_o16(19, 0x100), op_o16(0x3f, 0x3ff), "b"},
+ {"bc3f", op_o16(19, 0x180), op_o16(0x3f, 0x3ff), "b"},
+ {"bc3t", op_o16(19, 0x101), op_o16(0x3f, 0x3ff), "b"},
+ {"bc3t", op_o16(19, 0x181), op_o16(0x3f, 0x3ff), "b"},
+
+ {"lb", one(32), one(0x3f), "t,j(s)"},
+ {"lh", one(33), one(0x3f), "t,j(s)"},
+ {"lwl", one(34), one(0x3f), "t,j(s)"},
+ {"lw", one(35), one(0x3f), "t,j(s)"},
+ {"lbu", one(36), one(0x3f), "t,j(s)"},
+ {"lhu", one(37), one(0x3f), "t,j(s)"},
+ {"lwr", one(38), one(0x3f), "t,j(s)"},
+ {"sb", one(40), one(0x3f), "t,j(s)"},
+ {"sh", one(41), one(0x3f), "t,j(s)"},
+ {"swl", one(42), one(0x3f), "t,j(s)"},
+ {"swr", one(46), one(0x3f), "t,j(s)"},
+ {"sw", one(43), one(0x3f), "t,j(s)"},
+ {"lwc0", one(48), one(0x3f), "t,j(s)"},
+ /* for fpu */
+ {"lwc1", one(49), one(0x3f), "T,j(s)"},
+ {"lwc2", one(50), one(0x3f), "t,j(s)"},
+ {"lwc3", one(51), one(0x3f), "t,j(s)"},
+ {"swc0", one(56), one(0x3f), "t,j(s)"},
+ /* for fpu */
+ {"swc1", one(57), one(0x3f), "T,j(s)"},
+ {"swc2", one(58), one(0x3f), "t,j(s)"},
+ {"swc3", one(59), one(0x3f), "t,j(s)"},
+ };
*** mips-pinsn.c.orig Mon Nov 5 10:27:50 1990
--- mips-pinsn.c Mon Nov 5 10:28:32 1990
***************
*** 0 ****
--- 1,149 ----
+ /* Print mips instructions for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Contributed by Nobuyuki Hikichi(hikichi at sra.co.jp)
+
+ This file is part of GDB.
+
+ GDB 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 1, or (at your option)
+ any later version.
+
+ GDB 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 GDB; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+ #include <stdio.h>
+
+ #include "defs.h"
+ #include "param.h"
+ #include "symtab.h"
+ #include "mips-opcode.h"
+
+ /* Mips instructions are never longer than this many bytes. */
+ #define MAXLEN 4
+
+ /* Number of elements in the opcode table. */
+ #define NOPCODES (sizeof mips_opcodes / sizeof mips_opcodes[0])
+
+ #define MKLONG(p) *(unsigned long*)p
+
+ extern char *reg_names[];
+
+
+ /* subroutine */
+ static unsigned char *
+ print_insn_arg (d, l, stream, pc)
+ char *d;
+ register unsigned long int *l;
+ FILE *stream;
+ CORE_ADDR pc;
+ {
+ switch (*d)
+ {
+ case ',':
+ case '(':
+ case ')':
+ fputc (*d, stream);
+ break;
+
+ case 's':
+ fprintf (stream, "$%s", reg_names[((struct op_i_fmt *)
l)->rs]);
+ break;
+
+ case 't':
+ fprintf (stream, "$%s", reg_names[((struct op_i_fmt *)
l)->rt]);
+ break;
+
+ case 'i':
+ fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
+ break;
+
+ case 'j': /* same as i, but sign-extended */
+ fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
+ break;
+
+ case 'a':
+ print_address ((pc & 0xC0000000) | (((struct op_j_fmt
*)l)->target << 2),
+ stream);
+ break;
+
+ case 'b':
+ print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4,
stream);
+ break;
+
+ case 'd':
+ fprintf (stream, "%s", reg_names[((struct op_r_fmt *) l)->rd]);
+ break;
+
+ case 'h':
+ fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
+ break;
+
+ case 'S':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
+ break;
+
+ case 'T':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
+ break;
+
+ case 'D':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
+ break;
+
+ default:
+ fprintf (stream, "# internal error, undefined modifier(%c)",
*d);
+ break;
+ }
+ }
+
+ /* Print the mips instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes, which
+ is always 4. */
+
+ int
+ print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+ {
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register char *d;
+ unsigned long int l;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ for (i = 0; i < NOPCODES; i++)
+ {
+ register unsigned int opcode = mips_opcodes[i].opcode;
+ register unsigned int match = mips_opcodes[i].match;
+ if ((*(unsigned int*)buffer & match) == opcode)
+ break;
+ }
+
+ l = MKLONG (buffer);
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ fprintf (stream, "0x%x",l);
+ return 4;
+ }
+
+ fprintf (stream, "%s", mips_opcodes[i].name);
+
+ if (!(d = mips_opcodes[i].args))
+ return 4;
+
+ fputc (' ', stream);
+
+ while (*d)
+ print_insn_arg (d++, &l, stream, memaddr);
+
+ return 4;
+ }
*** mipscoff.c.orig Mon Nov 5 10:27:50 1990
--- mipscoff.c Mon Nov 5 11:21:44 1990
***************
*** 0 ****
--- 1,2044 ----
+ /* Read coff symbol tables and convert to internal format, for GDB.
+ Design and support routines derived from dbxread.c, and UMAX COFF
+ specific routines written 9/1/87 by David D. Johnson, Brown
University.
+ Revised 11/27/87 ddj at cs.brown.edu
+ Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ GDB 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 1, or (at your option)
+ any later version.
+
+ GDB 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 GDB; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+
+ #include <a.out.h>
+ #include <stdio.h>
+ #include "symtab.h"
+ #include <sys/file.h>
+
+ PDR *proc_desc_table = NULL;
+ long proc_desc_length = 0;
+
+ static void add_symbol_to_list ();
+ static int read_coff_symtab ();
+ static void patch_opaque_types ();
+ static struct type *decode_function_type ();
+ static struct type *decode_type ();
+ static struct type *decode_base_type ();
+ static struct type *read_enum_type ();
+ static struct type *read_struct_type ();
+ static struct type *read_type ();
+ static void finish_block ();
+ static struct blockvector *make_blockvector ();
+ static struct symbol *process_coff_symbol ();
+ static char *getfilename ();
+ static char *getsymname ();
+
+ extern int fclose ();
+ extern void close ();
+ extern void free_all_symtabs ();
+ extern void free_all_psymtabs ();
+
+
+ /* Name of source file whose symbol data we are now processing.
+ This comes from a symbol named ".file". */
+
+ static char *last_source_file;
+
+ /* Core address of the end of the first object file. */
+ static CORE_ADDR first_object_file_end;
+
+ /* End of the text segment of the executable file,
+ as found in the symbol _etext. */
+
+ static CORE_ADDR end_of_text_addr;
+
+ /* The end address of the last seen procedure. */
+
+ static CORE_ADDR last_end_addr;
+
+ /* The file, a.out and text section headers of the symbol file */
+
+ static FILHDR file_hdr;
+ static SCNHDR text_hdr;
+ static AOUTHDR aout_hdr;
+
+ /* The index in the symbol table of the last coff symbol that was
processed. */
+
+ static int symnum;
+
+ /* Vector of types defined so far, indexed by their coff symnum. */
+
+ static struct typevector *type_vector;
+
+ /* Number of elements allocated for type_vector currently. */
+
+ static int type_vector_length;
+
+ /* Chain of typedefs of pointers to empty struct/union types.
+ They are chained thru the SYMBOL_VALUE. */
+
+ #define HASHSIZE 127
+ static struct symbol *opaque_type_chain[HASHSIZE];
+
+ /* Record the symbols defined for each context in a list.
+ We don't create a struct block for the context until we
+ know how long to make it. */
+
+ struct pending
+ {
+ struct pending *next;
+ struct symbol *symbol;
+ };
+
+ /* Here are the three lists that symbols are put on. */
+
+ struct pending *file_symbols; /* static at top level, and types */
+
+ struct pending *global_symbols; /* global functions and variables */
+
+ struct pending **global_symbols_all, **file_symbols_all;
+
+ struct pending *local_symbols; /* everything local to lexical context
*/
+
+ /* List of unclosed lexical contexts
+ (that will become blocks, eventually). */
+
+ struct context_stack
+ {
+ struct context_stack *next;
+ struct pending *locals;
+ struct pending_block *old_blocks;
+ struct symbol *name;
+ CORE_ADDR start_addr;
+ };
+
+ struct context_stack *context_stack;
+
+ /* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+ int within_function;
+
+ /* List of blocks already made (lexical contexts already closed).
+ This is used at the end to make the blockvector. */
+
+ struct pending_block
+ {
+ struct pending_block *next;
+ struct block *block;
+ };
+
+ struct pending_block *pending_blocks;
+
+ extern CORE_ADDR startup_file_start; /* From blockframe.c */
+ extern CORE_ADDR startup_file_end; /* From blockframe.c */
+
+ /* File name symbols were loaded from. */
+
+ static char *symfile;
+
+ /* Look up a coff type-number index. Return the address of the slot
+ where the type for that index is stored.
+ The type-number is in INDEX.
+
+ This can be used for finding the type associated with that index
+ or for associating a new type with the index. */
+
+ static struct type **
+ coff_lookup_type (index)
+ register int index;
+ {
+ if (index >= type_vector_length)
+ {
+ int old_vector_length = type_vector_length;
+
+ type_vector_length *= 2;
+ if (type_vector_length < index) {
+ type_vector_length = index * 2;
+ }
+ type_vector = (struct typevector *)
+ xrealloc (type_vector, sizeof (struct typevector)
+ + type_vector_length * sizeof (struct type *));
+ bzero (&type_vector->type[ old_vector_length ],
+ (type_vector_length - old_vector_length) * sizeof(struct type
*));
+ }
+ return &type_vector->type[index];
+ }
+
+ /* Make sure there is a type allocated for type number index
+ and return the type object.
+ This can create an empty (zeroed) type object. */
+
+ static struct type *
+ coff_alloc_type (index)
+ int index;
+ {
+ register struct type **type_addr = coff_lookup_type (index);
+ register struct type *type = *type_addr;
+
+ /* If we are referring to a type not known at all yet,
+ allocate an empty type for it.
+ We will fill it in later if we find out how. */
+ if (type == 0)
+ {
+ type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ bzero (type, sizeof (struct type));
+ *type_addr = type;
+ }
+ return type;
+ }
+
+ /* maintain the lists of symbols and blocks */
+
+ /* Add a symbol to one of the lists of symbols. */
+ static void
+ add_symbol_to_list (symbol, listhead)
+ struct symbol *symbol;
+ struct pending **listhead;
+ {
+ register struct pending *link
+ = (struct pending *) xmalloc (sizeof (struct pending));
+
+ link->next = *listhead;
+ link->symbol = symbol;
+ *listhead = link;
+ }
+
+ /* Take one of the lists of symbols and make a block from it.
+ Put the block on the list of pending blocks. */
+
+ static void
+ finish_block (symbol, listhead, old_blocks, start, end)
+ struct symbol *symbol;
+ struct pending **listhead;
+ struct pending_block *old_blocks;
+ CORE_ADDR start, end;
+ {
+ register struct pending *next, *next1;
+ register struct block *block;
+ register struct pending_block *pblock;
+ struct pending_block *opblock;
+ register int i;
+
+ /* Count the length of the list of symbols. */
+
+ for (next = *listhead, i = 0; next; next = next->next, i++);
+
+ block = (struct block *)
+ obstack_alloc (symbol_obstack, sizeof (struct block) + (i - 1) *
sizeof (struct symbol *));
+
+ /* Copy the symbols into the block. */
+
+ BLOCK_NSYMS (block) = i;
+ for (next = *listhead; next; next = next->next)
+ BLOCK_SYM (block, --i) = next->symbol;
+
+ BLOCK_START (block) = start;
+ BLOCK_END (block) = end;
+ BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is
made */
+
+ /* Put the block in as the value of the symbol that names it. */
+
+ if (symbol)
+ {
+ SYMBOL_BLOCK_VALUE (symbol) = block;
+ BLOCK_FUNCTION (block) = symbol;
+ }
+ else
+ BLOCK_FUNCTION (block) = 0;
+
+ /* Now free the links of the list, and empty the list. */
+
+ for (next = *listhead; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+ *listhead = 0;
+
+ /* Install this block as the superblock
+ of all blocks made since the start of this scope
+ that don't have superblocks yet. */
+
+ opblock = 0;
+ for (pblock = pending_blocks; pblock != old_blocks; pblock =
pblock->next)
+ {
+ if (BLOCK_SUPERBLOCK (pblock->block) == 0)
+ BLOCK_SUPERBLOCK (pblock->block) = block;
+ opblock = pblock;
+ }
+
+ /* Record this block on the list of all blocks in the file.
+ Put it after opblock, or at the beginning if opblock is 0.
+ This puts the block in the list after all its subblocks. */
+
+ pblock = (struct pending_block *) xmalloc (sizeof (struct
pending_block));
+ pblock->block = block;
+ if (opblock)
+ {
+ pblock->next = opblock->next;
+ opblock->next = pblock;
+ }
+ else
+ {
+ pblock->next = pending_blocks;
+ pending_blocks = pblock;
+ }
+ }
+
+ static struct blockvector *
+ make_blockvector ()
+ {
+ register struct pending_block *next, *next1;
+ register struct blockvector *blockvector;
+ register int i;
+
+ /* Count the length of the list of blocks. */
+
+ for (next = pending_blocks, i = 0; next; next = next->next, i++);
+
+ blockvector = (struct blockvector *)
+ obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i -
1) * sizeof (struct block *));
+
+ /* Copy the blocks into the blockvector.
+ This is done in reverse order, which happens to put
+ the blocks into the proper order (ascending starting address).
+ finish_block has hair to insert each block into the list
+ after its subblocks in order to make sure this is true. */
+
+ BLOCKVECTOR_NBLOCKS (blockvector) = i;
+ for (next = pending_blocks; next; next = next->next)
+ BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+
+ /* Now free the links of the list, and empty the list. */
+
+ for (next = pending_blocks; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+ pending_blocks = 0;
+
+ return blockvector;
+ }
+
+ /* Manage the vector of line numbers. */
+
+ static
+ record_line (line, pc)
+ int line;
+ CORE_ADDR pc;
+ {
+ }
+
+ /* Start a new symtab for a new source file.
+ This is called when a COFF ".file" symbol is seen;
+ it indicates the start of data for one original source file. */
+
+ static void
+ start_symtab ()
+ {
+ context_stack = 0;
+ within_function = 0;
+ last_source_file = 0;
+
+ /* Initialize the source file information for this file. */
+
+ }
+
+ /* Finish the symbol definitions for one main source file,
+ close off all the lexical contexts for that file
+ (creating struct block's for them), then make the
+ struct symtab for that file and put it in the list of all such.
+
+ END_ADDR is the address of the end of the file's text. */
+
+ static void
+ end_symtab (start_addr, end_addr, linetable)
+ CORE_ADDR start_addr, end_addr;
+ struct linetable *linetable;
+ {
+ register struct symtab *symtab;
+ register struct context_stack *cstk;
+ register struct blockvector *blockvector;
+ struct partial_symtab *psymtab;
+
+ if (aout_hdr.entry < end_addr
+ && aout_hdr.entry >= start_addr)
+ {
+ startup_file_start = start_addr;
+ startup_file_end = end_addr;
+ }
+
+ /* Finish the lexical context of the last function in the file. */
+
+ if (context_stack)
+ {
+ cstk = context_stack;
+ context_stack = 0;
+ /* Make a block for the local symbols within. */
+ finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+ cstk->start_addr, end_addr);
+ free (cstk);
+ }
+
+ /* Create the two top-level blocks for this file. */
+ finish_block (0, &file_symbols, 0, start_addr, end_addr);
+ finish_block (0, &global_symbols, 0, start_addr, end_addr);
+
+ /* Create the blockvector that points to all the file's blocks. */
+ blockvector = make_blockvector ();
+
+ /* Now create the symtab object for this source file. */
+ symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
+ symtab->free_ptr = 0;
+
+ /* Fill in its components. */
+ symtab->blockvector = blockvector;
+ symtab->free_code = free_linetable;
+ symtab->filename = last_source_file;
+ symtab->linetable = linetable;
+ symtab->nlines = 0;
+ symtab->line_charpos = 0;
+
+ /* Link the new symtab into the list of such. */
+ symtab->next = symtab_list;
+ symtab_list = symtab;
+
+ /* Reinitialize for beginning of new file. */
+ last_source_file = 0;
+
+ /* Create a fake partial_symtab, so that find_pc_partial_function
+ * will do the right thing. */
+ psymtab = (struct partial_symtab *)
+ obstack_alloc (psymbol_obstack,
+ sizeof (struct partial_symtab));
+ bzero (psymtab, sizeof (struct partial_symtab));
+ psymtab->next = partial_symtab_list;
+ partial_symtab_list = psymtab;
+ psymtab->textlow = start_addr;
+ psymtab->texthigh = end_addr;
+ psymtab->filename = symtab->filename ? symtab->filename : "";
+ psymtab->readin = 1;
+
+ }
+
+ /* Accumulate the misc functions in bunches of 127.
+ At the end, copy them all into one newly allocated structure. */
+
+ #define MISC_BUNCH_SIZE 127
+
+ struct misc_bunch
+ {
+ struct misc_bunch *next;
+ struct misc_function contents[MISC_BUNCH_SIZE];
+ };
+
+ /* Bunch currently being filled up.
+ The next field points to chain of filled bunches. */
+
+ static struct misc_bunch *misc_bunch;
+
+ /* Number of slots filled in current bunch. */
+
+ static int misc_bunch_index;
+
+ /* Total number of misc functions recorded so far. */
+
+ static int misc_count;
+
+ static void
+ init_misc_functions ()
+ {
+ misc_count = 0;
+ misc_bunch = 0;
+ misc_bunch_index = MISC_BUNCH_SIZE;
+ }
+
+ static void
+ record_misc_function (name, address)
+ char *name;
+ CORE_ADDR address;
+ {
+ register struct misc_bunch *new;
+
+ if (misc_bunch_index == MISC_BUNCH_SIZE)
+ {
+ new = (struct misc_bunch *) xmalloc (sizeof (struct
misc_bunch));
+ misc_bunch_index = 0;
+ new->next = misc_bunch;
+ misc_bunch = new;
+ }
+ misc_bunch->contents[misc_bunch_index].name = savestring (name,
strlen (name));
+ misc_bunch->contents[misc_bunch_index].address = address;
+ misc_bunch->contents[misc_bunch_index].type = (char)mf_unknown;
+ misc_bunch_index++;
+ misc_count++;
+ }
+
+ /* if we see a function symbol, we do record_misc_function.
+ * however, if it turns out the next symbol is '.bf', then
+ * we call here to undo the misc definition
+ */
+ static void
+ unrecord_misc_function ()
+ {
+ if (misc_bunch_index == 0)
+ error ("Internal error processing symbol table, at symbol %d.",
+ symnum);
+ misc_bunch_index--;
+ misc_count--;
+ }
+
+
+ static int
+ compare_misc_functions (fn1, fn2)
+ struct misc_function *fn1, *fn2;
+ {
+ /* Return a signed result based on unsigned comparisons
+ so that we sort into unsigned numeric order. */
+ if (fn1->address < fn2->address)
+ return -1;
+ if (fn1->address > fn2->address)
+ return 1;
+ return 0;
+ }
+
+ static void
+ discard_misc_bunches ()
+ {
+ register struct misc_bunch *next;
+
+ while (misc_bunch)
+ {
+ next = misc_bunch->next;
+ free (misc_bunch);
+ misc_bunch = next;
+ }
+ }
+
+ static void
+ condense_misc_bunches ()
+ {
+ register int i, j;
+ register struct misc_bunch *bunch;
+ #ifdef NAMES_HAVE_UNDERSCORE
+ int offset = 1;
+ #else
+ int offset = 0;
+ #endif
+
+ misc_function_vector
+ = (struct misc_function *)
+ xmalloc (misc_count * sizeof (struct misc_function));
+
+ j = 0;
+ bunch = misc_bunch;
+ while (bunch)
+ {
+ for (i = 0; i < misc_bunch_index; i++)
+ {
+ register char *tmp;
+
+ misc_function_vector[j] = bunch->contents[i];
+ tmp = misc_function_vector[j].name;
+ misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset :
tmp);
+ j++;
+ }
+ bunch = bunch->next;
+ misc_bunch_index = MISC_BUNCH_SIZE;
+ }
+
+ misc_function_count = j;
+
+ /* Sort the misc functions by address. */
+
+ qsort (misc_function_vector, j, sizeof (struct misc_function),
+ compare_misc_functions);
+ }
+
+ /* Call sort_syms to sort alphabetically
+ the symbols of each block of each symtab. */
+
+ static int
+ compare_symbols (s1, s2)
+ struct symbol **s1, **s2;
+ {
+ /* Names that are less should come first. */
+ register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME
(*s2));
+ if (namediff != 0) return namediff;
+ /* For symbols of the same name, registers should come first. */
+ return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
+ - (SYMBOL_CLASS (*s1) == LOC_REGISTER));
+ }
+
+ static void
+ sort_syms ()
+ {
+ register struct symtab *s;
+ register int i, nbl;
+ register struct blockvector *bv;
+ register struct block *b;
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ bv = BLOCKVECTOR (s);
+ nbl = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < nbl; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ if (BLOCK_SHOULD_SORT (b))
+ qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+ sizeof (struct symbol *), compare_symbols);
+ }
+ }
+ }
+
+ /* Call sort_proc_descs to sort the procedure descriptors by address.
*/
+
+ static int
+ compare_proc_descs (p1, p2)
+ PDR *p1, *p2;
+ {
+ unsigned int a1, a2;
+
+ a1 = PROC_LOW_ADDR (p1);
+ a2 = PROC_LOW_ADDR (p2);
+ if (a1 < a2)
+ return -1;
+ if (a1 > a2)
+ return 1;
+ return 0;
+ }
+
+ static void
+ sort_proc_descs ()
+ {
+ qsort (proc_desc_table, proc_desc_length,
+ sizeof (PDR), compare_proc_descs);
+ }
+
+
+ /* This is the symbol-file command. Read the file, analyze its
symbols,
+ and add a struct symtab to symtab_list. */
+
+ /* !!! !!! */
+ int dump_stuff=0;
+
+ static void free_proc_descs ()
+ {
+ if (proc_desc_table != NULL) {
+ free (proc_desc_table);
+ proc_desc_table = NULL;
+ proc_desc_length = 0;
+ }
+ }
+
+ void
+ symbol_file_command (name)
+ char *name;
+ {
+ int desc;
+ int num_symbols;
+ int num_sections;
+ int symtab_offset;
+ register int val;
+ struct cleanup *old_chain;
+
+ dont_repeat ();
+
+ if (name == 0)
+ {
+ if (symtab_list && !query ("Discard symbol table? ", 0))
+ error ("Not confirmed.");
+ if (symfile)
+ free (symfile);
+ symfile = 0;
+ free_all_symtabs ();
+ free_proc_descs ();
+ return;
+ }
+
+ name = tilde_expand (name);
+ make_cleanup (free, name);
+
+ if (symtab_list && !query ("Load new symbol table from \"%s\"? ",
name))
+ error ("Not confirmed.");
+
+ if (symfile)
+ free (symfile);
+ symfile = 0;
+
+ {
+ char *absolute_name;
+
+ desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0,
&absolute_name);
+ if (desc < 0)
+ perror_with_name (name);
+ else
+ name = absolute_name;
+ }
+
+ old_chain = make_cleanup (close, desc);
+ make_cleanup (free_current_contents, &name);
+
+ if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0)
+ error ("File \"%s\" not in executable format.", name);
+
+ /* If an a.out header is present, read it in. If not (e.g. a .o
file)
+ deal with its absence. */
+ if (file_hdr.f_opthdr == 0
+ || read_aout_hdr (desc, &aout_hdr, file_hdr.f_opthdr) < 0)
+ {
+ /* We will not actually be able to run code, since backtraces
would
+ fly off the bottom of the stack (there is no way to reliably
+ detect bottom of stack), but that's fine since the kernel won't
+ run something without an a.out header anyway. Passive examination
+ of .o files is one place this might make sense. */
+ /* ~0 will not be in any file. */
+ aout_hdr.entry = ~0;
+ /* set the startup file to be an empty range. */
+ startup_file_start = 0;
+ startup_file_end = 0;
+ }
+
+ if (num_symbols == 0)
+ {
+ free_all_symtabs ();
+ free_proc_descs ();
+ printf ("%s does not have a symbol-table.\n", name);
+ fflush (stdout);
+ do_cleanups (old_chain);
+ return;
+ }
+
+ printf ("Reading symbol data from %s...", name);
+ fflush (stdout);
+
+ /* Throw away the old symbol table. */
+
+ free_all_symtabs ();
+ free_proc_descs ();
+ free_all_psymtabs (); /* Make sure that partial_symtab_list */
+ /* is 0 also. */
+
+ num_sections = file_hdr.f_nscns;
+ symtab_offset = file_hdr.f_symptr;
+
+ if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0)
+ error ("\"%s\": can't read text section header", name);
+
+ /* Position to read the symbol table. Do not read it all at once.
*/
+ val = lseek (desc, (long)symtab_offset, 0);
+ if (val < 0)
+ perror_with_name (name);
+
+ init_misc_functions ();
+ make_cleanup (discard_misc_bunches, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ val = read_coff_symtab (desc, num_symbols, symtab_offset);
+ if (val < 0) error("Bad symbol table format");
+
+ patch_opaque_types ();
+
+ /* Sort symbols alphabetically within each block. */
+
+ sort_syms ();
+
+ /* Go over the misc functions and install them in vector. */
+
+ condense_misc_bunches ();
+
+ /* Sort the procedure descriptor table. */
+
+ sort_proc_descs ();
+
+ /* Don't allow char * to have a typename (else would get caddr_t.)
*/
+
+ TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
+
+ /* Make a default for file to list. */
+
+ symfile = savestring (name, strlen (name));
+
+ do_cleanups (old_chain);
+
+ printf ("done.\n");
+ fflush (stdout);
+ }
+
+ /* Return name of file symbols were loaded from, or 0 if none.. */
+
+ char *
+ get_sym_file ()
+ {
+ return symfile;
+ }
+
+ /* Simplified internal version of coff symbol table information */
+
+ struct coff_symbol {
+ char *c_name;
+ int c_symnum; /* symbol number of this entry */
+ int c_nsyms; /* 1 if syment only, 2 if syment + auxent */
+ long c_value;
+ int c_sclass;
+ int c_secnum;
+ unsigned int c_type;
+ };
+
+ static char *
+ read_table(desc, size, offset)
+ long offset;
+ {
+ char *buf;
+ if (lseek(desc, offset, 0) < 0)
+ error("Bad symbol table format [seek]");
+ buf = xmalloc(size);
+ if (buf == NULL) error("Not enough memory");
+ if (myread (desc, buf, size) != size)
+ error("Bad symbol table format [read]");
+ return buf;
+ }
+
+ static char * (MapStNames[]) = { /* symbol type names */
+ "Nil", "Global", "Static", "Param", "Local", "Label", "Proc",
"Block",
+ "End", "Member", "Typedef", "File", "RegReloc", "Forward",
"StaticProc",
+ "Constant", "BlockPatched"
+ };
+
+ long stNameSize = sizeof(MapStNames)/sizeof(MapStNames[0]);
+
+ static char * MapScNames[] = { /* storage class names */
+ "Nil", "Text", "Data", "Bss", "Register", "Abs", "Undefined",
"CdbLocal",
+ "Bits", "Dbx", "RegImage", "Info", "UserStruct", "SData", "SBss",
"RData",
+ "Var", "Common", "SCommon", "VarRegister", "Variant",
"SUndefined", "Init"
+ };
+
+
+ long scNameSize = sizeof(MapScNames)/sizeof(MapScNames[0]);
+
+ static char *(MapBtNames[]) = { /* base type names */
+ "Nil", "Adr", "Char", "UChar", "Short", "UShort", "Int", "UInt",
"Long",
+ "ULong", "Float", "Double", "Struct", "Union", "Enum", "Typedef",
"Range",
+ "Set", "Complex", "DComplex", "Indirect", "FixedDec", "FloatDec",
"String",
+ "Bit", "Picture"
+ };
+
+ long btNameSize = sizeof(MapBtNames)/sizeof(MapBtNames[0]);
+
+ /* Given pointers to a symbol table in coff style exec file,
+ analyze them and create struct symtab's describing the symbols.
+ NSYMS is the number of symbols in the symbol table.
+ We read them one at a time using read_one_sym (). */
+
+ /* stBlockPatched indicates an stBlock symbol which has been patched
+ * so that the value points to s struct type */
+
+ #define stBlockPatched 16
+
+ static FDR *file_descriptor_table;
+ static RFDT *rel_file_table;
+ static SYMR *local_symbol_table;
+ static char *local_string_table;
+ static AUXU *aux_symbol_table;
+ static FDR *cur_file_descriptor;
+ static int file_descriptor_count;
+ /* Note that PDR is also used for frame chaining, and is defined above
*/
+
+ static int cur_proc_number; /* number of procedure within current file
*/
+ static CORE_ADDR cur_proc_addr;
+ static int cur_file_number;
+ static int cur_isymBase;
+ static int cur_issBase;
+
+ static void
+ select_file(i)
+ int i;
+ {
+ global_symbols_all[cur_file_number] = global_symbols;
+ file_symbols_all[cur_file_number] = file_symbols;
+ global_symbols = global_symbols_all[i];
+ file_symbols = file_symbols_all[i];
+ cur_file_number = i;
+ cur_file_descriptor = &file_descriptor_table[i];
+ cur_isymBase = cur_file_descriptor->isymBase;
+ cur_issBase = cur_file_descriptor->issBase;
+ }
+
+ /* side-effect: changes cur_file_descriptor */
+
+ static SYMR *
+ get_type_context(auxp)
+ AUXU** auxp;
+ {
+ SYMR *sym;
+ FDR *sym_file_desc;
+ int rfi;
+ int rfd = (*auxp)->rndx.rfd;
+ int sym_index = (*auxp)->rndx.index;
+ (*auxp)++;
+ if (rfd == ST_RFDESCAPE) { rfd = (*auxp)->isym; (*auxp)++; }
+ if (rfd == ST_EXTIFD || sym_index == ST_ANONINDEX) return NULL;
+ rfi = rel_file_table[cur_file_descriptor->rfdBase + rfd];
+ if (rfi >= file_descriptor_count) return NULL;
+ sym_file_desc = &file_descriptor_table[rfi];
+ if (sym_index >= sym_file_desc->csym || sym_index == 0) return
NULL;
+ sym = &local_symbol_table[sym_file_desc->isymBase + sym_index];
+ if (sym->index == 0) return NULL;
+ select_file(rfi);
+ if (dump_stuff)
+ printf("rfd(%d,%d)->[%s,%x,st%s,sc%s,inx:%d (%x)]\n",
+ rfi, sym_index,
+ &local_string_table[cur_issBase+sym->iss],
+ sym->value,
+ MapStNames[sym->st], MapScNames[sym->sc],
+ sym->index, sym);
+ return sym;
+ }
+
+ static struct type *
+ get_struct_type(sym, kind)
+ SYMR *sym;
+ int kind; /* either btStruct or btUnion or btNil (unknown) */
+ {
+ struct type *type;
+ if (sym->st == stBlockPatched)
+ {
+ type = (struct type*)sym->value;
+ /* Patch up possibly-wrong guess about struct vs. union */
+ if (kind == btStruct) TYPE_CODE(type) = TYPE_CODE_STRUCT;
+ else if (kind == btUnion) TYPE_CODE(type) = TYPE_CODE_UNION;
+ }
+ else if (sym->st != stBlock)
+ {
+ fprintf(stderr,"Bad symbol table: struct/union points to
non-stBlock\n");
+ type = builtin_type_void;
+ }
+ else
+ {
+ int nfields = 0;
+ SYMR *first_field = sym+1;
+ register struct field *cur_field;
+ char *sym_name = &local_string_table[cur_issBase+sym->iss];
+ int iauxBase = cur_file_descriptor->iauxBase;
+ type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ bzero (type, sizeof (struct type));
+ TYPE_LENGTH (type) = sym->value;
+
+ /* we "remember" the type generated from this block */
+ sym->st = stBlockPatched;
+ sym->value = (long)type;
+
+ /* first count the number of fields */
+ for (sym = first_field; sym->st != stEnd; sym++)
+ if (sym->st == stMember) nfields++;
+ else if (sym->st == stBlock || sym->st == stBlockPatched)
+ {
+ if (sym->sc == scVariant) ; /* UNIMPLEMENTED */
+ if (sym->index != 0)
+ sym = &local_symbol_table[cur_isymBase + sym->index - 1];
+ }
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = cur_field = (struct field*)
+ obstack_alloc (symbol_obstack, nfields * sizeof (struct field));
+ for (sym = first_field; sym->st != stEnd; sym++)
+ if (sym->st == stMember)
+ {
+ AUXU *aux = &aux_symbol_table[iauxBase + sym->index];
+ char *name = &local_string_table[cur_issBase+sym->iss];
+ cur_field->name =
+ obstack_copy0 (symbol_obstack, name, strlen (name));
+
+ cur_field->type = read_type(sym->index, &cur_field->bitsize);
+ cur_field->bitpos = sym->value;
+ cur_field++;
+ }
+ else if (sym->st == stTypedef) ; /* just ignore it */
+ else if (sym->st == stBlock || sym->st == stBlockPatched)
+ {
+ if (sym->sc == scVariant) ; /* UNIMPLEMENTED */
+ if (sym->index != 0)
+ sym = &local_symbol_table[cur_isymBase + sym->index - 1];
+ }
+ else
+ fprintf(stderr, "[Bad member in struct/union field list]\n");
+ /*
+ * Heuristic: if 2nd field has offset 0, this is a union,
+ * otherwise, a struct definition.
+ * If nfields <= 1, we guess struct.
+ * If the type is used later, we fix it up.
+ * (This is done in the stBlockPatched case at the top of this
routine).
+ */
+ if (kind == btNil && nfields > 1)
+ {
+ if (TYPE_FIELDS(type)[1].bitpos > 0) kind = btStruct;
+ else kind = btUnion;
+ }
+ TYPE_CODE (type) = kind == btUnion ? TYPE_CODE_UNION :
TYPE_CODE_STRUCT;
+ TYPE_NAME (type) = concat ("",
+ (kind == btUnion ? "union " : "struct "),
+ sym_name);
+ }
+ return type;
+ }
+
+ static struct type *
+ read_struct_type(auxp, kind)
+ AUXU** auxp;
+ int kind; /* either btStruct or btUnion */
+ {
+ struct type *type;
+ int save_file_number = cur_file_number;
+ SYMR *sym = get_type_context(auxp);
+ if (sym == NULL) {
+ printf(stderr, "Bad symbol for struct/union definition");
+ return builtin_type_void;
+ }
+ if (sym->st == stTypedef)
+ type = read_type(sym->index, NULL);
+ else
+ type = get_struct_type(sym, kind);
+ select_file (save_file_number);
+ return type;
+ }
+
+ static struct type *
+ get_enum_type(sym)
+ SYMR *sym;
+ {
+ struct type *type;
+ if (sym->st == stBlockPatched)
+ type = (struct type*)sym->value;
+ else if (sym->st != stBlock)
+ {
+ fprintf(stderr,"Bad symbol table: enum points to
non-stBlock\n");
+ type = builtin_type_void;
+ }
+ else
+ {
+ int nfields = 0;
+ SYMR *first_field = sym+1;
+ register struct field *cur_field;
+ type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ bzero (type, sizeof (struct type));
+ TYPE_LENGTH (type) = sym->value;
+
+ /* we "remember" the type generated from this block */
+ sym->st = stBlockPatched;
+ sym->value = (long)type;
+
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_LENGTH (type) = sizeof (int);
+ TYPE_NAME (type) = concat ("", "enum ",
+ &local_string_table[cur_issBase+sym->iss]);
+
+ nfields = &local_symbol_table[cur_isymBase+sym->index] -
first_field - 1;
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = cur_field = (struct field*)
+ obstack_alloc (symbol_obstack, nfields * sizeof (struct field));
+ for (sym = first_field; sym->st != stEnd; sym++)
+ if (sym->st == stMember)
+ {
+ char *name = &local_string_table[cur_issBase+sym->iss];
+ cur_field->name =
+ obstack_copy0 (symbol_obstack, name, strlen (name));
+
+ cur_field->bitpos = sym->value;
+ cur_field->bitsize = 0;
+ cur_field++;
+ }
+ else
+ fprintf(stderr, "[Bad member in enum list]\n");
+ }
+ return type;
+ }
+
+ static struct type *
+ read_enum_type(auxp)
+ AUXU** auxp;
+ {
+ struct type *type;
+ int save_file_number = cur_file_number;
+ SYMR *sym = get_type_context(auxp);
+ if (sym == NULL) {
+ printf(stderr, "Bad symbol for enum definition");
+ return builtin_type_int;
+ }
+ if (sym->st == stTypedef)
+ type = read_type(sym->index, NULL);
+ else
+ type = get_enum_type (sym);
+ select_file (save_file_number);
+ return type;
+ }
+
+ static struct type *
+ read_range_type(auxp)
+ AUXU** auxp;
+ {
+ struct type *range_type;
+ int save_file_number = cur_file_number;
+ SYMR *sym = get_type_context(auxp);
+ /* sym (if non-NULL) may point at an stBlock/scInfo, but ignore it
*/
+ range_type = (struct type *) obstack_alloc (symbol_obstack,
+ sizeof (struct type));
+ TYPE_CODE (range_type) = TYPE_CODE_RANGE;
+ TYPE_TARGET_TYPE (range_type) = builtin_type_int;
+ TYPE_LENGTH (range_type) = sizeof (int);
+ TYPE_NFIELDS (range_type) = 2;
+ TYPE_FIELDS (range_type) =
+ (struct field *) obstack_alloc (symbol_obstack,
+ 2 * sizeof (struct field));
+ TYPE_FIELD_BITPOS (range_type, 0) = (*auxp)++->dnLow;
+ TYPE_FIELD_BITPOS (range_type, 1) = (*auxp)++->dnHigh;
+
+ select_file (save_file_number);
+ return range_type;
+ }
+
+ static struct type *
+ modify_type(type, qualifier, auxp)
+ struct type *type;
+ int qualifier;
+ AUXU** auxp;
+ {
+ switch (qualifier) {
+ case tqPtr: return lookup_pointer_type(type);
+ case tqNil: return type;
+ case tqArray:
+ {
+ struct type *range_type = read_range_type(auxp);
+ long lower = TYPE_FIELD_BITPOS (range_type, 0);
+ long upper = TYPE_FIELD_BITPOS (range_type, 1);
+ int elem_size = (*auxp)++->width; /* not used */
+ struct type *atype;
+
+ atype = (struct type *)
+ obstack_alloc (symbol_obstack, sizeof (struct type));
+ bzero (atype, sizeof (struct type));
+
+ TYPE_CODE (atype) = TYPE_CODE_ARRAY;
+ TYPE_TARGET_TYPE (atype) = type;
+ TYPE_LENGTH (atype) = (upper - lower + 1) * TYPE_LENGTH (type);
+ TYPE_NFIELDS (atype) = 1;
+ TYPE_FIELDS (atype) =
+ (struct field *) obstack_alloc (symbol_obstack,
+ sizeof (struct field));
+ TYPE_FIELD_TYPE (atype, 0) = range_type;
+ return atype;
+ }
+ case tqVol: return type;
+ case tqProc: return lookup_function_type(type);
+ default:
+ fprintf(stderr, "[Unimplemented type qualifier: %d]\n", qualifier);
+ return type;
+ }
+ }
+
+ static struct type *
+ apply_type_modifiers(type, tip, auxp)
+ struct type *type;
+ TIR *tip;
+ AUXU** auxp;
+ {
+ for (;;) {
+ if (tip->tq0 == tqNil) return type;
+ type = modify_type(type, tip->tq0, auxp);
+ if (tip->tq1 == tqNil) return type;
+ type = modify_type(type, tip->tq1, auxp);
+ if (tip->tq2 == tqNil) return type;
+ type = modify_type(type, tip->tq2, auxp);
+ if (tip->tq3 == tqNil) return type;
+ type = modify_type(type, tip->tq3, auxp);
+ if (tip->tq4 == tqNil) return type;
+ type = modify_type(type, tip->tq4, auxp);
+ if (tip->tq5 == tqNil) return type;
+ type = modify_type(type, tip->tq5, auxp);
+ if (!tip->continued) return type;
+ tip++;
+ }
+ }
+
+ static struct type *
+ read_type(index, widthp)
+ int index;
+ int *widthp; /* if non-NULL: set to (if bit field: width, else:
0) */
+ {
+ TIR *tip;
+ AUXU *aux;
+ struct type *base_type;
+ int width;
+ if (index == 0xfffff) return builtin_type_int; /* no type info */
+ /* if (index < 0 || index > ) ...; */
+
+ aux = &aux_symbol_table[cur_file_descriptor->iauxBase + index];
+ tip = &aux->ti;
+ for ( ; aux->ti.continued; aux++) ;
+ aux++; /* skip last TIR field */
+
+ /* sym.h claims that width comes after RNDX, but seems to be wrong
*/
+ width = tip->fBitfield ? (aux++)->width : 0;
+ if (widthp) *widthp = width;
+
+ switch (tip->bt) {
+ case btVoid:
+ case btNil: base_type = builtin_type_void; break;
+ case btAdr: base_type = lookup_pointer_type(builtin_type_void);
break;
+ case btChar: base_type = builtin_type_char; break;
+ case btUChar: base_type = builtin_type_unsigned_char; break;
+ case btShort: base_type = builtin_type_short; break;
+ case btUShort: base_type = builtin_type_unsigned_short; break;
+ case btInt: base_type = builtin_type_int; break;
+ case btUInt: base_type = builtin_type_unsigned_int; break;
+ case btLong: base_type = builtin_type_long; break;
+ case btULong: base_type = builtin_type_unsigned_long; break;
+ case btFloat: base_type = builtin_type_float; break;
+ case btDouble: base_type = builtin_type_double; break;
+ case btStruct: case btUnion:
+ base_type = read_struct_type(&aux, tip->bt); break;
+ case btEnum:
+ base_type = read_enum_type(&aux); break;
+ case btRange:
+ base_type = read_range_type(&aux); break;
+ case btTypedef:
+ case btSet: case btComplex: case btDComplex:
+ case btIndirect:
+ case btFixedDec: case btFloatDec: case btString:
+ case btBit: case btPicture:
+ default:
+ fprintf(stderr, "[Unimplemented kind of type: %d]\n", tip->bt);
+ base_type = builtin_type_void;
+ }
+ return apply_type_modifiers(base_type, tip, &aux);
+ }
+
+ static struct symbol *
+ alloc_symbol(name, value)
+ char *name;
+ int value;
+ {
+ register struct symbol *sym;
+ sym = (struct symbol *)obstack_alloc (symbol_obstack, sizeof(struct
symbol));
+ #ifdef NAMES_HAVE_UNDERSCORE
+ if (name[0] == '_') name++;
+ #endif
+
+ bzero (sym, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen
(name));
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_TYPE (sym) = builtin_type_void;
+
+ return sym;
+ }
+
+ static
+ read_symbol(csym, name)
+ SYMR *csym;
+ char *name;
+ {
+ register struct symbol *sym = alloc_symbol(name, csym->value);
+
+ switch (csym->st)
+ {
+ case stNil: break;
+ case stFile:
+ last_source_file = obstack_copy0 (symbol_obstack, name, strlen
(name));
+ break;
+ case stGlobal:
+ SYMBOL_TYPE (sym) = read_type(csym->index, NULL);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+ case stStatic:
+ SYMBOL_TYPE (sym) = read_type(csym->index, NULL);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ if (within_function) {
+ /* Static symbol of local scope */
+ add_symbol_to_list (sym, &local_symbols);
+ }
+ else {
+ /* Static symbol at top level of file */
+ add_symbol_to_list (sym, &file_symbols);
+ }
+ break;
+
+ case stLocal:
+ SYMBOL_TYPE (sym) = read_type(csym->index, NULL);
+ switch (csym->sc) {
+ case scRegister: SYMBOL_CLASS (sym) = LOC_REGISTER; break;
+ case scAbs: SYMBOL_CLASS (sym) = LOC_LOCAL; break;
+
+ }
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case stParam:
+ SYMBOL_TYPE (sym) = read_type(csym->index, NULL);
+ switch (csym->sc) {
+ case scAbs: SYMBOL_CLASS (sym) = LOC_ARG; break;
+ case scRegister: SYMBOL_CLASS (sym) = LOC_REGPARM; break;
+ case scVar: SYMBOL_CLASS (sym) = LOC_REF_ARG; break;
+ case scVarRegister: SYMBOL_CLASS (sym) = LOC_REGPARM; break;
/*WRONG!*/
+ }
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case stTypedef:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_TYPE (sym) = read_type(csym->index, NULL);
+ if (within_function) {
+ /* Static symbol of local scope */
+ add_symbol_to_list (sym, &local_symbols);
+ }
+ else {
+ /* Static symbol at top level of file */
+ add_symbol_to_list (sym, &file_symbols);
+ }
+ break;
+
+ case stEnd:
+ default: break;
+ }
+ return 1;
+ }
+
+ static int
+ read_tagged_block (index)
+ {
+ SYMR *csym = &local_symbol_table[cur_isymBase+index];
+ char *name = &local_string_table[cur_issBase+csym->iss];
+ struct pending **symlist = within_function ? &local_symbols:
&file_symbols;
+ register struct symbol *sym;
+
+ /* A kludge to decide if this is an enum definition. */
+ if ((csym[1].st == stMember
+ && read_type(csym[1].index, 0) == builtin_type_void)
+ || (csym->st == stBlockPatched
+ && TYPE_CODE((struct type*)(csym->value)) == TYPE_CODE_ENUM))
+ {
+ struct type *type = get_enum_type (csym);
+ if (type && TYPE_CODE(type) == TYPE_CODE_ENUM)
+ {
+ int nfields = TYPE_NFIELDS (type);
+ register int i;
+ register struct field *cur_field = TYPE_FIELDS(type);
+ if (name && name[0] && name[0] != '.')
+ {
+ sym = alloc_symbol(name, 0);
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ add_symbol_to_list (sym, symlist);
+ }
+ for (i = nfields; --i >= 0; cur_field++)
+ {
+ sym = alloc_symbol(cur_field->name, cur_field->bitpos);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = type;
+ add_symbol_to_list (sym, symlist);
+ }
+ return nfields + 2;
+ }
+ }
+ else
+ {
+ if (name && name[0] && name[0] != '.')
+ {
+ struct type *type = get_struct_type (csym, btNil);
+ sym = alloc_symbol(name, 0);
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ add_symbol_to_list (sym, symlist);
+ }
+ return read_symbols (index + 1) + 2;
+ }
+ }
+
+ /* Read symbols until an stEnd symbol is encountered. Return count.
*/
+
+ static int
+ read_symbols(index)
+ int index; /* relative to current file */
+ {
+ register struct context_stack *new;
+ static int blocks_seen = 0;
+ int index0 = index;
+ SYMR *start_symbol;
+ for (;;)
+ {
+ SYMR *csym = &local_symbol_table[cur_isymBase+index];
+ char *name = &local_string_table[cur_issBase+csym->iss];
+
+ if (dump_stuff)
+ printf("[%s,%x,st%s,sc%s,inx:%d (%x)]\n", name, csym->value,
+ MapStNames[csym->st], MapScNames[csym->sc],
+ csym->index, csym);
+
+ switch (csym->st)
+ {
+ case stFile:
+ last_source_file =
+ obstack_copy0 (symbol_obstack, name, strlen (name));
+ index++;
+ index += read_symbols(index) + 1;
+ return index - index0;
+ case stBlock:
+ case stBlockPatched:
+ if (csym->sc == scText)
+ { /* lexical block */
+ if (!local_symbol_table[cur_isymBase+csym->index-1].value)
+ {
+ new = 0;
+ }
+ else
+ {
+ new = (struct context_stack *)
+ xmalloc (sizeof (struct context_stack));
+ new->next = context_stack;
+ context_stack = new;
+ new->locals = local_symbols;
+ new->old_blocks = pending_blocks;
+ new->start_addr = cur_proc_addr + csym->value;
+ new->name = 0;
+ local_symbols = 0;
+ }
+ blocks_seen++;
+ start_symbol=csym;
+ index++;
+ index += read_symbols (index);
+ csym = &local_symbol_table[cur_isymBase+index]; /* stEnd */
+ index++;
+
+ if (csym->st != stEnd ||
+ start_symbol != &local_symbol_table[cur_isymBase+csym->index])
+ abort();
+ if (new)
+ {
+ if (local_symbols && context_stack->next)
+ {
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr,
+ cur_proc_addr + csym->value);
+ }
+ local_symbols = new->locals;
+ context_stack = new->next;
+ free (new);
+ }
+ }
+ else if (csym->sc == scInfo)
+ index += read_tagged_block (index);
+ break;
+ case stProc:
+ case stStaticProc:
+ {
+ PDR *proc = &proc_desc_table
+ [cur_file_descriptor->ipdFirst+cur_proc_number++];
+ CORE_ADDR saved_cur_proc_addr = cur_proc_addr;
+ struct symbol *sym = alloc_symbol(name, csym->value);
+ struct context_stack *saved_context_stack = context_stack;
+ int save_blocks_seen = blocks_seen;
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ /* Add one to csym->index, to the skip the isymMac value
+ * (which is there only for st*Proc). */
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type(csym->index+1, NULL));
+ if (csym->st == stStaticProc)
+ add_symbol_to_list (sym, &file_symbols);
+ else
+ add_symbol_to_list (sym, &global_symbols);
+ cur_proc_addr = csym->value;
+ within_function++;
+ new = (struct context_stack *)
+ xmalloc (sizeof (struct context_stack));
+ new->next = 0;
+ context_stack = new;
+ new->locals = 0;
+ new->old_blocks = pending_blocks;
+ new->start_addr = csym->value;
+ new->name = sym;
+ if (dump_stuff)
+
printf("[PROC:%s,@%x,framereg:%d,froff:%d,rmsk:%d,fmsk:%d,floff:%d,regof
ff:%d,iline:%d,lnLo:%d,lnHi:%d (%x)]\n",
+ name, proc->adr,
+ proc->framereg, proc->frameoffset, proc->regmask,
+ proc->fregmask, proc->fregoffset,
+ proc->regoffset,
+ proc->iline,proc->lnLow,proc->lnHigh, proc);
+
+ start_symbol = csym;
+ index++;
+ index += read_symbols(index);
+
+ csym = &local_symbol_table[cur_isymBase+index];/*stEnd symbol*/
+
+ if (csym->st != stEnd ||
+ start_symbol != &local_symbol_table[cur_isymBase+csym->index])
+ abort();
+
+ index++;
+ PROC_SYMBOL(proc) =
+ blocks_seen == save_blocks_seen ? NULL : sym;
+ PROC_LOW_ADDR(proc) = start_symbol->value;
+ PROC_HIGH_ADDR(proc) = last_end_addr =
+ start_symbol->value + csym->value;
+
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ start_symbol->value, last_end_addr);
+ context_stack = saved_context_stack;
+ cur_proc_addr = saved_cur_proc_addr;
+ within_function--;
+ free (new);
+ break;
+ }
+
+ case stEnd:
+ #if 1
+ return index - index0;
+ #else
+ start_symbol = &local_symbol_table[cur_isymBase+csym->index];
+ switch (start_symbol->st)
+ {
+ case stProc:
+ case stStaticProc:
+ case stFile:
+ case stBlock:
+ case stBlockPatched:
+ return index - index0;
+ default:
+ index++;
+ }
+ break;
+ #endif
+ default:
+ read_symbol(csym, name);
+ index++;
+ }
+ }
+ }
+
+ static int
+ read_coff_symtab (desc, nsyms, symtab_offset)
+ int desc;
+ int nsyms;
+ int symtab_offset;
+ {
+ HDRR hdrr;
+ struct coff_symbol coff_symbol;
+ register struct coff_symbol *cs = &coff_symbol;
+ struct coff_symbol fcn_cs_saved;
+
+ int num_object_files = 0;
+ int next_file_symnum = -1;
+ char *filestring;
+ int fcn_first_line;
+ int fcn_last_line;
+ int fcn_start_addr;
+ long fcn_line_ptr;
+ struct cleanup *file_chain, *ext_chain, *old_chain;
+ int isym, ifile;
+
+ char *line_number_table;
+ EXTR *external_symbol_table;
+ char *external_string_table;
+ struct linetable **line_vector_all;
+
+ if (myread (desc, (char *)&hdrr, sizeof hdrr) != sizeof hdrr)
+ return -1;
+
+ file_descriptor_count = hdrr.ifdMax;
+ line_vector_all = (struct linetable**)
+ alloca (file_descriptor_count * sizeof(struct linetable *));
+ global_symbols_all = (struct pending**)
+ alloca (file_descriptor_count * sizeof(struct pending *));
+ file_symbols_all = (struct pending**)
+ alloca (file_descriptor_count * sizeof(struct pending *));
+ proc_desc_length = hdrr.ipdMax;
+ proc_desc_table = (PDR*)
+ read_table(desc, hdrr.ipdMax * sizeof(PDR), hdrr.cbPdOffset);
+ old_chain = make_cleanup (free_all_symtabs, 0);
+ make_cleanup (free_proc_descs, 0);
+ file_descriptor_table = (FDR*)
+ read_table(desc, hdrr.ifdMax * sizeof(FDR), hdrr.cbFdOffset);
+ file_chain = make_cleanup (free, file_descriptor_table);
+
+ line_number_table = read_table(desc, hdrr.cbLine,
hdrr.cbLineOffset);
+ ext_chain = make_cleanup (free, line_number_table);
+
+ for (ifile = 0; ifile < hdrr.ifdMax; ifile++)
+ {
+ int iproc, ipdMax;
+ char *cur_line_entry;
+ int cur_addr_offset = 0;
+ int cur_addr;
+
+ /* Vector of line number information. */
+ struct linetable *line_vector;
+
+ /* Index of next entry to go in line_vector_index. */
+ int line_vector_index;
+
+ /* Number of elements allocated for line_vector currently. */
+ int line_vector_length;
+
+ select_file (ifile);
+ global_symbols_all[ifile] = 0;
+ file_symbols_all[ifile] = 0;
+
+ /* read line numbers */
+ cur_addr = cur_file_descriptor->adr;
+ iproc = cur_file_descriptor->ipdFirst;
+
+ line_vector_index = 0;
+ line_vector_length = 1000;
+ line_vector = (struct linetable *)
+ xmalloc (sizeof (struct linetable)
+ + line_vector_length * sizeof (struct linetable_entry));
+
+ /* we read the line numbers first, since read_symbol
over-writes
+ some of the fields in a proc descriptor */
+ ipdMax = iproc + cur_file_descriptor->cpd;
+ cur_line_entry = line_number_table +
cur_file_descriptor->cbLineOffset;
+ for ( ; iproc < ipdMax; iproc++) {
+ PDR *proc = &proc_desc_table[iproc];
+ int nlines = (iproc+1 < ipdMax ? (proc+1)->iline :
cur_file_descriptor->cline)
+ - proc->iline;
+ int cur_source_line = proc->lnLow;
+ if (dump_stuff)
+ printf(
+
"[proc:%x,framereg:%d,ofset:%d,rmask:%d,flmask:%d,floff:%d,iline:%d,lnLo
o:%d,lnHi:%d,csl:%d]\n",
+ proc->adr,
+ proc->framereg, proc->frameoffset, proc->regmask,
+ proc->fregmask, proc->fregoffset,
+ proc->iline,proc->lnLow,proc->lnHigh, cur_source_line);
+ if (proc->iline == -1) continue;
+ for (isym = proc->iline; nlines > 0; isym++) {
+ struct linetable_entry *e;
+ int code = *cur_line_entry++;
+ int delta = code >> 4;
+ int count = (code & 15) + 1;
+ if (dump_stuff & 1) printf("%2x", 0xFF & code);
+ if (delta == -8)
+ {
+ if (dump_stuff & 1)
+ printf(" %2x%2x", 0xff & cur_line_entry[0],
+ 0xff & cur_line_entry[1]);
+ delta = *cur_line_entry++;
+ delta = (delta << 8) | (unsigned)*cur_line_entry++;
+ isym += 2;
+ }
+ cur_source_line += delta;
+ if (dump_stuff & 1)
+ printf("\t%2d.%2d li:%d %X", delta, count,
+ cur_source_line,
+ cur_file_descriptor->adr + 4 * cur_addr_offset);
+
+ e = &line_vector->item[line_vector_index];
+ if (line_vector_index == 0 || e[-1].line != cur_source_line)
+ {
+
+ /* Make sure line vector is big enough. */
+ if (line_vector_index + 2 >= line_vector_length)
+ {
+ line_vector_length *= 2;
+ line_vector = (struct linetable *)
+ xrealloc (line_vector, sizeof (struct linetable)
+ + (line_vector_length
+ * sizeof (struct linetable_entry)));
+ e = &line_vector->item[line_vector_index];
+ }
+
+ e->line = cur_source_line;
+ e->pc = cur_file_descriptor->adr + 4 * cur_addr_offset;
+ line_vector_index++;
+ }
+
+ if (delta != 0)
+ {
+ int save_addr = cur_addr;
+ if (cur_addr_offset != 0)
+ {
+ int toffset = (cur_addr_offset - 1) * 4;
+ if (dump_stuff & 1)
+ printf(" [li: %d %x-%x]",
+ cur_source_line, cur_addr, cur_addr+toffset);
+ }
+ cur_addr = save_addr + cur_addr_offset * 4;
+ }
+ cur_addr_offset += count;
+ nlines -= count;
+ if (dump_stuff & 1) putchar('\n');
+ /* if (delta != 0) { } */
+ }
+ }
+
+ line_vector->nitems = line_vector_index;
+ line_vector_all[ifile] = (struct linetable *)
+ xrealloc (line_vector, (sizeof (struct linetable)
+ + line_vector_index * sizeof (struct linetable_entry)));
+ }
+ do_cleanups (ext_chain);
+
+ aux_symbol_table = (AUXU*)
+ read_table(desc, hdrr.iauxMax * sizeof(AUXU), hdrr.cbAuxOffset);
+ make_cleanup (free, aux_symbol_table);
+ rel_file_table = (RFDT*)
+ read_table(desc, hdrr.crfd * sizeof(RFDT), hdrr.cbRfdOffset);
+ make_cleanup (free, rel_file_table);
+ local_symbol_table = (SYMR*)
+ read_table(desc, hdrr.isymMax * sizeof(SYMR), hdrr.cbSymOffset);
+ make_cleanup (free, local_symbol_table);
+ local_string_table = read_table(desc, hdrr.issMax,
hdrr.cbSsOffset);
+ make_cleanup (free, local_string_table);
+
+ external_symbol_table = (EXTR*)
+ read_table(desc, hdrr.iextMax * sizeof(EXTR), hdrr.cbExtOffset);
+ ext_chain = make_cleanup (free, external_symbol_table);
+ external_string_table = read_table(desc, hdrr.issExtMax,
hdrr.cbSsExtOffset);
+ make_cleanup (free, external_string_table);
+
+ /* do the external symbols first */
+ /* The reason is that each file's end_symtab is done with the locals
*/
+
+ for (isym = 0; isym < hdrr.iextMax; isym++)
+ {
+ EXTR *ext = &external_symbol_table[isym];
+ SYMR *csym = &ext->asym;
+ char *name = external_string_table+csym->iss;
+ if ((unsigned)ext->ifd >= hdrr.ifdMax) return -1;
+ select_file (ext->ifd);
+ record_misc_function (name, csym->value);
+ if (csym->st != stProc && csym->st != stStaticProc)
+ read_symbol(csym, name);
+ #if 1
+ if (dump_stuff)
+ printf("EXT[%s,%x,st%s,sc%s,inx:%d,ifd:%d]\n",
+ name, csym->value, MapStNames[csym->st],
+ MapScNames[csym->sc], csym->index, ext->ifd);
+ #endif
+ }
+
+ do_cleanups (ext_chain);
+
+ for (ifile = 0; ifile < hdrr.ifdMax; ifile++)
+ {
+ select_file (ifile);
+
+ cur_proc_number = 0;
+ last_end_addr = cur_file_descriptor->adr;
+
+ start_symtab ();
+
+ if (dump_stuff)
+
printf("<FILE.adr:%x,ilB:%d,cb:%d,cbLO:%d,cbL:%d,iSB:%d,cS:%d,nProcs:%d,
,first:%d>\n",
+ cur_file_descriptor->adr,
+ cur_file_descriptor->ilineBase, cur_file_descriptor->cline,
+ cur_file_descriptor->cbLineOffset,
cur_file_descriptor->cbLine,
+ cur_isymBase, cur_file_descriptor->csym,
+ cur_file_descriptor->cpd,
+ cur_file_descriptor->ipdFirst);
+
+ for (isym = 0; isym < cur_file_descriptor->csym; )
+ {
+ int count = read_symbols(isym);
+ if (count == 0)
+ { /* handle un-handled stEnd */
+ SYMR *sym = &local_symbol_table[cur_isymBase+isym];
+ char *name = &local_string_table[cur_issBase+sym->iss];
+ printf("stEnd confusion!");
+ read_symbol(sym, name);
+ count = 1;
+ }
+ isym += count;
+ }
+ end_symtab (cur_file_descriptor->adr, last_end_addr,
+ line_vector_all[ifile]);
+ }
+
+ do_cleanups (file_chain);
+
+ last_source_file = 0;
+ bzero (opaque_type_chain, sizeof opaque_type_chain);
+
+ type_vector_length = 160;
+ type_vector = (struct typevector *)
+ xmalloc (sizeof (struct typevector)
+ + type_vector_length * sizeof (struct type *));
+ bzero (type_vector->type, type_vector_length * sizeof (struct type
*));
+
+ if (last_source_file)
+ end_symtab ();
+ discard_cleanups (old_chain);
+ return 0;
+ }
+
+ /* Routines for reading headers and symbols from executable. */
+
+ /* Read COFF file header, check magic number,
+ and return number of symbols. */
+ read_file_hdr (chan, file_hdr)
+ int chan;
+ FILHDR *file_hdr;
+ {
+ lseek (chan, 0L, 0);
+ if (myread (chan, (char *)file_hdr, FILHSZ) < 0)
+ return -1;
+
+ switch (file_hdr->f_magic)
+ {
+ #ifdef MIPSEBMAGIC
+ case MIPSEBMAGIC:
+ #endif
+ #ifdef MIPSELMAGIC
+ case MIPSELMAGIC:
+ #endif
+ #ifdef MC68MAGIC
+ case MC68MAGIC:
+ #endif
+ #ifdef NS32GMAGIC
+ case NS32GMAGIC:
+ case NS32SMAGIC:
+ #endif
+ #ifdef I386MAGIC
+ case I386MAGIC:
+ #endif
+ #ifdef CLIPPERMAGIC
+ case CLIPPERMAGIC:
+ #endif
+ return file_hdr->f_nsyms;
+
+ default:
+ #ifdef BADMAG
+ if (BADMAG(file_hdr))
+ return -1;
+ else
+ return file_hdr->f_nsyms;
+ #else
+ return -1;
+ #endif
+ }
+ }
+
+ read_aout_hdr (chan, aout_hdr, size)
+ int chan;
+ AOUTHDR *aout_hdr;
+ int size;
+ {
+ lseek (chan, (long)FILHSZ, 0);
+ if (size != sizeof (AOUTHDR))
+ return -1;
+ if (myread (chan, (char *)aout_hdr, size) != size)
+ return -1;
+ return 0;
+ }
+
+ read_section_hdr (chan, section_name, section_hdr, nsects)
+ register int chan;
+ register char *section_name;
+ SCNHDR *section_hdr;
+ register int nsects;
+ {
+ register int i;
+
+ if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0)
+ return -1;
+
+ for (i = 0; i < nsects; i++)
+ {
+ if (myread (chan, (char *)section_hdr, SCNHSZ) < 0)
+ return -1;
+ if (strncmp (section_hdr->s_name, section_name, 8) == 0)
+ return 0;
+ }
+ return -1;
+ }
+
+
+ /* Support for string table handling */
+
+ static char *stringtab = NULL;
+
+
+ #if 0
+ static char *
+ getsymname (symbol_entry)
+ SYMENT *symbol_entry;
+ {
+ static char buffer[SYMNMLEN+1];
+ char *result;
+
+ if (symbol_entry->n_zeroes == 0)
+ {
+ result = stringtab + symbol_entry->n_offset;
+ }
+ else
+ {
+ strncpy (buffer, symbol_entry->n_name, SYMNMLEN);
+ buffer[SYMNMLEN] = '\0';
+ result = buffer;
+ }
+ return result;
+ }
+ #endif
+
+ /* Support for line number handling */
+ static char *linetab = NULL;
+ static long linetab_offset;
+ static int linetab_count;
+
+ static int
+ hashname (name)
+ char *name;
+ {
+ register char *p = name;
+ register int total = p[0];
+ register int c;
+
+ c = p[1];
+ total += c << 2;
+ if (c)
+ {
+ c = p[2];
+ total += c << 4;
+ if (c)
+ total += p[3] << 6;
+ }
+
+ return total % HASHSIZE;
+ }
+
+ static void
+ patch_type (type, real_type)
+ struct type *type;
+ struct type *real_type;
+ {
+ register struct type *target = TYPE_TARGET_TYPE (type);
+ register struct type *real_target = TYPE_TARGET_TYPE (real_type);
+ int field_size = TYPE_NFIELDS (real_target) * sizeof (struct
field);
+
+ TYPE_LENGTH (target) = TYPE_LENGTH (real_target);
+ TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target);
+ TYPE_FIELDS (target) = (struct field *)
+ obstack_alloc (symbol_obstack, field_size);
+
+ bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target),
field_size);
+
+ if (TYPE_NAME (real_target))
+ {
+ if (TYPE_NAME (target))
+ free (TYPE_NAME (target));
+ TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", "");
+ }
+ }
+
+ /* Patch up all appropriate typdef symbols in the opaque_type_chains
+ so that they can be used to print out opaque data structures
properly */
+
+ static void
+ patch_opaque_types ()
+ {
+ struct symtab *s;
+
+ /* Look at each symbol in the per-file block of each symtab. */
+ for (s = symtab_list; s; s = s->next)
+ {
+ register struct block *b;
+ register int i;
+
+ /* Go through the per-file symbols only */
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1);
+ for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+ {
+ register struct symbol *real_sym;
+
+ /* Find completed typedefs to use to fix opaque ones.
+ Remove syms from the chain when their types are stored,
+ but search the whole chain, as there may be several syms
+ from different files with the same name. */
+ real_sym = BLOCK_SYM (b, i);
+ if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF &&
+ SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE &&
+ TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR &&
+ TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0)
+ {
+ register char *name = SYMBOL_NAME (real_sym);
+ register int hash = hashname (name);
+ register struct symbol *sym, *prev;
+
+ prev = 0;
+ for (sym = opaque_type_chain[hash]; sym;)
+ {
+ if (name[0] == SYMBOL_NAME (sym)[0] &&
+ !strcmp (name + 1, SYMBOL_NAME (sym) + 1))
+ {
+ if (prev)
+ SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
+ else
+ opaque_type_chain[hash]
+ = (struct symbol *) SYMBOL_VALUE (sym);
+
+ patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym));
+
+ if (prev)
+ sym = (struct symbol *) SYMBOL_VALUE (prev);
+ else
+ sym = opaque_type_chain[hash];
+ }
+ else
+ {
+ prev = sym;
+ sym = (struct symbol *) SYMBOL_VALUE (sym);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* This function is really horrible, but to avoid it, there would
need
+ to be more filling in of forward references. THIS SHOULD BE MOVED
+ OUT OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE
SHARED. */
+ int
+ fill_in_vptr_fieldno (type)
+ struct type *type;
+ {
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ TYPE_VPTR_FIELDNO (type) =
+ fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1));
+ return TYPE_VPTR_FIELDNO (type);
+ }
+
+ /* partial symbol tables are not implemented in coff, therefore
+ block_for_pc() (and others) will never decide to call this. */
+
+ extern struct symtab *
+ psymtab_to_symtab ()
+ {
+ fatal ("error: Someone called psymtab_to_symtab\n");
+ }
+
+ /* These will stay zero all the time */
+ struct psymbol_allocation_list global_psymbols, static_psymbols;
*** munch.orig Wed Jul 5 15:46:28 1989
--- munch Mon Nov 5 10:28:33 1990
***************
*** 8,17 ****
if test "$1" = "-DSYSV" ; then
shift;
nm $* | egrep '^(.*[^a-zA-Z_]_|_)initialize_' | \
sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/ \1
();/'
else
! nm -p $* | egrep 'T *__initialize_' | \
sed -e 's/^.*T *_*\(.*\)/ _\1 ();/'
fi
echo '}'
--- 8,17 ----
if test "$1" = "-DSYSV" ; then
shift;
nm $* | egrep '^(.*[^a-zA-Z_]_|_)initialize_' | \
sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/ \1
();/'
else
! nm -p $* | egrep 'T *_?_initialize_' | \
sed -e 's/^.*T *_*\(.*\)/ _\1 ();/'
fi
echo '}'
*** valops.c.orig Thu Dec 28 16:28:29 1989
--- valops.c Mon Nov 5 10:28:34 1990
***************
*** 653,662 ****
--- 653,665 ----
struct_addr = sp;
sp += TYPE_LENGTH (value_type);
#endif
}
+ #ifdef PUSH_ARGUMENTS
+ PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+ #else /* !PUSH_ARGUMENTS */
for (i = nargs - 1; i >= 0; i--)
sp = value_arg_push (sp, args[i]);
#ifdef CALL_DUMMY_STACK_ADJUST
#if 1 INNER_THAN 2
***************
*** 675,684 ****
--- 678,688 ----
Also note that on some machines (like the sparc) pcc uses this
convention in a slightly twisted way also. */
if (struct_return)
STORE_STRUCT_RETURN (struct_addr, sp);
+ #endif /* !PUSH_ARGUMENTS */
/* Write the stack pointer. This is here because the statement
above
might fool with it */
write_register (SP_REGNUM, sp);
*** valprint.c.orig Thu Feb 1 17:48:29 1990
--- valprint.c Mon Nov 5 10:28:35 1990
***************
*** 530,541 ****
}
else
string[i++] = c;
}
! if (i != 0)
! print_string (stream, string, i, force_ellipses);
if (out_of_bounds)
fprintf_filtered (stream,
" <Address 0x%x out of bounds>",
(*(int *) valaddr) + i);
}
--- 530,540 ----
}
else
string[i++] = c;
}
! print_string (stream, string, i, force_ellipses);
if (out_of_bounds)
fprintf_filtered (stream,
" <Address 0x%x out of bounds>",
(*(int *) valaddr) + i);
}
More information about the Comp.unix.ultrix
mailing list