diff options
Diffstat (limited to 'gdb/RCS')
-rw-r--r-- | gdb/RCS/Makefile,v | 367 | ||||
-rw-r--r-- | gdb/RCS/blockframe.c,v | 606 | ||||
-rw-r--r-- | gdb/RCS/coffread.c,v | 2047 | ||||
-rwxr-xr-x | gdb/RCS/config.gdb,v | 229 | ||||
-rw-r--r-- | gdb/RCS/core.c,v | 651 | ||||
-rw-r--r-- | gdb/RCS/dbxread.c,v | 4610 | ||||
-rw-r--r-- | gdb/RCS/default-dep.c,v | 731 | ||||
-rw-r--r-- | gdb/RCS/findvar.c,v | 584 | ||||
-rw-r--r-- | gdb/RCS/gdb.texinfo,v | 3009 | ||||
-rw-r--r-- | gdb/RCS/gdbcore.h,v | 105 | ||||
-rw-r--r-- | gdb/RCS/inflow.c,v | 636 | ||||
-rw-r--r-- | gdb/RCS/infrun.c,v | 1855 | ||||
-rw-r--r-- | gdb/RCS/m-aux.h,v | 591 | ||||
-rw-r--r-- | gdb/RCS/m-hp9k320.h,v | 607 | ||||
-rw-r--r-- | gdb/RCS/m-sparc.h,v | 747 | ||||
-rw-r--r-- | gdb/RCS/m68k-pinsn.c,v | 824 | ||||
-rw-r--r-- | gdb/RCS/main.c,v | 1348 | ||||
-rwxr-xr-x | gdb/RCS/munch,v | 75 | ||||
-rw-r--r-- | gdb/RCS/printcmd.c,v | 1707 | ||||
-rw-r--r-- | gdb/RCS/remote.c,v | 662 | ||||
-rw-r--r-- | gdb/RCS/source.c,v | 990 | ||||
-rw-r--r-- | gdb/RCS/sparc-dep.c,v | 1091 | ||||
-rw-r--r-- | gdb/RCS/stack.c,v | 882 | ||||
-rw-r--r-- | gdb/RCS/utils.c,v | 726 | ||||
-rw-r--r-- | gdb/RCS/valprint.c,v | 1117 | ||||
-rw-r--r-- | gdb/RCS/values.c,v | 1047 |
26 files changed, 0 insertions, 27844 deletions
diff --git a/gdb/RCS/Makefile,v b/gdb/RCS/Makefile,v deleted file mode 100644 index fd71c1c..0000000 --- a/gdb/RCS/Makefile,v +++ /dev/null @@ -1,367 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.4 -date 89.03.27.21.28.33; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.18.33.31; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.13.19.02.58; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.03.15.53; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@More general support for ALLOCA and other local library routines; -other minor cleanup. -@ -text -@# On HPUX, you need to add -Ihp-include to CFLAGS. -# The headers in the directory hp-include override system headers -# and tell GDB to use BSD executable file format. -# You must also define REGEX & REGEX1 below and ALLOCA & ALLOCA1 (get -# alloca.c from the emacs distribution) to the CLIBS. -# If you compile GDB with GCC on HPUX, you must make sure that the "nm" used -# in "munch" is GNU's nm. This is because gcc uses a different .o -# file format than the native HPUX compiler. - -# On USG (System V) machines, you must make sure to setup REGEX & -# REGEX1 to point at regex.o and use the USG version of CLIBS. -# If your system has a broken alloca() -- most do -- then get -# alloca.c from the GNU Emacs distribution and set ALLOCA & ALLOCA1. -# Also, if you compile gdb with a compiler which uses the coff -# encapsulation feature (this is a function of the compiler used, NOT -# of the m-?.h file selected by config.gdb), you must make sure that -# the GNU nm is the one that is used by munch. - -# On Sunos 4.0 machines, make sure to compile *without* shared -# libraries if you want to run gdb on itself. Make sure to compile -# any program on which you want to run gdb without shared libraries. - -# If you are compiling with GCC, make sure that either 1) You use the -# -traditional flag, or 2) You have the fixed include files where GCC -# can reach them. Otherwise the ioctl calls in inflow.c will be -# incorrectly compiled. The "fixincludes" script in the gcc -# distribution will probably fix your include files up. - -CC=cc -SHELL=/bin/sh - -# Set this up with gcc if you have gnu ld and the loader will print out -# line numbers for undefinded refs. -CC-LD=${CC} - -# -I. for "#include <obstack.h>". Possibly regex.h also. -#CFLAGS = -g -pg -I. -O -CFLAGS = -I. -g -#LDFLAGS = -pg -g -LDFLAGS = -g - -# define this to be "obstack.o" if you don't have the obstack library installed -# you must at the same time define OBSTACK1 as "obstack.o" -# so that the dependencies work right. Similarly with REGEX and "regex.o". -# You must define REGEX and REGEX1 on USG machines. -# If your system is missing alloca(), or, more likely, it's there but it -# doesn't work, define ALLOCA and ALLOCA1. -OBSTACK = obstack.o -OBSTACK1 = obstack.o -REGEX = regex.o -REGEX1 = regex.o -ALLOCA = alloca.o -ALLOCA1 = alloca.o -ADD_FILES = $(OBSTACK) $(REGEX) $(ALLOCA) $(GNU_MALLOC) -ADD_DEPS = $(OBSTACK1) $(REGEX1) $(ALLOCA1) $(GNU_MALLOC) - -# -# define this to be "malloc.o" if you want to use the gnu malloc routine -# (useful for debugging memory allocation problems in gdb). Otherwise, leave -# it blank. -GNU_MALLOC = -#GNU_MALLOC = malloc.o - -# Flags to be used in compiling malloc.o -# Specify range checking for storage allocation. -MALLOC_FLAGS = -#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS - -# for BSD -CLIBS = $(ADD_FILES) -# for USG -#CLIBS= $(ADD_FILES) -lPW - -SFILES = blockframe.c breakpoint.c coffread.c command.c core.c dbxread.c \ - environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \ - kdb-start.c main.c printcmd.c \ - remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \ - utils.c valarith.c valops.c valprint.c values.c version.c expread.y \ - xgdb.c - -DEPFILES = convex-dep.c umax-dep.c gould-dep.c default-dep.c sun3-dep.c \ - sparc-dep.c hp9k320-dep.c news-dep.c i386-dep.c - -PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \ - ns32k-pinsn.c - -HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \ - inferior.h symseg.h symtab.h value.h wait.h \ - a.out.encap.h a.out.gnu.h stab.gnu.h - -OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \ - ns32k-opcode.h - -MFILES = m-hp9k320.h m-i386.h m-i386gas.h m-isi.h m-merlin.h m-news.h \ - m-npl.h m-pn.h m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \ - m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h - -POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c - -TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c - -OTHERS = Makefile createtags munch config.gdb ChangeLog README TAGS \ - gdb.texinfo .gdbinit COPYING expread.tab.c stab.def hp-include - -TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \ - ${POSSLIBS} -TARFILES = ${TAGFILES} ${OTHERS} - -OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \ - values.o eval.o valops.o valarith.o valprint.o printcmd.o \ - symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \ - command.o utils.o expread.o expprint.o pinsn.o environ.o version.o - -TSOBS = core.o inflow.o dep.o - -NTSOBS = standalone.o - -TSSTART = /lib/crt0.o - -NTSSTART = kdb-start.o - -gdb : $(OBS) $(TSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) > init.c - ${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) $(CLIBS) - -xgdb : $(OBS) $(TSOBS) xgdb.o $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(TSOBS) xgdb.o > init.c - $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \ - -lXaw -lXt -lX11 $(CLIBS) - -kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS) - -rm -f init.c - ./munch $(OBS) $(NTSOBS) > init.c - $(CC-LD) $(LDFLAGS) -c init.c $(CLIBS) - ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o -lc $(CLIBS) - -# If it can figure out the appropriate order, createtags will make sure -# that the proper m-*, *-dep, *-pinsn, and *-opcode files come first -# in the tags list. It will attempt to do the same for dbxread.c and -# coffread.c. This makes using M-. on machine dependent routines much -# easier. -# -TAGS: ${TAGFILES} - createtags ${TAGFILES} -tags: TAGS - -gdb.tar: ${TARFILES} - rm -f gdb.tar - mkdir dist-gdb - cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done - tar chf gdb.tar dist-gdb - rm -rf dist-gdb - -gdb.tar.Z: gdb.tar - compress gdb.tar - -clean: - -rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} - -rm -f init.c init.o - -rm -f gdb - -realclean: clean - -rm -f expread.tab.c tags TAGS - -xgdb.o : xgdb.c defs.h param.h symtab.h frame.h - $(CC) -c $(CFLAGS) xgdb.c -o $@@ - -expread.tab.c : expread.y - @@echo 'Expect 101 shift/reduce conflicts and 1 reduce/reduce conflict.' - yacc expread.y - mv y.tab.c expread.tab.c - -expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h - $(CC) -c ${CFLAGS} expread.tab.c - mv expread.tab.o expread.o - -# -# Only useful if you are using the gnu malloc routines. -# -malloc.o : malloc.c - ${CC} -c ${MALLOC_FLAGS} malloc.c - -# -# dep.o depends on ALL the dep files since we don't know which one -# is really being used. -# -dep.o : ${DEPFILES} defs.h param.h frame.h inferior.h obstack.h \ - a.out.encap.h - -# pinsn.o depends on ALL the opcode printers -# since we don't know which one is really being used. -pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \ - ${OPCODES} - -# -# The rest of this is a standard dependencies list (hand edited output of -# cpp -M). It does not include dependencies of .o files on .c files. -# -blockframe.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -breakpoint.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -coffread.o : defs.h param.h -command.o : command.h defs.h -core.o : defs.h param.h a.out.encap.h -dbxread.o : param.h defs.h symtab.h obstack.h symseg.h a.out.encap.h \ - stab.gnu.h -environ.o : environ.h -eval.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h -expprint.o : defs.h symtab.h obstack.h symseg.h param.h expression.h -findvar.o : defs.h param.h symtab.h obstack.h symseg.h frame.h value.h -infcmd.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - environ.h value.h -inflow.o : defs.h param.h frame.h inferior.h -infrun.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \ - wait.h -kdb-start.o : defs.h param.h -main.o : defs.h command.h param.h -malloc.o : getpagesize.h -obstack.o : obstack.h -printcmd.o : defs.h param.h frame.h symtab.h obstack.h symseg.h value.h \ - expression.h -regex.o : regex.h -remote.o : defs.h param.h frame.h inferior.h wait.h -source.o : defs.h symtab.h obstack.h symseg.h param.h -stack.o : defs.h param.h symtab.h obstack.h symseg.h frame.h -standalone.o : defs.h param.h symtab.h obstack.h symseg.h frame.h \ - inferior.h wait.h -symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h -symtab.o : defs.h symtab.h obstack.h symseg.h param.h obstack.h -utils.o : defs.h param.h -valarith.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h -valops.o : defs.h param.h symtab.h obstack.h symseg.h value.h frame.h \ - inferior.h -valprint.o : defs.h param.h symtab.h obstack.h symseg.h value.h -values.o : defs.h param.h symtab.h obstack.h symseg.h value.h - -robotussin.h : getpagesize.h -symtab.h : obstack.h symseg.h -a.out.encap.h : a.out.gnu.h -@ - - -1.3 -log -@A/UX changes. Use cc, use local regex.o, use local alloca.o -@ -text -@d4 2 -a5 2 -# You must also define REGEX & REGEX1 below and add alloca.o (from -# the emacs distribution) to the CLIBS. -d12 2 -d26 2 -a27 1 -# incorrectly compiled. -d46 2 -d52 4 -d70 1 -a70 1 -#CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC) -d72 1 -a72 1 -CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) alloca.o -d122 1 -a122 1 -gdb : $(OBS) $(TSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d127 1 -a127 1 -xgdb : $(OBS) $(TSOBS) xgdb.o $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d133 1 -a133 1 -kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC} -d161 1 -a161 1 - -rm -f init.c -d165 1 -a165 1 - -rm -f expread.tab.c -@ - - -1.2 -log -@All rm's to rm -f's. -@ -text -@d26 1 -a26 1 -CC=gcc -d45 2 -a46 2 -REGEX = -REGEX1 = -d61 1 -a61 1 -CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC) -d63 1 -a63 1 -#CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) -lPW -@ - - -1.1 -log -@Initial revision -@ -text -@d26 1 -a26 1 -CC=/bin/cc -d114 1 -a114 1 - -rm init.c -d119 1 -a119 1 - -rm init.c -d125 1 -a125 1 - -rm init.c -d151 3 -a153 3 - -rm ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} - -rm init.c - -rm gdb -d156 1 -a156 1 - -rm expread.tab.c -@ diff --git a/gdb/RCS/blockframe.c,v b/gdb/RCS/blockframe.c,v deleted file mode 100644 index fc64e2f..0000000 --- a/gdb/RCS/blockframe.c,v +++ /dev/null @@ -1,606 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.16.21.09.52; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.21.53; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.15.15.16; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Don't stop the stack trace until the "next frame pointer" is zero. -@ -text -@/* Get info from stack frames; - convert between frames, blocks, functions and pc values. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" - -/* Address of end of first object file. - This file is assumed to be a startup file - and frames with pc's inside it - are treated as nonexistent. */ - -CORE_ADDR first_object_file_end; - -/* Address of innermost stack frame (contents of FP register) */ - -static FRAME current_frame; - -struct block *block_for_pc (); -CORE_ADDR get_pc_function_start (); - -/* - * Cache for frame addresses already read by gdb. Valid only while - * inferior is stopped. Control variables for the frame cache should - * be local to this module. - */ -struct obstack frame_cache_obstack; - -/* Return the innermost (currently executing) stack frame. */ - -FRAME -get_current_frame () -{ - /* We assume its address is kept in a general register; - param.h says which register. */ - - return current_frame; -} - -void -set_current_frame (frame) - FRAME frame; -{ - current_frame = frame; -} - -FRAME -create_new_frame (addr, pc) - FRAME_ADDR addr; - CORE_ADDR pc; -{ - struct frame_info *fci; /* Same type as FRAME */ - - fci = (struct frame_info *) - obstack_alloc (&frame_cache_obstack, - sizeof (struct frame_info)); - - /* Arbitrary frame */ - fci->next = (struct frame_info *) 0; - fci->prev = (struct frame_info *) 0; - fci->frame = addr; - fci->next_frame = 0; /* Since arbitrary */ - fci->pc = pc; - -#ifdef INIT_EXTRA_FRAME_INFO - INIT_EXTRA_FRAME_INFO (fci); -#endif - - return fci; -} - -/* Return the frame that called FRAME. - If FRAME is the original frame (it has no caller), return 0. */ - -FRAME -get_prev_frame (frame) - FRAME frame; -{ - /* We're allowed to know that FRAME and "struct frame_info *" are - the same */ - return get_prev_frame_info (frame); -} - -/* - * Flush the entire frame cache. - */ -void -flush_cached_frames () -{ - /* Since we can't really be sure what the first object allocated was */ - obstack_free (&frame_cache_obstack, 0); - obstack_init (&frame_cache_obstack); - - current_frame = (struct frame_info *) 0; /* Invalidate cache */ -} - -/* Return a structure containing various interesting information - about a specified stack frame. */ -/* How do I justify including this function? Well, the FRAME - identifier format has gone through several changes recently, and - it's not completely inconceivable that it could happen again. If - it does, have this routine around will help */ - -struct frame_info * -get_frame_info (frame) - FRAME frame; -{ - return frame; -} - -/* Return a structure containing various interesting information - about the frame that called NEXT_FRAME. */ - -struct frame_info * -get_prev_frame_info (next_frame) - FRAME next_frame; -{ - FRAME_ADDR address; - struct frame_info *prev; - int fromleaf = 0; - - /* If we are within "start" right now, don't go any higher. */ - /* This truncates stack traces of things at sigtramp() though, - because sigtramp() doesn't have a normal return PC, it has - garbage or a small value (seen: 3) in the return PC slot. - It's VITAL to see where the signal occurred, so punt this. */ -#if 0 - if (next_frame && next_frame->pc < first_object_file_end) - return 0; -#endif - - /* If the requested entry is in the cache, return it. - Otherwise, figure out what the address should be for the entry - we're about to add to the cache. */ - - if (!next_frame) - { - if (!current_frame) - error ("No frame is currently selected."); - - return current_frame; - } - else - { - /* If we have the prev one, return it */ - if (next_frame->prev) - return next_frame->prev; - - /* There is a questionable, but probably always correct - assumption being made here. The assumption is that if - functions on a specific machine has a FUNCTION_START_OFFSET, - then this is used by the function call instruction for some - purpose. If the function call instruction has this much hair - in it, it probably also sets up the frame pointer - automatically (ie. we'll never have what I am calling a - "leaf node", one which shares a frame pointer with it's - calling function). This is true on a vax. The only other - way to find this out would be to setup a seperate macro - "FUNCTION_HAS_FRAME_POINTER", which would often be equivalent - to SKIP_PROLOGUE modifying a pc value. */ - -#if FUNCTION_START_OFFSET == 0 - if (!(next_frame->next)) - { - /* Innermost */ - CORE_ADDR func_start, after_prologue; - - func_start = (get_pc_function_start (next_frame->pc) + - FUNCTION_START_OFFSET); - after_prologue = func_start; - SKIP_PROLOGUE (after_prologue); - if (after_prologue == func_start) - { - fromleaf = 1; - address = next_frame->frame; - } - } -#endif - - if (!fromleaf) - { - /* Two macros defined in param.h specify the machine-dependent - actions to be performed here. */ - /* First, get the frame's chain-pointer. - If that is zero, the frame is the outermost frame. */ - address = FRAME_CHAIN (next_frame); - if (!FRAME_CHAIN_VALID (address, next_frame)) - return 0; - - /* If frame has a caller, combine the chain pointer and - the frame's own address to get the address of the caller. */ - address = FRAME_CHAIN_COMBINE (address, next_frame); - } - } - - prev = (struct frame_info *) - obstack_alloc (&frame_cache_obstack, - sizeof (struct frame_info)); - - if (next_frame) - next_frame->prev = prev; - 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 -get_frame_pc (frame) - FRAME frame; -{ - struct frame_info *fi; - fi = get_frame_info (frame); - return fi->pc; -} - -/* Find the addresses in which registers are saved in FRAME. */ - -void -get_frame_saved_regs (frame_info_addr, saved_regs_addr) - struct frame_info *frame_info_addr; - struct frame_saved_regs *saved_regs_addr; -{ -#if 1 - FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr); -#else - { - register int regnum; - register int regmask; - register CORE_ADDR next_addr; - register CORE_ADDR pc; - int nextinsn; - bzero (&*saved_regs_addr, sizeof *saved_regs_addr); - if ((frame_info_addr)->pc >= ((frame_info_addr)->frame - - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4) - && (frame_info_addr)->pc <= (frame_info_addr)->frame) - { - next_addr = (frame_info_addr)->frame; - pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; - } - else - { - pc = get_pc_function_start ((frame_info_addr)->pc); - /* Verify we have a link a6 instruction next; - if not we lose. If we win, find the address above the saved - regs using the amount of storage from the link instruction. */ - if (044016 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4); - pc += 4; - } - else if (047126 == read_memory_integer (pc, 2)) - { - next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2); - pc+=2; - } - else goto lose; - - /* If have an addal #-n, sp next, adjust next_addr. */ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) - { - next_addr += read_memory_integer (pc += 2, 4); - pc += 4; - } - } - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ - regmask = read_memory_integer (pc + 2, 2); - - /* But before that can come an fmovem. Check for it. */ - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf227 == nextinsn - && (regmask & 0xff00) == 0xe000) - { - pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 12); - regmask = read_memory_integer (pc + 2, 2); - } - if (0044327 == read_memory_integer (pc, 2)) - { - pc += 4; /* Regmask's low bit is for register 0, the first written */ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4; - } - else if (0044347 == read_memory_integer (pc, 2)) - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; - (*saved_regs_addr).regs[regnum] = (next_addr -= 4); } - /* fmovemx to index of sp may follow. */ - regmask = read_memory_integer (pc + 2, 2); - nextinsn = 0xffff & read_memory_integer (pc, 2); - if (0xf236 == nextinsn - && (regmask & 0xff00) == 0xf000) - { - pc += 10; /* Regmask's low bit is for register fp0, the first written */ - for (regnum = FP0_REGNUM + 7; - regnum >= FP0_REGNUM; - regnum--, regmask >>= 1) - if (regmask & 1) - (*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12; - regmask = read_memory_integer (pc + 2, 2); - } - /* clrw -(sp); movw ccr,-(sp) may follow. */ - if (0x426742e7 == read_memory_integer (pc, 4)) - (*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4); - lose: ; - (*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8; - (*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame; - (*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4; - } -#endif -} - -/* Return the innermost lexical block in execution - in a specified stack frame. The frame address is assumed valid. */ - -struct block * -get_frame_block (frame) - FRAME frame; -{ - struct frame_info *fi; - - fi = get_frame_info (frame); - return block_for_pc (fi->pc); -} - -struct block * -get_current_block () -{ - return block_for_pc (read_pc ()); -} - -CORE_ADDR -get_pc_function_start (pc) - CORE_ADDR pc; -{ - register struct block *bl = block_for_pc (pc); - register struct symbol *symbol; - if (bl == 0 || (symbol = block_function (bl)) == 0) - { - register int misc_index = find_pc_misc_function (pc); - if (misc_index >= 0) - return misc_function_vector[misc_index].address; - return 0; - } - bl = SYMBOL_BLOCK_VALUE (symbol); - return BLOCK_START (bl); -} - -/* Return the symbol for the function executing in frame FRAME. */ - -struct symbol * -get_frame_function (frame) - FRAME frame; -{ - register struct block *bl = get_frame_block (frame); - if (bl == 0) - return 0; - return block_function (bl); -} - -/* Return the innermost lexical block containing the specified pc value, - or 0 if there is none. */ - -extern struct symtab *psymtab_to_symtab (); - -struct block * -block_for_pc (pc) - register CORE_ADDR pc; -{ - register struct block *b; - register int bot, top, half; - register struct symtab *s; - register struct partial_symtab *ps; - struct blockvector *bl; - - /* First search all symtabs for one whose file contains our pc */ - - for (s = symtab_list; s; s = s->next) - { - bl = BLOCKVECTOR (s); - b = BLOCKVECTOR_BLOCK (bl, 0); - if (BLOCK_START (b) <= pc - && BLOCK_END (b) > pc) - break; - } - - if (s == 0) - for (ps = partial_symtab_list; ps; ps = ps->next) - { - if (ps->textlow <= pc - && ps->texthigh > pc) - { - s = psymtab_to_symtab (ps); - bl = BLOCKVECTOR (s); - b = BLOCKVECTOR_BLOCK (bl, 0); - break; - } - } - - if (s == 0) - return 0; - - /* Then search that symtab for the smallest block that wins. */ - /* Use binary search to find the last block that starts before PC. */ - - bot = 0; - top = BLOCKVECTOR_NBLOCKS (bl); - - while (top - bot > 1) - { - half = (top - bot + 1) >> 1; - b = BLOCKVECTOR_BLOCK (bl, bot + half); - if (BLOCK_START (b) <= pc) - bot += half; - else - top = bot + half; - } - - /* Now search backward for a block that ends after PC. */ - - while (bot >= 0) - { - b = BLOCKVECTOR_BLOCK (bl, bot); - if (BLOCK_END (b) > pc) - return b; - bot--; - } - - return 0; -} - -/* Return the function containing pc value PC. - Returns 0 if function is not known. */ - -struct symbol * -find_pc_function (pc) - CORE_ADDR pc; -{ - register struct block *b = block_for_pc (pc); - if (b == 0) - return 0; - return block_function (b); -} - -/* Find the misc function whose address is the largest - while being less than PC. Return its index in misc_function_vector. - Returns -1 if PC is not in suitable range. */ - -int -find_pc_misc_function (pc) - register CORE_ADDR pc; -{ - register int lo = 0; - register int hi = misc_function_count-1; - register int new; - register int distance; - - /* Note that the last thing in the vector is always _etext. */ - - /* Above statement is not *always* true - fix for case where there are */ - /* no misc functions at all (ie no symbol table has been read). */ - if (hi < 0) return -1; /* no misc functions recorded */ - - /* trivial reject range test */ - if (pc < misc_function_vector[0].address || - pc > misc_function_vector[hi].address) - return -1; - - do { - new = (lo + hi) >> 1; - distance = misc_function_vector[new].address - pc; - if (distance == 0) - return new; /* an exact match */ - else if (distance > 0) - hi = new; - else - lo = new; - } while (hi-lo != 1); - - /* if here, we had no exact match, so return the lower choice */ - return lo; -} - -/* Return the innermost stack frame executing inside of the specified block, - or zero if there is no such frame. */ - -FRAME -block_innermost_frame (block) - struct block *block; -{ - struct frame_info *fi; - register FRAME frame; - register CORE_ADDR start = BLOCK_START (block); - register CORE_ADDR end = BLOCK_END (block); - - frame = 0; - while (1) - { - frame = get_prev_frame (frame); - if (frame == 0) - return 0; - fi = get_frame_info (frame); - if (fi->pc >= start && fi->pc < end) - return frame; - } -} - -void -_initialize_blockframe () -{ - obstack_init (&frame_cache_obstack); -} -@ - - -1.2 -log -@Avoid fatal error for simple user error -@ -text -@d142 5 -d149 1 -@ - - -1.1 -log -@Initial revision -@ -text -@d152 1 -a152 1 - fatal ("get_prev_frame_info: Called before cache primed"); -@ diff --git a/gdb/RCS/coffread.c,v b/gdb/RCS/coffread.c,v deleted file mode 100644 index 9c45395..0000000 --- a/gdb/RCS/coffread.c,v +++ /dev/null @@ -1,2047 +0,0 @@ -head 1.5; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.5 -date 89.03.27.18.38.25; author gnu; state Exp; -branches ; -next 1.4; - -1.4 -date 89.03.27.18.37.20; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.18.36.15; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.38.05; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.32.45; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.5 -log -@Remake A/UX changes. -@ -text -@/* 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@@cs.brown.edu - Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#ifdef COFF_FORMAT -#include "symtab.h" - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#endif - -#include <a.out.h> -#include <stdio.h> -#include <obstack.h> -#include <sys/param.h> -#include <sys/file.h> - -/* Avoid problems with A/UX predefine */ -#undef aux - -static void add_symbol_to_list (); -static void 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 void finish_block (); -static struct blockvector *make_blockvector (); -static struct symbol *process_coff_symbol (); -static int init_stringtab (); -static void free_stringtab (); -static char *getfilename (); -static char *getsymname (); -static int init_lineno (); -static void enter_linenos (); - -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 start and end of text of current source file. - This comes from a ".text" symbol where x_nlinno > 0. */ - -static CORE_ADDR cur_src_start_addr; -static CORE_ADDR cur_src_end_addr; - -/* End of the text segment of the executable file, - as found in the symbol _etext. */ - -static CORE_ADDR end_of_text_addr; - -/* The addresses of the symbol table stream and number of symbols - of the object file we are reading (as copied into core). */ - -static FILE *nlist_stream_global; -static int nlist_nsyms_global; - -/* The file and text section headers of the symbol file */ - -static FILHDR file_hdr; -static SCNHDR text_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; - -/* Vector of line number information. */ - -static struct linetable *line_vector; - -/* Index of next entry to go in line_vector_index. */ - -static int line_vector_index; - -/* Last line number recorded in the line vector. */ - -static int prev_line_number; - -/* Number of elements allocated for line_vector currently. */ - -static int line_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 *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; - int depth; -}; - -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 first_object_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; -{ - struct linetable_entry *e; - /* 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 = line; e->pc = 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 () -{ - file_symbols = 0; - global_symbols = 0; - context_stack = 0; - within_function = 0; - last_source_file = 0; - - /* Initialize the source file information for this file. */ - - line_vector_index = 0; - line_vector_length = 1000; - prev_line_number = -2; /* Force first line number to be explicit */ - line_vector = (struct linetable *) - xmalloc (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry)); -} - -/* Save the vital information for use when closing off the current file. - NAME is the file name the symbols came from, START_ADDR is the first - text address for the file, and SIZE is the number of bytes of text. */ - -static void -complete_symtab (name, start_addr, size) - char *name; - CORE_ADDR start_addr; - unsigned int size; -{ - last_source_file = savestring (name, strlen (name)); - cur_src_start_addr = start_addr; - cur_src_end_addr = start_addr + size; -} - -/* 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. */ - -static void -end_symtab () -{ - register struct symtab *symtab; - register struct context_stack *cstk; - register struct blockvector *blockvector; - register struct linetable *lv; - - /* 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, cur_src_end_addr); - free (cstk); - } - - /* Ignore a file that has no functions with real debugging info. */ - if (pending_blocks == 0 && file_symbols == 0 && global_symbols == 0) - { - free (line_vector); - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; - return; - } - - /* Create the two top-level blocks for this file. */ - finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr); - finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_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; - lv = line_vector; - lv->nitems = line_vector_index; - symtab->linetable = (struct linetable *) - xrealloc (lv, (sizeof (struct linetable) - + lv->nitems * sizeof (struct linetable_entry))); - 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. */ - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; -} - -/* 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_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); - } - } -} - -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to symtab_list. */ - -void -symbol_file_command (name) - char *name; -{ - int desc; - int num_symbols; - int num_sections; - int symtab_offset; - extern void close (); - 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 (); - return; - } - - 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 (num_symbols == 0) - { - free_all_symtabs (); - printf ("%s does not have a symbol-table.\n", name); - fflush (stdout); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Throw away the old symbol table. */ - - free_all_symtabs (); - 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); - - /* Read the line number table, all at once. */ - - val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno); - if (val < 0) - error ("\"%s\": error reading line numbers\n", name); - - /* Now read the string table, all at once. */ - - val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ); - if (val < 0) - { - free_all_symtabs (); - printf ("\"%s\": can't get string table", name); - fflush (stdout); - return; - } - make_cleanup (free_stringtab, 0); - - /* 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. */ - - read_coff_symtab (desc, num_symbols); - - patch_opaque_types (); - - /* Sort symbols alphabetically within each block. */ - - sort_syms (); - - /* Go over the misc functions and install them in vector. */ - - condense_misc_bunches (); - - /* 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. */ - - select_source_symtab (symtab_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; -}; - -/* 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 (). */ - -static void -read_coff_symtab (desc, nsyms) - int desc; - int nsyms; -{ - int newfd; /* Avoid multiple closes on same desc */ - FILE *stream; - register struct context_stack *new; - struct coff_symbol coff_symbol; - register struct coff_symbol *cs = &coff_symbol; - static SYMENT main_sym; - static AUXENT main_aux; - struct coff_symbol fcn_cs_saved; - static SYMENT fcn_sym_saved; - static AUXENT fcn_aux_saved; - - int num_object_files = 0; - int next_file_symnum = -1; - char *filestring; - int depth; - int fcn_first_line; - int fcn_last_line; - int fcn_start_addr; - long fcn_line_ptr; - struct cleanup *old_chain; - int fclose(); - - newfd = dup (desc); - if (newfd == -1) - fatal ("Too many open files"); - stream = fdopen (newfd, "r"); - - old_chain = make_cleanup (free_all_symtabs, 0); - make_cleanup (fclose, stream); - nlist_stream_global = stream; - nlist_nsyms_global = nsyms; - 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 *)); - - start_symtab (); - - symnum = 0; - while (symnum < nsyms) - { - QUIT; /* Make this command interruptable. */ - read_one_sym (cs, &main_sym, &main_aux); - - if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) - { - CORE_ADDR last_file_end = cur_src_end_addr; - - if (last_source_file) - end_symtab (); - - start_symtab (); - complete_symtab ("_globals_", 0, first_object_file_end); - /* done with all files, everything from here on out is globals */ - } - - /* Special case for file with type declarations only, no text. */ - if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG) - complete_symtab (filestring, 0, 0); - - /* Typedefs should not be treated as symbol definitions. */ - if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF) - { - /* record as misc function. if we get '.bf' next, - * then we undo this step - */ - record_misc_function (cs->c_name, cs->c_value); - - fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; - fcn_start_addr = cs->c_value; - fcn_cs_saved = *cs; - fcn_sym_saved = main_sym; - fcn_aux_saved = main_aux; - continue; - } - - switch (cs->c_sclass) - { - case C_EFCN: - case C_EXTDEF: - case C_ULABEL: - case C_USTATIC: - case C_LINE: - case C_ALIAS: - case C_HIDDEN: - printf ("Bad n_sclass = %d\n", cs->c_sclass); - break; - - case C_FILE: - /* - * c_value field contains symnum of next .file entry in table - * or symnum of first global after last .file. - */ - next_file_symnum = cs->c_value; - filestring = getfilename (&main_aux); - /* - * Complete symbol table for last object file - * containing debugging information. - */ - if (last_source_file) - { - end_symtab (); - start_symtab (); - } - num_object_files++; - break; - - case C_STAT: - if (cs->c_name[0] == '.') { - if (strcmp (cs->c_name, _TEXT) == 0) { - if (num_object_files == 1) { - /* last address of startup file */ - first_object_file_end = cs->c_value + - main_aux.x_scn.x_scnlen; - } - /* for some reason the old code didn't do - * this if this section entry had - * main_aux.x_scn.x_nlinno equal to 0 - */ - complete_symtab (filestring, cs->c_value, - main_aux.x_scn.x_scnlen); - } - /* flush rest of '.' symbols */ - break; - } - /* fall in for static symbols that don't start with '.' */ - case C_EXT: - if (cs->c_sclass == C_EXT && - cs->c_secnum == N_ABS && - strcmp (cs->c_name, _ETEXT) == 0) - end_of_text_addr = cs->c_value; - if (cs->c_type == T_NULL) { - if (cs->c_secnum <= 1) { /* text or abs */ - record_misc_function (cs->c_name, cs->c_value); - break; - } else { - cs->c_type = T_INT; - } - } - (void) process_coff_symbol (cs, &main_aux); - break; - - case C_FCN: - if (strcmp (cs->c_name, ".bf") == 0) - { - unrecord_misc_function (); - - within_function = 1; - - /* value contains address of first non-init type code */ - /* main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains line number of '{' } */ - fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - new->depth = depth = 0; - new->next = 0; - context_stack = new; - new->locals = 0; - new->old_blocks = pending_blocks; - new->start_addr = fcn_start_addr; - fcn_cs_saved.c_name = getsymname (&fcn_sym_saved); - new->name = process_coff_symbol (&fcn_cs_saved, - &fcn_aux_saved); - } - else if (strcmp (cs->c_name, ".ef") == 0) - { - /* the value of .ef is the address of epilogue code; - * not useful for gdb - */ - /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains number of lines to '}' */ - fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); - new = context_stack; - - if (new == 0) - error ("Invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.", - symnum); - - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, - fcn_cs_saved.c_value + - fcn_aux_saved.x_sym.x_misc.x_fsize); - context_stack = 0; - within_function = 0; - free (new); - } - break; - - case C_BLOCK: - if (strcmp (cs->c_name, ".bb") == 0) - { - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - depth++; - new->depth = depth; - new->next = context_stack; - context_stack = new; - new->locals = local_symbols; - new->old_blocks = pending_blocks; - new->start_addr = cs->c_value; - new->name = 0; - local_symbols = 0; - } - else if (strcmp (cs->c_name, ".eb") == 0) - { - new = context_stack; - if (new == 0 || depth != new->depth) - error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.", - symnum); - 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, cs->c_value); - } - depth--; - local_symbols = new->locals; - context_stack = new->next; - free (new); - } - break; - - default: - (void) process_coff_symbol (cs, &main_aux); - break; - } - } - - if (last_source_file) - end_symtab (); - fclose (stream); - discard_cleanups (old_chain); -} - -/* 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 NS32GMAGIC - case NS32GMAGIC: - case NS32SMAGIC: -#endif -#ifdef I386MAGIC - case I386MAGIC: -#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; -} - -read_one_sym (cs, sym, aux) - register struct coff_symbol *cs; - register SYMENT *sym; - register AUXENT *aux; -{ - cs->c_symnum = symnum; - fread ((char *)sym, SYMESZ, 1, nlist_stream_global); - cs->c_nsyms = (sym->n_numaux & 0xff) + 1; - if (cs->c_nsyms == 2) - { - /* doc for coff says there is either no aux entry or just one */ - fread ((char *)aux, AUXESZ, 1, nlist_stream_global); - } - else if (cs->c_nsyms > 2) - error ("more than one aux symbol table entry at symnum=%d\n", symnum); - - cs->c_name = getsymname (sym); - cs->c_value = sym->n_value; - cs->c_sclass = (sym->n_sclass & 0xff); - cs->c_secnum = sym->n_scnum; - cs->c_type = (unsigned) sym->n_type; - - symnum += cs->c_nsyms; -} - -/* Support for string table handling */ - -static char *stringtab = NULL; - -static int -init_stringtab (chan, offset) - int chan; - long offset; -{ - long buffer; - int val; - - if (stringtab) - { - free (stringtab); - stringtab = NULL; - } - - if (lseek (chan, offset, 0) < 0) - return -1; - - val = myread (chan, (char *)&buffer, sizeof buffer); - - /* If no string table is needed, then the file may end immediately - after the symbols. Just return with `stringtab' set to null. */ - if (val != sizeof buffer || buffer == 0) - return 0; - - stringtab = (char *) xmalloc (buffer); - if (stringtab == NULL) - return -1; - - bcopy (&buffer, stringtab, sizeof buffer); - - val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0') - return -1; - - return 0; -} - -static void -free_stringtab () -{ - if (stringtab) - free (stringtab); - stringtab = NULL; -} - -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; -} - -static char * -getfilename (aux_entry) - AUXENT *aux_entry; -{ - static char buffer[BUFSIZ]; - register char *temp; - char *result; - extern char *rindex (); - -#ifndef COFF_NO_LONG_FILE_NAMES - if (aux_entry->x_file.x_foff != 0) - strcpy (buffer, stringtab + aux_entry->x_file.x_foff); - else -#endif - { - strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); - buffer[FILNMLEN] = '\0'; - } - result = buffer; - if ((temp = rindex (result, '/')) != NULL) - result = temp + 1; - return (result); -} - -/* Support for line number handling */ -static char *linetab = NULL; -static long linetab_offset; -static int linetab_count; - -static int -init_lineno (chan, offset, count) - int chan; - long offset; - int count; -{ - int val; - - if (lseek (chan, offset, 0) < 0) - return -1; - - if (linetab) - free (linetab); - linetab = (char *) xmalloc (count * LINESZ); - - val = myread (chan, linetab, count * LINESZ); - if (val != count * LINESZ) - return -1; - - linetab_offset = offset; - linetab_count = count; - return 0; -} - -static void -enter_linenos (file_offset, first_line, last_line) - long file_offset; - register int first_line; - register int last_line; -{ - register char *rawptr = &linetab[file_offset - linetab_offset]; - register struct lineno *lptr; - - /* skip first line entry for each function */ - rawptr += LINESZ; - /* line numbers start at one for the first line of the function */ - first_line--; - - for (lptr = (struct lineno *)rawptr; - lptr->l_lnno && lptr->l_lnno <= last_line; - rawptr += LINESZ, lptr = (struct lineno *)rawptr) - { - record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); - } -} - -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); - } - } - } - } - } -} - -static struct symbol * -process_coff_symbol (cs, aux) - register struct coff_symbol *cs; - register AUXENT *aux; -{ - register struct symbol *sym - = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - char *name; - char *dot; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - bzero (sym, sizeof (struct symbol)); - name = cs->c_name; - name = (name[0] == '_' ? name + offset : name); - SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name)); - - /* default assumptions */ - SYMBOL_VALUE (sym) = cs->c_value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - if (ISFCN (cs->c_type)) - { - SYMBOL_TYPE (sym) = - lookup_function_type (decode_function_type (cs, cs->c_type, aux)); - SYMBOL_CLASS (sym) = LOC_BLOCK; - if (cs->c_sclass == C_STAT) - add_symbol_to_list (sym, &file_symbols); - else if (cs->c_sclass == C_EXT) - add_symbol_to_list (sym, &global_symbols); - } - else - { - SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); - switch (cs->c_sclass) - { - case C_NULL: - break; - - case C_AUTO: - SYMBOL_CLASS (sym) = LOC_LOCAL; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_EXT: - SYMBOL_CLASS (sym) = LOC_STATIC; - add_symbol_to_list (sym, &global_symbols); - break; - - case C_STAT: - 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 C_REG: - case C_REGPARM: - SYMBOL_CLASS (sym) = LOC_REGISTER; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_LABEL: - break; - - case C_ARG: - SYMBOL_CLASS (sym) = LOC_ARG; - add_symbol_to_list (sym, &local_symbols); - /* If PCC says a parameter is a short or a char, - it is really an int. */ - if (SYMBOL_TYPE (sym) == builtin_type_char - || SYMBOL_TYPE (sym) == builtin_type_short) - SYMBOL_TYPE (sym) = builtin_type_int; - else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char - || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) - SYMBOL_TYPE (sym) = builtin_type_unsigned_int; - break; - - case C_TPDEF: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - /* If type has no name, give it one */ - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat (SYMBOL_NAME (sym), "", ""); - - /* Keep track of any type which points to empty structured type, - so it can be filled from a definition from another file */ - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0) - { - register int i = hashname (SYMBOL_NAME (sym)); - - SYMBOL_VALUE (sym) = (int) opaque_type_chain[i]; - opaque_type_chain[i] = sym; - } - add_symbol_to_list (sym, &file_symbols); - break; - - case C_STRTAG: - case C_UNTAG: - case C_ENTAG: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat ("", - (cs->c_sclass == C_ENTAG - ? "enum " - : (cs->c_sclass == C_STRTAG - ? "struct " : "union ")), - SYMBOL_NAME (sym)); - add_symbol_to_list (sym, &file_symbols); - break; - - default: - break; - } - } - return sym; -} - -/* Decode a coff type specifier; - return the type that is meant. */ - -static -struct type * -decode_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - register struct type *type = 0; - register int n; - unsigned int new_c_type; - - if (c_type & ~N_BTMASK) - { - new_c_type = DECREF (c_type); - if (ISPTR (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_pointer_type (type); - } - else if (ISFCN (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_function_type (type); - } - else if (ISARY (c_type)) - { - int i, n; - register unsigned short *dim; - struct type *base_type; - - /* Define an array type. */ - /* auxent refers to array, not base type */ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; - - /* shift the indices down */ - dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; - i = 1; - n = dim[0]; - for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) - *dim = *(dim + 1); - *dim = 0; - - type = (struct type *) - obstack_alloc (symbol_obstack, sizeof (struct type)); - bzero (type, sizeof (struct type)); - - base_type = decode_type (cs, new_c_type, aux); - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (type) = base_type; - TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type); - } - return type; - } - - /* Reference to existing type */ - if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0) - { - type = coff_alloc_type (aux->x_sym.x_tagndx); - return type; - } - - return decode_base_type (cs, BTYPE (c_type), aux); -} - -/* Decode a coff type specifier for function definition; - return the type that the function returns. */ - -static -struct type * -decode_function_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; /* auxent refers to function, not base type */ - - return decode_type (cs, DECREF (cs->c_type), aux); -} - -/* basic C types */ - -static -struct type * -decode_base_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - struct type *type; - - switch (c_type) - { - case T_NULL: - /* shows up with "void (*foo)();" structure members */ - return builtin_type_void; - - case T_ARG: - /* shouldn't show up here */ - break; - - case T_CHAR: - return builtin_type_char; - - case T_SHORT: - return builtin_type_short; - - case T_INT: - return builtin_type_int; - - case T_LONG: - return builtin_type_long; - - case T_FLOAT: - return builtin_type_float; - - case T_DOUBLE: - return builtin_type_double; - - case T_STRUCT: - if (cs->c_nsyms != 2) - { - /* anonymous structure type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_NAME (type) = concat ("struct ", "<opaque>", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - return type; - - case T_UNION: - if (cs->c_nsyms != 2) - { - /* anonymous union type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_NAME (type) = concat ("union ", "<opaque>", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - TYPE_CODE (type) = TYPE_CODE_UNION; - return type; - - case T_ENUM: - return read_enum_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - - case T_MOE: - /* shouldn't show up here */ - break; - - case T_UCHAR: - return builtin_type_unsigned_char; - - case T_USHORT: - return builtin_type_unsigned_short; - - case T_UINT: - return builtin_type_unsigned_int; - - case T_ULONG: - return builtin_type_unsigned_long; - } - printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum); - return builtin_type_void; -} - -/* This page contains subroutines of read_type. */ - -/* Read the description of a structure (or union type) - and return an object describing the type. */ - -static struct type * -read_struct_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - struct nextfield - { - struct nextfield *next; - struct field field; - }; - - register struct type *type; - register struct nextfield *list = 0; - struct nextfield *new; - int nfields = 0; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - int done = 0; - - type = coff_alloc_type (index); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_LENGTH (type) = length; - - while (!done && symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOS: - case C_MOU: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = 8 * ms->c_value; - list->field.bitsize = 0; - nfields++; - break; - - case C_FIELD: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = ms->c_value; - list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size; - nfields++; - break; - - case C_EOS: - done = 1; - break; - } - } - /* Now create the vector of fields, and record how big it is. */ - - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); - - /* Copy the saved-up fields into the field vector. */ - - for (n = nfields; list; list = list->next) - TYPE_FIELD (type, --n) = list->field; - - return type; -} - -/* Read a definition of an enumeration type, - and create and return a suitable type object. - Also defines the symbols that represent the values of the type. */ - -static struct type * -read_enum_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - register struct symbol *sym; - register struct type *type; - int nsyms = 0; - struct pending **symlist; - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - struct pending *osyms, *syms; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - type = coff_alloc_type (index); - if (within_function) - symlist = &local_symbols; - else - symlist = &file_symbols; - osyms = *symlist; - - while (symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOE: - sym = (struct symbol *) xmalloc (sizeof (struct symbol)); - bzero (sym, sizeof (struct symbol)); - - SYMBOL_NAME (sym) = savestring (name, strlen (name)); - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_VALUE (sym) = ms->c_value; - add_symbol_to_list (sym, symlist); - nsyms++; - break; - - case C_EOS: - break; - } - } - - /* Now fill in the fields of the type-structure. */ - - TYPE_LENGTH (type) = sizeof (int); - TYPE_CODE (type) = TYPE_CODE_ENUM; - TYPE_NFIELDS (type) = nsyms; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); - - /* Find the symbols for the values and put them into the type. - The symbols can be found in the symlist that we put them on - to cause them to be defined. osyms contains the old value - of that symlist; everything up to there was defined by us. */ - - for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next) - { - SYMBOL_TYPE (syms->symbol) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol); - TYPE_FIELD_VALUE (type, n) = 0; - TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (syms->symbol); - TYPE_FIELD_BITSIZE (type, n) = 0; - } - return type; -} - -/* 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 partial_symbol *global_psymbols, *static_psymbols; - -_initialize_coff () -{ - symfile = 0; - - static_psymbols = global_psymbols = (struct partial_symbol *) 0; - - add_com ("symbol-file", class_files, symbol_file_command, - "Load symbol table (in coff format) from executable file FILE."); -} - - -#endif /* COFF_FORMAT */ - -@ - - -1.4 -log -@Avoid A/UX change (#undef aux) for sending in to FSF. -@ -text -@d40 3 -@ - - -1.3 -log -@A/UX and USG changes. If BADMAG defined, use it. Avoid <sys/fcntl.h>. -Declare fclose(). #undef aux which we use as a var. -@ -text -@a39 3 -/* Avoid problems with A/UX predefine */ -#undef aux - -@ - - -1.2 -log -@If discarding the symbol table, discard its name too, so "info files" -will give the right answer. -@ -text -@d31 1 -a31 1 -#include <sys/fcntl.h> -d40 3 -d847 1 -a847 1 - -d1093 6 -d1100 1 -@ - - -1.1 -log -@Initial revision -@ -text -@d5 1 -a5 1 - Copyright (C) 1987, 1988 Free Software Foundation, Inc. -d684 3 -@ diff --git a/gdb/RCS/config.gdb,v b/gdb/RCS/config.gdb,v deleted file mode 100755 index b569f62..0000000 --- a/gdb/RCS/config.gdb,v +++ /dev/null @@ -1,229 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @@; - - -1.2 -date 89.03.27.18.38.55; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.13.19.14.24; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Add A/UX option (config.gdb aux). -@ -text -@#!/bin/sh - -# -# Shell script to create proper links to machine-dependent files in -# preparation for compiling gdb. -# -# Usage: config.gdb machine [operating-system] -# -# If config.gdb succeeds, it leaves its status in config.status. -# If config.gdb fails after disturbing the status quo, -# config.status is removed. -# - -progname=$0 - -case $# in -1) - machine=$1 - os="none" - ;; -2) - machine=$1 - os=$2 - ;; -*) - echo "Usage: $progname machine [operating-system]" - echo "Available machine types:" - echo m-*.h | sed 's/m-//g' | sed 's/\.h//g' - if [ -r config.status ] - then - cat config.status - fi - exit 1 - ;; -esac - -paramfile=m-${machine}.h -pinsnfile=${machine}-pinsn.c -opcodefile=${machine}-opcode.h -if [ -r ${machine}-dep.c ] -then - depfile=${machine}-dep.c -else - depfile=default-dep.c -fi - -# -# Special cases. -# If a file is not needed, set the filename to 'skip' and it will be -# ignored. -# -case $machine in -aux) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -vax) - pinsnfile=vax-pinsn.c - opcodefile=vax-opcode.h - ;; -hp9k320) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -isi) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -i386) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - opcodefile=skip - ;; -i386gas) - echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile" - echo "Use of the coff encapsulation features also requires the GNU binutils utilities" - echo "to be ahead of their System V counterparts in your path." - pinsnfile=i386-pinsn.c - depfile=i386-dep.c - opcodefile=skip - ;; -merlin) - pinsnfile=ns32k-pinsn.c - opcodefile=ns32k-opcode.h - ;; -news) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -npl) - pinsnfile=gld-pinsn.c - ;; -pn) - pinsnfile=gld-pinsn.c - ;; -sun2) - case $os in - os4|sunos4) - paramfile=m-sun2os4.h - ;; - os2|sunos2) - paramfile=m-sun2os2.h - esac - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun2os2) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun2os4) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun3) - case $os in - os4|sunos4) - paramfile=m-sun3os4.h - esac - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - ;; -sun3os4) - pinsnfile=m68k-pinsn.c - opcodefile=m68k-opcode.h - depfile=sun3-dep.c - ;; -sun4os4) - pinsnfile=sparc-pinsn.c - opcodefile=sparc-opcode.h - depfile=sparc-dep.c - ;; -umax) - pinsnfile=ns32k-pinsn.c - opcodefile=ns32k-opcode.h - ;; -sparc|sun4) - case $os in - os4|sunos4) - paramfile=m-sun4os4.h - esac - pinsnfile=sparc-pinsn.c - opcodefile=sparc-opcode.h - depfile=sparc-dep.c - paramfile=m-sparc.h - ;; -test) - paramfile=one - pinsnfile=three - opcodefile=four - ;; -*) - echo "Unknown machine type: \`$machine'" - echo "Available types:" - echo m-*.h | sed 's/m-//g' | sed 's/\.h//g' - exit 1 -esac - -files="$paramfile $pinsnfile $opcodefile $depfile" -links="param.h pinsn.c opcode.h dep.c" - -while [ -n "$files" ] -do - # set file to car of files, files to cdr of files - set $files; file=$1; shift; files=$* - set $links; link=$1; shift; links=$* - - if [ "$file" != skip ] - then - if [ ! -r $file ] - then - echo "$progname: cannot create a link \`$link'," - echo "since the file \`$file' does not exist." - exit 1 - fi - - rm -f $link config.status - # Make a symlink if possible, otherwise try a hard link - ln -s $file $link 2>/dev/null || ln $file $link - - if [ ! -r $link ] - then - echo "$progname: unable to link \`$link' to \`$file'." - exit 1 - fi - echo "Linked \`$link' to \`$file'." - fi -done - -echo "Links are now set up for use with a $machine." \ - | tee config.status -exit 0 - -@ - - -1.1 -log -@Initial revision -@ -text -@d53 4 -@ diff --git a/gdb/RCS/core.c,v b/gdb/RCS/core.c,v deleted file mode 100644 index f63081d..0000000 --- a/gdb/RCS/core.c,v +++ /dev/null @@ -1,651 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.4 -date 89.03.27.18.39.18; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.02.10.01.39.45; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.22.33; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.49.56; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@Unisoft Assholes changes for user.ps. Avoid sys/fcntl.h. -@ -text -@/* Work with core dump and executable files, for GDB. - Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#include "gdbcore.h" - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#endif - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#else -#include <a.out.h> -#endif - -#ifndef N_MAGIC -#ifdef COFF_FORMAT -#define N_MAGIC(exec) ((exec).magic) -#else -#define N_MAGIC(exec) ((exec).a_magic) -#endif -#endif - -#include <stdio.h> -#include <signal.h> -#include <sys/param.h> -#include <sys/dir.h> -#include <sys/file.h> -#include <sys/stat.h> - -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#include <sys/seg.h> /* Required for user.ps */ -#include <sys/time.h> /* '' */ -#include <sys/mmu.h> /* '' */ -#include <sys/reg.h> -#define mc68881 /* Required to get float in user.ps */ -#endif - -#ifdef UMAX_CORE -#include <sys/ptrace.h> -#else -#include <sys/user.h> -#endif - -#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 */ - -#ifndef COFF_FORMAT -#define AOUTHDR struct exec -#endif - -extern char *sys_siglist[]; - -extern core_file_command (), exec_file_command (); - -/* Hook for `exec_file_command' command to call. */ - -void (*exec_file_display_hook) (); - -/* File names of core file and executable file. */ - -char *corefile; -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. */ - -int corechan; -int execchan; - -/* Last modification time of executable file. - Also used in source.c to compare against mtime of a source file. */ - -int exec_mtime; - -/* Virtual addresses of bounds of the two areas of memory in the core file. */ - -CORE_ADDR data_start; -CORE_ADDR data_end; -CORE_ADDR stack_start; -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. */ - -CORE_ADDR text_start; -CORE_ADDR text_end; - -CORE_ADDR exec_data_start; -CORE_ADDR exec_data_end; - -/* Address in executable file of start of text area data. */ - -int text_offset; - -/* Address in executable file of start of data area data. */ - -int exec_data_offset; - -/* Address in core file of start of data area data. */ - -int data_offset; - -/* Address in core file of start of stack area data. */ - -int stack_offset; - -#ifdef COFF_FORMAT -/* various coff data structures */ - -FILHDR file_hdr; -SCNHDR text_hdr; -SCNHDR data_hdr; - -#endif /* not COFF_FORMAT */ - -/* a.out header saved in core file. */ - -AOUTHDR core_aouthdr; - -/* a.out header of exec file. */ - -AOUTHDR exec_aouthdr; - -void validate_files (); -unsigned int register_addr (); - -/* Call this to specify the hook for exec_file_command to call back. - This is called from the x-window display code. */ - -void -specify_exec_file_hook (hook) - void (*hook) (); -{ - exec_file_display_hook = hook; -} - -/* The exec file must be closed before running an inferior. - If it is needed again after the inferior dies, it must - be reopened. */ - -void -close_exec_file () -{ - if (execchan >= 0) - close (execchan); - execchan = -1; -} - -void -reopen_exec_file () -{ - if (execchan < 0 && execfile != 0) - { - char *filename = concat (execfile, "", ""); - exec_file_command (filename, 0); - free (filename); - } -} - -/* If we have both a core file and an exec file, - print a warning if they don't go together. - This should really check that the core file came - from that exec file, but I don't know how to do it. */ - -void -validate_files () -{ - if (execfile != 0 && corefile != 0) - { - struct stat st_core; - - fstat (corechan, &st_core); - - if (N_MAGIC (core_aouthdr) != 0 - && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr)) - printf ("Warning: core file does not match specified executable file.\n"); - else if (exec_mtime > st_core.st_mtime) - printf ("Warning: exec file is newer than core file.\n"); - } -} - -/* Return the name of the executable file as a string. - ERR nonzero means get error if there is none specified; - otherwise return 0 in that case. */ - -char * -get_exec_file (err) - int err; -{ - if (err && execfile == 0) - error ("No executable file specified.\n\ -Use the \"exec-file\" and \"symbol-file\" commands."); - return execfile; -} - -int -have_core_file_p () -{ - return corefile != 0; -} - -static void -files_info () -{ - char *symfile; - extern char *get_sym_file (); - - if (execfile) - printf ("Executable file \"%s\".\n", execfile); - else - printf ("No executable file\n"); - - if (corefile) - printf ("Core dump file \"%s\".\n", corefile); - else - printf ("No core dump file\n"); - - if (have_inferior_p ()) - printf ("Using the running image of the program, rather than these files.\n"); - - symfile = get_sym_file (); - if (symfile != 0) - printf ("Symbols from \"%s\".\n", symfile); - - if (! have_inferior_p ()) - { - if (execfile) - { - printf ("Text segment in executable from 0x%x to 0x%x.\n", - text_start, text_end); - printf ("Data segment in executable from 0x%x to 0x%x.\n", - exec_data_start, exec_data_end); - if (corefile) - printf("(But since we have a core file, we're using...)\n"); - } - if (corefile) - { - printf ("Data segment in core file from 0x%x to 0x%x.\n", - data_start, data_end); - printf ("Stack segment in core file from 0x%x to 0x%x.\n", - stack_start, stack_end); - } - } -} - -/* Read "memory data" from core file and/or executable file. - Returns zero if successful, 1 if xfer_core_file failed, errno value if - ptrace failed. */ - -int -read_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - if (have_inferior_p ()) - return read_inferior_memory (memaddr, myaddr, len); - else - return xfer_core_file (memaddr, myaddr, len); -} - -/* Write LEN bytes of data starting at address MYADDR - into debugged program memory at address MEMADDR. - Returns zero if successful, or an errno value if ptrace failed. */ - -int -write_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - if (have_inferior_p ()) - return write_inferior_memory (memaddr, myaddr, len); - else - error ("Can write memory only when program being debugged is running."); -} - -/* Read from the program's memory (except for inferior processes). - This function is misnamed, since it only reads, never writes; and - since it will use the core file and/or executable file as necessary. - - It should be extended to write as well as read, FIXME, for patching files. - - Return 0 if address could be read, 1 if not. */ - -int -xfer_core_file (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - register int i; - register int val; - int xferchan; - char **xferfile; - int fileptr; - int returnval = 0; - - while (len > 0) - { - xferfile = 0; - xferchan = 0; - - /* Determine which file the next bunch of addresses reside in, - and where in the file. Set the file's read/write pointer - to point at the proper place for the desired address - and set xferfile and xferchan for the correct file. - - If desired address is nonexistent, leave them zero. - - i is set to the number of bytes that can be handled - along with the next address. - - We put the most likely tests first for efficiency. */ - - /* Note that if there is no core file - data_start and data_end are equal. */ - if (memaddr >= data_start && memaddr < data_end) - { - i = min (len, data_end - memaddr); - fileptr = memaddr - data_start + data_offset; - xferfile = &corefile; - xferchan = corechan; - } - /* Note that if there is no core file - stack_start and stack_end are equal. */ - else if (memaddr >= stack_start && memaddr < stack_end) - { - i = min (len, stack_end - memaddr); - fileptr = memaddr - stack_start + stack_offset; - xferfile = &corefile; - xferchan = corechan; - } - else if (corechan < 0 - && memaddr >= exec_data_start && memaddr < exec_data_end) - { - i = min (len, exec_data_end - memaddr); - fileptr = memaddr - exec_data_start + exec_data_offset; - xferfile = &execfile; - xferchan = execchan; - } - else if (memaddr >= text_start && memaddr < text_end) - { - i = min (len, text_end - memaddr); - fileptr = memaddr - text_start + text_offset; - xferfile = &execfile; - xferchan = execchan; - } - else if (memaddr < text_start) - { - i = min (len, text_start - memaddr); - } - else if (memaddr >= text_end - && memaddr < (corechan >= 0? data_start : exec_data_start)) - { - i = min (len, data_start - memaddr); - } - else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end) - && memaddr < stack_start) - { - i = min (len, stack_start - memaddr); - } - else if (memaddr >= stack_end && stack_end != 0) - { - i = min (len, - memaddr); - } - else - { - /* Address did not classify into one of the known ranges. - This could be because data_start != exec_data_start - or data_end similarly. */ - abort(); - } - - /* Now we know which file to use. - Set up its pointer and transfer the data. */ - if (xferfile) - { - if (*xferfile == 0) - if (xferfile == &execfile) - error ("No program file to examine."); - else - error ("No core dump file or running program to examine."); - val = lseek (xferchan, fileptr, 0); - if (val < 0) - perror_with_name (*xferfile); - val = myread (xferchan, myaddr, i); - if (val < 0) - perror_with_name (*xferfile); - } - /* If this address is for nonexistent memory, - read zeros if reading, or do nothing if writing. - (FIXME we never write.) */ - else - { - bzero (myaddr, i); - returnval = 1; - } - - memaddr += i; - myaddr += i; - len -= i; - } - return returnval; -} - -/* My replacement for the read system call. - Used like `read' but keeps going if `read' returns too soon. */ - -int -myread (desc, addr, len) - int desc; - char *addr; - int len; -{ - register int val; - int orglen = len; - - while (len > 0) - { - val = read (desc, addr, len); - if (val < 0) - return val; - if (val == 0) - return orglen - len; - len -= val; - addr += val; - } - return orglen; -} - -#ifdef REGISTER_U_ADDR - -/* Return the address in the core dump or inferior of register REGNO. - BLOCKEND is the address of the end of the user structure. */ - -unsigned int -register_addr (regno, blockend) - int regno; - int blockend; -{ - int addr; - - if (regno < 0 || regno >= NUM_REGS) - error ("Invalid register number %d.", regno); - - REGISTER_U_ADDR (addr, blockend, regno); - - return addr; -} - -#endif /* REGISTER_U_ADDR */ - -void -_initialize_core() -{ - corechan = -1; - execchan = -1; - corefile = 0; - execfile = 0; - exec_file_display_hook = 0; - - text_start = 0; - text_end = 0; - data_start = 0; - data_end = 0; - exec_data_start = 0; - exec_data_end = 0; - stack_start = STACK_END_ADDR; - stack_end = STACK_END_ADDR; - - add_com ("core-file", class_files, core_file_command, - "Use FILE as core dump for examining memory and registers.\n\ -No arg means have no core file."); - add_com ("exec-file", class_files, exec_file_command, - "Use FILE as program for getting contents of pure memory.\n\ -If FILE cannot be found as specified, your execution directory path\n\ -is searched for a command of that name.\n\ -No arg means have no executable file."); - add_info ("files", files_info, "Names of files being debugged."); -} - -@ - - -1.3 -log -@Fix up "info files" some more, to give more information. -Rearrange the tests in xfer_core_file to avoid dependencies -between data_start and exec_data_start, and for efficiency -and add an abort() to test correctness. (If you take out -never mind...) -@ -text -@d27 1 -a27 1 -#include <sys/fcntl.h> -d50 10 -@ - - -1.2 -log -@Create gdbcore.h for externally visible variables; -spiff up the "info files" output to make it easier to read and more -informative. -@ -text -@d250 4 -d257 4 -a260 7 - printf ("Data segment in core file from 0x%x to 0x%x.\nStack segment in core file from 0x%x to 0x%x.\n", - data_start, data_end, stack_start, stack_end); - } - else if (execfile) - { - printf ("Data segment in executable from 0x%x to 0x%x.\n", - exec_data_start, exec_data_end); -d297 3 -a299 1 -/* Return 0 if address could be read, 1 if not. */ -d301 4 -d327 1 -d329 1 -d331 3 -a333 1 - along with the next address. */ -a334 17 - if (memaddr < text_start) - { - i = min (len, text_start - memaddr); - } - else if (memaddr >= text_end && memaddr < data_start) - { - i = min (len, data_start - memaddr); - } - else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end) - && memaddr < stack_start) - { - i = min (len, stack_start - memaddr); - } - else if (memaddr >= stack_end && stack_end != 0) - { - i = min (len, - memaddr); - } -d337 1 -a337 1 - else if (memaddr >= data_start && memaddr < data_end) -d368 25 -d411 2 -a412 1 - read zeros if reading, or do nothing if writing. */ -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987 Free Software Foundation, Inc. -d23 1 -d35 1 -d43 1 -d231 4 -a234 1 - if (corefile == 0) -a235 2 - else - printf ("Core dump file \"%s\".\n", corefile); -d242 1 -a242 1 - printf ("Symbols loaded from \"%s\".\n", symfile); -d248 1 -a248 1 - printf ("Text segment from 0x%x to 0x%x.\n", -d253 1 -a253 1 - printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n", -d256 1 -a256 1 - else -@ diff --git a/gdb/RCS/dbxread.c,v b/gdb/RCS/dbxread.c,v deleted file mode 100644 index eb9d1cd..0000000 --- a/gdb/RCS/dbxread.c,v +++ /dev/null @@ -1,4610 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.18.41.32; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.38.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.30.11; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Avoid sys/fcntl.h. -@ -text -@/* Read dbx symbol tables and convert to internal format, for GDB. - Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "param.h" - -#ifdef READ_DBX_FORMAT - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#define L_SET 0 -#define L_INCR 1 -#endif - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#include "stab.gnu.h" -#else -#include <a.out.h> -#include <stab.h> -#endif - -/* - * Define specifically gnu symbols here. - */ - -/* The following type indicates the definition of a symbol as being - an indirect reference to another symbol. The other symbol - appears as an undefined reference, immediately following this symbol. - - Indirection is asymmetrical. The other symbol's value will be used - to satisfy requests for the indirect symbol, but not vice versa. - If the other symbol does not have a definition, libraries will - be searched to find a definition. */ -#ifndef N_INDR -#define N_INDR 0xa -#endif - -/* The following symbols refer to set elements. - All the N_SET[ATDB] symbols with the same name form one set. - Space is allocated for the set in the text section, and each set - element's value is stored into one word of the space. - The first word of the space is the length of the set (number of elements). - - The address of the set is made into an N_SETV symbol - whose name is the same as the name of the set. - This symbol acts like a N_DATA global symbol - in that it can satisfy undefined external references. */ - -#ifndef N_SETA -#define N_SETA 0x14 /* Absolute set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETT -#define N_SETT 0x16 /* Text set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETD -#define N_SETD 0x18 /* Data set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -#ifndef N_SETB -#define N_SETB 0x1A /* Bss set element symbol */ -#endif /* This is input to LD, in a .o file. */ - -/* Macros dealing with the set element symbols defined in a.out.h */ -#define SET_ELEMENT_P(x) ((x)>=N_SETA&&(x)<=(N_SETB|N_EXT)) -#define TYPE_OF_SET_ELEMENT(x) ((x)-N_SETA+N_ABS) - -#ifndef N_SETV -#define N_SETV 0x1C /* Pointer to set vector in data area. */ -#endif /* This is output from LD. */ - -#ifndef N_WARNING -#define N_WARNING 0x1E /* Warning message to print if file included */ -#endif /* This is input to ld */ - -#ifndef __GNU_STAB__ - -/* Line number for the data section. This is to be used to describe - the source location of a variable declaration. */ -#ifndef N_DSLINE -#define N_DSLINE (N_SLINE+N_DATA-N_TEXT) -#endif - -/* Line number for the bss section. This is to be used to describe - the source location of a variable declaration. */ -#ifndef N_BSLINE -#define N_BSLINE (N_SLINE+N_BSS-N_TEXT) -#endif - -#endif /* not __GNU_STAB__ */ - -#include <stdio.h> -#include <obstack.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/stat.h> -#include "defs.h" -#include "symtab.h" - -#ifndef COFF_FORMAT -#define AOUTHDR struct exec -#endif - -static void add_symbol_to_list (); -static void read_dbx_symtab (); -static void process_one_symbol (); -static void free_all_psymbols (); -static struct type *read_type (); -static struct type *read_range_type (); -static struct type *read_enum_type (); -static struct type *read_struct_type (); -static struct type *read_array_type (); -static long read_number (); -static void finish_block (); -static struct blockvector *make_blockvector (); -static struct symbol *define_symbol (); -static void start_subfile (); -static int hashname (); -static void hash_symsegs (); - -extern struct symtab *read_symsegs (); -extern void free_all_symtabs (); -extern void free_all_psymtabs (); -extern void free_inclink_symtabs (); - -/* C++ */ -static struct type **read_args(); - -/* Macro to determine which symbols to ignore when reading the first symbol - of a file. Some machines override this definition. */ -#ifdef N_NSYMS -#ifndef IGNORE_SYMBOL -/* This code is used on Ultrix systems. Ignore it */ -#define IGNORE_SYMBOL(type) (type == N_NSYMS) -#endif -#else -#ifndef IGNORE_SYMBOL -/* Don't ignore any symbols. */ -#define IGNORE_SYMBOL(type) (0) -#endif -#endif /* not N_NSYMS */ - -/* Macro for number of symbol table entries (in usual a.out format). - Some machines override this definition. */ -#ifndef NUMBER_OF_SYMBOLS -#ifdef COFF_HEADER -#define NUMBER_OF_SYMBOLS \ - ((COFF_HEADER(hdr) ? hdr.coffhdr.filehdr.f_nsyms : hdr.a_syms) / \ - sizeof (struct nlist)) -#else -#define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist)) -#endif -#endif - -/* Macro for file-offset of symbol table (in usual a.out format). */ -#ifndef SYMBOL_TABLE_OFFSET -#define SYMBOL_TABLE_OFFSET N_SYMOFF (hdr) -#endif - -/* Macro for file-offset of string table (in usual a.out format). */ -#ifndef STRING_TABLE_OFFSET -#define STRING_TABLE_OFFSET (N_SYMOFF (hdr) + hdr.a_syms) -#endif - -/* Macro to store the length of the string table data in INTO. */ -#ifndef READ_STRING_TABLE_SIZE -#define READ_STRING_TABLE_SIZE(INTO) \ -{ val = myread (desc, &INTO, sizeof INTO); \ - if (val < 0) perror_with_name (name); } -#endif - -/* Macro to declare variables to hold the file's header data. */ -#ifndef DECLARE_FILE_HEADERS -#define DECLARE_FILE_HEADERS AOUTHDR hdr -#endif - -/* Macro to read the header data from descriptor DESC and validate it. - NAME is the file name, for error messages. */ -#ifndef READ_FILE_HEADERS -#ifdef HEADER_SEEK_FD -#define READ_FILE_HEADERS(DESC, NAME) \ -{ HEADER_SEEK_FD (DESC); \ - val = myread (DESC, &hdr, sizeof hdr); \ - if (val < 0) perror_with_name (NAME); \ - if (N_BADMAG (hdr)) \ - error ("File \"%s\" not in executable format.", NAME); } -#else -#define READ_FILE_HEADERS(DESC, NAME) \ -{ val = myread (DESC, &hdr, sizeof hdr); \ - if (val < 0) perror_with_name (NAME); \ - if (N_BADMAG (hdr)) \ - error ("File \"%s\" not in executable format.", NAME); } -#endif -#endif - -/* Macro for size of text segment */ -#ifndef SIZE_OF_TEXT_SEGMENT -#define SIZE_OF_TEXT_SEGMENT hdr.a_text -#endif - -/* Macro for name of symbol to indicate a file compiled with gcc. */ -#ifndef GCC_COMPILED_FLAG_SYMBOL -#define GCC_COMPILED_FLAG_SYMBOL "gcc_compiled." -#endif - -/* Chain of symtabs made from reading the file's symsegs. - These symtabs do not go into symtab_list themselves, - but the information is copied from them when appropriate - to make the symtabs that will exist permanently. */ - -static struct symtab *symseg_chain; - -/* Symseg symbol table for the file whose data we are now processing. - It is one of those in symseg_chain. Or 0, for a compilation that - has no symseg. */ - -static struct symtab *current_symseg; - -/* Name of source file whose symbol data we are now processing. - This comes from a symbol of type N_SO. */ - -static char *last_source_file; - -/* Core address of start of text of current source file. - This too comes from the N_SO symbol. */ - -static CORE_ADDR last_source_start_addr; - -/* End of the text segment of the executable file, - as found in the symbol _etext. */ - -static CORE_ADDR end_of_text_addr; - -/* The list of sub-source-files within the current individual compilation. - Each file gets its own symtab with its own linetable and associated info, - but they all share one blockvector. */ - -struct subfile -{ - struct subfile *next; - char *name; - struct linetable *line_vector; - int line_vector_length; - int line_vector_index; - int prev_line_number; -}; - -static struct subfile *subfiles; - -static struct subfile *current_subfile; - -/* Count symbols as they are processed, for error messages. */ - -static int symnum; - -/* Vector of types defined so far, indexed by their dbx type numbers. - (In newer sun systems, dbx uses a pair of numbers in parens, - as in "(SUBFILENUM,NUMWITHINSUBFILE)". Then these numbers must be - translated through the type_translations hash table to get - the index into the type vector.) */ - -static struct typevector *type_vector; - -/* Number of elements allocated for type_vector currently. */ - -static int type_vector_length; - -/* Vector of line number information. */ - -static struct linetable *line_vector; - -/* Index of next entry to go in line_vector_index. */ - -static int line_vector_index; - -/* Last line number recorded in the line vector. */ - -static int prev_line_number; - -/* Number of elements allocated for line_vector currently. */ - -static int line_vector_length; - -/* Hash table of global symbols whose values are not known yet. - They are chained thru the SYMBOL_VALUE, since we don't - have the correct data for that slot yet. */ - -#define HASHSIZE 127 -static struct symbol *global_sym_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. */ - -#define PENDINGSIZE 100 - -struct pending -{ - struct pending *next; - int nsyms; - struct symbol *symbol[PENDINGSIZE]; -}; - -/* List of free `struct pending' structures for reuse. */ -struct pending *free_pendings; - -/* 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 *local_symbols; /* everything local to lexical context */ - -/* Stack representing unclosed lexical contexts - (that will become blocks, eventually). */ - -struct context_stack -{ - struct pending *locals; - struct pending_block *old_blocks; - struct symbol *name; - CORE_ADDR start_addr; - int depth; -}; - -struct context_stack *context_stack; - -/* Index of first unused entry in context stack. */ -int context_stack_depth; - -/* Currently allocated size of context stack. */ - -int context_stack_size; - -/* 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 first_object_file_end; /* From blockframe.c */ - -/* File name symbols were loaded from. */ - -static char *symfile; - -/* Low and high symbol values (inclusive) for the global variable - entries in the symbol file. */ - -static int first_global_sym, last_global_sym; - -/* Partial symbol list for all of the global and static symbols found - in a file */ - -struct partial_symbol *global_psymbols, *static_psymbols; -int global_psymbols_allocated, static_psymbols_allocated; - -/* Position for next psymbol to be added */ - -struct partial_symbol *next_ps_global, *next_ps_static; - -/* Global variable which, when set, indicates that we are processing a - .o file compiled with gcc */ - -static unsigned char processing_gcc_compilation; - -static int -xxmalloc (n) -{ - int v = malloc (n); - if (v == 0) - abort (); - return v; -} - -/* Make a copy of the string at PTR with SIZE characters in the symbol obstack - (and add a null character at the end in the copy). - Returns the address of the copy. */ - -static char * -obsavestring (ptr, size) - char *ptr; - int size; -{ - register char *p = (char *) obstack_alloc (symbol_obstack, size + 1); - /* Open-coded bcopy--saves function call time. - These strings are usually short. */ - { - register char *p1 = ptr; - register char *p2 = p; - char *end = ptr + size; - while (p1 != end) - *p2++ = *p1++; - } - p[size] = 0; - return p; -} - -/* Concatenate strings S1, S2 and S3; return the new string. - Space is found in the symbol_obstack. */ - -static char * -obconcat (s1, s2, s3) - char *s1, *s2, *s3; -{ - register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; - register char *val = (char *) obstack_alloc (symbol_obstack, len); - strcpy (val, s1); - strcat (val, s2); - strcat (val, s3); - return val; -} - -/* Support for Sun changes to dbx symbol format */ - -/* For each identified header file, we have a table of types defined - in that header file. - - header_files maps header file names to their type tables. - It is a vector of n_header_files elements. - Each element describes one header file. - It contains a vector of types. - - Sometimes it can happen that the same header file produces - different results when included in different places. - This can result from conditionals or from different - things done before including the file. - When this happens, there are multiple entries for the file in this table, - one entry for each distinct set of results. - The entries are distinguished by the INSTANCE field. - The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is - used to match header-file references to their corresponding data. */ - -struct header_file -{ - char *name; /* Name of header file */ - int instance; /* Numeric code distinguishing instances - of one header file that produced - different results when included. - It comes from the N_BINCL or N_EXCL. */ - struct type **vector; /* Pointer to vector of types */ - int length; /* Allocated length (# elts) of that vector */ -}; - -static struct header_file *header_files; - -static int n_header_files; - -static int n_allocated_header_files; - -/* During initial symbol readin, we need to have a structure to keep - track of which psymtabs have which bincls in them. This structure - is used during readin to setup the list of dependencies within each - partial symbol table. */ - -struct header_file_location -{ - char *name; /* Name of header file */ - int instance; /* See above */ - struct partial_symtab *pst; /* Partial symtab that has the - BINCL/EINCL defs for this file */ -}; - -/* The actual list and controling variables */ -static struct header_file_location *bincl_list, *next_bincl; -static int bincls_allocated; - -/* Within each object file, various header files are assigned numbers. - A type is defined or referred to with a pair of numbers - (FILENUM,TYPENUM) where FILENUM is the number of the header file - and TYPENUM is the number within that header file. - TYPENUM is the index within the vector of types for that header file. - - FILENUM == 1 is special; it refers to the main source of the object file, - and not to any header file. FILENUM != 1 is interpreted by looking it up - in the following table, which contains indices in header_files. */ - -static int *this_object_header_files; - -static int n_this_object_header_files; - -static int n_allocated_this_object_header_files; - -/* When a header file is getting special overriding definitions - for one source file, record here the header_files index - of its normal definition vector. - At other times, this is -1. */ - -static int header_file_prev_index; - -/* At the start of reading dbx symbols, allocate our tables. */ - -static void -init_header_files () -{ - n_allocated_header_files = 10; - header_files = (struct header_file *) xxmalloc (10 * sizeof (struct header_file)); - n_header_files = 0; - - n_allocated_this_object_header_files = 10; - this_object_header_files = (int *) xxmalloc (10 * sizeof (int)); -} - -/* At the end of reading dbx symbols, free our tables. */ - -static void -free_header_files () -{ - register int i; - for (i = 0; i < n_header_files; i++) - free (header_files[i].name); - if (header_files) free (header_files); - if (this_object_header_files) - free (this_object_header_files); -} - -/* Called at the start of each object file's symbols. - Clear out the mapping of header file numbers to header files. */ - -static void -new_object_header_files () -{ - /* Leave FILENUM of 0 free for builtin types and this file's types. */ - n_this_object_header_files = 1; - header_file_prev_index = -1; -} - -/* Add header file number I for this object file - at the next successive FILENUM. */ - -static void -add_this_object_header_file (i) - int i; -{ - if (n_this_object_header_files == n_allocated_this_object_header_files) - { - n_allocated_this_object_header_files *= 2; - this_object_header_files - = (int *) xrealloc (this_object_header_files, - n_allocated_this_object_header_files * sizeof (int)); - } - - this_object_header_files[n_this_object_header_files++] = i; -} - -/* Add to this file an "old" header file, one already seen in - a previous object file. NAME is the header file's name. - INSTANCE is its instance code, to select among multiple - symbol tables for the same header file. */ - -static void -add_old_header_file (name, instance) - char *name; - int instance; -{ - register struct header_file *p = header_files; - register int i; - - for (i = 0; i < n_header_files; i++) - if (!strcmp (p[i].name, name) && instance == p[i].instance) - { - add_this_object_header_file (i); - return; - } - error ("Invalid symbol data: \"repeated\" header file that hasn't been seen before, at symtab pos %d.", - symnum); -} - -/* Add to this file a "new" header file: definitions for its types follow. - NAME is the header file's name. - Most often this happens only once for each distinct header file, - but not necessarily. If it happens more than once, INSTANCE has - a different value each time, and references to the header file - use INSTANCE values to select among them. - - dbx output contains "begin" and "end" markers for each new header file, - but at this level we just need to know which files there have been; - so we record the file when its "begin" is seen and ignore the "end". */ - -static void -add_new_header_file (name, instance) - char *name; - int instance; -{ - register int i; - register struct header_file *p = header_files; - header_file_prev_index = -1; - -#if 0 - /* This code was used before I knew about the instance codes. - My first hypothesis is that it is not necessary now - that instance codes are handled. */ - - /* Has this header file a previous definition? - If so, make a new entry anyway so that this use in this source file - gets a separate entry. Later source files get the old entry. - Record here the index of the old entry, so that any type indices - not previously defined can get defined in the old entry as - well as in the new one. */ - - for (i = 0; i < n_header_files; i++) - if (!strcmp (p[i].name, name)) - { - header_file_prev_index = i; - } - -#endif - - /* Make sure there is room for one more header file. */ - - if (n_header_files == n_allocated_header_files) - { - n_allocated_header_files *= 2; - header_files = (struct header_file *) - xrealloc (header_files, - (n_allocated_header_files - * sizeof (struct header_file))); - } - - /* Create an entry for this header file. */ - - i = n_header_files++; - header_files[i].name = savestring (name, strlen(name)); - header_files[i].instance = instance; - header_files[i].length = 10; - header_files[i].vector - = (struct type **) xxmalloc (10 * sizeof (struct type *)); - bzero (header_files[i].vector, 10 * sizeof (struct type *)); - - add_this_object_header_file (i); -} - -/* Look up a dbx type-number pair. Return the address of the slot - where the type for that number-pair is stored. - The number-pair is in TYPENUMS. - - This can be used for finding the type associated with that pair - or for associating a new type with the pair. */ - -static struct type ** -dbx_lookup_type (typenums) - int typenums[2]; -{ - register int filenum = typenums[0], index = typenums[1]; - - if (filenum < 0 || filenum >= n_this_object_header_files) - error ("Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.", - filenum, index, symnum); - - if (filenum == 0) - { - /* Type is defined outside of header files. - Find it in this object file's type vector. */ - if (index >= type_vector_length) - { - type_vector_length *= 2; - type_vector = (struct typevector *) - xrealloc (type_vector, - (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *))); - bzero (&type_vector->type[type_vector_length / 2], - type_vector_length * sizeof (struct type *) / 2); - } - return &type_vector->type[index]; - } - else - { - register int real_filenum = this_object_header_files[filenum]; - register struct header_file *f; - - if (real_filenum >= n_header_files) - abort (); - - f = &header_files[real_filenum]; - - if (index >= f->length) - { - f->length *= 2; - f->vector = (struct type **) - xrealloc (f->vector, f->length * sizeof (struct type *)); - bzero (&f->vector[f->length / 2], - f->length * sizeof (struct type *) / 2); - } - return &f->vector[index]; - } -} - -/* Make sure there is a type allocated for type numbers TYPENUMS - and return the type object. - This can create an empty (zeroed) type object. */ - -static struct type * -dbx_alloc_type (typenums) - int typenums[2]; -{ - register struct type **type_addr = dbx_lookup_type (typenums); - 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_VPTR_FIELDNO (type) = -1; - *type_addr = type; - } - return type; -} - -#if 0 -static struct type ** -explicit_lookup_type (real_filenum, index) - int real_filenum, index; -{ - register struct header_file *f = &header_files[real_filenum]; - - if (index >= f->length) - { - f->length *= 2; - f->vector = (struct type **) - xrealloc (f->vector, f->length * sizeof (struct type *)); - bzero (&f->vector[f->length / 2], - f->length * sizeof (struct type *) / 2); - } - return &f->vector[index]; -} -#endif - -/* 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; -{ - /* We keep PENDINGSIZE symbols in each link of the list. - If we don't have a link with room in it, add a new link. */ - if (*listhead == 0 || (*listhead)->nsyms == PENDINGSIZE) - { - register struct pending *link; - if (free_pendings) - { - link = free_pendings; - free_pendings = link->next; - } - else - link = (struct pending *) xxmalloc (sizeof (struct pending)); - - link->next = *listhead; - *listhead = link; - link->nsyms = 0; - } - - (*listhead)->symbol[(*listhead)->nsyms++] = symbol; -} - -/* At end of reading syms, or in case of quit, - really free as many `struct pending's as we can easily find. */ - -static void -really_free_pendings () -{ - struct pending *next, *next1; - struct pending_block *bnext, *bnext1; - - for (next = free_pendings; next; next = next1) - { - next1 = next->next; - free (next); - } - free_pendings = 0; - - for (bnext = pending_blocks; bnext; bnext = bnext1) - { - bnext1 = bnext->next; - free (bnext); - } - pending_blocks = 0; - - for (next = file_symbols; next; next = next1) - { - next1 = next->next; - free (next); - } - for (next = global_symbols; next; next = next1) - { - next1 = next->next; - free (next); - } -} - -/* Take one of the lists of symbols and make a block from it. - Keep the order the symbols have in the list (reversed from the input file). - 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; i += next->nsyms, next = next->next); - - 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) - { - register int j; - for (j = next->nsyms - 1; j >= 0; j--) - BLOCK_SYM (block, --i) = next->symbol[j]; - } - - BLOCK_START (block) = start; - BLOCK_END (block) = end; - BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */ - BLOCK_GCC_COMPILED (block) = processing_gcc_compilation; - - /* 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; - next->next = free_pendings; - free_pendings = 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. */ - - /* Allocate in the symbol_obstack to save time. - It wastes a little space. */ - pblock = (struct pending_block *) - obstack_alloc (symbol_obstack, - 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; - -#if 0 /* Now we make the links in the obstack, so don't free them. */ - /* Now free the links of the list, and empty the list. */ - - for (next = pending_blocks; next; next = next1) - { - next1 = next->next; - free (next); - } -#endif - pending_blocks = 0; - - return blockvector; -} - -/* Manage the vector of line numbers. */ - -static void -record_line (line, pc) - int line; - CORE_ADDR pc; -{ - struct linetable_entry *e; - /* Ignore the dummy line number in libg.o */ - - if (line == 0xffff) - return; - - /* Make sure line vector is big enough. */ - - if (line_vector_index + 1 >= line_vector_length) - { - line_vector_length *= 2; - line_vector = (struct linetable *) - xrealloc (line_vector, - (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry))); - current_subfile->line_vector = line_vector; - } - - e = line_vector->item + line_vector_index++; - e->line = line; e->pc = pc; -} - -/* Start a new symtab for a new source file. - This is called when a dbx symbol of type N_SO is seen; - it indicates the start of data for one original source file. */ - -static void -start_symtab (name, start_addr) - char *name; - CORE_ADDR start_addr; -{ - register struct symtab *s; - - last_source_file = name; - last_source_start_addr = start_addr; - file_symbols = 0; - global_symbols = 0; - within_function = 0; - - /* Context stack is initially empty, with room for 10 levels. */ - context_stack - = (struct context_stack *) xxmalloc (10 * sizeof (struct context_stack)); - context_stack_size = 10; - context_stack_depth = 0; - - new_object_header_files (); - - for (s = symseg_chain; s; s = s->next) - if (s->ldsymoff == symnum * sizeof (struct nlist)) - break; - current_symseg = s; - if (s != 0) - return; - - type_vector_length = 160; - type_vector = (struct typevector *) - xxmalloc (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (type_vector->type, type_vector_length * sizeof (struct type *)); - - /* Initialize the list of sub source files with one entry - for this file (the top-level source file). */ - - subfiles = 0; - current_subfile = 0; - start_subfile (name); - - /* Set default for compiler to pcc; assume that we aren't processing - a gcc compiled file until proved otherwise. */ - - processing_gcc_compilation = 0; -} - -/* Handle an N_SOL symbol, which indicates the start of - code that came from an included (or otherwise merged-in) - source file with a different name. */ - -static void -start_subfile (name) - char *name; -{ - register struct subfile *subfile; - - /* Save the current subfile's line vector data. */ - - if (current_subfile) - { - current_subfile->line_vector_index = line_vector_index; - current_subfile->line_vector_length = line_vector_length; - current_subfile->prev_line_number = prev_line_number; - } - - /* See if this subfile is already known as a subfile of the - current main source file. */ - - for (subfile = subfiles; subfile; subfile = subfile->next) - { - if (!strcmp (subfile->name, name)) - { - line_vector = subfile->line_vector; - line_vector_index = subfile->line_vector_index; - line_vector_length = subfile->line_vector_length; - prev_line_number = subfile->prev_line_number; - current_subfile = subfile; - return; - } - } - - /* This subfile is not known. Add an entry for it. */ - - line_vector_index = 0; - line_vector_length = 1000; - prev_line_number = -2; /* Force first line number to be explicit */ - line_vector = (struct linetable *) - xxmalloc (sizeof (struct linetable) - + line_vector_length * sizeof (struct linetable_entry)); - - /* Make an entry for this subfile in the list of all subfiles - of the current main source file. */ - - subfile = (struct subfile *) xxmalloc (sizeof (struct subfile)); - subfile->next = subfiles; - subfile->name = savestring (name, strlen (name)); - subfile->line_vector = line_vector; - subfiles = subfile; - current_subfile = subfile; -} - -/* 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 (end_addr) - CORE_ADDR end_addr; -{ - register struct symtab *symtab; - register struct blockvector *blockvector; - register struct subfile *subfile; - register struct linetable *lv; - struct subfile *nextsub; - - if (current_symseg != 0) - { - last_source_file = 0; - current_symseg = 0; - return; - } - - /* Finish the lexical context of the last function in the file; - pop the context stack. */ - - if (context_stack_depth > 0) - { - register struct context_stack *cstk; - context_stack_depth--; - cstk = &context_stack[context_stack_depth]; - /* Make a block for the local symbols within. */ - finish_block (cstk->name, &local_symbols, cstk->old_blocks, - cstk->start_addr, end_addr); - } - - /* Finish defining all the blocks of this symtab. */ - finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr); - finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr); - blockvector = make_blockvector (); - - current_subfile->line_vector_index = line_vector_index; - - /* Now create the symtab objects proper, one for each subfile. */ - /* (The main file is one of them.) */ - - for (subfile = subfiles; subfile; subfile = nextsub) - { - symtab = (struct symtab *) xxmalloc (sizeof (struct symtab)); - symtab->free_ptr = 0; - - /* Fill in its components. */ - symtab->blockvector = blockvector; - type_vector->length = type_vector_length; - symtab->typevector = type_vector; - symtab->free_code = free_linetable; - if (subfile->next == 0) - symtab->free_ptr = (char *) type_vector; - - symtab->filename = subfile->name; - lv = subfile->line_vector; - lv->nitems = subfile->line_vector_index; - symtab->linetable = (struct linetable *) - xrealloc (lv, (sizeof (struct linetable) - + lv->nitems * sizeof (struct linetable_entry))); - symtab->nlines = 0; - symtab->line_charpos = 0; - - /* Link the new symtab into the list of such. */ - symtab->next = symtab_list; - symtab_list = symtab; - - nextsub = subfile->next; - free (subfile); - } - - type_vector = 0; - type_vector_length = -1; - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; -} - -#ifdef N_BINCL - -/* Handle the N_BINCL and N_EINCL symbol types - that act like N_SOL for switching source files - (different subfiles, as we call them) within one object file, - but using a stack rather than in an arbitrary order. */ - -struct subfile_stack -{ - struct subfile_stack *next; - char *name; - int prev_index; -}; - -struct subfile_stack *subfile_stack; - -static void -push_subfile () -{ - register struct subfile_stack *tem - = (struct subfile_stack *) xxmalloc (sizeof (struct subfile_stack)); - - tem->next = subfile_stack; - subfile_stack = tem; - if (current_subfile == 0 || current_subfile->name == 0) - abort (); - tem->name = current_subfile->name; - tem->prev_index = header_file_prev_index; -} - -static char * -pop_subfile () -{ - register char *name; - register struct subfile_stack *link = subfile_stack; - - if (link == 0) - abort (); - - name = link->name; - subfile_stack = link->next; - header_file_prev_index = link->prev_index; - free (link); - - return name; -} -#endif /* Have N_BINCL */ - -/* 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 *) xxmalloc (sizeof (struct misc_bunch)); - misc_bunch_index = 0; - new->next = misc_bunch; - misc_bunch = new; - } - misc_bunch->contents[misc_bunch_index].name = name; - misc_bunch->contents[misc_bunch_index].address = address; - 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; - } -} - -/* INCLINK nonzero means bunches are from an incrementally-linked file. - Add them to the existing bunches. - Otherwise INCLINK is zero, and we start from scratch. */ -static void -condense_misc_bunches (inclink) - int inclink; -{ - register int i, j; - register struct misc_bunch *bunch; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - if (inclink) - { - misc_function_vector - = (struct misc_function *) - xrealloc (misc_function_vector, (misc_count + misc_function_count) - * sizeof (struct misc_function)); - j = misc_function_count; - } - else - { - misc_function_vector - = (struct misc_function *) - xxmalloc (misc_count * sizeof (struct misc_function)); - j = 0; - } - - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - misc_function_vector[j] = bunch->contents[i]; - misc_function_vector[j].name - = obconcat (misc_function_vector[j].name - + (misc_function_vector[j].name[0] == '_' ? offset : 0), - "", ""); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - if (inclink) - misc_function_count += misc_count; - else - misc_function_count = j; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, misc_function_count, - 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; -{ - register int namediff; - - /* Compare the initial characters. */ - namediff = SYMBOL_NAME (*s1)[0] - SYMBOL_NAME (*s2)[0]; - if (namediff != 0) return namediff; - - /* If they match, compare the rest of the names. */ - 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_symtab_syms (); - -static void -sort_syms () -{ - register struct symtab *s; - - for (s = symtab_list; s; s = s->next) - sort_symtab_syms (s); -} - -static void -sort_symtab_syms (s) - register struct symtab *s; -{ - register struct blockvector *bv = BLOCKVECTOR (s); - int nbl = BLOCKVECTOR_NBLOCKS (bv); - int i; - register struct block *b; - - /* Note that in the following sort, we always make sure that - register debug symbol declarations always come before regular - debug symbol declarations (as might happen when parameters are - then put into registers by the compiler). We do this by a - correct compare in compare_symbols, and by the reversal of the - symbols if we don't sort. This works as long as a register debug - symbol always comes after a parameter debug symbol. */ - - /* This is no longer necessary; lookup_block_symbol now always - prefers some other declaration over a parameter declaration. We - still sort the thing (that is necessary), but we don't reverse it - if we shouldn't sort it. */ - - 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); - } -} - - -extern struct symtab *psymtab_to_symtab (); - -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to symtab_list. */ - -void -symbol_file_command (name) - char *name; -{ - register int desc; - DECLARE_FILE_HEADERS; - struct nlist *nlist; - char *stringtab; - long buffer; - register int val; - extern void close (); - struct cleanup *old_chain; - struct symtab *symseg; - struct stat statbuf; - - dont_repeat (); - - if (name == 0) - { - if ((symtab_list || partial_symtab_list) - && !query ("Discard symbol table? ", 0)) - error ("Not confirmed."); - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - return; - } - - if ((symtab_list || partial_symtab_list) - && !query ("Load new symbol table from \"%s\"? ", name)) - error ("Not confirmed."); - - { - 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); - - READ_FILE_HEADERS (desc, name); - - if (NUMBER_OF_SYMBOLS == 0) - { - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - printf ("%s has no symbol-table; symbols discarded.\n", name); - fflush (stdout); - do_cleanups (old_chain); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Now read the string table, all at once. */ - val = lseek (desc, STRING_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - stat (name, &statbuf); - READ_STRING_TABLE_SIZE (buffer); - if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); - - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val < 0) - perror_with_name (name); - - /* Throw away the old symbol table. */ - - if (symfile) - free (symfile); - symfile = 0; - free_all_symtabs (); - free_all_psymtabs (); - - /* Empty the hash table of global syms looking for values. */ - bzero (global_sym_chain, sizeof global_sym_chain); - -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ - symseg_chain = 0; -#endif - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - - /* Don't put these on the cleanup chain; they need to stick around - until the next call to symbol_file_command. *Then* we'll free - them. */ - free_header_files (); - init_header_files (); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - /* Now that the symbol table data of the executable file are all in core, - process them and define symbols accordingly. Closes desc. */ - - read_dbx_symtab (desc, stringtab, NUMBER_OF_SYMBOLS, 0, 0, 0); - - /* Go over the misc functions and install them in vector. */ - - condense_misc_bunches (0); - - /* 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)); - - /* Call to select_source_symtab used to be here; it was using too - much time. I'll make sure that list_sources can handle the lack - of current_source_symtab */ - - do_cleanups (old_chain); /* Descriptor closed here */ - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - while (symseg_chain) - { - register struct symtab *s = symseg_chain->next; - free (symseg_chain); - symseg_chain = s; - } - - if (!partial_symtab_list) - printf ("\n(no debugging symbols found)..."); - - printf ("done.\n"); - fflush (stdout); -} - -/* Return name of file symbols were loaded from, or 0 if none.. */ - -char * -get_sym_file () -{ - return symfile; -} - -/* Buffer for reading the symbol table entries. */ -static struct nlist symbuf[4096]; -static int symbuf_idx; -static int symbuf_end; - -/* I/O descriptor for reading the symbol table. */ -static int symtab_input_desc; - -/* The address of the string table - of the object file we are reading (as copied into core). */ -static char *stringtab_global; - -/* Refill the symbol table input buffer - and set the variables that control fetching entries from it. - Reports an error if no data available. - This function can read past the end of the symbol table - (into the string table) but this does no harm. */ - -static int -fill_symbuf () -{ - int nbytes = myread (symtab_input_desc, symbuf, sizeof (symbuf)); - if (nbytes <= 0) - error ("error or end of file reading symbol table"); - symbuf_end = nbytes / sizeof (struct nlist); - symbuf_idx = 0; - return 1; -} - -/* dbx allows the text of a symbol name to be continued into the - next symbol name! When such a continuation is encountered - (a \ at the end of the text of a name) - call this function to get the continuation. */ - -static char * -next_symbol_text () -{ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - symnum++; - return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global; -} - -/* - * Initializes storage for all of the partial symbols that will be - * created by read_dbx_symtab and subsidiaries. - */ -void -init_psymbol_list (total_symbols) - int total_symbols; -{ - /* Current best guess is that there are approximately a twentieth - of the total symbols (in a debugging file) are global or static - oriented symbols */ - global_psymbols_allocated = total_symbols / 10; - static_psymbols_allocated = total_symbols / 10; - next_ps_global = global_psymbols = (struct partial_symbol *) - xmalloc (global_psymbols_allocated * sizeof (struct partial_symbol)); - next_ps_static = static_psymbols = (struct partial_symbol *) - xmalloc (static_psymbols_allocated * sizeof (struct partial_symbol)); -} - -/* - * Initialize the list of bincls to contain none and have some - * allocated. - */ -static void -init_bincl_list (number) - int number; -{ - bincls_allocated = number; - next_bincl = bincl_list = (struct header_file_location *) - xmalloc (bincls_allocated * sizeof(struct header_file_location)); -} - -/* - * Add a bincl to the list. - */ -static void -add_bincl_to_list (pst, name, instance) - struct partial_symtab *pst; - char *name; - int instance; -{ - if (next_bincl >= bincl_list + bincls_allocated) - { - int offset = next_bincl - bincl_list; - bincls_allocated *= 2; - bincl_list = (struct header_file_location *) - xrealloc (bincl_list, - bincls_allocated * sizeof (struct header_file_location)); - next_bincl = bincl_list + offset; - } - next_bincl->pst = pst; - next_bincl->instance = instance; - next_bincl++->name = name; -} - -/* - * Given a name, value pair, find the corresponding - * bincl in the list. Return the partial symtab associated - * with that header_file_location. - */ -struct partial_symtab * -find_corresponding_bincl_psymtab (name, instance) - char *name; - int instance; -{ - struct header_file_location *bincl; - - for (bincl = bincl_list; bincl < next_bincl; bincl++) - if (bincl->instance == instance - && !strcmp (name, bincl->name)) - return bincl->pst; - - return (struct partial_symtab *) 0; -} - -/* - * Free the storage allocated for the bincl list. - */ -static void -free_bincl_list () -{ - free (bincl_list); - bincls_allocated = 0; -} - -static struct partial_symtab *start_psymtab (); -static void add_psymtab_dependency (); -static void end_psymtab(); - -/* Given pointers to an a.out symbol table in core containing dbx - style data, setup partial_symtab's describing each source file for - which debugging information is available. NLISTLEN is the number - of symbols in the symbol table. All symbol names are given as - offsets relative to STRINGTAB. - - I have no idea whether or not this routine should be setup to deal - with inclinks. It seems reasonable to me that they be dealt with - standardly, so I am not going to make a strong effort to deal with - them here. - */ - -static void process_symbol_for_psymtab (); - -static void -read_dbx_symtab (desc, stringtab, nlistlen, inclink, text_addr, text_size) - int desc; - register char *stringtab; - register int nlistlen; - int inclink; - unsigned text_addr; - int text_size; -{ - register char *namestring; - register struct symbol *sym, *prev; - int hash; - int num_object_files = 0; - int past_first_source_file = 0; - struct cleanup *old_chain; - int current_text_start, current_file_symbol_start; - struct pending *global_symbols, *static_symbols; - int nsl; /* Length of namestring, when needed */ - - /* Current partial symtab */ - struct partial_symtab *pst; - - /* List of current psymtab's include files */ - char **psymtab_include_list; - int includes_allocated; - int includes_used; - - /* Index within current psymtab dependency list */ - struct partial_symtab **dependency_list; - int dependencies_used, dependencies_allocated; - - /* Setup a define to deal cleanly with the underscore problem */ - -#ifdef NAMES_HAVE_UNDERSCORE -#define HASH_OFFSET 1 -#else -#define HASH_OFFSET 0 -#endif - - global_symbols = static_symbols = - (struct pending *) 0; - pst = (struct partial_symtab *) 0; - - includes_allocated = 30; - includes_used = 0; - psymtab_include_list = (char **) alloca (includes_allocated * - sizeof (char *)); - - dependencies_allocated = 30; - dependencies_used = 0; - dependency_list = - (struct partial_symtab **) alloca (dependencies_allocated * - sizeof (struct partial_symtab *)); - - old_chain = make_cleanup (free_all_psymtabs, 0); - - /* Init bincl list */ - init_bincl_list (20); - make_cleanup (free_bincl_list, 0); - - /* Setup global partial symbol list */ - init_psymbol_list (nlistlen); - - last_source_file = 0; - -#ifdef END_OF_TEXT_DEFAULT - end_of_text_addr = END_OF_TEXT_DEFAULT; -#endif - - symtab_input_desc = desc; /* This is needed for fill_symbuf below */ - symbuf_end = symbuf_idx = 0; - - for (symnum = 0; symnum < nlistlen; symnum++) - { - struct nlist *bufp; - unsigned char type; - - /* Get the symbol for this run and pull out some info */ - QUIT; /* allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - /* - * Special cases to speed up readin. - */ - if (type == N_SLINE) continue; - - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - switch (type) - { - /* - * Standard, non-debugger, symbols - */ - - case N_TEXT | N_EXT: - /* Catch etext */ - - if (!strcmp (namestring, "_etext")) - end_of_text_addr = bufp->n_value; - /* Fall through */ - -#ifdef N_NBTEXT - case N_NBTEXT | N_EXT: -#endif -#ifdef N_NBDATA - case N_NBDATA | N_EXT: -#endif -#ifdef N_NBBSS - case N_NBBSS | N_EXT: -#endif - case N_ABS | N_EXT: - case N_DATA | N_EXT: - case N_BSS | N_EXT: - /* Figure out beginning and end of global linker symbol - section and put non-debugger specified symbols on - tmp_symchain */ - - last_global_sym = symnum; - if (!first_global_sym) first_global_sym = symnum; - - record_misc_function (namestring, bufp->n_value); /* Always */ - - continue; - -#ifdef N_NBTEXT - case N_NBTEXT: -#endif - case N_TEXT: - if (!strcmp (namestring + strlen (namestring) - 2, ".o") - || !strncmp (namestring, "-l", 2)) - { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; - if (past_first_source_file && pst) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), bufp->n_value, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - pst = (struct partial_symtab *) 0; - includes_used = 0; - dependencies_used = 0; - } - else - past_first_source_file = 1; - } - continue; - - case N_UNDF: - case N_UNDF | N_EXT: - case N_ABS: - case N_DATA: - case N_BSS: -#ifdef N_NBDATA - case N_NBDATA: -#endif -#ifdef N_NBBSS - case N_NBBSS: -#endif - case N_FN: - /* Keep going . . .*/ - - /* - * Special symbol types for GNU - */ -#ifdef N_INDR - case N_INDR: - case N_INDR | N_EXT: -#endif -#ifdef N_SETA - case N_SETA: - case N_SETA | N_EXT: - case N_SETT: - case N_SETT | N_EXT: - case N_SETD: - case N_SETD | N_EXT: - case N_SETB: - case N_SETB | N_EXT: - case N_SETV: - case N_SETV | N_EXT: -#endif - continue; - - /* - * Debugger symbols - */ - - case N_SO: - /* End the current partial symtab and start a new one */ - - if (past_first_source_file && pst) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), bufp->n_value, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - pst = (struct partial_symtab *) 0; - includes_used = 0; - dependencies_used = 0; - } - else - past_first_source_file = 1; - - pst = start_psymtab (namestring, bufp->n_value, - symnum * sizeof (struct nlist), - next_ps_global, next_ps_static); - - continue; - -#ifdef N_BINCL - case N_BINCL: - /* Add this bincl to the bincl_list for future EXCLs. No - need to save the string; it'll be around until - read_dbx_symtab function return */ - add_bincl_to_list (pst, namestring, bufp->n_value); - - /* Fall through */ -#endif - - case N_SOL: - /* Mark down an include file in the current psymtab */ - - psymtab_include_list[includes_used++] = namestring; - if (includes_used >= includes_allocated) - { - char **orig = psymtab_include_list; - - psymtab_include_list = (char **) - alloca ((includes_allocated *= 2) * - sizeof (char *)); - bcopy (orig, psymtab_include_list, - includes_used * sizeof (char *)); -#ifdef DEBUG_INFO - fprintf (stderr, "Had to realloc includes. New size: %d\n", - includes_allocated); -#endif - } - continue; - - case N_FUN: - case N_SSYM: - case N_GSYM: - case N_LSYM: - case N_STSYM: - case N_LCSYM: - case N_ENTRY: -#ifdef N_MAIN - case N_MAIN: -#endif -#ifdef N_BSLINE - case N_BSLINE: -#endif - case N_PC: -#ifdef N_M2C - case N_M2C: - case N_SCOPE: -#endif - /* Process a symbol as appropriate for the type (this - information is contained in the name of the symbol) */ - - if (namestring[0] != '\0') -#if 1 - process_symbol_for_psymtab (namestring); -#else - process_symbol_for_psymtab (namestring, tmp_symchain); -#endif - continue; - -#ifdef N_BINCL - case N_EXCL: - /* Find the corresponding bincl and mark that psymtab on the - psymtab dependency list */ - { - struct partial_symtab *needed_pst = - find_corresponding_bincl_psymtab (namestring, bufp->n_value); - - /* If this include file was defined earlier in this file, - leave it alone. */ - if (needed_pst == pst) continue; - - if (needed_pst) - { - int i; - int found = 0; - - for (i = 0; i < dependencies_used; i++) - if (dependency_list[i] == needed_pst) - { - found = 1; - break; - } - - /* If it's already in the list, skip the rest. */ - if (found) continue; - - dependency_list[dependencies_used++] = needed_pst; - if (dependencies_used >= dependencies_allocated) - { - struct partial_symtab **orig = dependency_list; - dependency_list = - (struct partial_symtab **) - alloca ((dependencies_allocated *= 2) - * sizeof (struct partial_symtab *)); - bcopy (orig, dependency_list, - (dependencies_used - * sizeof (struct partial_symtab *))); -#ifdef DEBUG_INFO - fprintf (stderr, "Had to reallocate dependency list.\n"); - fprintf (stderr, "New dependencies allocated: %d\n", - dependencies_allocated); -#endif - } - } - else - error ("Invalid symbol data: \"repeated\" header file not previously seen, at symtab pos %d.", - symnum); - } - continue; - - case N_EINCL: -#endif -#ifdef N_DSLINE - case N_DSLINE: -#endif - case N_LENG: - case N_BCOMM: - case N_ECOMM: - case N_ECOML: - case N_FNAME: - case N_SLINE: - case N_RSYM: - case N_PSYM: - case N_LBRAC: - case N_RBRAC: - /* These symbols aren't interesting; don't worry about them */ - - continue; - - default: - /* If we haven't found it yet, we've got problems */ - - if (IGNORE_SYMBOL (type)) - continue; - - fatal ("Bad symbol type 0x%x encountered in gdb scan", type); - } - } - - if (last_source_file) - { - end_psymtab (pst, psymtab_include_list, includes_used, - symnum * sizeof (struct nlist), end_of_text_addr, - dependency_list, dependencies_used, - next_ps_global, next_ps_static); - includes_used = 0; - dependencies_used = 0; - pst = (struct partial_symtab *) 0; - } - - free_bincl_list (); - discard_cleanups (old_chain); -} - -/* - * Take a single symbol (name: NAME) and process it (add it to the - * app psymbol list or not). - */ -static void -process_symbol_for_psymtab (name) - char *name; -{ - char *p = (char *) index(name, ':') + 1; - int deftype; - struct partial_symbol *sym; - enum { T_IGNORE, T_STATIC, T_GLOBAL } symbol_type; - enum namespace ns = UNDEF_NAMESPACE; - enum address_class class; - int hash; - - if (p == (char *) 0x1) - /* No ":" ; I guess it's not a debuggging symbol */ - return; - - if ((*p >= '0' && *p <= '9') || *p == '(') - deftype = 'l'; - else - deftype = *p; - - /* Figure out how to handle this symbol */ - switch (deftype) - { - /* T is a struct/union/enum, t is a typedef */ - case 'T': - symbol_type = T_STATIC; - ns = STRUCT_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 't': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_TYPEDEF; - break; - case 'c': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_CONST; - break; - case 'S': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - case 'f': - symbol_type = T_STATIC; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'F': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_BLOCK; - break; - case 'G': - symbol_type = T_GLOBAL; - ns = VAR_NAMESPACE; - class = LOC_STATIC; - break; - default: - return; - } - - /* Create the symbol and store it on the list */ - /* There's a better algorithm possible for the allocation; figure - out how far through the symbol table we are and do a reestimate */ - if (symbol_type == T_STATIC) - { - if (next_ps_static >= static_psymbols + static_psymbols_allocated) - { - static_psymbols = (struct partial_symbol *) - xrealloc (static_psymbols, - (static_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - /* Next assumes we only went one over. Should be good if - program works correctly */ - next_ps_static = static_psymbols + static_psymbols_allocated; - static_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc statics\n"); -#endif - } - sym = next_ps_static++; - } - else - { - if (next_ps_global >= global_psymbols + global_psymbols_allocated) - { - global_psymbols = (struct partial_symbol *) - xrealloc (global_psymbols, - (global_psymbols_allocated * 2 - * sizeof (struct partial_symbol))); - next_ps_global = global_psymbols + global_psymbols_allocated; - global_psymbols_allocated *= 2; -#ifdef DEBUGINFO - fprintf(stderr, "debuginfo: Had to realloc globals\n"); -#endif - } - sym = next_ps_global++; - } - - SYMBOL_NAME(sym) = (char *) obstack_alloc (psymbol_obstack, - p - name); - strncpy(SYMBOL_NAME(sym), name, p - name - 1); - SYMBOL_NAME(sym)[p - name - 1] = '\0'; - SYMBOL_NAMESPACE(sym) = ns; - SYMBOL_CLASS(sym) = class; -} -#undef HASH_OFFSET - -/* - * Allocate and partially fill a partial symtab. It will be - * completely filled at the end of the symbol list. - */ -static struct partial_symtab * -start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms) - char *filename; - int textlow; - int ldsymoff; - struct partial_symbol *global_syms; - struct partial_symbol *static_syms; -{ - struct partial_symtab *result = - (struct partial_symtab *) obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab)); - - result->filename = - (char *) obstack_alloc (psymbol_obstack, - strlen (filename) + 1); - strcpy (result->filename, filename); - - result->textlow = textlow; - result->ldsymoff = ldsymoff; - - result->readin = 0; - - result->globals_offset = global_syms - global_psymbols; - result->statics_offset = static_syms - static_psymbols; - - result->n_global_syms = 0; - result->n_static_syms = 0; - - return result; -} - -static int -compare_psymbols (s1, s2) - register struct partial_symbol *s1, *s2; -{ - register char - *st1 = SYMBOL_NAME (s1), - *st2 = SYMBOL_NAME (s2); - - return (st1[0] - st2[0] ? st1[0] - st2[0] : - strcmp (st1 + 1, st2 + 1)); -} - - -/* Close off the current usage of a partial_symbol table entry. This - involves setting the correct number of includes (with a realloc), - setting the high text mark, setting the symbol length in the - executable, and setting the length of the global and static lists - of psymbols. - - The global symbols and static symbols are then seperately sorted. - - Then the partial symtab is put on the global list. - *** List variables and peculiarities of same. *** - */ -static void -end_psymtab (pst, include_list, num_includes, capping_symbol_offset, - capping_text, dependency_list, number_dependencies, - capping_global, capping_static) - struct partial_symtab *pst; - char **include_list; - int num_includes; - int capping_symbol_offset; - int capping_text; - struct partial_symtab **dependency_list; - int number_dependencies; - struct partial_symbol *capping_global, *capping_static; -{ - int i; - - pst->ldsymlen = capping_symbol_offset - pst->ldsymoff; - pst->texthigh = capping_text; - - pst->n_global_syms = - capping_global - (global_psymbols + pst->globals_offset); - pst->n_static_syms = - capping_static - (static_psymbols + pst->statics_offset); - - pst->dependencies = (struct partial_symtab **) - obstack_alloc (psymbol_obstack, - number_dependencies * sizeof (struct partial_symtab *)); - bcopy (dependency_list, pst->dependencies, - number_dependencies * sizeof (struct partial_symtab *)); - pst->number_of_dependencies = number_dependencies; - - for (i = 0; i < num_includes; i++) - { - /* Eventually, put this on obstack */ - struct partial_symtab *subpst = - (struct partial_symtab *) - obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab)); - - subpst->filename = - (char *) obstack_alloc (psymbol_obstack, - strlen (include_list[i]) + 1); - strcpy (subpst->filename, include_list[i]); - - subpst->ldsymoff = - subpst->ldsymlen = - subpst->textlow = - subpst->texthigh = 0; - subpst->readin = 0; - - subpst->dependencies = (struct partial_symtab **) - obstack_alloc (psymbol_obstack, - sizeof (struct partial_symtab *)); - subpst->dependencies[0] = pst; - subpst->number_of_dependencies = 1; - - subpst->globals_offset = - subpst->n_global_syms = - subpst->statics_offset = - subpst->n_static_syms = 0; - - subpst->next = partial_symtab_list; - partial_symtab_list = subpst; - } - - /* Sort the global list; don't sort the static list */ - qsort (global_psymbols + pst->globals_offset, pst->n_global_syms, - sizeof (struct partial_symbol), compare_psymbols); - - /* Put the psymtab on the psymtab list */ - pst->next = partial_symtab_list; - partial_symtab_list = pst; -} - -/* - * Read in all of the symbols for a given psymtab for real. Return - * the value of the symtab you create. Do not free the storage - * allocated to the psymtab; it may have pointers to it. - */ -static void scan_file_globals (); -static void read_ofile_symtab (); - -struct symtab * -psymtab_to_symtab(pst) - struct partial_symtab *pst; -{ - int desc; - DECLARE_FILE_HEADERS; - char *stringtab; - struct partial_symtab **list_patch; - int stsize, val; - struct stat statbuf; - struct cleanup *old_chain; - extern void close (); - int i; - struct symtab *result; - char *name = symfile; /* Some of the macros require the */ - /* variable "name" to be defined in */ - /* the context in which they execute */ - /* (Yech!) */ - - if (!pst) - return 0; - - if (pst->readin) - { - fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n", - pst->filename); - return 0; - } - - if (!name) - error("No symbol file currently specified; use command symbol-file"); - - /* Read in all partial symbtabs on which this one is dependent */ - for (i = 0; i < pst->number_of_dependencies; i++) - if (!pst->dependencies[i]->readin) - psymtab_to_symtab (pst->dependencies[i]); - - if (pst->ldsymlen) /* Otherwise it's a dummy */ - { - /* Open symbol file and read in string table */ - stat (name, &statbuf); - desc = open(name, O_RDONLY, 0); /* symbol_file_command - guarrantees that the symbol file name - will be absolute, so there is no - need for openp */ - - old_chain = make_cleanup (close, desc); - - if (desc < 0) - error("Symbol file not readable"); - - READ_FILE_HEADERS (desc, name); - - /* Read in the string table */ - lseek (desc, STRING_TABLE_OFFSET, L_SET); - READ_STRING_TABLE_SIZE (stsize); - if (stsize >= 0 && stsize < statbuf.st_size) - stringtab = (char *) alloca (stsize); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, stsize); - - bcopy (&stsize, stringtab, sizeof stsize); - val = myread (desc, stringtab + sizeof stsize, stsize - sizeof stsize); - if (val < 0) - perror_with_name (name); - - /* Init stuff necessary for reading in symbols */ - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - /* Read in this files symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - read_ofile_symtab (desc, stringtab, pst->ldsymoff, - pst->ldsymlen, pst->textlow, - pst->texthigh - pst->textlow, 0); - sort_symtab_syms (symtab_list); /* At beginning since just added */ - - /* Match with global symbols */ - lseek (desc, SYMBOL_TABLE_OFFSET, L_SET); - scan_file_globals (desc, stringtab, - first_global_sym * sizeof(struct nlist), - last_global_sym - first_global_sym + 1); - - do_cleanups (old_chain); - } - - /* Find pst in list, prune it, and free it's storage */ - for (list_patch = &partial_symtab_list; - *list_patch && *list_patch != pst; - list_patch = &((*list_patch)->next)) - ; - - if (!(*list_patch)) /* pst not in list. Don't worry about it? */ - fatal ("internal: psymtab_to_symtab called with non-listed pst"); - - *list_patch = (*list_patch)->next; /* Prune */ - - pst->readin = 1; /* Mark as read in */ - - /* It's the last one if we actually read something in */ - if (pst->ldsymlen) - return symtab_list; - else - /* Search through list for correct name. */ - for (result = symtab_list; result; result = result->next) - if (!strcmp (result->filename, pst->filename)) - return result; - - return 0; -} - -/* - * Scan through all of the global symbols defined in the object file, - * assigning values to the debugging symbols that need to be assigned - * to. - * - * DESC is the file descriptor of the symbol file, with the seek - * pointer pointing at the beginning of the symbol table. - * STRINGTAB is the file's string table, already read in. - * OFFSET is the offset (in bytes) of the beginning of the global - * symbols from the beginning of the symbol table. - * NUMSYMS is the number of symbols that have to be checked. - */ -static void -scan_file_globals (desc, stringtab, offset, numsyms) - int desc; - char *stringtab; - int offset; - int numsyms; -{ - int hash; - - lseek(desc, offset, L_INCR); - symtab_input_desc = desc; - symbuf_end = symbuf_idx = 0; - - for (symnum = 0; symnum < numsyms; symnum++) - { - struct nlist *bufp; - unsigned char type; - char *namestring; - - QUIT; - if (symbuf_idx == symbuf_end) - fill_symbuf (); - - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - if (type & N_EXT && type != N_EXT) - { - struct symbol *sym, *prev; - - namestring = bufp->n_un.n_strx ? - bufp->n_un.n_strx + stringtab : ""; - prev = (struct symbol *) 0; - - /* Get the hash index and check all the symbols - under that hash index. */ - -#ifdef NAMES_HAVE_UNDERSCORE - hash = hashname (namestring + 1); -#else /* ! NAMES_HAVE_UNDERSCORE */ - hash = hashname (namestring); -#endif /* ! NAMES_HAVE_UNDERSCORE */ - for (sym = global_sym_chain[hash]; sym;) - { - if ( -#ifdef NAMES_HAVE_UNDERSCORE - *namestring == '_' - && namestring[1] == SYMBOL_NAME (sym)[0] - && !strcmp(namestring + 2, SYMBOL_NAME (sym) + 1) -#else /* ! NAMES_HAVE_UNDERSCORE */ - namestring[0] == SYMBOL_NAME (sym) [0] - && !strcmp(namestring + 1, SYMBOL_NAME(sym) + 1) -#endif /* ! NAMES_HAVE_UNDERSCORE */ - ) - { - /* Splice this symbol out of the hash chain and - assign the value we have to it. */ - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - global_sym_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = global_sym_chain[hash]; - break; /* Only one reference per file */ - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - } - /* There shouldn't be anything left on the hash list at this point. - If there is, we have done something wrong. For right now it's - worth checking, until I get the bugs out. */ - /* Sigh. Unfortunately, the above is not true. If an extern - variable is mentioned in an include file (or a program) and the - variable is never either referenced or defined, there will be a - debugger symbol with no "real" symbol. Oh well. */ -} - -/* - * Read in a defined section of a specific object file's symbols. - * - * DESC is the file descriptor for the file, positioned at the - * beginning of the symtab - * STRINGTAB is a pointer to the files string - * table, already read in - * SYM_OFFSET is the offset within the file of - * the beginning of the symbols we want to read, NUM_SUMBOLS is the - * number of symbols to read - * TEXT_OFFSET is the offset to be added to - * all values of symbols coming in and - * TEXT_SIZE is the size of the text segment read in. - * OFFSET is a flag which indicates that the value of all of the - * symbols should be offset by TEXT_OFFSET (for the purposes of - * incremental linking). - */ - -static void -read_ofile_symtab (desc, stringtab, sym_offset, - sym_size, text_offset, text_size, offset) - int desc; - register char *stringtab; - int sym_offset; - int sym_size; - int text_offset; - int text_size; - int offset; -{ - register char *namestring; - register struct symbol *sym, *prev; - int hash; - struct cleanup *old_chain; - struct nlist *bufp; - unsigned char type; -#ifdef N_BINCL - subfile_stack = 0; -#endif - - stringtab_global = stringtab; - last_source_file = 0; - - symtab_input_desc = desc; - symbuf_end = symbuf_idx = 0; - lseek(desc, sym_offset, L_INCR); - - fill_symbuf(); - bufp = &symbuf[symbuf_idx]; - if ((unsigned char) bufp->n_type != N_SO) - fatal("First symbol in segment of executable not a source symbol"); - - for (symnum = 0; - symnum < sym_size / sizeof(struct nlist); - symnum++) - { - QUIT; /* Allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf(); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type; - - if (offset && - (type == N_TEXT || type == N_DATA || type == N_BSS)) - bufp->n_value += text_offset; - - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - if (type & N_STAB) - process_one_symbol(type, bufp->n_desc, - bufp->n_value, namestring); - /* We skip checking for a new .o or -l file; that should never - happen in this routine. */ - else if (type == N_TEXT - && !strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL)) - processing_gcc_compilation = 1; - else if (type & N_EXT || type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - /* Global symbol: see if we came across a dbx defintion for - a corresponding symbol. If so, store the value. Remove - syms from the chain when their values are stored, but - search the whole chain, as there may be several syms from - different files with the same name. */ - /* This is probably not true. Since the files will be read - in one at a time, each reference to a global symbol will - be satisfied in each file as it appears. So we skip this - section. */ - &stringtab_global; /* For debugger; am I right? */ - } - end_symtab (text_offset + text_size); -} - -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; - } - - /* Ensure result is positive. */ - if (total < 0) total += (1000 << 6); - return total % HASHSIZE; -} - -/* Put all appropriate global symbols in the symseg data - onto the hash chains so that their addresses will be stored - when seen later in loader global symbols. */ - -static void -hash_symsegs () -{ - /* Look at each symbol in each block in each symseg symtab. */ - struct symtab *s; - for (s = symseg_chain; s; s = s->next) - { - register int n; - for (n = BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)) - 1; n >= 0; n--) - { - register struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), n); - register int i; - for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) - { - register struct symbol *sym = BLOCK_SYM (b, i); - - /* Put the symbol on a chain if its value is an address - that is figured out by the loader. */ - - if (SYMBOL_CLASS (sym) == LOC_EXTERNAL) - { - register int hash = hashname (SYMBOL_NAME (sym)); - SYMBOL_VALUE (sym) = (int) global_sym_chain[hash]; - global_sym_chain[hash] = sym; - SYMBOL_CLASS (sym) = LOC_STATIC; - } - } - } - } -} - -static void -process_one_symbol (type, desc, value, name) - int type, desc; - CORE_ADDR value; - char *name; -{ - register struct context_stack *new; - - /* Something is wrong if we see real data before - seeing a source file name. */ - - if (last_source_file == 0 && type != N_SO) - { - /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines - where that code is defined, and all symbols on the Convex. */ - if (IGNORE_SYMBOL (type)) - return; - - error ("Invalid symbol data: does not start by identifying a source file."); - } - - switch (type) - { - case N_FUN: - case N_FNAME: - /* Either of these types of symbols indicates the start of - a new function. We must process its "name" normally for dbx, - but also record the start of a new lexical context, and possibly - also the end of the lexical context for the previous function. */ - - within_function = 1; - if (context_stack_depth > 0) - { - new = &context_stack[--context_stack_depth]; - /* Make a block for the local symbols within. */ - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, value); - } - /* Stack must be empty now. */ - if (context_stack_depth != 0) - error ("Invalid symbol data: unmatched N_LBRAC before symtab pos %d.", - symnum); - - new = &context_stack[context_stack_depth++]; - new->old_blocks = pending_blocks; - new->start_addr = value; - new->name = define_symbol (value, name, desc); - local_symbols = 0; - break; - - case N_LBRAC: - /* This "symbol" just indicates the start of an inner lexical - context within a function. */ - - if (context_stack_depth == context_stack_size) - { - context_stack_size *= 2; - context_stack = (struct context_stack *) - xrealloc (context_stack, - (context_stack_size - * sizeof (struct context_stack))); - } - - new = &context_stack[context_stack_depth++]; - new->depth = desc; - new->locals = local_symbols; - new->old_blocks = pending_blocks; - new->start_addr = value; - new->name = 0; - local_symbols = 0; - break; - - case N_RBRAC: - /* This "symbol" just indicates the end of an inner lexical - context that was started with N_RBRAC. */ - new = &context_stack[--context_stack_depth]; - if (desc != new->depth) - error ("Invalid symbol data: N_LBRAC/N_RBRAC symbol mismatch, symtab pos %d.", symnum); - local_symbols = new->locals; - - /* If this is not the outermost LBRAC...RBRAC pair in the - function, its local symbols preceded it, and are the ones - just recovered from the context stack. Defined the block for them. - - If this is the outermost LBRAC...RBRAC pair, there is no - need to do anything; leave the symbols that preceded it - to be attached to the function's own block. */ - if (local_symbols && context_stack_depth > 1) - { - /* Muzzle a compiler bug that makes end > start. */ - if (new->start_addr > value) - new->start_addr = value; - /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, new->old_blocks, - new->start_addr + last_source_start_addr, - value + last_source_start_addr); - } - break; - - case N_FN: - /* This kind of symbol supposedly indicates the start - of an object file. In fact this type does not appear. */ - break; - - case N_SO: - /* This type of symbol indicates the start of data - for one source file. - Finish the symbol table of the previous source file - (if any) and start accumulating a new symbol table. */ - if (last_source_file) - end_symtab (value); - start_symtab (name, value); - break; - - case N_SOL: - /* This type of symbol indicates the start of data for - a sub-source-file, one whose contents were copied or - included in the compilation of the main source file - (whose name was given in the N_SO symbol.) */ - start_subfile (name); - break; - -#ifdef N_BINCL - case N_BINCL: - push_subfile (); - add_new_header_file (name, value); - start_subfile (name); - break; - - case N_EINCL: - start_subfile (pop_subfile ()); - break; - - case N_EXCL: - add_old_header_file (name, value); - break; -#endif /* have N_BINCL */ - - case N_SLINE: - /* This type of "symbol" really just records - one line-number -- core-address correspondence. - Enter it in the line list for this symbol table. */ - record_line (desc, value); - break; - - case N_BCOMM: - case N_ECOMM: - case N_ECOML: - case N_LENG: - break; - - default: - if (name) - define_symbol (value, name, desc); - } -} - -/* This function was added for C++ functionality. I presume that it - condenses the bunches formed by reading in an additional .o file - (incremental linking). */ - -static void -condense_addl_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 *) xrealloc (misc_function_vector, - (misc_count + misc_function_count) * sizeof (struct misc_function)); - - j = misc_function_count; - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - misc_function_vector[j] = bunch->contents[i]; - misc_function_vector[j].name - = concat (misc_function_vector[j].name - + (misc_function_vector[j].name[0] == '_' ? offset : 0), - "", ""); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - misc_function_count += misc_count; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, misc_function_count, - sizeof (struct misc_function), compare_misc_functions); -} - - -/* Read in another .o file and create a symtab entry for it.*/ - -static void -read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) - int desc; - register char *stringtab; - register int nlistlen; - unsigned text_addr; - int text_size; -{ - FILE *stream = fdopen (desc, "r"); - register char *namestring; - register struct symbol *sym, *prev; - int hash; - int num_object_files = 0; - -#ifdef N_BINCL - subfile_stack = 0; -#endif - - last_source_file = 0; - bzero (global_sym_chain, sizeof global_sym_chain); - symtab_input_desc = desc; - stringtab_global = stringtab; - fill_symbuf (); - - for (symnum = 0; symnum < nlistlen; symnum++) - { - struct nlist *bufp; - unsigned char type; - - QUIT; /* allow this to be interruptable */ - if (symbuf_idx == symbuf_end) - fill_symbuf (); - bufp = &symbuf[symbuf_idx++]; - type = bufp->n_type & N_TYPE; - namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; - - if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) ) - { - /* Relocate this file's symbol table information - to the address it has been loaded into. */ - bufp->n_value += text_addr; - } - - type = bufp->n_type; - - if (type & N_STAB) - process_one_symbol (type, bufp->n_desc, - bufp->n_value, namestring); - /* A static text symbol whose name ends in ".o" - can only mean the start of another object file. - So end the symtab of the source file we have been processing. - This is how we avoid counting the libraries as part - or the last source file. - Also this way we find end of first object file (crt0). */ - else if ((type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - && (!strcmp (namestring + strlen (namestring) - 2, ".o")) - || ! strcmp (namestring, "-l", 2)) - { - if (num_object_files++ == 1) - first_object_file_end = bufp->n_value; - if (last_source_file) - end_symtab (bufp->n_value); - } - else if (type & N_EXT || type == N_TEXT -#ifdef N_NBTEXT - || type == N_NBTEXT -#endif - ) - { - int used_up = 0; - - /* Record the location of _etext. */ - if (type == (N_TEXT | N_EXT) - && !strcmp (namestring, "_etext")) - end_of_text_addr = bufp->n_value; - - /* Global symbol: see if we came across a dbx definition - for a corresponding symbol. If so, store the value. - Remove syms from the chain when their values are stored, - but search the whole chain, as there may be several syms - from different files with the same name. */ - if (type & N_EXT) - { - prev = 0; -#ifdef NAMES_HAVE_UNDERSCORE - hash = hashname (namestring + 1); -#else /* not NAMES_HAVE_UNDERSCORE */ - hash = hashname (namestring); -#endif /* not NAMES_HAVE_UNDERSCORE */ - for (sym = global_sym_chain[hash]; - sym;) - { - if ( -#ifdef NAMES_HAVE_UNDERSCORE - *namestring == '_' - && namestring[1] == SYMBOL_NAME (sym)[0] - && - !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1) -#else /* NAMES_HAVE_UNDERSCORE */ - namestring[0] == SYMBOL_NAME (sym)[0] - && - !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1) -#endif /* NAMES_HAVE_UNDERSCORE */ - ) - { - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - global_sym_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - SYMBOL_VALUE (sym) = bufp->n_value; - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = global_sym_chain[hash]; - - used_up = 1; - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - - /* Defined global or text symbol: record as a misc function - if it didn't give its address to a debugger symbol above. */ - if (type <= (N_TYPE | N_EXT) - && type != N_EXT - && ! used_up) - record_misc_function (namestring, bufp->n_value); - } - } - - if (last_source_file) - end_symtab (text_addr + text_size); - - fclose (stream); -} - -/* C++: - This function allows the addition of incrementally linked object files. - Since this has a fair amount of code in common with symbol_file_command, - it might be worthwhile to consolidate things, as was done with - read_dbx_symtab and condense_misc_bunches. */ - -void -add_file_command (arg_string) - char* arg_string; -{ - register int desc; - DECLARE_FILE_HEADERS; - struct nlist *nlist; - char *stringtab; - long buffer; - register int val; - extern void close (); - struct cleanup *old_chain; - struct symtab *symseg; - struct stat statbuf; - char *name; - unsigned text_addr; - - if (arg_string == 0) - error ("add-file takes a file name and an address"); - - for( ; *arg_string == ' '; arg_string++ ); - name = arg_string; - for( ; *arg_string && *arg_string != ' ' ; arg_string++ ); - *arg_string++ = (char) 0; - - if (name[0] == 0) - error ("add-file takes a file name and an address"); - - text_addr = parse_and_eval_address (arg_string); - - dont_repeat (); - - if (!query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", - name, text_addr)) - error ("Not confirmed."); - - desc = open (name, O_RDONLY); - if (desc < 0) - perror_with_name (name); - - old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - - READ_FILE_HEADERS (desc, name); - - if (NUMBER_OF_SYMBOLS == 0) - { - printf ("%s does not have a symbol-table.\n", name); - fflush (stdout); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Now read the string table, all at once. */ - val = lseek (desc, STRING_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - stat (name, &statbuf); - READ_STRING_TABLE_SIZE (buffer); - if (buffer >= 0 && buffer < statbuf.st_size) - stringtab = (char *) alloca (buffer); - else - stringtab = NULL; - if (stringtab == NULL) - error ("ridiculous string table size: %d bytes", name, buffer); - - bcopy (&buffer, stringtab, sizeof buffer); - val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val < 0) - perror_with_name (name); - -#ifdef READ_GDB_SYMSEGS - /* That puts us at the symsegs. Read them. */ - symseg_chain = read_symsegs (desc, name); - hash_symsegs (); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - for (symseg = symseg_chain; symseg; symseg = symseg->next) - { - int i; - struct sourcevector *sv = (struct sourcevector *) symseg->linetable; - - for (i = 0; i < sv->length; i++) - { - int j; - struct source *source = sv->source[i]; - struct symtab *sp1 - = (struct symtab *) xxmalloc (sizeof (struct symtab)); - - bcopy (symseg, sp1, sizeof (struct symtab)); - sp1->filename = savestring (source->name, strlen (source->name)); - sp1->linetable = &source->contents; - sp1->free_code = free_nothing; - sp1->free_ptr = (i == 0) ? (char *) symseg : 0; - - sp1->next = symtab_list; - symtab_list = sp1; - } - } -#else - /* Where people are using the 4.2 ld program, must not check for - symsegs, because that ld puts randonm garbage at the end of - the output file and that would trigger an error message. */ - symseg_chain = 0; -#endif - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, SYMBOL_TABLE_OFFSET, 0); - if (val < 0) - perror_with_name (name); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - init_header_files (); - make_cleanup (free_header_files, 0); - free_pendings = 0; - pending_blocks = 0; - file_symbols = 0; - global_symbols = 0; - make_cleanup (really_free_pendings, 0); - - read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr, - SIZE_OF_TEXT_SEGMENT); - - - /* Sort symbols alphabetically within each block. */ - - sort_syms (); - - /* Go over the misc functions and install them in vector. */ - - condense_addl_misc_bunches (1); - - /* 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. */ - /* Hmmm. I'd say we don't want this in add_file_command, but . . . */ - - select_source_symtab (symtab_list); - - do_cleanups (old_chain); - - /* Free the symtabs made by read_symsegs, but not their contents, - which have been copied into symtabs on symtab_list. */ - while (symseg_chain) - { - register struct symtab *s = symseg_chain->next; - free (symseg_chain); - symseg_chain = s; - } - - printf ("done.\n"); - fflush (stdout); -} - -static struct symbol * -define_symbol (value, string, desc) - int value; - char *string; - int desc; -{ - register struct symbol *sym - = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - char *p = (char *) index (string, ':'); - int deftype; - register int i; - - /* Ignore syms with empty names. */ - if (string[0] == 0) - return 0; - - SYMBOL_NAME (sym) - = (char *) obstack_alloc (symbol_obstack, ((p - string) + 1)); - /* Open-coded bcopy--saves function call time. */ - { - register char *p1 = string; - register char *p2 = SYMBOL_NAME (sym); - while (p1 != p) - *p2++ = *p1++; - *p2++ = '\0'; - } - p++; - /* Determine the type of name being defined. */ - if ((*p >= '0' && *p <= '9') || *p == '(') - deftype = 'l'; - else - deftype = *p++; - - /* c is a special case, not followed by a type-number. - SYMBOL:c=iVALUE for an integer constant symbol. - SYMBOL:c=rVALUE for a floating constant symbol. */ - if (deftype == 'c') - { - if (*p++ != '=') - error ("Invalid symbol data at symtab pos %d.", symnum); - switch (*p++) - { - case 'r': - { - double d = atof (p); - char *value; - - SYMBOL_TYPE (sym) = builtin_type_double; - value = (char *) obstack_alloc (symbol_obstack, sizeof (double)); - bcopy (&d, value, sizeof (double)); - SYMBOL_VALUE_BYTES (sym) = value; - SYMBOL_CLASS (sym) = LOC_CONST; - } - break; - case 'i': - { - SYMBOL_TYPE (sym) = builtin_type_int; - SYMBOL_VALUE (sym) = atoi (p); - SYMBOL_CLASS (sym) = LOC_CONST_BYTES; - } - break; - default: - error ("Invalid symbol data at symtab pos %d.", symnum); - } - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - return sym; - } - - /* Now usually comes a number that says which data type, - and possibly more stuff to define the type - (all of which is handled by read_type) */ - - if (deftype == 'p' && *p == 'F') - /* pF is a two-letter code that means a function parameter in Fortran. - The type-number specifies the type of the return value. - Translate it into a pointer-to-function type. */ - { - p++; - SYMBOL_TYPE (sym) - = lookup_pointer_type (lookup_function_type (read_type (&p))); - } - else - { - struct type *type = read_type (&p); - - if ((deftype == 'F' || deftype == 'f') - && TYPE_CODE (type) != TYPE_CODE_FUNC) - SYMBOL_TYPE (sym) = lookup_function_type (type); - else - SYMBOL_TYPE (sym) = type; - } - - switch (deftype) - { - case 'f': - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - break; - - case 'F': - SYMBOL_CLASS (sym) = LOC_BLOCK; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &global_symbols); - break; - - case 'G': - /* For a class G (global) symbol, it appears that the - value is not correct. It is necessary to search for the - corresponding linker definition to find the value. - These definitions appear at the end of the namelist. */ - i = hashname (SYMBOL_NAME (sym)); - SYMBOL_VALUE (sym) = (int) global_sym_chain[i]; - global_sym_chain[i] = sym; - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &global_symbols); - break; - - /* This case is faked by a conditional above, - when there is no code letter in the dbx data. - Dbx data never actually contains 'l'. */ - case 'l': - SYMBOL_CLASS (sym) = LOC_LOCAL; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'p': - SYMBOL_CLASS (sym) = LOC_ARG; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - /* DESC == 0 implies compiled with GCC. - In this case, if it says `short', believe it. */ - if (desc == 0) - break; - /* If PCC says a parameter is a short or a char, - it is really an int. */ - if (SYMBOL_TYPE (sym) == builtin_type_char - || SYMBOL_TYPE (sym) == builtin_type_short) - SYMBOL_TYPE (sym) = builtin_type_int; - else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char - || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) - SYMBOL_TYPE (sym) = builtin_type_unsigned_int; - break; - - case 'P': - SYMBOL_CLASS (sym) = LOC_REGPARM; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'r': - SYMBOL_CLASS (sym) = LOC_REGISTER; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - case 'S': - /* Static symbol at top level of file */ - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &file_symbols); - break; - - case 't': - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = - obsavestring (SYMBOL_NAME (sym), - strlen (SYMBOL_NAME (sym))); - /* C++ vagaries: we may have a type which is derived from - a base type which did not have its name defined when the - derived class was output. We fill in the derived class's - base part member's name here in that case. */ - else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT - || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION) - && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym))) - { - int i; - for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--) - if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) == 0) - TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) = - TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i)); - } - - add_symbol_to_list (sym, &file_symbols); - break; - - case 'T': - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = obconcat ("", - (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM - ? "enum " - : (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT - ? "struct " : "union ")), - SYMBOL_NAME (sym)); - add_symbol_to_list (sym, &file_symbols); - break; - - case 'V': - case 'v': - /* Static symbol of local scope */ - SYMBOL_CLASS (sym) = LOC_STATIC; - SYMBOL_VALUE (sym) = value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - add_symbol_to_list (sym, &local_symbols); - break; - - default: - error ("Invalid symbol data: unknown symbol-type code `%c' at symtab pos %d.", deftype, symnum); - } - return sym; -} - -/* Read a number by which a type is referred to in dbx data, - or perhaps read a pair (FILENUM, TYPENUM) in parentheses. - Just a single number N is equivalent to (0,N). - Return the two numbers by storing them in the vector TYPENUMS. - TYPENUMS will then be used as an argument to dbx_lookup_type. */ - -static void -read_type_number (pp, typenums) - register char **pp; - register int *typenums; -{ - if (**pp == '(') - { - (*pp)++; - typenums[0] = read_number (pp, ','); - typenums[1] = read_number (pp, ')'); - } - else - { - typenums[0] = 0; - typenums[1] = read_number (pp, 0); - } -} - -/* Read a dbx type reference or definition; - return the type that is meant. - This can be just a number, in which case it references - a type already defined and placed in type_vector. - Or the number can be followed by an =, in which case - it means to define a new type according to the text that - follows the =. */ - -static -struct type * -read_type (pp) - register char **pp; -{ - register struct type *type = 0; - register int n; - struct type *type1; - int typenums[2]; - int xtypenums[2]; - - read_type_number (pp, typenums); - - /* Detect random reference to type not yet defined. - Allocate a type object but leave it zeroed. */ - if (**pp != '=') - return dbx_alloc_type (typenums); - - *pp += 2; - switch ((*pp)[-1]) - { - case 'x': - type = dbx_alloc_type (typenums); - /* Set the type code according to the following letter. */ - switch ((*pp)[0]) - { - case 's': - TYPE_CODE (type) = TYPE_CODE_STRUCT; - break; - case 'u': - TYPE_CODE (type) = TYPE_CODE_UNION; - break; - case 'e': - TYPE_CODE (type) = TYPE_CODE_ENUM; - break; - } - /* Skip the name the cross-ref points to. */ - /* Note: for C++, the cross reference may be to a base type which - has not yet been seen. In this case, we skip to the comma, - which will mark the end of the base class name. (The ':' - at the end of the base class name will be skipped as well.) */ - *pp = (char *) index (*pp, ','); - /* Just allocate the type and leave it zero if nothing known */ - return dbx_alloc_type (typenums); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '(': - (*pp)--; - read_type_number (pp, xtypenums); - type = *dbx_lookup_type (xtypenums); - if (type == 0) - type = builtin_type_void; - *dbx_lookup_type (typenums) = type; - break; - - case '*': - type1 = read_type (pp); - if (TYPE_POINTER_TYPE (type1)) - { - type = TYPE_POINTER_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_pointer_type (type, type1); - } - break; - - case '@@': - { - struct type *domain = read_type (pp); - char c; - struct type *memtype; - - if (*(*pp)++ != ',') - error ("invalid member type data format, at symtab pos %d.", - symnum); - - memtype = read_type (pp); - type = dbx_alloc_type (typenums); - smash_to_member_type (type, domain, memtype); - } - break; - - case '&': - type1 = read_type (pp); - if (TYPE_REFERENCE_TYPE (type1)) - { - type = TYPE_REFERENCE_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_reference_type (type, type1); - } - break; - - case 'f': - type1 = read_type (pp); - if (TYPE_FUNCTION_TYPE (type1)) - { - type = TYPE_FUNCTION_TYPE (type1); - *dbx_lookup_type (typenums) = type; - } - else - { - type = dbx_alloc_type (typenums); - smash_to_function_type (type, type1); - } - break; - - case 'r': - type = read_range_type (pp, typenums); - *dbx_lookup_type (typenums) = type; - break; - - case 'e': - type = dbx_alloc_type (typenums); - type = read_enum_type (pp, type); - *dbx_lookup_type (typenums) = type; - break; - - case 's': - type = dbx_alloc_type (typenums); - type = read_struct_type (pp, type); - break; - - case 'u': - type = dbx_alloc_type (typenums); - type = read_struct_type (pp, type); - TYPE_CODE (type) = TYPE_CODE_UNION; - break; - - case 'a': - if (*(*pp)++ != 'r') - error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.", - (*pp)[-1], "at symtab position", symnum); - - type = dbx_alloc_type (typenums); - type = read_array_type (pp, type); - break; - -#if 0 - /* Format of an array type: - "ar<index type>;lower;upper;<array_contents_type>". Put code - in to handle this. */ - - /* dbx expresses array types in terms of a range type for the index, - and that range type is specified right inside the array type spec - making ar1;MIN;MAX;VALTYPE */ - if (!strncmp (*pp, "r1;0;", 5)) - (*pp) += 5; - else if (!strncmp (*pp, "r(0,1);0;", 9)) - (*pp) += 9; - else break; - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - /* In Fortran, an upper bound may be T... meaning a parameter specifies - the length of the data. In this case, just pretend the bound is 1. - This happens only for array parameters, which are really passed - as pointers anyway, and we will translate them into such. */ - if (**pp == 'T') - { - n = 1; - while (**pp != ';') - (*pp)++; - } - else - n = read_number (pp, ';') + 1; - TYPE_TARGET_TYPE (type) = read_type (pp); - TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type)) * n; - break; -#endif - - default: - error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.", - (*pp)[-1], symnum); - } - - if (type == 0) - abort (); - -#if 0 - /* If this is an overriding temporary alteration for a header file's - contents, and this type number is unknown in the global definition, - put this type into the global definition at this type number. */ - if (header_file_prev_index >= 0) - { - register struct type **tp - = explicit_lookup_type (header_file_prev_index, typenums[1]); - if (*tp == 0) - *tp = type; - } -#endif - return type; -} - -/* This page contains subroutines of read_type. */ - -/* Read the description of a structure (or union type) - and return an object describing the type. */ - -static struct type * -read_struct_type (pp, type) - char **pp; - register struct type *type; -{ - struct nextfield - { - struct nextfield *next; - int visibility; - struct field field; - }; - - struct next_fnfield - { - struct next_fnfield *next; - int visibility; - struct fn_field fn_field; - }; - - struct next_fnfieldlist - { - struct next_fnfieldlist *next; - struct fn_fieldlist fn_fieldlist; - }; - - register struct nextfield *list = 0; - struct nextfield *new; - int totalsize; - char *name; - register char *p; - int nfields = 0; - register int n; - - register struct next_fnfieldlist *mainlist = 0; - int nfn_fields = 0; - struct type *baseclass = NULL; - int read_possible_virtual_info = 0; - - TYPE_CODE (type) = TYPE_CODE_STRUCT; - - /* First comes the total size in bytes. */ - - TYPE_LENGTH (type) = read_number (pp, 0); - - /* C++: Now, if the class is a derived class, then the next character - will be a '!', followed by the number of base classes derived from. - Each element in the list contains visibility information, - the offset of this base class in the derived structure, - and then the base type. */ - if (**pp == '!') - { - int i, n_baseclasses, offset; - struct type **baseclass_vec; - struct type *baseclass; - int via_public, via_virtual; - - *pp += 1; - - n_baseclasses = read_number (pp, ','); - baseclass_vec = (struct type **) - obstack_alloc (symbol_obstack, - (n_baseclasses) * sizeof (struct type **)) - 1; - - for (i = 1; i <= n_baseclasses; i++) - { - if (**pp == '\\') - *pp = next_symbol_text (); - - switch (*(*pp)++) - { - case '0': - via_virtual = 0; - break; - case '1': - via_virtual = 1; - break; - default: - error ("Invalid symbol data: bad visibility format at symtab pos %d", - symnum); - } - - switch (*(*pp)++) - { - case '0': - via_public = 0; - break; - case '2': - via_public = 1; - break; - default: - error ("Invalid symbol data: bad visibility format at symtab pos %d.", - symnum); - } - offset = read_number (pp, ','); - baseclass = read_type (pp); - *pp += 1; /* skip trailing ';' */ - baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public); - - /* Make this baseclass visible for structure-printing purposes. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - list->field.type = baseclass_vec[i]; - list->field.name = TYPE_NAME (baseclass_vec[i]); - list->field.bitpos = offset; - list->field.bitsize = 0; /* this should be an unpacked field! */ - nfields++; - } - TYPE_N_BASECLASSES (type) = n_baseclasses; - TYPE_BASECLASSES (type) = baseclass_vec; - } - - /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one. - At the end, we see a semicolon instead of a field. - - In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for - a static field. - - The `?' is a placeholder for one of '+' (public visibility), - '0' (protected visibility), and '-' (private visibility). */ - - while (**pp != ';') - { - int visibility; - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Read the data. */ - p = *pp; - while (*p != ':') p++; - list->field.name = obsavestring (*pp, p - *pp); - - /* C++: Check to see if we have hit the methods yet. */ - if (p[1] == ':') - break; - - *pp = p + 1; - - /* This means we have a visibility for a field coming. */ - if (**pp == '/') - { - switch (*++*pp) - { - case '0': - visibility = 0; - *pp += 1; - break; - - case '1': - visibility = 1; - *pp += 1; - break; - - case '2': - visibility = 2; - *pp += 1; - break; - } - } - /* else normal dbx-style format. */ - - list->field.type = read_type (pp); - if (**pp == ':') - { - list->field.bitpos = (long)-1; - p = ++(*pp); - while (*p != ';') p++; - list->field.bitsize = (long) savestring (*pp, p - *pp); - *pp = p + 1; - nfields++; - continue; - } - else if (**pp != ',') - error ("Invalid symbol data: bad structure-type format at symtab pos %d.", - symnum); - (*pp)++; /* Skip the comma. */ - list->field.bitpos = read_number (pp, ','); - list->field.bitsize = read_number (pp, ';'); - /* Detect an unpacked field and mark it as such. - dbx gives a bit size for all fields. - Note that forward refs cannot be packed, - and treat enums as if they had the width of ints. */ - if (TYPE_CODE (list->field.type) != TYPE_CODE_INT - && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM) - list->field.bitsize = 0; - if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type) - || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM - && list->field.bitsize == 8 * TYPE_LENGTH (builtin_type_int))) - && - list->field.bitpos % 8 == 0) - list->field.bitsize = 0; - nfields++; - } - - /* Now come the method fields, as NAME::methods - where each method is of the form TYPENUM,ARGS,...:PHYSNAME; - At the end, we see a semicolon instead of a field. - - For the case of overloaded operators, the format is - OPERATOR::*.methods, where OPERATOR is the string "operator", - `*' holds the place for an operator name (such as `+=') - and `.' marks the end of the operator name. */ - if (p[1] == ':') - { - /* Now, read in the methods. To simplify matters, we - "unread" the name that has been read, so that we can - start from the top. */ - - p = *pp; - - /* chill the list of fields: the last entry (at the head) - is a partially constructed entry which we now scrub. */ - list = list->next; - - /* For each list of method lists... */ - do - { - int i; - struct next_fnfield *sublist = 0; - struct fn_field *fn_fields = 0; - int length = 0; - struct next_fnfieldlist *new_mainlist = - (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist)); - - /* read in the name. */ - while (*p != ':') p++; - if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$') - { - static char opname[32] = "operator "; - char *o = opname + 9; - - /* Skip past '::'. */ - p += 2; - while (*p != '.') - *o++ = *p++; - new_mainlist->fn_fieldlist.name = savestring (opname, o - opname); - /* Skip past '.' */ - *pp = p + 1; - } - else - { - i = 0; - new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp); - /* Skip past '::'. */ - *pp = p + 2; - } - - do - { - struct next_fnfield *new_sublist = - (struct next_fnfield *)alloca (sizeof (struct next_fnfield)); - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - new_sublist->fn_field.type = read_type (pp); - new_sublist->fn_field.args = read_args (pp, ':'); - p = *pp; - while (*p != ';') p++; - new_sublist->fn_field.physname = savestring (*pp, p - *pp); - *pp = p + 1; - new_sublist->visibility = *(*pp)++ - '0'; - if (**pp == '\\') *pp = next_symbol_text (); - - if (*(*pp)++ == '*') - new_sublist->fn_field.voffset = read_number (pp, ';') + 1; - else - new_sublist->fn_field.voffset = 0; - - new_sublist->next = sublist; - sublist = new_sublist; - length++; - } - while (**pp != ';'); - - *pp += 1; - - new_mainlist->fn_fieldlist.fn_fields = - (struct fn_field *) obstack_alloc (symbol_obstack, - sizeof (struct fn_field) * length); - TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (length >> 5))); - - TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (length >> 5))); - - for (i = length; sublist; sublist = sublist->next) - { - new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field; - if (sublist->visibility == 0) - B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i); - else if (sublist->visibility == 1) - B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i); - } - - new_mainlist->fn_fieldlist.length = length; - new_mainlist->next = mainlist; - mainlist = new_mainlist; - nfn_fields++; - } - while (**pp != ';'); - } - - *pp += 1; - - /* Now create the vector of fields, and record how big it is. */ - - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, - sizeof (struct field) * nfields); - TYPE_FIELD_PRIVATE_BITS (type) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (nfields >> 5))); - TYPE_FIELD_PROTECTED_BITS (type) = - (int *) obstack_alloc (symbol_obstack, - sizeof (int) * (1 + (nfields >> 5))); - - TYPE_NFN_FIELDS (type) = nfn_fields; - TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields; - if (baseclass) - TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass); - - TYPE_FN_FIELDLISTS (type) = - (struct fn_fieldlist *) obstack_alloc (symbol_obstack, - sizeof (struct fn_fieldlist) * nfn_fields); - - /* Copy the saved-up fields into the field vector. */ - - for (n = nfields; list; list = list->next) - { - TYPE_FIELD (type, --n) = list->field; - if (list->visibility == 0) - SET_TYPE_FIELD_PRIVATE (type, n); - else if (list->visibility == 1) - SET_TYPE_FIELD_PROTECTED (type, n); - } - - for (n = nfn_fields; mainlist; mainlist = mainlist->next) - TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist; - - if (**pp == '~') - { - *pp += 1; - - if (**pp == '=') - { - TYPE_FLAGS (type) - |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR; - *pp += 1; - } - else if (**pp == '+') - { - TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR; - *pp += 1; - } - else if (**pp == '-') - { - TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR; - *pp += 1; - } - - /* Read either a '%' or the final ';'. */ - if (*(*pp)++ == '%') - { - /* Now we must record the virtual function table pointer's - field information. */ - - struct type *t; - int i; - - t = read_type (pp); - p = (*pp)++; - while (*p != ';') p++; - TYPE_VPTR_BASETYPE (type) = t; - if (type == t) - { - if (TYPE_FIELD_NAME (t, 0) == 0) - TYPE_VPTR_FIELDNO (type) = i = 0; - else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i) - if (! strncmp (TYPE_FIELD_NAME (t, i), *pp, - strlen (TYPE_FIELD_NAME (t, i)))) - { - TYPE_VPTR_FIELDNO (type) = i; - break; - } - if (i < 0) - error ("virtual function table field not found"); - } - else - TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1)); - *pp = p + 1; - } - else - { - TYPE_VPTR_BASETYPE (type) = 0; - TYPE_VPTR_FIELDNO (type) = -1; - } - } - else - { - TYPE_VPTR_BASETYPE (type) = 0; - TYPE_VPTR_FIELDNO (type) = -1; - } - - return type; -} - -/* Read a definition of an enumberation type, - and create and return a suitable type object. - Also creates a range type which represents the bounds of that - array. */ -static struct type * -read_array_type (pp, type) - register char **pp; - register struct type *type; -{ - struct type *index_type, *element_type, *range_type; - int lower, upper; - - /* Format of an array type: - "ar<index type>;lower;upper;<array_contents_type>". Put code in - to handle this. */ - - index_type = read_type (pp); - if (*(*pp)++ != ';') - error ("Invalid symbol data; improper format of array type decl."); - lower = read_number (pp, ';'); - upper = read_number (pp, ';'); - element_type = read_type (pp); - - { - /* Create range type. */ - range_type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - TYPE_CODE (range_type) = TYPE_CODE_RANGE; - TYPE_TARGET_TYPE (range_type) = index_type; - - /* This should never be needed. */ - 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) = lower; - TYPE_FIELD_BITPOS (range_type, 1) = upper; - } - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (type) = element_type; - TYPE_LENGTH (type) = (upper - lower + 1) * TYPE_LENGTH (element_type); - TYPE_NFIELDS (type) = 1; - TYPE_FIELDS (type) = - (struct field *) obstack_alloc (symbol_obstack, - sizeof (struct field)); - TYPE_FIELD_TYPE (type, 0) = range_type; - - return type; -} - - -/* Read a definition of an enumeration type, - and create and return a suitable type object. - Also defines the symbols that represent the values of the type. */ - -static struct type * -read_enum_type (pp, type) - register char **pp; - register struct type *type; -{ - register char *p; - char *name; - register long n; - register struct symbol *sym; - int nsyms = 0; - struct pending **symlist; - struct pending *osyms, *syms; - int o_nsyms; - - if (within_function) - symlist = &local_symbols; - else - symlist = &file_symbols; - osyms = *symlist; - o_nsyms = osyms ? osyms->nsyms : 0; - - /* Read the value-names and their values. - The input syntax is NAME:VALUE,NAME:VALUE, and so on. - A semicolon instead of a NAME means the end. */ - while (**pp && **pp != ';') - { - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') *pp = next_symbol_text (); - - p = *pp; - while (*p != ':') p++; - name = obsavestring (*pp, p - *pp); - *pp = p + 1; - n = read_number (pp, ','); - - sym = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - bzero (sym, sizeof (struct symbol)); - SYMBOL_NAME (sym) = name; - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_VALUE (sym) = n; - add_symbol_to_list (sym, symlist); - nsyms++; - } - - (*pp)++; /* Skip the semicolon. */ - - /* Now fill in the fields of the type-structure. */ - - TYPE_LENGTH (type) = sizeof (int); - TYPE_CODE (type) = TYPE_CODE_ENUM; - TYPE_NFIELDS (type) = nsyms; - TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); - - /* Find the symbols for the values and put them into the type. - The symbols can be found in the symlist that we put them on - to cause them to be defined. osyms contains the old value - of that symlist; everything up to there was defined by us. */ - - for (syms = *symlist, n = nsyms; syms; syms = syms->next) - { - int j = 0; - if (syms == osyms) - j = o_nsyms; - for (; j < syms->nsyms; j++) - { - struct symbol *sym = syms->symbol[j]; - SYMBOL_TYPE (sym) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (sym); - TYPE_FIELD_VALUE (type, n) = 0; - TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (sym); - TYPE_FIELD_BITSIZE (type, n) = 0; - } - if (syms == osyms) - break; - } - - return type; -} - -#define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - 1) -#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 1))) - -static struct type * -read_range_type (pp, typenums) - char **pp; - int typenums[2]; -{ - char *errp = *pp; - int rangenums[2]; - int n2, n3; - int self_subrange; - struct type *result_type; - - /* First comes a type we are a subrange of. - In C it is usually 0, 1 or the type being defined. */ - read_type_number (pp, rangenums); - self_subrange = (rangenums[0] == typenums[0] && - rangenums[1] == typenums[1]); - - /* A semicolon should now follow; skip it. */ - if (**pp == ';') - (*pp)++; - - /* The remaining two operands are usually lower and upper bounds - of the range. But in some special cases they mean something else. */ - n2 = read_number (pp, ';'); - n3 = read_number (pp, ';'); - - /* A type defined as a subrange of itself, with bounds both 0, is void. */ - if (self_subrange && n2 == 0 && n3 == 0) - return builtin_type_void; - - /* If n3 is zero and n2 is not, we want a floating type, - and n2 is the width in bytes. - - Fortran programs appear to use this for complex types also, - and they give no way to distinguish between double and single-complex! - We don't have complex types, so we would lose on all fortran files! - So return type `double' for all of those. It won't work right - for the complex values, but at least it makes the file loadable. */ - - if (n3 == 0 && n2 > 0) - { - if (n2 == sizeof (float)) - return builtin_type_float; - return builtin_type_double; - } - - /* If the upper bound is -1, it must really be an unsigned int. */ - - else if (n2 == 0 && n3 == -1) - { - if (sizeof (int) == sizeof (long)) - return builtin_type_unsigned_int; - else - return builtin_type_unsigned_long; - } - - /* Special case: char is defined (Who knows why) as a subrange of - itself with range 0-127. */ - else if (self_subrange && n2 == 0 && n3 == 127) - return builtin_type_char; - - /* Assumptions made here: Subrange of self is equivalent to subrange - of int. */ - else if (n2 == 0 - && (self_subrange || - *dbx_lookup_type (rangenums) == builtin_type_int)) - { - /* an unsigned type */ - if (n3 == (1 << (8 * sizeof (int))) - 1) - return builtin_type_unsigned_int; - if (n3 == (1 << (8 * sizeof (short))) - 1) - return builtin_type_unsigned_short; - if (n3 == (1 << (8 * sizeof (char))) - 1) - return builtin_type_unsigned_char; - } - else if (n2 == -n3 -1) - { - /* a signed type */ - if (n3 == (1 << (8 * sizeof (int) - 1)) - 1) - return builtin_type_int; - if (n3 == (1 << (8 * sizeof (long) - 1)) - 1) - return builtin_type_long; - if (n3 == (1 << (8 * sizeof (short) - 1)) - 1) - return builtin_type_short; - if (n3 == (1 << (8 * sizeof (char) - 1)) - 1) - return builtin_type_char; - } - - /* We have a real range type on our hands. Allocate space and - return a real pointer. */ - - /* At this point I don't have the faintest idea how to deal with - a self_subrange type; I'm going to assume that this is used - as an idiom, and that all of them are special cases. So . . . */ - if (self_subrange) - error ("Type defined as subrange of itself."); - - result_type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (result_type, sizeof (struct type)); - - TYPE_TARGET_TYPE (result_type) = (self_subrange ? - builtin_type_int : - *dbx_lookup_type(rangenums)); - - /* We have to figure out how many bytes it takes to hold this - range type. I'm going to assume that anything that is pushing - the bounds of a long was taken care of above. */ - if (n2 >= MIN_OF_TYPE(char) && n3 <= MAX_OF_TYPE(char)) - TYPE_LENGTH (result_type) = 1; - else if (n2 >= MIN_OF_TYPE(short) && n3 <= MAX_OF_TYPE(short)) - TYPE_LENGTH (result_type) = sizeof (short); - else if (n2 >= MIN_OF_TYPE(int) && n3 <= MAX_OF_TYPE(int)) - TYPE_LENGTH (result_type) = sizeof (int); - else if (n2 >= MIN_OF_TYPE(long) && n3 <= MAX_OF_TYPE(long)) - TYPE_LENGTH (result_type) = sizeof (long); - else - error ("Ranged type doesn't fit within known sizes."); - - TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type)); - TYPE_CODE (result_type) = TYPE_CODE_RANGE; - TYPE_NFIELDS (result_type) = 2; - TYPE_FIELDS (result_type) = - (struct field *) obstack_alloc (symbol_obstack, - 2 * sizeof (struct field)); - bzero (TYPE_FIELDS (result_type), 2 * sizeof (struct field)); - TYPE_FIELD_BITPOS (result_type, 0) = n2; - TYPE_FIELD_BITPOS (result_type, 1) = n3; - - return result_type; -} - -/* Read a number from the string pointed to by *PP. - The value of *PP is advanced over the number. - If END is nonzero, the character that ends the - number must match END, or an error happens; - and that character is skipped if it does match. - If END is zero, *PP is left pointing to that character. */ - -static long -read_number (pp, end) - char **pp; - int end; -{ - register char *p = *pp; - register long n = 0; - register int c; - int sign = 1; - - /* Handle an optional leading minus sign. */ - - if (*p == '-') - { - sign = -1; - p++; - } - - /* Read the digits, as far as they go. */ - - while ((c = *p++) >= '0' && c <= '9') - { - n *= 10; - n += c - '0'; - } - if (end) - { - if (c && c != end) - error ("Invalid symbol data: invalid character \\%03o at symbol pos %d.", c, symnum); - } - else - --p; - - *pp = p; - return n * sign; -} - -/* Read in an argument list. This is a list of types. It is terminated with - a ':', FYI. Return the list of types read in. */ -static struct type ** -read_args (pp, end) - char **pp; - int end; -{ - struct type *types[1024], **rval; /* allow for fns of 1023 parameters */ - int n = 0; - - while (**pp != end) - { - if (**pp != ',') - error ("Invalid argument list: no ',', at symtab pos %d", symnum); - *pp += 1; - - /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); - - types[n++] = read_type (pp); - } - *pp += 1; /* get past `end' (the ':' character) */ - - if (n == 1) - { - rval = (struct type **) xmalloc (2 * sizeof (struct type *)); - } - else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID) - { - rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *)); - bzero (rval + n, sizeof (struct type *)); - } - else - { - rval = (struct type **) xmalloc (n * sizeof (struct type *)); - } - bcopy (types, rval, n * sizeof (struct type *)); - return rval; -} - -/* 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); -} - -void -_initialize_dbxread () -{ - symfile = 0; - header_files = (struct header_file *) 0; - this_object_header_files = (int *) 0; - - add_com ("symbol-file", class_files, symbol_file_command, - "Load symbol table (in dbx format) from executable file FILE."); - - add_com ("add-file", class_files, add_file_command, - "Load the symbols from FILE, assuming its code is at TEXT_START.") ; -} - -#endif /* READ_DBX_FORMAT */ -@ - - -1.2 -log -@If discarding the symbol table, discard its name too, so "info files" -will give the right answer. -@ -text -@d27 1 -a27 1 -#include <sys/fcntl.h> -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. -d1457 3 -@ diff --git a/gdb/RCS/default-dep.c,v b/gdb/RCS/default-dep.c,v deleted file mode 100644 index 81c18f3..0000000 --- a/gdb/RCS/default-dep.c,v +++ /dev/null @@ -1,731 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.4 -date 89.03.27.20.08.50; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.20.07.47; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.27.18.49.06; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.19.47.11; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@Restore A/UX-specific changes. -@ -text -@/* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" - -#ifdef USG -#include <sys/types.h> -#endif - -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#define mc68881 /* Needed to get float in user.h!!! */ -#include <sys/seg.h> /* For user.h */ -#include <sys/mmu.h> -#include <sys/time.h> -/* Things Unisoft defined differently from every other Unix system */ -#define NBPG PAGESIZE -#define UPAGES USIZE -#define KERNEL_U_ADDR UDOT -#endif - -#include <stdio.h> -#include <sys/param.h> -#include <sys/dir.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <fcntl.h> - -#ifdef COFF_ENCAPSULATE -#include "a.out.encap.h" -#else -#include <a.out.h> -#endif -#ifndef N_SET_MAGIC -#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val)) -#endif - -#include <sys/user.h> /* After a.out.h */ -#include <sys/file.h> -#include <sys/stat.h> - -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. - - If you are having trouble debugging ptrace calls, turn on DEBUG - and every call to ptrace, in this module or elsewhere, will be - logged to stderr. */ -int -call_ptrace (request, pid, arg3, arg4) - int request, pid, arg3, arg4; -{ -#ifdef DEBUG - int result; - - fprintf(stderr, "ptrace(%x,,%x, %x) = ", request, arg3, arg4); - result=ptrace (request, pid, arg3, arg4); - fprintf(stderr, "%x\n", result); - return result; - -#define ptrace call_ptrace - -#else - return ptrace (request, pid, arg3, arg4); -#endif -} - -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"); - } -} - -void -fetch_inferior_registers () -{ - register int regno; - register unsigned int regaddr; - char buf[MAX_REGISTER_RAW_SIZE]; - register int i; - - struct user u; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; - offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; - - for (regno = 0; regno < NUM_REGS; regno++) - { - regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) - { - *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0); - regaddr += sizeof (int); - } - supply_register (regno, 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]; - - struct user u; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; - offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR; - - if (regno >= 0) - { - regaddr = register_addr (regno, offset); - errno = 0; -#ifdef UNISOFT_ASSHOLES - /* You can't write the PC with ptrace 6, only with ptrace 11! */ - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); - if (errno != 0) - { - sprintf (buf, "writing register number %d", regno); - perror_with_name (buf); - } - } - else for (regno = 0; regno < NUM_REGS; regno++) - { - regaddr = register_addr (regno, offset); - errno = 0; -#ifdef UNISOFT_ASSHOLES - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); - if (errno != 0) - { - sprintf (buf, "writing all regs, number %d", regno); - perror_with_name (buf); - } - } -} - -/* 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 (remote_debugging) - buffer[i] = remote_fetch_word (addr); - else - 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. */ - -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - -#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 -#define AOUTHDR struct exec -#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; - -#ifdef COFF_FORMAT -/* 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) - { - 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; - - 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; Unisoft - seems to put the offset in the upage of the regs. Sigh. */ - 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; - - for (regno = 0; regno < NUM_REGS; regno++) - { - char buf[MAX_REGISTER_RAW_SIZE]; - - val = lseek (corechan, register_addr (regno, reg_offset), 0); - if (val < 0) - perror_with_name (reg_names[regno]); - - val = myread (corechan, buf, sizeof buf); - if (val < 0) - perror_with_name (reg_names[regno]); - 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) - { - execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, - &execfile); - if (execchan < 0) - perror_with_name (filename); - -#ifdef COFF_FORMAT - { - 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 = text_hdr.s_scnptr; - exec_data_start = exec_aouthdr.data_start; - exec_data_end = exec_data_start + exec_aouthdr.dsize; - exec_data_offset = data_hdr.s_scnptr; - data_start = exec_data_start; - data_end += exec_data_start; - exec_mtime = file_hdr.f_timdat; - } -#else /* not COFF_FORMAT */ - { - struct stat st_exec; - -#ifdef HEADER_SEEK_FD - HEADER_SEEK_FD (execchan); -#endif - - val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); - - if (val < 0) - perror_with_name (filename); - - text_start = N_TXTADDR (exec_aouthdr); - exec_data_start = N_DATADDR (exec_aouthdr); - - text_offset = N_TXTOFF (exec_aouthdr); - exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; - - text_end = text_start + exec_aouthdr.a_text; - exec_data_end = exec_data_start + exec_aouthdr.a_data; - data_start = exec_data_start; - data_end += exec_data_start; - - fstat (execchan, &st_exec); - exec_mtime = st_exec.st_mtime; - } -#endif /* not COFF_FORMAT */ - - 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); -} -@ - - -1.3 -log -@Remove A/UX-specific changes for shipping to FSF. -@ -text -@d30 13 -d176 7 -a182 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d193 6 -a198 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -@ - - -1.2 -log -@A/UX and USG changes, and a little better error reporting. -@ -text -@a29 13 -#ifdef UNISOFT_ASSHOLES -#define PMMU -#define NEW_PMMU -#define mc68881 /* Needed to get float in user.h!!! */ -#include <sys/seg.h> /* For user.h */ -#include <sys/mmu.h> -#include <sys/time.h> -/* Things Unisoft defined differently from every other Unix system */ -#define NBPG PAGESIZE -#define UPAGES USIZE -#define KERNEL_U_ADDR UDOT -#endif - -d163 1 -a163 7 -#ifdef UNISOFT_ASSHOLES - /* You can't write the PC with ptrace 6, only with ptrace 11! */ - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d174 1 -a174 6 -#ifdef UNISOFT_ASSHOLES - if (regno == PC_REGNUM) - ptrace(11, inferior_pid, 16, read_register(regno)); - else -#endif - ptrace (6, inferior_pid, regaddr, read_register (regno)); -@ - - -1.1 -log -@Initial revision -@ -text -@d30 13 -a46 1 -#include <sys/user.h> -d58 2 -d67 5 -a71 1 - machine-dependent file. */ -d76 11 -d88 1 -d176 7 -a182 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d193 6 -a198 1 - ptrace (6, inferior_pid, regaddr, read_register (regno)); -d201 1 -a201 1 - sprintf (buf, "writing register number %d", regno); -d446 3 -a448 1 - perror_with_name (filename); -d455 6 -a460 1 - reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR; -d478 1 -a478 1 - perror_with_name (filename); -d482 1 -a482 1 - perror_with_name (filename); -@ diff --git a/gdb/RCS/findvar.c,v b/gdb/RCS/findvar.c,v deleted file mode 100644 index 9095f2b..0000000 --- a/gdb/RCS/findvar.c,v +++ /dev/null @@ -1,584 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.01.06.46; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@use XXX_BIG_ENDIAN macros rather than runtime tests. -@ -text -@/* Find a variable's value in memory, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" -#include "value.h" - -CORE_ADDR read_register (); - -/* Return the address in which frame FRAME's value of register REGNUM - has been saved in memory. Or return zero if it has not been saved. - If REGNUM specifies the SP, the value we return is actually - the SP value, not an address where it was saved. */ - -CORE_ADDR -find_saved_register (frame, regnum) - FRAME frame; - int regnum; -{ - struct frame_info *fi; - struct frame_saved_regs saved_regs; - - register FRAME frame1 = 0; - register CORE_ADDR addr = 0; - -#ifdef HAVE_REGISTER_WINDOWS - /* We assume that a register in a register window will only be saved - in one place (since the name changes and dissapears as you go - towards inner frames), so we only call get_frame_saved_regs on - the current frame. This is directly in contradiction to the - usage below, which assumes that registers used in a frame must be - saved in a lower (more interior) frame. This change is a result - of working on a register window machine; get_frame_saved_regs - always returns the registers saved within a frame, within the - context (register namespace) of that frame. */ - - if (REGISTER_IN_WINDOW_P(regnum)) - { - fi = get_frame_info (frame); - get_frame_saved_regs (fi, &saved_regs); - return (saved_regs.regs[regnum] ? - saved_regs.regs[regnum] : 0); - } -#endif /* HAVE_REGISTER_WINDOWS */ - - /* Note that this next routine assumes that registers used in - frame x will be saved only in the frame that x calls and - frames interior to it. This is not true on the sparc, but the - above macro takes care of it, so we should be all right. */ - while (1) - { - QUIT; - frame1 = get_prev_frame (frame1); - if (frame1 == 0 || frame1 == frame) - break; - fi = get_frame_info (frame1); - get_frame_saved_regs (fi, &saved_regs); - if (saved_regs.regs[regnum]) - addr = saved_regs.regs[regnum]; - } - - return addr; -} - -/* Copy the bytes of register REGNUM, relative to the current stack frame, - into our memory at MYADDR. - The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). */ - -void -read_relative_register_raw_bytes (regnum, myaddr) - int regnum; - char *myaddr; -{ - register CORE_ADDR addr; - - if (regnum == FP_REGNUM) - { - bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR)); - return; - } - - addr = find_saved_register (selected_frame, regnum); - - if (addr) - { - if (regnum == SP_REGNUM) - { - CORE_ADDR buffer = addr; - bcopy (&buffer, myaddr, sizeof (CORE_ADDR)); - } - else - read_memory (addr, myaddr, REGISTER_RAW_SIZE (regnum)); - return; - } - read_register_bytes (REGISTER_BYTE (regnum), - myaddr, REGISTER_RAW_SIZE (regnum)); -} - -/* Return a `value' with the contents of register REGNUM - in its virtual format, with the type specified by - REGISTER_VIRTUAL_TYPE. */ - -value -value_of_register (regnum) - int regnum; -{ - register CORE_ADDR addr; - register value val; - char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; - - if (! (have_inferior_p () || have_core_file_p ())) - error ("Can't get value of register without inferior or core file"); - - addr = find_saved_register (selected_frame, regnum); - if (addr) - { - if (regnum == SP_REGNUM) - return value_from_long (builtin_type_int, (LONGEST) addr); - read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum)); - } - else - read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, - REGISTER_RAW_SIZE (regnum)); - - REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer); - val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); - bcopy (virtual_buffer, VALUE_CONTENTS (val), REGISTER_VIRTUAL_SIZE (regnum)); - VALUE_LVAL (val) = addr ? lval_memory : lval_register; - VALUE_ADDRESS (val) = addr ? addr : REGISTER_BYTE (regnum); - VALUE_REGNO (val) = regnum; - return val; -} - -/* Low level examining and depositing of registers. - - Note that you must call `fetch_registers' once - before examining or depositing any registers. */ - -char registers[REGISTER_BYTES]; - -/* Copy LEN bytes of consecutive data from registers - starting with the REGBYTE'th byte of register data - into memory at MYADDR. */ - -void -read_register_bytes (regbyte, myaddr, len) - int regbyte; - char *myaddr; - int len; -{ - bcopy (®isters[regbyte], myaddr, len); -} - -/* Copy LEN bytes of consecutive data from memory at MYADDR - into registers starting with the REGBYTE'th byte of register data. */ - -void -write_register_bytes (regbyte, myaddr, len) - int regbyte; - char *myaddr; - int len; -{ - bcopy (myaddr, ®isters[regbyte], len); - if (have_inferior_p ()) - store_inferior_registers (-1); -} - -/* Return the contents of register REGNO, - regarding it as an integer. */ - -CORE_ADDR -read_register (regno) - int regno; -{ - /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */ - return *(int *) ®isters[REGISTER_BYTE (regno)]; -} - -/* Store VALUE in the register number REGNO, regarded as an integer. */ - -void -write_register (regno, val) - int regno, val; -{ - /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */ -#if defined(sun4) - /* This is a no-op on a Sun 4. */ - if (regno == 0) - return; -#endif - - *(int *) ®isters[REGISTER_BYTE (regno)] = val; - - if (have_inferior_p ()) - store_inferior_registers (regno); -} - -/* Record that register REGNO contains VAL. - This is used when the value is obtained from the inferior or core dump, - so there is no need to store the value there. */ - -void -supply_register (regno, val) - int regno; - char *val; -{ - bcopy (val, ®isters[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno)); -} - -/* Given a struct symbol for a variable, - and a stack frame address, read the value of the variable - and return a (pointer to a) struct value containing the value. */ - -value -read_var_value (var, frame) - register struct symbol *var; - FRAME frame; -{ - register value v; - - struct frame_info *fi; - - struct type *type = SYMBOL_TYPE (var); - register CORE_ADDR addr = 0; - int val = SYMBOL_VALUE (var); - register int len; - - v = allocate_value (type); - VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */ - len = TYPE_LENGTH (type); - - if (frame == 0) frame = selected_frame; - - switch (SYMBOL_CLASS (var)) - { - case LOC_CONST: - case LOC_LABEL: - bcopy (&val, VALUE_CONTENTS (v), len); - VALUE_LVAL (v) = not_lval; - return v; - - case LOC_CONST_BYTES: - bcopy (val, VALUE_CONTENTS (v), len); - VALUE_LVAL (v) = not_lval; - return v; - - case LOC_STATIC: - addr = val; - break; - - case LOC_ARG: - fi = get_frame_info (frame); - addr = val + FRAME_ARGS_ADDRESS (fi); - break; - - case LOC_LOCAL: - fi = get_frame_info (frame); - addr = val + FRAME_LOCALS_ADDRESS (fi); - break; - - case LOC_TYPEDEF: - error ("Cannot look up value of a typedef"); - - case LOC_BLOCK: - VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); - return v; - - case LOC_REGISTER: - case LOC_REGPARM: - v = value_from_register (type, val, frame); - return v; - } - - read_memory (addr, VALUE_CONTENTS (v), len); - VALUE_ADDRESS (v) = addr; - return v; -} - -/* Return a value of type TYPE, stored in register REGNUM, in frame - FRAME. */ - -value -value_from_register (type, regnum, frame) - struct type *type; - int regnum; - FRAME frame; -{ - char raw_buffer [MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; - CORE_ADDR addr; - value v = allocate_value (type); - int len = TYPE_LENGTH (type); - char *value_bytes = 0; - int value_bytes_copied = 0; - int num_storage_locs; - - VALUE_REGNO (v) = regnum; - - num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ? - ((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 : - 1); - - if (num_storage_locs > 1) - { - /* Value spread across multiple storage locations. */ - - int local_regnum; - int mem_stor = 0, reg_stor = 0; - int mem_tracking = 1; - CORE_ADDR last_addr = 0; - - value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE); - - /* Copy all of the data out, whereever it may be. */ - - for (local_regnum = regnum; - value_bytes_copied < len; - (value_bytes_copied += REGISTER_RAW_SIZE (local_regnum), - ++local_regnum)) - { - int register_index = local_regnum - regnum; - addr = find_saved_register (frame, local_regnum); - if (addr == 0) - { - read_register_bytes (REGISTER_BYTE (local_regnum), - value_bytes + value_bytes_copied, - REGISTER_RAW_SIZE (local_regnum)); - reg_stor++; - } - else - { - read_memory (addr, value_bytes + value_bytes_copied, - REGISTER_RAW_SIZE (local_regnum)); - mem_stor++; - mem_tracking = - (mem_tracking - && (regnum == local_regnum - || addr == last_addr)); - } - last_addr = addr; - } - - if ((reg_stor && mem_stor) - || (mem_stor && !mem_tracking)) - /* Mixed storage; all of the hassle we just went through was - for some good purpose. */ - { - VALUE_LVAL (v) = lval_reg_frame_relative; - VALUE_FRAME (v) = FRAME_FP (frame); - VALUE_FRAME_REGNUM (v) = regnum; - } - else if (mem_stor) - { - VALUE_LVAL (v) = lval_memory; - VALUE_ADDRESS (v) = find_saved_register (frame, regnum); - } - else if (reg_stor) - { - VALUE_LVAL (v) = lval_register; - VALUE_ADDRESS (v) = REGISTER_BYTE (regnum); - } - else - fatal ("value_from_register: Value not stored anywhere!"); - - /* Any structure stored in more than one register will always be - an inegral number of registers. Otherwise, you'd need to do - some fiddling with the last register copied here for little - endian machines. */ - - /* Copy into the contents section of the value. */ - bcopy (value_bytes, VALUE_CONTENTS (v), len); - - return v; - } - - /* Data is completely contained within a single register. Locate the - register's contents in a real register or in core; - read the data in raw format. */ - - addr = find_saved_register (frame, regnum); - if (addr == 0) - { - /* Value is really in a register. */ - - VALUE_LVAL (v) = lval_register; - VALUE_ADDRESS (v) = REGISTER_BYTE (regnum); - - read_register_bytes (REGISTER_BYTE (regnum), - raw_buffer, REGISTER_RAW_SIZE (regnum)); - } - else - { - /* Value was in a register that has been saved in memory. */ - - read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum)); - VALUE_LVAL (v) = lval_memory; - VALUE_ADDRESS (v) = addr; - } - - /* Convert the raw contents to virtual contents. - (Just copy them if the formats are the same.) */ - - REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer); - - if (REGISTER_CONVERTIBLE (regnum)) - { - /* When the raw and virtual formats differ, the virtual format - corresponds to a specific data type. If we want that type, - copy the data into the value. - Otherwise, do a type-conversion. */ - - if (type != REGISTER_VIRTUAL_TYPE (regnum)) - { - /* eg a variable of type `float' in a 68881 register - with raw type `extended' and virtual type `double'. - Fetch it as a `double' and then convert to `float'. */ - v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum)); - bcopy (virtual_buffer, VALUE_CONTENTS (v), len); - v = value_cast (type, v); - } - else - bcopy (virtual_buffer, VALUE_CONTENTS (v), len); - } - else - { - /* Raw and virtual formats are the same for this register. */ - -#ifdef BYTES_BIG_ENDIAN - if (len < REGISTER_RAW_SIZE (regnum)) - { - /* Big-endian, and we want less than full size. */ - VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len; - } -#endif - - bcopy (virtual_buffer + VALUE_OFFSET (v), - VALUE_CONTENTS (v), len); - } - - return v; -} - -/* Given a struct symbol for a variable, - and a stack frame address, - return a (pointer to a) struct value containing the variable's address. */ - -value -locate_var_value (var, frame) - register struct symbol *var; - FRAME frame; -{ - register CORE_ADDR addr = 0; - int val = SYMBOL_VALUE (var); - struct frame_info *fi; - struct type *type = SYMBOL_TYPE (var); - - if (frame == 0) frame = selected_frame; - - switch (SYMBOL_CLASS (var)) - { - case LOC_CONST: - case LOC_CONST_BYTES: - error ("Address requested for identifier \"%s\" which is a constant.", - SYMBOL_NAME (var)); - - case LOC_REGISTER: - case LOC_REGPARM: - addr = find_saved_register (frame, val); - if (addr != 0) - { - int len = TYPE_LENGTH (type); -#ifdef BYTES_BIG_ENDIAN - if (len < REGISTER_RAW_SIZE (val)) - /* Big-endian, and we want less than full size. */ - addr += REGISTER_RAW_SIZE (val) - len; -#endif - break; - } - error ("Address requested for identifier \"%s\" which is in a register.", - SYMBOL_NAME (var)); - - case LOC_STATIC: - case LOC_LABEL: - addr = val; - break; - - case LOC_ARG: - fi = get_frame_info (frame); - addr = val + FRAME_ARGS_ADDRESS (fi); - break; - - case LOC_LOCAL: - fi = get_frame_info (frame); - addr = val + FRAME_LOCALS_ADDRESS (fi); - break; - - case LOC_TYPEDEF: - error ("Address requested for identifier \"%s\" which is a typedef.", - SYMBOL_NAME (var)); - - case LOC_BLOCK: - addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); - break; - } - - return value_cast (lookup_pointer_type (type), - value_from_long (builtin_type_long, (LONGEST) addr)); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d448 2 -a449 5 - union { int i; char c; } test; - /* If we want less than the full size, we need to - test for a big-endian or little-endian machine. */ - test.i = 1; - if (test.c != 1 && len < REGISTER_RAW_SIZE (regnum)) -d454 2 -a455 1 - -a490 1 - union { int i; char c; } test; -d492 2 -a493 4 - /* If var is less than the full size of register, we need to - test for a big-endian or little-endian machine. */ - test.i = 1; - if (test.c != 1 && len < REGISTER_RAW_SIZE (val)) -d496 1 -@ diff --git a/gdb/RCS/gdb.texinfo,v b/gdb/RCS/gdb.texinfo,v deleted file mode 100644 index ff38f18..0000000 --- a/gdb/RCS/gdb.texinfo,v +++ /dev/null @@ -1,3009 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @@; - - -1.2 -date 89.02.10.01.41.38; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.00.33.03; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Improve doc in various ways, mostly xref{Expressions} so you can -find out what an expression is (I had trouble finding it, since -it's in a nested menu somewhere.) -@ -text -@\input texinfo -@@setfilename ../info/gdb -@@settitle GDB, The GNU Debugger -@@ifinfo -This file documents the GNU debugger GDB. - -Copyright (C) 1988 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -@@ignore -Permission is granted to process this file through Tex and print the -results, provided the printed document carries copying permission -notice identical to this one except for the removal of this paragraph -(this paragraph not being relevant to the printed manual). - -@@end ignore -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. -@@end ifinfo - -@@setchapternewpage odd -@@settitle GDB Manual -@@titlepage -@@sp 6 -@@center @@titlefont{GDB Manual} -@@sp 1 -@@center The GNU Source-Level Debugger -@@sp 4 -@@center Third Edition, GDB version 3.1 -@@sp 1 -@@center January 1989 -@@sp 5 -@@center Richard M. Stallman -@@page -@@vskip 0pt plus 1filll -Copyright @@copyright{} 1988, 1989 Free Software Foundation, Inc. - -Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided also that the -sections entitled ``Distribution'' and ``GDB General Public License'' are -included exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that the sections entitled ``Distribution'' and ``GDB General Public -License'' may be included in a translation approved by the author instead -of in the original English. -@@end titlepage -@@page - -@@node Top, Commands,, (DIR) -@@unnumbered Summary of GDB - -The purpose of a debugger such as GDB is to allow you to execute another -program while examining what is going on inside it. We call the other -program ``your program'' or ``the program being debugged''. - -GDB can do four kinds of things (plus other things in support of these): - -@@enumerate -@@item -Start the program, specifying anything that might affect its behavior. - -@@item -Make the program stop on specified conditions. - -@@item -Examine what has happened, when the program has stopped, so that you -can see bugs happen. - -@@item -Change things in the program, so you can correct the effects of one bug -and go on to learn about another without having to recompile first. -@@end enumerate - -GDB can be used to debug programs written in C and C++. Pascal support -is being implemented, and Fortran support will be added when a GNU -Fortran compiler is written. - -@@menu -* License:: The GDB General Public License gives you permission - to redistribute GDB on certain terms; and also - explains that there is no warranty. -* Input:: GDB command syntax and input conventions. -* Files:: Specifying files for GDB to operate on. -* Options:: GDB arguments and options. -* Compilation::Compiling your program so you can debug it. -* Running:: Running your program under GDB. -* Stopping:: Making your program stop. Why it may stop. What to do then. -* Stack:: Examining your program's stack. -* Source:: Examining your program's source files. -* Data:: Examining data in your program. -* Symbols:: Examining the debugger's symbol table. -* Altering:: Altering things in your program. -* Sequences:: Canned command sequences for repeated use. -* Emacs:: Using GDB through GNU Emacs. -* Remote:: Remote kernel debugging across a serial line. -* Commands:: Index of GDB commands. -* Concepts:: Index of GDB concepts. -@@end menu - -@@node License, Input, Top, Top -@@unnumbered GDB General Public License -@@center (Clarified 11 Feb 1988) - - The license agreements of most software companies keep you at the mercy -of those companies. By contrast, our general public license is intended to -give everyone the right to share GDB. To make sure that you get the rights -we want you to have, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. Hence this -license agreement. - - Specifically, we want to make sure that you have the right to give away -copies of GDB, that you receive source code or else can get it if you want -it, that you can change GDB or use pieces of it in new free programs, and -that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute copies -of GDB, you must give the recipients all the rights that you have. You -must make sure that they, too, receive or can get the source code. And you -must tell them their rights. - - Also, for our own protection, we must make certain that everyone finds -out that there is no warranty for GDB. If GDB is modified by someone else -and passed on, we want its recipients to know that what they have is not -what we distributed, so that any problems introduced by others will not -reflect on our reputation. - - Therefore we (Richard Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be -allowed to distribute or change GDB. - -@@unnumberedsec Copying Policies - -@@enumerate -@@item -You may copy and distribute verbatim copies of GDB source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each file a valid copyright notice ``Copyright -@@copyright{} 1988 Free Software Foundation, Inc.'' (or with whatever year -is appropriate); keep intact the notices on all files that -refer to this License Agreement and to the absence of any warranty; and -give any other recipients of the GDB program a copy of this License -Agreement along with the program. You may charge a distribution fee -for the physical act of transferring a copy. - -@@item -You may modify your copy or copies of GDB source code or any portion -of it, and copy and distribute such modifications under the terms of -Paragraph 1 above, provided that you also do the following: - -@@itemize @@bullet -@@item -cause the modified files to carry prominent notices stating -that you changed the files and the date of any change; and - -@@item -cause the whole of any work that you distribute or publish, that -in whole or in part contains or is a derivative of GDB or any -part thereof, to be licensed at no charge to all third parties on -terms identical to those contained in this License Agreement -(except that you may choose to grant more extensive warranty -protection to some or all third parties, at your option). - -@@item -if the modified program serves as a debugger, cause it, when -started running in the simplest and usual way, to print an -announcement including a valid copyright notice ``Copyright -@@copyright{} 1988 Free Software Foundation, Inc.'' (or with the -year that is appropriate), saying that there is no warranty (or -else, saying that you provide a warranty) and that users may -redistribute the program under these conditions, and telling the -user how to view a copy of this License Agreement. - -@@item -You may charge a distribution fee for the physical act of -transferring a copy, and you may at your option offer warranty -protection in exchange for a fee. -@@end itemize - -Mere aggregation of another unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - -@@item -You may copy and distribute GDB (or a portion or derivative of it, -under Paragraph 2) in object code or executable form under the terms -of Paragraphs 1 and 2 above provided that you also do one of the -following: - -@@itemize @@bullet -@@item -accompany it with the complete corresponding machine-readable -source code, which must be distributed under the terms of -Paragraphs 1 and 2 above; or, - -@@item -accompany it with a written offer, valid for at least three -years, to give any third party free (except for a nominal -shipping charge) a complete machine-readable copy of the -corresponding source code, to be distributed under the terms of -Paragraphs 1 and 2 above; or, - -@@item -accompany it with the information you received as to where the -corresponding source code may be obtained. (This alternative is -allowed only for noncommercial distribution and only if you -received the program in object code or executable form alone.) -@@end itemize - -For an executable file, complete source code means all the source code -for all modules it contains; but, as a special exception, it need not -include source code for modules which are standard libraries that -accompany the operating system on which the executable file runs. - -@@item -You may not copy, sublicense, distribute or transfer GDB except as -expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer GDB is void and -your rights to use GDB under this License agreement shall be -automatically terminated. However, parties who have received computer -software programs from you with this License Agreement will not have -their licenses terminated so long as such parties remain in full -compliance. - -@@item -If you wish to incorporate parts of GDB into other free programs whose -distribution conditions are different, write to the Free Software -Foundation. We have not yet worked out a simple rule that can be -stated here, but we will often permit this. We will be guided by the -two goals of preserving the free status of all derivatives our free -software and of promoting the sharing and reuse of software. -@@end enumerate - -@@iftex -@@vfil -@@eject -@@end iftex -@@unnumberedsec NO WARRANTY - - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, THE FREE SOFTWARE FOUNDATION, INC, -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB ``AS IS'' -WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY -AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE GDB -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY -SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE -FOUNDATION, INC., RICHARD M. STALLMAN, AND/OR ANY OTHER PARTY WHO MAY -MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY -FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY -OTHER PARTY. - -@@node Input, Files, License, Top -@@chapter GDB Input Conventions - -GDB is invoked with the shell command @@samp{gdb}. Once started, it reads -commands from the terminal until you tell it to exit. - -A GDB command is a single line of input. There is no limit on how long -it can be. It starts with a command name, which is followed by arguments -whose meaning depends on the command name. Some command names do not -allow arguments. - -GDB command names may always be abbreviated if the abbreviation is -unambiguous. Sometimes even ambiguous abbreviations are allowed; for -example, @@samp{s} is specially defined as equivalent to @@samp{step} -even though there are other commands whose names start with @@samp{s}. -Possible command abbreviations are often stated in the documentation -of the individual commands. - -A blank line as input to GDB means to repeat the previous command verbatim. -Certain commands do not allow themselves to be repeated this way; these are -commands for which unintentional repetition might cause trouble and which -you are unlikely to want to repeat. Certain others (@@samp{list} and -@@samp{x}) act differently when repeated because that is more useful. - -A line of input starting with @@samp{#} is a comment; it does nothing. -This is useful mainly in command files (@@xref{Command Files}). - -Occasionally it is useful to execute a shell command from within gdb. -This can be done with the @@samp{shell} command, or the shell escape -character @@samp{!}. - -@@table @@code -@@item shell @@var{shell command string} -@@kindex shell -@@item !@@var{shell command string} -@@kindex ! -@@cindex shell escape -Directs GDB to invoke an inferior shell to execute @@samp{shell command string}. -The environmental variable @@samp{SHELL} is used if it exists, otherwise gdb -uses @@samp{/bin/sh}. -@@end table - -GDB @@dfn{prompts} for commands with a string that is normally @@samp{(gdb)}. -When debugging GDB with GDB, it is useful to change the prompt in one of -the GDBs so that you can distinguish them. This can be done with the -@@samp{set prompt} command. - -@@table @@code -@@item set prompt @@var{newprompt} -@@kindex set prompt -Directs GDB to use @@var{newprompt} as its prompt string henceforth. -@@end table - -@@cindex exiting GDB -@@kindex quit -To exit GDB, use the @@samp{quit} command (abbreviated @@samp{q}). -@@kbd{Ctrl-c} will not exit from GDB, but rather will terminate the action -of any GDB command that is in progress and return to GDB command level. -It is safe to type @@kbd{Ctrl-c} at any time because GDB does not allow -it to take effect until a time when it is safe. - -@@node Files, Options, Input, Top -@@chapter Specifying GDB's Files - -@@cindex core dump file -@@cindex executable file -@@cindex symbol table -GDB needs to know the filename of the program to be debugged. To debug a -core dump of a previous run, GDB must be told the filename of the core -dump. - -@@menu -* Arguments: File Arguments. Specifying files with arguments - (when you start GDB). -* Commands: File Commands. Specifying files with GDB commands. -@@end menu - -@@node File Arguments, File Commands, Files, Files -@@section Specifying Files with Arguments - -The usual way to specify the executable and core dump file names is with -two command arguments given when you start GDB. The first argument is used -as the file for execution and symbols, and the second argument (if any) is -used as the core dump file name. Thus, - -@@example -gdb progm core -@@end example - -@@noindent -specifies @@file{progm} as the executable program and @@file{core} as a core -dump file to examine. (You do not need to have a core dump file if what -you plan to do is debug the program interactively.) - -@@xref{Options}, for full information on command options and arguments for -GDB. - -@@node File Commands,, File Arguments, Files -@@section Specifying Files with Commands - -Usually you specify the files for GDB to work with by giving arguments when -you invoke GDB. But occasionally it is necessary to change to a different -file during a GDB session. Or you may run GDB and forget to specify the -files you want to use. In these situations the GDB commands to specify new -files are useful. - -@@table @@code -@@item exec-file @@var{filename} -@@kindex exec-file -Specify that the program to be run is found in @@var{filename}. If you -do not specify a directory and the file is not found in GDB's working -directory, GDB will use the environment variable @@samp{PATH} as a list -of directories to search, just as the shell does when looking for a -program to run. - -@@item symbol-file @@var{filename} -@@kindex symbol-file -Read symbol table information from file @@var{filename}. @@samp{PATH} -is searched when necessary. Most of the time you will use both the -@@samp{exec-file} and @@samp{symbol-file} commands on the same file. - -@@samp{symbol-file} with no argument clears out GDB's symbol table. - -@@item core-file @@var{filename} -@@kindex core-file -Specify the whereabouts of a core dump file to be used as the -``contents of memory''. Note that the core dump contains only the -writable parts of memory; the read-only parts must come from the -executable file. - -@@samp{core-file} with no argument specifies that no core file is -to be used. - -@@item add-file @@var{filename} @@var{address} -@@kindex add-file -The @@samp{add-file} command takes two arguments, a file name, and the -address at which that file has been (or should be) dynamically loaded. -GDB will then treat that file as though it had always been dynamically -linked, and provide the user with all the normal GDB features, including -symbolic debugging. - -With the @@samp{add-file} command, it is possible to debug code which was -not present in the initial load image of the program under test. -Suppose you have a program which can, while running, dynamically link a -program fragment into its address space. One program which does this is -KCL, a free common lisp implementation. The fragment will be loaded -into the main program's address space at some address, and the main -program can then call functions within the fragment by calculating (or -otherwise obtaining) their addresses. - -@@item kill -@@kindex kill -Cancel running the program under GDB. This could be used if you wish -to debug a core dump instead. GDB ignores any core dump file if it is -actually running the program, so the @@samp{kill} command is the only -sure way to go back to using the core dump file. - -@@item info files -@@kindex info files -Print the names of the executable and core dump files currently in -use by GDB, and the file from which symbols were loaded. -@@end table - -While all three file-specifying commands allow both absolute and relative -file names as arguments, GDB always converts the file name to an absolute -one and remembers it that way. - -The @@samp{symbol-file} command causes GDB to forget the contents of its -convenience variables, the value history, and all breakpoints and -auto-display expressions. This is because they may contain pointers to the -internal data recording symbols and data types, which are part of the old -symbol table data being discarded inside GDB. - -@@node Options, Compilation, Files, Top -@@chapter Options and Arguments for GDB - -When you invoke GDB, you can pass commands telling it what files to -operate on and what other things to do. - -@@menu -* Mode Options:: Options controlling modes of operation. -* File Options:: Options to specify files (executable, coredump, commands) -* Other Arguments:: Any other arguments without options - also specify files. -@@end menu - -@@node Mode Options, File Options, Options, Options -@@section Mode Options - -@@table @@samp -@@item -nx -Do not execute commands from the init files @@file{.gdbinit}. -Normally, the commands in these files are executed after all the -command options and arguments have been processed. @@xref{Command -Files}. - -@@item -q -``Quiet''. Do not print the usual introductory messages. - -@@item -batch -Run in batch mode. Exit with code 1 after processing all the command -files specified with @@samp{-x} (and @@file{.gdbinit}, if not -inhibited). Exit also if, due to an error, GDB would otherwise -attempt to read a command from the terminal. - -@@item -fullname -This option is used when Emacs runs GDB as a subprocess. It tells GDB -to output the full file name and line number in a standard, -recognizable fashion each time a stack frame is displayed (which -includes each time the program stops). This recognizable format looks -like two @@samp{\032} characters, followed by the filename, line number -and character position separated by colons, and a newline. The -Emacs-to-GDB interface program uses the two @@samp{\032} characters as -a signal to display the source code for the frame. -@@end table - -@@node File Options, Other Arguments, Mode Options, Options -@@section File-specifying Options - -All the options and command line arguments given are processed -in sequential order. The order makes a difference when the -@@samp{-x} command is used. - -@@table @@samp -@@item -s @@var{file} -Read symbol table from file @@var{file}. - -@@item -e @@var{file} -Use file @@var{file} as the executable file to execute when -appropriate, and for examining pure data in conjunction with a core -dump. - -@@item -se @@var{file} -Read symbol table from file @@var{file} and use it as the executable -file. - -@@item -c @@var{file} -Use file @@var{file} as a core dump to examine. - -@@item -x @@var{file} -Execute GDB commands from file @@var{file}. - -@@item -d @@var{directory} -Add @@var{directory} to the path to search for source files. -@@end table - -@@node Other Arguments,, File Options, Options -@@section Other Arguments - -If there are arguments to GDB that are not options or associated with -options, the first one specifies the symbol table and executable file name -(as if it were preceded by @@samp{-se}) and the second one specifies a core -dump file name (as if it were preceded by @@samp{-c}). - -@@node Compilation, Running, Options, Top -@@chapter Compiling Your Program for Debugging - -In order to debug a program effectively, you need to ask for debugging -information when you compile it. This information in the object file -describes the data type of each variable or function and the correspondence -between source line numbers and addresses in the executable code. - -To request debugging information, specify the @@samp{-g} option when you run -the compiler. - -The Unix C compiler is unable to handle the @@samp{-g} and @@samp{-O} options -together. This means that you cannot ask for optimization if you ask for -debugger information. - -The GNU C compiler supports @@samp{-g} with or without @@samp{-O}, making it -possible to debug optimized code. We recommend that you @@emph{always} use -@@samp{-g} whenever you compile a program. You may think the program is -correct, but there's no sense in pushing your luck. - -If you are using the GNU C compiler, the GNU assembler and the GNU linker, -you can choose between two formats of debugging information: the standard -Unix format, which is what you get with @@samp{-g}, and GDB's own format, -which you request by using @@samp{-gg} instead of @@samp{-g}. This stores -debugging information in the executable file in a format much like that -which is used inside GDB. This has these advantages and disadvantages: - -@@itemize @@bullet -@@item -GDB can read @@samp{-gg} format more than twice as fast as Unix -@@samp{-g} format. - -@@item -The @@samp{-gg} format uses much more disk space than Unix format. - -@@item -The Unix debuggers can understand only Unix format, so you cannot use -Unix source-level debuggers if you compile with @@samp{-gg}. (The -@@code{adb} debugger works with either format; it does not use this -information in any case.) -@@end itemize - -@@node Running, Stopping, Compilation, Top -@@chapter Running Your Program Under GDB - -@@cindex running -@@kindex run -To start your program under GDB, use the @@samp{run} command. The program -must already have been specified using the @@samp{exec-file} command or with -an argument to GDB (@@pxref{Files}); what @@samp{run} does is create an -inferior process, load the program into it, and set it in motion. - -The execution of a program is affected by certain information it receives -from its superior. GDB provides ways to specify them, which you must do -@@i{before} starting the program. (You can change them after starting the -program, but such changes do not affect the program unless you start it -over again.) - -@@table @@asis -@@item The @@i{arguments.} -You specify the arguments to give the program as the arguments of the -@@samp{run} command. - -@@item The @@i{environment.} -The program normally inherits its environment from GDB, but you can -use the GDB commands @@samp{set environment} and -@@samp{unset environment} to change parts of the environment that will -be given to the program.@@refill - -@@item The @@i{working directory.} -The program inherits its working directory from GDB. You can set GDB's -working directory with the @@samp{cd} command in GDB. -@@end table - -After the @@samp{run} command, the debugger does nothing but wait for your -program to stop. @@xref{Stopping}. - -Note that once your program has been started by the @@samp{run} command, -you may evaluate expressions that involve calls to functions in the -inferior. @@xref{Expressions}. If you wish to evaluate a function -simply for it's side affects, you may use the @@samp{set} command. -@@xref{Assignment}. - -@@menu -* Arguments:: Specifying the arguments for your program. -* Environment:: Specifying the environment for your program. -* Working Directory:: Specifying the working directory for giving - to your program when it is run. -* Input/Output:: Specifying the program's standard input and output. -* Attach:: Debugging a process started outside GDB. -@@end menu - -@@node Arguments, Environment, Running, Running -@@section Your Program's Arguments - -@@cindex arguments (to your program) -You specify the arguments to give the program as the arguments of the -@@samp{run} command. They are passed to a shell, which expands wildcard -characters and performs redirection of I/O, and thence to the program. - -@@samp{run} with no arguments uses the same arguments used by the previous -@@samp{run}. - -@@kindex set args -The command @@samp{set args} can be used to specify the arguments to be used -the next time the program is run. If @@samp{set args} has no arguments, it -means to use no arguments the next time the program is run. If you have -run your program with arguments and want to run it again with no arguments, -this is the only way to do so. - -@@node Environment, Working Directory, Arguments, Running -@@section Your Program's Environment - -@@cindex environment (of your program) -The @@dfn{environment} consists of a set of @@dfn{environment variables} and -their values. Environment variables conventionally record such things as -your user name, your home directory, your terminal type, and your search -path for programs to run. Usually you set up environment variables with -the shell and they are inherited by all the other programs you run. When -debugging, it can be useful to try running the program with different -environments without having to start the debugger over again. - -@@table @@code -@@item info environment @@var{varname} -@@kindex info environment -Print the value of environment variable @@var{varname} to be given to -your program when it is started. This command can be abbreviated -@@samp{i env @@var{varname}}. - -@@item info environment -Print the names and values of all environment variables to be given to -your program when it is started. This command can be abbreviated -@@samp{i env}. - -@@item set environment @@var{varname} @@var{value} -@@item set environment @@var{varname} = @@var{value} -@@kindex set environment -Sets environment variable @@var{varname} to @@var{value}, for your program -only, not for GDB itself. @@var{value} may be any string; the values of -environment variables are just strings, and any interpretation is -supplied by your program itself. The @@var{value} parameter is optional; -if it is eliminated, the variable is set to a null value. This command -can be abbreviated as short as @@samp{set e}. - -@@item delete environment @@var{varname} -@@kindex delete environment -@@item unset environment @@var{varname} -@@kindex unset environment -Remove variable @@var{varname} from the environment to be passed to -your program. This is different from @@samp{set env @@var{varname} =} -because @@samp{delete environment} makes a variable not be defined at -all, which is distinguishable from an empty value. This command can -be abbreviated @@samp{d e}. -@@end table - -@@node Working Directory, Input/Output, Environment, Running -@@section Your Program's Working Directory - -@@cindex working directory (of your program) -Each time you start your program with @@samp{run}, it inherits its working -directory from the current working directory of GDB. GDB's working -directory is initially whatever it inherited from its superior, but you can -specify the working directory for GDB with the @@samp{cd} command. - -The GDB working directory also serves as a default for the commands -that specify files for GDB to operate on. @@xref{Files}. - -@@table @@code -@@item cd @@var{directory} -@@kindex cd -Set GDB's working directory to @@var{directory}. - -@@item pwd -@@kindex pwd -Print GDB's working directory. -@@end table - -@@node Input/Output, Attach, Working Directory, Running -@@section Your Program's Input and Output - -@@cindex redirection -@@cindex controlling terminal -By default, the program you run under GDB does input and output to the same -terminal that GDB uses. - -You can redirect the program's input and/or output using @@samp{sh}-style -redirection commands in the @@samp{run} command. For example, - -@@example -run > outfile -@@end example - -@@noindent -starts the program, diverting its output to the file @@file{outfile}. - -@@kindex tty -Another way to specify where the program should do input and output is with -the @@samp{tty} command. This command accepts a file name as argument, and -causes this file to be the default for future @@samp{run} commands. It also -resets the controlling terminal for future @@samp{run} commands. For -example, - -@@example -tty /dev/ttyb -@@end example - -@@noindent -directs that processes started with subsequent @@samp{run} commands default -to do input and output on the terminal @@file{/dev/ttyb} and sets the -controlling terminal to @@file{/dev/ttyb}. An explicit redirection in -@@samp{run} overrides the @@samp{tty} command's effect on input/output -redirection. - -When you use the @@samp{tty} command or redirect input in the @@samp{run} -command, the @@emph{input for your program} comes from the specified file, -but the input for GDB still comes from your terminal. - -@@node Attach,, Input/Output, Running -@@section Debugging an Already-Running Process -@@kindex detach -@@kindex attach -@@cindex attach - -Some operating systems (in particular, Sun) allow GDB to begin debugging an -already-running process that was started outside of GDB. To do this you -must use the @@samp{attach} command instead of the @@samp{run} command. - -The @@samp{attach} command requires one argument, which is the process-id of -the process you want to debug. (The usual way to find out the process-id -of the process is with the @@samp{ps} utility.) - -The first thing GDB does after arranging to debug the process is to stop -it. You can examine and modify an attached process with all the GDB -commands that ordinarily available when you start processes with -@@samp{run}. You can insert breakpoints; you can step and continue; you -can modify storage. If you would rather the process continue running, -use the @@samp{continue} command after attaching. - -When you are finished debugging the attached process, you can use the -@@samp{detach} command to release it from GDB's control. Detaching -the process continues its execution. After the @@samp{detach} command, -that process and GDB become completely independent once more, and you -are ready to @@samp{attach} another process or start one with @@samp{run}. - -If you exit GDB or use the @@samp{run} command while you have an attached -process, you kill that process. You will be asked for confirmation if you -try to do either of these things. - -@@node Stopping, Stack, Running, Top -@@chapter Stopping and Continuing - -When you run a program normally, it runs until exiting. The purpose -of using a debugger is so that you can stop it before that point; -or so that if the program runs into trouble you can find out why. - -@@menu -* Signals:: Fatal signals in your program just stop it; - then you can use GDB to see what is going on. -* Breakpoints:: Breakpoints let you stop your program when it - reaches a specified point in the code. -* Continuing:: Resuming execution until the next signal or breakpoint. -* Stepping:: Stepping runs the program a short distance and - then stops it wherever it has come to. -@@end menu - -@@node Signals, Breakpoints, Stopping, Stopping -@@section Signals - -A signal is an asynchronous event that can happen in a program. The -operating system defines the possible kinds of signals, and gives each kind -a name and a number. For example, @@code{SIGINT} is the signal a program -gets when you type @@kbd{Ctrl-c}; @@code{SIGSEGV} is the signal a program -gets from referencing a place in memory far away from all the areas in use; -@@code{SIGALRM} occurs when the alarm clock timer goes off (which happens -only if the program has requested an alarm). - -Some signals, including @@code{SIGALRM}, are a normal part of the -functioning of the program. Others, such as @@code{SIGSEGV}, indicate -errors; these signals are @@dfn{fatal} (kill the program immediately) if the -program has not specified in advance some other way to handle the signal. -@@code{SIGINT} does not indicate an error in the program, but it is normally -fatal so it can carry out the purpose of @@kbd{Ctrl-c}: to kill the program. - -GDB has the ability to detect any occurrence of a signal in the program -running under GDB's control. You can tell GDB in advance what to do for -each kind of signal. - -Normally, GDB is set up to ignore non-erroneous signals like @@code{SIGALRM} -(so as not to interfere with their role in the functioning of the program) -but to stop the program immediately whenever an error signal happens. -You can change these settings with the @@samp{handle} command. You must -specify which signal you are talking about with its number. - -@@table @@code -@@item info signal -@@kindex info signal -Print a table of all the kinds of signals and how GDB has been told to -handle each one. You can use this to see the signal numbers of all -the defined types of signals. - -@@item handle @@var{signalnum} @@var{keywords}@@dots{} -@@kindex handle -Change the way GDB handles signal @@var{signalnum}. The @@var{keywords} -say what change to make. -@@end table - -To use the @@samp{handle} command you must know the code number of the -signal you are concerned with. To find the code number, type @@samp{info -signal} which prints a table of signal names and numbers. - -The keywords allowed by the handle command can be abbreviated. Their full -names are - -@@table @@code -@@item stop -GDB should stop the program when this signal happens. This implies -the @@samp{print} keyword as well. - -@@item print -GDB should print a message when this signal happens. - -@@item nostop -GDB should not stop the program when this signal happens. It may -still print a message telling you that the signal has come in. - -@@item noprint -GDB should not mention the occurrence of the signal at all. This -implies the @@samp{nostop} keyword as well. - -@@item pass -GDB should allow the program to see this signal; the program will be -able to handle the signal, or may be terminated if the signal is fatal -and not handled. - -@@item nopass -GDB should not allow the program to see this signal. -@@end table - -When a signal has been set to stop the program, the program cannot see the -signal until you continue. It will see the signal then, if @@samp{pass} is -in effect for the signal in question @@i{at that time}. In other words, -after GDB reports a signal, you can use the @@samp{handle} command with -@@samp{pass} or @@samp{nopass} to control whether that signal will be seen by -the program when you later continue it. - -You can also use the @@samp{signal} command to prevent the program from -seeing a signal, or cause it to see a signal it normally would not see, -or to give it any signal at any time. @@xref{Signaling}. - -@@node Breakpoints, Continuing, Signals, Stopping -@@section Breakpoints - -@@cindex breakpoints -A @@dfn{breakpoint} makes your program stop whenever a certain point in the -program is reached. You set breakpoints explicitly with GDB commands, -specifying the place where the program should stop by line number, function -name or exact address in the program. You can add various other conditions -to control whether the program will stop. - -Each breakpoint is assigned a number when it is created; these numbers are -successive integers starting with 1. In many of the commands for controlling -various features of breakpoints you use the breakpoint number to say which -breakpoint you want to change. Each breakpoint may be @@dfn{enabled} or -@@dfn{disabled}; if disabled, it has no effect on the program until you -enable it again. - -@@kindex info break -@@kindex $_ -The command @@samp{info break} prints a list of all breakpoints set and not -cleared, showing their numbers, where in the program they are, and any -special features in use for them. Disabled breakpoints are included in the -list, but marked as disabled. @@samp{info break} with a breakpoint number -as argument lists only that breakpoint. The convenience variable @@samp{$_} -and the default examining-address for the @@samp{x} command are set to the -address of the last breakpoint listed (@@pxref{Memory}). - -@@menu -* Set Breaks:: How to establish breakpoints. -* Clear Breaks:: How to remove breakpoints no longer needed. -* Disabling:: How to disable breakpoints (turn them off temporarily). -* Conditions:: Making extra conditions on whether to stop. -* Break Commands:: Commands to be executed at a breakpoint. -* Error in Breakpoints:: "Cannot insert breakpoints" error--why, what to do. -@@end menu - -@@node Set Breaks, Clear Breaks, Breakpoints, Breakpoints -@@subsection Setting Breakpoints - -@@kindex break -Breakpoints are set with the @@samp{break} command (abbreviated @@samp{b}). -You have several ways to say where the breakpoint should go. - -@@table @@code -@@item break @@var{function} -Set a breakpoint at entry to function @@var{function}. - -@@item break @@var{linenum} -Set a breakpoint at line @@var{linenum} in the current source file. -That file is the last file whose source text was printed. This -breakpoint will stop the program just before it executes any of the -code on that line. - -@@item break @@var{filename}:@@var{linenum} -Set a breakpoint at line @@var{linenum} in source file @@var{filename}. - -@@item break @@var{filename}:@@var{function} -Set a breakpoint at entry to function @@var{function} found in file -@@var{filename}. Specifying a filename as well as a function name is -superfluous except when multiple files contain similarly named -functions. - -@@item break *@@var{address} -Set a breakpoint at address @@var{address}. You can use this to set -breakpoints in parts of the program which do not have debugging -information or source files. - -@@item break -Set a breakpoint at the next instruction to be executed in the selected -stack frame (@@pxref{Stack}). In any selected frame but the innermost, -this will cause the program to stop as soon as control returns to that -frame. This is equivalent to a @@samp{finish} command in the frame -inside the selected frame. If this is done in the innermost frame gdb -will stop the next time it reaches the current location; this may be -useful inside of loops. It does not stop at this breakpoint immediately -upon continuation of the program since no code would be executed if it -did. - -@@item break @@dots{} if @@var{cond} -Set a breakpoint with condition @@var{cond}; evaluate the expression -@@var{cond} each time the breakpoint is reached, and stop only if the -value is nonzero. @@samp{@@dots{}} stands for one of the possible -arguments described above (or no argument) specifying where to break. -@@xref{Conditions}, for more information on breakpoint conditions. - -@@item tbreak @@var{args} -@@kindex tbreak -Set a breakpoint enabled only for one stop. @@var{args} are the -same as in the @@samp{break} command, and the breakpoint is set in the same -way, but the breakpoint is automatically @@dfn{disabled} the first time it -is hit. -@@end table - -GDB allows you to set any number of breakpoints at the same place in the -program. There is nothing silly or meaningless about this. When the -breakpoints are conditional, this is even useful (@@pxref{Conditions}). - -@@node Clear Breaks, Disabling, Set Breaks, Breakpoints -@@subsection Clearing Breakpoints - -@@cindex clear breakpoint -@@cindex delete breakpoints -It is often necessary to eliminate a breakpoint once it has done its job -and you no longer want the program to stop there. This is called -@@dfn{clearing} or @@samp{deleting} the breakpoint. A breakpoint that -has been cleared no longer exists in any sense. - -With the @@samp{clear} command you can clear breakpoints according to where -they are in the program. With the @@samp{delete} command you can clear -individual breakpoints by specifying their breakpoint numbers. - -@@b{It is not necessary to clear a breakpoint to proceed past it.} GDB -automatically ignores breakpoints in the first instruction to be executed -when you continue execution at the same address where the program stopped. - -@@table @@code -@@item clear -@@kindex clear -Clear any breakpoints at the next instruction to be executed in the -selected stack frame (@@pxref{Selection}). When the innermost frame -is selected, this is a good way to clear a breakpoint that the program -just stopped at. - -@@item clear @@var{function} -@@itemx clear @@var{filename}:@@var{function} -Clear any breakpoints set at entry to the function @@var{function}. - -@@item clear @@var{linenum} -@@item clear @@var{filename}:@@var{linenum} -Clear any breakpoints set at or within the code of the specified line. - -@@item delete @@var{bnums}@@dots{} -@@kindex delete -Delete the breakpoints of the numbers specified as arguments. -A breakpoint deleted is forgotten completely. -@@end table - -@@node Disabling, Conditions, Clear Breaks, Breakpoints -@@subsection Disabling Breakpoints - -@@cindex disabled breakpoints -@@cindex enabled breakpoints -Rather than clearing a breakpoint, you might prefer to @@dfn{disable} it. -This makes the breakpoint inoperative as if it had been cleared, but -remembers the information on the breakpoint so that you can @@dfn{enable} -it again later. - -You disable and enable breakpoints with the @@samp{enable} and -@@samp{disable} commands, specifying one or more breakpoint numbers as -arguments. Use @@samp{info break} to print a list of breakpoints if you -don't know which breakpoint numbers to use. - -A breakpoint can have any of four different states of enablement: - -@@itemize @@bullet -@@item -Enabled. The breakpoint will stop the program. A breakpoint made -with the @@samp{break} command starts out in this state. -@@item -Disabled. The breakpoint has no effect on the program. -@@item -Enabled once. The breakpoint will stop the program, but -when it does so it will become disabled. A breakpoint made -with the @@samp{tbreak} command starts out in this state. -@@item -Enabled for deletion. The breakpoint will stop the program, but -immediately after it does so it will be deleted permanently. -@@end itemize - -You change the state of enablement of a breakpoint with the following -commands: - -@@table @@code -@@item disable breakpoints @@var{bnums}@@dots{} -@@kindex disable breakpoints -@@item disable @@var{bnums}@@dots{} -@@kindex disable -Disable the specified breakpoints. A disabled breakpoint has no -effect but is not forgotten. All options such as ignore-counts, -conditions and commands are remembered in case the breakpoint is -enabled again later. - -@@item enable breakpoints @@var{bnums}@@dots{} -@@kindex enable breakpoints -@@item enable @@var{bnums}@@dots{} -@@kindex enable -Enable the specified breakpoints. They become effective once again in -stopping the program, until you specify otherwise. - -@@item enable breakpoints once @@var{bnums}@@dots{} -@@item enable once @@var{bnums}@@dots{} -Enable the specified breakpoints temporarily. Each will be disabled -again the next time it stops the program (unless you have used one of -these commands to specify a different state before that time comes). - -@@item enable breakpoints delete @@var{bnums}@@dots{} -@@item enable delete @@var{bnums}@@dots{} -Enable the specified breakpoints to work once and then die. Each of -the breakpoints will be deleted the next time it stops the program -(unless you have used one of these commands to specify a different -state before that time comes). -@@end table - -Aside from the automatic disablement or deletion of a breakpoint when it -stops the program, which happens only in certain states, the state of -enablement of a breakpoint changes only when one of the commands above -is used. - -@@node Conditions, Break Commands, Disabling, Breakpoints -@@subsection Break Conditions - -@@cindex conditions -The simplest sort of breakpoint breaks every time the program reaches a -specified place. You can also specify a @@dfn{condition} for a breakpoint. -A condition is just a boolean expression in your programming language -(@@xref{Expressions}). A breakpoint with a condition evaluates the -expression each time the program reaches it, and the program stops -only if the condition is true. - -Break conditions may have side effects, and may even call functions in your -program. These may sound like strange things to do, but their effects are -completely predictable unless there is another enabled breakpoint at the -same address. (In that case, GDB might see the other breakpoint first and -stop the program without checking the condition of this one.) Note that -breakpoint commands are usually more convenient and flexible for the -purpose of performing side effects when a breakpoint is reached -(@@pxref{Break Commands}). - -Break conditions can be specified when a breakpoint is set, by using -@@samp{if} in the arguments to the @@samp{break} command. @@xref{Set Breaks}. -They can also be changed at any time with the @@samp{condition} command: - -@@table @@code -@@item condition @@var{bnum} @@var{expression} -@@kindex condition -Specify @@var{expression} as the break condition for breakpoint number -@@var{bnum}. From now on, this breakpoint will stop the program only if -the value of @@var{expression} is true (nonzero, in C). @@var{expression} -is not evaluated at the time the @@samp{condition} command is given. -@@xref{Expressions}. - -@@item condition @@var{bnum} -Remove the condition from breakpoint number @@var{bnum}. It becomes -an ordinary unconditional breakpoint. -@@end table - -@@cindex ignore count (of breakpoint) -A special feature is provided for one kind of condition: to prevent the -breakpoint from doing anything until it has been reached a certain number -of times. This is done with the @@dfn{ignore count} of the breakpoint. -When the program reaches a breakpoint whose ignore count is positive, then -instead of stopping, it just decrements the ignore count by one and -continues. - -@@table @@code -@@item ignore @@var{bnum} @@var{count} -@@kindex ignore -Set the ignore count of breakpoint number @@var{bnum} to @@var{count}. -The next @@var{count} times the breakpoint is reached, it will not stop. - -To make the breakpoint stop the next time it is reached, specify -a count of zero. - -@@item cont @@var{count} -Continue execution of the program, setting the ignore count of the -breakpoint that the program stopped at to @@var{count} minus one. -Continuing through the breakpoint does not itself count as one of -@@var{count}. Thus, the program will not stop at this breakpoint until the -@@var{count}'th time it is hit. - -This command is allowed only when the program stopped due to a -breakpoint. At other times, the argument to @@samp{cont} is ignored. -@@end table - -If a breakpoint has a positive ignore count and a condition, the condition -is not checked. Once the ignore count reaches zero, the condition will -start to be checked. - -Note that you could achieve the effect of the ignore count with a condition -such as @@samp{$foo-- <= 0} using a debugger convenience variable that is -decremented each time. That is why the ignore count is considered a -special case of a condition. @@xref{Convenience Vars}. - -@@node Break Commands, Error in Breakpoints, Conditions, Breakpoints -@@subsection Commands Executed on Breaking - -@@cindex breakpoint commands -You can give any breakpoint a series of commands to execute when the -program stops due to that breakpoint. For example, you might want to -print the values of certain expressions, or enable other breakpoints. - -@@table @@code -@@item commands @@var{bnum} -Specify commands for breakpoint number @@var{bnum}. The commands -themselves appear on the following lines. Type a line containing just -@@samp{end} to terminate the commands. - -To remove all commands from a breakpoint, use the command -@@samp{commands} and follow it immediately by @@samp{end}; that is, give -no commands. - -With no arguments, @@samp{commands} refers to the last breakpoint set. -@@end table - -It is possible for breakpoint commands to start the program up again. -Simply use the @@samp{cont} command, or @@samp{step}, or any other command -to resume execution. However, any remaining breakpoint commands are -ignored. When the program stops again, GDB will act according to why -that stop took place. - -@@kindex silent -If the first command specified is @@samp{silent}, the usual message about -stopping at a breakpoint is not printed. This may be desirable for -breakpoints that are to print a specific message and then continue. -If the remaining commands too print nothing, you will see no sign that -the breakpoint was reached at all. @@samp{silent} is not really a command; -it is meaningful only at the beginning of the commands for a breakpoint. - -The commands @@samp{echo} and @@samp{output} that allow you to print precisely -controlled output are often useful in silent breakpoints. @@xref{Output}. - -For example, here is how you could use breakpoint commands to print the -value of @@code{x} at entry to @@code{foo} whenever it is positive. We -assume that the newly created breakpoint is number 4; @@samp{break} will -print the number that is assigned. - -@@example -break foo if x>0 -commands 4 -silent -echo x is\040 -output x -echo \n -cont -end -@@end example - -One application for breakpoint commands is to correct one bug so you can -test another. Put a breakpoint just after the erroneous line of code, give -it a condition to detect the case in which something erroneous has been -done, and give it commands to assign correct values to any variables that -need them. End with the @@samp{cont} command so that the program does not -stop, and start with the @@samp{silent} command so that no output is -produced. Here is an example: - -@@example -break 403 -commands 5 -silent -set x = y + 4 -cont -end -@@end example - -One deficiency in the operation of automatically continuing breakpoints -under Unix appears when your program uses raw mode for the terminal. -GDB switches back to its own terminal modes (not raw) before executing -commands, and then must switch back to raw mode when your program is -continued. This causes any pending terminal input to be lost. - -In the GNU system, this will be fixed by changing the behavior of -terminal modes. - -Under Unix, when you have this problem, you might be able to get around -it by putting your actions into the breakpoint condition instead of -commands. For example - -@@example -condition 5 (x = y + 4), 0 -@@end example - -@@noindent -is a condition expression (@@xref{Expressions}) that will change @@code{x} -as needed, then always have the value 0 so the program will not stop. -Loss of input is avoided here because break conditions are evaluated -without changing the terminal modes. When you want to have nontrivial -conditions for performing the side effects, the operators @@samp{&&}, -@@samp{||} and @@samp{?@@: @@dots{} :@@:} may be useful. - -@@node Error in Breakpoints,, Break Commands, Breakpoints -@@subsection ``Cannot Insert Breakpoints'' Error - -Under some Unix systems, breakpoints cannot be used in a program if any -other process is running that program. Attempting to run or continue -the program with a breakpoint in this case will cause GDB to stop it. - -When this happens, you have three ways to proceed: - -@@enumerate -@@item -Remove or disable the breakpoints, then continue. - -@@item -Suspend GDB, and copy the file containing the program to a new name. -Resume GDB and use the @@samp{exec-file} command to specify that GDB -should run the program under that name. Then start the program again. - -@@item -Recompile the program so that the text is non-sharable (a.out format -OMAGIC). -@@end enumerate - -@@node Continuing, Stepping, Breakpoints, Stopping -@@section Continuing - -After your program stops, most likely you will want it to run some more if -the bug you are looking for has not happened yet. - -@@table @@code -@@item cont -@@kindex cont -Continue running the program at the place where it stopped. -@@end table - -If the program stopped at a breakpoint, the place to continue running -is the address of the breakpoint. You might expect that continuing would -just stop at the same breakpoint immediately. In fact, @@samp{cont} -takes special care to prevent that from happening. You do not need -to clear the breakpoint to proceed through it after stopping at it. - -You can, however, specify an ignore-count for the breakpoint that the -program stopped at, by means of an argument to the @@samp{cont} command. -@@xref{Conditions}. - -If the program stopped because of a signal other than @@code{SIGINT} or -@@code{SIGTRAP}, continuing will cause the program to see that signal. -You may not want this to happen. For example, if the program stopped -due to some sort of memory reference error, you might store correct -values into the erroneous variables and continue, hoping to see more -execution; but the program would probably terminate immediately as -a result of the fatal signal once it sees the signal. To prevent this, -you can continue with @@samp{signal 0}. @@xref{Signaling}. You can -also act in advance to prevent the program from seeing certain kinds -of signals, using the @@samp{handle} command (@@pxref{Signals}). - -@@node Stepping,, Continuing, Stopping -@@section Stepping - -@@cindex stepping -@@dfn{Stepping} means setting your program in motion for a limited time, so -that control will return automatically to the debugger after one line of -code or one machine instruction. Breakpoints are active during stepping -and the program will stop for them even if it has not gone as far as the -stepping command specifies. - -@@table @@code -@@item step -@@kindex step -Proceed the program until control reaches a different line, then stop -it and return to the debugger. This command is abbreviated @@samp{s}. - -@@item step @@var{count} -Proceed as in @@samp{step}, but do so @@var{count} times. If a breakpoint -or a signal not related to stepping is reached before @@var{count} steps, -stepping stops right away. - -This command may be given when control is within a routine for which -there is no debugging information. In that case, execution will proceed -until control reaches a different routine, or is about to return from -this routine. An argument repeats this action. - -@@item next -@@kindex next -Similar to @@samp{step}, but any function calls appearing within the line of -code are executed without stopping. Execution stops when control reaches a -different line of code at the stack level which was executing when the -@@samp{next} command was given. This command is abbreviated @@samp{n}. - -An argument is a repeat count, as in @@samp{step}. - -@@samp{next} within a routine without debugging information acts as does -@@samp{step}, but any function calls appearing within the code of the -routine are executed without stopping. - -@@item finish -@@kindex finish -Continue running until just after the selected stack frame returns -(or until there is some other reason to stop, such as a fatal signal -or a breakpoint). Print value returned by the selected stack frame (if -any). - -Contrast this with the @@samp{return} command (@@pxref{Returning}). - -@@item until -@@kindex until -Proceed the program until control reaches a line greater than the current -line, then stop is and return to the debugger. Control is also returned to -the debugger if the program exits the current stack frame. Note that this -form of the command uses single stepping, and hence is slower than -@@samp{until} with an argument. This command is abbreviated @@samp{u}. - -@@item until @@var{location} -Proceed the program until either the specified location is reached, or the -current (innermost) stack frame returns. This form of the command uses -breakpoints, and hence is quicker than @@samp{until} without an argument. - -@@item stepi -@@itemx si -@@kindex stepi -@@kindex si -Proceed one machine instruction, then stop and return to the debugger. - -It is often useful to do @@samp{display/i $pc} when stepping by machine -instructions. This will cause the next instruction to be executed to -be displayed automatically at each stop. @@xref{Auto Display}. - -An argument is a repeat count, as in @@samp{step}. - -@@item nexti -@@itemx ni -@@kindex nexti -@@kindex ni -Proceed one machine instruction, but if it is a subroutine call, -proceed until the subroutine returns. - -An argument is a repeat count, as in @@samp{next}. -@@end table - -A typical technique for using stepping is to put a breakpoint -(@@pxref{Breakpoints}) at the beginning of the function or the section of -the program in which a problem is believed to lie, and then step through -the suspect area, examining the variables that are interesting, until the -problem happens. - -The @@samp{cont} command can be used after stepping to resume execution -until the next breakpoint or signal. - -@@node Stack, Source, Stopping, Top -@@chapter Examining the Stack - -When your program has stopped, the first thing you need to know is where it -stopped and how it got there. - -@@cindex call stack -Each time your program performs a function call, the information about -where in the program the call was made from is saved in a block of data -called a @@dfn{stack frame}. The frame also contains the arguments of the -call and the local variables of the function that was called. All the -stack frames are allocated in a region of memory called the @@dfn{call -stack}. - -When your program stops, the GDB commands for examining the stack allow you -to see all of this information. - -One of the stack frames is @@dfn{selected} by GDB and many GDB commands -refer implicitly to the selected frame. In particular, whenever you ask -GDB for the value of a variable in the program, the value is found in the -selected frame. There are special GDB commands to select whichever frame -you are interested in. - -When the program stops, GDB automatically selects the currently executing -frame and describes it briefly as the @@samp{frame} command does -(@@pxref{Frame Info, Info}). - -@@menu -* Frames:: Explanation of stack frames and terminology. -* Backtrace:: Summarizing many frames at once. -* Selection:: How to select a stack frame. -* Info: Frame Info, Commands to print information on stack frames. -@@end menu - -@@node Frames, Backtrace, Stack, Stack -@@section Stack Frames - -@@cindex frame -The call stack is divided up into contiguous pieces called @@dfn{frames}; -each frame is the data associated with one call to one function. The frame -contains the arguments given to the function, the function's local -variables, and the address at which the function is executing. - -@@cindex initial frame -@@cindex outermost frame -@@cindex innermost frame -When your program is started, the stack has only one frame, that of the -function @@code{main}. This is called the @@dfn{initial} frame or the -@@dfn{outermost} frame. Each time a function is called, a new frame is -made. Each time a function returns, the frame for that function invocation -is eliminated. If a function is recursive, there can be many frames for -the same function. The frame for the function in which execution is -actually occurring is called the @@dfn{innermost} frame. This is the most -recently created of all the stack frames that still exist. - -@@cindex frame pointer -Inside your program, stack frames are identified by their addresses. A -stack frame consists of many bytes, each of which has its own address; each -kind of computer has a convention for choosing one of those bytes whose -address serves as the address of the frame. Usually this address is kept -in a register called the @@dfn{frame pointer register} while execution is -going on in that frame. - -@@cindex frame number -GDB assigns numbers to all existing stack frames, starting with zero for -the innermost frame, one for the frame that called it, and so on upward. -These numbers do not really exist in your program; they are to give you a -way of talking about stack frames in GDB commands. - -@@cindex selected frame -Many GDB commands refer implicitly to one stack frame. GDB records a stack -frame that is called the @@dfn{selected} stack frame; you can select any -frame using one set of GDB commands, and then other commands will operate -on that frame. When your program stops, GDB automatically selects the -innermost frame. - -@@node Backtrace, Selection, Frames, Stack -@@section Backtraces - -A backtrace is a summary of how the program got where it is. It shows one -line per frame, for many frames, starting with the currently executing -frame (frame zero), followed by its caller (frame one), and on up the -stack. - -@@table @@code -@@item backtrace -@@itemx bt -Print a backtrace of the entire stack: one line per frame for all -frames in the stack. - -You can stop the backtrace at any time by typing the system interrupt -character, normally @@kbd{Control-C}. - -@@item backtrace @@var{n} -@@itemx bt @@var{n} -Similar, but stop after @@var{n} frames. - -@@item backtrace @@var{-n} -@@itemx bt @@var{-n} -Similar, but print the outermost @@var{n} frames instead of the -innermost. -@@end table - -Each line in a backtrace shows the frame number, the program counter, the -function and its arguments, and the source file name and line number (if -known). The program counter is omitted if is the beginning of the code for -the source line. This is the same as the first of the two lines printed -when you select a frame. - -@@node Selection, Frame Info, Backtrace, Stack -@@section Selecting a Frame - -Most commands for examining the stack and other data in the program work on -whichever stack frame is selected at the moment. Here are the commands for -selecting a stack frame; all of them finish by printing a brief description -of the stack frame just selected. - -@@table @@code -@@item frame @@var{n} -@@kindex frame -Select frame number @@var{n}. Recall that frame zero is the innermost -(currently executing) frame, frame one is the frame that called the -innermost one, and so on. The highest-numbered frame is @@code{main}'s -frame. - -@@item frame @@var{addr} -Select the frame at address @@var{addr}. This is useful mainly if the -chaining of stack frames has been damaged by a bug, making it -impossible for GDB to assign numbers properly to all frames. In -addition, this can be useful when the program has multiple stacks and -switches between them. - -@@item up @@var{n} -@@kindex up -Select the frame @@var{n} frames up from the frame previously selected. -For positive numbers @@var{n}, this advances toward the outermost -frame, to higher frame numbers, to frames that have existed longer. -@@var{n} defaults to one. - -@@item down @@var{n} -@@kindex down -Select the frame @@var{n} frames down from the frame previously -selected. For positive numbers @@var{n}, this advances toward the -innermost frame, to lower frame numbers, to frames that were created -more recently. @@var{n} defaults to one. -@@end table - -All of these commands end by printing some information on the frame that -has been selected: the frame number, the function name, the arguments, the -source file and line number of execution in that frame, and the text of -that source line. For example: - -@@example -#3 main (argc=3, argv=??, env=??) at main.c, line 67 -67 read_input_file (argv[i]); -@@end example - -After such a printout, the @@samp{list} command with no arguments will print -ten lines centered on the point of execution in the frame. @@xref{List}. - -@@node Frame Info,, Selection, Stack -@@section Information on a Frame - -There are several other commands to print information about the selected -stack frame. - -@@table @@code -@@item frame -This command prints a brief description of the selected stack frame. -It can be abbreviated @@samp{f}. With an argument, this command is -used to select a stack frame; with no argument, it does not change -which frame is selected, but still prints the same information. - -@@item info frame -@@kindex info frame -This command prints a verbose description of the selected stack frame, -including the address of the frame, the addresses of the next frame in -(called by this frame) and the next frame out (caller of this frame), -the address of the frame's arguments, the program counter saved in it -(the address of execution in the caller frame), and which registers -were saved in the frame. The verbose description is useful when -something has gone wrong that has made the stack format fail to fit -the usual conventions. - -@@item info frame @@var{addr} -Print a verbose description of the frame at address @@var{addr}, -without selecting that frame. The selected frame remains unchanged by -this command. - -@@item info args -@@kindex info args -Print the arguments of the selected frame, each on a separate line. - -@@item info locals -@@kindex info locals -Print the local variables of the selected frame, each on a separate -line. These are all variables declared static or automatic within all -program blocks that execution in this frame is currently inside of. -@@end table - -@@node Source, Data, Stack, Top -@@chapter Examining Source Files - -GDB knows which source files your program was compiled from, and -can print parts of their text. When your program stops, GDB -spontaneously prints the line it stopped in. Likewise, when you -select a stack frame (@@pxref{Selection}), GDB prints the line -which execution in that frame has stopped in. You can also -print parts of source files by explicit command. - -@@menu -* List:: Using the @@samp{list} command to print source files. -* Search:: Commands for searching source files. -* Source Path:: Specifying the directories to search for source files. -@@end menu - -@@node List, Search, Source, Source -@@section Printing Source Lines - -@@kindex list -To print lines from a source file, use the @@samp{list} command -(abbreviated @@samp{l}). There are several ways to specify what part -of the file you want to print. - -Here are the forms of the @@samp{list} command most commonly used: - -@@table @@code -@@item list @@var{linenum} -Print ten lines centered around line number @@var{linenum} in the -current source file. - -@@item list @@var{function} -Print ten lines centered around the beginning of function -@@var{function}. - -@@item list -Print ten more lines. If the last lines printed were printed with a -@@samp{list} command, this prints ten lines following the last lines -printed; however, if the last line printed was a solitary line printed -as part of displaying a stack frame (@@pxref{Stack}), this prints ten -lines centered around that line. - -@@item list @@minus{} -Print ten lines just before the lines last printed. -@@end table - -Repeating a @@samp{list} command with @@key{RET} discards the argument, -so it is equivalent to typing just @@samp{list}. This is more useful -than listing the same lines again. An exception is made for an -argument of @@samp{-}; that argument is preserved in repetition so that -each repetition moves up in the file. - -In general, the @@samp{list} command expects you to supply zero, one or two -@@dfn{linespecs}. Linespecs specify source lines; there are several ways -of writing them but the effect is always to specify some source line. -Here is a complete description of the possible arguments for @@samp{list}: - -@@table @@code -@@item list @@var{linespec} -Print ten lines centered around the line specified by @@var{linespec}. - -@@item list @@var{first},@@var{last} -Print lines from @@var{first} to @@var{last}. Both arguments are -linespecs. - -@@item list ,@@var{last} -Print ten lines ending with @@var{last}. - -@@item list @@var{first}, -Print ten lines starting with @@var{first}. - -@@item list + -Print ten lines just after the lines last printed. - -@@item list @@minus{} -Print ten lines just before the lines last printed. - -@@item list -As described in the preceding table. -@@end table - -Here are the ways of specifying a single source line---all the -kinds of linespec. - -@@table @@asis -@@item @@var{linenum} -Specifies line @@var{linenum} of the current source file. -When a @@samp{list} command has two linespecs, this refers to -the same source file as the first linespec. - -@@item +@@var{offset} -Specifies the line @@var{offset} lines after the last line printed. -When used as the second linespec in a @@samp{list} command that has -two, this specifies the line @@var{offset} lines down from the -first linespec. - -@@item @@minus{}@@var{offset} -Specifies the line @@var{offset} lines before the last line printed. - -@@item @@var{filename}:@@var{linenum} -Specifies line @@var{linenum} in the source file @@var{filename}. - -@@item @@var{function} -Specifies the line of the open-brace that begins the body of the -function @@var{function}. - -@@item @@var{filename}:@@var{function} -Specifies the line of the open-brace that begins the body of the -function @@var{function} in the file @@var{filename}. The file name is -needed with a function name only for disambiguation of identically -named functions in different source files. - -@@item *@@var{address} -Specifies the line containing the program address @@var{address}. -@@var{address} may be any expression. -@@end table - -One other command is used to map source lines to program addresses. - -@@table @@code -@@item info line @@var{linenum} -@@kindex info line -Print the starting and ending addresses of the compiled code for -source line @@var{linenum}. - -@@kindex $_ -The default examine address for the @@samp{x} command is changed to the -starting address of the line, so that @@samp{x/i} is sufficient to -begin examining the machine code (@@pxref{Memory}). Also, this address -is saved as the value of the convenience variable @@samp{$_} -(@@pxref{Convenience Vars}). -@@end table - -@@node Search, Source Path, List, Source -@@section Searching Source Files -@@cindex searching -@@kindex forward-search -@@kindex reverse-search - -There are two commands for searching through the current source file for a -regular expression. - -The command @@samp{forward-search @@var{regexp}} checks each line, starting -with the one following the last line listed, for a match for @@var{regexp}. -It lists the line that is found. You can abbreviate the command name -as @@samp{fo}. - -The command @@samp{reverse-search @@var{regexp}} checks each line, starting -with the one before the last line listed and going backward, for a match -for @@var{regexp}. It lists the line that is found. You can abbreviate -this command with as little as @@samp{rev}. - -@@node Source Path,, Search, Source -@@section Specifying Source Directories - -@@cindex source path -@@cindex directories for source files -Executable programs do not record the directories of the source files they -were compiled from, just the names. GDB remembers a list of directories to -search for source files; this is called the @@dfn{source path}. Each time -GDB wants a source file, it tries all the directories in the list, in the -order they are present in the list, until it finds a file with the desired -name. - -@@kindex directory -When you start GDB, its source path contains just the current working -directory. To add other directories, use the @@samp{directory} command. -@@b{Note that the search path for executable files and the working directory -are @@i{not} used for finding source files.} - -@@table @@code -@@item directory @@var{dirname} -Add directory @@var{dirname} to the end of the source path. - -@@item directory -Reset the source path to just the current working directory of GDB. -This requires confirmation. - -@@samp{directory} with no argument can cause source files previously -found by GDB to be found in a different directory. To make this work -correctly, this command also clears out the tables GDB maintains -about the source files it has already found. - -@@item info directories -@@kindex info directories -Print the source path: show which directories it contains. -@@end table - -Because the @@samp{directory} command adds to the end of the source path, -it does not affect any file that GDB has already found. If the source -path contains directories that you do not want, and these directories -contain misleading files with names matching your source files, the -way to correct the situation is as follows: - -@@enumerate -@@item -Choose the directory you want at the beginning of the source path. -Use the @@samp{cd} command to make that the current working directory. - -@@item -Use @@samp{directory} with no argument to reset the source path to just -that directory. - -@@item -Use @@samp{directory} with suitable arguments to add any other -directories you want in the source path. -@@end enumerate - -@@node Data, Symbols, Source, Top -@@chapter Examining Data - -@@cindex printing data -@@cindex examining data -@@kindex print -The usual way of examining data in your program is with the @@samp{print} -command (abbreviated @@samp{p}). It evaluates and prints the value of any -valid expression of the language the program is written in (for now, C). -You type - -@@example -print @@var{exp} -@@end example - -@@noindent -where @@var{exp} is any valid expression, and the value of @@var{exp} -is printed in a format appropriate to its data type. - -A more low-level way of examining data is with the @@samp{x} command. -It examines data in memory at a specified address and prints it in a -specified format. - -GDB supports one command to modify the default format of displayed data: - -@@table @@samp -@@item set array-max -@@kindex set array-max -@@samp{set array-max} sets the maximum number of elements of an array which -will be printed. This limit also applies to the display of strings. -@@end table - -@@menu -* Expressions:: Expressions that can be computed and printed. -* Variables:: Using your program's variables in expressions. -* Assignment:: Setting your program's variables. -* Arrays:: Examining part of memory as an array. -* Formats:: Specifying formats for printing values. -* Memory:: Examining memory explicitly. -* Auto Display:: Printing certain expressions whenever program stops. -* Value History:: Referring to values previously printed. -* Convenience Vars:: Giving names to values for future reference. -* Registers:: Referring to and storing in machine registers. -@@end menu - -@@node Expressions, Variables, Data, Data -@@section Expressions - -@@cindex expressions -Many different GDB commands accept an expression and compute its value. -Any kind of constant, variable or operator defined by the programming -language you are using is legal in an expression in GDB. This includes -conditional expressions, function calls, casts and string constants. -It unfortunately does not include symbols defined by preprocessor -#define commands. - -Casts are supported in all languages, not just in C, because it is so -useful to cast a number into a pointer so as to examine a structure -at that address in memory. - -GDB supports three kinds of operator in addition to those of programming -languages: - -@@table @@code -@@item @@@@ -@@samp{@@@@} is a binary operator for treating parts of memory as arrays. -@@xref{Arrays}, for more information. - -@@item :: -@@samp{::} allows you to specify a variable in terms of the file or -function it is defined in. @@xref{Variables}. - -@@item @@{@@var{type}@@} @@var{addr} -Refers to an object of type @@var{type} stored at address @@var{addr} in -memory. @@var{addr} may be any expression whose value is an integer or -pointer (but parentheses are required around nonunary operators, just as in -a cast). This construct is allowed regardless of what kind of data is -officially supposed to reside at @@var{addr}.@@refill -@@end table - -@@node Variables, Arrays, Expressions, Data -@@section Program Variables - -The most common kind of expression to use is the name of a variable -in your program. - -Variables in expressions are understood in the selected stack frame -(@@pxref{Selection}); they must either be global (or static) or be visible -according to the scope rules of the programming language from the point of -execution in that frame. This means that in the function - -@@example -foo (a) - int a; -@@{ - bar (a); - @@{ - int b = test (); - bar (b); - @@} -@@} -@@end example - -@@noindent -the variable @@code{a} is usable whenever the program is executing -within the function @@code{foo}, but the variable @@code{b} is visible -only while the program is executing inside the block in which @@code{b} -is declared. - -As a special exception, you can refer to a variable or function whose -scope is a single source file even if the current execution point is not -in this file. But it is possible to have more than one such variable -or function with the same name (if they are in different source files). -In such a case, it is not defined which one you will get. If you wish, -you can specify any one of them using the colon-colon construct: - -@@example -@@var{block}::@@var{variable} -@@end example - -@@noindent -Here @@var{block} is the name of the source file whose variable you want. - -@@node Arrays, Formats, Variables, Data -@@section Artificial Arrays - -@@cindex artificial array -It is often useful to print out several successive objects of the -same type in memory; a section of an array, or an array of -dynamically determined size for which only a pointer exists in the -program. - -This can be done by constructing an @@dfn{artificial array} with the -binary operator @@samp{@@@@}. The left operand of @@samp{@@@@} should be -the first element of the desired array, as an individual object. -The right operand should be the length of the array. The result is -an array value whose elements are all of the type of the left argument. -The first element is actually the left argument; the second element -comes from bytes of memory immediately following those that hold the -first element, and so on. Here is an example. If a program says - -@@example -int *array = (int *) malloc (len * sizeof (int)); -@@end example - -@@noindent -you can print the contents of @@code{array} with - -@@example -p *array@@@@len -@@end example - -The left operand of @@samp{@@@@} must reside in memory. Array values made -with @@samp{@@@@} in this way behave just like other arrays in terms of -subscripting, and are coerced to pointers when used in expressions. -(It would probably appear in an expression via the value history, -after you had printed it out.) - -@@node Formats, Memory, Arrays, Data -@@section Formats - -@@cindex formatted output -@@cindex output formats -GDB normally prints all values according to their data types. Sometimes -this is not what you want. For example, you might want to print a number -in hex, or a pointer in decimal. Or you might want to view data in memory -at a certain address as a character string or an instruction. These things -can be done with @@dfn{output formats}. - -The simplest use of output formats is to say how to print a value -already computed. This is done by starting the arguments of the -@@samp{print} command with a slash and a format letter. The format -letters supported are: - -@@table @@samp -@@item x -Regard the bits of the value as an integer, and print the integer in -hexadecimal. - -@@item d -Print as integer in signed decimal. - -@@item u -Print as integer in unsigned decimal. - -@@item o -Print as integer in octal. - -@@item a -Print as an address, both absolute in hex and then relative -to a symbol defined as an address below it. - -@@item c -Regard as an integer and print it as a character constant. - -@@item f -Regard the bits of the value as a floating point number and print -using typical floating point syntax. -@@end table - -For example, to print the program counter in hex (@@pxref{Registers}), type - -@@example -p/x $pc -@@end example - -@@noindent -Note that no space is required before the slash; this is because command -names in GDB cannot contain a slash. - -To reprint the last value in the value history with a different format, -you can use the @@samp{print} command with just a format and no -expression. For example, @@samp{p/x} reprints the last value in hex. - -@@node Memory, Auto Display, Formats, Data -@@subsection Examining Memory - -@@cindex examining memory -@@kindex x -The command @@samp{x} (for `examine') can be used to examine memory under -explicit control of formats, without reference to the program's data types. - -@@samp{x} is followed by a slash and an output format specification, -followed by an expression for an address. The expression need not have -a pointer value (though it may); it is used as an integer, as the -address of a byte of memory. @@xref{Expressions} for more information -on expressions. - -The output format in this case specifies both how big a unit of memory -to examine and how to print the contents of that unit. It is done -with one or two of the following letters: - -These letters specify just the size of unit to examine: - -@@table @@samp -@@item b -Examine individual bytes. - -@@item h -Examine halfwords (two bytes each). - -@@item w -Examine words (four bytes each). - -@@cindex word -Many assemblers and cpu designers still use `word' for a 16-bit quantity, -as a holdover from specific predecessor machines of the 1970's that really -did use two-byte words. But more generally the term `word' has always -referred to the size of quantity that a machine normally operates on and -stores in its registers. This is 32 bits for all the machines that GNU -runs on. - -@@item g -Examine giant words (8 bytes). -@@end table - -These letters specify just the way to print the contents: - -@@table @@samp -@@item x -Print as integers in unsigned hexadecimal. - -@@item d -Print as integers in signed decimal. - -@@item u -Print as integers in unsigned decimal. - -@@item o -Print as integers in unsigned octal. - -@@item a -Print as an address, both absolute in hex and then relative -to a symbol defined as an address below it. - -@@item c -Print as character constants. - -@@item f -Print as floating point. This works only with sizes @@samp{w} and -@@samp{g}. - -@@item s -Print a null-terminated string of characters. The specified unit size -is ignored; instead, the unit is however many bytes it takes to reach -a null character (including the null character). - -@@item i -Print a machine instruction in assembler syntax (or nearly). The -specified unit size is ignored; the number of bytes in an instruction -varies depending on the type of machine, the opcode and the addressing -modes used. -@@end table - -If either the manner of printing or the size of unit fails to be specified, -the default is to use the same one that was used last. If you don't want -to use any letters after the slash, you can omit the slash as well. - -You can also omit the address to examine. Then the address used is -just after the last unit examined. This is why string and instruction -formats actually compute a unit-size based on the data: so that the -next string or instruction examined will start in the right place. -The @@samp{print} command sometimes sets the default address for -the @@samp{x} command; when the value printed resides in memory, the -default is set to examine the same location. @@samp{info line} also -sets the default for @@samp{x}, to the address of the start of the -machine code for the specified line and @@samp{info breakpoints} sets -it to the address of the last breakpoint listed. - -When you use @@key{RET} to repeat an @@samp{x} command, it does not repeat -exactly the same: the address specified previously (if any) is ignored, so -that the repeated command examines the successive locations in memory -rather than the same ones. - -You can examine several consecutive units of memory with one command by -writing a repeat-count after the slash (before the format letters, if any). -The repeat count must be a decimal integer. It has the same effect as -repeating the @@samp{x} command that many times except that the output may -be more compact with several units per line. - -@@example -x/10i $pc -@@end example - -@@noindent -Prints ten instructions starting with the one to be executed next in the -selected frame. After doing this, you could print another ten following -instructions with - -@@example -x/10 -@@end example - -@@noindent -in which the format and address are allowed to default. - -@@kindex $_ -@@kindex $__ -The addresses and contents printed by the @@samp{x} command are not put in -the value history because there is often too much of them and they would -get in the way. Instead, GDB makes these values available for subsequent -use in expressions as values of the convenience variables @@samp{$_} and -@@samp{$__}. - -After an @@samp{x} command, the last address examined is available for use -in expressions in the convenience variable @@samp{$_}. The contents of that -address, as examined, are available in the convenience variable @@samp{$__}. - -If the @@samp{x} command has a repeat count, the address and contents saved -are from the last memory unit printed; this is not the same as the last -address printed if several units were printed on the last line of output. - -@@node Auto Display, Value History, Memory, Data -@@section Automatic Display - -If you find that you want to print the value of an expression frequently -(to see how it changes), you might want to add it to the @@dfn{automatic -display list} so that GDB will print its value each time the program stops. -Each expression added to the list is given a number to identify it; -to remove an expression from the list, you specify that number. -The automatic display looks like this: - -@@example -2: foo = 38 -3: bar[5] = (struct hack *) 0x3804 -@@end example - -@@noindent -showing item numbers, expressions and their current values. - -@@table @@code -@@item display @@var{exp} -@@kindex display -Add the expression @@var{exp} to the list of expressions to display -each time the program stops. @@xref{Expressions}. - -@@item display/@@var{fmt} @@var{exp} -For @@var{fmt} specifying only a display format and not a size or -count, add the expression @@var{exp} to the auto-display list but -arranges to display it each time in the specified format @@var{fmt}. - -@@item display/@@var{fmt} @@var{addr} -For @@var{fmt} @@samp{i} or @@samp{s}, or including a unit-size or a -number of units, add the expression @@var{addr} as a memory address to -be examined each time the program stops. Examining means in effect -doing @@samp{x/@@var{fmt} @@var{addr}}. @@xref{Memory}. - -@@item undisplay @@var{dnums}@@dots{} -@@kindex undisplay -@@item delete display @@var{dnums}@@dots{} -@@kindex delete display -Remove item numbers @@var{dnums} from the list of expressions to display. - -@@item disable display @@var{dnums}@@dots{} -@@kindex disable display -Disable the display of item numbers @@var{dnums}. A disabled display item -has no effect but is not forgotten. It may be later enabled. - -@@item enable display @@var{dnums}@@dots{} -@@kindex enable display -Enable display of item numbers @@var{dnums}. It becomes effective once -again in auto display of its expression, until you specify otherwise. - -@@item display -Display the current values of the expressions on the list, just as is -done when the program stops. - -@@item info display -@@kindex info display -Print the list of expressions to display automatically, each one -with its item number, but without showing the values. -@@end table - -@@node Value History, Convenience Vars, Auto Display, Data -@@section Value History - -@@cindex value history -Every value printed by the @@samp{print} command is saved for the entire -session in GDB's @@dfn{value history} so that you can refer to it in -other expressions. - -@@cindex $ -@@cindex $$ -The values printed are given @@dfn{history numbers} for you to refer to them -by. These are successive integers starting with 1. @@samp{print} shows you -the history number assigned to a value by printing @@samp{$@@var{n} = } -before the value; here @@var{n} is the history number. - -To refer to any previous value, use @@samp{$} followed by the value's -history number. The output printed by @@samp{print} is designed to remind -you of this. Just @@samp{$} refers to the most recent value in the history, -and @@samp{$$} refers to the value before that. - -For example, suppose you have just printed a pointer to a structure and -want to see the contents of the structure. It suffices to type - -@@example -p *$ -@@end example - -If you have a chain of structures where the component @@samp{next} points -to the next one, you can print the contents of the next one with - -@@example -p *$.next -@@end example - -It might be useful to repeat this command many times by typing @@key{RET}. - -Note that the history records values, not expressions. If the value of -@@code{x} is 4 and you type - -@@example -print x -set x=5 -@@end example - -@@noindent -then the value recorded in the value history by the @@samp{print} command -remains 4 even though @@code{x}'s value has changed. - -@@table @@code -@@item info history -@@kindex info history -Print the last ten values in the value history, with their item -numbers. This is like @@samp{p $$9} repeated ten times, except that -@@samp{info history} does not change the history. - -@@item info history @@var{n} -Print ten history values centered on history item number @@var{n}. -@@end table - -@@node Convenience Vars, Registers, Value History, Data -@@section Convenience Variables - -@@cindex convenience variables -GDB provides @@dfn{convenience variables} that you can use within GDB to -hold on to a value and refer to it later. These variables exist entirely -within GDB; they are not part of your program, and setting a convenience -variable has no effect on further execution of your program. That's why -you can use them freely. - -Convenience variables have names starting with @@samp{$}. Any name starting -with @@samp{$} can be used for a convenience variable, unless it is one of -the predefined set of register names (@@pxref{Registers}). - -You can save a value in a convenience variable with an assignment -expression, just as you would set a variable in your program. Example: - -@@example -set $foo = *object_ptr -@@end example - -@@noindent -would save in @@samp{$foo} the value contained in the object pointed to by -@@code{object_ptr}. - -Using a convenience variable for the first time creates it; but its value -is @@code{void} until you assign a new value. You can alter the value with -another assignment at any time. - -Convenience variables have no fixed types. You can assign a convenience -variable any type of value, even if it already has a value of a different -type. The convenience variable as an expression has whatever type its -current value has. - -@@table @@code -@@item info convenience -@@kindex info convenience -Print a list of convenience variables used so far, and their values. -Abbreviated @@samp{i con}. -@@end table - -One of the ways to use a convenience variable is as a counter to be -incremented or a pointer to be advanced. For example: - -@@example -set $i = 0 -print bar[$i++]->contents -@@i{@@dots{}repeat that command by typing @@key{RET}.} -@@end example - -Some convenience variables are created automatically by GDB and given -values likely to be useful. - -@@table @@samp -@@item $_ -The variable @@samp{$_} is automatically set by the @@samp{x} command to -the last address examined (@@pxref{Memory}). Other commands which -provide a default address for @@samp{x} to examine also set @@samp{$_} -to that address; these commands include @@samp{info line} and @@samp{info -breakpoint}. - -@@item $__ -The variable @@samp{$__} is automatically set by the @@samp{x} command -to the value found in the last address examined. -@@end table - -@@node Registers,, Convenience Vars, Data -@@section Registers - -@@cindex registers -Machine register contents can be referred to in expressions as variables -with names starting with @@samp{$}. The names of registers are different -for each machine; use @@samp{info registers} to see the names used on your -machine. The names @@samp{$pc} and @@samp{$sp} are used on all machines for -the program counter register and the stack pointer. Often @@samp{$fp} is -used for a register that contains a pointer to the current stack frame. - -GDB always considers the contents of an ordinary register as an integer -when the register is examined in this way. Some machines have special -registers which can hold nothing but floating point; these registers are -considered floating point. There is no way to refer to the contents of an -ordinary register as floating point value (although you can @@emph{print} -it as a floating point value with @@samp{print/f $@@var{regname}}). - -Some registers have distinct ``raw'' and ``virtual'' data formats. This -means that the data format in which the register contents are saved by the -operating system is not the same one that your program normally sees. For -example, the registers of the 68881 floating point coprocessor are always -saved in ``extended'' format, but virtually all C programs expect to work with -``double'' format. In such cases, GDB normally works with the virtual -format only (the format that makes sense for your program), but the -@@samp{info registers} command prints the data in both formats. - -Register values are relative to the selected stack frame -(@@pxref{Selection}). This means that you get the value that the register -would contain if all stack frames farther in were exited and their saved -registers restored. In order to see the real contents of all registers, -you must select the innermost frame (with @@samp{frame 0}). - -Some registers are never saved (typically those numbered zero or one) -because they are used for returning function values; for these registers, -relativization makes no difference. - -@@table @@code -@@item info registers -@@kindex info registers -Print the names and relativized values of all registers. - -@@item info registers @@var{regname} -Print the relativized value of register @@var{regname}. @@var{regname} -may be any register name valid on the machine you are using, with -or without the initial @@samp{$}. -@@end table - -@@subsection Examples - -You could print the program counter in hex with - -@@example -p/x $pc -@@end example - -@@noindent -or print the instruction to be executed next with - -@@example -x/i $pc -@@end example - -@@noindent -or add four to the stack pointer with - -@@example -set $sp += 4 -@@end example - -@@noindent -The last is a way of removing one word from the stack, on machines where -stacks grow downward in memory (most machines, nowadays). This assumes -that the innermost stack frame is selected. Setting @@samp{$sp} is -not allowed when other stack frames are selected. - -@@node Symbols, Altering, Data, Top -@@chapter Examining the Symbol Table - -The commands described in this section allow you to make inquiries for -information about the symbols (names of variables, functions and types) -defined in your program. This information is found by GDB in the symbol -table loaded by the @@samp{symbol-file} command; it is inherent in the text -of your program and does not change as the program executes. - -@@table @@code -@@item whatis @@var{exp} -@@kindex whatis -Print the data type of expression @@var{exp}. @@var{exp} is not -actually evaluated, and any side-effecting operations (such as -assignments or function calls) inside it do not take place. -@@xref{Expressions}. - -@@item whatis -Print the data type of @@samp{$}, the last value in the value history. - -@@item info address @@var{symbol} -@@kindex info address -Describe where the data for @@var{symbol} is stored. For register -variables, this says which register. For other automatic variables, -this prints the stack-frame offset at which the variable is always -stored. Note the contrast with @@samp{print &@@var{symbol}}, which does -not work at all for register variables and for automatic variables -prints the exact address of the current instantiation of the variable. - -@@item ptype @@var{typename} -@@kindex ptype -Print a description of data type @@var{typename}. @@var{typename} may be -the name of a type, or for C code it may have the form -@@samp{struct @@var{struct-tag}}, @@samp{union @@var{union-tag}} or -@@samp{enum @@var{enum-tag}}.@@refill - -@@item info sources -@@kindex info sources -Print the names of all source files in the program for which there -is debugging information. - -@@item info functions -@@kindex info functions -Print the names and data types of all defined functions. - -@@item info functions @@var{regexp} -Print the names and data types of all defined functions -whose names contain a match for regular expression @@var{regexp}. -Thus, @@samp{info fun step} finds all functions whose names -include @@samp{step}; @@samp{info fun ^step} finds those whose names -start with @@samp{step}. - -@@item info variables -@@kindex info variables -Print the names and data types of all variables that are declared -outside of functions. - -@@item info variables @@var{regexp} -Print the names and data types of all variables, declared outside of -functions, whose names contain a match for regular expression -@@var{regexp}. - -@@item info types -@@kindex info types -Print all data types that are defined in the program. - -@@item info types @@var{regexp} -Print all data types that are defined in the program whose names -contain a match for regular expression @@var{regexp}. - -@@item info methods -@@item info methods @@var{regexp} -@@kindex info methods -The @@samp{info-methods} command permits the user to examine all defined -methods within C@@code{++} program, or (with the @@var{regexp} argument) a -specific set of methods found in the various C@@code{++} classes. Many -C@@code{++} classes which implement a large number of differently typed -methods implement a large number of methods as well. Thus, the -@@samp{ptype} command can give the user a tremendous overdose of -information about what methods are associated with a given class. The -@@samp{info-methods} command filters these methods do to only those -methods which match the regular-expression search key. - -@@item printsyms @@var{filename} -@@kindex printsyms -Write a complete dump of the debugger's symbol data into the -file @@var{filename}. -@@end table - -@@node Altering, Sequences, Symbols, Top -@@chapter Altering Execution - -There are several ways to alter the execution of your program with GDB -commands. - -@@menu -* Assignment:: Altering variable values or memory contents. -* Jumping:: Altering control flow. -* Signaling:: Making signals happen in the program. -* Returning:: Making a function return prematurely. -@@end menu - -@@node Assignment, Jumping, Altering, Altering -@@section Assignment to Variables - -@@cindex assignment -@@cindex setting variables -To alter the value of a variable, evaluate an assignment expression. -@@xref{Expressions}. For example, - -@@example -print x=4 -@@end example - -@@noindent -would store the value 4 into the variable @@code{x}, and then print -the value of the assignment expression (which is 4). - -@@kindex set -@@kindex set variable -If you are not interested in seeing the value of the assignment, use the -@@samp{set} command instead of the @@samp{print} command. @@samp{set} is -really the same as @@samp{print} except that the expression's value is not -printed and is not put in the value history (@@pxref{Value History}). The -expression is evaluated only for side effects. - -Note that if the beginning of the argument string of the @@samp{set} command -appears identical to a @@samp{set} subcommand, it may be necessary to use -the @@samp{set variable} command. This command is identical to @@samp{set} -except for its lack of subcommands. - -GDB allows more implicit conversions in assignments than C does; you can -freely store an integer value into a pointer variable or vice versa, and -any structure can be converted to any other structure that is the same -length or shorter. - -In C, all the other assignment operators such as @@samp{+=} and @@samp{++} -are supported as well. - -To store into arbitrary places in memory, use the @@samp{@@{@@dots{}@@}} -construct to generate a value of specified type at a specified address -(@@pxref{Expressions}). For example, - -@@example -set @@{int@@}0x83040 = 4 -@@end example - -@@node Jumping, Signaling, Assignment, Altering -@@section Continuing at a Different Address - -@@table @@code -@@item jump @@var{linenum} -@@kindex jump -Resume execution at line number @@var{linenum}. Execution may stop -immediately if there is a breakpoint there. - -The @@samp{jump} command does not change the current stack frame, or -the stack pointer, or the contents of any memory location or any -register other than the program counter. If line @@var{linenum} is in -a different function from the one currently executing, the results may -be wild if the two functions expect different patterns of arguments or -of local variables. For this reason, the @@samp{jump} command requests -confirmation if the specified line is not in the function currently -executing. However, even wild results are predictable based on -changing the program counter. - -@@item jump *@@var{address} -Resume execution at the instruction at address @@var{address}. -@@end table - -A similar effect can be obtained by storing a new value into the register -@@samp{$pc}, but not exactly the same. - -@@example -set $pc = 0x485 -@@end example - -@@noindent -specifies the address at which execution will resume, but does not resume -execution. That does not happen until you use the @@samp{cont} command or a -stepping command (@@pxref{Stepping}). - -@@node Signaling, Returning, Jumping, Altering -@@section Giving the Program a Signal - -@@table @@code -@@item signal @@var{signalnum} -@@kindex signal -Resume execution where the program stopped, but give it immediately -the signal number @@var{signalnum}. - -Alternatively, if @@var{signalnum} is zero, continue execution and give -no signal. This is useful when the program has received a signal -but you don't want the program to see that signal; the @@samp{cont} command -would signal the program. -@@end table - -@@node Returning,, Signaling, Altering -@@section Returning from a Function - -@@cindex returning from a function -@@kindex return -You can make any function call return immediately, using the @@samp{return} -command. - -First select the stack frame that you wish to return from -(@@pxref{Selection}). Then type the @@samp{return} command. If you wish to -specify the value to be returned, give that as an argument. - -This pops the selected stack frame (and any other frames inside of it), -leaving its caller as the innermost remaining frame. That frame becomes -selected. The specified value is stored in the registers used for -returning values of functions. - -The @@samp{return} command does not resume execution; it leaves the program -stopped in the state that would exist if the function had just returned. -Contrast this with the @@samp{finish} command (@@pxref{Stepping}), which -resumes execution @@i{until} the selected stack frame returns naturally. - -@@node Sequences, Emacs, Altering, Top -@@chapter Canned Sequences of Commands - -GDB provides two ways to store sequences of commands for execution as a -unit: user-defined commands and command files. - -@@menu -* Define:: User-defined commands. -* Command Files:: Command files. -* Output:: Controlled output commands useful in - user-defined commands and command files. -@@end menu - -@@node Define, Command Files, Sequences, Sequences -@@section User-Defined Commands - -@@cindex user-defined commands -A @@dfn{user-defined command} is a sequence of GDB commands to which you -assign a new name as a command. This is done with the @@samp{define} -command. - -@@table @@code -@@item define @@var{commandname} -@@kindex define -Define a command named @@var{commandname}. If there is already a command -by that name, you are asked to confirm that you want to redefine it. - -The definition of the command is made up of other GDB command lines, -which are given following the @@samp{define} command. The end of these -commands is marked by a line containing @@samp{end}. - -@@item document @@var{commandname} -@@kindex document -Give documentation to the user-defined command @@var{commandname}. The -command @@var{commandname} must already be defined. This command reads -lines of documentation just as @@samp{define} reads the lines of the -command definition, ending with @@samp{end}. After the @@samp{document} command is finished, -@@samp{help} on command @@var{commandname} will print the documentation -you have specified. - -You may use the @@samp{document} command again to change the -documentation of a command. Redefining the command with @@samp{define} -does not change the documentation. -@@end table - -User-defined commands do not take arguments. When they are executed, the -commands of the definition are not printed. An error in any command -stops execution of the user-defined command. - -Commands that would ask for confirmation if used interactively proceed -without asking when used inside a user-defined command. Many GDB commands -that normally print messages to say what they are doing omit the messages -when used in user-defined command. - -@@node Command Files, Output, Define, Sequences -@@section Command Files - -@@cindex command files -A command file for GDB is a file of lines that are GDB commands. Comments -(lines starting with @@samp{#}) may also be included. An empty line in a -command file does nothing; it does not mean to repeat the last command, as -it would from the terminal. - -@@cindex init file -@@cindex .gdbinit -When GDB starts, it automatically executes its @@dfn{init files}, command -files named @@file{.gdbinit}. GDB reads the init file (if any) in your home -directory and then the init file (if any) in the current working -directory. (The init files are not executed if the @@samp{-nx} option -is given.) You can also request the execution of a command file with the -@@samp{source} command: - -@@table @@code -@@item source @@var{filename} -@@kindex source -Execute the command file @@var{filename}. -@@end table - -The lines in a command file are executed sequentially. They are not -printed as they are executed. An error in any command terminates execution -of the command file. - -Commands that would ask for confirmation if used interactively proceed -without asking when used in a command file. Many GDB commands that -normally print messages to say what they are doing omit the messages -when used in a command file. - -@@node Output,, Command Files, Sequences -@@section Commands for Controlled Output - -During the execution of a command file or a user-defined command, the only -output that appears is what is explicitly printed by the commands of the -definition. This section describes three commands useful for generating -exactly the output you want. - -@@table @@code -@@item echo @@var{text} -@@kindex echo -Print @@var{text}. Nonprinting characters can be included in -@@var{text} using C escape sequences, such as @@samp{\n} to print a -newline. @@b{No newline will be printed unless you specify one.} - -A backslash at the end of @@var{text} is ignored. It is useful for -outputting a string ending in spaces, since trailing spaces are -trimmed from all arguments. A backslash at the beginning preserves -leading spaces in the same way, because @@samp{\ } as an escape -sequence stands for a space. Thus, to print @@samp{ and foo = }, do - -@@example -echo \ and foo = \ -@@end example - -@@item output @@var{expression} -@@kindex output -Print the value of @@var{expression} and nothing but that value: no -newlines, no @@samp{$@@var{nn} = }. The value is not entered in the -value history either. @@xref{Expressions} for more information -on expressions. - -@@item output/@@var{fmt} @@var{expression} -Print the value of @@var{expression} in format @@var{fmt}. -@@xref{Formats}, for more information. - -@@item printf @@var{string}, @@var{expressions}@@dots{} -@@kindex printf -Print the values of the @@var{expressions} under the control of -@@var{string}. The @@var{expressions} are separated by commas and may -be either numbers or pointers. Their values are printed as specified -by @@var{string}, exactly as if the program were to execute - -@@example -printf (@@var{string}, @@var{expressions}@@dots{}); -@@end example - -For example, you can print two values in hex like this: - -@@example -printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo -@@end example - -The only backslash-escape sequences that you can use in the string are -the simple ones that consist of backslash followed by a letter. -@@end table - -@@node Emacs, Remote, Sequences, Top -@@chapter Using GDB under GNU Emacs - -A special interface allows you to use GNU Emacs to view (and -edit) the source files for the program you are debugging with -GDB. - -To use this interface, use the command @@kbd{M-x gdb} in Emacs. -Give the executable file you want to debug as an argument. This -command starts a GDB process as a subprocess of Emacs, with input -and output through a newly created Emacs buffer. - -Using this GDB process is just like using GDB normally except for two things: - -@@itemize @@bullet -@@item -All ``terminal'' input and output goes through the Emacs buffer. This -applies both to GDB commands and their output, and to the input and -output done by the program you are debugging. - -This is useful because it means that you can copy the text of previous -commands and input them again; you can even use parts of the output -in this way. - -All the facilities of Emacs's Shell mode are available for this purpose. - -@@item -GDB displays source code through Emacs. Each time GDB displays a -stack frame, Emacs automatically finds the source file for that frame -and puts an arrow (@@samp{=>}) at the left margin of the current line. - -Explicit GDB @@samp{list} or search commands still produce output as -usual, but you probably will have no reason to use them. -@@end itemize - -In the GDB I/O buffer, you can use these special Emacs commands: - -@@table @@kbd -@@item M-s -Execute to another source line, like the GDB @@samp{step} command. - -@@item M-n -Execute to next source line in this function, skipping all function -calls, like the GDB @@samp{next} command. - -@@item M-i -Execute one instruction, like the GDB @@samp{stepi} command. - -@@item M-u -Move up one stack frame (and display that frame's source file in -Emacs), like the GDB @@samp{up} command. - -@@item M-d -Move down one stack frame (and display that frame's source file in -Emacs), like the GDB @@samp{down} command. (This means that you cannot -delete words in the usual fashion in the GDB buffer; I am guessing you -won't often want to do that.) - -@@item C-c C-f -Execute until exit from the selected stack frame, like the GDB -@@samp{finish} command. -@@end table - -In any source file, the Emacs command @@kbd{C-x SPC} (@@code{gdb-break}) -tells GDB to set a breakpoint on the source line point is on. - -The source files displayed in Emacs are in ordinary Emacs buffers -which are visiting the source files in the usual way. You can edit -the files with these buffers if you wish; but keep in mind that GDB -communicates with Emacs in terms of line numbers. If you add or -delete lines from the text, the line numbers that GDB knows will cease -to correspond properly to the code. - -@@node Remote, Commands, Emacs, Top -@@chapter Remote Kernel Debugging - -GDB has a special facility for debugging a remote machine via a serial -connection. This can be used for kernel debugging. - -The program to be debugged on the remote machine needs to contain a -debugging device driver which talks to GDB over the serial line using the -protocol described below. The same version of GDB that is used ordinarily -can be used for this. - -@@menu -* Remote Commands:: Commands used to start and finish remote debugging. -@@end menu - -For details of the communication protocol, see the comments in the GDB -source file @@file{remote.c}. - -@@node Remote Commands,, Remote, Remote -@@section Commands for Remote Debugging - -To start remote debugging, first run GDB and specify as an executable file -the program that is running in the remote machine. This tells GDB how -to find the program's symbols and the contents of its pure text. Then -establish communication using the @@samp{attach} command with a device -name rather than a pid as an argument. For example: - -@@example -attach /dev/ttyd -@@end example - -@@noindent -if the serial line is connected to the device named @@file{/dev/ttyd}. This -will stop the remote machine if it is not already stopped. - -Now you can use all the usual commands to examine and change data and to -step and continue the remote program. - -To resume the remote program and stop debugging it, use the @@samp{detach} -command. - -@@node Commands, Concepts, Remote, Top -@@unnumbered Command Index - -@@printindex ky - -@@node Concepts,, Commands, Top -@@unnumbered Concept Index - -@@printindex cp - -@@contents -@@bye -@ - - -1.1 -log -@Initial revision -@ -text -@d617 3 -a619 2 -inferior. If you wish to evaluate a function simply for it's side -affects, you may use the @@samp{set} command. @@xref{Assignment}. -d1101 4 -a1104 3 -A condition is just a boolean expression in your programming language. -A breakpoint with a condition evaluates the expression each time the -program reaches it, and the program stops only if the condition is true. -d1126 1 -d1259 6 -a1264 5 -is a condition expression that will change @@code{x} as needed, then always -have the value 0 so the program will not stop. Loss of input is avoided -here because break conditions are evaluated without changing the terminal -modes. When you want to have nontrivial conditions for performing the side -effects, the operators @@samp{&&}, @@samp{||} and @@samp{?@@: @@dots{} :@@:} may be useful. -d1269 3 -a1271 3 -Under Unix, breakpoints cannot be used in a program if any other process -is running that program. Attempting to run or continue the program with -a breakpoint in this case will cause GDB to stop it. -d1875 2 -d2047 2 -a2048 1 -address of a byte of memory. -d2196 1 -a2196 1 -each time the program stops. -d2382 1 -a2382 1 -saved in ``extended'' format, but all C programs expect to work with -d2451 1 -d2544 1 -a2544 1 -For example, -d2628 3 -a2630 3 -no signal. This may be useful when the program has received a signal -and the @@samp{cont} command would allow the program to see that -signal. -d2691 1 -a2691 1 -command definition. After the @@samp{document} command is finished, -d2771 2 -a2772 1 -value history either. -@ diff --git a/gdb/RCS/gdbcore.h,v b/gdb/RCS/gdbcore.h,v deleted file mode 100644 index 872e5af9..0000000 --- a/gdb/RCS/gdbcore.h,v +++ /dev/null @@ -1,105 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.02.09.23.23.12; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.43.14; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Create gdbcore.h with external variables that relate to core files. -@ -text -@/* Machine independent variables that describe the core file under GDB. - Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -/* 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; -@ - - -1.1 -log -@Initial revision -@ -text -@d1 68 -@ diff --git a/gdb/RCS/inflow.c,v b/gdb/RCS/inflow.c,v deleted file mode 100644 index 972b615..0000000 --- a/gdb/RCS/inflow.c,v +++ /dev/null @@ -1,636 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.20.12.35; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.23.40; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.22.28.04; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@General portability changes. Make various local terminal control -parameter processing #ifdef the particular IOCTL used to get them. -This handles various Sys V/Berkeley merges. Also avoid vfork -and <sys/fcntl.h>. -@ -text -@/* Low level interface to ptrace, for GDB when running under Unix. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#endif - -#include <stdio.h> -#include <sys/param.h> -#include <sys/dir.h> -#include <signal.h> - -#ifdef HAVE_TERMIO -#include <termio.h> -#undef TIOCGETP -#define TIOCGETP TCGETA -#undef TIOCSETN -#define TIOCSETN TCSETA -#undef TIOCSETP -#define TIOCSETP TCSETAF -#define TERMINAL struct termio -#else -#include <sys/ioctl.h> -#include <fcntl.h> -#include <sgtty.h> -#define TERMINAL struct sgttyb -#endif - -#ifdef SET_STACK_LIMIT_HUGE -#include <sys/time.h> -#include <sys/resource.h> -extern int original_stack_limit; -#endif /* SET_STACK_LIMIT_HUGE */ - -extern int errno; - -/* Nonzero if we are debugging an attached outside process - rather than an inferior. */ - -int attach_flag; - - -/* Record terminal status separately for debugger and inferior. */ - -static TERMINAL sg_inferior; -static TERMINAL sg_ours; - -static int tflags_inferior; -static int tflags_ours; - -#ifdef TIOCGETC -static struct tchars tc_inferior; -static struct tchars tc_ours; -#endif - -#ifdef TIOCGLTC -static struct ltchars ltc_inferior; -static struct ltchars ltc_ours; -#endif /* TIOCGLTC */ - -#ifdef TIOCLGET -static int lmode_inferior; -static int lmode_ours; -#endif - -#ifdef TIOCGPGRP -static int pgrp_inferior; -static int pgrp_ours; -#else -static int (*sigint_ours) (); -static int (*sigquit_ours) (); -#endif /* TIOCGPGRP */ - -/* Copy of inferior_io_terminal when inferior was last started. */ -static char *inferior_thisrun_terminal; - -static void terminal_ours_1 (); - -/* Nonzero if our terminal settings are in effect. - Zero if the inferior's settings are in effect. */ -static int terminal_is_ours; - -/* Initialize the terminal settings we record for the inferior, - before we actually run the inferior. */ - -void -terminal_init_inferior () -{ - if (remote_debugging) - return; - - sg_inferior = sg_ours; - tflags_inferior = tflags_ours; - -#ifdef TIOCGETC - tc_inferior = tc_ours; -#endif - -#ifdef TIOCGLTC - ltc_inferior = ltc_ours; -#endif - -#ifdef TIOCLGET - lmode_inferior = lmode_ours; -#endif - -#ifdef TIOCGPGRP - pgrp_inferior = inferior_pid; -#endif /* TIOCGPGRP */ - - terminal_is_ours = 1; -} - -/* Put the inferior's terminal settings into effect. - This is preparation for starting or resuming the inferior. */ - -void -terminal_inferior () -{ - if (remote_debugging) - return; - - if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */ - { - fcntl (0, F_SETFL, tflags_inferior); - fcntl (0, F_SETFL, tflags_inferior); - ioctl (0, TIOCSETN, &sg_inferior); -#ifdef TIOCGETC - ioctl (0, TIOCSETC, &tc_inferior); -#endif -#ifdef TIOCGLTC - ioctl (0, TIOCSLTC, <c_inferior); -#endif -#ifdef TIOCLGET - ioctl (0, TIOCLSET, &lmode_inferior); -#endif - -#ifdef TIOCGPGRP - ioctl (0, TIOCSPGRP, &pgrp_inferior); -#else - sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN); - sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN); -#endif /* TIOCGPGRP */ - } - terminal_is_ours = 0; -} - -/* Put some of our terminal settings into effect, - enough to get proper results from our output, - but do not change into or out of RAW mode - so that no input is discarded. - - After doing this, either terminal_ours or terminal_inferior - should be called to get back to a normal state of affairs. */ - -void -terminal_ours_for_output () -{ - if (remote_debugging) - return; - - terminal_ours_1 (1); -} - -/* Put our terminal settings into effect. - First record the inferior's terminal settings - so they can be restored properly later. */ - -void -terminal_ours () -{ - if (remote_debugging) - return; - - terminal_ours_1 (0); -} - -static void -terminal_ours_1 (output_only) - int output_only; -{ -#ifdef TIOCGPGRP - /* Ignore this signal since it will happen when we try to set the pgrp. */ - int (*osigttou) (); -#endif /* TIOCGPGRP */ - - if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */ - { - terminal_is_ours = 1; - -#ifdef TIOCGPGRP - osigttou = signal (SIGTTOU, SIG_IGN); - - ioctl (0, TIOCGPGRP, &pgrp_inferior); - ioctl (0, TIOCSPGRP, &pgrp_ours); - - signal (SIGTTOU, osigttou); -#else - signal (SIGINT, sigint_ours); - signal (SIGQUIT, sigquit_ours); -#endif /* TIOCGPGRP */ - - tflags_inferior = fcntl (0, F_GETFL, 0); - ioctl (0, TIOCGETP, &sg_inferior); - -#ifdef TIOCGETC - ioctl (0, TIOCGETC, &tc_inferior); -#endif -#ifdef TIOCGLTC - ioctl (0, TIOCGLTC, <c_inferior); -#endif -#ifdef TIOCLGET - ioctl (0, TIOCLGET, &lmode_inferior); -#endif - } - -#ifdef HAVE_TERMIO - sg_ours.c_lflag |= ICANON; - if (output_only && !(sg_inferior.c_lflag & ICANON)) - sg_ours.c_lflag &= ~ICANON; -#else /* not HAVE_TERMIO */ - sg_ours.sg_flags &= ~RAW & ~CBREAK; - if (output_only) - sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags; -#endif /* not HAVE_TERMIO */ - - fcntl (0, F_SETFL, tflags_ours); - fcntl (0, F_SETFL, tflags_ours); - ioctl (0, TIOCSETN, &sg_ours); - -#ifdef TIOCGETC - ioctl (0, TIOCSETC, &tc_ours); -#endif -#ifdef TIOCGLTC - ioctl (0, TIOCSLTC, <c_ours); -#endif -#ifdef TIOCLGET - ioctl (0, TIOCLSET, &lmode_ours); -#endif - - -#ifdef HAVE_TERMIO - sg_ours.c_lflag |= ICANON; -#else /* not HAVE_TERMIO */ - sg_ours.sg_flags &= ~RAW & ~CBREAK; -#endif /* not HAVE_TERMIO */ -} - -static void -term_status_command () -{ - register int i; - - if (remote_debugging) - { - printf ("No terminal status when remote debugging.\n"); - return; - } - - printf ("Inferior's terminal status (currently saved by GDB):\n"); - -#ifdef HAVE_TERMIO - - printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n", - tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag); - printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", - sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line); - printf ("c_cc: "); - for (i = 0; (i < NCC); i += 1) - printf ("0x%x ", sg_inferior.c_cc[i]); - printf ("\n"); - -#else /* not HAVE_TERMIO */ - - printf ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n", - tflags_inferior, sg_inferior.sg_flags, pgrp_inferior); - -#endif /* not HAVE_TERMIO */ - -#ifdef TIOCGETC - printf ("tchars: "); - for (i = 0; i < sizeof (struct tchars); i++) - printf ("0x%x ", ((char *)&tc_inferior)[i]); - printf ("\n"); -#endif - -#ifdef TIOCGLTC - printf ("ltchars: "); - for (i = 0; i < sizeof (struct ltchars); i++) - printf ("0x%x ", ((char *)<c_inferior)[i]); - printf ("\n"); - ioctl (0, TIOCSLTC, <c_ours); -#endif - -#ifdef TIOCLGET - printf ("lmode: %x\n", lmode_inferior); -#endif -} - -static void -new_tty (ttyname) - char *ttyname; -{ - register int tty; - register int fd; - -#ifdef TIOCNOTTY - /* Disconnect the child process from our controlling terminal. */ - tty = open("/dev/tty", O_RDWR); - if (tty > 0) - { - ioctl(tty, TIOCNOTTY, 0); - close(tty); - } -#endif - - /* Now open the specified new terminal. */ - - tty = open(ttyname, O_RDWR); - if (tty == -1) - _exit(1); - - dup2(tty, 0); - dup2(tty, 1); - dup2(tty, 2); - close(tty); -} - -/* Start an inferior process and returns its pid. - ALLARGS is a string containing shell command to run the program. - ENV is the environment vector to pass. */ - -#ifndef SHELL_FILE -#define SHELL_FILE "/bin/sh" -#endif - -int -create_inferior (allargs, env) - char *allargs; - char **env; -{ - int pid; - char *shell_command; - extern int sys_nerr; - extern char *sys_errlist[]; - extern int errno; - - /* If desired, concat something onto the front of ALLARGS. - SHELL_COMMAND is the result. */ -#ifdef SHELL_COMMAND_CONCAT - shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1); - strcpy (shell_command, SHELL_COMMAND_CONCAT); - strcat (shell_command, allargs); -#else - shell_command = allargs; -#endif - - /* exec is said to fail if the executable is open. */ - close_exec_file (); - - pid = fork (); - if (pid < 0) - perror_with_name ("fork"); - - if (pid == 0) - { -#ifdef TIOCGPGRP - /* Run inferior in a separate process group. */ - setpgrp (getpid (), getpid ()); -#endif /* TIOCGPGRP */ - -#ifdef SET_STACK_LIMIT_HUGE - /* Reset the stack limit back to what it was. */ - { - struct rlimit rlim; - - getrlimit (RLIMIT_STACK, &rlim); - rlim.rlim_cur = original_stack_limit; - setrlimit (RLIMIT_STACK, &rlim); - } -#endif /* SET_STACK_LIMIT_HUGE */ - - - inferior_thisrun_terminal = inferior_io_terminal; - if (inferior_io_terminal != 0) - new_tty (inferior_io_terminal); - -/* Not needed on Sun, at least, and loses there - because it clobbers the superior. */ -/*??? signal (SIGQUIT, SIG_DFL); - signal (SIGINT, SIG_DFL); */ - - call_ptrace (0); - execle (SHELL_FILE, "sh", "-c", shell_command, 0, env); - - fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE, - errno < sys_nerr ? sys_errlist[errno] : "unknown error"); - fflush (stderr); - _exit (0177); - } - return pid; -} - -/* Kill the inferior process. Make us have no inferior. */ - -static void -kill_command () -{ - if (remote_debugging) - return; - if (inferior_pid == 0) - error ("The program is not being run."); - if (!query ("Kill the inferior process? ")) - error ("Not confirmed."); - kill_inferior (); -} - -void -inferior_died () -{ - inferior_pid = 0; - attach_flag = 0; - mark_breakpoints_out (); - select_frame ( (FRAME) 0, -1); - reopen_exec_file (); - if (have_core_file_p ()) - set_current_frame ( create_new_frame (read_register (FP_REGNUM), - read_pc ())); -} - -static void -try_writing_regs_command () -{ - register int i; - register int value; - extern int errno; - - if (inferior_pid == 0) - error ("There is no inferior process now."); - - for (i = 0; ; i += 2) - { - QUIT; - errno = 0; - value = call_ptrace (3, inferior_pid, i, 0); - call_ptrace (6, inferior_pid, i, value); - if (errno == 0) - { - printf (" Succeeded with address 0x%x; value 0x%x (%d).\n", - i, value, value); - } - else if ((i & 0377) == 0) - printf (" Failed at 0x%x.\n", i); - } -} - -void -_initialize_inflow () -{ - add_com ("term-status", class_obscure, term_status_command, - "Print info on inferior's saved terminal status."); - - add_com ("try-writing-regs", class_obscure, try_writing_regs_command, - "Try writing all locations in inferior's system block.\n\ -Report which ones can be written."); - - add_com ("kill", class_run, kill_command, - "Kill execution of program being debugged."); - - inferior_pid = 0; - - ioctl (0, TIOCGETP, &sg_ours); - fcntl (0, F_GETFL, tflags_ours); - -#ifdef TIOCGETC - ioctl (0, TIOCGETC, &tc_ours); -#endif -#ifdef TIOCGLTC - ioctl (0, TIOCGLTC, <c_ours); -#endif -#ifdef TIOCLGET - ioctl (0, TIOCLGET, &lmode_ours); -#endif - -#ifdef TIOCGPGRP - ioctl (0, TIOCGPGRP, &pgrp_ours); -#endif /* TIOCGPGRP */ - - terminal_is_ours = 1; -} - -@ - - -1.2 -log -@When the inferior process dies, deselect the current frame so that -the "where" ("backtrace") command will not think there's a stack. -@ -text -@d27 1 -a27 1 -#include <sys/fcntl.h> -a34 6 -/* May be unnecessary since many parts of inflow.c - have migrated to *-infdep.c */ -#ifdef USG -#include <sys/user.h> -#endif - -d73 1 -a73 1 -#ifdef TIOCGLTC -d76 3 -d81 3 -d86 1 -a86 1 -#endif /* TIOCGLTC */ -d117 4 -a121 1 - tc_inferior = tc_ours; -d123 3 -d127 1 -a127 1 -#endif /* TIOCGLTC */ -d150 3 -a153 1 - ioctl (0, TIOCSETC, &tc_inferior); -d155 2 -d158 1 -a158 1 -#endif /* TIOCGLTC */ -d228 3 -a231 1 - ioctl (0, TIOCGETC, &tc_inferior); -d233 2 -d236 1 -a236 1 -#endif /* TIOCGLTC */ -d253 3 -a256 1 - ioctl (0, TIOCSETC, &tc_ours); -d258 2 -d261 1 -a261 1 -#endif /* TIOCGLTC */ -d297 6 -a302 3 - printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n", - tflags_inferior, lmode_inferior, - sg_inferior.sg_flags, pgrp_inferior); -d307 3 -d314 2 -d317 3 -a319 1 -#endif /* not HAVE_TERMIO */ -d383 1 -a383 1 - pid = vfork (); -d385 1 -a385 1 - perror_with_name ("vfork"); -d497 3 -a500 1 - ioctl (0, TIOCGETC, &tc_ours); -d502 2 -d505 1 -a505 1 -#endif /* TIOCGLTC */ -@ - - -1.1 -log -@Initial revision -@ -text -@d418 1 -@ diff --git a/gdb/RCS/infrun.c,v b/gdb/RCS/infrun.c,v deleted file mode 100644 index 983922f..0000000 --- a/gdb/RCS/infrun.c,v +++ /dev/null @@ -1,1855 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.03.27.20.15.05; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.09.23.25.40; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.17.11.52; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@A/UX-specific change: define X_OK since Apple fucked it up. -@ -text -@/* Start and stop the inferior process, for GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -/* Notes on the algorithm used in wait_for_inferior to determine if we - just did a subroutine call when stepping. We have the following - information at that point: - - Current and previous (just before this step) pc. - Current and previous sp. - Current and previous start of current function. - - If the start's of the functions don't match, then - - a) We did a subroutine call. - - In this case, the pc will be at the beginning of a function. - - b) We did a subroutine return. - - Otherwise. - - c) We did a longjmp. - - If we did a longjump, we were doing "nexti", since a next would - have attempted to skip over the assembly language routine in which - the longjmp is coded and would have simply been the equivalent of a - continue. I consider this ok behaivior. We'd like one of two - things to happen if we are doing a nexti through the longjmp() - routine: 1) It behaves as a stepi, or 2) It acts like a continue as - above. Given that this is a special case, and that anybody who - thinks that the concept of sub calls is meaningful in the context - of a longjmp, I'll take either one. Let's see what happens. - - Acts like a subroutine return. I can handle that with no problem - at all. - - -->So: If the current and previous beginnings of the current - function don't match, *and* the pc is at the start of a function, - we've done a subroutine call. If the pc is not at the start of a - function, we *didn't* do a subroutine call. - - -->If the beginnings of the current and previous function do match, - either: - - a) We just did a recursive call. - - In this case, we would be at the very beginning of a - function and 1) it will have a prologue (don't jump to - before prologue, or 2) (we assume here that it doesn't have - a prologue) there will have been a change in the stack - pointer over the last instruction. (Ie. it's got to put - the saved pc somewhere. The stack is the usual place. In - a recursive call a register is only an option if there's a - prologue to do something with it. This is even true on - register window machines; the prologue sets up the new - window. It might not be true on a register window machine - where the call instruction moved the register window - itself. Hmmm. One would hope that the stack pointer would - also change. If it doesn't, somebody send me a note, and - I'll work out a more general theory. - randy@@wheaties.ai.mit.edu). This is true (albeit slipperly - so) on all machines I'm aware of: - - m68k: Call changes stack pointer. Regular jumps don't. - - sparc: Recursive calls must have frames and therefor, - prologues. - - vax: All calls have frames and hence change the - stack pointer. - - b) We did a return from a recursive call. I don't see that we - have either the ability or the need to distinguish this - from an ordinary jump. The stack frame will be printed - when and if the frame pointer changes; if we are in a - function without a frame pointer, it's the users own - lookout. - - c) We did a jump within a function. We assume that this is - true if we didn't do a recursive call. - - d) We are in no-man's land ("I see no symbols here"). We - don't worry about this; it will make calls look like simple - jumps (and the stack frames will be printed when the frame - pointer moves), which is a reasonably non-violent response. - -#if 0 - We skip this; it causes more problems than it's worth. -#ifdef SUN4_COMPILER_FEATURE - We do a special ifdef for the sun 4, forcing it to single step - into calls which don't have prologues. This means that we can't - nexti over leaf nodes, we can probably next over them (since they - won't have debugging symbols, usually), and we can next out of - functions returning structures (with a "call .stret4" at the end). -#endif -#endif -*/ - - - - - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" -#include "inferior.h" -#include "wait.h" - -#include <stdio.h> -#include <signal.h> - -/* unistd.h is needed to #define X_OK */ -#ifdef USG -#include <unistd.h> -#else -#include <sys/file.h> -#endif - -/* The idiots at Apple only define X_OK if POSIX is defined. Fuck 'em. */ -#ifndef X_OK -#define X_OK 1 /* Execute permission for access() */ -#endif - -#ifdef UMAX_PTRACE -#include <sys/param.h> -#include <sys/ptrace.h> -#endif /* UMAX_PTRACE */ - -extern char *sys_siglist[]; -extern int errno; - -/* Tables of how to react to signals; the user sets them. */ - -static char signal_stop[NSIG]; -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; - -/* This is the sequence of bytes we insert for a breakpoint. */ - -static char break_insn[] = BREAKPOINT; - -/* Nonzero => address for special breakpoint for resuming stepping. */ - -static CORE_ADDR step_resume_break_address; - -/* Original contents of the byte where the special breakpoint is. */ - -static char step_resume_break_shadow[sizeof break_insn]; - -/* Nonzero means the special breakpoint is a duplicate - so it has not itself been inserted. */ - -static int step_resume_break_duplicate; - -/* Nonzero if we are expecting a trace trap and should proceed from it. - 2 means expecting 2 trace traps and should continue both times. - That occurs when we tell sh to exec the program: we will get - a trap after the exec of sh and a second when the program is exec'd. */ - -static int trap_expected; - -/* Nonzero if the next time we try to continue the inferior, it will - step one instruction and generate a spurious trace trap. - This is used to compensate for a bug in HP-UX. */ - -static int trap_expected_after_continue; - -/* Nonzero means expecting a trace trap - and should stop the inferior and return silently when it happens. */ - -int stop_after_trap; - -/* Nonzero means expecting a trace trap due to attaching to a process. */ - -int stop_after_attach; - -/* Nonzero if pc has been changed by the debugger - since the inferior stopped. */ - -int pc_changed; - -/* Nonzero if debugging a remote machine via a serial link or ethernet. */ - -int remote_debugging; - -/* Save register contents here when about to pop a stack dummy frame. */ - -char stop_registers[REGISTER_BYTES]; - -/* Nonzero if program stopped due to error trying to insert breakpoints. */ - -static int breakpoints_failed; - -/* Nonzero if inferior is in sh before our program got exec'd. */ - -static int running_in_shell; - -/* Nonzero after stop if current stack frame should be printed. */ - -static int stop_print_frame; - -#ifdef NO_SINGLE_STEP -extern int one_stepped; /* From machine dependent code */ -extern void single_step (); /* Same. */ -#endif /* NO_SINGLE_STEP */ - -static void insert_step_breakpoint (); -static void remove_step_breakpoint (); -static void wait_for_inferior (); -static void normal_stop (); - - -/* Clear out all variables saying what to do when inferior is continued. - First do this, then set the ones you want, then call `proceed'. */ - -void -clear_proceed_status () -{ - trap_expected = 0; - step_range_start = 0; - step_range_end = 0; - step_frame_address = 0; - step_over_calls = -1; - step_resume_break_address = 0; - stop_after_trap = 0; - stop_after_attach = 0; - - /* Discard any remaining commands left by breakpoint we had stopped at. */ - clear_breakpoint_commands (); -} - -/* Basic routine for continuing the program in various fashions. - - ADDR is the address to resume at, or -1 for resume where stopped. - SIGNAL is the signal to give it, or 0 for none, - or -1 for act according to how it stopped. - STEP is nonzero if should trap after one instruction. - -1 means return after that and print nothing. - You should probably set various step_... variables - before calling here, if you are stepping. - - You should call clear_proceed_status before calling proceed. */ - -void -proceed (addr, signal, step) - CORE_ADDR addr; - int signal; - int step; -{ - int oneproc = 0; - - if (step > 0) - step_start_function = find_pc_function (read_pc ()); - if (step < 0) - stop_after_trap = 1; - - if (addr == -1) - { - /* If there is a breakpoint at the address we will resume at, - step one instruction before inserting breakpoints - so that we do not stop right away. */ - - if (!pc_changed && breakpoint_here_p (read_pc ())) - oneproc = 1; - } - else - { - write_register (PC_REGNUM, addr); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, addr + 4); -#endif - } - - if (trap_expected_after_continue) - { - /* If (step == 0), a trap will be automatically generated after - the first instruction is executed. Force step one - instruction to clear this condition. This should not occur - if step is nonzero, but it is harmless in that case. */ - oneproc = 1; - trap_expected_after_continue = 0; - } - - if (oneproc) - /* We will get a trace trap after one instruction. - Continue it automatically and insert breakpoints then. */ - trap_expected = 1; - else - { - int temp = insert_breakpoints (); - if (temp) - { - print_sys_errmsg ("ptrace", temp); - error ("Cannot insert breakpoints.\n\ -The same program may be running in another process."); - } - breakpoints_inserted = 1; - } - - /* Install inferior's terminal modes. */ - terminal_inferior (); - - if (signal >= 0) - stop_signal = signal; - /* If this signal should not be seen by program, - give it zero. Used for debugging signals. */ - else if (stop_signal < NSIG && !signal_program[stop_signal]) - stop_signal= 0; - - /* Resume inferior. */ - resume (oneproc || step, stop_signal); - - /* Wait for it to stop (if not standalone) - and in any case decode why it stopped, and act accordingly. */ - - wait_for_inferior (); - normal_stop (); -} - -/* Writing the inferior pc as a register calls this function - to inform infrun that the pc has been set in the debugger. */ - -void -writing_pc (val) - CORE_ADDR val; -{ - stop_pc = val; - pc_changed = 1; -} - -/* Start an inferior process for the first time. - Actually it was started by the fork that created it, - but it will have stopped one instruction after execing sh. - Here we must get it up to actual execution of the real program. */ - -void -start_inferior () -{ - /* We will get a trace trap after one instruction. - Continue it automatically. Eventually (after shell does an exec) - it will get another trace trap. Then insert breakpoints and continue. */ - -#ifdef START_INFERIOR_TRAPS_EXPECTED - trap_expected = START_INFERIOR_TRAPS_EXPECTED; -#else - trap_expected = 2; -#endif - - running_in_shell = 0; /* Set to 1 at first SIGTRAP, 0 at second. */ - trap_expected_after_continue = 0; - breakpoints_inserted = 0; - mark_breakpoints_out (); - - /* Set up the "saved terminal modes" of the inferior - based on what modes we are starting it with. */ - terminal_init_inferior (); - - /* Install inferior's terminal modes. */ - terminal_inferior (); - - if (remote_debugging) - { - trap_expected = 0; - fetch_inferior_registers(); - set_current_frame (create_new_frame (read_register (FP_REGNUM), - read_pc ())); - stop_frame_address = FRAME_FP (get_current_frame()); - inferior_pid = 3; - if (insert_breakpoints()) - fatal("Can't insert breakpoints"); - breakpoints_inserted = 1; - proceed(-1, -1, 0); - } - else - { - wait_for_inferior (); - normal_stop (); - } -} - -/* Start remote-debugging of a machine over a serial link. */ - -void -start_remote () -{ - clear_proceed_status (); - running_in_shell = 0; - trap_expected = 0; - inferior_pid = 3; - breakpoints_inserted = 0; - mark_breakpoints_out (); - wait_for_inferior (); - normal_stop(); -} - -#ifdef ATTACH_DETACH - -/* Attach to process PID, then initialize for debugging it - and wait for the trace-trap that results from attaching. */ - -void -attach_program (pid) - int pid; -{ - attach (pid); - inferior_pid = pid; - - mark_breakpoints_out (); - terminal_init_inferior (); - clear_proceed_status (); - stop_after_attach = 1; - /*proceed (-1, 0, -2);*/ - wait_for_inferior (); - normal_stop (); -} -#endif /* ATTACH_DETACH */ - -/* Wait for control to return from inferior to debugger. - If inferior gets a signal, we may decide to start it up again - instead of returning. That is why there is a loop in this function. - When this function actually returns it means the inferior - should be left stopped and GDB should read more commands. */ - -static void -wait_for_inferior () -{ - register int pid; - WAITTYPE w; - CORE_ADDR pc; - int tem; - int another_trap; - int random_signal; - CORE_ADDR stop_sp, prev_sp; - CORE_ADDR prev_func_start, stop_func_start; - CORE_ADDR prologue_pc; - int stop_step_resume_break; - CORE_ADDR step_resume_break_sp; - int newmisc; - int newfun_pc; - struct symbol *newfun; - struct symtab_and_line sal; - int prev_pc; - extern CORE_ADDR text_end; - - prev_pc = read_pc (); - prev_func_start = get_pc_function_start (prev_pc) + FUNCTION_START_OFFSET; - prev_sp = read_register (SP_REGNUM); - - while (1) - { - /* Clean up saved state that will become invalid */ - pc_changed = 0; - flush_cached_frames (); - - if (remote_debugging) - remote_wait (&w); - else - { - pid = wait (&w); - if (pid != inferior_pid) - continue; - } - - /* See if the process still exists; clean up if it doesn't. */ - if (WIFEXITED (w)) - { - terminal_ours_for_output (); - if (WRETCODE (w)) - printf ("\nProgram exited with code 0%o.\n", WRETCODE (w)); - else - printf ("\nProgram exited normally.\n"); - fflush (stdout); - inferior_died (); -#ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ - stop_print_frame = 0; - break; - } - else if (!WIFSTOPPED (w)) - { - kill_inferior (); - stop_print_frame = 0; - stop_signal = WTERMSIG (w); - terminal_ours_for_output (); - printf ("\nProgram terminated with signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - printf ("The inferior process no longer exists.\n"); - fflush (stdout); -#ifdef NO_SINGLE_STEP - one_stepped = 0; /* Clear single_step state since proc gone */ -#endif /* NO_SINGLE_STEP */ - break; - } - -#ifdef NO_SINGLE_STEP - if (one_stepped) - single_step (0); /* This actually cleans up the ss */ -#endif /* NO_SINGLE_STEP */ - - fetch_inferior_registers (); - stop_pc = read_pc (); - set_current_frame ( create_new_frame (read_register (FP_REGNUM), - read_pc ())); -#ifdef CONVEX_PTRACE - /* pop frame stored by user-mode trap, if present */ - if (stop_pc == BREAK_TRAP_ADDR) - { - POP_FRAME; - stop_pc = read_pc () - 2; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; - } - else if (stop_pc > STACK_END_ADDR) - { - POP_FRAME; - stop_pc = read_pc (); - } -#endif /* CONVEX_PTRACE */ - stop_frame_address = FRAME_FP (get_current_frame ()); - stop_sp = read_register (SP_REGNUM); - stop_func_start = - get_pc_function_start (stop_pc) + FUNCTION_START_OFFSET; - another_trap = 0; - stop_breakpoint = 0; - stop_step = 0; - stop_stack_dummy = 0; - stop_print_frame = 1; - stop_step_resume_break = 0; - random_signal = 0; - stopped_by_random_signal = 0; - breakpoints_failed = 0; - - /* Look at the cause of the stop, and decide what to do. - The alternatives are: - 1) break; to really stop and return to the debugger, - 2) drop through to start up again - (set another_trap to 1 to single step once) - 3) set random_signal to 1, and the decision between 1 and 2 - will be made according to the signal handling tables. */ - - stop_signal = WSTOPSIG (w); - - /* First, distinguish signals caused by the debugger from signals - that have to do with the program's own actions. - Note that breakpoint insns may cause SIGTRAP or SIGILL - or SIGEMT, depending on the operating system version. - Here we detect when a SIGILL or SIGEMT is really a breakpoint - and change it to SIGTRAP. */ - - if (stop_signal == SIGTRAP -#ifndef CONVEX_PTRACE - || (breakpoints_inserted && - (stop_signal == SIGILL - || stop_signal == SIGEMT)) -#endif /* not CONVEX_PTRACE */ - || stop_after_attach) - { - if (stop_signal == SIGTRAP && stop_after_trap) - { - stop_print_frame = 0; - break; - } - if (stop_after_attach) - break; - /* Don't even think about breakpoints - if still running the shell that will exec the program - or if just proceeded over a breakpoint. */ - if (stop_signal == SIGTRAP && trap_expected) - stop_breakpoint = 0; - else - { - /* See if there is a breakpoint at the current PC. */ -#if DECR_PC_AFTER_BREAK - /* Notice the case of stepping through a jump - that leads just after a breakpoint. - Don't confuse that with hitting the breakpoint. - What we check for is that 1) stepping is going on - and 2) the pc before the last insn does not match - the address of the breakpoint before the current pc. */ - if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && step_range_end && !step_resume_break_address)) -#endif /* DECR_PC_AFTER_BREAK not zero */ - { - /* For condition exprs. */ - select_frame (get_current_frame (), 0); - stop_breakpoint = - breakpoint_stop_status (stop_pc, stop_frame_address); - /* Following in case break condition called a - function. */ - stop_print_frame = 1; - if (stop_breakpoint && DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); -#ifdef NPC_REGNUM - write_register (NPC_REGNUM, stop_pc + 4); -#endif - pc_changed = 0; - } - } - /* See if we stopped at the special breakpoint for - stepping over a subroutine call. */ - if (stop_pc - DECR_PC_AFTER_BREAK - == step_resume_break_address) - { - stop_step_resume_break = 1; - if (DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); - pc_changed = 0; - } - } - } - - if (stop_signal == SIGTRAP) - random_signal - = !(stop_breakpoint || trap_expected - || stop_step_resume_break -#ifndef CONVEX_PTRACE - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#else - || stop_pc == text_end - 2 -#endif - || (step_range_end && !step_resume_break_address)); - else - { - random_signal - = !(stop_breakpoint - || stop_step_resume_break -#ifdef news800 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#endif - - ); - if (!random_signal) - stop_signal = SIGTRAP; - } - } - else - random_signal = 1; - - /* For the program's own signals, act according to - the signal handling tables. */ - - if (random_signal - && !(running_in_shell && stop_signal == SIGSEGV)) - { - /* Signal not for debugging purposes. */ - int printed = 0; - - stopped_by_random_signal = 1; - - if (stop_signal >= NSIG - || signal_print[stop_signal]) - { - printed = 1; - terminal_ours_for_output (); - printf ("\nProgram received signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - fflush (stdout); - } - if (stop_signal >= NSIG - || signal_stop[stop_signal]) - break; - /* If not going to stop, give terminal back - if we took it away. */ - else if (printed) - terminal_inferior (); - } - - /* Handle cases caused by hitting a breakpoint. */ - - if (!random_signal - && (stop_breakpoint || stop_step_resume_break)) - { - /* Does a breakpoint want us to stop? */ - if (stop_breakpoint && stop_breakpoint != -1 - && stop_breakpoint != -0x1000001) - { - /* 0x1000000 is set in stop_breakpoint as returned by - breakpoint_stop_status to indicate a silent - breakpoint. */ - if ((stop_breakpoint > 0 ? stop_breakpoint : - -stop_breakpoint) - & 0x1000000) - { - stop_print_frame = 0; - if (stop_breakpoint > 0) - stop_breakpoint -= 0x1000000; - else - stop_breakpoint += 0x1000000; - } - break; - } - /* But if we have hit the step-resumption breakpoint, - remove it. It has done its job getting us here. - The sp test is to make sure that we don't get hung - up in recursive calls in functions without frame - pointers. If the stack pointer isn't outside of - where the breakpoint was set (within a routine to be - stepped over), we're in the middle of a recursive - call. Not true for reg window machines (sparc) - because the must change frames to call things and - the stack pointer doesn't have to change if it - the bp was set in a routine without a frame (pc can - be stored in some other window). - - The removal of the sp test is to allow calls to - alloca. Nasty things were happening. Oh, well, - gdb can only handle one level deep of lack of - frame pointer. */ - if (stop_step_resume_break - && (step_frame_address == 0 - || (stop_frame_address == step_frame_address -#if 0 -#ifndef HAVE_REGISTER_WINDOWS - && step_resume_break_sp INNER_THAN stop_sp -#endif -#endif - ))) - { - remove_step_breakpoint (); - step_resume_break_address = 0; - } - /* Otherwise, must remove breakpoints and single-step - to get us past the one we hit. */ - else - { - remove_breakpoints (); - remove_step_breakpoint (); - breakpoints_inserted = 0; - another_trap = 1; - } - - /* We come here if we hit a breakpoint but should not - stop for it. Possibly we also were stepping - and should stop for that. So fall through and - test for stepping. But, if not stepping, - do not stop. */ - } - - /* If this is the breakpoint at the end of a stack dummy, - just stop silently. */ -#ifndef CONVEX_PTRACE - if (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -#else - /* "stack" dummy must be in text segment for Convex Unix */ - if (stop_pc == text_end - 2) -#endif - { - stop_print_frame = 0; - stop_stack_dummy = 1; -#ifdef HP9K320 - trap_expected_after_continue = 1; -#endif - break; - } - - if (step_resume_break_address) - /* Having a step-resume breakpoint overrides anything - else having to do with stepping commands until - that breakpoint is reached. */ - ; - /* If stepping through a line, keep going if still within it. */ - else if (!random_signal - && step_range_end - && stop_pc >= step_range_start - && stop_pc < step_range_end - /* The step range might include the start of the - function, so if we are at the start of the - step range and either the stack or frame pointers - just changed, we've stepped outside */ - && !(stop_pc == step_range_start - && stop_frame_address - && (stop_sp != prev_sp - || stop_frame_address != step_frame_address))) - { - /* Don't step through the return from a function - unless that is the first instruction stepped through. */ - if (ABOUT_TO_RETURN (stop_pc)) - { - stop_step = 1; - break; - } - } - - /* We stepped out of the stepping range. See if that was due - to a subroutine call that we should proceed to the end of. */ - else if (!random_signal && step_range_end) - { - if (stop_func_start) - { - prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); - } - - /* ==> See comments at top of file on this algorithm. <==*/ - - if (stop_pc == stop_func_start - && (stop_func_start != prev_func_start - || prologue_pc != stop_func_start - || stop_sp != prev_sp)) - { - newfun = find_pc_function (stop_pc); - /* It's a subroutine call */ - if (step_over_calls > 0 || (step_over_calls && newfun == 0)) - { - /* A subroutine call has happened. */ - /* Set a special breakpoint after the return */ - step_resume_break_address = - SAVED_PC_AFTER_CALL (get_current_frame ()); - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - step_resume_break_sp = stop_sp; - if (breakpoints_inserted) - insert_step_breakpoint (); - } - /* Subroutine call with source code we should not step over. - Do step to the first line of code in it. */ - else if (step_over_calls) - { - SKIP_PROLOGUE (stop_func_start); - sal = find_pc_line (stop_func_start, 0); - /* Use the step_resume_break to step until - the end of the prologue, even if that involves jumps - (as it seems to on the vax under 4.2). */ - /* If the prologue ends in the middle of a source line, - continue to the end of that source line. - Otherwise, just go to end of prologue. */ -#ifdef convex - /* no, don't either. It skips any code that's - legitimately on the first line. */ -#else - if (sal.end && sal.pc != stop_func_start) - stop_func_start = sal.end; -#endif - - if (stop_func_start == stop_pc) - { - /* We are already there: stop now. */ - stop_step = 1; - break; - } - else - /* Put the step-breakpoint there and go until there. */ - { - step_resume_break_address = stop_func_start; - step_resume_break_sp = stop_sp; - - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - if (breakpoints_inserted) - insert_step_breakpoint (); - /* Do not specify what the fp should be when we stop - since on some machines the prologue - is where the new fp value is established. */ - step_frame_address = 0; - /* And make sure stepping stops right away then. */ - step_range_end = step_range_start; - } - } - else - { - /* We get here only if step_over_calls is 0 and we - just stepped into a subroutine. I presume - that step_over_calls is only 0 when we're - supposed to be stepping at the assembly - language level.*/ - stop_step = 1; - break; - } - } - /* No subroutince call; stop now. */ - else - { - stop_step = 1; - break; - } - } - - /* Save the pc before execution, to compare with pc after stop. */ - prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */ - prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER - BREAK is defined, the - original pc would not have - been at the start of a - function. */ - prev_sp = stop_sp; - - /* If we did not do break;, it means we should keep - running the inferior and not return to debugger. */ - - /* If trap_expected is 2, it means continue once more - and insert breakpoints at the next trap. - If trap_expected is 1 and the signal was SIGSEGV, it means - the shell is doing some memory allocation--just resume it - with SIGSEGV. - Otherwise insert breakpoints now, and possibly single step. */ - - if (trap_expected > 1) - { - trap_expected--; - running_in_shell = 1; - resume (0, 0); - } - else if (running_in_shell && stop_signal == SIGSEGV) - { - resume (0, SIGSEGV); - } - else - { - /* Here, we are not awaiting another exec to get - the program we really want to debug. - Insert breakpoints now, unless we are trying - to one-proceed past a breakpoint. */ - running_in_shell = 0; - if (!breakpoints_inserted && !another_trap) - { - insert_step_breakpoint (); - breakpoints_failed = insert_breakpoints (); - if (breakpoints_failed) - break; - breakpoints_inserted = 1; - } - - trap_expected = another_trap; - - if (stop_signal == SIGTRAP) - stop_signal = 0; - - resume ((step_range_end && !step_resume_break_address) - || trap_expected, - stop_signal); - } - } -} - -/* Here to return control to GDB when the inferior stops for real. - Print appropriate messages, remove breakpoints, give terminal our modes. - - RUNNING_IN_SHELL nonzero means the shell got a signal before - exec'ing the program we wanted to run. - STOP_PRINT_FRAME nonzero means print the executing frame - (pc, function, args, file, line number and line text). - BREAKPOINTS_FAILED nonzero means stop was due to error - attempting to insert breakpoints. */ - -/* FIXME, normal_stop is ALWAYS called immediately after wait_for_inferior. - They should probably be merged into a single function, since that - would avoid numerous tests (e.g. of inferior_pid). */ - -static void -normal_stop () -{ - /* Make sure that the current_frame's pc is correct. This - is a correction for setting up the frame info before doing - DECR_PC_AFTER_BREAK */ - if (inferior_pid) - (get_current_frame ())->pc = read_pc (); - - if (breakpoints_failed) - { - terminal_ours_for_output (); - print_sys_errmsg ("ptrace", breakpoints_failed); - printf ("Stopped; cannot insert breakpoints.\n\ -The same program may be running in another process.\n"); - } - - if (inferior_pid) - remove_step_breakpoint (); - - if (inferior_pid && breakpoints_inserted) - if (remove_breakpoints ()) - { - terminal_ours_for_output (); - printf ("Cannot remove breakpoints because program is no longer writable.\n\ -It must be running in another process.\n\ -Further execution is probably impossible.\n"); - } - - breakpoints_inserted = 0; - - /* Delete the breakpoint we stopped at, if it wants to be deleted. - Delete any breakpoint that is to be deleted at the next stop. */ - - breakpoint_auto_delete (stop_breakpoint); - - /* If an auto-display called a function and that got a signal, - delete that auto-display to avoid an infinite recursion. */ - - if (stopped_by_random_signal) - delete_current_display (); - - if (step_multi && stop_step) - return; - - terminal_ours (); - - if (running_in_shell) - { - if (stop_signal == SIGSEGV) - { - char *exec_file = (char *) get_exec_file (1); - - if (access (exec_file, X_OK) != 0) - printf ("The file \"%s\" is not executable.\n", exec_file); - else - printf ("\ -You have just encountered a bug in \"sh\". GDB starts your program\n\ -by running \"sh\" with a command to exec your program.\n\ -This is so that \"sh\" will process wildcards and I/O redirection.\n\ -This time, \"sh\" crashed.\n\ -\n\ -One known bug in \"sh\" bites when the environment takes up a lot of space.\n\ -Try \"info env\" to see the environment; then use \"unset-env\" to kill\n\ -some variables whose values are large; then do \"run\" again.\n\ -\n\ -If that works, you might want to put those \"unset-env\" commands\n\ -into a \".gdbinit\" file in this directory so they will happen every time.\n"); - } - /* Don't confuse user with his program's symbols on sh's data. */ - stop_print_frame = 0; - } - - if (inferior_pid == 0) - return; - - /* Select innermost stack frame except on return from a stack dummy routine, - or if the program has exited. */ - if (!stop_stack_dummy) - { - select_frame (get_current_frame (), 0); - - if (stop_print_frame) - { - if (stop_breakpoint > 0) - printf ("\nBpt %d, ", stop_breakpoint); - print_sel_frame (stop_step - && step_frame_address == stop_frame_address - && step_start_function == find_pc_function (stop_pc)); - /* Display the auto-display expressions. */ - do_displays (); - } - } - - /* Save the function value return registers - We might be about to restore their previous contents. */ - read_register_bytes (0, stop_registers, REGISTER_BYTES); - - if (stop_stack_dummy) - { - /* Pop the empty frame that contains the stack dummy. - POP_FRAME ends with a setting of the current frame, so we - can use that next. */ - POP_FRAME; - select_frame (get_current_frame (), 0); - } -} - -static void -insert_step_breakpoint () -{ - if (step_resume_break_address && !step_resume_break_duplicate) - { - read_memory (step_resume_break_address, - step_resume_break_shadow, sizeof break_insn); - write_memory (step_resume_break_address, - break_insn, sizeof break_insn); - } -} - -static void -remove_step_breakpoint () -{ - if (step_resume_break_address && !step_resume_break_duplicate) - write_memory (step_resume_break_address, step_resume_break_shadow, - sizeof break_insn); -} - -/* Specify how various signals in the inferior should be handled. */ - -static void -handle_command (args, from_tty) - char *args; - int from_tty; -{ - register char *p = args; - int signum = 0; - register int digits, wordlen; - - if (!args) - error_no_arg ("signal to handle"); - - while (*p) - { - /* Find the end of the next word in the args. */ - for (wordlen = 0; p[wordlen] && p[wordlen] != ' ' && p[wordlen] != '\t'; - wordlen++); - for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++); - - /* If it is all digits, it is signal number to operate on. */ - if (digits == wordlen) - { - signum = atoi (p); - if (signum <= 0 || signum >= NSIG) - { - p[wordlen] = '\0'; - error ("Invalid signal %s given as argument to \"handle\".", p); - } - if (signum == SIGTRAP || signum == SIGINT) - { - if (!query ("Signal %d is used by the debugger.\nAre you sure you want to change it? ", signum)) - error ("Not confirmed."); - } - } - else if (signum == 0) - error ("First argument is not a signal number."); - - /* Else, if already got a signal number, look for flag words - saying what to do for it. */ - else if (!strncmp (p, "stop", wordlen)) - { - signal_stop[signum] = 1; - signal_print[signum] = 1; - } - else if (wordlen >= 2 && !strncmp (p, "print", wordlen)) - signal_print[signum] = 1; - else if (wordlen >= 2 && !strncmp (p, "pass", wordlen)) - signal_program[signum] = 1; - else if (!strncmp (p, "ignore", wordlen)) - signal_program[signum] = 0; - else if (wordlen >= 3 && !strncmp (p, "nostop", wordlen)) - signal_stop[signum] = 0; - else if (wordlen >= 4 && !strncmp (p, "noprint", wordlen)) - { - signal_print[signum] = 0; - signal_stop[signum] = 0; - } - else if (wordlen >= 4 && !strncmp (p, "nopass", wordlen)) - signal_program[signum] = 0; - else if (wordlen >= 3 && !strncmp (p, "noignore", wordlen)) - signal_program[signum] = 1; - /* Not a number and not a recognized flag word => complain. */ - else - { - p[wordlen] = 0; - error ("Unrecognized flag word: \"%s\".", p); - } - - /* Find start of next word. */ - p += wordlen; - while (*p == ' ' || *p == '\t') p++; - } - - if (from_tty) - { - /* Show the results. */ - printf ("Number\tStop\tPrint\tPass to program\tDescription\n"); - printf ("%d\t", signum); - printf ("%s\t", signal_stop[signum] ? "Yes" : "No"); - printf ("%s\t", signal_print[signum] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[signum] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[signum]); - } -} - -/* Print current contents of the tables set by the handle command. */ - -static void -signals_info (signum_exp) - char *signum_exp; -{ - register int i; - printf ("Number\tStop\tPrint\tPass to program\tDescription\n"); - - if (signum_exp) - { - i = parse_and_eval_address (signum_exp); - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); - return; - } - - printf ("\n"); - for (i = 0; i < NSIG; i++) - { - QUIT; - if (i > 0 && i % 16 == 0) - { - printf ("[Type Return to see more]"); - fflush (stdout); - gdb_read_line (0, 0); - } - printf ("%d\t", i); - printf ("%s\t", signal_stop[i] ? "Yes" : "No"); - printf ("%s\t", signal_print[i] ? "Yes" : "No"); - printf ("%s\t\t", signal_program[i] ? "Yes" : "No"); - printf ("%s\n", sys_siglist[i]); - } - - printf ("\nUse the \"handle\" command to change these tables.\n"); -} - -/* Save all of the information associated with the inferior<==>gdb - connection. INF_STATUS is a pointer to a "struct inferior_status" - (defined in inferior.h). */ - -struct command_line *get_breakpoint_commands (); - -void -save_inferior_status (inf_status, restore_stack_info) - struct inferior_status *inf_status; - int restore_stack_info; -{ - inf_status->pc_changed = pc_changed; - inf_status->stop_signal = stop_signal; - inf_status->stop_pc = stop_pc; - inf_status->stop_frame_address = stop_frame_address; - inf_status->stop_breakpoint = stop_breakpoint; - inf_status->stop_step = stop_step; - inf_status->stop_stack_dummy = stop_stack_dummy; - inf_status->stopped_by_random_signal = stopped_by_random_signal; - inf_status->trap_expected = trap_expected; - inf_status->step_range_start = step_range_start; - inf_status->step_range_end = step_range_end; - inf_status->step_frame_address = step_frame_address; - inf_status->step_over_calls = step_over_calls; - inf_status->step_resume_break_address = step_resume_break_address; - inf_status->stop_after_trap = stop_after_trap; - inf_status->stop_after_attach = stop_after_attach; - inf_status->breakpoint_commands = get_breakpoint_commands (); - inf_status->restore_stack_info = restore_stack_info; - - bcopy (stop_registers, inf_status->stop_registers, REGISTER_BYTES); - - record_selected_frame (&(inf_status->selected_frame_address), - &(inf_status->selected_level)); - return; -} - -void -restore_inferior_status (inf_status) - struct inferior_status *inf_status; -{ - FRAME fid; - int level = inf_status->selected_level; - - pc_changed = inf_status->pc_changed; - stop_signal = inf_status->stop_signal; - stop_pc = inf_status->stop_pc; - stop_frame_address = inf_status->stop_frame_address; - stop_breakpoint = inf_status->stop_breakpoint; - stop_step = inf_status->stop_step; - stop_stack_dummy = inf_status->stop_stack_dummy; - stopped_by_random_signal = inf_status->stopped_by_random_signal; - trap_expected = inf_status->trap_expected; - step_range_start = inf_status->step_range_start; - step_range_end = inf_status->step_range_end; - step_frame_address = inf_status->step_frame_address; - step_over_calls = inf_status->step_over_calls; - step_resume_break_address = inf_status->step_resume_break_address; - stop_after_trap = inf_status->stop_after_trap; - stop_after_attach = inf_status->stop_after_attach; - set_breakpoint_commands (inf_status->breakpoint_commands); - - bcopy (inf_status->stop_registers, stop_registers, REGISTER_BYTES); - - if (inf_status->restore_stack_info) - { - fid = find_relative_frame (get_current_frame (), - &level); - - if (FRAME_FP (fid) != inf_status->selected_frame_address || - level != 0) - { - fprintf (stderr, "Unable to restore previously selected frame.\n"); - select_frame (get_current_frame (), 0); - return; - } - - select_frame (fid, inf_status->selected_level); - } - return; -} - - -void -_initialize_infrun () -{ - register int i; - - add_info ("signals", signals_info, - "What debugger does when program gets various signals.\n\ -Specify a signal number as argument to print info on that signal only."); - - add_com ("handle", class_run, handle_command, - "Specify how to handle a signal.\n\ -Args are signal number followed by flags.\n\ -Flags allowed are \"stop\", \"print\", \"pass\",\n\ - \"nostop\", \"noprint\" or \"nopass\".\n\ -Print means print a message if this signal happens.\n\ -Stop means reenter debugger if this signal happens (implies print).\n\ -Pass means let program see this signal; otherwise program doesn't know.\n\ -Pass and Stop may be combined."); - - for (i = 0; i < NSIG; i++) - { - signal_stop[i] = 1; - signal_print[i] = 1; - signal_program[i] = 1; - } - - /* Signals caused by debugger's own actions - should not be given to the program afterwards. */ - signal_program[SIGTRAP] = 0; - signal_program[SIGINT] = 0; - - /* Signals that are not errors should not normally enter the debugger. */ -#ifdef SIGALRM - signal_stop[SIGALRM] = 0; - signal_print[SIGALRM] = 0; -#endif /* SIGALRM */ -#ifdef SIGVTALRM - signal_stop[SIGVTALRM] = 0; - signal_print[SIGVTALRM] = 0; -#endif /* SIGVTALRM */ -#ifdef SIGPROF - signal_stop[SIGPROF] = 0; - signal_print[SIGPROF] = 0; -#endif /* SIGPROF */ -#ifdef SIGCHLD - signal_stop[SIGCHLD] = 0; - signal_print[SIGCHLD] = 0; -#endif /* SIGCHLD */ -#ifdef SIGCLD - signal_stop[SIGCLD] = 0; - signal_print[SIGCLD] = 0; -#endif /* SIGCLD */ -#ifdef SIGIO - signal_stop[SIGIO] = 0; - signal_print[SIGIO] = 0; -#endif /* SIGIO */ -#ifdef SIGURG - signal_stop[SIGURG] = 0; - signal_print[SIGURG] = 0; -#endif /* SIGURG */ -} - -@ - - -1.2 -log -@Avoid accessing inferior process if it just exited or terminated with -a signal. Clean up stack frame stuff in that case too, so that the -various stack commands ("i frame", "up", "frame", "where") don't get -confused. -@ -text -@d137 5 -@ - - -1.1 -log -@Initial revision -@ -text -@d472 4 -d485 35 -a524 2 - pc_changed = 0; - flush_cached_frames (); -d569 1 -a569 30 - if (WIFEXITED (w)) - { - terminal_ours_for_output (); - if (WRETCODE (w)) - printf ("\nProgram exited with code 0%o.\n", WRETCODE (w)); - else - printf ("\nProgram exited normally.\n"); - fflush (stdout); - inferior_died (); - stop_print_frame = 0; - break; - } - else if (!WIFSTOPPED (w)) - { - kill_inferior (); - stop_print_frame = 0; - stop_signal = WTERMSIG (w); - terminal_ours_for_output (); - printf ("\nProgram terminated with signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - printf ("The inferior process no longer exists.\n"); - fflush (stdout); - break; - } - else - { - stop_signal = WSTOPSIG (w); -d571 6 -a576 6 - /* First, distinguish signals caused by the debugger from signals - that have to do with the program's own actions. - Note that breakpoint insns may cause SIGTRAP or SIGILL - or SIGEMT, depending on the operating system version. - Here we detect when a SIGILL or SIGEMT is really a breakpoint - and change it to SIGTRAP. */ -d578 1 -a578 1 - if (stop_signal == SIGTRAP -d580 3 -a582 3 - || (breakpoints_inserted && - (stop_signal == SIGILL - || stop_signal == SIGEMT)) -d584 15 -a598 1 - || stop_after_attach) -d600 1 -a600 15 - if (stop_signal == SIGTRAP && stop_after_trap) - { - stop_print_frame = 0; - break; - } - if (stop_after_attach) - break; - /* Don't even think about breakpoints - if still running the shell that will exec the program - or if just proceeded over a breakpoint. */ - if (stop_signal == SIGTRAP && trap_expected) - stop_breakpoint = 0; - else - { - /* See if there is a breakpoint at the current PC. */ -d602 8 -a609 8 - /* Notice the case of stepping through a jump - that leads just after a breakpoint. - Don't confuse that with hitting the breakpoint. - What we check for is that 1) stepping is going on - and 2) the pc before the last insn does not match - the address of the breakpoint before the current pc. */ - if (!(prev_pc != stop_pc - DECR_PC_AFTER_BREAK - && step_range_end && !step_resume_break_address)) -d611 9 -d621 2 -a622 11 - /* For condition exprs. */ - select_frame (get_current_frame (), 0); - stop_breakpoint = - breakpoint_stop_status (stop_pc, stop_frame_address); - /* Following in case break condition called a - function. */ - stop_print_frame = 1; - if (stop_breakpoint && DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); -d624 1 -a624 1 - write_register (NPC_REGNUM, stop_pc + 4); -d626 1 -a626 2 - pc_changed = 0; - } -d628 12 -a639 12 - /* See if we stopped at the special breakpoint for - stepping over a subroutine call. */ - if (stop_pc - DECR_PC_AFTER_BREAK - == step_resume_break_address) - { - stop_step_resume_break = 1; - if (DECR_PC_AFTER_BREAK) - { - stop_pc -= DECR_PC_AFTER_BREAK; - write_register (PC_REGNUM, stop_pc); - pc_changed = 0; - } -d642 1 -d644 4 -a647 4 - if (stop_signal == SIGTRAP) - random_signal - = !(stop_breakpoint || trap_expected - || stop_step_resume_break -d649 2 -a650 2 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d652 1 -a652 1 - || stop_pc == text_end - 2 -d654 6 -a659 6 - || (step_range_end && !step_resume_break_address)); - else - { - random_signal - = !(stop_breakpoint - || stop_step_resume_break -d661 2 -a662 2 - || (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d665 3 -a667 4 - ); - if (!random_signal) - stop_signal = SIGTRAP; - } -d669 3 -a671 2 - else - random_signal = 1; -d673 2 -a674 2 - /* For the program's own signals, act according to - the signal handling tables. */ -d676 50 -a725 19 - if (random_signal - && !(running_in_shell && stop_signal == SIGSEGV)) - { - /* Signal not for debugging purposes. */ - int printed = 0; - - stopped_by_random_signal = 1; - - if (stop_signal >= NSIG - || signal_print[stop_signal]) - { - printed = 1; - terminal_ours_for_output (); - printf ("\nProgram received signal %d, %s\n", - stop_signal, - stop_signal < NSIG - ? sys_siglist[stop_signal] - : "(undocumented)"); - fflush (stdout); -d727 1 -a727 7 - if (stop_signal >= NSIG - || signal_stop[stop_signal]) - break; - /* If not going to stop, give terminal back - if we took it away. */ - else if (printed) - terminal_inferior (); -d729 20 -a748 45 - - /* Handle cases caused by hitting a breakpoint. */ - - if (!random_signal - && (stop_breakpoint || stop_step_resume_break)) - { - /* Does a breakpoint want us to stop? */ - if (stop_breakpoint && stop_breakpoint != -1 - && stop_breakpoint != -0x1000001) - { - /* 0x1000000 is set in stop_breakpoint as returned by - breakpoint_stop_status to indicate a silent - breakpoint. */ - if ((stop_breakpoint > 0 ? stop_breakpoint : - -stop_breakpoint) - & 0x1000000) - { - stop_print_frame = 0; - if (stop_breakpoint > 0) - stop_breakpoint -= 0x1000000; - else - stop_breakpoint += 0x1000000; - } - break; - } - /* But if we have hit the step-resumption breakpoint, - remove it. It has done its job getting us here. - The sp test is to make sure that we don't get hung - up in recursive calls in functions without frame - pointers. If the stack pointer isn't outside of - where the breakpoint was set (within a routine to be - stepped over), we're in the middle of a recursive - call. Not true for reg window machines (sparc) - because the must change frames to call things and - the stack pointer doesn't have to change if it - the bp was set in a routine without a frame (pc can - be stored in some other window). - - The removal of the sp test is to allow calls to - alloca. Nasty things were happening. Oh, well, - gdb can only handle one level deep of lack of - frame pointer. */ - if (stop_step_resume_break - && (step_frame_address == 0 - || (stop_frame_address == step_frame_address -d751 1 -a751 1 - && step_resume_break_sp INNER_THAN stop_sp -d754 13 -a766 20 - ))) - { - remove_step_breakpoint (); - step_resume_break_address = 0; - } - /* Otherwise, must remove breakpoints and single-step - to get us past the one we hit. */ - else - { - remove_breakpoints (); - remove_step_breakpoint (); - breakpoints_inserted = 0; - another_trap = 1; - } - - /* We come here if we hit a breakpoint but should not - stop for it. Possibly we also were stepping - and should stop for that. So fall through and - test for stepping. But, if not stepping, - do not stop. */ -d769 9 -a777 2 - /* If this is the breakpoint at the end of a stack dummy, - just stop silently. */ -d779 2 -a780 2 - if (stop_sp INNER_THAN stop_pc - && stop_pc INNER_THAN stop_frame_address) -d782 2 -a783 2 - /* "stack" dummy must be in text segment for Convex Unix */ - if (stop_pc == text_end - 2) -d785 3 -a787 3 - { - stop_print_frame = 0; - stop_stack_dummy = 1; -d789 1 -a789 1 - trap_expected_after_continue = 1; -d791 2 -a792 2 - break; - } -d794 22 -a815 18 - if (step_resume_break_address) - /* Having a step-resume breakpoint overrides anything - else having to do with stepping commands until - that breakpoint is reached. */ - ; - /* If stepping through a line, keep going if still within it. */ - else if (!random_signal - && step_range_end - && stop_pc >= step_range_start - && stop_pc < step_range_end - /* The step range might include the start of the - function, so if we are at the start of the - step range and either the stack or frame pointers - just changed, we've stepped outside */ - && !(stop_pc == step_range_start - && stop_frame_address - && (stop_sp != prev_sp - || stop_frame_address != step_frame_address))) -d817 2 -a818 7 - /* Don't step through the return from a function - unless that is the first instruction stepped through. */ - if (ABOUT_TO_RETURN (stop_pc)) - { - stop_step = 1; - break; - } -d820 1 -d822 43 -a864 43 - /* We stepped out of the stepping range. See if that was due - to a subroutine call that we should proceed to the end of. */ - else if (!random_signal && step_range_end) - { - if (stop_func_start) - { - prologue_pc = stop_func_start; - SKIP_PROLOGUE (prologue_pc); - } - - /* ==> See comments at top of file on this algorithm. <==*/ - - if (stop_pc == stop_func_start - && (stop_func_start != prev_func_start - || prologue_pc != stop_func_start - || stop_sp != prev_sp)) - { - newfun = find_pc_function (stop_pc); - /* It's a subroutine call */ - if (step_over_calls > 0 || (step_over_calls && newfun == 0)) - { - /* A subroutine call has happened. */ - /* Set a special breakpoint after the return */ - step_resume_break_address = - SAVED_PC_AFTER_CALL (get_current_frame ()); - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - step_resume_break_sp = stop_sp; - if (breakpoints_inserted) - insert_step_breakpoint (); - } - /* Subroutine call with source code we should not step over. - Do step to the first line of code in it. */ - else if (step_over_calls) - { - SKIP_PROLOGUE (stop_func_start); - sal = find_pc_line (stop_func_start, 0); - /* Use the step_resume_break to step until - the end of the prologue, even if that involves jumps - (as it seems to on the vax under 4.2). */ - /* If the prologue ends in the middle of a source line, - continue to the end of that source line. - Otherwise, just go to end of prologue. */ -d866 2 -a867 2 - /* no, don't either. It skips any code that's - legitimately on the first line. */ -d869 2 -a870 2 - if (sal.end && sal.pc != stop_func_start) - stop_func_start = sal.end; -d872 6 -a877 24 - - if (stop_func_start == stop_pc) - { - /* We are already there: stop now. */ - stop_step = 1; - break; - } - else - /* Put the step-breakpoint there and go until there. */ - { - step_resume_break_address = stop_func_start; - step_resume_break_sp = stop_sp; - - step_resume_break_duplicate - = breakpoint_here_p (step_resume_break_address); - if (breakpoints_inserted) - insert_step_breakpoint (); - /* Do not specify what the fp should be when we stop - since on some machines the prologue - is where the new fp value is established. */ - step_frame_address = 0; - /* And make sure stepping stops right away then. */ - step_range_end = step_range_start; - } -d880 1 -d882 13 -a894 7 - /* We get here only if step_over_calls is 0 and we - just stepped into a subroutine. I presume - that step_over_calls is only 0 when we're - supposed to be stepping at the assembly - language level.*/ - stop_step = 1; - break; -a896 1 - /* No subroutince call; stop now. */ -d899 5 -d908 6 -d983 4 -d993 2 -a994 1 - (get_current_frame ())->pc = read_pc (); -@ diff --git a/gdb/RCS/m-aux.h,v b/gdb/RCS/m-aux.h,v deleted file mode 100644 index 2bf0702..0000000 --- a/gdb/RCS/m-aux.h,v +++ /dev/null @@ -1,591 +0,0 @@ -head 1.4; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.4 -date 89.04.26.00.51.42; author gnu; state Exp; -branches ; -next 1.3; - -1.3 -date 89.03.27.20.16.05; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.26.20.13.28; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.13.19.16.52; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.4 -log -@(1) Defined the big-endianness of the target machine. -(2) Define float to be IEEE compatible. -(3) Define invalid floats to be NaNs. -@ -text -@/* Parameters for execution on A/UX, for GDB, the GNU debugger. - Copyright (C) 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#ifndef aux -#define aux -#endif - -/* It's a USG system */ -#define USG - -/* Assembler instructions in USG "SGS" (sw generation system) format */ -#define USG_SGS_ASM - -/* Debugger information will be in COFF format. */ -#define COFF_FORMAT -#define COFF_NO_LONG_FILE_NAMES - -/* Terminal interface via termio */ -#define HAVE_TERMIO - -/* Unisoft fucked up the include files */ -#define UNISOFT_ASSHOLES - -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ -#define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN -#define WORDS_BIG_ENDIAN - -/* Floating point is IEEE compatible */ -#define IEEE_FLOAT - -/* 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, 2); \ - if (op == 0047126) \ - pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ - pc += 6; /* Skip link #long */ \ -} - -/* Immediately after a function call, return the saved pc. - Can't go through the frames for this because on some machines - the new frame is not set up until the new function executes - some instructions. */ - -#define SAVED_PC_AFTER_CALL(frame) \ -read_memory_integer (read_register (SP_REGNUM), 4) - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0x20000000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Sequence of bytes for breakpoint instruction. */ -/* A/UX uses "trap &1" */ - -#define BREAKPOINT {0x4e, 0x41} - -/* 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. */ - -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) - -/* Return 1 if P points to an invalid floating point value. */ -/* FIXME, it's not clear what "invalid" means here. I take it to mean - "something that coredumps gdb if gdb tries to manipulate it" */ - -#define INVALID_FLOAT(p, len) is_nan(p, len) - -/* 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 29 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#define REGISTER_NAMES \ - {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ - "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ - "ps", "pc", \ - "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ - "fpcontrol", "fpstatus", "fpiaddr" } - -/* 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. */ - -#define FP_REGNUM 14 /* Contains address of executing stack frame */ -#define SP_REGNUM 15 /* Contains address of top of stack */ -#define PS_REGNUM 16 /* Contains processor status */ -#define PC_REGNUM 17 /* Contains program counter */ -#define FP0_REGNUM 18 /* Floating point register 0 */ -#define FPC_REGNUM 26 /* 68881 control register */ - -/* This is a piece of magic that is given a register number REGNO - and as BLOCKEND the address in the system of the end of the user structure - and stores in ADDR the address in the kernel or core dump - of that register. */ - -#define REGISTER_U_ADDR(addr, blockend, regno) { \ - struct user u; \ - if (regno <= SP_REGNUM) \ - addr = blockend + regno * 4; \ - else if (regno == PS_REGNUM) \ - addr = blockend + RPS * 4; /* From reg.h */ \ - else if (regno == PC_REGNUM) \ - addr = blockend + PC * 4; /* From reg.h */ \ - else if (regno < FPC_REGNUM) \ - addr = (char *) u.u_fpdreg [regno-FP0_REGNUM] - (char *)&u; \ - else \ - addr = (char *)&u.u_fpsysreg[regno-FPC_REGNUM] - (char *)&u; \ -} - -/* Describe the pointer in each stack frame to the previous stack frame - (its caller). */ -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+20) - -/* Index within `registers' of the first byte of the space for - register N. */ - -#define REGISTER_BYTE(N) \ - ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \ - : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \ - : (N) * 4) - -/* Number of bytes of storage in the actual machine representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 12 bytes. */ -/* Note that the unsigned cast here forces the result of the - subtractiion to very high positive values if N < FP0_REGNUM */ - -#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) - -/* Number of bytes of storage in the program's representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 8-byte doubles. */ - -#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 12 - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 - -/* Nonzero if register N requires conversion - from raw format to virtual format. */ - -#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8) - -/* Convert data from raw format for register REGNUM - to virtual format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_from_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } - -/* Convert data from virtual format for register REGNUM - to raw format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_to_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } - -/* Return the GDB type object for the "standard" data type - of data in register N. */ - -#define REGISTER_VIRTUAL_TYPE(N) \ - (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : 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) \ - { write_register (9, (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, 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 (0, 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)) - - -/* 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 68k, the frame's nominal address - is the address of a 4-byte word containing the calling frame's address. */ - -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) - -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) - -#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) - -/* Define other aspects of the stack frame. */ - -#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4)) - -#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame) - -#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) - -/* Set VAL to the number of args passed to frame described by FI. - Can set VAL to -1, meaning no way to tell. */ - -/* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) - -#if 0 -#define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \ - register int insn = 0177777 & read_memory_integer (pc, 2); \ - val = 0; \ - if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ - val = read_memory_integer (pc + 2, 2); \ - else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \ - || (insn & 0170777) == 0050117) /* addqw */ \ - { val = (insn >> 9) & 7; if (val == 0) val = 8; } \ - else if (insn == 0157774) /* addal #WW, sp */ \ - val = read_memory_integer (pc + 2, 4); \ - val >>= 2; } -#endif - -/* Return number of bytes at start of arglist that are not really args. */ - -#define FRAME_ARGS_SKIP 8 - -/* 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) \ -{ register int regnum; \ - register int regmask; \ - register CORE_ADDR next_addr; \ - register CORE_ADDR pc; \ - int nextinsn; \ - bzero (&frame_saved_regs, sizeof frame_saved_regs); \ - if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ - && (frame_info)->pc <= (frame_info)->frame) \ - { next_addr = (frame_info)->frame; \ - pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ - else \ - { pc = get_pc_function_start ((frame_info)->pc); \ - /* Verify we have a link a6 instruction next; \ - if not we lose. If we win, find the address above the saved \ - regs using the amount of storage from the link instruction. */\ - if (044016 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \ - else if (047126 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \ - else goto lose; \ - /* If have an addal #-n, sp next, adjust next_addr. */ \ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ - next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ - } \ - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ - regmask = read_memory_integer (pc + 2, 2); \ - /* But before that can come an fmovem. Check for it. */ \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf227 == nextinsn \ - && (regmask & 0xff00) == 0xe000) \ - { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 12); \ - regmask = read_memory_integer (pc + 2, 2); } \ - if (0044327 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 0, the first written */ \ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \ - else if (0044347 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \ - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - /* fmovemx to index of sp may follow. */ \ - regmask = read_memory_integer (pc + 2, 2); \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf236 == nextinsn \ - && (regmask & 0xff00) == 0xf000) \ - { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \ - regmask = read_memory_integer (pc + 2, 2); } \ - /* clrw -(sp); movw ccr,-(sp) may follow. */ \ - if (0x426742e7 == read_memory_integer (pc, 4)) \ - (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ - lose: ; \ - (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \ - (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \ - (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \ -} - -/* Things needed for making the inferior call functions. */ - -/* Push an empty stack frame, to record the current PC, etc. */ - -#define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ - register int regnum; \ - char raw_buffer[12]; \ - sp = push_word (sp, read_register (PC_REGNUM)); \ - sp = push_word (sp, read_register (FP_REGNUM)); \ - write_register (FP_REGNUM, sp); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \ - sp = push_bytes (sp, raw_buffer, 12); } \ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - sp = push_word (sp, read_register (regnum)); \ - sp = push_word (sp, read_register (PS_REGNUM)); \ - write_register (SP_REGNUM, sp); } - -/* Discard from the stack the innermost frame, - restoring all saved registers. */ - -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ - write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ())); } - -/* This sequence of words is the instructions - fmovem 0xff,-(sp) - moveml 0xfffc,-(sp) - clrw -(sp) - movew ccr,-(sp) - /..* The arguments are pushed at this point by GDB; - no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of - the following jsr instruction. *../ - jsr @@#32323232 - addl #69696969,sp - trap #15 - nop -Note this is 28 bytes. -We actually start executing at the jsr, since the pushing of the -registers is done by PUSH_DUMMY_FRAME. If this were real code, -the arguments for the function called by the jsr would be pushed -between the moveml and the jsr, and we could allow it to execute through. -But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done, -and we cannot allow the moveml to push the registers again lest they be -taken for the arguments. */ - -#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71} - -#define CALL_DUMMY_LENGTH 28 - -#define CALL_DUMMY_START_OFFSET 12 - -/* 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 *)((char *) dummyname + 20) = nargs * 4; \ - *(int *)((char *) dummyname + 14) = 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, 0, 0, 0, SIGTRAP, 0, 0, 0, \ - 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - SIGILL } - -/* 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 ("movel #end, sp"); \ - asm ("movel #0,a6"); } - -/* Push the frame pointer register on the stack. */ -#define PUSH_FRAME_PTR \ - asm ("movel a6,sp@@-"); - -/* Copy the top-of-stack to the frame pointer register. */ -#define POP_FRAME_PTR \ - asm ("movl sp@@,a6"); - -/* 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 \ -{ asm ("clrw -(sp)"); \ - asm ("pea sp@@(10)"); \ - asm ("movem #0xfffe,sp@@-"); } - -/* 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 \ -{ asm ("subil #8,sp@@(28)"); \ - asm ("movem sp@@,#0xffff"); \ - asm ("rte"); } -@ - - -1.3 -log -@Fix DECR_PC_AFTER_BREAK; A/UX reports breaks at the breakpoint addr, -not there+2. -@ -text -@d41 11 -d100 2 -d103 1 -a103 1 -#define INVALID_FLOAT(p, len) 1 /* FIXME! Just a first guess; not checked */ -@ - - -1.2 -log -@Mostly works! -@ -text -@d82 1 -a82 1 -#define DECR_PC_AFTER_BREAK 2 -@ - - -1.1 -log -@Initial revision -@ -text -@d1 504 -@ diff --git a/gdb/RCS/m-hp9k320.h,v b/gdb/RCS/m-hp9k320.h,v deleted file mode 100644 index 8df1709..0000000 --- a/gdb/RCS/m-hp9k320.h,v +++ /dev/null @@ -1,607 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.17.11; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.19.29.58; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Change "HPUX_ASM" define to "USG_SGS_ASM", since it's really the USG -Software Generation System assembler that we're fighting here. -., -@ -text -@/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#ifndef HP9K320 -#define HP9K320 -#endif - -/* Set flag to indicate whether HP's assembler is in use. */ -#ifdef __GNU__ -#ifdef __HPUX_ASM__ -#define USG_SGS_ASM -#endif -#else -#define USG_SGS_ASM -#endif - -/* Define this for versions of hp-ux older than 6.0 */ -/* #define HPUX_VERSION_5 */ - -/* define USG if you are using sys5 /usr/include's */ -#define USG - -#define HAVE_TERMIO - -/* 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. */ - -#define NAMES_HAVE_UNDERSCORE - -/* Debugger information will be in DBX format. */ - -#define READ_DBX_FORMAT - -/* 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, 2); \ - if (op == 0047126) \ - pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ - pc += 6; /* Skip link #long */ \ -} - -/* Immediately after a function call, return the saved pc. - Can't go through the frames for this because on some machines - the new frame is not set up until the new function executes - some instructions. */ - -#define SAVED_PC_AFTER_CALL(frame) \ -read_memory_integer (read_register (SP_REGNUM), 4) - -/* This is the amount to subtract from u.u_ar0 - to get the offset in the core file of the register values. */ - -#ifdef HPUX_VERSION_5 -#define KERNEL_U_ADDR 0x00979000 -#else -#define KERNEL_U_ADDR 0x00C01000 -#endif - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0xFFF00000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Sequence of bytes for breakpoint instruction. */ - -#define BREAKPOINT {0x4e, 0x41} - -/* 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 2 - -/* Nonzero if instruction at PC is a return instruction. */ - -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) - -/* Return 1 if P points to an invalid floating point value. */ - -#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */ - -/* 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 29 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#define REGISTER_NAMES \ - {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \ - "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \ - "ps", "pc", \ - "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \ - "fpcontrol", "fpstatus", "fpiaddr" } - -/* 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. */ - -#define FP_REGNUM 14 /* Contains address of executing stack frame */ -#define SP_REGNUM 15 /* Contains address of top of stack */ -#define PS_REGNUM 16 /* Contains processor status */ -#define PC_REGNUM 17 /* Contains program counter */ -#define FP0_REGNUM 18 /* Floating point register 0 */ -#define FPC_REGNUM 26 /* 68881 control register */ - -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+12) - -/* Index within `registers' of the first byte of the space for - register N. */ - -#define REGISTER_BYTE(N) \ - ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \ - : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \ - : (N) * 4) - -/* Number of bytes of storage in the actual machine representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 12 bytes. */ - -#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) - -/* Number of bytes of storage in the program's representation - for register N. On the 68000, all regs are 4 bytes - except the floating point regs which are 8-byte doubles. */ - -#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 12 - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 - -/* Nonzero if register N requires conversion - from raw format to virtual format. */ - -#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8) - -/* Convert data from raw format for register REGNUM - to virtual format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_from_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } - -/* Convert data from virtual format for register REGNUM - to raw format for register REGNUM. */ - -#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_to_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } - -/* Return the GDB type object for the "standard" data type - of data in register N. */ - -#define REGISTER_VIRTUAL_TYPE(N) \ - (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : 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) \ - { write_register (9, (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, 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 (0, 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)) - -#define REGISTER_ADDR(u_ar0, regno) \ - (((regno) < PS_REGNUM) \ - ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \ - : (((regno) == PS_REGNUM) \ - ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \ - : (&((struct exception_stack *) (u_ar0))->e_PC))) - -#define FP_REGISTER_ADDR(u, regno) \ - (((char *) \ - (((regno) < FPC_REGNUM) \ - ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \ - : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \ - - ((char *) (& u))) - -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS - -/* 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 Sun, the frame's nominal address - is the address of a 4-byte word containing the calling frame's address. */ - -#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4)) - -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) - -#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) - -/* Define other aspects of the stack frame. */ - -#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4)) - -#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame) - -#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) - -/* Set VAL to the number of args passed to frame described by FI. - Can set VAL to -1, meaning no way to tell. */ - -/* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) - -#if 0 -#define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \ - register int insn = 0177777 & read_memory_integer (pc, 2); \ - val = 0; \ - if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ - val = read_memory_integer (pc + 2, 2); \ - else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \ - || (insn & 0170777) == 0050117) /* addqw */ \ - { val = (insn >> 9) & 7; if (val == 0) val = 8; } \ - else if (insn == 0157774) /* addal #WW, sp */ \ - val = read_memory_integer (pc + 2, 4); \ - val >>= 2; } -#endif - -/* Return number of bytes at start of arglist that are not really args. */ - -#define FRAME_ARGS_SKIP 8 - -/* 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) \ -{ register int regnum; \ - register int regmask; \ - register CORE_ADDR next_addr; \ - register CORE_ADDR pc; \ - int nextinsn; \ - bzero (&frame_saved_regs, sizeof frame_saved_regs); \ - if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \ - && (frame_info)->pc <= (frame_info)->frame) \ - { next_addr = (frame_info)->frame; \ - pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\ - else \ - { pc = get_pc_function_start ((frame_info)->pc); \ - /* Verify we have a link a6 instruction next; \ - if not we lose. If we win, find the address above the saved \ - regs using the amount of storage from the link instruction. */\ - if (044016 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \ - else if (047126 == read_memory_integer (pc, 2)) \ - next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \ - else goto lose; \ - /* If have an addal #-n, sp next, adjust next_addr. */ \ - if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \ - next_addr += read_memory_integer (pc += 2, 4), pc += 4; \ - } \ - /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \ - regmask = read_memory_integer (pc + 2, 2); \ - /* But before that can come an fmovem. Check for it. */ \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf227 == nextinsn \ - && (regmask & 0xff00) == 0xe000) \ - { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 12); \ - regmask = read_memory_integer (pc + 2, 2); } \ - if (0044327 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 0, the first written */ \ - for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \ - else if (0044347 == read_memory_integer (pc, 2)) \ - { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \ - for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \ - { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \ - (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \ - /* fmovemx to index of sp may follow. */ \ - regmask = read_memory_integer (pc + 2, 2); \ - nextinsn = 0xffff & read_memory_integer (pc, 2); \ - if (0xf236 == nextinsn \ - && (regmask & 0xff00) == 0xf000) \ - { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \ - if (regmask & 1) \ - (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \ - regmask = read_memory_integer (pc + 2, 2); } \ - /* clrw -(sp); movw ccr,-(sp) may follow. */ \ - if (0x426742e7 == read_memory_integer (pc, 4)) \ - (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \ - lose: ; \ - (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \ - (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \ - (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \ -} - -/* Things needed for making the inferior call functions. */ - -/* Push an empty stack frame, to record the current PC, etc. */ - -#define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ - register int regnum; \ - char raw_buffer[12]; \ - sp = push_word (sp, read_register (PC_REGNUM)); \ - sp = push_word (sp, read_register (FP_REGNUM)); \ - write_register (FP_REGNUM, sp); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \ - sp = push_bytes (sp, raw_buffer, 12); } \ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - sp = push_word (sp, read_register (regnum)); \ - sp = push_word (sp, read_register (PS_REGNUM)); \ - write_register (SP_REGNUM, sp); } - -/* Discard from the stack the innermost frame, - restoring all saved registers. */ - -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \ - if (fsr.regs[regnum]) \ - { read_memory (fsr.regs[regnum], raw_buffer, 12); \ - write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\ - for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \ - if (fsr.regs[regnum]) \ - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - write_register (FP_REGNUM, read_memory_integer (fp, 4)); \ - write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \ - write_register (SP_REGNUM, fp + 8); \ - flush_cached_frames (); \ - set_current_frame (create_new_frame (read_register (FP_REGNUM),\ - read_pc ()));} - -/* This sequence of words is the instructions - fmovem 0xff,-(sp) - moveml 0xfffc,-(sp) - clrw -(sp) - movew ccr,-(sp) - /..* The arguments are pushed at this point by GDB; - no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of - the following jsr instruction. *../ - jsr @@#32323232 - addl #69696969,sp - bpt - nop -Note this is 28 bytes. -We actually start executing at the jsr, since the pushing of the -registers is done by PUSH_DUMMY_FRAME. If this were real code, -the arguments for the function called by the jsr would be pushed -between the moveml and the jsr, and we could allow it to execute through. -But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done, -and we cannot allow the moveml to push the registers again lest they be -taken for the arguments. */ - -#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71} - -#define CALL_DUMMY_LENGTH 28 - -#define CALL_DUMMY_START_OFFSET 12 - -/* 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 *)((char *) dummyname + 20) = nargs * 4; \ - *(int *)((char *) dummyname + 14) = 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, 0, 0, 0, SIGTRAP, 0, 0, 0, \ - 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - SIGILL } - -#ifndef HPUX_ASM - -/* 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 ("movel $ end, sp"); \ - asm ("clrl fp"); } - -/* Push the frame pointer register on the stack. */ -#define PUSH_FRAME_PTR \ - asm ("movel fp, -(sp)"); - -/* 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 \ -{ asm ("clrw -(sp)"); \ - asm ("pea 10(sp)"); \ - asm ("movem $ 0xfffe,-(sp)"); } - -/* 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 \ -{ asm ("subil $8,28(sp)"); \ - asm ("movem (sp),$ 0xffff"); \ - asm ("rte"); } - -#else /* HPUX_ASM */ - -/* 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 ("global end"); \ - asm ("mov.l &end,%sp"); \ - asm ("clr.l %a6"); } - -/* Push the frame pointer register on the stack. */ -#define PUSH_FRAME_PTR \ - asm ("mov.l %fp,-(%sp)"); - -/* Copy the top-of-stack to the frame pointer register. */ -#define POP_FRAME_PTR \ - asm ("mov.l (%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 \ -{ asm ("clr.w -(%sp)"); \ - asm ("pea 10(%sp)"); \ - asm ("movm.l &0xfffe,-(%sp)"); } - -/* 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 \ -{ asm ("subi.l &8,28(%sp)"); \ - asm ("mov.m (%sp),&0xffff"); \ - asm ("rte"); } - -#endif /* HPUX_ASM */ -@ - - -1.1 -log -@Initial revision -@ -text -@d28 1 -a28 1 -#define HPUX_ASM -d31 1 -a31 1 -#define HPUX_ASM -@ diff --git a/gdb/RCS/m-sparc.h,v b/gdb/RCS/m-sparc.h,v deleted file mode 100644 index 1720dfe..0000000 --- a/gdb/RCS/m-sparc.h,v +++ /dev/null @@ -1,747 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.26.00.52.29; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.16.21.10.29; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.14.15.28.32; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@(1) Define big-endianness of SPARC. -(2) Define IEEE compatible float. -@ -text -@/* Parameters for execution on a Sun 4, for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@@mcc.com) - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#ifndef sun4 -#define sun4 -#endif - -/* 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. */ - -#define NAMES_HAVE_UNDERSCORE - -/* Debugger information will be in DBX format. */ - -#define READ_DBX_FORMAT - -/* Big or Little-Endian target machine - BITS: defined if bit #0 is the high-order bit of a byte. - BYTES:defined if byte#0 is the high-order byte of an int. - WORDS:defined if word#0 is the high-order word of a double. */ -#define BITS_BIG_ENDIAN -#define BYTES_BIG_ENDIAN -#define WORDS_BIG_ENDIAN - -/* Floating point is IEEE compatible. */ -#define IEEE_FLOAT - -/* 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) \ - { pc = skip_prologue (pc); } - -/* Immediately after a function call, return the saved pc. - Can't go through the frames for this because on some machines - the new frame is not set up until the new function executes - some instructions. */ - -/* On the Sun 4 under SunOS, the compile will leave a fake insn which - encodes the structure size being returned. If we detect such - a fake insn, step past it. */ - -#define PC_ADJUST(pc) ((read_memory_integer (pc + 8, 4) & 0xfffffe00) == 0 ? \ - pc+12 : pc+8) - -#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM)) - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0xf8000000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Stack has strict alignment. */ - -#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8) - -/* Sequence of bytes for breakpoint instruction. */ - -#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01} - -/* 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 SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0". - - Note: this does not work for functions returning structures under SunOS. */ -#define ABOUT_TO_RETURN(pc) \ - ((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008) - -/* Return 1 if P points to an invalid floating point value. */ - -#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */ - -/* 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 72 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#define REGISTER_NAMES \ -{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \ - "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \ - "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \ - "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \ - \ - "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", \ - \ - "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" }; - -/* 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. */ - -#define FP_REGNUM 30 /* Contains address of executing stack frame */ -#define RP_REGNUM 15 /* Contains return address value, *before* \ - any windows get switched. */ -#define SP_REGNUM 14 /* Contains address of top of stack, \ - which is also the bottom of the frame. */ -#define Y_REGNUM 64 /* Temp register for multiplication, etc. */ -#define PS_REGNUM 65 /* Contains processor status */ -#define PC_REGNUM 68 /* Contains program counter */ -#define NPC_REGNUM 69 /* Contains next PC */ -#define FP0_REGNUM 32 /* Floating point register 0 */ -#define FPS_REGNUM 70 /* Floating point status register */ -#define CPS_REGNUM 71 /* Coprocessor status register */ - -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (32*4+32*4+8*4) - -/* Index within `registers' of the first byte of the space for - register N. */ -/* ?? */ -#define REGISTER_BYTE(N) ((N)*4) - -/* The SPARC processor has register windows. */ - -#define HAVE_REGISTER_WINDOWS - -/* Is this register part of the register window system? A yes answer - implies that 1) The name of this register will not be the same in - other frames, and 2) This register is automatically "saved" (out - registers shifting into ins counts) upon subroutine calls and thus - there is no need to search more than one stack frame for it. */ - -#define REGISTER_IN_WINDOW_P(regnum) \ - ((regnum) >= 8 && (regnum) < 32) - -/* Number of bytes of storage in the actual machine representation - for register N. */ - -/* On the SPARC, all regs are 4 bytes. */ - -#define REGISTER_RAW_SIZE(N) (4) - -/* Number of bytes of storage in the program's representation - for register N. */ - -/* On the SPARC, all regs are 4 bytes. */ - -#define REGISTER_VIRTUAL_SIZE(N) (4) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 8 - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 - -/* 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), 4); } - -/* 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), 4); } - -/* Return the GDB type object for the "standard" data type - of data in register N. */ - -#define REGISTER_VIRTUAL_TYPE(N) \ - ((N) < 32 ? builtin_type_int : (N) < 64 ? 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) \ - { write_memory ((SP)+(16*4), &(ADDR), 4); } - -/* 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 (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE)) - -/* Write into appropriate registers a function return value - of type TYPE, given in virtual format. */ -/* On sparc, values are returned in register %o0. */ -#define STORE_RETURN_VALUE(TYPE,VALBUF) \ - write_register_bytes (REGISTER_BYTE (8), 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) \ - (read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4)) - -/* Enable use of alternate code to read and write registers. */ - -#define NEW_SUN_PTRACE - -/* Enable use of alternate code for Sun's format of core dump file. */ - -#define NEW_SUN_CORE - -/* Do implement the attach and detach commands. */ - -#define ATTACH_DETACH - -/* It is safe to look for symsegs on a Sun, because Sun's ld - does not screw up with random garbage at end of file. */ - -#define READ_GDB_SYMSEGS - - -/* Describe the pointer in each stack frame to the previous stack frame - (its caller). */ -#include <machine/reg.h> - -#define GET_RWINDOW_REG(FRAME, REG) \ - (read_memory_integer (&((struct rwindow *)FRAME)->REG, 4)) - -/* 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 Sun 4, the frame-chain's nominal address - is held in the frame pointer register. - - On the Sun4, the frame (in %fp) is %sp for the previous frame. - From the previous frame's %sp, we can find the previous frame's - %fp: it is in the save area just above the previous frame's %sp. - - If we are setting up an arbitrary frame, we'll need to know where - it ends. Hence the following. This part of the frame cache - structure should be checked before it is assumed that this frame's - bottom is in the stack pointer. - - If there isn't a frame below this one, the bottom of this frame is - in the stack pointer. - - If there is a frame below this one, and the frame pointers are - identical, it's a leaf frame and the bottoms are the same also. - - Otherwise the bottom of this frame is the top of the next frame. */ - -#define EXTRA_FRAME_INFO FRAME_ADDR bottom; -#define INIT_EXTRA_FRAME_INFO(fci) \ - (fci)->bottom = \ - ((fci)->next ? \ - ((fci)->frame == (fci)->next_frame ? \ - (fci)->next->bottom : (fci)->next->frame) : \ - read_register (SP_REGNUM)); - -#define FRAME_CHAIN(thisframe) \ - GET_RWINDOW_REG ((thisframe)->frame, rw_in[6]) - -/* Avoid checking FRAME_SAVED_PC since that screws us due to - improperly set up saved PC on a signal trampoline call */ -#if 0 -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) -#else -#define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0) -#endif - -#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) - -/* Define other aspects of the stack frame. */ - -/* Where is the PC for a specific frame */ - -#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_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame) - -#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) - -/* Set VAL to the number of args passed to frame described by FI. - Can set VAL to -1, meaning no way to tell. */ - -/* We can't tell how many args there are - now that the C compiler delays popping them. */ -#define FRAME_NUM_ARGS(val,fi) (val = -1) - -/* Return number of bytes at start of arglist that are not really args. */ - -#define FRAME_ARGS_SKIP 68 - -/* 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. - - Note that on register window machines, we are currently making the - assumption that window registers are being saved somewhere in the - frame in which they are being used. If they are stored in an - inferior frame, find_saved_register will break. - - On the Sun 4, the only time all registers are saved is when - a dummy frame is involved. Otherwise, the only saved registers - are the LOCAL and IN registers which are saved as a result - of the "save/restore" opcodes. This condition is determined - by address rather than by value. */ - -#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \ -{ register int regnum; \ - register CORE_ADDR pc; \ - FRAME_ADDR frame = read_register (FP_REGNUM); \ - FRAME fid = FRAME_INFO_ID (fi); \ - if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \ - bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \ - if ((fi)->pc >= frame - CALL_DUMMY_LENGTH - 0x140 \ - && (fi)->pc <= frame) \ - { \ - for (regnum = 1; regnum < 8; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + regnum * 4 - 0xa0; \ - for (regnum = 24; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - 24) * 4 - 0xc0; \ - for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - FP0_REGNUM) * 4 - 0x80; \ - for (regnum = 64; regnum < NUM_REGS; regnum++) \ - (frame_saved_regs).regs[regnum] = \ - frame + (regnum - 64) * 4 - 0xe0; \ - frame = (fi)->bottom ? \ - (fi)->bottom : read_register (SP_REGNUM); \ - } \ - else \ - { \ - frame = (fi)->bottom ? \ - (fi)->bottom : read_register (SP_REGNUM); \ - for (regnum = 16; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \ - } \ - if ((fi)->next) \ - { \ - /* Pull off either the next frame pointer or \ - the stack pointer */ \ - FRAME_ADDR next_next_frame = \ - ((fi)->next->bottom ? \ - (fi)->next->bottom : \ - read_register (SP_REGNUM)); \ - for (regnum = 8; regnum < 16; regnum++) \ - (frame_saved_regs).regs[regnum] = next_next_frame + regnum * 4; \ - } \ - /* Otherwise, whatever we would get from ptrace(GETREGS) */ \ - /* is accurate */ \ - for (regnum = 30; regnum < 32; regnum++) \ - (frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \ - (frame_saved_regs).regs[SP_REGNUM] = frame; \ - (frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \ -} - -/* Things needed for making the inferior call functions. */ -/* - * First of all, let me give my opinion of what the DUMMY_FRAME - * actually looks like. - * - * | | - * | | - * + - - - - - - - - - - - - - - - - +<-- fp (level 0) - * | | - * | | - * | | - * | | - * | Frame of innermost program | - * | function | - * | | - * | | - * | | - * | | - * | | - * |---------------------------------|<-- sp (level 0), fp (c) - * | | - * DUMMY | fp0-31 | - * | | - * | ------ |<-- fp - 0x80 - * FRAME | g0-7 |<-- fp - 0xa0 - * | i0-7 |<-- fp - 0xc0 - * | other |<-- fp - 0xe0 - * | ? | - * | ? | - * |---------------------------------|<-- sp' = fp - 0x140 - * | | - * xcution start | | - * sp' + 0x94 -->| CALL_DUMMY (x code) | - * | | - * | | - * |---------------------------------|<-- sp'' = fp - 0x200 - * | align sp to 8 byte boundary | - * | ==> args to fn <== | - * Room for | | - * i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44| - * |---------------------------------|<-- final sp (variable) - * | | - * | Where function called will | - * | build frame. | - * | | - * | | - * - * I understand everything in this picture except what the space - * between fp - 0xe0 and fp - 0x140 is used for. Oh, and I don't - * understand why there's a large chunk of CALL_DUMMY that never gets - * executed (its function is superceeded by PUSH_DUMMY_FRAME; they - * are designed to do the same thing). - * - * PUSH_DUMMY_FRAME saves the registers above sp' and pushes the - * register file stack down one. - * - * call_function then writes CALL_DUMMY, pushes the args onto the - * stack, and adjusts the stack pointer. - * - * run_stack_dummy then starts execution (in the middle of - * CALL_DUMMY, as directed by call_function). - */ - -/* Push an empty stack frame, to record the current PC, etc. */ - -/* Note: to be perfectly correct, we have to restore the - IN registers (which were the OUT registers of the calling frame). */ -/* Note that the write's are of registers in the context of the newly - pushed frame. Thus the the fp*'s, the g*'s, the i*'s, and - the others, of the new frame, are being saved. - The locals are new; they don't need to be saved. The i's and l's of - the last frame were saved by the do_save_insn in the register - file (ie. on the stack, since a context switch happended imm after) */ -/* We note that the return pointer register does not *need* to have - the pc saved into it (return from this frame will be accomplished - by a POP_FRAME), however, just in case it might be needed, we will - leave it. However, we will write the original value of RP into the - location on the stack for saving i7 (what rp turns into upon call); - this way we don't loose the value with our function call. */ -/* Note that the pc saved must be 8 less than the actual pc, since - both POP_FRAME and the normal return sequence on the sparc return - to 8 more than the value of RP_REGNUM */ - -#define PUSH_DUMMY_FRAME \ -{ extern char registers[]; \ - register int regnum; \ - CORE_ADDR fp = read_register (FP_REGNUM); \ - CORE_ADDR pc = read_register (PC_REGNUM) - 8; \ - CORE_ADDR rp = read_register (RP_REGNUM); \ - void do_save_insn (); \ - supply_register (RP_REGNUM, &pc); \ - do_save_insn (0x140); \ - fp = read_register (FP_REGNUM); \ - write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\ - write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \ - write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 7 * 4); \ - write_memory (fp - 0xa4, &rp, 4); \ - write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \ -} - -/* Discard from the stack the innermost frame, - restoring all saved registers. - Note that the values stored in fsr by get_frame_saved_regs are *in - the context of the inferior frame*. What this means is that the i - regs of fsr must be restored into the o regs of the frame popped - into. We don't care about the output regs of the inferior frame. - - This is true for dummy frames. Is it true for normal frames? It - really does appear so. */ - -#define POP_FRAME \ -{ register FRAME frame = get_current_frame (); \ - register CORE_ADDR fp; \ - register CORE_ADDR pc; \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info *fi; \ - char raw_buffer[REGISTER_BYTES]; \ - void do_restore_insn (); \ - fi = get_frame_info (frame); \ - fp = fi->frame; \ - get_frame_saved_regs (fi, &fsr); \ - pc = read_memory_integer (fsr.regs[PC_REGNUM], 4); \ - do_restore_insn (PC_ADJUST (pc)); \ - if (fsr.regs[FP0_REGNUM]) \ - { \ - read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); \ - write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4); \ - } \ - if (fsr.regs[1]) \ - { \ - read_memory (fsr.regs[1], raw_buffer, 7 * 4); \ - write_register_bytes (REGISTER_BYTE (1), raw_buffer, 7 * 4); \ - } \ - if (fsr.regs[24]) \ - { \ - read_memory (fsr.regs[24], raw_buffer, 8 * 4); \ - write_register_bytes (REGISTER_BYTE (8), raw_buffer, 8 * 4); \ - } \ - if (fsr.regs[PS_REGNUM]) \ - write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \ - if (fsr.regs[Y_REGNUM]) \ - write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4)); \ - if (fsr.regs[NPC_REGNUM]) \ - write_register (NPC_REGNUM, read_memory_integer (fsr.regs[NPC_REGNUM], 4)); \ - flush_cached_frames (); \ - set_current_frame ( create_new_frame (read_register (FP_REGNUM), \ - read_pc ())); } - -/* This sequence of words is the instructions - - save %sp,-0x140,%sp - std %f30,[%fp-0x08] - std %f28,[%fp-0x10] - std %f26,[%fp-0x18] - std %f24,[%fp-0x20] - std %f22,[%fp-0x28] - std %f20,[%fp-0x30] - std %f18,[%fp-0x38] - std %f16,[%fp-0x40] - std %f14,[%fp-0x48] - std %f12,[%fp-0x50] - std %f10,[%fp-0x58] - std %f8,[%fp-0x60] - std %f6,[%fp-0x68] - std %f4,[%fp-0x70] - std %f2,[%fp-0x78] - std %f0,[%fp-0x80] - std %g6,[%fp-0x88] - std %g4,[%fp-0x90] - std %g2,[%fp-0x98] - std %g0,[%fp-0xa0] - std %i6,[%fp-0xa8] - std %i4,[%fp-0xb0] - std %i2,[%fp-0xb8] - std %i0,[%fp-0xc0] - nop ! stcsr [%fp-0xc4] - nop ! stfsr [%fp-0xc8] - nop ! wr %npc,[%fp-0xcc] - nop ! wr %pc,[%fp-0xd0] - rd %tbr,%o0 - st %o0,[%fp-0xd4] - rd %wim,%o1 - st %o0,[%fp-0xd8] - rd %psr,%o0 - st %o0,[%fp-0xdc] - rd %y,%o0 - st %o0,[%fp-0xe0] - - /..* The arguments are pushed at this point by GDB; - no code is needed in the dummy for this. - The CALL_DUMMY_START_OFFSET gives the position of - the following ld instruction. *../ - - ld [%sp+0x58],%o5 - ld [%sp+0x54],%o4 - ld [%sp+0x50],%o3 - ld [%sp+0x4c],%o2 - ld [%sp+0x48],%o1 - call 0x00000000 - ld [%sp+0x44],%o0 - nop - ta 1 - nop - - note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes. - note that the `call' insn is a relative, not an absolute call. - note that the `nop' at the end is needed to keep the trap from - clobbering things (if NPC pointed to garbage instead). - -We actually start executing at the `sethi', since the pushing of the -registers (as arguments) is done by PUSH_DUMMY_FRAME. If this were -real code, the arguments for the function called by the CALL would be -pushed between the list of ST insns and the CALL, and we could allow -it to execute through. But the arguments have to be pushed by GDB -after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST -insns to be performed again, lest the registers saved be taken for -arguments. */ - -#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8, \ - 0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8, \ - 0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8, \ - 0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88, \ - 0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68, \ - 0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48, \ - 0xf03fbf40, 0x01000000, 0x01000000, 0x01000000, \ - 0x01000000, 0x91580000, 0xd027bf50, 0x93500000, \ - 0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000, \ - 0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050, \ - 0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044, \ - 0x01000000, 0x91d02001, 0x01000000, 0x01000000} - -#define CALL_DUMMY_LENGTH 192 - -#define CALL_DUMMY_START_OFFSET 148 - -#define CALL_DUMMY_STACK_ADJUST 68 - -/* 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 *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \ - if (TYPE_CODE (type) == TYPE_CODE_STRUCT \ - || TYPE_CODE (type) == TYPE_CODE_UNION) \ - *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \ -} - - -/* Sparc has no reliable single step ptrace call */ - -#define NO_SINGLE_STEP 1 - -/* It does have a wait structure, and it might help things out . . . */ - -#define HAVE_WAIT_STRUCT - -/* Handle a feature in the sun4 compiler ("call .stret4" at the end of - functions returning structures). */ - -#define SUN4_COMPILER_FEATURE - -/* We need two arguments (in general) to the "info frame" command. - Note that the definition of this macro implies that there exists a - function "setup_arbitrary_frame" in mach-dep.c */ - -#define FRAME_SPECIFICATION_DYADIC - -/* KDB stuff flushed for now. */ -@ - - -1.2 -log -@Don't stop the stack trace until the "next frame pointer" is zero. -@ -text -@d39 11 -@ - - -1.1 -log -@Initial revision -@ -text -@d66 1 -a66 1 -#define STACK_END_ADDR 0xff000000 -d307 3 -d312 4 -@ diff --git a/gdb/RCS/m68k-pinsn.c,v b/gdb/RCS/m68k-pinsn.c,v deleted file mode 100644 index d8c7f84..0000000 --- a/gdb/RCS/m68k-pinsn.c,v +++ /dev/null @@ -1,824 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.19.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.19.29.33; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Change HPUX_ASM to USG_SGS_ASM since it's really the Sys V -"Software Generation System" that we are fighting here. -@ -text -@/* Print m68k instructions for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "opcode.h" - -/* 68k instructions are never longer than this many bytes. */ -#define MAXLEN 22 - -/* Number of elements in the opcode table. */ -#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0]) - -extern char *reg_names[]; -char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr", - "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"}; - -static unsigned char *print_insn_arg (); -static unsigned char *print_indexed (); -static void print_base (); -static int fetch_arg (); - -#define NEXTBYTE(p) (p += 2, ((char *)p)[-1]) - -#define NEXTWORD(p) \ - (p += 2, ((((char *)p)[-2]) << 8) + p[-1]) - -#define NEXTLONG(p) \ - (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]) - -#define NEXTSINGLE(p) \ - (p += 4, *((float *)(p - 4))) - -#define NEXTDOUBLE(p) \ - (p += 8, *((double *)(p - 8))) - -#define NEXTEXTEND(p) \ - (p += 12, 0.0) /* Need a function to convert from extended to double - precision... */ - -#define NEXTPACKED(p) \ - (p += 12, 0.0) /* Need a function to convert from packed to double - precision. Actually, it's easier to print a - packed number than a double anyway, so maybe - there should be a special case to handle this... */ - -/* Print the m68k instruction at address MEMADDR in debugged memory, - on STREAM. Returns length of the instruction, in bytes. */ - -int -print_insn (memaddr, stream) - CORE_ADDR memaddr; - FILE *stream; -{ - unsigned char buffer[MAXLEN]; - register int i; - register unsigned char *p; - register char *d; - register int bestmask; - int best; - - read_memory (memaddr, buffer, MAXLEN); - - bestmask = 0; - best = -1; - for (i = 0; i < NOPCODES; i++) - { - register unsigned int opcode = m68k_opcodes[i].opcode; - register unsigned int match = m68k_opcodes[i].match; - if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24))) - && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16))) - && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8))) - && ((0xff & buffer[3] & match) == (0xff & opcode))) - { - /* Don't use for printout the variants of divul and divsl - that have the same register number in two places. - The more general variants will match instead. */ - for (d = m68k_opcodes[i].args; *d; d += 2) - if (d[1] == 'D') - break; - - /* Don't use for printout the variants of most floating - point coprocessor instructions which use the same - register number in two places, as above. */ - if (*d == 0) - for (d = m68k_opcodes[i].args; *d; d += 2) - if (d[1] == 't') - break; - - if (*d == 0 && match > bestmask) - { - best = i; - bestmask = match; - } - } - } - - /* Handle undefined instructions. */ - if (best < 0) - { - fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]); - return 2; - } - - fprintf (stream, "%s", m68k_opcodes[best].name); - - /* Point at first word of argument data, - and at descriptor for first argument. */ - p = buffer + 2; - - /* Why do this this way? -MelloN */ - for (d = m68k_opcodes[best].args; *d; d += 2) - { - if (d[0] == '#') - { - if (d[1] == 'l' && p - buffer < 6) - p = buffer + 6; - else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' ) - p = buffer + 4; - } - if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4) - p = buffer + 4; - if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6) - p = buffer + 6; - } - - d = m68k_opcodes[best].args; - - if (*d) - fputc (' ', stream); - - while (*d) - { - p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream); - d += 2; - if (*d && *(d - 2) != 'I' && *d != 'k') - fprintf (stream, ","); - } - return p - buffer; -} - -static unsigned char * -print_insn_arg (d, buffer, p, addr, stream) - char *d; - unsigned char *buffer; - register unsigned char *p; - CORE_ADDR addr; /* PC for this arg to be relative to */ - FILE *stream; -{ - register int val; - register int place = d[1]; - int regno; - register char *regname; - register unsigned char *p1; - register double flval; - int flt_p; - - switch (*d) - { - case 'C': - fprintf (stream, "ccr"); - break; - - case 'S': - fprintf (stream, "sr"); - break; - - case 'U': - fprintf (stream, "usp"); - break; - - case 'J': - { - static struct { char *name; int value; } names[] - = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002}, - {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802}, - {"msp", 0x803}, {"isp", 0x804}}; - - val = fetch_arg (buffer, place, 12); - for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--) - if (names[regno].value == val) - { - fprintf (stream, names[regno].name); - break; - } - if (regno < 0) - fprintf (stream, "%d", val); - } - break; - - case 'Q': - val = fetch_arg (buffer, place, 3); - if (val == 0) val = 8; - fprintf (stream, "#%d", val); - break; - - case 'M': - val = fetch_arg (buffer, place, 8); - if (val & 0x80) - val = val - 0x100; - fprintf (stream, "#%d", val); - break; - - case 'T': - val = fetch_arg (buffer, place, 4); - fprintf (stream, "#%d", val); - break; - - case 'D': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 'A': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]); - break; - - case 'R': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]); - break; - - case 'F': - fprintf (stream, "fp%d", fetch_arg (buffer, place, 3)); - break; - - case 'O': - val = fetch_arg (buffer, place, 6); - if (val & 0x20) - fprintf (stream, "%s", reg_names [val & 7]); - else - fprintf (stream, "%d", val); - break; - - case '+': - fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; - - case '-': - fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; - - case 'k': - if (place == 'k') - fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]); - else if (place == 'C') - { - val = fetch_arg (buffer, place, 7); - if ( val > 63 ) /* This is a signed constant. */ - val -= 128; - fprintf (stream, "{#%d}", val); - } - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - break; - - case '#': - p1 = buffer + 2; - if (place == 's') - val = fetch_arg (buffer, place, 4); - else if (place == 'C') - val = fetch_arg (buffer, place, 7); - else if (place == '8') - val = fetch_arg (buffer, place, 3); - else if (place == '3') - val = fetch_arg (buffer, place, 8); - else if (place == 'b') - val = NEXTBYTE (p1); - else if (place == 'w') - val = NEXTWORD (p1); - else if (place == 'l') - val = NEXTLONG (p1); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; - - case '^': - if (place == 's') - val = fetch_arg (buffer, place, 4); - else if (place == 'C') - val = fetch_arg (buffer, place, 7); - else if (place == '8') - val = fetch_arg (buffer, place, 3); - else if (place == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; - - case 'B': - if (place == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else if (place == 'g') - { - val = ((char *)buffer)[1]; - if (val == 0) - val = NEXTWORD (p); - else if (val == -1) - val = NEXTLONG (p); - } - else if (place == 'c') - { - if (buffer[1] & 0x40) /* If bit six is one, long offset */ - val = NEXTLONG (p); - else - val = NEXTWORD (p); - } - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - - print_address (addr + val, stream); - break; - - case 'd': - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 's': - fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]); - break; - - case 'I': - val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */ - if (val != 1) /* Unusual coprocessor ID? */ - fprintf (stream, "(cpid=%d) ", val); - if (place == 'i') - p += 2; /* Skip coprocessor extended operands */ - break; - - case '*': - case '~': - case '%': - case ';': - case '@@': - case '!': - case '$': - case '?': - case '/': - case '&': - - if (place == 'd') - { - val = fetch_arg (buffer, 'x', 6); - val = ((val & 7) << 3) + ((val >> 3) & 7); - } - else - val = fetch_arg (buffer, 's', 6); - - /* Get register number assuming address register. */ - regno = (val & 7) + 8; - regname = reg_names[regno]; - switch (val >> 3) - { - case 0: - fprintf (stream, "%s", reg_names[val]); - break; - - case 1: - fprintf (stream, "%s", regname); - break; - - case 2: - fprintf (stream, "(%s)", regname); - break; - - case 3: - fprintf (stream, "(%s)+", regname); - break; - - case 4: - fprintf (stream, "-(%s)", regname); - break; - - case 5: - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, regname); - break; - - case 6: - p = print_indexed (regno, p, addr, stream); - break; - - case 7: - switch (val & 7) - { - case 0: - val = NEXTWORD (p); - fprintf (stream, "@@#"); - print_address (val, stream); - break; - - case 1: - val = NEXTLONG (p); - fprintf (stream, "@@#"); - print_address (val, stream); - break; - - case 2: - val = NEXTWORD (p); - print_address (addr + val, stream); - break; - - case 3: - p = print_indexed (-1, p, addr, stream); - break; - - case 4: - flt_p = 1; /* Assume it's a float... */ - switch( place ) - { - case 'b': - val = NEXTBYTE (p); - flt_p = 0; - break; - - case 'w': - val = NEXTWORD (p); - flt_p = 0; - break; - - case 'l': - val = NEXTLONG (p); - flt_p = 0; - break; - - case 'f': - flval = NEXTSINGLE(p); - break; - - case 'F': - flval = NEXTDOUBLE(p); - break; - - case 'x': - flval = NEXTEXTEND(p); - break; - - case 'p': - flval = NEXTPACKED(p); - break; - - default: - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - } - if ( flt_p ) /* Print a float? */ - fprintf (stream, "#%g", flval); - else - fprintf (stream, "#%d", val); - break; - - default: - fprintf (stream, "<invalid address mode 0%o>", val); - } - } - break; - - default: - error ("Invalid arg format in opcode table: \"%c\".", *d); - } - - return (unsigned char *) p; -} - -/* Fetch BITS bits from a position in the instruction specified by CODE. - CODE is a "place to put an argument", or 'x' for a destination - that is a general address (mode and register). - BUFFER contains the instruction. */ - -static int -fetch_arg (buffer, code, bits) - unsigned char *buffer; - char code; - int bits; -{ - register int val; - switch (code) - { - case 's': - val = buffer[1]; - break; - - case 'd': /* Destination, for register or quick. */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 9; - break; - - case 'x': /* Destination, for general arg */ - val = (buffer[0] << 8) + buffer[1]; - val >>= 6; - break; - - case 'k': - val = (buffer[3] >> 4); - break; - - case 'C': - val = buffer[3]; - break; - - case '1': - val = (buffer[2] << 8) + buffer[3]; - val >>= 12; - break; - - case '2': - val = (buffer[2] << 8) + buffer[3]; - val >>= 6; - break; - - case '3': - case 'j': - val = (buffer[2] << 8) + buffer[3]; - break; - - case '4': - val = (buffer[4] << 8) + buffer[5]; - val >>= 12; - break; - - case '5': - val = (buffer[4] << 8) + buffer[5]; - val >>= 6; - break; - - case '6': - val = (buffer[4] << 8) + buffer[5]; - break; - - case '7': - val = (buffer[2] << 8) + buffer[3]; - val >>= 7; - break; - - case '8': - val = (buffer[2] << 8) + buffer[3]; - val >>= 10; - break; - - default: - abort (); - } - - switch (bits) - { - case 3: - return val & 7; - case 4: - return val & 017; - case 5: - return val & 037; - case 6: - return val & 077; - case 7: - return val & 0177; - case 8: - return val & 0377; - case 12: - return val & 07777; - default: - abort (); - } -} - -/* Print an indexed argument. The base register is BASEREG (-1 for pc). - P points to extension word, in buffer. - ADDR is the nominal core address of that extension word. */ - -static unsigned char * -print_indexed (basereg, p, addr, stream) - int basereg; - unsigned char *p; - FILE *stream; - CORE_ADDR addr; -{ - register int word; - static char *scales[] = {"", "*2", "*4", "*8"}; - register int base_disp; - register int outer_disp; - char buf[40]; - - word = NEXTWORD (p); - - /* Generate the text for the index register. - Where this will be output is not yet determined. */ - sprintf (buf, "[%s.%c%s]", - reg_names[(word >> 12) & 0xf], - (word & 0x800) ? 'l' : 'w', - scales[(word >> 9) & 3]); - - /* Handle the 68000 style of indexing. */ - - if ((word & 0x100) == 0) - { - print_base (basereg, - ((word & 0x80) ? word | 0xff00 : word & 0xff) - + ((basereg == -1) ? addr : 0), - stream); - fprintf (stream, "%s", buf); - return p; - } - - /* Handle the generalized kind. */ - /* First, compute the displacement to add to the base register. */ - - if (word & 0200) - basereg = -2; - if (word & 0100) - buf[0] = 0; - base_disp = 0; - switch ((word >> 4) & 3) - { - case 2: - base_disp = NEXTWORD (p); - break; - case 3: - base_disp = NEXTLONG (p); - } - if (basereg == -1) - base_disp += addr; - - /* Handle single-level case (not indirect) */ - - if ((word & 7) == 0) - { - print_base (basereg, base_disp, stream); - fprintf (stream, "%s", buf); - return p; - } - - /* Two level. Compute displacement to add after indirection. */ - - outer_disp = 0; - switch (word & 3) - { - case 2: - outer_disp = NEXTWORD (p); - break; - case 3: - outer_disp = NEXTLONG (p); - } - - fprintf (stream, "%d(", outer_disp); - print_base (basereg, base_disp, stream); - - /* If postindexed, print the closeparen before the index. */ - if (word & 4) - fprintf (stream, ")%s", buf); - /* If preindexed, print the closeparen after the index. */ - else - fprintf (stream, "%s)", buf); - - return p; -} - -/* Print a base register REGNO and displacement DISP, on STREAM. - REGNO = -1 for pc, -2 for none (suppressed). */ - -static void -print_base (regno, disp, stream) - int regno; - int disp; - FILE *stream; -{ - if (regno == -2) - fprintf (stream, "%d", disp); - else if (regno == -1) - fprintf (stream, "0x%x", disp); - else - fprintf (stream, "%d(%s)", disp, reg_names[regno]); -} - -/* This is not part of insn printing, but it is machine-specific, - so this is a convenient place to put it. - - Convert a 68881 extended float to a double. - FROM is the address of the extended float. - Store the double in *TO. */ - -convert_from_68881 (from, to) - char *from; - double *to; -{ -#ifdef USG_SGS_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.x (%a0),%fp0"); - asm ("fmove.d %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ -#if 0 - asm ("movl a6@@(8),a0"); - asm ("movl a6@@(12),a1"); - asm ("fmovex a0@@,fp0"); - asm ("fmoved fp0,a1@@"); -#else - /* Hand-assemble those insns since some assemblers lose - and some have different syntax. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2104800"); - asm (".long 0xf2117400"); -#endif -#endif /* not USG_SGS_ASM */ -} - -/* The converse: convert the double *FROM to an extended float - and store where TO points. */ - -convert_to_68881 (from, to) - double *from; - char *to; -{ -#ifdef USG_SGS_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.d (%a0),%fp0"); - asm ("fmove.x %fp0,(%a1)"); -#else /* not USG_SGS_ASM */ -#if 0 - asm ("movl a6@@(8),a0"); - asm ("movl a6@@(12),a1"); - asm ("fmoved a0@@,fp0"); - asm ("fmovex fp0,a1@@"); -#else - /* Hand-assemble those insns since some assemblers lose. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2105400"); - asm (".long 0xf2116800"); -#endif -#endif /* not USG_SGS_ASM */ -} -@ - - -1.1 -log -@Initial revision -@ -text -@d717 1 -a717 1 -#ifdef HPUX_ASM -d722 1 -a722 1 -#else /* not HPUX_ASM */ -d738 1 -a738 1 -#endif /* not HPUX_ASM */ -d748 1 -a748 1 -#ifdef HPUX_ASM -d753 1 -a753 1 -#else /* not HPUX_ASM */ -d768 1 -a768 1 -#endif /* not HPUX_ASM */ -@ diff --git a/gdb/RCS/main.c,v b/gdb/RCS/main.c,v deleted file mode 100644 index 1e6fafa..0000000 --- a/gdb/RCS/main.c,v +++ /dev/null @@ -1,1348 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.21.15.02; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.27.21.11.51; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Fix up "munch" so it generates a name that doesn't match its own -"grep" conventions. Change main so that it calls the new name, -and also doesn't use the conventions for functions that should NOT -be called by init.c. -@ -text -@/* Top level for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ -#include "defs.h" -#include "command.h" -#include "param.h" - -#ifdef USG -#include <sys/types.h> -#include <unistd.h> -#endif - -#include <sys/file.h> -#include <stdio.h> -#include <setjmp.h> -#include <signal.h> -#include <sys/param.h> - -#ifdef SET_STACK_LIMIT_HUGE -#include <sys/time.h> -#include <sys/resource.h> - -int original_stack_limit; -#endif - -/* Version number of GDB, as a string. */ - -extern char *version; - -/* - * Declare all cmd_list_element's - */ - -/* Chain containing all defined commands. */ - -struct cmd_list_element *cmdlist; - -/* Chain containing all defined info subcommands. */ - -struct cmd_list_element *infolist; - -/* Chain containing all defined enable subcommands. */ - -struct cmd_list_element *enablelist; - -/* Chain containing all defined disable subcommands. */ - -struct cmd_list_element *disablelist; - -/* Chain containing all defined delete subcommands. */ - -struct cmd_list_element *deletelist; - -/* Chain containing all defined "enable breakpoint" subcommands. */ - -struct cmd_list_element *enablebreaklist; - -/* Chain containing all defined set subcommands */ - -struct cmd_list_element *setlist; - -/* stdio stream that command input is being read from. */ - -FILE *instream; - -/* Current working directory. */ - -char *current_directory; - -/* The directory name is actually stored here (usually). */ -static char dirbuf[MAXPATHLEN]; - -/* Nonzero if we should refrain from using an X window. */ - -int inhibit_windows = 0; - -/* Function to call before reading a command, if nonzero. - The function receives two args: an input stream, - and a prompt string. */ - -void (*window_hook) (); - -extern int frame_file_full_name; - -void free_command_lines (); -char *gdb_read_line (); -static void init_main (); -static void init_cmd_lists (); -void command_loop (); -static void source_command (); -static void print_gdb_version (); - -/* gdb prints this when reading a command interactively */ -static char *prompt; - -/* Buffer used for reading command lines, and the size - allocated for it so far. */ - -char *line; -int linesize; - -/* This is how `error' returns to command level. */ - -jmp_buf to_top_level; - -void -return_to_top_level () -{ - quit_flag = 0; - immediate_quit = 0; - clear_breakpoint_commands (); - clear_momentary_breakpoints (); - delete_current_display (); - do_cleanups (0); - longjmp (to_top_level, 1); -} - -/* Call FUNC with arg ARG, catching any errors. - If there is no error, return the value returned by FUNC. - If there is an error, return zero after printing ERRSTRING - (which is in addition to the specific error message already printed). */ - -int -catch_errors (func, arg, errstring) - int (*func) (); - int arg; - char *errstring; -{ - jmp_buf saved; - int val; - struct cleanup *saved_cleanup_chain; - - saved_cleanup_chain = save_cleanups (); - - bcopy (to_top_level, saved, sizeof (jmp_buf)); - - if (setjmp (to_top_level) == 0) - val = (*func) (arg); - else - { - fprintf (stderr, "%s\n", errstring); - val = 0; - } - - restore_cleanups (saved_cleanup_chain); - - bcopy (saved, to_top_level, sizeof (jmp_buf)); - return val; -} - -/* Handler for SIGHUP. */ - -static void -disconnect () -{ - kill_inferior_fast (); - signal (SIGHUP, SIG_DFL); - kill (getpid (), SIGHUP); -} - -/* Clean up on error during a "source" command (or execution of a - user-defined command). - Close the file opened by the command - and restore the previous input stream. */ - -static void -source_cleanup (stream) - FILE *stream; -{ - /* Instream may be 0; set to it when executing user-defined command. */ - if (instream) - fclose (instream); - instream = stream; -} - - -int -main (argc, argv, envp) - int argc; - char **argv; - char **envp; -{ - extern void request_quit (); - int count; - int inhibit_gdbinit = 0; - int quiet = 0; - int batch = 0; - register int i; - - quit_flag = 0; - linesize = 100; - line = (char *) xmalloc (linesize); - instream = stdin; - - getwd (dirbuf); - current_directory = dirbuf; - -#ifdef SET_STACK_LIMIT_HUGE - { - struct rlimit rlim; - - /* Set the stack limit huge so that alloca (particularly stringtab - * in dbxread.c) does not fail. */ - getrlimit (RLIMIT_STACK, &rlim); - original_stack_limit = rlim.rlim_cur; - rlim.rlim_cur = rlim.rlim_max; - setrlimit (RLIMIT_STACK, &rlim); - } -#endif /* SET_STACK_LIMIT_HUGE */ - - /* Look for flag arguments. */ - - for (i = 1; i < argc; i++) - { - if (!strcmp (argv[i], "-q") || !strcmp (argv[i], "-quiet")) - quiet = 1; - else if (!strcmp (argv[i], "-nx")) - inhibit_gdbinit = 1; - else if (!strcmp (argv[i], "-nw")) - inhibit_windows = 1; - else if (!strcmp (argv[i], "-batch")) - batch = 1, quiet = 1; - else if (!strcmp (argv[i], "-fullname")) - frame_file_full_name = 1; - else if (argv[i][0] == '-') - i++; - } - - /* Run the init function of each source file */ - - init_cmd_lists (); /* This needs to be done first */ - init_all_files (); - init_main (); /* But that omits this file! Do it now */ - - signal (SIGINT, request_quit); - signal (SIGQUIT, SIG_IGN); - if (signal (SIGHUP, SIG_IGN) != SIG_IGN) - signal (SIGHUP, disconnect); - - if (!quiet) - print_gdb_version (); - - /* Process the command line arguments. */ - - count = 0; - for (i = 1; i < argc; i++) - { - register char *arg = argv[i]; - /* Args starting with - say what to do with the following arg - as a filename. */ - if (arg[0] == '-') - { - extern void exec_file_command (), symbol_file_command (); - extern void core_file_command (), directory_command (); - extern void tty_command (); - - if (!strcmp (arg, "-q") || !strcmp (arg, "-nx") - || !strcmp (arg, "-quiet") || !strcmp (arg, "-batch") - || !strcmp (arg, "-fullname")) - /* Already processed above */ - continue; - - if (++i == argc) - fprintf (stderr, "No argument follows \"%s\".\n", arg); - if (!setjmp (to_top_level)) - { - /* -s foo: get syms from foo. -e foo: execute foo. - -se foo: do both with foo. -c foo: use foo as core dump. */ - if (!strcmp (arg, "-se")) - { - exec_file_command (argv[i], !batch); - symbol_file_command (argv[i], !batch); - } - else if (!strcmp (arg, "-s") || !strcmp (arg, "-symbols")) - symbol_file_command (argv[i], !batch); - else if (!strcmp (arg, "-e") || !strcmp (arg, "-exec")) - exec_file_command (argv[i], !batch); - else if (!strcmp (arg, "-c") || !strcmp (arg, "-core")) - core_file_command (argv[i], !batch); - /* -x foo: execute commands from foo. */ - else if (!strcmp (arg, "-x") || !strcmp (arg, "-command") - || !strcmp (arg, "-commands")) - source_command (argv[i]); - /* -d foo: add directory `foo' to source-file directory - search-list */ - else if (!strcmp (arg, "-d") || !strcmp (arg, "-dir") - || !strcmp (arg, "-directory")) - directory_command (argv[i], 0); - /* -cd FOO: specify current directory as FOO. - GDB remembers the precise string FOO as the dirname. */ - else if (!strcmp (arg, "-cd")) - { - int len = strlen (argv[i]); - current_directory = argv[i]; - if (len > 1 && current_directory[len - 1] == '/') - current_directory = savestring (current_directory, len-1); - chdir (current_directory); - init_source_path (); - } - /* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */ - else if (!strcmp (arg, "-t") || !strcmp (arg, "-tty")) - tty_command (argv[i], 0); - else - error ("Unknown command-line switch: \"%s\"\n", arg); - } - } - else - { - /* Args not thus accounted for - are treated as, first, the symbol/executable file - and, second, the core dump file. */ - count++; - if (!setjmp (to_top_level)) - switch (count) - { - case 1: - exec_file_command (arg, !batch); - symbol_file_command (arg, !batch); - break; - - case 2: - core_file_command (arg, !batch); - break; - - case 3: - fprintf (stderr, "Excess command line args ignored. (%s%s)\n", - arg, (i == argc - 1) ? "" : " ..."); - } - } - } - - /* Read init file, if it exists in home directory */ - if (getenv ("HOME")) - { - char *s; - s = (char *) xmalloc (strlen (getenv ("HOME")) + 10); - strcpy (s, getenv ("HOME")); - strcat (s, "/.gdbinit"); - if (!inhibit_gdbinit && access (s, R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (s); - } - - /* Read init file, if it exists in current directory. */ - if (!inhibit_gdbinit && access (".gdbinit", R_OK) == 0) - if (!setjmp (to_top_level)) - source_command (".gdbinit"); - - if (batch) - fatal ("Attempt to read commands from stdin in batch mode."); - - if (!quiet) - printf ("Type \"help\" for a list of commands.\n"); - - /* The command loop. */ - - while (1) - { - if (!setjmp (to_top_level)) - command_loop (); - clearerr (stdin); /* Don't get hung if C-d is typed. */ - } -} - -/* Execute the line P as a command. - Pass FROM_TTY as second argument to the defining function. */ - -void -execute_command (p, from_tty) - char *p; - int from_tty; -{ - register struct cmd_list_element *c; - register struct command_line *cmdlines; - - free_all_values (); - while (*p == ' ' || *p == '\t') p++; - if (*p) - { - c = lookup_cmd (&p, cmdlist, "", 0); - if (c->function == 0) - error ("That is not a command, just a help topic."); - else if (c->class == (int) class_user) - { - struct cleanup *old_chain; - - if (*p) - error ("User-defined commands cannot take arguments."); - cmdlines = (struct command_line *) c->function; - if (cmdlines == (struct command_line *) 0) - /* Null command */ - return; - - /* Set the instream to 0, indicating execution of a - user-defined function. */ - old_chain = make_cleanup (source_cleanup, instream); - instream = (FILE *) 0; - while (cmdlines) - { - execute_command (cmdlines->line, 0); - cmdlines = cmdlines->next; - } - do_cleanups (old_chain); - } - else - /* Pass null arg rather than an empty one. */ - (*c->function) (*p ? p : 0, from_tty); - } -} - -static void -do_nothing () -{ -} - -/* Read commands from `instream' and execute them - until end of file. */ -void -command_loop () -{ - struct cleanup *old_chain; - while (!feof (instream)) - { - if (window_hook && instream == stdin) - (*window_hook) (instream, prompt); - - quit_flag = 0; - old_chain = make_cleanup (do_nothing, 0); - execute_command (gdb_read_line (instream == stdin ? prompt : 0, - instream == stdin), - instream == stdin); - /* Do any commands attached to breakpoint we stopped at. */ - do_breakpoint_commands (); - do_cleanups (old_chain); - } -} - -#ifdef SIGTSTP -static void -stop_sig () -{ - signal (SIGTSTP, SIG_DFL); - sigsetmask (0); - kill (getpid (), SIGTSTP); - signal (SIGTSTP, stop_sig); - printf ("%s", prompt); - fflush (stdout); - - /* Forget about any previous command -- null line now will do nothing. */ - *line = 0; -} -#endif /* SIGTSTP */ - -/* Commands call this if they do not want to be repeated by null lines. */ - -void -dont_repeat () -{ - *line = 0; -} - -/* Read one line from the command input stream `instream' - into the buffer `line' (whose current length is `linesize'). - The buffer is made bigger as necessary. - Returns the address of the start of the line. */ - -char * -gdb_read_line (prompt, repeat) - char *prompt; - int repeat; -{ - register char *p = line; - register char *p1; - register int c; - char *nline; - - /* Control-C quits instantly if typed while in this loop - since it should not wait until the user types a newline. */ - immediate_quit++; -#ifdef SIGTSTP - signal (SIGTSTP, stop_sig); -#endif - - if (prompt) - { - printf (prompt); - fflush (stdout); - } - - while (1) - { - c = fgetc (instream); - if (c == -1 || c == '\n') - break; - /* Ignore backslash-newline; keep adding to the same line. */ - else if (c == '\\') - { - int c1 = fgetc (instream); - if (c1 == '\n') - continue; - else - ungetc (c1, instream); - } - - if (p - line == linesize - 1) - { - linesize *= 2; - nline = (char *) xrealloc (line, linesize); - p += nline - line; - line = nline; - } - *p++ = c; - } - -#ifdef SIGTSTP - signal (SIGTSTP, SIG_DFL); -#endif - immediate_quit--; - - /* If we just got an empty line, and that is supposed - to repeat the previous command, leave the last input unchanged. */ - if (p == line && repeat) - return line; - - /* If line is a comment, clear it out. */ - p1 = line; - while ((c = *p1) == ' ' || c == '\t') p1++; - if (c == '#') - p = line; - - *p = 0; - - return line; -} - -/* Read lines from the input stream - and accumulate them in a chain of struct command_line's - which is then returned. */ - -struct command_line * -read_command_lines () -{ - struct command_line *first = 0; - register struct command_line *next, *tail = 0; - register char *p, *p1; - struct cleanup *old_chain = 0; - - while (1) - { - dont_repeat (); - p = gdb_read_line (0, 1); - /* Remove leading and trailing blanks. */ - while (*p == ' ' || *p == '\t') p++; - p1 = p + strlen (p); - while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t')) p1--; - - /* Is this "end"? */ - if (p1 - p == 3 && !strncmp (p, "end", 3)) - break; - - /* No => add this line to the chain of command lines. */ - next = (struct command_line *) xmalloc (sizeof (struct command_line)); - next->line = savestring (p, p1 - p); - next->next = 0; - if (tail) - { - tail->next = next; - } - else - { - /* We just read the first line. - From now on, arrange to throw away the lines we have - if we quit or get an error while inside this function. */ - first = next; - old_chain = make_cleanup (free_command_lines, &first); - } - tail = next; - } - - dont_repeat (); - - /* Now we are about to return the chain to our caller, - so freeing it becomes his responsibility. */ - if (first) - discard_cleanups (old_chain); - return first; -} - -/* Free a chain of struct command_line's. */ - -void -free_command_lines (lptr) - struct command_line **lptr; -{ - register struct command_line *l = *lptr; - register struct command_line *next; - - while (l) - { - next = l->next; - free (l->line); - free (l); - l = next; - } -} - -/* Add an element to the list of info subcommands. */ - -void -add_info (name, fun, doc) - char *name; - void (*fun) (); - char *doc; -{ - add_cmd (name, no_class, fun, doc, &infolist); -} - -/* Add an alias to the list of info subcommands. */ - -void -add_info_alias (name, oldname, abbrev_flag) - char *name; - char *oldname; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, 0, abbrev_flag, &infolist); -} - -/* The "info" command is defined as a prefix, with allow_unknown = 0. - Therefore, its own definition is called only for "info" with no args. */ - -static void -info_command () -{ - printf ("\"info\" must be followed by the name of an info command.\n"); - help_list (infolist, "info ", -1, stdout); -} - -/* Add an element to the list of commands. */ - -void -add_com (name, class, fun, doc) - char *name; - int class; - void (*fun) (); - char *doc; -{ - add_cmd (name, class, fun, doc, &cmdlist); -} - -/* Add an alias or abbreviation command to the list of commands. */ - -void -add_com_alias (name, oldname, class, abbrev_flag) - char *name; - char *oldname; - int class; - int abbrev_flag; -{ - add_alias_cmd (name, oldname, class, abbrev_flag, &cmdlist); -} - -void -error_no_arg (why) - char *why; -{ - error ("Argument required (%s).", why); -} - -static void -help_command (command, from_tty) - char *command; - int from_tty; /* Ignored */ -{ - help_cmd (command, stdout); -} - -static void -validate_comname (comname) - char *comname; -{ - register char *p; - - if (comname == 0) - error_no_arg ("name of command to define"); - - p = comname; - while (*p) - { - if (!(*p >= 'A' && *p <= 'Z') - && !(*p >= 'a' && *p <= 'z') - && !(*p >= '0' && *p <= '9') - && *p != '-') - error ("Junk in argument list: \"%s\"", p); - p++; - } -} - -static void -define_command (comname, from_tty) - char *comname; - int from_tty; -{ - register struct command_line *cmds; - register struct cmd_list_element *c; - char *tem = comname; - - validate_comname (comname); - - c = lookup_cmd (&tem, cmdlist, "", -1); - if (c) - { - if (c->class == (int) class_user || c->class == (int) class_alias) - tem = "Redefine command \"%s\"? "; - else - tem = "Really redefine built-in command \"%s\"? "; - if (!query (tem, comname)) - error ("Command \"%s\" not redefined.", comname); - } - - if (from_tty) - { - printf ("Type commands for definition of \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - fflush (stdout); - } - comname = savestring (comname, strlen (comname)); - - cmds = read_command_lines (); - - if (c && c->class == (int) class_user) - free_command_lines (&c->function); - - add_com (comname, class_user, cmds, - (c && c->class == (int) class_user) - ? c->doc : savestring ("User-defined.", 13)); -} - -static void -document_command (comname, from_tty) - char *comname; - int from_tty; -{ - struct command_line *doclines; - register struct cmd_list_element *c; - char *tem = comname; - - validate_comname (comname); - - c = lookup_cmd (&tem, cmdlist, "", 0); - - if (c->class != (int) class_user) - error ("Command \"%s\" is built-in.", comname); - - if (from_tty) - printf ("Type documentation for \"%s\".\n\ -End with a line saying just \"end\".\n", comname); - - doclines = read_command_lines (); - - if (c->doc) free (c->doc); - - { - register struct command_line *cl1; - register int len = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - len += strlen (cl1->line) + 1; - - c->doc = (char *) xmalloc (len + 1); - *c->doc = 0; - - for (cl1 = doclines; cl1; cl1 = cl1->next) - { - strcat (c->doc, cl1->line); - if (cl1->next) - strcat (c->doc, "\n"); - } - } - - free_command_lines (&doclines); -} - -static void -copying_info () -{ - immediate_quit++; - printf (" GDB GENERAL PUBLIC LICENSE\n\ - (Clarified 11 Feb 1988)\n\ -\n\ - Copyright (C) 1988 Richard M. Stallman\n\ - Everyone is permitted to copy and distribute verbatim copies\n\ - of this license, but changing it is not allowed.\n\ - You can also use this wording to make the terms for other programs.\n\ -\n\ - The license agreements of most software companies keep you at the\n\ -mercy of those companies. By contrast, our general public license is\n\ -intended to give everyone the right to share GDB. To make sure that\n\ -you get the rights we want you to have, we need to make restrictions\n\ -that forbid anyone to deny you these rights or to ask you to surrender\n\ -the rights. Hence this license agreement.\n\ -\n\ - Specifically, we want to make sure that you have the right to give\n\ -away copies of GDB, that you receive source code or else can get it\n\ -if you want it, that you can change GDB or use pieces of it in new\n\ -free programs, and that you know you can do these things.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - To make sure that everyone has such rights, we have to forbid you to\n\ -deprive anyone else of these rights. For example, if you distribute\n\ -copies of GDB, you must give the recipients all the rights that you\n\ -have. You must make sure that they, too, receive or can get the\n\ -source code. And you must tell them their rights.\n\ -\n\ - Also, for our own protection, we must make certain that everyone\n\ -finds out that there is no warranty for GDB. If GDB is modified by\n\ -someone else and passed on, we want its recipients to know that what\n\ -they have is not what we distributed, so that any problems introduced\n\ -by others will not reflect on our reputation.\n\ -\n\ - Therefore we (Richard Stallman and the Free Software Foundation,\n\ -Inc.) make the following terms which say what you must do to be\n\ -allowed to distribute or change GDB.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - COPYING POLICIES\n\ -\n\ - 1. You may copy and distribute verbatim copies of GDB source code as\n\ -you receive it, in any medium, provided that you conspicuously and\n\ -appropriately publish on each copy a valid copyright notice \"Copyright\n\ -\(C) 1988 Free Software Foundation, Inc.\" (or with whatever year is\n\ -appropriate); keep intact the notices on all files that refer\n\ -to this License Agreement and to the absence of any warranty; and give\n\ -any other recipients of the GDB program a copy of this License\n\ -Agreement along with the program. You may charge a distribution fee\n\ -for the physical act of transferring a copy.\n\ -\n\ - 2. You may modify your copy or copies of GDB or any portion of it,\n\ -and copy and distribute such modifications under the terms of\n\ -Paragraph 1 above, provided that you also do the following:\n\ -\n\ - a) cause the modified files to carry prominent notices stating\n\ - that you changed the files and the date of any change; and\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - b) cause the whole of any work that you distribute or publish,\n\ - that in whole or in part contains or is a derivative of GDB\n\ - or any part thereof, to be licensed to all third parties on terms\n\ - identical to those contained in this License Agreement (except that\n\ - you may choose to grant more extensive warranty protection to some\n\ - or all third parties, at your option).\n\ -\n"); - printf ("\ - c) if the modified program serves as a debugger, cause it\n\ - when started running in the simplest and usual way, to print\n\ - an announcement including a valid copyright notice\n\ - \"Copyright (C) 1988 Free Software Foundation, Inc.\" (or with\n\ - the year that is appropriate), saying that there is no warranty\n\ - (or else, saying that you provide a warranty) and that users may\n\ - redistribute the program under these conditions, and telling the user\n\ - how to view a copy of this License Agreement.\n\ -\n\ - d) You may charge a distribution fee for the physical act of\n\ - transferring a copy, and you may at your option offer warranty\n\ - protection in exchange for a fee.\n\ -\n\ -Mere aggregation of another unrelated program with this program (or its\n\ -derivative) on a volume of a storage or distribution medium does not bring\n\ -the other program under the scope of these terms.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 3. You may copy and distribute GDB (or a portion or derivative of it,\n\ -under Paragraph 2) in object code or executable form under the terms of\n\ -Paragraphs 1 and 2 above provided that you also do one of the following:\n\ -\n\ - a) accompany it with the complete corresponding machine-readable\n\ - source code, which must be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\ -\n\ - b) accompany it with a written offer, valid for at least three\n\ - years, to give any third party free (except for a nominal\n\ - shipping charge) a complete machine-readable copy of the\n\ - corresponding source code, to be distributed under the terms of\n\ - Paragraphs 1 and 2 above; or,\n\n"); - - printf ("\ - c) accompany it with the information you received as to where the\n\ - corresponding source code may be obtained. (This alternative is\n\ - allowed only for noncommercial distribution and only if you\n\ - received the program in object code or executable form alone.)\n\ -\n\ -For an executable file, complete source code means all the source code for\n\ -all modules it contains; but, as a special exception, it need not include\n\ -source code for modules which are standard libraries that accompany the\n\ -operating system on which the executable file runs.\n\ ---Type Return to print more--"); - fflush (stdout); - gdb_read_line (0, 0); - - printf ("\ - 4. You may not copy, sublicense, distribute or transfer GDB\n\ -except as expressly provided under this License Agreement. Any attempt\n\ -otherwise to copy, sublicense, distribute or transfer GDB is void and\n\ -your rights to use the program under this License agreement shall be\n\ -automatically terminated. However, parties who have received computer\n\ -software programs from you with this License Agreement will not have\n\ -their licenses terminated so long as such parties remain in full compliance.\n\ -\n\ -"); - printf ("\ - 5. If you wish to incorporate parts of GDB into other free\n\ -programs whose distribution conditions are different, write to the Free\n\ -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet\n\ -worked out a simple rule that can be stated here, but we will often permit\n\ -this. We will be guided by the two goals of preserving the free status of\n\ -all derivatives of our free software and of promoting the sharing and reuse\n\ -of software.\n\ -\n\ -In other words, go ahead and share GDB, but don't try to stop\n\ -anyone else from sharing it farther. Help stamp out software hoarding!\n\ -"); - immediate_quit--; -} - -static void -warranty_info () -{ - immediate_quit++; - printf (" NO WARRANTY\n\ -\n\ - BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO\n\ -WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT\n\ -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,\n\ -RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB \"AS IS\" WITHOUT\n\ -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\n\ -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\ -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND\n\ -PERFORMANCE OF GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU\n\ -ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n"); - - printf ("\ - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.\n\ -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY\n\ -WHO MAY MODIFY AND REDISTRIBUTE GDB, BE LIABLE TO\n\ -YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER\n\ -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR\n\ -INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA\n\ -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A\n\ -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN\n\ -IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR\n\ -ANY CLAIM BY ANY OTHER PARTY.\n"); - immediate_quit--; -} - -static void -print_gdb_version () -{ - printf ("GDB %s, Copyright (C) 1988 Free Software Foundation, Inc.\n\ -There is ABSOLUTELY NO WARRANTY for GDB; type \"info warranty\" for details.\n\ -GDB is free software and you are welcome to distribute copies of it\n\ - under certain conditions; type \"info copying\" to see the conditions.\n", - version); -} - -static void -version_info () -{ - immediate_quit++; - print_gdb_version (); - immediate_quit--; -} - -/* xgdb calls this to reprint the usual GDB prompt. */ - -void -print_prompt () -{ - printf ("%s", prompt); - fflush (stdout); -} - -/* Command to specify a prompt string instead of "(gdb) ". */ - -static void -set_prompt_command (text) - char *text; -{ - char *p, *q; - register int c; - char *new; - - if (text == 0) - error_no_arg ("string to which to set prompt"); - - new = (char *) xmalloc (strlen (text) + 2); - p = text; q = new; - while (c = *p++) - { - if (c == '\\') - { - /* \ at end of argument is used after spaces - so they won't be lost. */ - if (*p == 0) - break; - c = parse_escape (&p); - if (c == 0) - break; /* C loses */ - else if (c > 0) - *q++ = c; - } - else - *q++ = c; - } - if (*(p - 1) != '\\') - *q++ = ' '; - *q++ = '\0'; - new = (char *) xrealloc (new, q - new); - free (prompt); - prompt = new; -} - -static void -quit_command () -{ - if (have_inferior_p ()) - { - if (query ("The program is running. Quit anyway? ")) - { - /* Prevent any warning message from reopen_exec_file, in case - we have a core file that's inconsistent with the exec file. */ - exec_file_command (0, 0); - kill_inferior (); - } - else - error ("Not confirmed."); - } - exit (0); -} - -int -input_from_terminal_p () -{ - return instream == stdin; -} - -static void -pwd_command (arg, from_tty) - char *arg; - int from_tty; -{ - if (arg) error ("The \"pwd\" command does not take an argument: %s", arg); - getwd (dirbuf); - - if (strcmp (dirbuf, current_directory)) - printf ("Working directory %s\n (canonically %s).\n", - current_directory, dirbuf); - else - printf ("Working directory %s.\n", current_directory); -} - -static void -cd_command (dir, from_tty) - char *dir; - int from_tty; -{ - int len; - int change; - - if (dir == 0) - error_no_arg ("new working directory"); - - len = strlen (dir); - dir = savestring (dir, len - (len > 1 && dir[len-1] == '/')); - if (dir[0] == '/') - current_directory = dir; - else - { - current_directory = concat (current_directory, "/", dir); - free (dir); - } - - /* Now simplify any occurrences of `.' and `..' in the pathname. */ - - change = 1; - while (change) - { - char *p; - change = 0; - - for (p = current_directory; *p;) - { - if (!strncmp (p, "/./", 2) - && (p[2] == 0 || p[2] == '/')) - strcpy (p, p + 2); - else if (!strncmp (p, "/..", 3) - && (p[3] == 0 || p[3] == '/') - && p != current_directory) - { - char *q = p; - while (q != current_directory && q[-1] != '/') q--; - if (q != current_directory) - { - strcpy (q-1, p+3); - p = q-1; - } - } - else p++; - } - } - - if (chdir (dir) < 0) - perror_with_name (dir); - - if (from_tty) - pwd_command ((char *) 0, 1); -} - -static void -source_command (file) - char *file; -{ - FILE *stream; - struct cleanup *cleanups; - - if (file == 0) - error_no_arg ("file to read commands from"); - - stream = fopen (file, "r"); - if (stream == 0) - perror_with_name (file); - - cleanups = make_cleanup (source_cleanup, instream); - - instream = stream; - - command_loop (); - - do_cleanups (cleanups); -} - -static void -echo_command (text) - char *text; -{ - char *p = text; - register int c; - - if (text) - while (c = *p++) - { - if (c == '\\') - { - /* \ at end of argument is used after spaces - so they won't be lost. */ - if (*p == 0) - return; - - c = parse_escape (&p); - if (c >= 0) - fputc (c, stdout); - } - else - fputc (c, stdout); - } -} - -static void -dump_me_command () -{ - if (query ("Should GDB dump core? ")) - { - signal (SIGQUIT, SIG_DFL); - kill (getpid (), SIGQUIT); - } -} - -static void -init_cmd_lists () -{ - cmdlist = (struct cmd_list_element *) 0; - infolist = (struct cmd_list_element *) 0; - enablelist = (struct cmd_list_element *) 0; - disablelist = (struct cmd_list_element *) 0; - deletelist = (struct cmd_list_element *) 0; - enablebreaklist = (struct cmd_list_element *) 0; - setlist = (struct cmd_list_element *) 0; -} - -static void -init_main () -{ - prompt = savestring ("(gdb) ", 6); - - /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ - - add_cmd ("obscure", class_obscure, 0, "Obscure features.", &cmdlist); - add_cmd ("alias", class_alias, 0, "Aliases of other commands.", &cmdlist); - add_cmd ("user", class_user, 0, "User-defined commands.\n\ -The commands in this class are those defined by the user.\n\ -Use the \"define\" command to define a command.", &cmdlist); - add_cmd ("support", class_support, 0, "Support facilities.", &cmdlist); - add_cmd ("status", class_info, 0, "Status inquiries.", &cmdlist); - add_cmd ("files", class_files, 0, "Specifying and examining files.", &cmdlist); - add_cmd ("breakpoints", class_breakpoint, 0, "Making program stop at certain points.", &cmdlist); - add_cmd ("data", class_vars, 0, "Examining data.", &cmdlist); - add_cmd ("stack", class_stack, 0, "Examining the stack.\n\ -The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\ -counting from zero for the innermost (currently executing) frame.\n\n\ -At any time gdb identifies one frame as the \"selected\" frame.\n\ -Variable lookups are done with respect to the selected frame.\n\ -When the program being debugged stops, gdb selects the innermost frame.\n\ -The commands below can be used to select other frames by number or address.", - &cmdlist); - add_cmd ("running", class_run, 0, "Running the program.", &cmdlist); - - add_com ("pwd", class_files, pwd_command, - "Print working directory. This is used for your program as well."); - add_com ("cd", class_files, cd_command, - "Set working directory to DIR for debugger and program being debugged.\n\ -The change does not take effect for the program being debugged\n\ -until the next time it is started."); - - add_cmd ("prompt", class_support, set_prompt_command, - "Change gdb's prompt from the default of \"(gdb)\"", - &setlist); - add_com ("echo", class_support, echo_command, - "Print a constant string. Give string as argument.\n\ -C escape sequences may be used in the argument.\n\ -No newline is added at the end of the argument;\n\ -use \"\\n\" if you want a newline to be printed.\n\ -Since leading and trailing whitespace are ignored in command arguments,\n\ -if you want to print some you must use \"\\\" before leading whitespace\n\ -to be printed or after trailing whitespace."); - add_com ("document", class_support, document_command, - "Document a user-defined command.\n\ -Give command name as argument. Give documentation on following lines.\n\ -End with a line of just \"end\"."); - add_com ("define", class_support, define_command, - "Define a new command name. Command name is argument.\n\ -Definition appears on following lines, one command per line.\n\ -End with a line of just \"end\".\n\ -Use the \"document\" command to give documentation for the new command.\n\ -Commands defined in this way do not take arguments."); - - add_com ("source", class_support, source_command, - "Read commands from a file named FILE.\n\ -Note that the file \".gdbinit\" is read automatically in this way\n\ -when gdb is started."); - add_com ("quit", class_support, quit_command, "Exit gdb."); - add_com ("help", class_support, help_command, "Print list of commands."); - add_com_alias ("q", "quit", class_support, 1); - add_com_alias ("h", "help", class_support, 1); - - add_com ("dump-me", class_obscure, dump_me_command, - "Get fatal error; make debugger dump its core."); - - add_prefix_cmd ("info", class_info, info_command, - "Generic command for printing status.", - &infolist, "info ", 0, &cmdlist); - add_com_alias ("i", "info", class_info, 1); - - add_info ("copying", copying_info, "Conditions for redistributing copies of GDB."); - add_info ("warranty", warranty_info, "Various kinds of warranty you do not have."); - add_info ("version", version_info, "Report what version of GDB this is."); -} -@ - - -1.1 -log -@Initial revision -@ -text -@d103 2 -a104 2 -static void initialize_main (); -static void initialize_cmd_lists (); -d247 3 -a249 3 - initialize_cmd_lists (); /* This needs to be done first */ - initialize_all_files (); - initialize_main (); /* But that omits this file! Do it now */ -d1206 1 -a1206 1 -initialize_cmd_lists () -d1218 1 -a1218 1 -initialize_main () -@ diff --git a/gdb/RCS/munch,v b/gdb/RCS/munch,v deleted file mode 100755 index bac6946..0000000 --- a/gdb/RCS/munch,v +++ /dev/null @@ -1,75 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.3 -date 89.03.27.21.15.45; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.03.27.20.18.28; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.58.17; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix up "munch" so it generates a name that doesn't match its own -"grep" conventions. Change main so that it calls the new name, -and also doesn't use the conventions for functions that should NOT -be called by init.c. -@ -text -@#! /bin/sh - -# create an initialization procedure from a list of .o files -# Look in object files, find symbols including the string _initialize_, -# and call each one as a function. - -echo '/* Do not modify this file. It is created automatically by "munch". */' -echo 'void init_all_files () {' - -nm $* | egrep '_initialize_' | \ - sed -e 's/^.*\(initialize_[a-zA-Z_0-9]*\).*$/ _\1 ();/' | \ - sort -u - -echo '}' -@ - - -1.2 -log -@Generic change: make it not care much about the output format of "nm". -Now as long as _initialize_foo is not touching any other -symbol or alphanumeric, we'll find it and use it. -@ -text -@d8 1 -a8 1 -echo 'void initialize_all_files () {' -@ - - -1.1 -log -@Initial revision -@ -text -@d4 2 -d10 3 -a12 1 -nm -p $* | egrep 'T *__?initialize_' | sed -e 's/^.*T *_*\(.*\)/ _\1 ();/' -@ diff --git a/gdb/RCS/printcmd.c,v b/gdb/RCS/printcmd.c,v deleted file mode 100644 index 2ab3acc..0000000 --- a/gdb/RCS/printcmd.c,v +++ /dev/null @@ -1,1707 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.00.54.22; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.49; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@(1) Depend on XXX_BIG_ENDIAN rather than testing gdb's object code. -(2) Print to the STREAM parameter, not to stdout. -(3) Use is_nan with new arguments. -(4) Use unpack_double with new args, and deal with invalid results. -(5) Don't print history numbers in the "print" command for things -that weren't recorded in history (because they were invalid values). -@ -text -@/* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "symtab.h" -#include "value.h" -#include "expression.h" - -struct format_data -{ - int count; - char format; - char size; -}; - -/* Last specified output format. */ - -static char last_format = 'x'; - -/* Last specified examination size. 'b', 'h', 'w' or `q'. */ - -static char last_size = 'w'; - -/* Default address to examine next. */ - -static CORE_ADDR next_address; - -/* Last address examined. */ - -static CORE_ADDR last_examine_address; - -/* Contents of last address examined. - This is not valid past the end of the `x' command! */ - -static value last_examine_value; - -/* Number of auto-display expression currently being displayed. - So that we can deleted it if we get an error or a signal within it. - -1 when not doing one. */ - -int current_display_number; - -static void do_one_display (); - -void do_displays (); -void print_address (); -void print_scalar_formatted (); - - -/* Decode a format specification. *STRING_PTR should point to it. - OFORMAT and OSIZE are used as defaults for the format and size - if none are given in the format specification. - The structure returned describes all the data - found in the specification. In addition, *STRING_PTR is advanced - past the specification and past all whitespace following it. */ - -struct format_data -decode_format (string_ptr, oformat, osize) - char **string_ptr; - char oformat; - char osize; -{ - struct format_data val; - register char *p = *string_ptr; - - val.format = oformat; - val.size = osize; - val.count = 1; - - if (*p >= '0' && *p <= '9') - val.count = atoi (p); - while (*p >= '0' && *p <= '9') p++; - - /* Now process size or format letters that follow. */ - - while (1) - { - if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g') - val.size = *p++; -#ifdef LONG_LONG - else if (*p == 'l') - { - val.size = 'g'; - p++; - } -#endif - else if (*p >= 'a' && *p <= 'z') - val.format = *p++; - else - break; - } - -#ifndef LONG_LONG - /* Make sure 'g' size is not used on integer types. - Well, actually, we can handle hex. */ - if (val.size == 'g' && val.format != 'f' && val.format != 'x') - val.size = 'w'; -#endif - - while (*p == ' ' || *p == '\t') p++; - *string_ptr = p; - - return val; -} - -/* Print value VAL on stdout according to FORMAT, a letter or 0. - Do not end with a newline. - 0 means print VAL according to its own type. - SIZE is the letter for the size of datum being printed. - This is used to pad hex numbers so they line up. */ - -static void -print_formatted (val, format, size) - register value val; - register char format; - char size; -{ - int len = TYPE_LENGTH (VALUE_TYPE (val)); - - if (VALUE_LVAL (val) == lval_memory) - next_address = VALUE_ADDRESS (val) + len; - - switch (format) - { - case 's': - next_address = VALUE_ADDRESS (val) - + value_print (value_addr (val), stdout, 0); - break; - - case 'i': - next_address = VALUE_ADDRESS (val) - + print_insn (VALUE_ADDRESS (val), stdout); - break; - - default: - if (format == 0 - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION - || VALUE_REPEATED (val)) - value_print (val, stdout, format); - else - print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val), - format, size, stdout); - } -} - -/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, - according to letters FORMAT and SIZE on STREAM. - FORMAT may not be zero. Formats s and i are not supported at this level. - - This is how the elements of an array or structure are printed - with a format. */ - -void -print_scalar_formatted (valaddr, type, format, size, stream) - char *valaddr; - struct type *type; - char format; - int size; - FILE *stream; -{ - LONGEST val_long; - int len = TYPE_LENGTH (type); - - if (size == 'g' && sizeof (LONGEST) < 8 - && format == 'x') - { - /* ok, we're going to have to get fancy here. Assumption: a - long is four bytes. */ - unsigned long v1, v2, tmp; - - v1 = unpack_long (builtin_type_long, valaddr); - v2 = unpack_long (builtin_type_long, valaddr + 4); - -#ifdef BYTES_BIG_ENDIAN -#else - /* Little endian -- swap the two for printing */ - tmp = v1; - v1 = v2; - v2 = tmp; -#endif - - switch (format) - { - case 'x': - fprintf (stream, "0x%08x%08x", v1, v2); - break; - default: - error ("Output size \"g\" unimplemented for format \"%c\".", - format); - } - return; - } - - val_long = unpack_long (type, valaddr); - - /* If value is unsigned, truncate it in case negative. */ - if (format != 'd') - { - if (len == sizeof (char)) - val_long &= (1 << 8 * sizeof(char)) - 1; - else if (len == sizeof (short)) - val_long &= (1 << 8 * sizeof(short)) - 1; - else if (len == sizeof (long)) - val_long &= (unsigned long) - 1; - } - - switch (format) - { - case 'x': -#ifdef LONG_LONG - if (!size) - size = (len < sizeof (long long) ? 'w' : 'g'); - switch (size) - { - case 'b': - fprintf (stream, "0x%02llx", val_long); - break; - case 'h': - fprintf (stream, "0x%04llx", val_long); - break; - case 0: /* no size specified, like in print */ - case 'w': - fprintf (stream, "0x%08llx", val_long); - break; - case 'g': - fprintf (stream, "0x%16llx", val_long); - break; - default: - error ("Undefined output size \"%c\".", size); - } -#else - switch (size) - { - case 'b': - fprintf (stream, "0x%02x", val_long); - break; - case 'h': - fprintf (stream, "0x%04x", val_long); - break; - case 0: /* no size specified, like in print */ - case 'w': - fprintf (stream, "0x%08x", val_long); - break; - case 'g': - fprintf (stream, "0x%16x", val_long); - break; - default: - error ("Undefined output size \"%c\".", size); - } -#endif /* not LONG_LONG */ - break; - - case 'd': -#ifdef LONG_LONG - fprintf (stream, "%lld", val_long); -#else - fprintf (stream, "%d", val_long); -#endif - break; - - case 'u': -#ifdef LONG_LONG - fprintf (stream, "%llu", val_long); -#else - fprintf (stream, "%u", val_long); -#endif - break; - - case 'o': - if (val_long) -#ifdef LONG_LONG - fprintf (stream, "0%llo", val_long); -#else - fprintf (stream, "0%o", val_long); -#endif - else - fprintf (stream, "0"); - break; - - case 'a': - print_address ((CORE_ADDR) val_long, stream); - break; - - case 'c': - value_print (value_from_long (builtin_type_char, val_long), stream, 0); - break; - - case 'f': - if (len == sizeof (float)) - type = builtin_type_float; - else if (len == sizeof (double)) - type = builtin_type_double; - else abort(); - -#ifdef IEEE_FLOAT - if (is_nan (valaddr, len)) - { - fprintf (stream, "NaN"); - break; - } -#endif - { - double doub; - int inv; - - doub = unpack_double (type, valaddr, &inv); - if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, len > 4? "%.16g": "%.6g", doub); - } - break; - - case 0: - abort (); - - default: - error ("Undefined output format \"%c\".", format); - } -} - -/* Specify default address for `x' command. - `info lines' uses this. */ - -void -set_next_address (addr) - CORE_ADDR addr; -{ - next_address = addr; - - /* Make address available to the user as $_. */ - set_internalvar (lookup_internalvar ("_"), - value_from_long (builtin_type_int, (LONGEST) addr)); -} - -/* Print address ADDR symbolically on STREAM. - First print it as a number. Then perhaps print - <SYMBOL + OFFSET> after the number. */ - -void -print_address (addr, stream) - CORE_ADDR addr; - FILE *stream; -{ - register int i; - struct symbol *fs; - char *name; - int name_location; - - fprintf (stream, "0x%x", addr); - - fs = find_pc_function (addr); - - if (!fs) - { - i = find_pc_misc_function (addr); - - if (i < 0) return; /* If nothing comes through, don't - print anything symbolic */ - - name = misc_function_vector[i].name; - name_location = misc_function_vector[i].address; - } - else - { - name = fs->name; - name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (fs)); - } - - if (addr - name_location) - fprintf (stream, " <%s+%d>", - name, - addr - name_location); - else - fprintf (stream, " <%s>", name); -} - -/* Examine data at address ADDR in format FMT. - Fetch it from memory and print on stdout. */ - -static void -do_examine (fmt, addr) - struct format_data fmt; - CORE_ADDR addr; -{ - register char format = 0; - register char size; - register int count = 1; - struct type *val_type; - register int i; - register int maxelts; - - format = fmt.format; - size = fmt.size; - count = fmt.count; - next_address = addr; - - /* String or instruction format implies fetch single bytes - regardless of the specified size. */ - if (format == 's' || format == 'i') - size = 'b'; - - if (size == 'b') - val_type = builtin_type_char; - else if (size == 'h') - val_type = builtin_type_short; - else if (size == 'w') - val_type = builtin_type_long; - else if (size == 'g') -#ifndef LONG_LONG - val_type = builtin_type_double; -#else - val_type = builtin_type_long_long; -#endif - - maxelts = 8; - if (size == 'w') - maxelts = 4; - if (size == 'g') - maxelts = 2; - if (format == 's' || format == 'i') - maxelts = 1; - - /* Print as many objects as specified in COUNT, at most maxelts per line, - with the address of the next one at the start of each line. */ - - while (count > 0) - { - print_address (next_address, stdout); - fputc (':', stdout); - for (i = maxelts; - i > 0 && count > 0; - i--, count--) - { - fputc ('\t', stdout); - /* Note that print_formatted sets next_address for the next - object. */ - last_examine_address = next_address; - last_examine_value = value_at (val_type, next_address); - print_formatted (last_examine_value, format, size); - } - fputc ('\n', stdout); - fflush (stdout); - } -} - -static void -validate_format (fmt, cmdname) - struct format_data fmt; - char *cmdname; -{ - if (fmt.size != 0) - error ("Size letters are meaningless in \"%s\" command.", cmdname); - if (fmt.count != 1) - error ("Item count other than 1 is meaningless in \"%s\" command.", - cmdname); - if (fmt.format == 'i' || fmt.format == 's') - error ("Format letter \"%c\" is meaningless in \"%s\" command.", - fmt.format, cmdname); -} - -static void -print_command (exp) - char *exp; -{ - struct expression *expr; - register struct cleanup *old_chain = 0; - register char format = 0; - register value val; - struct format_data fmt; - int histindex; - int cleanup = 0; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, last_format, 0); - validate_format (fmt, "print"); - last_format = format = fmt.format; - } - - if (exp && *exp) - { - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - cleanup = 1; - val = evaluate_expression (expr); - } - else - val = access_value_history (0); - - histindex = record_latest_value (val); - if (histindex >= 0) printf ("$%d = ", histindex); - - print_formatted (val, format, fmt.size); - printf ("\n"); - - if (cleanup) - do_cleanups (old_chain); -} - -static void -output_command (exp) - char *exp; -{ - struct expression *expr; - register struct cleanup *old_chain; - register char format = 0; - register value val; - struct format_data fmt; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, 0, 0); - validate_format (fmt, "print"); - format = fmt.format; - } - - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - - val = evaluate_expression (expr); - - print_formatted (val, format, fmt.size); - - do_cleanups (old_chain); -} - -static void -set_command (exp) - char *exp; -{ - struct expression *expr = parse_c_expression (exp); - register struct cleanup *old_chain - = make_cleanup (free_current_contents, &expr); - evaluate_expression (expr); - do_cleanups (old_chain); -} - -static void -address_info (exp) - char *exp; -{ - register struct symbol *sym; - register CORE_ADDR val; - int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero - if exp is a field of `this'. */ - - if (exp == 0) - error ("Argument required."); - - sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE, - &is_a_field_of_this); - if (sym == 0) - { - register int i; - - if (is_a_field_of_this) - { - printf("Symbol \"%s\" is a field of the local class variable `this'\n", exp); - return; - } - - for (i = 0; i < misc_function_count; i++) - if (!strcmp (misc_function_vector[i].name, exp)) - break; - - if (i < misc_function_count) - printf ("Symbol \"%s\" is at 0x%x in a file compiled without -g.\n", - exp, misc_function_vector[i].address); - else - error ("No symbol \"%s\" in current context.", exp); - return; - } - - printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym)); - val = SYMBOL_VALUE (sym); - - switch (SYMBOL_CLASS (sym)) - { - case LOC_CONST: - case LOC_CONST_BYTES: - printf ("constant"); - break; - - case LOC_LABEL: - printf ("a label at address 0x%x", val); - break; - - case LOC_REGISTER: - printf ("a variable in register %s", reg_names[val]); - break; - - case LOC_STATIC: - printf ("static at address 0x%x", val); - break; - - case LOC_REGPARM: - printf ("an argument in register %s", reg_names[val]); - break; - - case LOC_ARG: - printf ("an argument at offset %d", val); - break; - - case LOC_LOCAL: - printf ("a local variable at frame offset %d", val); - break; - - case LOC_TYPEDEF: - printf ("a typedef"); - break; - - case LOC_BLOCK: - printf ("a function at address 0x%x", - BLOCK_START (SYMBOL_BLOCK_VALUE (sym))); - break; - } - printf (".\n"); -} - -static void -x_command (exp, from_tty) - char *exp; - int from_tty; -{ - struct expression *expr; - struct format_data fmt; - struct cleanup *old_chain; - - fmt.format = last_format; - fmt.size = last_size; - fmt.count = 1; - - if (exp && *exp == '/') - { - exp++; - fmt = decode_format (&exp, last_format, last_size); - last_size = fmt.size; - last_format = fmt.format; - } - - /* If we have an expression, evaluate it and use it as the address. */ - - if (exp != 0 && *exp != 0) - { - expr = parse_c_expression (exp); - /* Cause expression not to be there any more - if this command is repeated with Newline. - But don't clobber a user-defined command's definition. */ - if (from_tty) - *exp = 0; - old_chain = make_cleanup (free_current_contents, &expr); - next_address = (CORE_ADDR) value_as_long (evaluate_expression (expr)); - do_cleanups (old_chain); - } - - do_examine (fmt, next_address); - - /* Set a couple of internal variables if appropriate. */ - if (last_examine_value) - { - /* Make last address examined available to the user as $_. */ - set_internalvar (lookup_internalvar ("_"), - value_from_long (builtin_type_int, - (LONGEST) last_examine_address)); - - /* Make contents of last address examined available to the user as $__.*/ - set_internalvar (lookup_internalvar ("__"), last_examine_value); - } -} - -/* Commands for printing types of things. */ - -static void -whatis_command (exp) - char *exp; -{ - struct expression *expr; - register value val; - register struct cleanup *old_chain; - - if (exp) - { - expr = parse_c_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - val = evaluate_type (expr); - } - else - val = access_value_history (0); - - printf ("type = "); - type_print (VALUE_TYPE (val), "", stdout, 1); - printf ("\n"); - - if (exp) - do_cleanups (old_chain); -} - -static void -ptype_command (typename) - char *typename; -{ - register char *p = typename; - register int len; - extern struct block *get_current_block (); - register struct block *b - = (have_inferior_p () || have_core_file_p ()) ? get_current_block () : 0; - register struct type *type; - - if (typename == 0) - error_no_arg ("type name"); - - while (*p && *p != ' ' && *p != '\t') p++; - len = p - typename; - while (*p == ' ' || *p == '\t') p++; - - if (len == 6 && !strncmp (typename, "struct", 6)) - type = lookup_struct (p, b); - else if (len == 5 && !strncmp (typename, "union", 5)) - type = lookup_union (p, b); - else if (len == 4 && !strncmp (typename, "enum", 4)) - type = lookup_enum (p, b); - else - { - type = lookup_typename (typename, b, 1); - if (type == 0) - { - register struct symbol *sym - = lookup_symbol (typename, b, STRUCT_NAMESPACE, 0); - if (sym == 0) - error ("No type named %s.", typename); - printf ("No type named %s, but there is a ", - typename); - switch (TYPE_CODE (SYMBOL_TYPE (sym))) - { - case TYPE_CODE_STRUCT: - printf ("struct"); - break; - - case TYPE_CODE_UNION: - printf ("union"); - break; - - case TYPE_CODE_ENUM: - printf ("enum"); - } - printf (" %s. Type \"help ptype\".\n", typename); - type = SYMBOL_TYPE (sym); - } - } - - type_print (type, "", stdout, 1); - printf ("\n"); -} - -enum display_status {disabled, enabled}; - -struct display -{ - /* Chain link to next auto-display item. */ - struct display *next; - /* Expression to be evaluated and displayed. */ - struct expression *exp; - /* Item number of this auto-display item. */ - int number; - /* Display format specified. */ - struct format_data format; - /* Innermost block required by this expression when evaluated */ - struct block *block; - /* Status of this display (enabled or disabled) */ - enum display_status status; -}; - -/* Chain of expressions whose values should be displayed - automatically each time the program stops. */ - -static struct display *display_chain; - -static int display_number; - -/* Add an expression to the auto-display chain. - Specify the expression. */ - -static void -display_command (exp, from_tty) - char *exp; - int from_tty; -{ - struct format_data fmt; - register struct expression *expr; - register struct display *new; - extern struct block *innermost_block; - - if (exp == 0) - { - do_displays (); - return; - } - - if (*exp == '/') - { - exp++; - fmt = decode_format (&exp, 0, 0); - if (fmt.size && fmt.format == 0) - fmt.format = 'x'; - if (fmt.format == 'i' || fmt.format == 's') - fmt.size = 'b'; - } - else - { - fmt.format = 0; - fmt.size = 0; - fmt.count = 0; - } - - innermost_block = 0; - expr = parse_c_expression (exp); - - new = (struct display *) xmalloc (sizeof (struct display)); - - new->exp = expr; - new->block = innermost_block; - new->next = display_chain; - new->number = ++display_number; - new->format = fmt; - new->status = enabled; - display_chain = new; - - if (from_tty && have_inferior_p ()) - do_one_display (new); - - dont_repeat (); -} - -static void -free_display (d) - struct display *d; -{ - free (d->exp); - free (d); -} - -/* Clear out the display_chain. - Done when new symtabs are loaded, since this invalidates - the types stored in many expressions. */ - -void -clear_displays () -{ - register struct display *d; - - while (d = display_chain) - { - free (d->exp); - display_chain = d->next; - free (d); - } -} - -/* Delete the auto-display number NUM. */ - -void -delete_display (num) - int num; -{ - register struct display *d1, *d; - - if (!display_chain) - error ("No display number %d.", num); - - if (display_chain->number == num) - { - d1 = display_chain; - display_chain = d1->next; - free_display (d1); - } - else - for (d = display_chain; ; d = d->next) - { - if (d->next == 0) - error ("No display number %d.", num); - if (d->next->number == num) - { - d1 = d->next; - d->next = d1->next; - free_display (d1); - break; - } - } -} - -/* Delete some values from the auto-display chain. - Specify the element numbers. */ - -static void -undisplay_command (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d, *d1; - - if (args == 0) - { - if (query ("Delete all auto-display expressions? ")) - clear_displays (); - dont_repeat (); - return; - } - - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - delete_display (num); - - p = p1; - while (*p == ' ' || *p == '\t') p++; - } - dont_repeat (); -} - -/* Display a single auto-display. - Do nothing if the display cannot be printed in the current context, - or if the display is disabled. */ - -static void -do_one_display (d) - struct display *d; -{ - int within_current_scope; - - if (d->status == disabled) - return; - - if (d->block) - within_current_scope = contained_in (get_selected_block (), d->block); - else - within_current_scope = 1; - if (!within_current_scope) - return; - - current_display_number = d->number; - - printf ("%d: ", d->number); - if (d->format.size) - { - printf ("x/"); - if (d->format.count != 1) - printf ("%d", d->format.count); - printf ("%c", d->format.format); - if (d->format.format != 'i' && d->format.format != 's') - printf ("%c", d->format.size); - printf (" "); - print_expression (d->exp, stdout); - if (d->format.count != 1) - printf ("\n"); - else - printf (" "); - do_examine (d->format, - (CORE_ADDR) value_as_long (evaluate_expression (d->exp))); - - } - else - { - if (d->format.format) - printf ("/%c ", d->format.format); - print_expression (d->exp, stdout); - printf (" = "); - print_formatted (evaluate_expression (d->exp), - d->format.format, d->format.size); - printf ("\n"); - } - - fflush (stdout); - current_display_number = -1; -} - -/* Display all of the values on the auto-display chain which can be - evaluated in the current scope. */ - -void -do_displays () -{ - register struct display *d; - - for (d = display_chain; d; d = d->next) - do_one_display (d); -} - -/* Delete the auto-display which we were in the process of displaying. - This is done when there is an error or a signal. */ - -void -delete_current_display () -{ - if (current_display_number >= 0) - { - delete_display (current_display_number); - fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n", - current_display_number); - } - current_display_number = -1; -} - -static void -display_info () -{ - register struct display *d; - - if (!display_chain) - printf ("There are no auto-display expressions now.\n"); - else - printf ("Auto-display expressions now in effect:\n\ -Num Enb Expression\n"); - - for (d = display_chain; d; d = d->next) - { - printf ("%d: %c ", d->number, "ny"[(int)d->status]); - if (d->format.size) - printf ("/%d%c%c ", d->format.count, d->format.size, - d->format.format); - else if (d->format.format) - printf ("/%c ", d->format.format); - print_expression (d->exp, stdout); - if (d->block && !contained_in (get_selected_block (), d->block)) - printf (" (cannot be evaluated in the current context)"); - printf ("\n"); - fflush (stdout); - } -} - -void -enable_display (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d->next) - d->status = enabled; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = enabled; - goto win; - } - printf ("No display number %d.\n", num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } -} - -void -disable_display (args) - char *args; -{ - register char *p = args; - register char *p1; - register int num; - register struct display *d; - - if (p == 0) - { - for (d = display_chain; d; d->next) - d->status = disabled; - } - else - while (*p) - { - p1 = p; - while (*p1 >= '0' && *p1 <= '9') - p1++; - if (*p1 && *p1 != ' ' && *p1 != '\t') - error ("Arguments must be display numbers."); - - num = atoi (p); - - for (d = display_chain; d; d = d->next) - if (d->number == num) - { - d->status = disabled; - goto win; - } - printf ("No display number %d.\n", num); - win: - p = p1; - while (*p == ' ' || *p == '\t') - p++; - } -} - - -/* Print the value in stack frame FRAME of a variable - specified by a struct symbol. */ - -void -print_variable_value (var, frame, stream) - struct symbol *var; - CORE_ADDR frame; - FILE *stream; -{ - value val = read_var_value (var, frame); - value_print (val, stream, 0); -} - -/* Print the arguments of a stack frame, given the function FUNC - running in that frame (as a symbol), the info on the frame, - and the number of args according to the stack frame (or -1 if unknown). */ - -static void print_frame_nameless_args (); - -void -print_frame_args (func, fi, num, stream) - struct symbol *func; - struct frame_info *fi; - int num; - FILE *stream; -{ - struct block *b; - int nsyms = 0; - int first = 1; - register int i; - register int last_offset = FRAME_ARGS_SKIP; - register int last_regparm = 0; - register struct symbol *lastsym, *sym, *nextsym; - register value val; - register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); - - if (func) - { - b = SYMBOL_BLOCK_VALUE (func); - nsyms = BLOCK_NSYMS (b); - } - - lastsym = 0; - while (1) - { - /* Find first arg that is not before LAST_OFFSET. */ - nextsym = 0; - for (i = 0; i < nsyms; i++) - { - QUIT; - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG) - { - if (SYMBOL_VALUE (sym) >= last_offset - && (nextsym == 0 - || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) - nextsym = sym; - } - else if (SYMBOL_CLASS (sym) == LOC_REGPARM) - { - /* This shouldn't be sorted by number. Since we can't - find nameless args with register parameters, print - this out in order by .stabs. */ - if (sym > lastsym && nextsym == 0) - nextsym = sym; - } - } - if (nextsym == 0) - break; - sym = nextsym; - /* Print any nameless args between the last arg printed - and the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_ARG - && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) - { - print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), - stream); - first = 0; - } - /* Print the next arg. */ - if (SYMBOL_CLASS (sym) == LOC_REGPARM) - val = value_from_register (SYMBOL_TYPE (sym), - SYMBOL_VALUE (sym), - FRAME_INFO_ID (fi)); - else - val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); - - if (! first) - fprintf (stream, ", "); - fprintf (stream, "%s=", SYMBOL_NAME (sym)); - value_print (val, stream, 0); - first = 0; - if (SYMBOL_CLASS (sym) == LOC_ARG) - last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); - else - { - last_regparm = SYMBOL_VALUE (sym) + 1; - last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); - } - - /* Round up address of next arg to multiple of size of int. */ - last_offset - = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); - lastsym = sym; - } - if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) - print_frame_nameless_args (addr, last_offset, - num * sizeof (int) + FRAME_ARGS_SKIP, stream); -} - -static void -print_frame_nameless_args (argsaddr, start, end, stream) - CORE_ADDR argsaddr; - int start; - int end; - FILE *stream; -{ - while (start < end) - { - QUIT; - if (start != FRAME_ARGS_SKIP) - fprintf (stream, ", "); - fprintf (stream, "%d", - read_memory_integer (argsaddr + start, sizeof (int))); - start += sizeof (int); - } -} - -static void -printf_command (arg) - char *arg; -{ - register char *f; - register char *s = arg; - char *string; - value *val_args; - int nargs = 0; - int allocated_args = 20; - char *arg_bytes; - char *argclass; - int i; - int argindex; - int nargs_wanted; - - val_args = (value *) xmalloc (allocated_args * sizeof (value)); - - if (s == 0) - error_no_arg ("format-control string and values to print"); - - /* Skip white space before format string */ - while (*s == ' ' || *s == '\t') s++; - - /* A format string should follow, enveloped in double quotes */ - if (*s++ != '"') - error ("Bad format string, missing '\"'."); - - /* Parse the format-control string and copy it into the string STRING, - processing some kinds of escape sequence. */ - - f = string = (char *) alloca (strlen (s) + 1); - while (*s != '"') - { - int c = *s++; - switch (c) - { - case '\0': - error ("Bad format string, non-terminated '\"'."); - /* doesn't return */ - - case '\\': - switch (c = *s++) - { - case '\\': - *f++ = '\\'; - break; - case 'n': - *f++ = '\n'; - break; - case 't': - *f++ = '\t'; - break; - case 'r': - *f++ = '\r'; - break; - case '"': - *f++ = '"'; - break; - default: - /* ??? TODO: handle other escape sequences */ - error ("Unrecognized \\ escape character in format string."); - } - break; - - default: - *f++ = c; - } - } - - /* Skip over " and following space and comma. */ - s++; - *f++ = '\0'; - while (*s == ' ' || *s == '\t') s++; - - if (*s != ',' && *s != 0) - error ("Invalid argument syntax"); - - if (*s == ',') s++; - while (*s == ' ' || *s == '\t') s++; - - /* Now scan the string for %-specs and see what kinds of args they want. - argclass[I] is set to 1 if the Ith arg should be a string. - It's set to 2 if the Ith arg should be floating point. */ - - argclass = (char *) alloca (strlen (s)); - nargs_wanted = 0; - f = string; - while (*f) - if (*f++ == '%') - { - while (index ("0123456789.hlL-+ #", *f)) f++; - if (*f == 's') - argclass[nargs_wanted++] = 1; - else if (*f == 'e' || *f == 'f' || *f == 'g') - argclass[nargs_wanted++] = 2; - else if (*f != '%') - argclass[nargs_wanted++] = 0; - f++; - } - - /* Now, parse all arguments and evaluate them. - Store the VALUEs in VAL_ARGS. */ - - while (*s != '\0') - { - char *s1; - if (nargs == allocated_args) - val_args = (value *) xrealloc (val_args, - (allocated_args *= 2) - * sizeof (value)); - s1 = s; - val_args[nargs] = parse_to_comma_and_eval (&s1); - - /* If format string wants a float, unchecked-convert the value to - floating point of the same size */ - - if (argclass[nargs] == 2) - { - argclass[nargs] = 0; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (float)) - VALUE_TYPE (val_args[nargs]) = builtin_type_float; - if (TYPE_LENGTH (VALUE_TYPE (val_args[nargs])) == sizeof (double)) - VALUE_TYPE (val_args[nargs]) = builtin_type_double; - } - nargs++; - s = s1; - if (*s == ',') - s++; - } - - if (nargs != nargs_wanted) - error ("Wrong number of arguments for specified format-string"); - - /* Now lay out an argument-list containing the arguments - as doubles, integers and C pointers. */ - - arg_bytes = (char *) alloca (sizeof (double) * nargs); - argindex = 0; - for (i = 0; i < nargs; i++) - { - if (argclass[i]) - { - char *str; - int tem, j; - tem = value_as_long (val_args[i]); - - /* This is a %s argument. Find the length of the string. */ - for (j = 0; ; j++) - { - char c; - QUIT; - read_memory (tem + j, &c, 1); - if (c == 0) - break; - } - - /* Copy the string contents into a string inside GDB. */ - str = (char *) alloca (j + 1); - read_memory (tem, str, j); - str[j] = 0; - - /* Pass address of internal copy as the arg to vprintf. */ - *((int *) &arg_bytes[argindex]) = (int) str; - argindex += sizeof (int); - } - else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT) - { - *((double *) &arg_bytes[argindex]) = value_as_double (val_args[i]); - argindex += sizeof (double); - } - else -#ifdef LONG_LONG - if (TYPE_LENGTH (VALUE_TYPE (val_args[i])) == sizeof (long long)) - { - *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]); - argindex += sizeof (long long); - } - else -#endif - { - *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]); - argindex += sizeof (int); - } - } - - vprintf (string, arg_bytes); -} - -extern struct cmd_list_element *enablelist, *disablelist, *deletelist; -extern struct cmd_list_element *cmdlist, *setlist; - -void -_initialize_printcmd () -{ - current_display_number = -1; - - add_info ("address", address_info, - "Describe where variable VAR is stored."); - - add_com ("x", class_vars, x_command, - "Examine memory: x/FMT ADDRESS.\n\ -ADDRESS is an expression for the memory address to examine.\n\ -FMT is a repeat count followed by a format letter and a size letter.\n\ -Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ - f(float), a(address), i(instruction), c(char) and s(string).\n\ -Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\ - g is meaningful only with f, for type double.\n\ -The specified number of objects of the specified size are printed\n\ -according to the format.\n\n\ -Defaults for format and size letters are those previously used.\n\ -Default count is 1. Default address is following last thing printed\n\ -with this command or \"print\"."); - - add_com ("ptype", class_vars, ptype_command, - "Print definition of type TYPE.\n\ -Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ -or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ -The selected stack frame's lexical context is used to look up the name."); - - add_com ("whatis", class_vars, whatis_command, - "Print data type of expression EXP."); - - add_info ("display", display_info, - "Expressions to display when program stops, with code numbers."); - - add_abbrev_cmd ("undisplay", class_vars, undisplay_command, - "Cancel some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means cancel all automatic-display expressions.\n\ -\"delete display\" has the same effect as this command.\n\ -Do \"info display\" to see current list of code numbers.", - &cmdlist); - - add_com ("display", class_vars, display_command, - "Print value of expression EXP each time the program stops.\n\ -/FMT may be used before EXP as in the \"print\" command.\n\ -/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\ -as in the \"x\" command, and then EXP is used to get the address to examine\n\ -and examining is done as in the \"x\" command.\n\n\ -With no argument, display all currently requested auto-display expressions.\n\ -Use \"undisplay\" to cancel display requests previously made."); - - add_cmd ("display", class_vars, enable_display, - "Enable some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to resume displaying.\n\ -No argument means enable all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &enablelist); - - add_cmd ("display", class_vars, disable_display, - "Disable some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means disable all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &disablelist); - - add_cmd ("display", class_vars, undisplay_command, - "Cancel some expressions to be displayed when program stops.\n\ -Arguments are the code numbers of the expressions to stop displaying.\n\ -No argument means cancel all automatic-display expressions.\n\ -Do \"info display\" to see current list of code numbers.", &deletelist); - - add_com ("printf", class_vars, printf_command, - "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\ -This is useful for formatted output in user-defined commands."); - add_com ("output", class_vars, output_command, - "Like \"print\" but don't put in value history and don't print newline.\n\ -This is useful in user-defined commands."); - - add_prefix_cmd ("set", class_vars, set_command, -"Perform an assignment VAR = EXP.\n\ -You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\ -(names starting with $), a register (a few standard names starting with $),\n\ -or an actual variable in the program being debugged. EXP is any expression.\n\ -Use \"set variable\" for variables with names identical to set subcommands.\n\ -\nWith a subcommand, this command modifies parts of the gdb environment", - &setlist, "set ", 1, &cmdlist); - - add_cmd ("variable", class_vars, set_command, - "Perform an assignment VAR = EXP.\n\ -You must type the \"=\". VAR may be a debugger \"convenience\" variable\n\ -(names starting with $), a register (a few standard names starting with $),\n\ -or an actual variable in the program being debugged. EXP is any expression.\n\ -This may usually be abbreviated to simply \"set\".", - &setlist); - - add_com ("print", class_vars, print_command, - concat ("Print value of expression EXP.\n\ -Variables accessible are those of the lexical environment of the selected\n\ -stack frame, plus all those whose scope is global or an entire file.\n\ -\n\ -$NUM gets previous value number NUM. $ and $$ are the last two values.\n\ -$$NUM refers to NUM'th value back from the last one.\n\ -Names starting with $ refer to registers (with the values they would have\n\ -if the program were to return to the stack frame now selected, restoring\n\ -all registers saved by frames farther in) or else to debugger\n\ -\"convenience\" variables (any such name not a known register).\n\ -Use assignment expressions to give values to convenience variables.\n", - "\n\ -\{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\ -@@ is a binary operator for treating consecutive data objects\n\ -anywhere in memory as an array. FOO@@NUM gives an array whose first\n\ -element is FOO, whose second element is stored in the space following\n\ -where FOO is stored, etc. FOO must be an expression whose value\n\ -resides in memory.\n", - "\n\ -EXP may be preceded with /FMT, where FMT is a format letter\n\ -but no count or size letter (see \"x\" command).")); - add_com_alias ("p", "print", class_vars, 1); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@a191 1 - int bigendian = 0; -d196 7 -a202 5 - { - union { - char a, b, c, d; - long i; - } x; -a203 10 - x.i = 1; - if (x.a) - { - /* Little endian */ - tmp = v1; - v1 = v2; - v2 = tmp; - } - } - -d207 1 -a207 1 - printf ("0x%08x%08x", v1, v2); -d238 1 -a238 1 - printf ("0x%02llx", val_long); -d241 1 -a241 1 - printf ("0x%04llx", val_long); -d245 1 -a245 1 - printf ("0x%08llx", val_long); -d248 1 -a248 1 - printf ("0x%16llx", val_long); -d257 1 -a257 1 - printf ("0x%02x", val_long); -d260 1 -a260 1 - printf ("0x%04x", val_long); -d264 1 -a264 1 - printf ("0x%08x", val_long); -d267 1 -a267 1 - printf ("0x%16x", val_long); -d277 1 -a277 1 - printf ("%lld", val_long); -d279 1 -a279 1 - printf ("%d", val_long); -d285 1 -a285 1 - printf ("%llu", val_long); -d287 1 -a287 1 - printf ("%u", val_long); -d294 1 -a294 1 - printf ("0%llo", val_long); -d296 1 -a296 1 - printf ("0%o", val_long); -d299 1 -a299 1 - printf ("0"); -d313 1 -a313 1 - if (len == sizeof (double)) -d315 2 -d318 1 -a318 1 - if (is_nan (unpack_double (type, valaddr))) -d320 1 -a320 1 - printf ("Nan"); -d324 10 -a333 4 - if (len > 4) - printf ("%.16g", unpack_double (type, valaddr)); - else - printf ("%.6g", unpack_double (type, valaddr)); -d515 1 -a515 1 - printf ("$%d = ", histindex); -@ diff --git a/gdb/RCS/remote.c,v b/gdb/RCS/remote.c,v deleted file mode 100644 index 213113d..0000000 --- a/gdb/RCS/remote.c,v +++ /dev/null @@ -1,662 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.21.22; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.45.46; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid <sys/fcntl.h>. -@ -text -@/* Memory-access and commands for inferior process, for GDB. - Copyright (C) 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -/* Remote communication protocol. - All values are encoded in ascii hex digits. - - Request Packet - - read registers g - reply XX....X Each byte of register data - is described by two hex digits. - Registers are in the internal order - for GDB, and the bytes in a register - are in the same order the machine uses. - or ENN for an error. - - write regs GXX..XX Each byte of register data - is described by two hex digits. - reply OK for success - ENN for an error - - read mem mAA..AA,LLLL AA..AA is address, LLLL is length. - reply XX..XX XX..XX is mem contents - or ENN NN is errno - - write mem MAA..AA,LLLL:XX..XX - AA..AA is address, - LLLL is number of bytes, - XX..XX is data - reply OK for success - ENN for an error - - cont cAA..AA AA..AA is address to resume - If AA..AA is omitted, - resume at same address. - - step sAA..AA AA..AA is address to resume - If AA..AA is omitted, - resume at same address. - - There is no immediate reply to step or cont. - The reply comes when the machine stops. - It is SAA AA is the "signal number" - - kill req k -*/ - -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" - -#include "wait.h" - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#endif - -#include <stdio.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/file.h> - -#ifdef HAVE_TERMIO -#include <termio.h> -#undef TIOCGETP -#define TIOCGETP TCGETA -#undef TIOCSETN -#define TIOCSETN TCSETA -#undef TIOCSETP -#define TIOCSETP TCSETAF -#define TERMINAL struct termio -#else -#include <sgtty.h> -#define TERMINAL struct sgttyb -#endif - -int kiodebug; - -int icache; - -/* Descriptor for I/O to remote machine. */ -int remote_desc; - -#define PBUFSIZ 400 - -static void remote_send (); -static void putpkt (); -static void getpkt (); -static void dcache_flush (); - - -/* Open a connection to a remote debugger. - NAME is the filename used for communication. */ - -void -remote_open (name, from_tty) - char *name; - int from_tty; -{ - TERMINAL sg; - - remote_debugging = 0; - dcache_init (); - - remote_desc = open (name, O_RDWR); - if (remote_desc < 0) - perror_with_name (name); - - ioctl (remote_desc, TIOCGETP, &sg); -#ifdef HAVE_TERMIO - sg.c_lflag &= ~ICANON; -#else - sg.sg_flags = RAW; -#endif - ioctl (remote_desc, TIOCSETP, &sg); - - if (from_tty) - printf ("Remote debugging using %s\n", name); - remote_debugging = 1; -} - -/* Convert hex digit A to a number. */ - -static int -fromhex (a) - int a; -{ - if (a >= '0' && a <= '9') - return a - '0'; - else if (a >= 'a' && a <= 'f') - return a - 'a' + 10; - else - error ("Reply contains invalid hex digit"); -} - -/* Convert number NIB to a hex digit. */ - -static int -tohex (nib) - int nib; -{ - if (nib < 10) - return '0'+nib; - else - return 'a'+nib-10; -} - -/* Tell the remote machine to resume. */ - -int -remote_resume (step, signal) - int step, signal; -{ - char buf[PBUFSIZ]; - - dcache_flush (); - - strcpy (buf, step ? "s": "c"); - - putpkt (buf); -} - -/* Wait until the remote machine stops, then return, - storing status in STATUS just as `wait' would. */ - -int -remote_wait (status) - WAITTYPE *status; -{ - char buf[PBUFSIZ]; - - WSETEXIT ((*status), 0); - getpkt (buf); - if (buf[0] == 'E') - error ("Remote failure reply: %s", buf); - if (buf[0] != 'S') - error ("Invalid remote reply: %s", buf); - WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2])))); -} - -/* Read the remote registers into the block REGS. */ - -void -remote_fetch_registers (regs) - char *regs; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - sprintf (buf, "g"); - remote_send (buf); - - /* Reply describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf; - for (i = 0; i < REGISTER_BYTES; i++) - { - if (p[0] == 0 || p[1] == 0) - error ("Remote reply is too short: %s", buf); - regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } -} - -/* Store the remote registers from the contents of the block REGS. */ - -void -remote_store_registers (regs) - char *regs; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - buf[0] = 'G'; - - /* Command describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf + 1; - for (i = 0; i < REGISTER_BYTES; i++) - { - *p++ = tohex ((regs[i] >> 4) & 0xf); - *p++ = tohex (regs[i] & 0xf); - } - - remote_send (buf); -} - -/* Read a word from remote address ADDR and return it. - This goes through the data cache. */ - -int -remote_fetch_word (addr) - CORE_ADDR addr; -{ - if (icache) - { - extern CORE_ADDR text_start, text_end; - - if (addr >= text_start && addr < text_end) - { - int buffer; - xfer_core_file (addr, &buffer, sizeof (int)); - return buffer; - } - } - return dcache_fetch (addr); -} - -/* Write a word WORD into remote address ADDR. - This goes through the data cache. */ - -void -remote_store_word (addr, word) - CORE_ADDR addr; - int word; -{ - dcache_poke (addr, word); -} - -/* Write memory data directly to the remote machine. - This does not inform the data cache; the data cache uses this. - MEMADDR is the address in the remote memory space. - MYADDR is the address of the buffer in our space. - LEN is the number of bytes. */ - -void -remote_write_bytes (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - if (len > PBUFSIZ / 2 - 20) - abort (); - - sprintf (buf, "M%x,%x:", memaddr, len); - - /* Command describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf + strlen (buf); - for (i = 0; i < len; i++) - { - *p++ = tohex ((myaddr[i] >> 4) & 0xf); - *p++ = tohex (myaddr[i] & 0xf); - } - - remote_send (buf); -} - -/* Read memory data directly from the remote machine. - This does not use the data cache; the data cache uses this. - MEMADDR is the address in the remote memory space. - MYADDR is the address of the buffer in our space. - LEN is the number of bytes. */ - -void -remote_read_bytes (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - char buf[PBUFSIZ]; - int i; - char *p; - - if (len > PBUFSIZ / 2 - 1) - abort (); - - sprintf (buf, "m%x,%x", memaddr, len); - remote_send (buf); - - /* Reply describes registers byte by byte, - each byte encoded as two hex characters. */ - - p = buf; - for (i = 0; i < len; i++) - { - if (p[0] == 0 || p[1] == 0) - error ("Remote reply is too short: %s", buf); - myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]); - p += 2; - } -} - -/* - -A debug packet whose contents are <data> -is encapsulated for transmission in the form: - - $ <data> # CSUM1 CSUM2 - - <data> must be ASCII alphanumeric and cannot include characters - '$' or '#' - - CSUM1 and CSUM2 are ascii hex representation of an 8-bit - checksum of <data>, the most significant nibble is sent first. - the hex digits 0-9,a-f are used. - -Receiver responds with: - - + - if CSUM is correct and ready for next packet - - - if CSUM is incorrect - -*/ - -/* Send the command in BUF to the remote machine, - and read the reply into BUF. - Report an error if we get an error reply. */ - -static void -remote_send (buf) - char *buf; -{ - int i; - putpkt (buf); - getpkt (buf); - - if (buf[0] == 'E') - error ("Remote failure reply: %s", buf); -} - -/* Send a packet to the remote machine, with error checking. - The data of the packet is in BUF. */ - -static void -putpkt (buf) - char *buf; -{ - int i; - char csum = 0; - char buf2[500]; - char buf3[1]; - int cnt = strlen (buf); - char *p; - - if (kiodebug) - fprintf (stderr, "Sending packet: %s\n", buf); - - /* Copy the packet into buffer BUF2, encapsulating it - and giving it a checksum. */ - - p = buf2; - *p++ = '$'; - - for (i = 0; i < cnt; i++) - { - csum += buf[i]; - *p++ = buf[i]; - } - *p++ = '#'; - *p++ = tohex ((csum >> 4) & 0xf); - *p++ = tohex (csum & 0xf); - - /* Send it over and over until we get a positive ack. */ - - do { - write (remote_desc, buf2, p - buf2); - read (remote_desc, buf3, 1); - } while (buf3[0] != '+'); -} - -static int -readchar () -{ - char buf[1]; - while (read (remote_desc, buf, 1) != 1) ; - return buf[0] & 0x7f; -} - -/* Read a packet from the remote machine, with error checking, - and store it in BUF. */ - -static void -getpkt (buf) - char *buf; -{ - char *bp; - unsigned char csum; - unsigned int c, c1, c2; - extern kiodebug; - - while (1) - { - /* Force csum to be zero here because of possible error retry. */ - csum = 0; - - while ((c = readchar()) != '$'); - - bp = buf; - while (1) - { - c = readchar (); - if (c == '#') - break; - *bp++ = c; - csum += c; - } - *bp = 0; - - c1 = fromhex (readchar ()); - c2 = fromhex (readchar ()); - if (csum == (c1 << 4) + c2) - break; - printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", - (c1 << 4) + c2, csum, buf); - write (remote_desc, "-", 1); - } - - write (remote_desc, "+", 1); - - if (kiodebug) - fprintf (stderr,"Packet received :%s\n", buf); -} - -/* The data cache records all the data read from the remote machine - since the last time it stopped. - - Each cache block holds 16 bytes of data - starting at a multiple-of-16 address. */ - -#define DCACHE_SIZE 64 /* Number of cache blocks */ - -struct dcache_block { - struct dcache_block *next, *last; - unsigned int addr; /* Address for which data is recorded. */ - int data[4]; -}; - -struct dcache_block dcache_free, dcache_valid; - -/* Free all the data cache blocks, thus discarding all cached data. */ - -static void -dcache_flush () -{ - register struct dcache_block *db; - - while ((db = dcache_valid.next) != &dcache_valid) - { - remque (db); - insque (db, &dcache_free); - } -} - -/* - * If addr is present in the dcache, return the address of the block - * containing it. - */ - -struct dcache_block * -dcache_hit (addr) -{ - register struct dcache_block *db; - - if (addr & 3) - abort (); - - /* Search all cache blocks for one that is at this address. */ - db = dcache_valid.next; - while (db != &dcache_valid) - { - if ((addr & 0xfffffff0) == db->addr) - return db; - db = db->next; - } - return NULL; -} - -/* Return the int data at address ADDR in dcache block DC. */ - -int -dcache_value (db, addr) - struct dcache_block *db; - unsigned int addr; -{ - if (addr & 3) - abort (); - return (db->data[(addr>>2)&3]); -} - -/* Get a free cache block, put it on the valid list, - and return its address. The caller should store into the block - the address and data that it describes. */ - -struct dcache_block * -dcache_alloc () -{ - register struct dcache_block *db; - - if ((db = dcache_free.next) == &dcache_free) - /* If we can't get one from the free list, take last valid */ - db = dcache_valid.last; - - remque (db); - insque (db, &dcache_valid); - return (db); -} - -/* Return the contents of the word at address ADDR in the remote machine, - using the data cache. */ - -int -dcache_fetch (addr) - CORE_ADDR addr; -{ - register struct dcache_block *db; - - db = dcache_hit (addr); - if (db == 0) - { - db = dcache_alloc (); - remote_read_bytes (addr & ~0xf, db->data, 16); - db->addr = addr & ~0xf; - } - return (dcache_value (db, addr)); -} - -/* Write the word at ADDR both in the data cache and in the remote machine. */ - -dcache_poke (addr, data) - CORE_ADDR addr; - int data; -{ - register struct dcache_block *db; - - /* First make sure the word is IN the cache. DB is its cache block. */ - db = dcache_hit (addr); - if (db == 0) - { - db = dcache_alloc (); - remote_read_bytes (addr & ~0xf, db->data, 16); - db->addr = addr & ~0xf; - } - - /* Modify the word in the cache. */ - db->data[(addr>>2)&3] = data; - - /* Send the changed word. */ - remote_write_bytes (addr, &data, 4); -} - -/* Initialize the data cache. */ - -dcache_init () -{ - register i; - register struct dcache_block *db; - - db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) * - DCACHE_SIZE); - dcache_free.next = dcache_free.last = &dcache_free; - dcache_valid.next = dcache_valid.last = &dcache_valid; - for (i=0;i<DCACHE_SIZE;i++,db++) - insque (db, &dcache_free); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d74 1 -a74 1 -#include <sys/fcntl.h> -@ diff --git a/gdb/RCS/source.c,v b/gdb/RCS/source.c,v deleted file mode 100644 index f19ff1d..0000000 --- a/gdb/RCS/source.c,v +++ /dev/null @@ -1,990 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.21.45; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.20.18.45.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid <sys/fcntl.h>. -@ -text -@/* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "symtab.h" -#include "param.h" - -#ifdef USG -#include <sys/types.h> -#include <fcntl.h> -#endif - -#include <stdio.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/file.h> - -/* Path of directories to search for source files. - Same format as the PATH environment variable's value. */ - -static char *source_path; - -/* Symtab of default file for listing lines of. */ - -struct symtab *current_source_symtab; - -/* Default next line to list. */ - -int current_source_line; - -/* Line number of last line printed. Default for various commands. - current_source_line is usually, but not always, the same as this. */ - -static int last_line_listed; - -/* First line number listed by last listing command. */ - -static int first_line_listed; - - -struct symtab *psymtab_to_symtab (); - -/* Set the source file default for the "list" command, - specifying a symtab. */ - -void -select_source_symtab (s) - register struct symtab *s; -{ - struct symtabs_and_lines sals; - struct symtab_and_line sal; - struct partial_symtab *ps, *cs_pst; - - /* Make the default place to list be the function `main' - if one exists. */ - if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0)) - { - sals = decode_line_spec ("main", 1); - sal = sals.sals[0]; - free (sals.sals); - current_source_symtab = sal.symtab; - current_source_line = sal.line - 9; - return; - } - - /* If there is no `main', use the last symtab in the list, - which is actually the first found in the file's symbol table. - But ignore .h files. */ - if (s) - { - do - { - char *name = s->filename; - int len = strlen (name); - if (! (len > 2 && !strcmp (&name[len - 2], ".h"))) - current_source_symtab = s; - s = s->next; - } - while (s); - current_source_line = 1; - } - else - { - ps = partial_symtab_list; - while (ps) - { - char *name = ps->filename; - int len = strlen (name); - if (! (len > 2 && !strcmp (&name[len - 2], ".h"))) - cs_pst = ps; - ps = ps->next; - } - if (cs_pst) - current_source_symtab = psymtab_to_symtab (cs_pst); - else - current_source_symtab = 0; - current_source_line = 1; - } -} - -static void -directories_info () -{ - printf ("Source directories searched: %s\n", source_path); -} - -void -init_source_path () -{ - register struct symtab *s; - - source_path = savestring (current_directory, strlen (current_directory)); - - /* Forget what we learned about line positions in source files; - must check again now since files may be found in - a different directory now. */ - for (s = symtab_list; s; s = s->next) - if (s->line_charpos != 0) - { - free (s->line_charpos); - s->line_charpos = 0; - } -} - -void -directory_command (dirname, from_tty) - char *dirname; - int from_tty; -{ - char *old = source_path; - - if (dirname == 0) - { - if (query ("Reinitialize source path to %s? ", current_directory)) - { - init_source_path (); - free (old); - } - } - else - { - struct stat st; - register int len = strlen (dirname); - register char *tem; - extern char *index (); - - if (index (dirname, ':')) - error ("Please add one directory at a time to the source path."); - if (dirname[len - 1] == '/') - /* Sigh. "foo/" => "foo" */ - dirname[--len] == '\0'; - - while (dirname[len - 1] == '.') - { - if (len == 1) - { - /* "." => getwd () */ - dirname = current_directory; - goto append; - } - else if (dirname[len - 2] == '/') - { - if (len == 2) - { - /* "/." => "/" */ - dirname[--len] = '\0'; - goto append; - } - else - { - /* "...foo/." => "...foo" */ - dirname[len -= 2] = '\0'; - continue; - } - } - break; - } - - if (dirname[0] != '/') - dirname = concat (current_directory, "/", dirname); - else - dirname = savestring (dirname, len); - make_cleanup (free, dirname); - - if (stat (dirname, &st) < 0) - perror_with_name (dirname); - if ((st.st_mode & S_IFMT) != S_IFDIR) - error ("%s is not a directory.", dirname); - - append: - len = strlen (dirname); - tem = source_path; - while (1) - { - if (!strncmp (tem, dirname, len) - && (tem[len] == '\0' || tem[len] == ':')) - { - printf ("\"%s\" is already in the source path.\n", - dirname); - break; - } - tem = index (tem, ':'); - if (tem) - tem++; - else - { - source_path = concat (old, ":", dirname); - free (old); - break; - } - } - if (from_tty) - directories_info (); - } -} - -/* Open a file named STRING, searching path PATH (dir names sep by colons) - using mode MODE and protection bits PROT in the calls to open. - If TRY_CWD_FIRST, try to open ./STRING before searching PATH. - (ie pretend the first element of PATH is ".") - If FILENAMED_OPENED is non-null, set it to a newly allocated string naming - the actual file opened (this string will always start with a "/" - - If a file is found, return the descriptor. - Otherwise, return -1, with errno set for the last name we tried to open. */ - -/* >>>> This should only allow files of certain types, - >>>> eg executable, non-directory */ -int -openp (path, try_cwd_first, string, mode, prot, filename_opened) - char *path; - int try_cwd_first; - char *string; - int mode; - int prot; - char **filename_opened; -{ - register int fd; - register char *filename; - register char *p, *p1; - register int len; - - /* ./foo => foo */ - while (string[0] == '.' && string[1] == '/') - string += 2; - - if (try_cwd_first || string[0] == '/') - { - filename = string; - fd = open (filename, mode, prot); - if (fd >= 0 || string[0] == '/') - goto done; - } - - filename = (char *) alloca (strlen (path) + strlen (string) + 2); - fd = -1; - for (p = path; p; p = p1 ? p1 + 1 : 0) - { - p1 = (char *) index (p, ':'); - if (p1) - len = p1 - p; - else - len = strlen (p); - - strncpy (filename, p, len); - filename[len] = 0; - strcat (filename, "/"); - strcat (filename, string); - - fd = open (filename, mode, prot); - if (fd >= 0) break; - } - - done: - if (filename_opened) - if (fd < 0) - *filename_opened = (char *) 0; - else if (filename[0] == '/') - *filename_opened = savestring (filename, strlen (filename)); - else - { - *filename_opened = concat (current_directory, "/", filename); - } - - return fd; -} - -/* Create and initialize the table S->line_charpos that records - the positions of the lines in the source file, which is assumed - to be open on descriptor DESC. - All set S->nlines to the number of such lines. */ - -static void -find_source_lines (s, desc) - struct symtab *s; - int desc; -{ - struct stat st; - register char *data, *p, *end; - int nlines = 0; - int lines_allocated = 1000; - int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int)); - extern int exec_mtime; - - fstat (desc, &st); - if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime) - printf ("Source file is more recent than executable.\n"); - - data = (char *) alloca (st.st_size); - myread (desc, data, st.st_size); - end = data + st.st_size; - p = data; - line_charpos[0] = 0; - nlines = 1; - while (p != end) - { - if (*p++ == '\n' - /* A newline at the end does not start a new line. */ - && p != end) - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = (int *) xrealloc (line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = p - data; - } - } - s->nlines = nlines; - s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int)); -} - -/* Return the character position of a line LINE in symtab S. - Return 0 if anything is invalid. */ - -int -source_line_charpos (s, line) - struct symtab *s; - int line; -{ - if (!s) return 0; - if (!s->line_charpos || line <= 0) return 0; - if (line > s->nlines) - line = s->nlines; - return s->line_charpos[line - 1]; -} - -/* Return the line number of character position POS in symtab S. */ - -int -source_charpos_line (s, chr) - register struct symtab *s; - register int chr; -{ - register int line = 0; - register int *lnp; - - if (s == 0 || s->line_charpos == 0) return 0; - lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok */ - while (line < s->nlines && *lnp <= chr) - { - line++; - lnp++; - } - if (line >= s->nlines) - line = s->nlines; - return line; -} - -/* Get full pathname and line number positions for a symtab. - Return nonzero if line numbers may have changed. - Set *FULLNAME to actual name of the file as found by `openp', - or to 0 if the file is not found. */ - -int -get_filename_and_charpos (s, line, fullname) - struct symtab *s; - int line; - char **fullname; -{ - register int desc, linenums_changed = 0; - - desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname); - if (desc < 0) - { - if (fullname) - *fullname = NULL; - return 0; - } - if (fullname) - *fullname = s->fullname; - if (s->line_charpos == 0) linenums_changed = 1; - if (linenums_changed) find_source_lines (s, desc); - close (desc); - return linenums_changed; -} - -/* Print text describing the full name of the source file S - and the line number LINE and its corresponding character position. - The text starts with two Ctrl-z so that the Emacs-GDB interface - can easily find it. - - MID_STATEMENT is nonzero if the PC is not at the beginning of that line. - - Return 1 if successful, 0 if could not find the file. */ - -int -identify_source_line (s, line, mid_statement) - struct symtab *s; - int line; - int mid_statement; -{ - if (s->line_charpos == 0) - get_filename_and_charpos (s, line, 0); - if (s->fullname == 0) - return 0; - printf ("\032\032%s:%d:%d:%s\n", s->fullname, - line, s->line_charpos[line - 1], - mid_statement ? "middle" : "beg"); - current_source_line = line; - first_line_listed = line; - last_line_listed = line; - current_source_symtab = s; - return 1; -} - -/* Print source lines from the file of symtab S, - starting with line number LINE and stopping before line number STOPLINE. */ - -void -print_source_lines (s, line, stopline, noerror) - struct symtab *s; - int line, stopline; - int noerror; -{ - register int c; - register int desc; - register FILE *stream; - int nlines = stopline - line; - - desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname); - if (desc < 0) - { - extern int errno; - if (! noerror) - perror_with_name (s->filename); - print_sys_errmsg (s->filename, errno); - return; - } - - if (s->line_charpos == 0) - find_source_lines (s, desc); - - if (line < 1 || line > s->nlines) - { - close (desc); - error ("Line number out of range; %s has %d lines.", - s->filename, s->nlines); - } - - if (lseek (desc, s->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (s->filename); - } - - current_source_symtab = s; - current_source_line = line; - first_line_listed = line; - - stream = fdopen (desc, "r"); - clearerr (stream); - - while (nlines-- > 0) - { - c = fgetc (stream); - if (c == EOF) break; - last_line_listed = current_source_line; - printf ("%d\t", current_source_line++); - do - { - if (c < 040 && c != '\t' && c != '\n') - { - fputc ('^', stdout); - fputc (c + 0100, stdout); - } - else if (c == 0177) - printf ("^?"); - else - fputc (c, stdout); - } while (c != '\n' && (c = fgetc (stream)) >= 0); - } - - fclose (stream); -} - - - -/* - C++ - Print a list of files and line numbers which a user may choose from - in order to list a function which was specified ambiguously - (as with `list classname::overloadedfuncname', for example). - The vector in SALS provides the filenames and line numbers. - */ -static void -ambiguous_line_spec (sals) - struct symtabs_and_lines *sals; -{ - int i; - - for (i = 0; i < sals->nelts; ++i) - printf("file: \"%s\", line number: %d\n", - sals->sals[i].symtab->filename, sals->sals[i].line); -} - - -static void -list_command (arg, from_tty) - char *arg; - int from_tty; -{ - struct symtabs_and_lines sals, sals_end; - struct symtab_and_line sal, sal_end; - struct symbol *sym; - char *arg1; - int no_end = 1; - int dummy_end = 0; - int dummy_beg = 0; - int linenum_beg = 0; - char *p; - - if (symtab_list == 0 && partial_symtab_list == 0) - error ("Listing source lines requires symbols."); - - /* Pull in a current source symtab if necessary */ - if (current_source_symtab == 0 && - (arg == 0 || arg[0] == '+' || arg[0] == '-')) - select_source_symtab (symtab_list); - - /* "l" or "l +" lists next ten lines. */ - - if (arg == 0 || !strcmp (arg, "+")) - { - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - print_source_lines (current_source_symtab, current_source_line, - current_source_line + 10, 0); - return; - } - - /* "l -" lists previous ten lines, the ones before the ten just listed. */ - if (!strcmp (arg, "-")) - { - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - print_source_lines (current_source_symtab, - max (first_line_listed - 10, 1), - first_line_listed, 0); - return; - } - - /* Now if there is only one argument, decode it in SAL - and set NO_END. - If there are two arguments, decode them in SAL and SAL_END - and clear NO_END; however, if one of the arguments is blank, - set DUMMY_BEG or DUMMY_END to record that fact. */ - - arg1 = arg; - if (*arg1 == ',') - dummy_beg = 1; - else - { - sals = decode_line_1 (&arg1, 0, 0, 0); - - if (! sals.nelts) return; /* C++ */ - if (sals.nelts > 1) - { - ambiguous_line_spec (&sals); - free (sals.sals); - return; - } - - sal = sals.sals[0]; - free (sals.sals); - } - - /* Record whether the BEG arg is all digits. */ - - for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++); - linenum_beg = (p == arg1); - - while (*arg1 == ' ' || *arg1 == '\t') - arg1++; - if (*arg1 == ',') - { - no_end = 0; - arg1++; - while (*arg1 == ' ' || *arg1 == '\t') - arg1++; - if (*arg1 == 0) - dummy_end = 1; - else - { - if (dummy_beg) - sals_end = decode_line_1 (&arg1, 0, 0, 0); - else - sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line); - if (sals_end.nelts == 0) - return; - if (sals_end.nelts > 1) - { - ambiguous_line_spec (&sals_end); - free (sals_end.sals); - return; - } - sal_end = sals_end.sals[0]; - free (sals_end.sals); - } - } - - if (*arg1) - error ("Junk at end of line specification."); - - if (!no_end && !dummy_beg && !dummy_end - && sal.symtab != sal_end.symtab) - error ("Specified start and end are in different files."); - if (dummy_beg && dummy_end) - error ("Two empty args do not say what lines to list."); - - /* if line was specified by address, - first print exactly which line, and which file. - In this case, sal.symtab == 0 means address is outside - of all known source files, not that user failed to give a filename. */ - if (*arg == '*') - { - if (sal.symtab == 0) - error ("No source file for address 0x%x.", sal.pc); - sym = find_pc_function (sal.pc); - if (sym) - printf ("0x%x is in %s (%s, line %d).\n", - sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line); - else - printf ("0x%x is in %s, line %d.\n", - sal.pc, sal.symtab->filename, sal.line); - } - - /* If line was not specified by just a line number, - and it does not imply a symtab, it must be an undebuggable symbol - which means no source code. */ - - if (! linenum_beg && sal.symtab == 0) - error ("No line number known for %s.", arg); - - /* If this command is repeated with RET, - turn it into the no-arg variant. */ - - if (from_tty) - *arg = 0; - - if (dummy_beg && sal_end.symtab == 0) - error ("No default source file yet. Do \"help list\"."); - if (dummy_beg) - print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1), - sal_end.line + 1, 0); - else if (sal.symtab == 0) - error ("No default source file yet. Do \"help list\"."); - else if (no_end) - print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0); - else - print_source_lines (sal.symtab, sal.line, - dummy_end ? sal.line + 10 : sal_end.line + 1, - 0); -} - -/* Print info on range of pc's in a specified line. */ - -static void -line_info (arg, from_tty) - char *arg; - int from_tty; -{ - struct symtabs_and_lines sals; - struct symtab_and_line sal; - int start_pc, end_pc; - int i; - - if (arg == 0) - { - sal.symtab = current_source_symtab; - sal.line = last_line_listed; - sals.nelts = 1; - sals.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - sals.sals[0] = sal; - } - else - { - sals = decode_line_spec_1 (arg, 0); - - /* If this command is repeated with RET, - turn it into the no-arg variant. */ - if (from_tty) - *arg = 0; - } - - /* C++ More than one line may have been specified, as when the user - specifies an overloaded function name. Print info on them all. */ - for (i = 0; i < sals.nelts; i++) - { - sal = sals.sals[i]; - - if (sal.symtab == 0) - error ("No source file specified."); - - if (sal.line > 0 - && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc)) - { - if (start_pc == end_pc) - printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n", - sal.line, sal.symtab->filename, start_pc); - else - printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n", - sal.line, sal.symtab->filename, start_pc, end_pc); - /* x/i should display this line's code. */ - set_next_address (start_pc); - /* Repeating "info line" should do the following line. */ - last_line_listed = sal.line + 1; - } - else - printf ("Line number %d is out of range for \"%s\".\n", - sal.line, sal.symtab->filename); - } -} - -/* Commands to search the source file for a regexp. */ - -static void -forward_search_command (regex, from_tty) - char *regex; -{ - register int c; - register int desc; - register FILE *stream; - int line = last_line_listed + 1; - char *msg; - - msg = (char *) re_comp (regex); - if (msg) - error (msg); - - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - - /* Search from last_line_listed+1 in current_source_symtab */ - - desc = openp (source_path, 0, current_source_symtab->filename, - O_RDONLY, 0, ¤t_source_symtab->fullname); - if (desc < 0) - perror_with_name (current_source_symtab->filename); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); - - if (line < 1 || line > current_source_symtab->nlines) - { - close (desc); - error ("Expression not found"); - } - - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (current_source_symtab->filename); - } - - stream = fdopen (desc, "r"); - clearerr (stream); - while (1) { - char buf[4096]; /* Should be reasonable??? */ - register char *p = buf; - - c = fgetc (stream); - if (c == EOF) - break; - do { - *p++ = c; - } while (c != '\n' && (c = fgetc (stream)) >= 0); - - /* we now have a source line in buf, null terminate and match */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - fclose (stream); - print_source_lines (current_source_symtab, - line, line+1, 0); - current_source_line = max (line - 5, 1); - return; - } - line++; - } - - printf ("Expression not found\n"); - fclose (stream); -} - -static void -reverse_search_command (regex, from_tty) - char *regex; -{ - register int c; - register int desc; - register FILE *stream; - int line = last_line_listed - 1; - char *msg; - - msg = (char *) re_comp (regex); - if (msg) - error (msg); - - if (current_source_symtab == 0) - error ("No default source file yet. Do \"help list\"."); - - /* Search from last_line_listed-1 in current_source_symtab */ - - desc = openp (source_path, 0, current_source_symtab->filename, - O_RDONLY, 0, ¤t_source_symtab->fullname); - if (desc < 0) - perror_with_name (current_source_symtab->filename); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc); - - if (line < 1 || line > current_source_symtab->nlines) - { - close (desc); - error ("Expression not found"); - } - - if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - close (desc); - perror_with_name (current_source_symtab->filename); - } - - stream = fdopen (desc, "r"); - clearerr (stream); - while (1) - { - char buf[4096]; /* Should be reasonable??? */ - register char *p = buf; - - c = fgetc (stream); - if (c == EOF) - break; - do { - *p++ = c; - } while (c != '\n' && (c = fgetc (stream)) >= 0); - - /* We now have a source line in buf; null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - fclose (stream); - print_source_lines (current_source_symtab, - line, line+1, 0); - current_source_line = max (line - 5, 1); - return; - } - line--; - if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0) - { - fclose (stream); - perror_with_name (current_source_symtab->filename); - } - } - - printf ("Expression not found\n"); - fclose (stream); - return; -} - -void -_initialize_source () -{ - current_source_symtab = 0; - init_source_path (); - - add_com ("directory", class_files, directory_command, - "Add directory DIR to end of search path for source files.\n\ -With no argument, reset the search path to just the working directory\n\ -and forget cached info on line positions in source files."); - - add_info ("directories", directories_info, - "Current search path for finding source files."); - - add_info ("line", line_info, - "Core addresses of the code for a source line.\n\ -Line can be specified as\n\ - LINENUM, to list around that line in current file,\n\ - FILE:LINENUM, to list around that line in that file,\n\ - FUNCTION, to list around beginning of that function,\n\ - FILE:FUNCTION, to distinguish among like-named static functions.\n\ -Default is to describe the last source line that was listed.\n\n\ -This sets the default address for \"x\" to the line's first instruction\n\ -so that \"x/i\" suffices to start examining the machine code.\n\ -The address is also stored as the value of \"$_\"."); - - add_com ("forward-search", class_files, forward_search_command, - "Search for regular expression (see regex(3)) from last line listed."); - add_com_alias ("search", "forward-search", class_files, 0); - - add_com ("reverse-search", class_files, reverse_search_command, - "Search backward for regular expression (see regex(3)) from last line listed."); - - add_com ("list", class_files, list_command, - "List specified function or line.\n\ -With no argument, lists ten more lines after or around previous listing.\n\ -\"list -\" lists the ten lines before a previous ten-line listing.\n\ -One argument specifies a line, and ten lines are listed around that line.\n\ -Two arguments with comma between specify starting and ending lines to list.\n\ -Lines can be specified in these ways:\n\ - LINENUM, to list around that line in current file,\n\ - FILE:LINENUM, to list around that line in that file,\n\ - FUNCTION, to list around beginning of that function,\n\ - FILE:FUNCTION, to distinguish among like-named static functions.\n\ - *ADDRESS, to list around the line containing that address.\n\ -With two args if one is empty it stands for ten lines away from the other arg."); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d27 1 -a27 1 -#include <sys/fcntl.h> -@ diff --git a/gdb/RCS/sparc-dep.c,v b/gdb/RCS/sparc-dep.c,v deleted file mode 100644 index 8178e00..0000000 --- a/gdb/RCS/sparc-dep.c,v +++ /dev/null @@ -1,1091 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.04.21.31.02; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.02.10.01.47.27; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.10.01.46.36; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix handling of annulled branches in single step. "b foo; bcc,a bar" -annuls the instruction at foo, not just after the bcc,a. Also, -handle CBcc (coprocessor) annulled branch, and improve doc. -@ -text -@/* Machine-dependent code which would otherwise be in inflow.c and core.c, - for GDB, the GNU debugger. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - This code is for the sparc cpu. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include "defs.h" -#include "param.h" -#include "frame.h" -#include "inferior.h" -#include "obstack.h" -#include "sparc-opcode.h" -#include "gdbcore.h" - -#include <stdio.h> -#include <sys/param.h> -#include <sys/dir.h> -#include <sys/user.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <fcntl.h> - -#include <sys/ptrace.h> -#include <machine/reg.h> - -#include <a.out.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/core.h> - -extern int errno; -extern int attach_flag; - -/* 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); -} - -void -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.*/ - -void -kill_inferior_fast () -{ - if (remote_debugging) - return; - if (inferior_pid == 0) - return; - ptrace (8, inferior_pid, 0, 0); - wait (0); -} - -/* Simulate single-step ptrace call for sun4. Code written by Gary - Beihl (beihl@@mcc.com). */ - -/* - * Duplicated from breakpoint.c because (at least for now) this is a - * machine dependent routine. - */ -static char break_insn[] = BREAKPOINT; - -/* From infrun.c */ -extern int stop_after_trap, stop_after_attach; - -static CORE_ADDR next_pc, npc4, target; -static int brknpc4, brktrg; -typedef char binsn_quantum[sizeof break_insn]; -static binsn_quantum break_mem[3]; - -/* Non-zero if we just simulated a single-step ptrace call. This is - needed because we cannot remove the breakpoints in the inferior - process until after the `wait' in `wait_for_inferior'. Used for - sun4. */ - -int one_stepped; - -void -single_step (signal) - int signal; -{ - branch_type br, isannulled(); - CORE_ADDR pc; - - next_pc = read_register (NPC_REGNUM); - npc4 = next_pc + 4; /* branch not taken */ - - if (!one_stepped) - { - /* Always set breakpoint for NPC. */ - read_memory (next_pc, break_mem[0], sizeof break_insn); - write_memory (next_pc, break_insn, sizeof break_insn); - /* printf ("set break at %x\n",next_pc); */ - - pc = read_register (PC_REGNUM); - br = isannulled (pc, &target); - brknpc4 = brktrg = 0; - - if (br == bicca) - { - /* Conditional annulled branch will either end up at - npc (if taken) or at npc+4 (if not taken). Trap npc+4. */ - brknpc4 = 1; - read_memory (npc4, break_mem[1], sizeof break_insn); - write_memory (npc4, break_insn, sizeof break_insn); - } - else if (br == baa && target != next_pc) - { - /* Unconditional annulled branch will always end up at - the target. */ - brktrg = 1; - read_memory (target, break_mem[2], sizeof break_insn); - write_memory (target, break_insn, sizeof break_insn); - } - - /* Let it go */ - ptrace (7, inferior_pid, 1, signal); - one_stepped = 1; - return; - } - else - { - /* Remove breakpoints */ - write_memory (next_pc, break_mem[0], sizeof break_insn); - - if (brknpc4) - { - write_memory (npc4, break_mem[1], sizeof break_insn); - } - if (brktrg) - { - write_memory (target, break_mem[2], sizeof break_insn); - } - one_stepped = 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 - { - /* Sparc doesn't have single step on ptrace */ - if (step) - single_step (signal); - else - ptrace (7, inferior_pid, 1, signal); - if (errno) - perror_with_name ("ptrace"); - } -} - -#ifdef ATTACH_DETACH - -/* Start debugging the process whose number is PID. */ - -int -attach (pid) - int pid; -{ - errno = 0; - ptrace (PTRACE_ATTACH, pid, 0, 0); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 1; - return pid; -} - -/* Stop debugging the process whose number is PID - and continue it with signal number SIGNAL. - SIGNAL = 0 means just continue it. */ - -void -detach (signal) - int signal; -{ - errno = 0; - ptrace (PTRACE_DETACH, inferior_pid, 1, signal); - if (errno) - perror_with_name ("ptrace"); - attach_flag = 0; -} -#endif /* ATTACH_DETACH */ - -void -fetch_inferior_registers () -{ - struct regs inferior_registers; - struct fp_status inferior_fp_registers; - extern char registers[]; - int cwp; - struct rwindow local_and_ins; - - if (remote_debugging) - remote_fetch_registers (registers); - else - { - ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); - ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); - - registers[REGISTER_BYTE (0)] = 0; - bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4); - bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], - sizeof inferior_fp_registers.fpu_fr); - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc; - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y; -/* *(int *)®isters[REGISTER_BYTE (RP_REGNUM)] = - inferior_registers.r_o7 + 8; - bcopy (&inferior_fp_registers.Fpu_fsr, - ®isters[REGISTER_BYTE (FPS_REGNUM)], - sizeof (FPU_FSR_TYPE)); */ - - read_inferior_memory (inferior_registers.r_sp, - ®isters[REGISTER_BYTE (16)], - 16*4); - } -} - -/* Store our register values back into the inferior. - If REGNO is -1, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ - -void -store_inferior_registers (regno) - int regno; -{ - struct regs inferior_registers; - struct fp_status inferior_fp_registers; - extern char registers[]; - - if (remote_debugging) - remote_store_registers (registers); - else - { - int in_regs = 1, in_fpregs = 1, in_fparegs, in_cpregs = 1; - - if (regno >= 0) - if (FP0_REGNUM <= regno && regno <= FP0_REGNUM + 32) - in_regs = 0; - else - in_fpregs = 0; - - if (in_regs) - { - bcopy (®isters[REGISTER_BYTE (1)], - &inferior_registers.r_g1, 15 * 4); - - inferior_registers.r_ps = - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; - inferior_registers.r_pc = - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; - inferior_registers.r_npc = - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)]; - inferior_registers.r_y = - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)]; - - write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)], - ®isters[REGISTER_BYTE (16)], - 16*4); - } - if (in_fpregs) - { - bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], - &inferior_fp_registers, - sizeof inferior_fp_registers.fpu_fr); - - /* bcopy (®isters[REGISTER_BYTE (FPS_REGNUM)], - &inferior_fp_registers.Fpu_fsr, - sizeof (FPU_FSR_TYPE)); - ****/ - } - - if (in_regs) - ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); - if (in_fpregs) - ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); - } -} - -/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory - in the NEW_SUN_PTRACE case. - It ought to be straightforward. But it appears that writing did - not write the data that I specified. I cannot understand where - it got the data that it actually did write. */ - -/* Copy LEN bytes 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 (remote_debugging) - buffer[i] = remote_fetch_word (addr); - else - 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; -} - - -/* Machine-dependent code which would otherwise be in core.c */ -/* Work with core dump and executable files, for GDB. */ - -/* Recognize COFF format systems because a.out.h defines AOUTHDR. */ -#ifdef AOUTHDR -#define COFF_FORMAT -#endif - -#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 -#define AOUTHDR struct exec -#endif - -extern char *sys_siglist[]; - -/* Hook for `exec_file_command' command to call. */ - -extern void (*exec_file_display_hook) (); - -#ifdef COFF_FORMAT -/* 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 (); - -void -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) - { - 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); - - { - struct core corestr; - - val = myread (corechan, &corestr, sizeof corestr); - if (val < 0) - perror_with_name (filename); - if (corestr.c_magic != CORE_MAGIC) - error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)", - filename, corestr.c_magic, (int) CORE_MAGIC); - else if (sizeof (struct core) != corestr.c_len) - error ("\"%s\" has an invalid struct core length (%d, expected %d)", - filename, corestr.c_len, (int) sizeof (struct core)); - - /* Note that data_start and data_end don't depend on the exec file */ - data_start = N_DATADDR (corestr.c_aouthdr); - data_end = data_start + corestr.c_dsize; - stack_start = stack_end - corestr.c_ssize; - data_offset = sizeof corestr; - stack_offset = sizeof corestr + corestr.c_dsize; - - /* G0 *always* holds 0. */ - *(int *)®isters[REGISTER_BYTE (0)] = 0; - /* The globals and output registers. */ - - bcopy (&corestr.c_regs.r_g1, ((int *) registers) + 1, 15 * 4); - *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; - *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; - *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc; - *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y; - - /* My best guess at where to get the locals and input - registers is exactly where they usually are, right above - the stack pointer. If the core dump was caused by a bus - writing off the stack pointer (as is possible) then this - won't work, but it's worth the try. */ - { - int sp; - - sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)]; - lseek (corechan, sp - stack_start + stack_offset, L_SET); - if (16 * 4 != myread (corechan, - ®isters[REGISTER_BYTE (16)], - 16 * 4)) - /* fprintf so user can still use gdb */ - fprintf (stderr, "Couldn't read input and local registers from core file\n"); - } - - bcopy (corestr.c_fpu.fpu_regs, - ®isters[REGISTER_BYTE (FP0_REGNUM)], - sizeof corestr.c_fpu.fpu_regs); -#ifdef FPU - bcopy (&corestr.c_fpu.fpu_fsr, - ®isters[REGISTER_BYTE (FPS_REGNUM)], - sizeof (FPU_FSR_TYPE)); -#endif - - bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec)); - - printf ("Core file is from \"%s\".\n", corestr.c_cmdname); - if (corestr.c_signo > 0) - printf ("Program terminated with signal %d, %s.\n", - corestr.c_signo, - corestr.c_signo < NSIG - ? sys_siglist[corestr.c_signo] - : "(undocumented)"); - } - 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"); -} - -void -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; - 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) - { - execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, - &execfile); - if (execchan < 0) - perror_with_name (filename); - -#ifdef COFF_FORMAT - { - 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 = text_hdr.s_scnptr; - exec_data_start = exec_aouthdr.data_start; - exec_data_end = exec_data_start + exec_aouthdr.dsize; - exec_data_offset = data_hdr.s_scnptr; - exec_mtime = file_hdr.f_timdat; - } -#else /* not COFF_FORMAT */ - { - struct stat st_exec; - val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR)); - - if (val < 0) - perror_with_name (filename); - - text_start = N_TXTADDR (exec_aouthdr); - exec_data_start = N_DATADDR (exec_aouthdr); - text_offset = N_TXTOFF (exec_aouthdr); - exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; - - text_end = text_start + exec_aouthdr.a_text; - exec_data_end = exec_data_start + exec_aouthdr.a_data; - - fstat (execchan, &st_exec); - exec_mtime = st_exec.st_mtime; - } -#endif /* not COFF_FORMAT */ - - 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); -} - -/* - * Find the pc saved in frame FRAME. - */ -CORE_ADDR -frame_saved_pc (frame) - FRAME frame; -{ - CORE_ADDR prev_pc; - - /* If it's at the bottom, the return value's stored in i7/rp */ - if (get_current_frame () == frame) - prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]); - else - /* Wouldn't this always work? This would allow this routine to - be completely a macro. */ - prev_pc = GET_RWINDOW_REG (frame->bottom, rw_in[7]); - - return PC_ADJUST (prev_pc); -} - -/* - * Since an individual frame in the frame cache is defined by two - * arguments (a frame pointer and a stack pointer), we need two - * arguments to get info for an arbitrary stack frame. This routine - * takes two arguments and makes the cached frames look as if these - * two arguments defined a frame on the cache. This allows the rest - * of info frame to extract the important arguments without - * difficulty. - */ -FRAME -setup_arbitrary_frame (frame, stack) - FRAME_ADDR frame, stack; -{ - struct frame_info *fci; - FRAME fid = create_new_frame (frame, 0); - - if (!fid) - fatal ("internal: create_new_frame returned invalid frame id"); - - fid->bottom = stack; - - return fid; -} - -/* This code was written by Gary Beihl (beihl@@mcc.com). - It was modified by Michael Tiemann (tiemann@@corto.inria.fr). */ - -struct command_line *get_breakpoint_commands (); - -/* - * This routine appears to be passed a size by which to increase the - * stack. It then executes a save instruction in the inferior to - * increase the stack by this amount. Only the register window system - * should be affected by this; the program counter & etc. will not be. - * - * This instructions used for this purpose are: - * - * sethi %hi(0x0),g1 * - * add g1,0x1ee0,g1 * - * save sp,g1,sp - * sethi %hi(0x0),g1 * - * add g1,0x1ee0,g1 * - * t g0,0x1,o0 - * sethi %hi(0x0),g0 (nop) - * - * I presume that these set g1 to be the negative of the size, do a - * save (putting the stack pointer at sp - size) and restore the - * original contents of g1. A * indicates that the actual value of - * the instruction is modified below. - */ -static int save_insn_opcodes[] = { - 0x03000000, 0x82007ee0, 0x9de38001, 0x03000000, - 0x82007ee0, 0x91d02001, 0x01000000 }; - -/* Neither do_save_insn or do_restore_insn save stack configuration - (since the stack is in an indeterminate state through the call to - each of them); that responsibility of the routine which calls them. */ - -void -do_save_insn (size) - int size; -{ - int g1 = read_register (1); - CORE_ADDR sp = read_register (SP_REGNUM); - CORE_ADDR pc = read_register (PC_REGNUM); - CORE_ADDR npc = read_register (NPC_REGNUM); - CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes); - struct inferior_status inf_status; - - save_inferior_status (&inf_status, 0); /* Don't restore stack info */ - /* - * See above. - */ - save_insn_opcodes[0] = 0x03000000 | ((-size >> 10) & 0x3fffff); - save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff); - save_insn_opcodes[3] = 0x03000000 | ((g1 >> 10) & 0x3fffff); - save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff); - write_memory (fake_pc, save_insn_opcodes, sizeof (save_insn_opcodes)); - - clear_proceed_status (); - stop_after_trap = 1; - proceed (fake_pc, 0, 0); - - write_register (PC_REGNUM, pc); - write_register (NPC_REGNUM, npc); - restore_inferior_status (&inf_status); -} - -/* - * This routine takes a program counter value. It restores the - * register window system to the frame above the current one, and sets - * the pc and npc to the correct values. - */ - -/* The following insns translate to: - - restore - t g0,0x1,o0 - sethi %hi(0x0), g0 */ - -static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 }; - -void -do_restore_insn (pc) - CORE_ADDR pc; -{ - CORE_ADDR sp = read_register (SP_REGNUM); - CORE_ADDR npc = pc + 4; - CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes); - struct inferior_status inf_status; - - save_inferior_status (&inf_status, 0); /* Don't restore stack info */ - - if (!pc) - abort(); - - write_memory (fake_pc, restore_insn_opcodes, sizeof (restore_insn_opcodes)); - - clear_proceed_status (); - stop_after_trap = 1; - proceed (fake_pc, 0, 0); - - write_register (PC_REGNUM, pc); - write_register (NPC_REGNUM, npc); - restore_inferior_status (&inf_status); -} - -/* - * This routine should be more specific in it's actions; making sure - * that it uses the same register in the initial prologue section. - */ -CORE_ADDR -skip_prologue (pc) - CORE_ADDR pc; -{ - union - { - union insn_fmt insn; - int i; - } x; - int dest = -1; - - x.i = read_memory_integer (pc, 4); - - /* Recognize sethi insn. Record destination. */ - if (x.insn.sethi.op == 0 - && x.insn.sethi.op2 == 4) - { - dest = x.insn.sethi.rd; - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* Recognizes an add immediate value to register to either %g1 or - the destination register recorded above. Actually, this might - well recognize several different arithmetic operations.*/ - if (x.insn.arith_imm.op == 2 - && x.insn.arith_imm.i == 1 - && (x.insn.arith_imm.rd == 1 - || x.insn.arith_imm.rd == dest)) - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* This recognizes any SAVE insn. But why do the XOR and then - the compare? That's identical to comparing against 60 (as long - as there isn't any sign extension). */ - if (x.insn.arith.op == 2 - && (x.insn.arith.op3 ^ 32) == 28) - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - - /* Now we need to recognize stores into the frame from the input - registers. This recognizes all non alternate stores of input - register, into a location offset from the frame pointer. */ - while (x.insn.arith_imm.op == 3 - && (x.insn.arith_imm.op3 & 0x3c) == 4 /* Store, non-alt */ - && (x.insn.arith_imm.rd & 0x18) == 0x18 /* Input register */ - && x.insn.arith_imm.i == 1 /* Immediate mode */ - && x.insn.arith_imm.rs1 == 30 /* Off of frame pointer */ - && x.insn.arith_imm.simm >= 0x44 /* Into reserved */ - && x.insn.arith_imm.simm < 0x5b) /* stack space. */ - { - pc += 4; - x.i = read_memory_integer (pc, 4); - } - return pc; -} - -/* - * Check instruction at "addr" to see if it is an annulled branch. - * All other instructions will go to NPC or will trap. - * - * Set *target if we find a candidate branch; set to zero if not. - */ - -branch_type -isannulled (addr, target) - CORE_ADDR addr, *target; -{ - union insn_fmt instr; - branch_type val = not_branch; - long offset; /* Must be signed for sign-extend */ - - *target = 0; - instr.intval = read_memory_integer (addr, 4); - /* printf("intval = %x\n",instr.intval); */ - switch (instr.op1.op1) - { - case 0: /* Format 2 */ - switch(instr.op2.op2) - { - case 2: case 6: case 7: /* Bcc, FBcc, CBcc */ - if (instr.branch.cond == 8) - val = instr.branch.a ? baa : ba; - else - val = instr.branch.a ? bicca : bicc; - /* 22 bits, sign extended */ - offset = 4 * ((int) (instr.branch.disp << 10) >> 10); - *target = addr + offset; - break; - } - break; - } - /*printf("isannulled ret: %d\n",val); */ - return val; -} -@ - - -1.2 -log -@ * Use gdbcore.h rather than a bunch of externs. - * Avoid dependency on "exec file" when figuring out data_start and data_end -of core file. -@ -text -@d97 2 -a98 2 -static CORE_ADDR next_pc, pc8, target; -static int brkpc8, brktrg; -d113 2 -a114 1 - branch_type br, isabranch(); -d117 1 -a117 1 - pc8 = read_register (PC_REGNUM) + 8; /* branch not taken */ -d124 1 -d126 3 -a128 3 - /* printf ("set break at %x\n",next_pc); */ - br = isabranch (pc8 - 8, &target); - brkpc8 = brktrg = 0; -d130 7 -a136 6 - if (br == bicca && pc8 != next_pc) - { - /* Handle branches with care */ - brkpc8 = 1; - read_memory (pc8, break_mem[1], sizeof break_insn); - write_memory (pc8, break_insn, sizeof break_insn); -d140 2 -d157 1 -a157 1 - if (brkpc8) -d159 1 -a159 1 - write_memory (pc8, break_mem[1], sizeof break_insn); -d895 6 -a900 1 -/* Set *target if we find a branch. */ -d903 1 -a903 1 -isabranch (addr, target) -d918 1 -a918 1 - case 2: case 6: /* BICC & FBCC */ -d930 1 -a930 1 - /*printf("isabranch ret: %d\n",val); */ -@ - - -1.1 -log -@Initial revision -@ -text -@d29 1 -a453 49 -/* 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; - -d520 2 -a521 1 - data_start = exec_data_start; -a601 2 - data_start = 0; - data_end -= exec_data_start; -a644 2 - data_start = exec_data_start; - data_end += exec_data_start; -a661 2 - data_start = exec_data_start; - data_end += exec_data_start; -@ diff --git a/gdb/RCS/stack.c,v b/gdb/RCS/stack.c,v deleted file mode 100644 index fc755c2..0000000 --- a/gdb/RCS/stack.c,v +++ /dev/null @@ -1,882 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.02.09.23.53.05; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.02.09.15.03.51; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Avoid coredumps if stack commands are used when there is no stack. -@ -text -@/* Print and select stack frames for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> - -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "frame.h" -#include "inferior.h" -#include "gdbcore.h" - - -/* Thie "selected" stack frame is used by default for local and arg access. - May be zero, for no selected frame. */ - -FRAME selected_frame; - -/* Level of the selected frame: - 0 for innermost, 1 for its caller, ... - or -1 for frame specified by address with no defined level. */ - -int selected_frame_level; - -/* Error message when selected_frame is zero when it's needed */ -char no_sel_frame[] = "There is no current stack frame."; - -/* Nonzero means print the full filename and linenumber - when a frame is printed, and do so in a format programs can parse. */ - -int frame_file_full_name = 0; - -static void select_calling_frame (); - -void print_frame_info (); - -/* Print a stack frame briefly. FRAME should be the frame address - and LEVEL should be its level in the stack (or -1 for level not defined). - This prints the level, the function executing, the arguments, - and the file name and line number. - If the pc is not at the beginning of the source line, - the actual pc is printed at the beginning. - - If SOURCE is 1, print the source line as well. - If SOURCE is -1, print ONLY the source line. */ - -/* FIXME, the argument "frame" is always "selected_frame". This is why - we can say "No selected frame" if it == 0. Probably shouldn't be an - argument anymore... */ - -static void -print_stack_frame (frame, level, source) - FRAME frame; - int level; - int source; -{ - struct frame_info *fi; - - if (frame == 0) - error (no_sel_frame); - fi = get_frame_info (frame); - - print_frame_info (fi, level, source, 1); -} - -void -print_frame_info (fi, level, source, args) - struct frame_info *fi; - register int level; - int source; - int args; -{ - struct symtab_and_line sal; - struct symbol *func; - register char *funname = 0; - int numargs; - - sal = find_pc_line (fi->pc, fi->next_frame); - func = find_pc_function (fi->pc); - if (func) - funname = SYMBOL_NAME (func); - else - { - register int misc_index = find_pc_misc_function (fi->pc); - if (misc_index >= 0) - funname = misc_function_vector[misc_index].name; - } - - if (source >= 0 || !sal.symtab) - { - if (level >= 0) - printf ("#%-2d ", level); - if (fi->pc != sal.pc || !sal.symtab) - printf ("0x%x in ", fi->pc); - printf ("%s (", funname ? funname : "??"); - if (args) - { - FRAME_NUM_ARGS (numargs, fi); - print_frame_args (func, fi, numargs, stdout); - } - printf (")"); - if (sal.symtab) - printf (" (%s line %d)", sal.symtab->filename, sal.line); - printf ("\n"); - } - - if (source != 0 && sal.symtab) - { - int done = 0; - int mid_statement = source < 0 && fi->pc != sal.pc; - if (frame_file_full_name) - done = identify_source_line (sal.symtab, sal.line, mid_statement); - if (!done) - { - if (mid_statement) - printf ("0x%x\t", fi->pc); - print_source_lines (sal.symtab, sal.line, sal.line + 1, 1); - } - current_source_line = max (sal.line - 5, 1); - } - if (source != 0) - set_default_breakpoint (1, fi->pc, sal.symtab, sal.line); - - fflush (stdout); -} - -/* Call here to print info on selected frame, after a trap. */ - -void -print_sel_frame (just_source) - int just_source; -{ - print_stack_frame (selected_frame, -1, just_source ? -1 : 1); -} - -/* Print info on the selected frame, including level number - but not source. */ - -void -print_selected_frame () -{ - print_stack_frame (selected_frame, selected_frame_level, 0); -} - -void flush_cached_frames (); /* FIXME, never called! */ - -#ifdef FRAME_SPECIFICATION_DYADIC -extern FRAME setup_arbitrary_frame (); -#endif - -/* - * Read a frame specification in whatever the appropriate format is. - */ -static FRAME -parse_frame_specification (frame_exp) - char *frame_exp; -{ - int numargs = 0; - int arg1, arg2; - - if (frame_exp) - { - char *addr_string, *p; - struct cleanup *tmp_cleanup; - struct frame_info *fci; - - while (*frame_exp == ' ') frame_exp++; - for (p = frame_exp; *p && *p != ' '; p++) - ; - - if (*frame_exp) - { - numargs = 1; - addr_string = savestring(frame_exp, p - frame_exp); - - { - tmp_cleanup = make_cleanup (free, addr_string); - arg1 = parse_and_eval_address (addr_string); - do_cleanups (tmp_cleanup); - } - - while (*p == ' ') p++; - - if (*p) - { - numargs = 2; - arg2 = parse_and_eval_address (p); - } - } - } - - switch (numargs) - { - case 0: - if (selected_frame == 0) - error (no_sel_frame); - return selected_frame; - /* NOTREACHED */ - case 1: - { - int level = arg1; - FRAME fid = find_relative_frame (get_current_frame (), &level); - FRAME tfid; - - if (level == 0) - /* find_relative_frame was successful */ - return fid; - - /* If (s)he specifies the frame with an address, he deserves what - (s)he gets. Still, give the highest one that matches. */ - - for (fid = get_current_frame (); - fid && FRAME_FP (fid) != arg1; - fid = get_prev_frame (fid)) - ; - - if (fid) - while ((tfid = get_prev_frame (fid)) && - (FRAME_FP (tfid) == arg1)) - fid = tfid; - -#ifdef FRAME_SPECIFICATION_DYADIC - if (!fid) - error ("Incorrect number of args in frame specification"); - - return fid; -#else - return create_new_frame (arg1, 0); -#endif - } - /* NOTREACHED */ - case 2: - /* Must be addresses */ -#ifndef FRAME_SPECIFICATION_DYADIC - error ("Incorrect number of args in frame specification"); -#else - return setup_arbitrary_frame (arg1, arg2); -#endif - /* NOTREACHED */ - } - fatal ("Internal: Error in parsing in parse_frame_specification"); - /* NOTREACHED */ -} - -/* Print verbosely the selected frame or the frame at address ADDR. - This means absolutely all information in the frame is printed. */ - -static void -frame_info (addr_exp) - char *addr_exp; -{ - FRAME frame; - struct frame_info *fi; - struct frame_saved_regs fsr; - struct symtab_and_line sal; - struct symbol *func; - FRAME calling_frame; - int i, count; - char *funname = 0; - int numargs; - - frame = parse_frame_specification (addr_exp); - - fi = get_frame_info (frame); - get_frame_saved_regs (fi, &fsr); - sal = find_pc_line (fi->pc, fi->next_frame); - func = get_frame_function (frame); - if (func) - funname = SYMBOL_NAME (func); - else - { - register int misc_index = find_pc_misc_function (fi->pc); - if (misc_index >= 0) - funname = misc_function_vector[misc_index].name; - } - calling_frame = get_prev_frame (frame); - - if (!addr_exp && selected_frame_level >= 0) - printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x", - selected_frame_level, FRAME_FP(frame), fi->pc); - else - printf ("Stack frame at 0x%x:\n pc = 0x%x", - FRAME_FP(frame), fi->pc); - - if (funname) - printf (" in %s", funname); - if (sal.symtab) - printf (" (%s line %d)", sal.symtab->filename, sal.line); - printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame)); - if (calling_frame) - printf (" called by frame at 0x%x", FRAME_FP (calling_frame)); - if (fi->next_frame && calling_frame) - printf (","); - if (fi->next_frame) - printf (" caller of frame at 0x%x", fi->next_frame); - if (fi->next_frame || calling_frame) - printf ("\n"); - printf (" Arglist at 0x%x,", FRAME_ARGS_ADDRESS (fi)); - FRAME_NUM_ARGS (i, fi); - if (i < 0) - printf (" args: "); - else if (i == 0) - printf (" no args."); - else if (i == 1) - printf (" 1 arg: "); - else - printf (" %d args: ", i); - - FRAME_NUM_ARGS (numargs, fi); - print_frame_args (func, fi, numargs, stdout); - printf ("\n"); - count = 0; - for (i = 0; i < NUM_REGS; i++) - if (fsr.regs[i]) - { - if (count % 4 != 0) - printf (", "); - else - { - if (count == 0) - printf (" Saved registers:"); - printf ("\n "); - } - printf ("%s at 0x%x", reg_names[i], fsr.regs[i]); - count++; - } - if (count) - printf ("\n"); -} - -#if 0 -/* Set a limit on the number of frames printed by default in a - backtrace. */ - -static int backtrace_limit; - -static void -set_backtrace_limit_command (count_exp, from_tty) - char *count_exp; - int from_tty; -{ - int count = parse_and_eval_address (count_exp); - - if (count < 0) - error ("Negative argument not meaningful as backtrace limit."); - - backtrace_limit = count; -} - -static void -backtrace_limit_info (arg, from_tty) - char *arg; - int from_tty; -{ - if (arg) - error ("\"Info backtrace-limit\" takes no arguments."); - - printf ("Backtrace limit: %d.\n", backtrace_limit); -} -#endif - -/* Print briefly all stack frames or just the innermost COUNT frames. */ - -static void -backtrace_command (count_exp) - char *count_exp; -{ - struct frame_info *fi; - register int count; - register FRAME frame; - register int i; - register FRAME trailing; - register int trailing_level; - - if (have_inferior_p () == 0 && corefile == 0) - error ("There is no running program or core file."); - - /* The following code must do two things. First, it must - set the variable TRAILING to the frame from which we should start - printing. Second, it must set the variable count to the number - of frames which we should print, or -1 if all of them. */ - trailing = get_current_frame (); - trailing_level = 0; - if (count_exp) - { - count = parse_and_eval_address (count_exp); - if (count < 0) - { - FRAME current; - - count = -count; - - current = trailing; - while (current && count--) - current = get_prev_frame (current); - - /* Will stop when CURRENT reaches the top of the stack. TRAILING - will be COUNT below it. */ - while (current) - { - trailing = get_prev_frame (trailing); - current = get_prev_frame (current); - trailing_level++; - } - - count = -1; - } - } - else -#if 0 - count = backtrace_limit; -#else - count = -1; -#endif - - for (i = 0, frame = trailing; - frame && count--; - i++, frame = get_prev_frame (frame)) - { - QUIT; - fi = get_frame_info (frame); - print_frame_info (fi, trailing_level + i, 0, 1); - } - - /* If we've stopped before the end, mention that. */ - if (frame) - printf ("(More stack frames follow...)\n"); -} - -/* Print the local variables of a block B active in FRAME. */ - -static void -print_block_frame_locals (b, frame, stream) - struct block *b; - register FRAME frame; - register FILE *stream; -{ - int nsyms; - register int i; - register struct symbol *sym; - - nsyms = BLOCK_NSYMS (b); - - for (i = 0; i < nsyms; i++) - { - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_LOCAL - || SYMBOL_CLASS (sym) == LOC_REGISTER - || SYMBOL_CLASS (sym) == LOC_STATIC) - { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); - print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); - fflush (stream); - } - } -} - -/* Print on STREAM all the local variables in frame FRAME, - including all the blocks active in that frame - at its current pc. - - Returns 1 if the job was done, - or 0 if nothing was printed because we have no info - on the function running in FRAME. */ - -static int -print_frame_local_vars (frame, stream) - register FRAME frame; - register FILE *stream; -{ - register struct block *block; - - block = get_frame_block (frame); - if (block == 0) - return 0; - while (block != 0) - { - print_block_frame_locals (block, frame, stream); - /* After handling the function's top-level block, stop. - Don't continue to its superblock, the block of - per-file symbols. */ - if (BLOCK_FUNCTION (block)) - break; - block = BLOCK_SUPERBLOCK (block); - } - return 1; -} - -static void -locals_info () -{ - if (selected_frame == 0) - error(no_sel_frame); - print_frame_local_vars (selected_frame, stdout); -} - -static int -print_frame_arg_vars (frame, stream) - register FRAME frame; - register FILE *stream; -{ - struct symbol *func; - register struct block *b; - int nsyms; - register int i; - register struct symbol *sym; - - func = get_frame_function (frame); - if (func == 0) - return 0; - - b = SYMBOL_BLOCK_VALUE (func); - nsyms = BLOCK_NSYMS (b); - - for (i = 0; i < nsyms; i++) - { - sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG || SYMBOL_CLASS (sym) == LOC_REGPARM) - { - fprintf (stream, "%s = ", SYMBOL_NAME (sym)); - print_variable_value (sym, frame, stream); - fprintf (stream, "\n"); - fflush (stream); - } - } - - return 1; -} - -static void -args_info () -{ - if (selected_frame == 0) - error(no_sel_frame); - print_frame_arg_vars (selected_frame, stdout); -} - -/* Select frame FRAME, and note that its stack level is LEVEL. - LEVEL may be -1 if an actual level number is not known. */ - -void -select_frame (frame, level) - FRAME frame; - int level; -{ - selected_frame = frame; - selected_frame_level = level; -} - -/* Store the selected frame and its level into *FRAMEP and *LEVELP. */ - -void -record_selected_frame (frameaddrp, levelp) - FRAME_ADDR *frameaddrp; - int *levelp; -{ - *frameaddrp = FRAME_FP (selected_frame); - *levelp = selected_frame_level; -} - -/* Return the symbol-block in which the selected frame is executing. - Can return zero under various legitimate circumstances. */ - -struct block * -get_selected_block () -{ - if (!have_inferior_p () && !have_core_file_p ()) - return 0; - - if (!selected_frame) - return get_current_block (); - return get_frame_block (selected_frame); -} - -/* Find a frame a certain number of levels away from FRAME. - LEVEL_OFFSET_PTR points to an int containing the number of levels. - Positive means go to earlier frames (up); negative, the reverse. - The int that contains the number of levels is counted toward - zero as the frames for those levels are found. - If the top or bottom frame is reached, that frame is returned, - but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates - how much farther the original request asked to go. */ - -FRAME -find_relative_frame (frame, level_offset_ptr) - register FRAME frame; - register int* level_offset_ptr; -{ - register FRAME prev; - register FRAME frame1, frame2; - - if (frame == 0) - error (no_sel_frame); - /* Going up is simple: just do get_prev_frame enough times - or until initial frame is reached. */ - while (*level_offset_ptr > 0) - { - prev = get_prev_frame (frame); - if (prev == 0) - break; - (*level_offset_ptr)--; - frame = prev; - } - /* Going down could be done by iterating get_frame_info to - find the next frame, but that would be quadratic - since get_frame_info must scan all the way from the current frame. - The following algorithm is linear. */ - if (*level_offset_ptr < 0) - { - /* First put frame1 at innermost frame - and frame2 N levels up from there. */ - frame1 = get_current_frame (); - frame2 = frame1; - while (*level_offset_ptr < 0 && frame2 != frame) - { - frame2 = get_prev_frame (frame2); - (*level_offset_ptr) ++; - } - /* Then slide frame1 and frame2 up in synchrony - and when frame2 reaches our starting point - frame1 must be N levels down from there. */ - while (frame2 != frame) - { - frame1 = get_prev_frame (frame1); - frame2 = get_prev_frame (frame2); - } - return frame1; - } - return frame; -} - -/* The "frame" command. With no arg, print selected frame briefly. - With arg LEVEL_EXP, select the frame at level LEVEL if it is a - valid level. Otherwise, treat level_exp as an address expression - and print it. See parse_frame_specification for more info on proper - frame expressions. */ - -static void -frame_command (level_exp, from_tty) - char *level_exp; - int from_tty; -{ - register FRAME frame, frame1; - unsigned int level = 0; - - frame = parse_frame_specification (level_exp); - - for (frame1 = get_prev_frame (0); - frame1 && frame1 != frame; - frame1 = get_prev_frame (frame1)) - level++; - - if (!frame1) - level = 0; - - select_frame (frame, level); - - if (!from_tty) - return; - - print_stack_frame (selected_frame, selected_frame_level, 1); -} - -/* Select the frame up one or COUNT stack levels - from the previously selected frame, and print it briefly. */ - -static void -up_command (count_exp) - char *count_exp; -{ - register FRAME frame; - int count = 1, count1; - if (count_exp) - count = parse_and_eval_address (count_exp); - count1 = count; - - frame = find_relative_frame (selected_frame, &count1); - if (count1 != 0 && count_exp == 0) - error ("Initial frame selected; you cannot go up."); - select_frame (frame, selected_frame_level + count - count1); - - print_stack_frame (selected_frame, selected_frame_level, 1); -} - -/* Select the frame down one or COUNT stack levels - from the previously selected frame, and print it briefly. */ - -static void -down_command (count_exp) - char *count_exp; -{ - register FRAME frame; - int count = -1, count1; - if (count_exp) - count = - parse_and_eval_address (count_exp); - count1 = count; - - frame = find_relative_frame (selected_frame, &count1); - if (count1 != 0 && count_exp == 0) - error ("Bottom (i.e., innermost) frame selected; you cannot go down."); - select_frame (frame, selected_frame_level + count - count1); - - print_stack_frame (selected_frame, selected_frame_level, 1); -} - -static void -return_command (retval_exp, from_tty) - char *retval_exp; - int from_tty; -{ - struct symbol *thisfun = get_frame_function (selected_frame); - - /* If interactive, require confirmation. */ - - if (from_tty) - { - if (thisfun != 0) - { - if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun))) - error ("Not confirmed."); - } - else - if (!query ("Make selected stack frame return now? ")) - error ("Not confirmed."); - } - - /* Do the real work. Pop until the specified frame is current. */ - - while (selected_frame != get_current_frame ()) - POP_FRAME; - - /* Then pop that frame. */ - - POP_FRAME; - - /* Compute the return value (if any) and store in the place - for return values. */ - - if (retval_exp) - set_return_value (parse_and_eval (retval_exp)); - - /* If interactive, print the frame that is now current. */ - - if (from_tty) - frame_command ("0", 1); -} - -extern struct cmd_list_element *setlist; - -void -_initialize_stack () -{ -#if 0 - backtrace_limit = 30; -#endif - - add_com ("return", class_stack, return_command, - "Make selected stack frame return to its caller.\n\ -Control remains in the debugger, but when you continue\n\ -execution will resume in the frame above the one now selected.\n\ -If an argument is given, it is an expression for the value to return."); - - add_com ("up", class_stack, up_command, - "Select and print stack frame that called this one.\n\ -An argument says how many frames up to go."); - - add_com ("down", class_stack, down_command, - "Select and print stack frame called by this one.\n\ -An argument says how many frames down to go."); - add_com_alias ("do", "down", class_stack, 1); - - add_com ("frame", class_stack, frame_command, - "Select and print a stack frame.\n\ -With no argument, print the selected stack frame. (See also \"info frame\").\n\ -An argument specifies the frame to select.\n\ -It can be a stack frame number or the address of the frame.\n\ -With argument, nothing is printed if input is coming from\n\ -a command file or a user-defined command."); - - add_com_alias ("f", "frame", class_stack, 1); - - add_com ("backtrace", class_stack, backtrace_command, - "Print backtrace of all stack frames, or innermost COUNT frames.\n\ -With a negative argument, print outermost -COUNT frames."); - add_com_alias ("bt", "backtrace", class_stack, 0); - add_com_alias ("where", "backtrace", class_alias, 0); - add_info ("stack", backtrace_command, - "Backtrace of the stack, or innermost COUNT frames."); - add_info_alias ("s", "stack", 1); - add_info ("frame", frame_info, - "All about selected stack frame, or frame at ADDR."); - add_info_alias ("f", "frame", 1); - add_info ("locals", locals_info, - "Local variables of current stack frame."); - add_info ("args", args_info, - "Argument variables of current stack frame."); - -#if 0 - add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command, - "Specify maximum number of frames for \"backtrace\" to print by default.", - &setlist); - add_info ("backtrace-limit", backtrace_limit_info, - "The maximum number of frames for \"backtrace\" to print by default."); -#endif -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d2 1 -a2 1 - Copyright (C) 1986, 1987 Free Software Foundation, Inc. -d27 2 -d42 3 -d64 4 -d76 2 -d162 1 -a162 1 -void flush_cached_frames (); -d212 2 -d392 3 -d489 3 -a491 1 - register struct block *block = get_frame_block (frame); -d510 2 -d520 1 -a520 1 - struct symbol *func = get_frame_function (frame); -d526 1 -d551 2 -d610 2 -@ diff --git a/gdb/RCS/utils.c,v b/gdb/RCS/utils.c,v deleted file mode 100644 index 1d8000d..0000000 --- a/gdb/RCS/utils.c,v +++ /dev/null @@ -1,726 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.03.27.20.22.34; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.03.23.14.27.48; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@Portability changes. If USG, we need to re-enable the SIGINT -signal handler when it is called. Also, build the sys_siglist -table at runtime, based on the actual values of the signal -#define's. Too many USG systems added Berkeley signal names -as various numbers. -@ -text -@/* General utility routines for GDB, the GNU debugger. - Copyright (C) 1986 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include "defs.h" -#include "param.h" -#ifdef HAVE_TERMIO -#include <termio.h> -#endif - -void error (); -void fatal (); - -/* Chain of cleanup actions established with make_cleanup, - to be executed if an error happens. */ - -static struct cleanup *cleanup_chain; - -/* Nonzero means a quit has been requested. */ - -int quit_flag; - -/* Nonzero means quit immediately if Control-C is typed now, - rather than waiting until QUIT is executed. */ - -int immediate_quit; - -/* Add a new cleanup to the cleanup_chain, - and return the previous chain pointer - to be passed later to do_cleanups or discard_cleanups. - Args are FUNCTION to clean up with, and ARG to pass to it. */ - -struct cleanup * -make_cleanup (function, arg) - void (*function) (); - int arg; -{ - register struct cleanup *new - = (struct cleanup *) xmalloc (sizeof (struct cleanup)); - register struct cleanup *old_chain = cleanup_chain; - - new->next = cleanup_chain; - new->function = function; - new->arg = arg; - cleanup_chain = new; - - return old_chain; -} - -/* Discard cleanups and do the actions they describe - until we get back to the point OLD_CHAIN in the cleanup_chain. */ - -void -do_cleanups (old_chain) - register struct cleanup *old_chain; -{ - register struct cleanup *ptr; - while ((ptr = cleanup_chain) != old_chain) - { - (*ptr->function) (ptr->arg); - cleanup_chain = ptr->next; - free (ptr); - } -} - -/* Discard cleanups, not doing the actions they describe, - until we get back to the point OLD_CHAIN in the cleanup_chain. */ - -void -discard_cleanups (old_chain) - register struct cleanup *old_chain; -{ - register struct cleanup *ptr; - while ((ptr = cleanup_chain) != old_chain) - { - cleanup_chain = ptr->next; - free (ptr); - } -} - -/* Set the cleanup_chain to 0, and return the old cleanup chain. */ -struct cleanup * -save_cleanups () -{ - struct cleanup *old_chain = cleanup_chain; - - cleanup_chain = 0; - return old_chain; -} - -/* Restore the cleanup chain from a previously saved chain. */ -void -restore_cleanups (chain) - struct cleanup *chain; -{ - cleanup_chain = chain; -} - -/* This function is useful for cleanups. - Do - - foo = xmalloc (...); - old_chain = make_cleanup (free_current_contents, &foo); - - to arrange to free the object thus allocated. */ - -void -free_current_contents (location) - char **location; -{ - free (*location); -} - -/* Generally useful subroutines used throughout the program. */ - -/* Like malloc but get error if no storage available. */ - -char * -xmalloc (size) - long size; -{ - register char *val = (char *) malloc (size); - if (!val) - fatal ("virtual memory exhausted.", 0); - return val; -} - -/* Like realloc but get error if no storage available. */ - -char * -xrealloc (ptr, size) - char *ptr; - long size; -{ - register char *val = (char *) realloc (ptr, size); - if (!val) - fatal ("virtual memory exhausted.", 0); - return val; -} - -/* Print the system error message for errno, and also mention STRING - as the file name for which the error was encountered. - Then return to command level. */ - -void -perror_with_name (string) - char *string; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - extern int errno; - char *err; - char *combined; - - if (errno < sys_nerr) - err = sys_errlist[errno]; - else - err = "unknown error"; - - combined = (char *) alloca (strlen (err) + strlen (string) + 3); - strcpy (combined, string); - strcat (combined, ": "); - strcat (combined, err); - - error ("%s.", combined); -} - -/* Print the system error message for ERRCODE, and also mention STRING - as the file name for which the error was encountered. */ - -void -print_sys_errmsg (string, errcode) - char *string; - int errcode; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - char *err; - char *combined; - - if (errcode < sys_nerr) - err = sys_errlist[errcode]; - else - err = "unknown error"; - - combined = (char *) alloca (strlen (err) + strlen (string) + 3); - strcpy (combined, string); - strcat (combined, ": "); - strcat (combined, err); - - printf ("%s.\n", combined); -} - -void -quit () -{ - fflush (stdout); -#ifdef HAVE_TERMIO - ioctl (fileno (stdout), TCFLSH, 1); -#else /* not HAVE_TERMIO */ - ioctl (fileno (stdout), TIOCFLUSH, 0); -#endif /* not HAVE_TERMIO */ - -#ifdef TIOCGPGRP - error ("Quit"); -#else - error ("Quit (expect signal %d when inferior is resumed)", SIGINT); -#endif /* TIOCGPGRP */ -} - -/* Control C comes here */ - -void -request_quit () -{ - quit_flag = 1; - -#ifdef USG - /* Restore the signal handler */ - signal(SIGINT, request_quit); -#endif - - if (immediate_quit) - quit (); -} - -/* Print an error message and return to command level. - STRING is the error message, used as a fprintf string, - and ARG is passed as an argument to it. */ - -void -error (string, arg1, arg2, arg3) - char *string; - int arg1, arg2, arg3; -{ - fflush (stdout); - fprintf (stderr, string, arg1, arg2, arg3); - fprintf (stderr, "\n"); - return_to_top_level (); -} - -/* Print an error message and exit reporting failure. - This is for a error that we cannot continue from. - STRING and ARG are passed to fprintf. */ - -void -fatal (string, arg) - char *string; - int arg; -{ - fprintf (stderr, "gdb: "); - fprintf (stderr, string, arg); - fprintf (stderr, "\n"); - exit (1); -} - -/* Make a copy of the string at PTR with SIZE characters - (and add a null character at the end in the copy). - Uses malloc to get the space. Returns the address of the copy. */ - -char * -savestring (ptr, size) - char *ptr; - int size; -{ - register char *p = (char *) xmalloc (size + 1); - bcopy (ptr, p, size); - p[size] = 0; - return p; -} - -char * -concat (s1, s2, s3) - char *s1, *s2, *s3; -{ - register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1; - register char *val = (char *) xmalloc (len); - strcpy (val, s1); - strcat (val, s2); - strcat (val, s3); - return val; -} - -void -print_spaces (n, file) - register int n; - register FILE *file; -{ - while (n-- > 0) - fputc (' ', file); -} - -/* Ask user a y-or-n question and return 1 iff answer is yes. - Takes three args which are given to printf to print the question. - The first, a control string, should end in "? ". - It should not say how to answer, because we do that. */ - -int -query (ctlstr, arg1, arg2) - char *ctlstr; -{ - register int answer; - - /* Automatically answer "yes" if input is not from a terminal. */ - if (!input_from_terminal_p ()) - return 1; - - while (1) - { - printf (ctlstr, arg1, arg2); - printf ("(y or n) "); - fflush (stdout); - answer = fgetc (stdin); - clearerr (stdin); /* in case of C-d */ - if (answer != '\n') - while (fgetc (stdin) != '\n') clearerr (stdin); - if (answer >= 'a') - answer -= 040; - if (answer == 'Y') - return 1; - if (answer == 'N') - return 0; - printf ("Please answer y or n.\n"); - } -} - -/* Parse a C escape sequence. STRING_PTR points to a variable - containing a pointer to the string to parse. That pointer - is updated past the characters we use. The value of the - escape sequence is returned. - - A negative value means the sequence \ newline was seen, - which is supposed to be equivalent to nothing at all. - - If \ is followed by a null character, we return a negative - value and leave the string pointer pointing at the null character. - - If \ is followed by 000, we return 0 and leave the string pointer - after the zeros. A value of 0 does not mean end of string. */ - -int -parse_escape (string_ptr) - char **string_ptr; -{ - register int c = *(*string_ptr)++; - switch (c) - { - case 'a': - return '\a'; - case 'b': - return '\b'; - case 'e': - return 033; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - case 'v': - return '\v'; - case '\n': - return -2; - case 0: - (*string_ptr)--; - return 0; - case '^': - c = *(*string_ptr)++; - if (c == '\\') - c = parse_escape (string_ptr); - if (c == '?') - return 0177; - return (c & 0200) | (c & 037); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - register int i = c - '0'; - register int count = 0; - while (++count < 3) - { - if ((c = *(*string_ptr)++) >= '0' && c <= '7') - { - i *= 8; - i += c - '0'; - } - else - { - (*string_ptr)--; - break; - } - } - return i; - } - default: - return c; - } -} - -/* Print the character CH on STREAM as part of the contents - of a literal string whose delimiter is QUOTER. */ - -void -printchar (ch, stream, quoter) - unsigned char ch; - FILE *stream; - int quoter; -{ - register int c = ch; - if (c < 040 || c >= 0177) - { - if (c == '\n') - fprintf (stream, "\\n"); - else if (c == '\b') - fprintf (stream, "\\b"); - else if (c == '\t') - fprintf (stream, "\\t"); - else if (c == '\f') - fprintf (stream, "\\f"); - else if (c == '\r') - fprintf (stream, "\\r"); - else if (c == 033) - fprintf (stream, "\\e"); - else if (c == '\a') - fprintf (stream, "\\a"); - else - fprintf (stream, "\\%03o", c); - } - else - { - if (c == '\\' || c == quoter) - fputc ('\\', stream); - fputc (c, stream); - } -} - - -#ifdef USG -bcopy (from, to, count) -char *from, *to; -{ - memcpy (to, from, count); -} - -bcmp (from, to, count) -{ - return (memcmp (to, from, count)); -} - -bzero (to, count) -char *to; -{ - while (count--) - *to++ = 0; -} - -getwd (buf) -char *buf; -{ - getcwd (buf, MAXPATHLEN); -} - -char * -index (s, c) - char *s; -{ - char *strchr (); - return strchr (s, c); -} - -char * -rindex (s, c) - char *s; -{ - char *strrchr (); - return strrchr (s, c); -} - -/* Queue routines */ - -struct queue { - struct queue *forw; - struct queue *back; -}; - -insque (item, after) -struct queue *item; -struct queue *after; -{ - item->forw = after->forw; - after->forw->back = item; - - item->back = after; - after->forw = item; -} - -remque (item) -struct queue *item; -{ - item->forw->back = item->back; - item->back->forw = item->forw; -} - - -/* - * There is too much variation in Sys V signal numbers and names, so - * we must initialize them at runtime. If C provided a way to initialize - * an array based on subscript and value, this would not be necessary. - */ -static char undoc[] = "(undocumented)"; - -char *sys_siglist[NSIG]; - -_initialize_utils() -{ - int i; - - for (i = 0; i < NSIG; i++) - sys_siglist[i] = undoc; - -#ifdef SIGHUP - sys_siglist[SIGHUP ] = "SIGHUP"; -#endif -#ifdef SIGINT - sys_siglist[SIGINT ] = "SIGINT"; -#endif -#ifdef SIGQUIT - sys_siglist[SIGQUIT ] = "SIGQUIT"; -#endif -#ifdef SIGILL - sys_siglist[SIGILL ] = "SIGILL"; -#endif -#ifdef SIGTRAP - sys_siglist[SIGTRAP ] = "SIGTRAP"; -#endif -#ifdef SIGIOT - sys_siglist[SIGIOT ] = "SIGIOT"; -#endif -#ifdef SIGEMT - sys_siglist[SIGEMT ] = "SIGEMT"; -#endif -#ifdef SIGFPE - sys_siglist[SIGFPE ] = "SIGFPE"; -#endif -#ifdef SIGKILL - sys_siglist[SIGKILL ] = "SIGKILL"; -#endif -#ifdef SIGBUS - sys_siglist[SIGBUS ] = "SIGBUS"; -#endif -#ifdef SIGSEGV - sys_siglist[SIGSEGV ] = "SIGSEGV"; -#endif -#ifdef SIGSYS - sys_siglist[SIGSYS ] = "SIGSYS"; -#endif -#ifdef SIGPIPE - sys_siglist[SIGPIPE ] = "SIGPIPE"; -#endif -#ifdef SIGALRM - sys_siglist[SIGALRM ] = "SIGALRM"; -#endif -#ifdef SIGTERM - sys_siglist[SIGTERM ] = "SIGTERM"; -#endif -#ifdef SIGUSR1 - sys_siglist[SIGUSR1 ] = "SIGUSR1"; -#endif -#ifdef SIGUSR2 - sys_siglist[SIGUSR2 ] = "SIGUSR2"; -#endif -#ifdef SIGCLD - sys_siglist[SIGCLD ] = "SIGCLD"; -#endif -#ifdef SIGCHLD - sys_siglist[SIGCHLD ] = "SIGCHLD"; -#endif -#ifdef SIGPWR - sys_siglist[SIGPWR ] = "SIGPWR"; -#endif -#ifdef SIGTSTP - sys_siglist[SIGTSTP ] = "SIGTSTP"; -#endif -#ifdef SIGTTIN - sys_siglist[SIGTTIN ] = "SIGTTIN"; -#endif -#ifdef SIGTTOU - sys_siglist[SIGTTOU ] = "SIGTTOU"; -#endif -#ifdef SIGSTOP - sys_siglist[SIGSTOP ] = "SIGSTOP"; -#endif -#ifdef SIGXCPU - sys_siglist[SIGXCPU ] = "SIGXCPU"; -#endif -#ifdef SIGXFSZ - sys_siglist[SIGXFSZ ] = "SIGXFSZ"; -#endif -#ifdef SIGVTALRM - sys_siglist[SIGVTALRM ] = "SIGVTALRM"; -#endif -#ifdef SIGPROF - sys_siglist[SIGPROF ] = "SIGPROF"; -#endif -#ifdef SIGWINCH - sys_siglist[SIGWINCH ] = "SIGWINCH"; -#endif -#ifdef SIGCONT - sys_siglist[SIGCONT ] = "SIGCONT"; -#endif -#ifdef SIGURG - sys_siglist[SIGURG ] = "SIGURG"; -#endif -#ifdef SIGIO - sys_siglist[SIGIO ] = "SIGIO"; -#endif -#ifdef SIGWIND - sys_siglist[SIGWIND ] = "SIGWIND"; -#endif -#ifdef SIGPHONE - sys_siglist[SIGPHONE ] = "SIGPHONE"; -#endif -#ifdef SIGPOLL - sys_siglist[SIGPOLL ] = "SIGPOLL"; -#endif -} -#endif /* USG */ - -@ - - -1.1 -log -@Initial revision -@ -text -@d223 1 -d237 6 -a506 26 -char *sys_siglist[32] = { - "SIG0", - "SIGHUP", - "SIGINT", - "SIGQUIT", - "SIGILL", - "SIGTRAP", - "SIGIOT", - "SIGEMT", - "SIGFPE", - "SIGKILL", - "SIGBUS", - "SIGSEGV", - "SIGSYS", - "SIGPIPE", - "SIGALRM", - "SIGTERM", - "SIGUSR1", - "SIGUSR2", - "SIGCLD", - "SIGPWR", - "SIGWIND", - "SIGPHONE", - "SIGPOLL", -}; - -d530 124 -@ diff --git a/gdb/RCS/valprint.c,v b/gdb/RCS/valprint.c,v deleted file mode 100644 index 52d89b0..0000000 --- a/gdb/RCS/valprint.c,v +++ /dev/null @@ -1,1117 +0,0 @@ -head 1.3; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.3 -date 89.04.26.01.49.11; author gnu; state Exp; -branches ; -next 1.2; - -1.2 -date 89.04.26.00.57.15; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.16.40; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.3 -log -@Fix spelling Nan => NaN -@ -text -@/* Print values for GNU debugger gdb. - Copyright (C) 1986, 1988 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "value.h" - -/* Maximum number of chars to print for a string pointer value - or vector contents. */ - -static int print_max; - -static void type_print_varspec_suffix (); -static void type_print_varspec_prefix (); -static void type_print_base (); -static void type_print_method_args (); - - -char **unsigned_type_table; -char **signed_type_table; -char **float_type_table; - -/* Print the value VAL in C-ish syntax on stream STREAM. - FORMAT is a format-letter, or 0 for print in natural format of data type. - If the object printed is a string pointer, returns - the number of string bytes printed. */ - -int -value_print (val, stream, format) - value val; - FILE *stream; - char format; -{ - register int i, n, typelen; - - /* A "repeated" value really contains several values in a row. - They are made by the @@ operator. - Print such values as if they were arrays. */ - - if (VALUE_REPEATED (val)) - { - n = VALUE_REPETITIONS (val); - typelen = TYPE_LENGTH (VALUE_TYPE (val)); - fputc ('{', stream); - /* Print arrays of characters using string syntax. */ - if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT - && format == 0) - { - fputc ('"', stream); - for (i = 0; i < n && i < print_max; i++) - { - QUIT; - printchar (VALUE_CONTENTS (val)[i], stream, '"'); - } - if (i < n) - fprintf (stream, "..."); - fputc ('"', stream); - } - else - { - for (i = 0; i < n && i < print_max; i++) - { - if (i) - fprintf (stream, ", "); - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, - stream, format, 1); - } - if (i < n) - fprintf (stream, "..."); - } - fputc ('}', stream); - return n * typelen; - } - else - { - /* If it is a pointer, indicate what it points to. - - Print type also if it is a reference. - - C++: if it is a member pointer, we will take care - of that when we print it. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR - || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF) - { - fprintf (stream, "("); - type_print (VALUE_TYPE (val), "", stream, -1); - fprintf (stream, ") "); - } - return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, 1); - } -} - -/* Print data of type TYPE located at VALADDR (within GDB), - which came from the inferior at address ADDRESS, - onto stdio stream STREAM according to FORMAT - (a letter or 0 for natural format). - - If the data are a string pointer, returns the number of - sting characters printed. - - if DEREF_REF is nonzero, then dereference references, - otherwise just print them like pointers. */ - -int -val_print (type, valaddr, address, stream, format, deref_ref) - struct type *type; - char *valaddr; - CORE_ADDR address; - FILE *stream; - char format; - int deref_ref; -{ - register int i; - int len, n_baseclasses; - struct type *elttype; - int eltlen; - LONGEST val; - unsigned char c; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - if (TYPE_LENGTH (type) >= 0) - { - elttype = TYPE_TARGET_TYPE (type); - eltlen = TYPE_LENGTH (elttype); - len = TYPE_LENGTH (type) / eltlen; - fprintf (stream, "{"); - /* For an array of chars, print with string syntax. */ - if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0) - { - fputc ('"', stream); - for (i = 0; i < len && i < print_max; i++) - { - QUIT; - printchar (valaddr[i], stream, '"'); - } - if (i < len) - fprintf (stream, "..."); - fputc ('"', stream); - } - else - { - for (i = 0; i < len && i < print_max; i++) - { - if (i) fprintf (stream, ", "); - val_print (elttype, valaddr + i * eltlen, - 0, stream, format, deref_ref); - } - if (i < len) - fprintf (stream, "..."); - } - fprintf (stream, "}"); - break; - } - /* Array of unspecified length: treat like pointer. */ - - case TYPE_CODE_PTR: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) - { - struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); - struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); - struct fn_field *f; - int j, len2; - char *kind = ""; - - val = unpack_long (builtin_type_int, valaddr); - if (TYPE_CODE (target) == TYPE_CODE_FUNC) - { - if (val < 128) - { - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (TYPE_FN_FIELD_VOFFSET (f, j) == val) - { - kind = "virtual"; - goto common; - } - } - } - } - else - { - struct symbol *sym = find_pc_function ((CORE_ADDR) val); - if (sym == 0) - error ("invalid pointer to member function"); - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) - goto common; - } - } - } - common: - if (i < len) - { - fputc ('&', stream); - type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); - fprintf (stream, kind); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (domain, i), stream); - break; - } - } - else - { - /* VAL is a byte offset into the structure type DOMAIN. - Find the name of the field for that offset and - print it. */ - int extra = 0; - int bits = 0; - len = TYPE_NFIELDS (domain); - val <<= 3; /* @@@@ Make VAL into bit offset */ - for (i = 0; i < len; i++) - { - int bitpos = TYPE_FIELD_BITPOS (domain, i); - QUIT; - if (val == bitpos) - break; - if (val < bitpos && i > 0) - { - int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); - /* Somehow pointing into a field. */ - i -= 1; - extra = (val - TYPE_FIELD_BITPOS (domain, i)); - if (extra & 0x3) - bits = 1; - else - extra >>= 3; - break; - } - } - if (i < len) - { - fputc ('&', stream); - type_print_base (domain, stream, 0, 0); - fprintf (stream, "::"); - fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); - if (extra) - fprintf (stream, " + %d bytes", extra); - if (bits) - fprintf (stream, " (offset in bits)"); - break; - } - } - fputc ('(', stream); - type_print (type, "", stream, -1); - fprintf (stream, ") %d", val >> 3); - } - else - { - fprintf (stream, "0x%x", * (int *) valaddr); - /* For a pointer to char or unsigned char, - also print the string pointed to, unless pointer is null. */ - - /* For an array of chars, print with string syntax. */ - elttype = TYPE_TARGET_TYPE (type); - i = 0; /* Number of characters printed. */ - if (TYPE_LENGTH (elttype) == 1 - && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0 - /* Convex needs this typecast to a long */ - && (long) unpack_long (type, valaddr) != 0 - && print_max) - { - fputc (' ', stream); - - /* Get first character. */ - if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr), - &c, 1)) - { - /* First address out of bounds. */ - fprintf (stream, "<Address 0x%x out of bounds>", - (* (int *) valaddr)); - break; - } - else - { - /* A real string. */ - int out_of_bounds = 0; - - fputc ('"', stream); - while (c) - { - QUIT; - printchar (c, stream, '"'); - if (++i >= print_max) - break; - if (read_memory ((CORE_ADDR) unpack_long (type, valaddr) - + i, &c, 1)) - { - /* This address was out of bounds. */ - fprintf (stream, - "\"*** <Address 0x%x out of bounds>", - (* (int *) valaddr) + i); - out_of_bounds = 1; - break; - } - } - if (!out_of_bounds) - { - fputc ('"', stream); - if (i == print_max) - fprintf (stream, "..."); - } - } - fflush (stream); - } - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return i + (print_max && i != print_max); - } - break; - - case TYPE_CODE_MEMBER: - error ("not implemented: member type in val_print"); - break; - - case TYPE_CODE_REF: - fprintf (stream, "(0x%x &) = ", * (int *) valaddr); - /* De-reference the reference. */ - if (deref_ref) - { - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) - { - value val = value_at (TYPE_TARGET_TYPE (type), * (int *) valaddr); - val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, deref_ref); - } - else - fprintf (stream, "???"); - } - break; - - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - n_baseclasses = TYPE_N_BASECLASSES (type); - for (i = 1; i <= n_baseclasses; i++) - { - fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i))); - val_print (TYPE_FIELD_TYPE (type, 0), - valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8, - 0, stream, 0, 0); - } - if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type)); - for (i -= 1; i < len; i++) - { - if (i > n_baseclasses) fprintf (stream, ", "); - fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); - /* check if static field */ - if (TYPE_FIELD_STATIC (type, i)) - { - value v; - - v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); - val_print (TYPE_FIELD_TYPE (type, i), - VALUE_CONTENTS (v), 0, stream, format, deref_ref); - } - else if (TYPE_FIELD_PACKED (type, i)) - { - val = unpack_field_as_long (type, valaddr, i); - val_print (TYPE_FIELD_TYPE (type, i), &val, 0, - stream, format, deref_ref); - } - else - { - val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format, deref_ref); - } - } - fprintf (stream, "}"); - break; - - case TYPE_CODE_ENUM: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - len = TYPE_NFIELDS (type); - val = (long) unpack_long (builtin_type_int, valaddr); - for (i = 0; i < len; i++) - { - QUIT; - if (val == TYPE_FIELD_BITPOS (type, i)) - break; - } - if (i < len) - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); - else - fprintf (stream, "%d", val); - break; - - case TYPE_CODE_FUNC: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - fprintf (stream, "{"); - type_print (type, "", stream, -1); - fprintf (stream, "} "); - fprintf (stream, "0x%x", address); - break; - - case TYPE_CODE_INT: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - fprintf (stream, - TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); - if (TYPE_LENGTH (type) == 1) - { - fprintf (stream, " '"); - printchar ((unsigned char) unpack_long (type, valaddr), - stream, '\''); - fputc ('\'', stream); - } - break; - - case TYPE_CODE_FLT: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - /* FIXME: When printing NaNs or invalid floats, print them - in raw hex in addition to the message. */ -#ifdef IEEE_FLOAT - if (is_nan ((void *)valaddr, TYPE_LENGTH(type))) - { - fprintf (stream, "NaN"); - break; - } -#endif - { - double doub; - int inv; - - doub = unpack_double (type, valaddr, &inv); - if (inv) - fprintf (stream, "Invalid float value"); - else - fprintf (stream, TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub); - } - break; - - case TYPE_CODE_VOID: - fprintf (stream, "void"); - break; - - default: - error ("Invalid type code in symbol table."); - } - fflush (stream); -} - -#ifdef IEEE_FLOAT - -/* Nonzero if ARG (a double) is a NAN. */ - -int -is_nan (fp, len) - void *fp; - int len; -{ - int lowhalf, highhalf; - union ieee { - long i[2]; /* ASSUMED 32 BITS */ - float f; /* ASSUMED 32 BITS */ - double d; /* ASSUMED 64 BITS */ - } *arg; - - arg = (union ieee *)fp; - - /* - * Single precision float. - */ - if (len == sizeof(long)) { - highhalf = arg->i[0]; - return ((((highhalf >> 23) & 0xFF) == 0xFF) - && 0 != (highhalf & 0x7FFFFF)); - } - - /* Separate the high and low words of the double. - Distinguish big and little-endian machines. */ -#ifdef WORDS_BIG_ENDIAN - lowhalf = arg->i[1], highhalf = arg->i[0]; -#else - lowhalf = arg->i[0], highhalf = arg->i[1]; -#endif - - /* Nan: exponent is the maximum possible, and fraction is nonzero. */ - return (((highhalf>>20) & 0x7ff) == 0x7ff - && - ! ((highhalf & 0xfffff == 0) && (lowhalf == 0))); -} -#endif - -/* Print a description of a type TYPE - in the form of a declaration of a variable named VARSTRING. - Output goes to STREAM (via stdio). - If SHOW is positive, we show the contents of the outermost level - of structure even if there is a type name that could be used instead. - If SHOW is negative, we never show the details of elements' types. */ - -void -type_print (type, varstring, stream, show) - struct type *type; - char *varstring; - FILE *stream; - int show; -{ - type_print_1 (type, varstring, stream, show, 0); -} - -/* LEVEL is the depth to indent lines by. */ - -void -type_print_1 (type, varstring, stream, show, level) - struct type *type; - char *varstring; - FILE *stream; - int show; - int level; -{ - register enum type_code code; - type_print_base (type, stream, show, level); - code = TYPE_CODE (type); - if ((varstring && *varstring) - || - /* Need a space if going to print stars or brackets; - but not if we will print just a type name. */ - ((show > 0 || TYPE_NAME (type) == 0) - && - (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC - || code == TYPE_CODE_ARRAY - || code == TYPE_CODE_MEMBER - || code == TYPE_CODE_REF))) - fprintf (stream, " "); - type_print_varspec_prefix (type, stream, show, 0); - fprintf (stream, "%s", varstring); - type_print_varspec_suffix (type, stream, show, 0); -} - -/* Print the method arguments ARGS to the file STREAM. */ -static void -type_print_method_args (args, prefix, varstring, stream) - struct type **args; - char *prefix, *varstring; - FILE *stream; -{ - int i; - - fprintf (stream, " %s%s (", prefix, varstring); - if (args[1] && args[1]->code != TYPE_CODE_VOID) - { - i = 1; /* skip the class variable */ - while (1) - { - type_print (args[i++], "", stream, 0); - if (!args[i]) - { - fprintf (stream, " ..."); - break; - } - else if (args[i]->code != TYPE_CODE_VOID) - { - fprintf (stream, ", "); - } - else break; - } - } - fprintf (stream, ")"); -} - -/* If TYPE is a derived type, then print out derivation - information. Print out all layers of the type heirarchy - until we encounter one with multiple inheritance. - At that point, print out that ply, and return. */ -static void -type_print_derivation_info (stream, type) - FILE *stream; - struct type *type; -{ - char *name; - int i, n_baseclasses = TYPE_N_BASECLASSES (type); - struct type *basetype = 0; - - while (type && n_baseclasses == 1) - { - basetype = TYPE_BASECLASS (type, 1); - if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) - { - while (*name != ' ') name++; - fprintf (stream, ": %s%s %s ", - TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); - } - n_baseclasses = TYPE_N_BASECLASSES (basetype); - type = basetype; - } - - if (type) - { - if (n_baseclasses != 0) - fprintf (stream, ": "); - for (i = 1; i <= n_baseclasses; i++) - { - basetype = TYPE_BASECLASS (type, i); - if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) - { - while (*name != ' ') name++; - fprintf (stream, "%s%s %s", - TYPE_VIA_PUBLIC (basetype) ? "public" : "private", - TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", - name + 1); - } - if (i < n_baseclasses) - fprintf (stream, ", "); - } - putc (' ', stream); - } -} - -/* Print any asterisks or open-parentheses needed before the - variable name (to describe its type). - - On outermost call, pass 0 for PASSED_A_PTR. - On outermost call, SHOW > 0 means should ignore - any typename for TYPE and show its details. - SHOW is always zero on recursive calls. */ - -static void -type_print_varspec_prefix (type, stream, show, passed_a_ptr) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; -{ - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_PTR: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('*', stream); - break; - - case TYPE_CODE_MEMBER: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fputc (' ', stream); - type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, - passed_a_ptr); - fprintf (stream, "::"); - break; - - case TYPE_CODE_REF: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fputc ('&', stream); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - if (passed_a_ptr) - fputc ('(', stream); - break; - - case TYPE_CODE_ARRAY: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - } -} - -/* Print any array sizes, function arguments or close parentheses - needed after the variable name (to describe its type). - Args work like type_print_varspec_prefix. */ - -static void -type_print_varspec_suffix (type, stream, show, passed_a_ptr) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; -{ - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - fprintf (stream, "["); - if (TYPE_LENGTH (type) >= 0 - && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) - fprintf (stream, "%d", - TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type))); - fprintf (stream, "]"); - break; - - case TYPE_CODE_MEMBER: - if (passed_a_ptr) - fputc (')', stream); - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); - break; - - case TYPE_CODE_PTR: - case TYPE_CODE_REF: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr); - if (passed_a_ptr) - fprintf (stream, ")"); - fprintf (stream, "()"); - break; - } -} - -/* Print the name of the type (or the ultimate pointer target, - function value or array element), or the description of a - structure or union. - - SHOW nonzero means don't print this type as just its name; - show its real definition even if it has a name. - SHOW zero means print just typename or struct tag if there is one - SHOW negative means abbreviate structure elements. - SHOW is decremented for printing of structure elements. - - LEVEL is the depth to indent by. - We increase it for some recursive calls. */ - -static void -type_print_base (type, stream, show, level) - struct type *type; - FILE *stream; - int show; - int level; -{ - char *name; - register int i; - register int len; - register int lastval; - - QUIT; - - if (type == 0) - { - fprintf (stream, "type unknown"); - return; - } - - if (TYPE_NAME (type) && show <= 0) - { - fprintf (stream, TYPE_NAME (type)); - return; - } - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - case TYPE_CODE_PTR: - case TYPE_CODE_MEMBER: - case TYPE_CODE_REF: - case TYPE_CODE_FUNC: - type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); - break; - - case TYPE_CODE_STRUCT: - fprintf (stream, "struct "); - goto struct_union; - - case TYPE_CODE_UNION: - fprintf (stream, "union "); - struct_union: - if (TYPE_NAME (type) && (name = TYPE_NAME (type))) - { - while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); - } - if (show < 0) - fprintf (stream, "{...}"); - else - { - int i; - - type_print_derivation_info (stream, type); - - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - if (len) fprintf (stream, "\n"); - else fprintf (stream, "<no data fields>\n"); - - /* If there is a base class for this type, - do not print the field that it occupies. */ - for (i = TYPE_N_BASECLASSES (type); i < len; i++) - { - QUIT; - /* Don't print out virtual function table. */ - if (! strncmp (TYPE_FIELD_NAME (type, i), - "_vptr$", 6)) - continue; - - print_spaces (level + 4, stream); - if (TYPE_FIELD_STATIC (type, i)) - { - fprintf (stream, "static "); - } - type_print_1 (TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_NAME (type, i), - stream, show - 1, level + 4); - if (!TYPE_FIELD_STATIC (type, i) - && TYPE_FIELD_PACKED (type, i)) - { - /* ??? don't know what to put here ??? */; - } - fprintf (stream, ";\n"); - } - - /* C++: print out the methods */ - len = TYPE_NFN_FIELDS (type); - if (len) fprintf (stream, "\n"); - for (i = 0; i < len; i++) - { - struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); - int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); - - for (j = 0; j < len2; j++) - { - QUIT; - print_spaces (level + 4, stream); - if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - fprintf (stream, "virtual "); - type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (type, i), stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (type, i), stream); - - fprintf (stream, ";\n"); - } - if (len2) fprintf (stream, "\n"); - } - - print_spaces (level, stream); - fputc ('}', stream); - } - break; - - case TYPE_CODE_ENUM: - fprintf (stream, "enum "); - if (TYPE_NAME (type)) - { - name = TYPE_NAME (type); - while (*name != ' ') name++; - fprintf (stream, "%s ", name + 1); - } - if (show < 0) - fprintf (stream, "{...}"); - else - { - fprintf (stream, "{"); - len = TYPE_NFIELDS (type); - lastval = 0; - for (i = 0; i < len; i++) - { - QUIT; - if (i) fprintf (stream, ", "); - fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); - if (lastval != TYPE_FIELD_BITPOS (type, i)) - { - fprintf (stream, " : %d", TYPE_FIELD_BITPOS (type, i)); - lastval = TYPE_FIELD_BITPOS (type, i); - } - lastval++; - } - fprintf (stream, "}"); - } - break; - - case TYPE_CODE_INT: - if (TYPE_UNSIGNED (type)) - name = unsigned_type_table[TYPE_LENGTH (type)]; - else - name = signed_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); - break; - - case TYPE_CODE_FLT: - name = float_type_table[TYPE_LENGTH (type)]; - fprintf (stream, "%s", name); - break; - - case TYPE_CODE_VOID: - fprintf (stream, "void"); - break; - - case 0: - fprintf (stream, "struct unknown"); - break; - - default: - error ("Invalid type code in symbol table."); - } -} - -static void -set_maximum_command (arg) - char *arg; -{ - if (!arg) error_no_arg ("value for maximum elements to print"); - print_max = atoi (arg); -} - -extern struct cmd_list_element *setlist; - -void -_initialize_valprint () -{ - add_cmd ("array-max", class_vars, set_maximum_command, - "Set NUMBER as limit on string chars or array elements to print.", - &setlist); - - print_max = 200; - - unsigned_type_table - = (char **) xmalloc ((1 + sizeof (unsigned LONGEST)) * sizeof (char *)); - bzero (unsigned_type_table, (1 + sizeof (unsigned LONGEST))); - unsigned_type_table[sizeof (unsigned char)] = "unsigned char"; - unsigned_type_table[sizeof (unsigned short)] = "unsigned short"; - unsigned_type_table[sizeof (unsigned long)] = "unsigned long"; - unsigned_type_table[sizeof (unsigned int)] = "unsigned int"; -#ifdef LONG_LONG - unsigned_type_table[sizeof (unsigned long long)] = "unsigned long long"; -#endif - - signed_type_table - = (char **) xmalloc ((1 + sizeof (LONGEST)) * sizeof (char *)); - bzero (signed_type_table, (1 + sizeof (LONGEST))); - signed_type_table[sizeof (char)] = "char"; - signed_type_table[sizeof (short)] = "short"; - signed_type_table[sizeof (long)] = "long"; - signed_type_table[sizeof (int)] = "int"; -#ifdef LONG_LONG - signed_type_table[sizeof (long long)] = "long long"; -#endif - - float_type_table - = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *)); - bzero (float_type_table, (1 + sizeof (double))); - float_type_table[sizeof (float)] = "float"; - float_type_table[sizeof (double)] = "double"; -} - -@ - - -1.2 -log -@(1) Use XXX_BIG_ENDIAN macros rather than testing at runtime. -(2) Change args to is_nan, support floats, change one call to it. -(3) Change args to unpack_double. -@ -text -@d488 1 -a488 1 - fprintf (stream, "Nan"); -@ - - -1.1 -log -@Initial revision -@ -text -@d483 2 -d486 1 -a486 1 - if (is_nan (unpack_double (type, valaddr))) -d492 10 -a501 4 - if (TYPE_LENGTH (type) <= 4) - fprintf (stream, "%.6g", unpack_double (type, valaddr)); - else - fprintf (stream, "%.16g", unpack_double (type, valaddr)); -a515 5 -union ieee { - int i[2]; - double d; -}; - -d519 3 -a521 2 -is_nan (arg) - union ieee arg; -d524 16 -a539 1 - union { int i; char c; } test; -d543 5 -a547 6 - test.i = 1; - if (test.c != 1) - /* Big-endian machine */ - lowhalf = arg.i[1], highhalf = arg.i[0]; - else - lowhalf = arg.i[0], highhalf = arg.i[1]; -@ diff --git a/gdb/RCS/values.c,v b/gdb/RCS/values.c,v deleted file mode 100644 index bc32f31..0000000 --- a/gdb/RCS/values.c,v +++ /dev/null @@ -1,1047 +0,0 @@ -head 1.2; -access ; -symbols ; -locks ; strict; -comment @ * @; - - -1.2 -date 89.04.26.01.05.45; author gnu; state Exp; -branches ; -next 1.1; - -1.1 -date 89.04.25.15.38.44; author gnu; state Exp; -branches ; -next ; - - -desc -@@ - - -1.2 -log -@(1) use XXX_BIG_ENDIAN macros rather than runtime tests. -(2) Invalid values aren't stored in the value history, but they do -not cause an error; a -1 is returned as their value index. -(3) unpack_double takes a new arg, and callers check it. -@ -text -@ -/* Low level packing and unpacking of values for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. - -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. - -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. - -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ - -#include <stdio.h> -#include "defs.h" -#include "param.h" -#include "symtab.h" -#include "value.h" - -/* The value-history records all the values printed - by print commands during this session. Each chunk - records 60 consecutive values. The first chunk on - the chain records the most recent values. - The total number of values is in value_history_count. */ - -#define VALUE_HISTORY_CHUNK 60 - -struct value_history_chunk -{ - struct value_history_chunk *next; - value values[VALUE_HISTORY_CHUNK]; -}; - -/* Chain of chunks now in use. */ - -static struct value_history_chunk *value_history_chain; - -static int value_history_count; /* Abs number of last entry stored */ - - -/* List of all value objects currently allocated - (except for those released by calls to release_value) - This is so they can be freed after each command. */ - -static value all_values; - -/* Allocate a value that has the correct length for type TYPE. */ - -value -allocate_value (type) - struct type *type; -{ - register value val; - - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type)); - VALUE_NEXT (val) = all_values; - all_values = val; - VALUE_TYPE (val) = type; - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME (val) = 0; - VALUE_OFFSET (val) = 0; - VALUE_BITPOS (val) = 0; - VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 0; - VALUE_REPETITIONS (val) = 0; - VALUE_REGNO (val) = -1; - return val; -} - -/* Allocate a value that has the correct length - for COUNT repetitions type TYPE. */ - -value -allocate_repeat_value (type, count) - struct type *type; - int count; -{ - register value val; - - val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count); - VALUE_NEXT (val) = all_values; - all_values = val; - VALUE_TYPE (val) = type; - VALUE_LVAL (val) = not_lval; - VALUE_ADDRESS (val) = 0; - VALUE_FRAME (val) = 0; - VALUE_OFFSET (val) = 0; - VALUE_BITPOS (val) = 0; - VALUE_BITSIZE (val) = 0; - VALUE_REPEATED (val) = 1; - VALUE_REPETITIONS (val) = count; - VALUE_REGNO (val) = -1; - return val; -} - -/* Free all the values that have been allocated (except for those released). - Called after each command, successful or not. */ - -void -free_all_values () -{ - register value val, next; - - for (val = all_values; val; val = next) - { - next = VALUE_NEXT (val); - free (val); - } - - all_values = 0; -} - -/* Remove VAL from the chain all_values - so it will not be freed automatically. */ - -void -release_value (val) - register value val; -{ - register value v; - - if (all_values == val) - { - all_values = val->next; - return; - } - - for (v = all_values; v; v = v->next) - { - if (v->next == val) - { - v->next = val->next; - break; - } - } -} - -/* Return a copy of the value ARG. - It contains the same contents, for same memory address, - but it's a different block of storage. */ - -static value -value_copy (arg) - value arg; -{ - register value val; - register struct type *type = VALUE_TYPE (arg); - if (VALUE_REPEATED (arg)) - val = allocate_repeat_value (type, VALUE_REPETITIONS (arg)); - else - val = allocate_value (type); - VALUE_LVAL (val) = VALUE_LVAL (arg); - VALUE_ADDRESS (val) = VALUE_ADDRESS (arg); - VALUE_OFFSET (val) = VALUE_OFFSET (arg); - VALUE_BITPOS (val) = VALUE_BITPOS (arg); - VALUE_BITSIZE (val) = VALUE_BITSIZE (arg); - VALUE_REGNO (val) = VALUE_REGNO (arg); - bcopy (VALUE_CONTENTS (arg), VALUE_CONTENTS (val), - TYPE_LENGTH (VALUE_TYPE (arg)) - * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1)); - return val; -} - -/* Access to the value history. */ - -/* Record a new value in the value history. - Returns the absolute history index of the entry. */ - -int -record_latest_value (val) - value val; -{ - int i; - double foo; - - /* Check error now if about to store an invalid float. We return -1 - to the caller, but allow them to continue, e.g. to print it as "Nan". */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) { - foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i); - if (i) return -1; /* Indicate value not saved in history */ - } - - /* Here we treat value_history_count as origin-zero - and applying to the value being stored now. */ - - i = value_history_count % VALUE_HISTORY_CHUNK; - if (i == 0) - { - register struct value_history_chunk *new - = (struct value_history_chunk *) xmalloc (sizeof (struct value_history_chunk)); - bzero (new->values, sizeof new->values); - new->next = value_history_chain; - value_history_chain = new; - } - - value_history_chain->values[i] = val; - release_value (val); - - /* Now we regard value_history_count as origin-one - and applying to the value just stored. */ - - return ++value_history_count; -} - -/* Return a copy of the value in the history with sequence number NUM. */ - -value -access_value_history (num) - int num; -{ - register struct value_history_chunk *chunk; - register int i; - register int absnum = num; - - if (absnum <= 0) - absnum += value_history_count; - - if (absnum <= 0) - { - if (num == 0) - error ("The history is empty."); - else if (num == 1) - error ("There is only one value in the history."); - else - error ("History does not go back to $$%d.", -num); - } - if (absnum > value_history_count) - error ("History has not yet reached $%d.", absnum); - - absnum--; - - /* Now absnum is always absolute and origin zero. */ - - chunk = value_history_chain; - for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK; - i > 0; i--) - chunk = chunk->next; - - return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]); -} - -/* Clear the value history entirely. - Must be done when new symbol tables are loaded, - because the type pointers become invalid. */ - -void -clear_value_history () -{ - register struct value_history_chunk *next; - register int i; - register value val; - - while (value_history_chain) - { - for (i = 0; i < VALUE_HISTORY_CHUNK; i++) - if (val = value_history_chain->values[i]) - free (val); - next = value_history_chain->next; - free (value_history_chain); - value_history_chain = next; - } - value_history_count = 0; -} - -static void -history_info (num_exp) - char *num_exp; -{ - register int i; - register value val; - register int num; - - if (num_exp) - num = parse_and_eval_address (num_exp) - 5; - else - num = value_history_count - 9; - - if (num <= 0) - num = 1; - - for (i = num; i < num + 10 && i <= value_history_count; i++) - { - val = access_value_history (i); - printf ("$%d = ", i); - value_print (val, stdout, 0); - printf ("\n"); - } -} - -/* Internal variables. These are variables within the debugger - that hold values assigned by debugger commands. - The user refers to them with a '$' prefix - that does not appear in the variable names stored internally. */ - -static struct internalvar *internalvars; - -/* Look up an internal variable with name NAME. NAME should not - normally include a dollar sign. - - If the specified internal variable does not exist, - one is created, with a void value. */ - -struct internalvar * -lookup_internalvar (name) - char *name; -{ - register struct internalvar *var; - - for (var = internalvars; var; var = var->next) - if (!strcmp (var->name, name)) - return var; - - var = (struct internalvar *) xmalloc (sizeof (struct internalvar)); - var->name = concat (name, "", ""); - var->value = allocate_value (builtin_type_void); - release_value (var->value); - var->next = internalvars; - internalvars = var; - return var; -} - -value -value_of_internalvar (var) - struct internalvar *var; -{ - register value val = value_copy (var->value); - VALUE_LVAL (val) = lval_internalvar; - VALUE_INTERNALVAR (val) = var; - return val; -} - -void -set_internalvar_component (var, offset, bitpos, bitsize, newval) - struct internalvar *var; - int offset, bitpos, bitsize; - value newval; -{ - register char *addr = VALUE_CONTENTS (var->value) + offset; - if (bitsize) - modify_field (addr, (int) value_as_long (newval), - bitpos, bitsize); - else - bcopy (VALUE_CONTENTS (newval), addr, - TYPE_LENGTH (VALUE_TYPE (newval))); -} - -void -set_internalvar (var, val) - struct internalvar *var; - value val; -{ - free (var->value); - var->value = value_copy (val); - release_value (var->value); -} - -char * -internalvar_name (var) - struct internalvar *var; -{ - return var->name; -} - -/* Free all internalvars. Done when new symtabs are loaded, - because that makes the values invalid. */ - -void -clear_internalvars () -{ - register struct internalvar *var; - - while (internalvars) - { - var = internalvars; - internalvars = var->next; - free (var->name); - free (var->value); - free (var); - } -} - -static void -convenience_info () -{ - register struct internalvar *var; - - if (internalvars) - printf ("Debugger convenience variables:\n\n"); - else - printf ("No debugger convenience variables now defined.\n\ -Convenience variables have names starting with \"$\";\n\ -use \"set\" as in \"set $foo = 5\" to define them.\n"); - - for (var = internalvars; var; var = var->next) - { - printf ("$%s: ", var->name); - value_print (var->value, stdout, 0); - printf ("\n"); - } -} - -/* Extract a value as a C number (either long or double). - Knows how to convert fixed values to double, or - floating values to long. - Does not deallocate the value. */ - -LONGEST -value_as_long (val) - register value val; -{ - return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val)); -} - -double -value_as_double (val) - register value val; -{ - double foo; - int inv; - - foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv); - if (inv) - error ("Invalid floating value found in program."); - return foo; -} - -/* Unpack raw data (copied from debugee) at VALADDR - as a long, or as a double, assuming the raw data is described - by type TYPE. Knows how to convert different sizes of values - and can convert between fixed and floating point. - - C++: It is assumed that the front-end has taken care of - all matters concerning pointers to members. A pointer - to member which reaches here is considered to be equivalent - to an INT (or some size). After all, it is only an offset. */ - -LONGEST -unpack_long (type, valaddr) - struct type *type; - char *valaddr; -{ - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - register int nosign = TYPE_UNSIGNED (type); - - if (code == TYPE_CODE_ENUM) - code = TYPE_CODE_INT; - if (code == TYPE_CODE_FLT) - { - if (len == sizeof (float)) - return * (float *) valaddr; - - if (len == sizeof (double)) - return * (double *) valaddr; - } - else if (code == TYPE_CODE_INT && nosign) - { - if (len == sizeof (char)) - return * (unsigned char *) valaddr; - - if (len == sizeof (short)) - return * (unsigned short *) valaddr; - - if (len == sizeof (int)) - return * (unsigned int *) valaddr; - - if (len == sizeof (long)) - return * (unsigned long *) valaddr; - } - else if (code == TYPE_CODE_INT) - { - if (len == sizeof (char)) - return * (char *) valaddr; - - if (len == sizeof (short)) - return * (short *) valaddr; - - if (len == sizeof (int)) - return * (int *) valaddr; - - if (len == sizeof (long)) - return * (long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (long long *) valaddr; -#endif - } - else if (code == TYPE_CODE_PTR - || code == TYPE_CODE_REF) - { - if (len == sizeof (char *)) - return (CORE_ADDR) * (char **) valaddr; - } - else if (code == TYPE_CODE_MEMBER) - error ("not implemented: member types in unpack_long"); - - error ("Value not integer or pointer."); -} - -/* Return a double value from the specified type and address. - * INVP points to an int which is set to 0 for valid value, - * 1 for invalid value (bad float format). In either case, - * the returned double is OK to use. */ - -double -unpack_double (type, valaddr, invp) - struct type *type; - char *valaddr; - int *invp; -{ - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - register int nosign = TYPE_UNSIGNED (type); - - *invp = 0; /* Assume valid */ - if (code == TYPE_CODE_FLT) - { - if (INVALID_FLOAT (valaddr, len)) { - *invp = 1; - return 1.234567891011121314; - } - - if (len == sizeof (float)) - return * (float *) valaddr; - - if (len == sizeof (double)) - { - /* Some machines require doubleword alignment for doubles. - This code works on them, and on other machines. */ - double temp; - bcopy ((char *) valaddr, (char *) &temp, sizeof (double)); - return temp; - } - } - else if (code == TYPE_CODE_INT && nosign) - { - if (len == sizeof (char)) - return * (unsigned char *) valaddr; - - if (len == sizeof (short)) - return * (unsigned short *) valaddr; - - if (len == sizeof (int)) - return * (unsigned int *) valaddr; - - if (len == sizeof (long)) - return * (unsigned long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (unsigned long long *) valaddr; -#endif - } - else if (code == TYPE_CODE_INT) - { - if (len == sizeof (char)) - return * (char *) valaddr; - - if (len == sizeof (short)) - return * (short *) valaddr; - - if (len == sizeof (int)) - return * (int *) valaddr; - - if (len == sizeof (long)) - return * (long *) valaddr; - -#ifdef LONG_LONG - if (len == sizeof (long long)) - return * (long long *) valaddr; -#endif - } - - error ("Value not floating number."); -} - -/* Given a value ARG1 of a struct or union type, - extract and return the value of one of its fields. - FIELDNO says which field. - - For C++, must also be able to return values from static fields */ - -value -value_field (arg1, fieldno) - register value arg1; - register int fieldno; -{ - register value v; - register struct type *type = TYPE_FIELD_TYPE (VALUE_TYPE (arg1), fieldno); - register int offset; - - /* Handle packed fields */ - - offset = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) / 8; - if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno)) - { - v = value_from_long (type, - (LONGEST) unpack_field_as_long (VALUE_TYPE (arg1), - VALUE_CONTENTS (arg1), - fieldno)); - VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8; - VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno); - } - else - { - v = allocate_value (type); - bcopy (VALUE_CONTENTS (arg1) + offset, - VALUE_CONTENTS (v), - TYPE_LENGTH (type)); - } - VALUE_LVAL (v) = VALUE_LVAL (arg1); - if (VALUE_LVAL (arg1) == lval_internalvar) - VALUE_LVAL (v) = lval_internalvar_component; - VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1); - VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1); - return v; -} - -value -value_fn_field (arg1, fieldno, subfieldno) - register value arg1; - register int fieldno; -{ - register value v; - struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno); - register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno); - struct symbol *sym; - - sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno), - 0, VAR_NAMESPACE, 0); - if (! sym) error ("Internal error: could not find physical method named %s", - TYPE_FN_FIELD_PHYSNAME (f, subfieldno)); - - v = allocate_value (type); - VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); - VALUE_TYPE (v) = type; - return v; -} - -/* Return a virtual function as a value. - ARG1 is the object which provides the virtual function - table pointer. - F is the list of member functions which contains the desired virtual - function. - J is an index into F which provides the desired virtual function. - TYPE is the basetype which first provides the virtual function table. */ -value -value_virtual_fn_field (arg1, f, j, type) - value arg1; - struct fn_field *f; - int j; - struct type *type; -{ - /* First, get the virtual function table pointer. That comes - with a strange type, so cast it to type `pointer to long' (which - should serve just fine as a function type). Then, index into - the table, and convert final value to appropriate function type. */ - value vfn, vtbl; - value vi = value_from_long (builtin_type_int, - (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); - VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type); - - /* This type may have been defined before its virtual function table - was. If so, fill in the virtual function table entry for the - type now. */ - if (TYPE_VPTR_FIELDNO (type) < 0) - TYPE_VPTR_FIELDNO (type) - = fill_in_vptr_fieldno (type); - - /* Pretend that this array is just an array of pointers to integers. - This will have to change for multiple inheritance. */ - vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type))); - VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int); - - /* Index into the virtual function table. */ - vfn = value_subscript (vtbl, vi); - - /* Reinstantiate the function pointer with the correct type. */ - VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); - return vfn; -} - -/* The value of a static class member does not depend - on its instance, only on its type. If FIELDNO >= 0, - then fieldno is a valid field number and is used directly. - Otherwise, FIELDNAME is the name of the field we are - searching for. If it is not a static field name, an - error is signaled. TYPE is the type in which we look for the - static field member. */ -value -value_static_field (type, fieldname, fieldno) - register struct type *type; - char *fieldname; - register int fieldno; -{ - register value v; - struct symbol *sym; - - if (fieldno < 0) - { - register struct type *t = type; - /* Look for static field. */ - while (t) - { - int i; - for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) - if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname)) - { - if (TYPE_FIELD_STATIC (t, i)) - { - fieldno = i; - goto found; - } - else - error ("field `%s' is not static"); - } - t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0; - } - - t = type; - - if (destructor_name_p (fieldname, t)) - error ("use `info method' command to print out value of destructor"); - - while (t) - { - int i, j; - - for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--) - { - if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname)) - { - error ("use `info method' command to print value of method \"%s\"", fieldname); - } - } - t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0; - } - error("there is no field named %s", fieldname); - } - - found: - - sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno), - 0, VAR_NAMESPACE, 0); - if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno)); - - type = TYPE_FIELD_TYPE (type, fieldno); - v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); - return v; -} - -long -unpack_field_as_long (type, valaddr, fieldno) - struct type *type; - char *valaddr; - int fieldno; -{ - long val; - int bitpos = TYPE_FIELD_BITPOS (type, fieldno); - int bitsize = TYPE_FIELD_BITSIZE (type, fieldno); - - bcopy (valaddr + bitpos / 8, &val, sizeof val); - - /* Extracting bits depends on endianness of the target machine. */ -#ifdef BITS_BIG_ENDIAN - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); -#else - val = val >> (bitpos % 8); -#endif - - val &= (1 << bitsize) - 1; - return val; -} - -void -modify_field (addr, fieldval, bitpos, bitsize) - char *addr; - int fieldval; - int bitpos, bitsize; -{ - long oword; - - bcopy (addr, &oword, sizeof oword); - - /* Shifting for bit field depends on endianness of the target machine. */ -#ifdef BITS_BIG_ENDIAN - bitpos = sizeof oword * 8 - bitpos - bitsize; -#endif - - oword &= ~(((1 << bitsize) - 1) << bitpos); - oword |= fieldval << bitpos; - bcopy (&oword, addr, sizeof oword); -} - -/* Convert C numbers into newly allocated values */ - -value -value_from_long (type, num) - struct type *type; - register LONGEST num; -{ - register value val = allocate_value (type); - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - - if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM) - { - if (len == sizeof (char)) - * (char *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (short)) - * (short *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (int)) - * (int *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (long)) - * (long *) VALUE_CONTENTS (val) = num; -#ifdef LONG_LONG - else if (len == sizeof (long long)) - * (long long *) VALUE_CONTENTS (val) = num; -#endif - else - error ("Integer type encountered with unexpected data length."); - } - else - error ("Unexpected type encountered for integer constant."); - - return val; -} - -value -value_from_double (type, num) - struct type *type; - double num; -{ - register value val = allocate_value (type); - register enum type_code code = TYPE_CODE (type); - register int len = TYPE_LENGTH (type); - - if (code == TYPE_CODE_FLT) - { - if (len == sizeof (float)) - * (float *) VALUE_CONTENTS (val) = num; - else if (len == sizeof (double)) - * (double *) VALUE_CONTENTS (val) = num; - else - error ("Floating type encountered with unexpected data length."); - } - else - error ("Unexpected type encountered for floating constant."); - - return val; -} - -/* Deal with the value that is "about to be returned". */ - -/* Return the value that a function returning now - would be returning to its caller, assuming its type is VALTYPE. - RETBUF is where we look for what ought to be the contents - of the registers (in raw form). This is because it is often - desirable to restore old values to those registers - after saving the contents of interest, and then call - this function using the saved values. - struct_return is non-zero when the function in question is - using the structure return conventions on the machine in question; - 0 when it is using the value returning conventions (this often - means returning pointer to where structure is vs. returning value). */ - -value -value_being_returned (valtype, retbuf, struct_return) - register struct type *valtype; - char retbuf[REGISTER_BYTES]; - int struct_return; -{ - register value val; - - if (struct_return) - return value_at (valtype, EXTRACT_STRUCT_VALUE_ADDRESS (retbuf)); - - val = allocate_value (valtype); - EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS (val)); - - return val; -} - -/* Return true if the function specified is using the structure returning - convention on this machine to return arguments, or 0 if it is using - the value returning convention. FUNCTION is the value representing - the function, FUNCADDR is the address of the function, and VALUE_TYPE - is the type returned by the function */ - -struct block *block_for_pc (); - -int -using_struct_return (function, funcaddr, value_type) - value function; - CORE_ADDR funcaddr; - struct type *value_type; -{ - register enum type_code code = TYPE_CODE (value_type); - - if (code == TYPE_CODE_STRUCT || - code == TYPE_CODE_ENUM || - code == TYPE_CODE_ARRAY) - { - struct block *b = block_for_pc (funcaddr); - - if (!(BLOCK_GCC_COMPILED (b) && TYPE_LENGTH (value_type) < 8)) - return 1; - } - - return 0; -} - -/* Store VAL so it will be returned if a function returns now. - Does not verify that VAL's type matches what the current - function wants to return. */ - -void -set_return_value (val) - value val; -{ - register enum type_code code = TYPE_CODE (VALUE_TYPE (val)); - char regbuf[REGISTER_BYTES]; - double dbuf; - LONGEST lbuf; - - if (code == TYPE_CODE_STRUCT - || code == TYPE_CODE_UNION) - error ("Specifying a struct or union return value is not supported."); - - if (code == TYPE_CODE_FLT) - { - dbuf = value_as_double (val); - - STORE_RETURN_VALUE (VALUE_TYPE (val), &dbuf); - } - else - { - lbuf = value_as_long (val); - STORE_RETURN_VALUE (VALUE_TYPE (val), &lbuf); - } -} - -void -_initialize_values () -{ - add_info ("convenience", convenience_info, - "Debugger convenience (\"$foo\") variables.\n\ -These variables are created when you assign them values;\n\ -thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\ -A few convenience variables are given values automatically GDB:\n\ -\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\ -\"$__\" holds the contents of the last address examined with \"x\"."); - - add_info ("history", history_info, - "Elements of value history (around item number IDX, or last ten)."); -} - -@ - - -1.1 -log -@Initial revision -@ -text -@d182 2 -a183 1 - register int i; -d185 6 -a190 3 - /* Get error now if about to store an invalid float. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) - value_as_double (val); -d427 7 -a433 1 - return unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val)); -d510 5 -d516 1 -a516 1 -unpack_double (type, valaddr) -d519 1 -d525 1 -d528 4 -a531 2 - if (INVALID_FLOAT (valaddr, len)) - error ("Invalid floating value found in program."); -a770 1 - union { int i; char c; } test; -d774 6 -a779 7 - /* Extracting bits depends on endianness of the machine. */ - test.i = 1; - if (test.c == 1) - /* Little-endian. */ - val = val >> (bitpos % 8); - else - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); -a791 1 - union { int i; char c; } test; -d795 4 -a798 5 - /* Shifting for bit field depends on endianness of the machine. */ - test.i = 1; - if (test.c != 1) - /* not little-endian: assume big-endian. */ - bitpos = sizeof oword * 8 - bitpos - bitsize; -@ |