This commit is contained in:
gdb-3.1 1989-01-31 17:56:40 +00:00 committed by Pedro Alves
parent bb7592f010
commit e91b87a368
150 changed files with 54576 additions and 10225 deletions

13
gdb/.gdbinit Normal file
View File

@ -0,0 +1,13 @@
b fatal
b info_command
commands
silent
return
end
define rr
run
end
set prompt (top-gdb)

File diff suppressed because it is too large Load Diff

View File

@ -1,109 +1,240 @@
# Makefile for 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!
# On HPUX, you need to add -Ihpux to CFLAGS.
# The headers in the subdir hpux override system headers
# 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 also need to add -lGNU to CLIBS, and perhaps CC = gcc.
# 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.
# -I. for "#include <obstack.h>"
CFLAGS = -g -I.
# NOTE!!! -O may FAIL TO WORK! See initialize.h for some weird hacks.
# 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.
# 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)
CLIBS = $(OBSTACK)
#
# 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
STARTOBS = main.o firstfile.o
# Flags to be used in compiling malloc.o
# Specify range checking for storage allocation.
MALLOC_FLAGS =
#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS
OBS = blockframe.o breakpoint.o findvar.o stack.o source.o \
# 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
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
TSOBS = core.o inflow.o dep.o
NTSOBS = standalone.o
ENDOBS = lastfile.o command.o utils.o expread.o expprint.o pinsn.o \
environ.o version.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
gdb+ : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
$(CC) $(LDFLAGS) -o gdb+ $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS)
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+ : $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) $(OBSTACK1)
$(CC) $(LDFLAGS) -o xgdb+ $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) \
-lXaw -lXt -lX11 $(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) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc $(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 $@
blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
command.o : command.c command.h
coffread.o : coffread.c defs.h initialize.h param.h symtab.h
core.o : core.c defs.h initialize.h param.h
dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
environ.o : environ.c environ.h
expprint.o : expprint.c defs.h symtab.h expression.h
expread.tab.c : expread.y
@echo 'Expect 96 shift/reduce conflicts.'
@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
eval.o : eval.c defs.h initialize.h symtab.h value.h expression.h
findvar.o : findvar.c defs.h initialize.h param.h symtab.h frame.h value.h
firstfile.o : firstfile.c initialize.h
infcmd.o : infcmd.c defs.h initialize.h param.h symtab.h frame.h inferior.h environ.h value.h
inflow.o : inflow.c defs.h initialize.h param.h frame.h inferior.h
infrun.o : infrun.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
kdb-start.o : kdb-start.c defs.h param.h
lastfile.o : lastfile.c
main.o : main.c defs.h command.h
#
# 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 : pinsn.c defs.h param.h symtab.h \
vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c sparc-opcode.h sparc-pinsn.c
printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h
remote.o : remote.c defs.h initialize.h param.h frame.h inferior.h
source.o : source.c defs.h initialize.h symtab.h
stack.o : stack.c defs.h initialize.h param.h symtab.h frame.h
standalone.o : standalone.c defs.h initialize.h param.h symtab.h frame.h inferior.h wait.h
symmisc.o : symmisc.c defs.h initialize.h symtab.h
symtab.o : symtab.c defs.h initialize.h param.h symtab.h
utils.o : utils.c defs.h
valarith.o : valarith.c defs.h initialize.h param.h symtab.h value.h expression.h
valops.o : valops.c defs.h initialize.h param.h symtab.h value.h
valprint.o : valprint.c defs.h initialize.h param.h symtab.h value.h
values.o : values.c defs.h initialize.h param.h symtab.h value.h
version.o : version.c
xgdb.o : xgdb.c defs.h initialize.h param.h symtab.h frame.h
$(CC) -c $(CFLAGS) xgdb.c -o $@
pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \
${OPCODES}
obstack.o : obstack.c
#
# 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

367
gdb/RCS/Makefile,v Normal file
View File

@ -0,0 +1,367 @@
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
@

606
gdb/RCS/blockframe.c,v Normal file
View File

@ -0,0 +1,606 @@
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");
@

2047
gdb/RCS/coffread.c,v Normal file

File diff suppressed because it is too large Load Diff

229
gdb/RCS/config.gdb,v Executable file
View File

@ -0,0 +1,229 @@
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
@

651
gdb/RCS/core.c,v Normal file
View File

@ -0,0 +1,651 @@
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
@

4610
gdb/RCS/dbxread.c,v Normal file

File diff suppressed because it is too large Load Diff

731
gdb/RCS/default-dep.c,v Normal file
View File

@ -0,0 +1,731 @@
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);
@

584
gdb/RCS/findvar.c,v Normal file
View File

@ -0,0 +1,584 @@
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 (&registers[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, &registers[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 *) &registers[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 *) &registers[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, &registers[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
@

3009
gdb/RCS/gdb.texinfo,v Normal file

File diff suppressed because it is too large Load Diff

105
gdb/RCS/gdbcore.h,v Normal file
View File

@ -0,0 +1,105 @@
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
@

636
gdb/RCS/inflow.c,v Normal file
View File

@ -0,0 +1,636 @@
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, &ltc_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, &ltc_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, &ltc_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 *)&ltc_inferior)[i]);
printf ("\n");
ioctl (0, TIOCSLTC, &ltc_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, &ltc_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
@

1855
gdb/RCS/infrun.c,v Normal file

File diff suppressed because it is too large Load Diff

591
gdb/RCS/m-aux.h,v Normal file
View File

@ -0,0 +1,591 @@
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
@

607
gdb/RCS/m-hp9k320.h,v Normal file
View File

@ -0,0 +1,607 @@
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
@

747
gdb/RCS/m-sparc.h,v Normal file
View File

@ -0,0 +1,747 @@
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, &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\
write_memory (fp - 0xa0, &registers[REGISTER_BYTE (0)], 8 * 4); \
write_memory (fp - 0xc0, &registers[REGISTER_BYTE (24)], 7 * 4); \
write_memory (fp - 0xa4, &rp, 4); \
write_memory (fp - 0xe0, &registers[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
@

824
gdb/RCS/m68k-pinsn.c,v Normal file
View File

@ -0,0 +1,824 @@
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 */
@

1348
gdb/RCS/main.c,v Normal file

File diff suppressed because it is too large Load Diff

75
gdb/RCS/munch,v Executable file
View File

@ -0,0 +1,75 @@
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 ();/'
@

1707
gdb/RCS/printcmd.c,v Normal file

File diff suppressed because it is too large Load Diff

662
gdb/RCS/remote.c,v Normal file
View File

@ -0,0 +1,662 @@
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>
@

990
gdb/RCS/source.c,v Normal file
View File

@ -0,0 +1,990 @@
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, &current_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, &current_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>
@

1091
gdb/RCS/sparc-dep.c,v Normal file

File diff suppressed because it is too large Load Diff

882
gdb/RCS/stack.c,v Normal file
View File

@ -0,0 +1,882 @@
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
@

726
gdb/RCS/utils.c,v Normal file
View File

@ -0,0 +1,726 @@
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
@

1117
gdb/RCS/valprint.c,v Normal file

File diff suppressed because it is too large Load Diff

1047
gdb/RCS/values.c,v Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,10 @@
This is GDB, a source-level debugger intended for GNU,
presently running under un*x.
Before compiling GDB, you must set up links to four files according to
Before compiling GDB, you must set up links to five files according to
the kind of machine you are running on. To do this, type `config.gdb
machine', where machine is something like `vax' or `sun2'. This
creates links named `param.h', `m-init.h', `opcode.h', and `pinsn.c'.
(Note: we lack information on certain machines.)
Also, `Makefile' must be changed to say `OBSTACK = obstack.o' instead
of `OBSTACK=-lobstack' (unless you want to install obstack.o as
/lib/libobstack.a).
creates links named `param.h', `opcode.h', `pinsn.c', and `infdep.c'.
Once these files are set up, just `make' will do everything,
producing an executable `gdb' in this directory.
@ -21,12 +16,52 @@ m-<machine>.h
This file contains macro definitions that express information
about the machine's registers, stack frame format and instructions.
m-<machine>init.h
This file defines one macro, which says how to round up from the
address of the end of the text of one .o file to the beginning of
the text of the next .o file.
<machine>-opcode.h, <machine>-pinsn.c
These files contain the information necessary to print instructions
for your cpu type.
<machine>-dep.c
Those routines which provide a low level interface to ptrace and which
tend to be machine-dependent. (The machine-independent routines are in
`infrun.c' and `inflow.c')
About debugging gdb with itself...
You probably want to do a "make TAGS" after you configure your
distribution; this will put the machine dependent routines for your
local machine where they will be accessed first by a M-period .
Also, you want to make sure that gdb is not compiled with shared
libraries on the Sun 4. And you want to make sure that you've
compiled gdb with your local cc or taken appropriate precautions
regarding ansification of include files. See the Makefile for more
information.
The "info" command, when executed without a subcommand in a gdb being
debugged by gdb, will pop you back up to the top level gdb. See
.gdbinit for more details.
About languages other than C...
C++ support has been integrated into gdb; it works, but somewhat
buggily. Pascal support has not yet been integrated in gdb; the work
is being done.
About reporting bugs...
The correct address for reporting bugs found with gdb is
"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
About xgdb...
xgdb.c was provided to us by the user community; it is not an integral
part of the gdb distribution. The problem of providing visual
debugging support on top of gdb is peripheral to the GNU project and
(at least right now) we can't afford to put time into it. So while we
will be happy to incorporate user fixes to xgdb.c, we do not guarantee
that it will work and we will not fix bugs reported in it.
For those intersted in auto display of source and the availability of
an editor while debugging I suggest trying gdb-mode in gnu-emacs.
Comments on this mode are welcome.

1265
gdb/TAGS

File diff suppressed because it is too large Load Diff

112
gdb/a.out.encap.h Normal file
View File

@ -0,0 +1,112 @@
/*
* another try at encapsulating bsd object files in coff
* by Pace Willisson 12/9/88
*
* This time, we will only use the coff headers to tell the kernel
* how to exec the file. Therefore, the only fields that need to
* be filled in are the scnptr and vaddr for the text and data
* sections, and the vaddr for the bss. As far as coff is concerned,
* there is no symbol table, relocation, or line numbers.
*
* A normal bsd header (struct exec) is placed after the coff headers,
* and before the real text. I defined a the new fields 'a_machtype'
* and a_flags. If a_machtype is M_386, and a_flags & A_ENCAP is
* true, then the bsd header is preceeded by a coff header. Macros
* like N_TXTOFF and N_TXTADDR use this field to find the bsd header.
*
* The only problem is to track down the bsd exec header. The
* macros HEADER_OFFSET, etc do this. Look at nm.c, dis.c, etc
* for examples.
*/
#include "a.out.gnu.h"
#define N_FLAGS_COFF_ENCAPSULATE 0x20 /* coff header precedes bsd header */
/* Describe the COFF header used for encapsulation. */
struct coffheader
{
/* filehdr */
unsigned short f_magic;
unsigned short f_nscns;
long f_timdat;
long f_symptr;
long f_nsyms;
unsigned short f_opthdr;
unsigned short f_flags;
/* aouthdr */
short magic;
short vstamp;
long tsize;
long dsize;
long bsize;
long entry;
long text_start;
long data_start;
struct coffscn
{
char s_name[8];
long s_paddr;
long s_vaddr;
long s_size;
long s_scnptr;
long s_relptr;
long s_lnnoptr;
unsigned short s_nreloc;
unsigned short s_nlnno;
long s_flags;
} scns[3];
};
/* Describe some of the parameters of the encapsulation,
including how to find the encapsulated BSD header. */
#ifdef i386
#define COFF_MAGIC 0514 /* I386MAGIC */
#endif
#if defined(i386)
short __header_offset_temp;
#define HEADER_OFFSET(f) \
(__header_offset_temp = 0, \
fread ((char *)&__header_offset_temp, sizeof (short), 1, (f)), \
fseek ((f), -sizeof (short), 1), \
__header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
#define HEADER_OFFSET_FD(fd) \
(__header_offset_temp = 0, \
read ((fd), (char *)&__header_offset_temp, sizeof (short)), \
lseek ((fd), -sizeof (short), 1), \
__header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
#else
#define HEADER_OFFSET(f) 0
#define HEADER_OFFSET_FD(fd) 0
#endif
#define HEADER_SEEK(f) (fseek ((f), HEADER_OFFSET((f)), 1))
#define HEADER_SEEK_FD(fd) (lseek ((fd), HEADER_OFFSET_FD((fd)), 1))
/* Describe the characteristics of the BSD header
that appears inside the encapsulation. */
#undef _N_HDROFF
#undef N_TXTADDR
#undef N_DATADDR
#define _N_HDROFF(x) ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
sizeof (struct coffheader) : 0)
/* Address of text segment in memory after it is loaded. */
#define N_TXTADDR(x) \
((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
sizeof (struct coffheader) + sizeof (struct exec) : 0)
#define SEGMENT_SIZE 0x400000
#define N_DATADDR(x) \
((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
(SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \
(N_TXTADDR(x)+(x).a_text))

182
gdb/a.out.gnu.h Normal file
View File

@ -0,0 +1,182 @@
#ifndef __A_OUT_GNU_H__
#define __A_OUT_GNU_H__
#define __GNU_EXEC_MACROS__
#ifndef __STRUCT_EXEC_OVERRIDE__
struct exec
{
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
unsigned a_text; /* length of text, in bytes */
unsigned a_data; /* length of data, in bytes */
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
unsigned a_syms; /* length of symbol table data in file, in bytes */
unsigned a_entry; /* start address */
unsigned a_trsize; /* length of relocation info for text, in bytes */
unsigned a_drsize; /* length of relocation info for data, in bytes */
};
#endif /* __STRUCT_EXEC_OVERRIDE__ */
/* these go in the N_MACHTYPE field */
enum machine_type {
M_OLDSUN2 = 0,
M_68010 = 1,
M_68020 = 2,
M_SPARC = 3,
/* skip a bunch so we don't run into any of sun's numbers */
M_386 = 100,
};
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
#define N_SET_INFO(exec, magic, type, flags) \
((exec).a_info = ((magic) & 0xffff) \
| (((int)(type) & 0xff) << 16) \
| (((flags) & 0xff) << 24))
#define N_SET_MAGIC(exec, magic) \
((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
#define N_SET_MACHTYPE(exec, machtype) \
((exec).a_info = \
((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
#define N_SET_FLAGS(exec, flags) \
((exec).a_info = \
((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
/* Code indicating object file or impure executable. */
#define OMAGIC 0407
/* Code indicating pure executable. */
#define NMAGIC 0410
/* Code indicating demand-paged executable. */
#define ZMAGIC 0413
#define N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
/* Address of text segment in memory after it is loaded. */
#define N_TXTADDR(x) 0
/* Address of data segment in memory after it is loaded.
Note that it is up to you to define SEGMENT_SIZE
on machines not listed here. */
#ifdef vax
#define SEGMENT_SIZE page_size
#endif
#ifdef is68k
#define SEGMENT_SIZE 0x20000
#endif
#ifndef N_DATADDR
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \
: (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))))
#endif
/* Address of bss segment in memory after it is loaded. */
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
struct nlist {
union {
char *n_name;
struct nlist *n_next;
long n_strx;
} n_un;
char n_type;
char n_other;
short n_desc;
unsigned n_value;
};
#define N_UNDF 0
#define N_ABS 2
#define N_TEXT 4
#define N_DATA 6
#define N_BSS 8
#define N_FN 15
#define N_EXT 1
#define N_TYPE 036
#define N_STAB 0340
/* 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. */
#define N_INDR 0xa
/* 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. */
/* These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /* Absolute set element symbol */
#define N_SETT 0x16 /* Text set element symbol */
#define N_SETD 0x18 /* Data set element symbol */
#define N_SETB 0x1A /* Bss set element symbol */
/* This is output from LD. */
#define N_SETV 0x1C /* Pointer to set vector in data area. */
/* This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures,
all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */
struct relocation_info
{
/* Address (within segment) to be relocated. */
int r_address;
/* The meaning of r_symbolnum depends on r_extern. */
unsigned int r_symbolnum:24;
/* Nonzero means value is a pc-relative offset
and it should be relocated for changes in its own address
as well as for changes in the symbol or section specified. */
unsigned int r_pcrel:1;
/* Length (as exponent of 2) of the field to be relocated.
Thus, a value of 2 indicates 1<<2 bytes. */
unsigned int r_length:2;
/* 1 => relocate with value of symbol.
r_symbolnum is the index of the symbol
in file's the symbol table.
0 => relocate with the address of a segment.
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
(the N_EXT bit may be set also, but signifies nothing). */
unsigned int r_extern:1;
/* Four bits that aren't used, but when writing an object file
it is desirable to clear them. */
unsigned int r_pad:4;
};
#endif /* __A_OUT_GNU_H__ */

191
gdb/alloca.c Normal file
View File

@ -0,0 +1,191 @@
/*
alloca -- (mostly) portable public-domain implementation -- D A Gwyn
last edit: 86/05/30 rms
include config.h, since on VMS it renames some symbols.
Use xmalloc instead of malloc.
This implementation of the PWB library alloca() function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
It should work under any C implementation that uses an
actual procedure stack (as opposed to a linked list of
frames). There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca()-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
#ifdef emacs
#include "config.h"
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif static
#endif emacs
#ifdef X3J11
typedef void *pointer; /* generic pointer type */
#else
typedef char *pointer; /* generic pointer type */
#endif
#define NULL 0 /* null pointer constant */
extern void free();
extern pointer xmalloc();
/*
Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
static void
find_stack_direction (/* void */)
{
static char *addr = NULL; /* address of first
`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*
An "alloca header" is used to:
(a) chain together all alloca()ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc()
alignment chunk size. The following default should work okay.
*/
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* to force sizeof(header) */
struct
{
union hdr *next; /* for chaining headers */
char *deep; /* for stack depth measure */
} h;
} header;
/*
alloca( size ) returns a pointer to at least `size' bytes of
storage which will be automatically reclaimed upon exit from
the procedure that called alloca(). Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32.
*/
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
alloca (size) /* returns pointer to storage */
unsigned size; /* # bytes to allocate */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* traverses linked list */
for (hp = last_alloca_header; hp != NULL;)
if (STACK_DIR > 0 && hp->h.deep > depth
|| STACK_DIR < 0 && hp->h.deep < depth)
{
register header *np = hp->h.next;
free ((pointer) hp); /* collect garbage */
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
last_alloca_header = hp; /* -> last valid storage */
}
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = xmalloc (sizeof (header) + size);
/* address of header */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
last_alloca_header = (header *)new;
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
}

BIN
gdb/alloca.o Normal file

Binary file not shown.

View File

@ -20,7 +20,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
@ -39,7 +38,12 @@ static FRAME current_frame;
struct block *block_for_pc ();
CORE_ADDR get_pc_function_start ();
START_FILE
/*
* 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. */
@ -59,6 +63,31 @@ set_current_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. */
@ -66,98 +95,154 @@ FRAME
get_prev_frame (frame)
FRAME frame;
{
CORE_ADDR pointer;
/* The caller of "no frame" is the innermost frame. */
if (frame == 0)
return get_current_frame ();
/* We're allowed to know that FRAME and "struct frame_info *" are
the same */
return get_prev_frame_info (frame);
}
/* 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. */
pointer = FRAME_CHAIN (frame);
if (!FRAME_CHAIN_VALID (pointer, 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. */
return FRAME_CHAIN_COMBINE (pointer, 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
struct frame_info *
get_frame_info (frame)
FRAME frame;
{
struct frame_info val;
FRAME current = get_current_frame ();
register FRAME frame1, frame2;
val.frame = frame;
if (frame == current)
{
val.pc = read_pc ();
val.next_frame = 0;
val.next_next_frame = 0;
}
else
{
for (frame1 = current, frame2 = 0;
frame1;
frame2 = frame1, frame1 = get_prev_frame (frame1))
{
QUIT;
if (frame1 == frame)
break;
val.pc = FRAME_SAVED_PC (frame1, frame2);
val.next_frame = frame1;
val.next_next_frame = frame2;
}
}
return val;
return frame;
}
/* Return a structure containing various interesting information
about the frame that called FRAME.
about the frame that called NEXT_FRAME. */
This is much faster than get_frame_info (get_prev_frame (FRAME))
because it does not need to search the entire stack
to find the frame called by the one being described -- that is FRAME. */
struct frame_info
get_prev_frame_info (next_frame, next_next_frame)
FRAME next_frame, next_next_frame;
struct frame_info *
get_prev_frame_info (next_frame)
FRAME next_frame;
{
struct frame_info val;
register FRAME frame = get_prev_frame (next_frame);
FRAME_ADDR address;
struct frame_info *prev;
int fromleaf = 0;
val.frame = frame;
val.next_frame = next_frame;
val.next_next_frame = next_next_frame;
/* 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 (next_frame == 0)
/* 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)
{
val.pc = read_pc ();
if (!current_frame)
error ("No frame is currently selected.");
return current_frame;
}
else
{
val.pc = FRAME_SAVED_PC (next_frame, next_next_frame);
/* 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);
}
}
return val;
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;
struct frame_info *fi;
fi = get_frame_info (frame);
return fi.pc;
return fi->pc;
}
/* Find the addresses in which registers are saved in FRAME. */
@ -167,7 +252,102 @@ get_frame_saved_regs (frame_info_addr, saved_regs_addr)
struct frame_info *frame_info_addr;
struct frame_saved_regs *saved_regs_addr;
{
FRAME_FIND_SAVED_REGS (*frame_info_addr, *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
@ -177,10 +357,10 @@ struct block *
get_frame_block (frame)
FRAME frame;
{
struct frame_info fi;
struct frame_info *fi;
fi = get_frame_info (frame);
return block_for_pc (fi.pc);
return block_for_pc (fi->pc);
}
struct block *
@ -195,17 +375,16 @@ get_pc_function_start (pc)
{
register struct block *bl = block_for_pc (pc);
register struct symbol *symbol;
if (bl == 0)
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;
}
symbol = block_function (bl);
bl = SYMBOL_BLOCK_VALUE (symbol);
return BLOCK_START (bl);
}
}
/* Return the symbol for the function executing in frame FRAME. */
@ -222,6 +401,8 @@ get_frame_function (frame)
/* 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;
@ -229,6 +410,7 @@ block_for_pc (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 */
@ -242,6 +424,19 @@ block_for_pc (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;
@ -307,7 +502,7 @@ find_pc_misc_function (pc)
if (hi < 0) return -1; /* no misc functions recorded */
/* trivial reject range test */
if (pc < misc_function_vector[0].address ||
if (pc < misc_function_vector[0].address ||
pc > misc_function_vector[hi].address)
return -1;
@ -333,7 +528,7 @@ FRAME
block_innermost_frame (block)
struct block *block;
{
struct frame_info fi;
struct frame_info *fi;
register FRAME frame;
register CORE_ADDR start = BLOCK_START (block);
register CORE_ADDR end = BLOCK_END (block);
@ -341,18 +536,17 @@ block_innermost_frame (block)
frame = 0;
while (1)
{
fi = get_prev_frame_info (frame);
frame = fi.frame;
frame = get_prev_frame (frame);
if (frame == 0)
return 0;
if (fi.pc >= start && fi.pc < end)
fi = get_frame_info (frame);
if (fi->pc >= start && fi->pc < end)
return frame;
}
}
static
initialize ()
void
_initialize_blockframe ()
{
obstack_init (&frame_cache_obstack);
}
END_FILE

View File

@ -19,7 +19,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
@ -32,10 +31,16 @@ static char break_insn[] = BREAKPOINT;
/* States of enablement of breakpoint.
`temporary' means disable when hit.
`once' means delete when hit. */
`delete' means delete when hit. */
enum enable { disabled, enabled, temporary, delete};
/* Not that the ->silent field is not currently used by any commands
(though the code is in there if it was to be and set_raw_breakpoint
does set it to 0). I implemented it because I thought it would be
useful for a hack I had to put in; I'm going to leave it in because
I can see how there might be times when it would indeed be useful */
struct breakpoint
{
struct breakpoint *next;
@ -49,6 +54,9 @@ struct breakpoint
struct symtab *symtab;
/* Zero means disabled; remember the info but don't break here. */
enum enable enable;
/* Non-zero means a silent breakpoint (don't print frame info
if we stop here). */
unsigned char silent;
/* Number of stops at this breakpoint that should
be continued automatically before really stopping. */
int ignore_count;
@ -62,8 +70,9 @@ struct breakpoint
char duplicate;
/* Chain of command lines to execute when this breakpoint is hit. */
struct command_line *commands;
/* Stack depth (frame). If nonzero, break only if fp equals this. */
FRAME frame;
/* Stack depth (address of frame). If nonzero, break only if fp
equals this. */
FRAME_ADDR frame;
/* Conditional. Break only if this expression's value is nonzero. */
struct expression *cond;
};
@ -95,10 +104,6 @@ int default_breakpoint_line;
struct command_line *breakpoint_commands;
START_FILE
extern char *read_line ();
static void delete_breakpoint ();
void clear_momentary_breakpoints ();
void breakpoint_auto_delete ();
@ -161,9 +166,6 @@ commands_command (arg)
register int bnum;
struct command_line *l;
if (arg == 0)
error_no_arg ("breakpoint number");
/* If we allowed this, we would have problems with when to
free the storage, if we change the commands currently
being read from. */
@ -171,15 +173,21 @@ commands_command (arg)
if (breakpoint_commands)
error ("Can't use the \"commands\" command among a breakpoint's commands.");
p = arg;
if (! (*p >= '0' && *p <= '9'))
error ("Argument must be integer (a breakpoint number).");
while (*p >= '0' && *p <= '9') p++;
if (*p)
error ("Unexpected extra arguments following breakpoint number.");
bnum = atoi (arg);
/* Allow commands by itself to refer to the last breakpoint. */
if (arg == 0)
bnum = breakpoint_count;
else
{
p = arg;
if (! (*p >= '0' && *p <= '9'))
error ("Argument must be integer (a breakpoint number).");
while (*p >= '0' && *p <= '9') p++;
if (*p)
error ("Unexpected extra arguments following breakpoint number.");
bnum = atoi (arg);
}
ALL_BREAKPOINTS (b)
if (b->number == bnum)
@ -254,7 +262,10 @@ insert_breakpoints ()
register struct breakpoint *b;
int val;
/* printf ("Inserting breakpoints.\n"); */
#ifdef BREAKPOINT_DEBUG
printf ("Inserting breakpoints.\n");
#endif /* BREAKPOINT_DEBUG */
ALL_BREAKPOINTS (b)
if (b->enable != disabled && ! b->inserted && ! b->duplicate)
{
@ -262,8 +273,10 @@ insert_breakpoints ()
val = write_memory (b->address, break_insn, sizeof break_insn);
if (val)
return val;
/* printf ("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
b->address, b->shadow_contents[0], b->shadow_contents[1]); */
#ifdef BREAKPOINT_DEBUG
printf ("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
b->address, b->shadow_contents[0], b->shadow_contents[1]);
#endif /* BREAKPOINT_DEBUG */
b->inserted = 1;
}
return 0;
@ -275,7 +288,10 @@ remove_breakpoints ()
register struct breakpoint *b;
int val;
/* printf ("Removing breakpoints.\n"); */
#ifdef BREAKPOINT_DEBUG
printf ("Removing breakpoints.\n");
#endif /* BREAKPOINT_DEBUG */
ALL_BREAKPOINTS (b)
if (b->inserted)
{
@ -283,8 +299,10 @@ remove_breakpoints ()
if (val)
return val;
b->inserted = 0;
/* printf ("Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
b->address, b->shadow_contents[0], b->shadow_contents[1]); */
#ifdef BREAKPOINT_DEBUG
printf ("Removed breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
b->address, b->shadow_contents[0], b->shadow_contents[1]);
#endif /* BREAKPOINT_DEBUG */
}
return 0;
@ -293,7 +311,7 @@ remove_breakpoints ()
/* Clear the "inserted" flag in all breakpoints.
This is done when the inferior is loaded. */
int
void
mark_breakpoints_out ()
{
register struct breakpoint *b;
@ -334,12 +352,13 @@ breakpoint_cond_eval (exp)
or -2 if breakpoint says it has deleted itself and don't stop,
or -3 if hit a breakpoint number -3 (delete when program stops),
or else the number of the breakpoint,
with 0x1000000 added for a silent breakpoint. */
with 0x1000000 added (or subtracted, for a negative return value) for
a silent breakpoint. */
int
breakpoint_stop_status (pc, frame)
breakpoint_stop_status (pc, frame_address)
CORE_ADDR pc;
FRAME frame;
FRAME_ADDR frame_address;
{
register struct breakpoint *b;
register int cont = 0;
@ -350,7 +369,7 @@ breakpoint_stop_status (pc, frame)
ALL_BREAKPOINTS (b)
if (b->enable != disabled && b->address == pc)
{
if (b->frame && b->frame != frame)
if (b->frame && b->frame != frame_address)
cont = -1;
else
{
@ -376,11 +395,15 @@ breakpoint_stop_status (pc, frame)
if (b->enable == temporary)
b->enable = disabled;
breakpoint_commands = b->commands;
if (breakpoint_commands
&& !strcmp ("silent", breakpoint_commands->line))
if (b->silent
|| (breakpoint_commands
&& !strcmp ("silent", breakpoint_commands->line)))
{
breakpoint_commands = breakpoint_commands->next;
return 0x1000000 + b->number;
if (breakpoint_commands)
breakpoint_commands = breakpoint_commands->next;
return (b->number > 0 ?
0x1000000 + b->number :
b->number - 0x1000000);
}
return b->number;
}
@ -538,6 +561,7 @@ set_raw_breakpoint (sal)
b->line_number = sal.line;
b->enable = enabled;
b->next = 0;
b->silent = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
@ -571,7 +595,7 @@ set_momentary_breakpoint (sal, frame)
b = set_raw_breakpoint (sal);
b->number = -3;
b->enable = delete;
b->frame = frame;
b->frame = (frame ? FRAME_FP (frame) : 0);
}
void
@ -622,14 +646,12 @@ set_breakpoint (s, line, tempflag)
}
/* Set a breakpoint according to ARG (function, linenum or *address)
and make it temporary if TEMPFLAG is nonzero.
LINE_NUM is for C++. */
and make it temporary if TEMPFLAG is nonzero. */
static void
break_command_1 (arg, tempflag, from_tty, line_num)
break_command_1 (arg, tempflag, from_tty)
char *arg;
int tempflag, from_tty, line_num;
int tempflag, from_tty;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
@ -637,6 +659,7 @@ break_command_1 (arg, tempflag, from_tty, line_num)
register struct breakpoint *b;
char *save_arg;
int i;
CORE_ADDR pc;
sals.sals = NULL;
sals.nelts = 0;
@ -644,58 +667,64 @@ break_command_1 (arg, tempflag, from_tty, line_num)
sal.line = sal.pc = sal.end = 0;
sal.symtab = 0;
if (arg)
{
CORE_ADDR pc;
sals = decode_line_1 (&arg, 1, 0, 0);
/* If no arg given, or if first arg is 'if ', use the default breakpoint. */
if (! sals.nelts) return;
save_arg = arg;
for (i = 0; i < sals.nelts; i++)
if (!arg || (arg[0] == 'i' && arg[1] == 'f'
&& (arg[2] == ' ' || arg[2] == '\t')))
{
if (default_breakpoint_valid)
{
sal = sals.sals[i];
if (sal.pc == 0 && sal.symtab != 0)
{
pc = find_line_pc (sal.symtab, sal.line);
if (pc == 0)
error ("No line %d in file \"%s\".",
sal.line, sal.symtab->filename);
}
else pc = sal.pc;
while (*arg)
{
if (arg[0] == 'i' && arg[1] == 'f'
&& (arg[2] == ' ' || arg[2] == '\t'))
cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
block_for_pc (pc), 0);
else
error ("Junk at end of arguments.");
}
arg = save_arg;
sals.sals[i].pc = pc;
sals.sals = (struct symtab_and_line *)
malloc (sizeof (struct symtab_and_line));
sal.pc = default_breakpoint_address;
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sals.sals[0] = sal;
sals.nelts = 1;
}
}
else if (default_breakpoint_valid)
{
sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
sal.pc = default_breakpoint_address;
sal.line = default_breakpoint_line;
sal.symtab = default_breakpoint_symtab;
sals.sals[0] = sal;
sals.nelts = 1;
else
error ("No default breakpoint address now.");
}
else
error ("No default breakpoint address now.");
if (default_breakpoint_valid)
sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
default_breakpoint_line);
else
sals = decode_line_1 (&arg, 1, 0, 0);
if (! sals.nelts)
return;
save_arg = arg;
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
if (sal.pc == 0 && sal.symtab != 0)
{
pc = find_line_pc (sal.symtab, sal.line);
if (pc == 0)
error ("No line %d in file \"%s\".",
sal.line, sal.symtab->filename);
}
else
pc = sal.pc;
while (arg && *arg)
{
if (arg[0] == 'i' && arg[1] == 'f'
&& (arg[2] == ' ' || arg[2] == '\t'))
cond = (struct expression *) parse_c_1 ((arg += 2, &arg),
block_for_pc (pc), 0);
else
error ("Junk at end of arguments.");
}
arg = save_arg;
sals.sals[i].pc = pc;
}
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
sal.line += line_num; /** C++ **/
if (line_num != 0)
{ /* get the pc for a particular line */
sal.pc = find_line_pc (sal.symtab, sal.line);
}
if (from_tty)
describe_other_breakpoints (sal.pc);
@ -711,6 +740,12 @@ break_command_1 (arg, tempflag, from_tty, line_num)
printf (": file %s, line %d.", b->symtab->filename, b->line_number);
printf ("\n");
}
if (sals.nelts > 1)
{
printf ("Multiple breakpoints were set.\n");
printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
}
free (sals.sals);
}
@ -719,7 +754,7 @@ break_command (arg, from_tty)
char *arg;
int from_tty;
{
break_command_1 (arg, 0, from_tty, 0);
break_command_1 (arg, 0, from_tty);
}
static void
@ -727,7 +762,62 @@ tbreak_command (arg, from_tty)
char *arg;
int from_tty;
{
break_command_1 (arg, 1, from_tty, 0);
break_command_1 (arg, 1, from_tty);
}
/*
* Helper routine for the until_command routine in infcmd.c. Here
* because it uses the mechanisms of breakpoints.
*/
void
until_break_command(arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
FRAME frame = get_current_frame ();
FRAME prev_frame = get_prev_frame (frame);
/* Set a breakpoint where the user wants it and at return from
this function */
if (default_breakpoint_valid)
sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
default_breakpoint_line);
else
sals = decode_line_1 (&arg, 1, 0, 0);
if (sals.nelts != 1)
error ("Couldn't get information on specified line.");
sal = sals.sals[0];
free (sals.sals); /* malloc'd, so freed */
if (*arg)
error ("Junk at end of arguments.");
if (sal.pc == 0 && sal.symtab != 0)
sal.pc = find_line_pc (sal.symtab, sal.line);
if (sal.pc == 0)
error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
set_momentary_breakpoint (sal, 0);
/* Keep within the current frame */
if (prev_frame)
{
struct frame_info *fi;
fi = get_frame_info (prev_frame);
sal = find_pc_line (fi->pc, 0);
sal.pc = fi->pc;
set_momentary_breakpoint (sal, prev_frame);
}
proceed (-1, -1, 0);
}
static void
@ -742,7 +832,9 @@ clear_command (arg, from_tty)
int i;
if (arg)
sals = decode_line_spec (arg, 1);
{
sals = decode_line_spec (arg, 1);
}
else
{
sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
@ -801,7 +893,7 @@ clear_command (arg, from_tty)
}
free (sals.sals);
}
/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
This is called after breakpoint BNUM has been hit.
Also delete any breakpoint numbered -3 unless there are breakpoint
@ -851,7 +943,7 @@ delete_breakpoint (bpt)
free (bpt);
}
void map_breakpoint_numbers ();
static void map_breakpoint_numbers ();
static void
delete_command (arg, from_tty)
@ -1048,19 +1140,41 @@ enable_delete_command (args)
map_breakpoint_numbers (args, enable_delete_breakpoint);
}
/*
* Use default_breakpoint_'s, or nothing if they aren't valid.
*/
struct symtabs_and_lines
decode_line_spec_1 (string, funfirstline)
char *string;
int funfirstline;
{
struct symtabs_and_lines sals;
if (string == 0)
error ("Empty line specification.");
if (default_breakpoint_valid)
sals = decode_line_1 (&string, funfirstline,
default_breakpoint_symtab, default_breakpoint_line);
else
sals = decode_line_1 (&string, funfirstline, 0, 0);
if (*string)
error ("Junk at end of line specification: %s", string);
return sals;
}
/* Chain containing all defined enable commands. */
struct cmd_list_element *enablelist;
extern struct cmd_list_element
*enablelist, *disablelist,
*deletelist, *enablebreaklist;
extern struct cmd_list_element *cmdlist;
static
initialize ()
void
_initialize_breakpoint ()
{
breakpoint_chain = 0;
breakpoint_count = 0;
enablelist = 0;
add_com ("ignore", class_breakpoint, ignore_command,
"Set ignore-count of breakpoint number N to COUNT.");
@ -1068,6 +1182,7 @@ initialize ()
add_com ("commands", class_breakpoint, commands_command,
"Set commands to be executed when a breakpoint is hit.\n\
Give breakpoint number as argument after \"commands\".\n\
With no argument, the targeted breakpoint is the last one set.\n\
The commands themselves follow starting on the next line.\n\
Type a line containing \"end\" to indicate the end of them.\n\
Give \"silent\" as the first line to make the breakpoint silent;\n\
@ -1085,35 +1200,80 @@ so it will be disabled when hit. Equivalent to \"break\" followed\n\
by using \"enable once\" on the breakpoint number.");
add_prefix_cmd ("enable", class_breakpoint, enable_command,
"Enable some breakpoints. Give breakpoint numbers as arguments.\n\
"Enable some breakpoints or auto-display expressions.\n\
Give breakpoint numbers (separated by spaces) as arguments.\n\
With no subcommand, breakpoints are enabled until you command otherwise.\n\
This is used to cancel the effect of the \"disable\" command.\n\
With a subcommand you can enable temporarily.",
With a subcommand you can enable temporarily.\n\
\n\
The \"display\" subcommand applies to auto-displays instead of breakpoints.",
&enablelist, "enable ", 1, &cmdlist);
add_cmd ("delete", 0, enable_delete_command,
add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command,
"Enable some breakpoints or auto-display expressions.\n\
Give breakpoint numbers (separated by spaces) as arguments.\n\
With no subcommand, breakpoints are enabled until you command otherwise.\n\
This is used to cancel the effect of the \"disable\" command.\n\
May be abbreviates to simply \"enable\".\n\
With a subcommand you can enable temporarily.",
&enablebreaklist, "enable breakpoints ", 1, &enablelist);
add_cmd ("once", no_class, enable_once_command,
"Enable breakpoints for one hit. Give breakpoint numbers.\n\
If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
See the \"tbreak\" command which sets a breakpoint and enables it once.",
&enablebreaklist);
add_cmd ("delete", no_class, enable_delete_command,
"Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
If a breakpoint is hit while enabled in this fashion, it is deleted.",
&enablebreaklist);
add_cmd ("delete", no_class, enable_delete_command,
"Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
If a breakpoint is hit while enabled in this fashion, it is deleted.",
&enablelist);
add_cmd ("once", 0, enable_once_command,
add_cmd ("once", no_class, enable_once_command,
"Enable breakpoints for one hit. Give breakpoint numbers.\n\
If a breakpoint is hit while enabled in this fashion, it becomes disabled.\n\
See the \"tbreak\" command which sets a breakpoint and enables it once.",
&enablelist);
add_com ("disable", class_breakpoint, disable_command,
"Disable some breakpoints. Give breakpoint numbers as arguments.\n\
With no arguments, disable all breakpoints.\n\
A disabled breakpoint is not forgotten,\n\
but it has no effect until enabled again.");
add_prefix_cmd ("disable", class_breakpoint, disable_command,
"Disable some breakpoints or auto-display expressions.\n\
Arguments are breakpoint numbers with spaces in between.\n\
To disable all breakpoints, give no argument.\n\
A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
\n\
The \"display\" subcommand applies to auto-displays instead of breakpoints.",
&disablelist, "disable ", 1, &cmdlist);
add_com_alias ("dis", "disable", class_breakpoint, 1);
add_com ("delete", class_breakpoint, delete_command,
"Delete breakpoints, specifying breakpoint numbers; or all breakpoints.\n\
add_abbrev_cmd ("breakpoints", class_breakpoint, disable_command,
"Disable some breakpoints or auto-display expressions.\n\
Arguments are breakpoint numbers with spaces in between.\n\
To delete all breakpoints, give no argument.");
To disable all breakpoints, give no argument.\n\
A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
This command may be abbreviated \"disable\".",
&disablelist);
add_prefix_cmd ("delete", class_breakpoint, delete_command,
"Delete some breakpoints or auto-display expressions.\n\
Arguments are breakpoint numbers with spaces in between.\n\
To delete all breakpoints, give no argument.\n\
\n\
The \"display\" subcommand applies to auto-displays instead of breakpoints.",
&deletelist, "delete ", 1, &cmdlist);
add_com_alias ("d", "delete", class_breakpoint, 1);
add_com_alias ("unset", "delete", class_breakpoint, 1);
add_abbrev_cmd ("breakpoints", class_breakpoint, delete_command,
"Delete some breakpoints or auto-display expressions.\n\
Arguments are breakpoint numbers with spaces in between.\n\
To delete all breakpoints, give no argument.\n\
This command may be abbreviated \"delete\".",
&deletelist);
add_com ("clear", class_breakpoint, clear_command,
"Clear breakpoint at specified line or function.\n\
@ -1152,4 +1312,3 @@ Convenience variable \"$_\" and default examine address for \"x\"\n\
are set to the address of the last breakpoint listed.");
}
END_FILE

14
gdb/c.h
View File

@ -1,14 +0,0 @@
#include "b.h"
inline c ()
{
Foo x = 1;
{
Foo y = 2;
{
b ();
}
Foo z = 3;
}
Foo w = 4;
}

View File

@ -2,7 +2,7 @@
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 Free Software Foundation, Inc.
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
@ -24,15 +24,22 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include "defs.h"
#include "param.h"
#ifdef COFF_FORMAT
#include "initialize.h"
#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 ();
@ -52,8 +59,8 @@ static int init_lineno ();
static void enter_linenos ();
extern void free_all_symtabs ();
extern void free_all_psymtabs ();
START_FILE
/* Name of source file whose symbol data we are now processing.
This comes from a symbol named ".file". */
@ -184,12 +191,17 @@ coff_lookup_type (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[type_vector_length / 2],
type_vector_length * sizeof (struct type *) / 2);
bzero (&type_vector->type[ old_vector_length ],
(type_vector_length - old_vector_length) * sizeof(struct type *));
}
return &type_vector->type[index];
}
@ -359,6 +371,7 @@ 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)
@ -366,21 +379,12 @@ record_line (line, pc)
line_vector_length *= 2;
line_vector = (struct linetable *)
xrealloc (line_vector, sizeof (struct linetable)
+ line_vector_length * sizeof (int));
+ (line_vector_length
* sizeof (struct linetable_entry)));
}
/* If this line is not continguous with previous one recorded,
all lines between subsequent line and current one are same pc.
Add one item to line vector, and if more than one line skipped,
record a line-number entry for it. */
if (prev_line_number > 0 && line != prev_line_number + 1)
line_vector->item[line_vector_index++] = pc;
if (prev_line_number < 0 || line > prev_line_number + 2)
line_vector->item[line_vector_index++] = - line;
prev_line_number = line;
/* Record the core address of the line. */
line_vector->item[line_vector_index++] = pc;
e = line_vector->item + line_vector_index++;
e->line = line; e->pc = pc;
}
/* Start a new symtab for a new source file.
@ -402,7 +406,8 @@ start_symtab ()
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 (int));
xmalloc (sizeof (struct linetable)
+ line_vector_length * sizeof (struct linetable_entry));
}
/* Save the vital information for use when closing off the current file.
@ -438,18 +443,31 @@ end_symtab ()
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 this source file. */
/* Now create the symtab object for this source file. */
symtab = (struct symtab *) xmalloc (sizeof (struct symtab));
symtab->free_ptr = 0;
@ -460,7 +478,8 @@ end_symtab ()
lv = line_vector;
lv->nitems = line_vector_index;
symtab->linetable = (struct linetable *)
xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int));
xrealloc (lv, (sizeof (struct linetable)
+ lv->nitems * sizeof (struct linetable_entry)));
symtab->nlines = 0;
symtab->line_charpos = 0;
@ -468,6 +487,7 @@ end_symtab ()
symtab->next = symtab_list;
symtab_list = symtab;
/* Reinitialize for beginning of new file. */
line_vector = 0;
line_vector_length = -1;
last_source_file = 0;
@ -525,6 +545,21 @@ record_misc_function (name, address)
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;
@ -621,8 +656,9 @@ sort_syms ()
for (i = 0; i < nbl; i++)
{
b = BLOCKVECTOR_BLOCK (bv, i);
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
sizeof (struct symbol *), compare_symbols);
if (BLOCK_SHOULD_SORT (b))
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
sizeof (struct symbol *), compare_symbols);
}
}
}
@ -648,6 +684,9 @@ symbol_file_command (name)
{
if (symtab_list && !query ("Discard symbol table? ", 0))
error ("Not confirmed.");
if (symfile)
free (symfile);
symfile = 0;
free_all_symtabs ();
return;
}
@ -689,6 +728,8 @@ symbol_file_command (name)
/* 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;
@ -783,23 +824,35 @@ read_coff_symtab (desc, nsyms)
int desc;
int nsyms;
{
FILE *stream = fdopen (desc, "r");
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;
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;
@ -835,26 +888,19 @@ read_coff_symtab (desc, nsyms)
if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG)
complete_symtab (filestring, 0, 0);
if (ISFCN (cs->c_type))
/* Typedefs should not be treated as symbol definitions. */
if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF)
{
/*
* gdb expects all functions to also be in misc_function
* list -- why not...
/* 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;
within_function = 1;
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 = cs->c_value;
new->name = process_coff_symbol (cs, &main_aux);
fcn_start_addr = cs->c_value;
fcn_cs_saved = *cs;
fcn_sym_saved = main_sym;
fcn_aux_saved = main_aux;
continue;
}
@ -889,79 +935,84 @@ read_coff_symtab (desc, nsyms)
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_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_STAT:
if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF)
{
if (strcmp (cs->c_name, _TEXT) == 0)
{
if (num_object_files == 1)
{
/* Record end address of first file, crt0.s */
first_object_file_end =
cs->c_value + main_aux.x_scn.x_scnlen;
}
/*
* Fill in missing information for debugged
* object file only if we have line number info.
*/
if (main_aux.x_scn.x_nlinno > 0)
{
complete_symtab (filestring, cs->c_value,
main_aux.x_scn.x_scnlen);
}
break;
}
else if (strcmp (cs->c_name, _DATA) == 0)
break;
else if (strcmp (cs->c_name, _BSS) == 0)
break;
/* get rid of assembly labels here */
/* record_misc_function (cs->c_name, cs->c_value); */
break;
}
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)
{
/* value contains address of exit/return from function */
/* round it up to next multiple of 16 */
cs->c_value = (cs->c_value + 15) & -16;
/* 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, cs->c_value);
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);
@ -987,7 +1038,8 @@ read_coff_symtab (desc, nsyms)
{
new = context_stack;
if (new == 0 || depth != new->depth)
error ("Invalid symbol data: .bb/.eb symbol mismatch.");
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. */
@ -1027,12 +1079,25 @@ read_file_hdr (chan, file_hdr)
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
}
}
@ -1107,15 +1172,22 @@ init_stringtab (chan, 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 (val != sizeof buffer)
return -1;
if (stringtab)
free (stringtab);
/* 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;
@ -1166,9 +1238,11 @@ getfilename (aux_entry)
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';
@ -1365,8 +1439,8 @@ process_coff_symbol (cs, aux)
if (ISFCN (cs->c_type))
{
SYMBOL_TYPE (sym)
= lookup_function_type (decode_function_type (cs, cs->c_type, aux));
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);
@ -1571,8 +1645,8 @@ decode_base_type (cs, c_type, aux)
switch (c_type)
{
case T_NULL:
/* shouldn't show up here */
break;
/* shows up with "void (*foo)();" structure members */
return builtin_type_void;
case T_ARG:
/* shouldn't show up here */
@ -1691,12 +1765,13 @@ read_struct_type (index, length, lastsym)
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 (symnum < lastsym && symnum < nlist_nsyms_global)
while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
{
read_one_sym (ms, &sub_sym, &sub_aux);
name = ms->c_name;
@ -1736,6 +1811,7 @@ read_struct_type (index, length, lastsym)
break;
case C_EOS:
done = 1;
break;
}
}
@ -1829,23 +1905,48 @@ read_enum_type (index, length, lastsym)
{
SYMBOL_TYPE (syms->symbol) = type;
TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol);
TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (syms->symbol);
TYPE_FIELD_BITPOS (type, n) = 0;
TYPE_FIELD_VALUE (type, n) = 0;
TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (syms->symbol);
TYPE_FIELD_BITSIZE (type, n) = 0;
}
return type;
}
static
initialize ()
/* 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.");
}
END_FILE
#endif /* COFF_FORMAT */

View File

@ -104,6 +104,7 @@ what you give them. Help stamp out software-hoarding! */
#include "command.h"
#include "defs.h"
#include <stdio.h>
#ifdef sparc
@ -112,8 +113,6 @@ what you give them. Help stamp out software-hoarding! */
extern char *xmalloc ();
static char *savestring ();
/* Add element named NAME to command list *LIST.
FUN should be the function to execute the command;
it will get a character string as argument, with leading
@ -149,6 +148,33 @@ add_cmd (name, class, fun, doc, list)
return c;
}
/* Same as above, except that the abbrev_flag is set. */
struct cmd_list_element *
add_abbrev_cmd (name, class, fun, doc, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **list;
{
register struct cmd_list_element *c
= (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
delete_cmd (name, list);
c->next = *list;
c->name = savestring (name, strlen (name));
c->class = class;
c->function = fun;
c->doc = doc;
c->prefixlist = 0;
c->allow_unknown = 0;
c->abbrev_flag = 1;
c->aux = 0;
*list = c;
return c;
}
struct cmd_list_element *
add_alias_cmd (name, oldname, class, abbrev_flag, list)
char *name;
@ -180,7 +206,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
return c;
}
/* Like add_prefix_cmd but adds an element for a command prefix:
/* Like add_cmd but adds an element for a command prefix:
a name that should be followed by a subcommand to be looked up
in another command list. PREFIXLIST should be the address
of the variable containing that list. */
@ -204,6 +230,28 @@ add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
return c;
}
/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
struct cmd_list_element *
add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
allow_unknown, list)
char *name;
int class;
void (*fun) ();
char *doc;
struct cmd_list_element **prefixlist;
char *prefixname;
int allow_unknown;
struct cmd_list_element **list;
{
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
c->prefixlist = prefixlist;
c->prefixname = prefixname;
c->allow_unknown = allow_unknown;
c->abbrev_flag = 1;
return c;
}
/* Remove the command named NAME from the command list. */
void
@ -228,65 +276,86 @@ delete_cmd (name, list)
}
}
/* Implement a help command on command list LIST.
COMMAND is the argument given (a command from the list to document)
or zero for no arg (describe briefly all the commands in the list).
CMDTYPE is a string to use in the error message if command COMMAND
is not found in the list. */
void help_cmd (), help_list (), help_cmd_list ();
/* CLASS should be -1 to list all commands in LIST,
or a nonnegative class number value to list just commands in that class,
or -2 to list the classes themselves. */
/* This command really has to deal with two things:
* 1) I want documentation on *this string* (usually called by
* "help commandname").
* 2) I want documentation on *this list* (usually called by
* giving a command that requires subcommands. Also called by saying
* just "help".)
*
* I am going to split this into two seperate comamnds, help_cmd and
* help_list.
*/
void
help_cmd (command, list, cmdtype, class, stream)
help_cmd (command, stream)
char *command;
FILE *stream;
{
struct cmd_list_element *c;
extern struct cmd_list_element *cmdlist;
if (!command)
{
help_list (cmdlist, "", -2, stream);
return;
}
c = lookup_cmd (&command, cmdlist, "", 0);
if (c == 0)
return;
/* There are three cases here.
If c->prefixlist is nonzer, we have a prefix command.
Print its documentation, then list its subcommands.
If c->function is nonzero, we really have a command.
Print its documentation and return.
If c->function is zero, we have a class name.
Print its documentation (as if it were a command)
and then set class to he number of this class
so that the commands in the class will be listed. */
fprintf (stream, "%s\n", c->doc);
if (c->prefixlist == 0 && c->function != 0)
return;
fputc ('\n', stream);
/* If this is a prefix command, print it's subcommands */
if (c->prefixlist)
help_list (*c->prefixlist, c->prefixname, -1, stream);
/* If this is a class name, print all of the commands in the class */
if (c->function == 0)
help_list (cmdlist, "", c->class, stream);
}
/*
* Get a specific kind of help on a command list.
*
* LIST is the list.
* CMDTYPE is the prefix to use in the title string.
* CLASS is the class with which to list the nodes of this list (see
* documentation for help_cmd_list below), As usual, -1 for
* everything, -2 for just classes, and non-negative for only things
* in a specific class.
* and STREAM is the output stream on which to print things.
* If you call this routine with a class >= 0, it recurses.
*/
void
help_list (list, cmdtype, class, stream)
struct cmd_list_element *list;
char *cmdtype;
int class;
FILE *stream;
{
register struct cmd_list_element *c;
register char *p;
register int ncmds;
struct cmdvec { struct cmd_list_element *cmd; int class; };
register struct cmdvec *cmdvec;
char *cmdtype1, *cmdtype2;
int len;
if (command)
{
c = lookup_cmd (&command, list, cmdtype, 0);
if (c == 0)
return;
/* There are three cases here.
If c->prefixlist is nonzer, we have a prefix command.
Print its documentation, then list its subcommands.
If c->function is nonzero, we really have a command.
Print its documentation and return.
If c->function is zero, we have a class name.
Print its documentation (as if it were a command)
and then set class to he number of this class
so that the commands in the class will be listed. */
p = c->doc;
fprintf (stream, "%s\n", p);
if (c->function != 0 && c->prefixlist == 0)
return;
fputc ('\n', stream);
if (c->prefixlist)
{
list = *c->prefixlist;
class = 0;
cmdtype = c->prefixname;
}
else
class = c->class;
}
char *cmdtype1, *cmdtype2;
/* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
len = strlen (cmdtype);
cmdtype1 = (char *) alloca (len + 1);
@ -307,21 +376,7 @@ help_cmd (command, list, cmdtype, class, stream)
else
fprintf (stream, "List of %scommands:\n\n", cmdtype2);
for (c = list; c; c = c->next)
{
if (c->abbrev_flag == 0
&& (class == -1 /* Listing all */
|| (c->class == class && c->function != 0) /* Listing one class */
|| (class == -2 && c->function == 0))) /* Listing the classes */
{
fprintf (stream, "%s -- ", c->name);
/* Print just first line of documentation. */
p = c->doc;
while (*p && *p != '\n') p++;
fwrite (c->doc, 1, p - c->doc, stream);
fputc ('\n', stream);
}
}
help_cmd_list (list, class, cmdtype, (class >= 0), stream);
if (class == -2)
fprintf (stream, "\n\
@ -333,6 +388,55 @@ Type \"help%s\" followed by %scommand name for full documentation.\n\
Command name abbreviations are allowed if unambiguous.\n",
cmdtype1, cmdtype2);
}
/*
* Implement a help command on command list LIST.
* RECURSE should be non-zero if this should be done recursively on
* all sublists of LIST.
* PREFIX is the prefix to print before each command name.
* STREAM is the stream upon which the output should be written.
* CLASS should be:
* A non-negative class number to list only commands in that
* class.
* -1 to list all commands in list.
* -2 to list all classes in list.
*
* Note that RECURSE will be active on *all* sublists, not just the
* ones seclected by the criteria above (ie. the selection mechanism
* is at the low level, not the high-level).
*/
void
help_cmd_list (list, class, prefix, recurse, stream)
struct cmd_list_element *list;
int class;
char *prefix;
int recurse;
FILE *stream;
{
register struct cmd_list_element *c;
register char *p;
for (c = list; c; c = c->next)
{
if (c->abbrev_flag == 0 &&
(class == -1
|| (class == -2 && c->function == 0)
|| (class == c->class && c->function != 0)))
{
fprintf (stream, "%s%s -- ", prefix, c->name);
/* Print just the first line */
p = c->doc;
while (*p && *p != '\n') p++;
fwrite (c->doc, 1, p - c->doc, stream);
fputc('\n', stream);
}
if (recurse
&& c->prefixlist != 0
&& c->abbrev_flag == 0)
help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
}
}
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
@ -355,6 +459,8 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
register struct cmd_list_element *c, *found;
int nfound;
char ambbuf[100];
char *processed_cmd;
int i, cmd_len;
/* Skip leading whitespace. */
@ -371,29 +477,53 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
/* Find end of command name. */
p = *line;
while (*p == '-'
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9'))
{
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
p++;
}
if (*p == '!')
p++;
else while (*p == '-'
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9'))
p++;
/* Look up the command name.
If exact match, keep that.
Otherwise, take command abbreviated, if unique. */
Otherwise, take command abbreviated, if unique. Note that (in my
opinion) a null string does *not* indicate ambiguity; simply the
end of the argument. */
if (p == *line)
{
if (!allow_unknown)
error ("Lack of needed %scommand", cmdtype);
return 0;
}
/* Copy over to a local buffer, converting to lowercase on the way.
This is in case the command being parsed is a subcommand which
doesn't match anything, and that's ok. We want the original
untouched for the routine of the original command. */
processed_cmd = (char *) alloca (p - *line + 1);
for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
{
char x = (*line)[cmd_len];
if (x >= 'A' && x <= 'Z')
processed_cmd[cmd_len] = x - 'A' + 'a';
else
processed_cmd[cmd_len] = x;
}
processed_cmd[cmd_len] = '\0';
/* Check all possibilities in the current command list. */
found = 0;
nfound = 0;
for (c = list; c; c = c->next)
{
if (!strncmp (*line, c->name, p - *line))
if (!strncmp (processed_cmd, c->name, cmd_len))
{
found = c;
nfound++;
if (c->name[p - *line] == 0)
if (c->name[cmd_len] == 0)
{
nfound = 1;
break;
@ -407,10 +537,9 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
{
if (nfound > 1 && allow_unknown >= 0)
{
*p = 0;
ambbuf[0] = 0;
for (c = list; c; c = c->next)
if (!strncmp (*line, c->name, p - *line))
if (!strncmp (processed_cmd, c->name, cmd_len))
{
if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
{
@ -424,13 +553,11 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
break;
}
}
error ("Ambiguous %scommand \"%s\": %s.", cmdtype, *line, ambbuf);
error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
processed_cmd, ambbuf);
}
else if (!allow_unknown)
{
*p = 0;
error ("Undefined %scommand: \"%s\".", cmdtype, *line);
}
error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
return 0;
}
@ -450,17 +577,48 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
return found;
}
/* 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. */
static char *
savestring (ptr, size)
char *ptr;
int size;
static void
shell_escape (arg, from_tty)
char *arg;
int from_tty;
{
register char *p = (char *) xmalloc (size + 1);
bcopy (ptr, p, size);
p[size] = 0;
return p;
int rc, status, pid;
char *p, *user_shell;
extern char *rindex ();
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
user_shell = "/bin/sh";
/* Get the name of the shell for arg0 */
if ((p = rindex (user_shell, '/')) == NULL)
p = user_shell;
else
p++; /* Get past '/' */
if ((pid = fork()) == 0)
{
if (!arg)
execl (user_shell, p, 0);
else
execl (user_shell, p, "-c", arg, 0);
fprintf (stderr, "Exec of shell failed\n");
exit (0);
}
if (pid != -1)
while ((rc = wait (&status)) != pid && rc != -1)
;
else
error ("Fork failed");
}
void
_initialize_command ()
{
add_com ("shell", class_support, shell_escape,
"Execute the rest of the line as a shell command. \n\
With no arguments, run an inferior shell.");
add_com_alias ("!", "shell", class_support, 1);
}

View File

@ -4,7 +4,7 @@
# Shell script to create proper links to machine-dependent files in
# preparation for compiling gdb.
#
# Usage: config.gdb machine
# 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,
@ -13,79 +13,159 @@
progname=$0
case $# in
case $# in
1)
machine=$1
paramfile=m-${machine}.h
initfile=m-${machine}init.h
pinsnfile=${machine}-pinsn.c
opcodefile=${machine}-opcode.h
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
case $machine in
hp9k320)
initfile=m-sun3init.h
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
hp9k320bsd)
initfile=m-sun3init.h
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
isi)
# some version of m68k-pinsn.c should work here
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
merlin)
# m-umaxinit.h?
initfile=unknown-or-unavailable
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)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun3)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun4)
pinsnfile=sparc-pinsn.c
opcodefile=sparc-opcode.h
;;
umax)
pinsnfile=ns32k-pinsn.c
opcodefile=ns32k-opcode.h
;;
test)
paramfile=one
initfile=two
pinsnfile=three
opcodefile=four
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 $initfile $pinsnfile $opcodefile"
links="param.h m-init.h pinsn.c opcode.h"
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=$*
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',"
@ -103,21 +183,10 @@ case $# in
exit 1
fi
echo "Linked \`$link' to \`$file'."
done
echo "Links are now set up for use with a $machine." \
| tee config.status
exit 0
;;
*)
echo "Usage: $progname machine"
echo -n "Where \`machine' is something like "
echo "\`vax', \`sun3', \`umax', etc."
if [ -r config.status ]
then
cat config.status
fi
exit 1
;;
esac
done
echo "Links are now set up for use with a $machine." \
| tee config.status
exit 0

524
gdb/convex-dep.c Normal file
View File

@ -0,0 +1,524 @@
/* 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>
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <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. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
/* Convex ptrace needs an extra 0 arg */
ptrace (8, inferior_pid, 0, 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
{
extern char registers[];
/* Blam the trace bits in the stack's saved psws to match the
desired step mode. This is required so that single-stepping a
return doesn't restore a psw with a clear trace bit and fly away,
and conversely, proceeding through a return in a routine that was
stepped into doesn't cause a phantom break by restoring a psw
with the trace bit set. */
scan_stack (PSW_T_BIT, step);
/* Write the registers back now */
ptrace (11, inferior_pid, 0, registers, REGISTER_BYTES);
if (errno != 0) perror_with_name ("writing registers");
errno = 0;
ptrace (step ? 9 : 7, inferior_pid, 1, &signal, sizeof signal);
if (errno)
perror_with_name ("ptrace");
}
}
void
fetch_inferior_registers ()
{
extern char registers[];
ptrace (10, inferior_pid, 0, registers, REGISTER_BYTES);
}
/* 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;
{
/* do this only once, right before resuming inferior. */
return;
}
/* 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;
{
errno = 0;
ptrace (1, inferior_pid, memaddr, myaddr, len);
if (errno)
bzero (myaddr, len);
return errno;
}
/* Copy LEN bytes of data from debugger memnory at MYADDR
to inferior's memory at MEMADDR.
Returns errno on failure (cannot write the inferior) */
int
write_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
errno = 0;
ptrace (4, inferior_pid, memaddr, myaddr, len);
return errno;
}
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* Required by convex's SOFF format
It may be desirable to remove the conditionals for SOFF_FORMAT, if
Convex is the only machine which will ever make use of them. */
#ifdef SOFF_FORMAT
#include <convex/filehdr.h>
#include <convex/opthdr.h>
#include <convex/scnhdr.h>
#include <convex/core.h>
#endif /* SOFF_FORMAT */
/* 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);
#ifdef SOFF_FORMAT
{
extern char *sys_errlist[], *sys_siglist[];
extern int sys_nerr;
int stop_signal;
struct core_hdr corehdr;
struct user u;
if (myread (corechan, &corehdr, sizeof corehdr) < 0)
perror_with_name (filename);
if (corehdr.c_magic != CH_MAGIC)
error ("%s: not a core file.", filename);
lseek (corechan, corehdr.c_user, 0);
if (myread (corechan, &u, sizeof u) < 0)
perror_with_name (filename);
lseek (corechan, corehdr.c_syscall_context, 0);
if (myread (corechan, registers, REGISTER_BYTES) < 0)
perror_with_name (filename);
if (corehdr.c_vecst)
{
lseek (corechan, corehdr.c_vecst, 0);
if (myread (corechan, vecst, sizeof vecst) < 0)
perror_with_name (filename);
}
data_offset = corehdr.c_data;
data_start = exec_data_start;
data_end = data_start + ctob (u.u_dsize);
stack_offset = corehdr.c_stack;
stack_start = stack_end - ctob (u.u_ssize);
printf ("Program %s", u.u_comm );
if (u.u_error >= sys_nerr)
printf (", last error: %d (undocumented),\n", u.u_error);
else if (u.u_error != 0)
printf (", last error: %s,", sys_errlist[u.u_error]);
stop_signal = u.u_arg[0];
printf (" received signal %d, %s\n", stop_signal,
stop_signal < NSIG ? sys_siglist[stop_signal] : "(undocumented)");
core_aouthdr.a_magic = 0;
}
#ifdef SOFF_FORMAT
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename);
}
/* Convex-specific code: remove the frame stored by a
user-mode trap, if present */
if (read_register (PC_REGNUM) > STACK_END_ADDR)
{
POP_FRAME;
}
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;
val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
if (val < 0)
perror_with_name (filename);
/* Convex-specific SOFF-FORMAT */
#ifdef SOFF_FORMAT
if (IS_SOFF_MAGIC (exec_aouthdr.a_magic))
{
FILEHDR filhdr;
OPTHDR opthdr;
SCNHDR scnhdr;
int n, gotem;
lseek (execchan, 0L, 0);
if (myread (execchan, &filhdr, sizeof filhdr) < 0)
perror_with_name (filename);
if (myread (execchan, &opthdr, filhdr.h_opthdr) <= 0)
perror_with_name (filename);
lseek (execchan, (long) filhdr.h_scnptr, 0);
n = -1;
gotem = 0;
while (++n < filhdr.h_nscns && gotem < 2)
{
if (myread (execchan, &scnhdr, SCNHSZ) < 0)
perror_with_name (filename);
if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT)
{
text_start = scnhdr.s_vaddr;
text_end = text_start + scnhdr.s_size;
text_offset = scnhdr.s_scnptr;
++gotem;
}
else if ((scnhdr.s_flags & S_TYPMASK) == S_DATA)
{
exec_data_start = scnhdr.s_vaddr;
exec_data_end = exec_data_start + scnhdr.s_size;
exec_data_offset = scnhdr.s_scnptr;
data_start = exec_data_start;
data_end += exec_data_start;
++gotem;
}
}
}
else
#endif SOFF_FORMAT
{
text_start = N_TXTADDR (exec_aouthdr);
text_end = text_start + exec_aouthdr.a_text;
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_start = N_DATADDR (exec_aouthdr);
exec_data_end = exec_data_start + exec_aouthdr.a_data;
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
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);
}

View File

@ -1,5 +1,5 @@
/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
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
@ -18,11 +18,29 @@ 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 "initialize.h"
#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>
@ -30,28 +48,21 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/file.h>
#include <sys/stat.h>
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
#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 NEW_SUN_CORE
#include <sys/core.h>
#else /* not NEW_SUN_CORE */
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else /* not UMAX_CORE */
#else
#include <sys/user.h>
#ifdef HP9K320
#include <sys/reg.h>
#include <sys/trap.h>
#ifdef HPUX_VERSION_5
#define e_PS e_regs[PS]
#define e_PC e_regs[PC]
#endif /* HPUX_VERSION_5 */
#endif /* HP9K320 */
#endif /* not UMAX_CORE */
#endif /* not NEW_SUN_CORE */
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
@ -61,20 +72,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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
#define AOUTHDR struct exec
#endif
extern char *sys_siglist[];
START_FILE
extern core_file_command (), exec_file_command ();
/* Hook for `exec_file_command' command to call. */
@ -82,15 +86,15 @@ void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
static char *corefile;
static char *execfile;
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. */
static int corechan;
static int execchan;
int corechan;
int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
@ -99,10 +103,10 @@ int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
static CORE_ADDR data_start;
static CORE_ADDR data_end;
static CORE_ADDR stack_start;
static CORE_ADDR stack_end;
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. */
@ -110,361 +114,49 @@ static CORE_ADDR stack_end;
CORE_ADDR text_start;
CORE_ADDR text_end;
static CORE_ADDR exec_data_start;
static CORE_ADDR exec_data_end;
CORE_ADDR exec_data_start;
CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
static int text_offset;
int text_offset;
/* Address in executable file of start of data area data. */
static int exec_data_offset;
int exec_data_offset;
/* Address in core file of start of data area data. */
static int data_offset;
int data_offset;
/* Address in core file of start of stack area data. */
static int stack_offset;
int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
static FILHDR file_hdr;
static SCNHDR text_hdr;
static SCNHDR data_hdr;
FILHDR file_hdr;
SCNHDR text_hdr;
SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
static AOUTHDR core_aouthdr;
AOUTHDR core_aouthdr;
/* a.out header of exec file. */
static AOUTHDR exec_aouthdr;
AOUTHDR exec_aouthdr;
static void validate_files ();
void validate_files ();
unsigned int register_addr ();
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);
#ifdef NEW_SUN_CORE
{
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));
data_start = exec_data_start;
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;
#if defined(sun2) || defined(sun3)
bcopy (&corestr.c_regs, registers, 16 * 4);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
bcopy (corestr.c_fpstatus.fps_regs,
&registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof corestr.c_fpstatus.fps_regs);
bcopy (&corestr.c_fpstatus.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
#endif
#if defined(sun4)
/* G0 *always* holds 0. */
*(int *)&registers[REGISTER_BYTE (0)] = 0;
/* The globals and output registers. I don't know where
to get the locals and input registers from the core file. */
bcopy (&corestr.c_regs.r_g1, registers, 15 * 4);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
*(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc;
*(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y;
bcopy (corestr.c_fpu.fpu_regs,
&registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof corestr.c_fpu.fpu_regs);
#ifdef FPU
bcopy (&corestr.c_fpu.fpu_fsr,
&registers[REGISTER_BYTE (FPS_REGNUM)],
sizeof (FPU_FSR_TYPE));
#endif
#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)");
}
#else /* not NEW_SUN_CORE */
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
#ifdef UMAX_CORE
struct ptrace_user u;
#else
struct user u;
#endif
int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name (filename);
data_start = exec_data_start;
#ifdef UMAX_CORE
data_end = data_start + u.pt_dsize;
stack_start = stack_end - u.pt_ssize;
data_offset = sizeof u;
stack_offset = data_offset + u.pt_dsize;
reg_offset = 0;
bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
printf ("Core file is from \"%s\".\n", u.pt_comm);
if (u.pt_signal > 0)
printf ("Program terminated with signal %d, %s.\n",
u.pt_signal,
u.pt_signal < NSIG
? sys_siglist[u.pt_signal]
: "(undocumented)");
#else /* not UMAX_CORE */
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);
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
core_aouthdr.a_magic = 0;
#endif /* not UMAX_CORE */
/* Read the register values out of the core file and store
them where `read_register' will find them. */
#ifdef HP9K320
{
register int regno;
struct exception_stack es;
int val;
val = lseek (corechan, (REGISTER_ADDR (reg_offset, 0)), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, es,
((char *) &es.e_regs[R0] - (char *) &es.e_offset));
if (val < 0)
perror_with_name (filename);
for (regno = 0; (regno < PS_REGNUM); regno++)
supply_register (regno, &es.e_regs[regno + R0]);
val = es.e_PS;
supply_register (regno++, &val);
supply_register (regno++, &es.e_PC);
for (; (regno < NUM_REGS); regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, (FP_REGISTER_ADDR (u, regno)), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
supply_register (regno, buf);
}
}
#else /* not HP9K320 */
{
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 (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
supply_register (regno, buf);
}
}
#endif /* not HP9K320 */
}
#endif /* not NEW_SUN_CORE */
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename);
}
set_current_frame (read_register (FP_REGNUM));
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 gould
FILHDR exec_coffhdr;
val = myread (execchan, &exec_coffhdr, sizeof exec_coffhdr);
if (val < 0)
perror_with_name (filename);
#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);
#ifdef gould
text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)
+ exec_aouthdr.a_text;
#else
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
#endif
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);
}
/* 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) ();
{
@ -475,6 +167,7 @@ specify_exec_file_hook (hook)
If it is needed again after the inferior dies, it must
be reopened. */
void
close_exec_file ()
{
if (execchan >= 0)
@ -482,6 +175,7 @@ close_exec_file ()
execchan = -1;
}
void
reopen_exec_file ()
{
if (execchan < 0 && execfile != 0)
@ -497,7 +191,7 @@ reopen_exec_file ()
This should really check that the core file came
from that exec file, but I don't know how to do it. */
static void
void
validate_files ()
{
if (execfile != 0 && corefile != 0)
@ -506,7 +200,7 @@ validate_files ()
fstat (corechan, &st_core);
if (core_aouthdr.a_magic != 0
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)
@ -544,49 +238,54 @@ files_info ()
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
if (corefile == 0)
printf ("No core dump file\n");
if (corefile)
printf ("Core dump file \"%s\".\n", corefile);
else
printf ("Core dump file \"%s\".\n", corefile);
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 loaded from \"%s\".\n", symfile);
printf ("Symbols from \"%s\".\n", symfile);
if (! have_inferior_p ())
{
if (execfile)
{
printf ("Text segment from 0x%x to 0x%x.\n",
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 from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
data_start, data_end, stack_start, stack_end);
}
else
{
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
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 */
/* 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 ())
read_inferior_memory (memaddr, myaddr, len);
return read_inferior_memory (memaddr, myaddr, len);
else
xfer_core_file (memaddr, myaddr, len, 0);
return xfer_core_file (memaddr, myaddr, len);
}
/* Write LEN bytes of data starting at address MYADDR
@ -605,6 +304,15 @@ write_memory (memaddr, myaddr, len)
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;
@ -615,6 +323,7 @@ xfer_core_file (memaddr, myaddr, len)
int xferchan;
char **xferfile;
int fileptr;
int returnval = 0;
while (len > 0)
{
@ -625,30 +334,17 @@ xfer_core_file (memaddr, myaddr, len)
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. */
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);
}
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. */
else if (memaddr >= data_start && memaddr < data_end)
if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
@ -679,6 +375,31 @@ xfer_core_file (memaddr, myaddr, len)
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. */
@ -697,19 +418,25 @@ xfer_core_file (memaddr, myaddr, len)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing. */
read zeros if reading, or do nothing if writing.
(FIXME we never write.) */
else
bzero (myaddr, i);
{
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;
@ -753,8 +480,8 @@ register_addr (regno, blockend)
#endif /* REGISTER_U_ADDR */
static
initialize ()
void
_initialize_core()
{
corechan = -1;
execchan = -1;
@ -782,4 +509,3 @@ No arg means have no executable file.");
add_info ("files", files_info, "Names of files being debugged.");
}
END_FILE

36
gdb/createtags Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
#
# Here we check to see if we are compiling in a directory that contains
# symlinks to the source files instead of the actual files. If this is so,
# we setup the TAGS entries to point to the actual source directory.
#
filelist=""
if test -h main.c ; then
prefix=`ls -l main.c | awk '{print $11}' | sed 's;main.c$;;'`
echo path 1
else
prefix=""
fi
for i in $@ ; do
filelist="$prefix$i $filelist"
done
#
# Here we simply make sure that the actual machine dependent files being used
# (if any) are ahead of all of the other machine dependent files in the list.
# This means that M-. will (almost) always give you exactly the routine
# you want.
#
if test -f param.h ; then
if `grep '^#define[ ]*COFF_FORMAT' param.h > /dev/null 2>&1`; then
frmatfile=${prefix}coffread.c
else
frmatfile=${prefix}dbxread.c
fi
hfile=$prefix`ls -l param.h | awk '{print $11}'`
dfile=$prefix`ls -l dep.c | awk '{print $11}'`
ofile=$prefix`ls -l opcode.h | awk '{print $11}'`
pfile=$prefix`ls -l pinsn.c | awk '{print $11}'`
etags $hfile $dfile $ofile $pfile $frmatfile $filelist
else
etags $filelist
fi

File diff suppressed because it is too large Load Diff

601
gdb/default-dep.c Normal file
View File

@ -0,0 +1,601 @@
/* 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);
}

View File

@ -26,6 +26,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
extern char *savestring ();
extern char *concat ();
extern char *xmalloc (), *xrealloc ();
extern char *alloca ();
extern int parse_escape ();
extern char *reg_names[];
@ -37,8 +38,9 @@ extern int immediate_quit;
enum command_class
{
class_run, class_vars, class_stack, class_files, class_support, class_info,
class_breakpoint, class_alias, class_obscure, class_user,
no_class = -1, class_run = 0, class_vars, class_stack,
class_files, class_support, class_info, class_breakpoint,
class_alias, class_obscure, class_user,
};
/* the cleanup list records things that have to be undone
@ -61,6 +63,8 @@ struct cleanup
extern void do_cleanups ();
extern void discard_cleanups ();
extern struct cleanup *make_cleanup ();
extern struct cleanup *save_cleanups ();
extern void restore_cleanups ();
extern void free_current_contents ();
/* Structure for saved commands lines
@ -81,3 +85,4 @@ char *current_directory;
#ifdef sparc
#include <alloca.h>
#endif

1
gdb/dep.c Symbolic link
View File

@ -0,0 +1 @@
sparc-dep.c

View File

@ -19,12 +19,11 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "symtab.h"
#include "value.h"
#include "expression.h"
START_FILE
/* Parse the string EXP as a C expression, evaluate it,
and return the result as a number. */
@ -38,7 +37,7 @@ parse_and_eval_address (exp)
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
addr = value_as_long (evaluate_expression (expr));
addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
do_cleanups (old_chain);
return addr;
}
@ -104,9 +103,11 @@ static value evaluate_subexp_with_coercion ();
/* Values of NOSIDE argument to eval_subexp. */
enum noside
{ EVAL_NORMAL,
EVAL_SKIP,
EVAL_AVOID_SIDE_EFFECTS,
{ EVAL_NORMAL,
EVAL_SKIP, /* Only effect is to increment pos. */
EVAL_AVOID_SIDE_EFFECTS, /* Don't modify any variables or
call any functions. Correct type
is returned. */
};
value
@ -137,7 +138,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
{
enum exp_opcode op;
int tem;
register int pc, pc2, *oldpos;
register int pc, pc2, oldpos;
register value arg1, arg2, arg3;
int nargs;
value *argvec;
@ -171,16 +172,38 @@ evaluate_subexp (expect_type, exp, pos, noside)
case OP_LAST:
(*pos) += 2;
return access_value_history (exp->elts[pc + 1].longconst);
return access_value_history ((int) exp->elts[pc + 1].longconst);
case OP_REGISTER:
(*pos) += 2;
return value_of_register (exp->elts[pc + 1].longconst);
return value_of_register ((int) exp->elts[pc + 1].longconst);
case OP_INTERNALVAR:
(*pos) += 2;
return value_of_internalvar (exp->elts[pc + 1].internalvar);
case OP_STRING:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
if (noside == EVAL_SKIP)
goto nosideret;
return value_string (&exp->elts[pc + 1].string, tem);
case TERNOP_COND:
/* Skip third and second args to evaluate the first one. */
arg1 = evaluate_subexp (0, exp, pos, noside);
if (value_zerop (arg1))
{
evaluate_subexp (0, exp, pos, EVAL_SKIP);
return evaluate_subexp (0, exp, pos, noside);
}
else
{
arg2 = evaluate_subexp (0, exp, pos, noside);
evaluate_subexp (0, exp, pos, EVAL_SKIP);
return arg2;
}
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
@ -189,7 +212,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
int fnptr;
int tem2;
nargs = exp->elts[pc + 1].longconst + 1;
nargs = (int) exp->elts[pc + 1].longconst + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
@ -213,7 +236,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg1 = evaluate_subexp (0, exp, pos, noside);
fnptr = value_as_long (arg1);
fnptr = (int) value_as_long (arg1);
if (fnptr < 128)
{
struct type *basetype;
@ -262,7 +285,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
/* Hair for method invocations */
int tem2;
nargs = exp->elts[pc + 1].longconst + 1;
nargs = (int) exp->elts[pc + 1].longconst + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
tem2 = strlen (&exp->elts[pc2 + 1].string);
@ -283,7 +306,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
nargs = exp->elts[pc + 1].longconst;
nargs = (int) exp->elts[pc + 1].longconst;
tem = 0;
}
argvec = (value *) alloca (sizeof (value) * (nargs + 2));
@ -311,31 +334,24 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
{
/* If the return type doesn't look like a function type, call an
error. This can happen if somebody tries to turn a variable into
a function call. This is here because people often want to
call, eg, strcmp, which gdb doesn't know is a function. If
gdb isn't asked for it's opinion (ie. through "whatis"),
it won't offer it. */
struct type *ftype =
TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
if (ftype)
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
else
error ("Expression of type other than \"Function returning ...\" used as function");
}
return call_function (argvec[0], nargs, argvec + 1);
case OP_STRING:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
if (noside == EVAL_SKIP)
goto nosideret;
return value_string (&exp->elts[pc + 1].string, tem);
case TERNOP_COND:
/* Skip third and second args to evaluate the first one. */
arg1 = evaluate_subexp (0, exp, pos, noside);
if (value_zerop (arg1))
{
evaluate_subexp (0, exp, pos, EVAL_SKIP);
return evaluate_subexp (0, exp, pos, noside);
}
else
{
arg2 = evaluate_subexp (0, exp, pos, noside);
evaluate_subexp (0, exp, pos, EVAL_SKIP);
return arg2;
}
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
@ -452,6 +468,16 @@ evaluate_subexp (expect_type, exp, pos, noside)
case BINOP_AND:
arg1 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
{
arg2 = evaluate_subexp (0, exp, pos, noside);
goto nosideret;
}
oldpos = *pos;
arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
*pos = oldpos;
if (binop_user_defined_p (op, arg1, arg2))
{
arg2 = evaluate_subexp (0, exp, pos, noside);
@ -463,11 +489,21 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg2 = evaluate_subexp (0, exp, pos,
(tem ? EVAL_SKIP : noside));
return value_from_long (builtin_type_int,
!tem && !value_zerop (arg2));
(LONGEST) (!tem && !value_zerop (arg2)));
}
case BINOP_OR:
arg1 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
{
arg2 = evaluate_subexp (0, exp, pos, noside);
goto nosideret;
}
oldpos = *pos;
arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
*pos = oldpos;
if (binop_user_defined_p (op, arg1, arg2))
{
arg2 = evaluate_subexp (0, exp, pos, noside);
@ -479,7 +515,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg2 = evaluate_subexp (0, exp, pos,
(!tem ? EVAL_SKIP : noside));
return value_from_long (builtin_type_int,
!tem || !value_zerop (arg2));
(LONGEST) (!tem || !value_zerop (arg2)));
}
case BINOP_EQUAL:
@ -494,7 +530,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_equal (arg1, arg2);
return value_from_long (builtin_type_int, tem);
return value_from_long (builtin_type_int, (LONGEST) tem);
}
case BINOP_NOTEQUAL:
@ -509,7 +545,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_equal (arg1, arg2);
return value_from_long (builtin_type_int, ! tem);
return value_from_long (builtin_type_int, (LONGEST) ! tem);
}
case BINOP_LESS:
@ -524,7 +560,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_less (arg1, arg2);
return value_from_long (builtin_type_int, tem);
return value_from_long (builtin_type_int, (LONGEST) tem);
}
case BINOP_GTR:
@ -539,7 +575,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_less (arg2, arg1);
return value_from_long (builtin_type_int, tem);
return value_from_long (builtin_type_int, (LONGEST) tem);
}
case BINOP_GEQ:
@ -554,7 +590,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_less (arg1, arg2);
return value_from_long (builtin_type_int, ! tem);
return value_from_long (builtin_type_int, (LONGEST) ! tem);
}
case BINOP_LEQ:
@ -569,7 +605,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
{
tem = value_less (arg2, arg1);
return value_from_long (builtin_type_int, ! tem);
return value_from_long (builtin_type_int, (LONGEST) ! tem);
}
case BINOP_REPEAT:
@ -577,7 +613,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg2 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_repeat (arg1, value_as_long (arg2));
return value_repeat (arg1, (int) value_as_long (arg2));
case BINOP_COMMA:
evaluate_subexp (0, exp, pos, noside);
@ -608,7 +644,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (unop_user_defined_p (op, arg1))
return value_x_unop (arg1, op, 0);
else
return value_from_long (builtin_type_int, value_zerop (arg1));
return value_from_long (builtin_type_int,
(LONGEST) value_zerop (arg1));
case UNOP_IND:
if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
@ -670,7 +707,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_at (exp->elts[pc + 1].type, value_as_long (arg1));
return value_at (exp->elts[pc + 1].type,
(CORE_ADDR) value_as_long (arg1));
case UNOP_PREINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
@ -682,7 +720,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
arg2 = value_add (arg1, value_from_long (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
@ -696,7 +735,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
arg2 = value_sub (arg1, value_from_long (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
@ -710,7 +750,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
arg2 = value_add (arg1, value_from_long (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
}
@ -725,7 +766,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
arg2 = value_sub (arg1, value_from_long (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
}
@ -735,11 +777,11 @@ evaluate_subexp (expect_type, exp, pos, noside)
return value_of_this (1);
default:
error ("internal error: I dont know how to evaluation what you gave me");
error ("internal error: I do not know how to evaluate what you gave me");
}
nosideret:
return value_from_long (builtin_type_long, 1);
return value_from_long (builtin_type_long, (LONGEST) 1);
}
/* Evaluate a subexpression of EXP, at index *POS,
@ -839,28 +881,22 @@ evaluate_subexp_for_sizeof (exp, pos)
case UNOP_IND:
(*pos)++;
val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
return value_from_long (builtin_type_int,
TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
return value_from_long (builtin_type_int, (LONGEST)
TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
case UNOP_MEMVAL:
(*pos) += 3;
return value_from_long (builtin_type_int,
TYPE_LENGTH (exp->elts[pc + 1].type));
return value_from_long (builtin_type_int,
(LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
case OP_VAR_VALUE:
(*pos) += 3;
return value_from_long (builtin_type_int,
TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
(LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
default:
val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
return value_from_long (builtin_type_int,
TYPE_LENGTH (VALUE_TYPE (val)));
(LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
}
}
static
initialize ()
{ }
END_FILE

View File

@ -20,6 +20,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include "defs.h"
#include "symtab.h"
#include "param.h"
#include "expression.h"
#include <stdio.h>
@ -79,7 +80,9 @@ static struct op_print op_print_tab[] =
{"&", UNOP_ADDR, PREC_PREFIX, 0},
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
/* C++ */
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
};
static void print_subexp ();
@ -119,6 +122,18 @@ print_subexp (exp, pos, stream, prec)
opcode = exp->elts[pc].opcode;
switch (opcode)
{
case OP_SCOPE:
myprec = PREC_PREFIX;
assoc = 0;
(*pos) += 2;
print_subexp (exp, pos, stream, (int) myprec + assoc);
fprintf (stream, " :: ");
nargs = strlen (&exp->elts[pc + 2].string);
(*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
fprintf (stream, &exp->elts[pc + 2].string);
return;
case OP_LONG:
(*pos) += 3;
value_print (value_from_long (exp->elts[pc + 1].type,

View File

@ -13,9 +13,8 @@ static int expout_size;
static int expout_ptr;
static int yylex ();
static yyerror ();
static void yyerror ();
static void write_exp_elt ();
static void write_exp_elt2 ();
static void write_exp_string ();
static void start_arglist ();
static int end_arglist ();
@ -27,6 +26,13 @@ static char *copy_name ();
static struct block *expression_context_block;
/* The innermost context required by the stack and register variables
we've encountered so far. */
struct block *innermost_block;
/* The block in which the most recently discovered symbol was found. */
struct block *block_found;
/* Number of arguments seen so far in innermost function call. */
static int arglist_len;
@ -50,7 +56,7 @@ struct stoken
int length;
};
# line 86 "expread.y"
# line 92 "expread.y"
typedef union
{
long lval;
@ -106,7 +112,7 @@ extern short yyerrflag;
YYSTYPE yylval, yyval;
# define YYERRCODE 256
# line 625 "expread.y"
# line 630 "expread.y"
/* Begin counting arguments for a function call,
@ -157,16 +163,13 @@ free_funcalls ()
/* Add one element to the end of the expression. */
/* To avoid a bug in the Sun 4 compiler, we pass only things that
can fit into a single register through here. */
/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
a register through here */
static void
write_exp_elt (expelt)
/* union exp_element expelt; */
long expelt;
union exp_element expelt;
{
union exp_element temp;
temp.longconst = expelt;
if (expout_ptr >= expout_size)
{
expout_size *= 2;
@ -174,25 +177,73 @@ write_exp_elt (expelt)
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
}
expout->elts[expout_ptr++] = /* expelt */ temp;
expout->elts[expout_ptr++] = expelt;
}
/* Things that take more space must come through here. */
static void
write_exp_elt2 (expelt)
write_exp_elt_opcode (expelt)
enum exp_opcode expelt;
{
union exp_element tmp;
tmp.opcode = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_sym (expelt)
struct symbol *expelt;
{
union exp_element tmp;
tmp.symbol = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_longcst (expelt)
LONGEST expelt;
{
union exp_element tmp;
tmp.longconst = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_dblcst (expelt)
double expelt;
{
union exp_element temp;
temp.doubleconst = expelt;
union exp_element tmp;
if (expout_ptr >= expout_size)
{
expout_size *= 2;
expout = (struct expression *) xrealloc (expout,
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
}
expout->elts[expout_ptr++] = temp;
tmp.doubleconst = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_type (expelt)
struct type *expelt;
{
union exp_element tmp;
tmp.type = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_intern (expelt)
struct internalvar *expelt;
{
union exp_element tmp;
tmp.internalvar = expelt;
write_exp_elt (tmp);
}
/* Add a string constant to the end of the expression.
@ -211,13 +262,13 @@ write_exp_string (str)
if (expout_ptr >= expout_size)
{
expout_size = max (expout_size * 2, expout_ptr + 10);
expout = (struct expression *) xrealloc (expout,
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
expout = (struct expression *)
xrealloc (expout, (sizeof (struct expression)
+ (expout_size * sizeof (union exp_element))));
}
bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
write_exp_elt (len);
write_exp_elt_longcst (len);
}
/* During parsing of a C expression, the pointer to the next character
@ -284,12 +335,13 @@ parse_number (olen)
while (len-- > 0)
{
c = *p++;
n *= base;
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
if (c != 'l')
n *= base;
if (c >= '0' && c <= '9')
n += c - '0';
else
{
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
if (base == 16 && c >= 'a' && c <= 'f')
n += c - 'a' + 10;
else if (len == 0 && c == 'l')
@ -346,6 +398,29 @@ static struct token tokentab2[] =
{">=", GEQ, BINOP_END}
};
/* assign machine-independent names to certain registers
* (unless overridden by the REGISTER_NAMES table)
*/
struct std_regs {
char *name;
int regnum;
} std_regs[] = {
#ifdef PC_REGNUM
{ "pc", PC_REGNUM },
#endif
#ifdef FP_REGNUM
{ "fp", FP_REGNUM },
#endif
#ifdef SP_REGNUM
{ "sp", SP_REGNUM },
#endif
#ifdef PS_REGNUM
{ "ps", PS_REGNUM },
#endif
};
#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
/* Read one token, getting characters through lexptr. */
static int
@ -529,7 +604,7 @@ yylex ()
/* Handle tokens that refer to machine registers:
$ followed by a register name. */
if (*tokstart == '$')
if (*tokstart == '$') {
for (c = 0; c < NUM_REGS; c++)
if (namelen - 1 == strlen (reg_names[c])
&& !strncmp (tokstart + 1, reg_names[c], namelen - 1))
@ -537,7 +612,14 @@ yylex ()
yylval.lval = c;
return REGNAME;
}
for (c = 0; c < NUM_STD_REGS; c++)
if (namelen - 1 == strlen (std_regs[c].name)
&& !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
{
yylval.lval = std_regs[c].regnum;
return REGNAME;
}
}
if (namelen == 6 && !strncmp (tokstart, "struct", 6))
{
return STRUCT;
@ -555,10 +637,10 @@ yylex ()
{
return ENUM;
}
if (!strncmp (tokstart, "this", 4))
{
return THIS;
}
if (!strncmp (tokstart, "this", 4)
&& lookup_symbol ("$this", expression_context_block,
VAR_NAMESPACE, 0))
return THIS;
}
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
{
@ -587,7 +669,7 @@ yylex ()
return NAME;
}
static
static void
yyerror ()
{
error ("Invalid syntax in expression.");
@ -846,6 +928,8 @@ parse_c_1 (stringptr, block, comma)
lexptr = *stringptr;
paren_depth = 0;
comma_terminates = comma;
if (lexptr == 0 || *lexptr == 0)
@ -859,8 +943,9 @@ parse_c_1 (stringptr, block, comma)
namecopy = (char *) alloca (strlen (lexptr) + 1);
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *) xmalloc (sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
expout = (struct expression *)
xmalloc (sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
make_cleanup (free_current_contents, &expout);
if (yyparse ())
yyerror ();
@ -1054,7 +1139,7 @@ short yydef[]={
0, 23, 0, 69, 0, 70, 0, 77, 71, 0,
78 };
#ifndef lint
static char yaccpar_sccsid[] = "@(#)yaccpar 1.6 88/02/08 SMI"; /* from UCB 4.1 83/02/11 */
static char yaccpar_sccsid[] = "@(#)yaccpar 1.5 86/08/27 SMI"; /* from UCB 4.1 83/02/11 */
#endif
#
@ -1203,202 +1288,202 @@ yyparse() {
switch(yym){
case 3:
# line 159 "expread.y"
{ write_exp_elt (BINOP_COMMA); } break;
# line 165 "expread.y"
{ write_exp_elt_opcode (BINOP_COMMA); } break;
case 4:
# line 164 "expread.y"
{ write_exp_elt (UNOP_IND); } break;
case 5:
# line 167 "expread.y"
{ write_exp_elt (UNOP_ADDR); } break;
case 6:
# line 170 "expread.y"
{ write_exp_elt (UNOP_NEG); } break;
{ write_exp_elt_opcode (UNOP_IND); } break;
case 5:
# line 173 "expread.y"
{ write_exp_elt_opcode (UNOP_ADDR); } break;
case 6:
# line 176 "expread.y"
{ write_exp_elt_opcode (UNOP_NEG); } break;
case 7:
# line 174 "expread.y"
{ write_exp_elt (UNOP_ZEROP); } break;
# line 180 "expread.y"
{ write_exp_elt_opcode (UNOP_ZEROP); } break;
case 8:
# line 178 "expread.y"
{ write_exp_elt (UNOP_LOGNOT); } break;
# line 184 "expread.y"
{ write_exp_elt_opcode (UNOP_LOGNOT); } break;
case 9:
# line 182 "expread.y"
{ write_exp_elt (UNOP_PREINCREMENT); } break;
# line 188 "expread.y"
{ write_exp_elt_opcode (UNOP_PREINCREMENT); } break;
case 10:
# line 186 "expread.y"
{ write_exp_elt (UNOP_PREDECREMENT); } break;
# line 192 "expread.y"
{ write_exp_elt_opcode (UNOP_PREDECREMENT); } break;
case 11:
# line 190 "expread.y"
{ write_exp_elt (UNOP_POSTINCREMENT); } break;
# line 196 "expread.y"
{ write_exp_elt_opcode (UNOP_POSTINCREMENT); } break;
case 12:
# line 194 "expread.y"
{ write_exp_elt (UNOP_POSTDECREMENT); } break;
# line 200 "expread.y"
{ write_exp_elt_opcode (UNOP_POSTDECREMENT); } break;
case 13:
# line 198 "expread.y"
{ write_exp_elt (UNOP_SIZEOF); } break;
# line 204 "expread.y"
{ write_exp_elt_opcode (UNOP_SIZEOF); } break;
case 14:
# line 202 "expread.y"
{ write_exp_elt (STRUCTOP_PTR);
write_exp_string (yypvt[-0].sval);
write_exp_elt (STRUCTOP_PTR); } break;
case 15:
# line 208 "expread.y"
{ write_exp_elt (STRUCTOP_MPTR); } break;
case 16:
# line 212 "expread.y"
{ write_exp_elt (STRUCTOP_STRUCT);
{ write_exp_elt_opcode (STRUCTOP_PTR);
write_exp_string (yypvt[-0].sval);
write_exp_elt (STRUCTOP_STRUCT); } break;
case 17:
write_exp_elt_opcode (STRUCTOP_PTR); } break;
case 15:
# line 214 "expread.y"
{ write_exp_elt_opcode (STRUCTOP_MPTR); } break;
case 16:
# line 218 "expread.y"
{ write_exp_elt (STRUCTOP_MEMBER); } break;
{ write_exp_elt_opcode (STRUCTOP_STRUCT);
write_exp_string (yypvt[-0].sval);
write_exp_elt_opcode (STRUCTOP_STRUCT); } break;
case 17:
# line 224 "expread.y"
{ write_exp_elt_opcode (STRUCTOP_MEMBER); } break;
case 18:
# line 222 "expread.y"
{ write_exp_elt (BINOP_SUBSCRIPT); } break;
case 19:
# line 228 "expread.y"
{ write_exp_elt_opcode (BINOP_SUBSCRIPT); } break;
case 19:
# line 234 "expread.y"
{ start_arglist (); } break;
case 20:
# line 230 "expread.y"
{ write_exp_elt (OP_FUNCALL);
write_exp_elt (end_arglist ());
write_exp_elt (OP_FUNCALL); } break;
# line 236 "expread.y"
{ write_exp_elt_opcode (OP_FUNCALL);
write_exp_elt_longcst (end_arglist ());
write_exp_elt_opcode (OP_FUNCALL); } break;
case 22:
# line 239 "expread.y"
# line 245 "expread.y"
{ arglist_len = 1; } break;
case 23:
# line 243 "expread.y"
# line 249 "expread.y"
{ arglist_len++; } break;
case 24:
# line 247 "expread.y"
{ write_exp_elt (UNOP_MEMVAL);
write_exp_elt (yypvt[-2].tval);
write_exp_elt (UNOP_MEMVAL); } break;
case 25:
# line 253 "expread.y"
{ write_exp_elt (UNOP_CAST);
write_exp_elt (yypvt[-2].tval);
write_exp_elt (UNOP_CAST); } break;
case 26:
{ write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (yypvt[-2].tval);
write_exp_elt_opcode (UNOP_MEMVAL); } break;
case 25:
# line 259 "expread.y"
{ write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (yypvt[-2].tval);
write_exp_elt_opcode (UNOP_CAST); } break;
case 26:
# line 265 "expread.y"
{ } break;
case 27:
# line 265 "expread.y"
{ write_exp_elt (BINOP_REPEAT); } break;
# line 271 "expread.y"
{ write_exp_elt_opcode (BINOP_REPEAT); } break;
case 28:
# line 269 "expread.y"
{ write_exp_elt (BINOP_MUL); } break;
# line 275 "expread.y"
{ write_exp_elt_opcode (BINOP_MUL); } break;
case 29:
# line 273 "expread.y"
{ write_exp_elt (BINOP_DIV); } break;
# line 279 "expread.y"
{ write_exp_elt_opcode (BINOP_DIV); } break;
case 30:
# line 277 "expread.y"
{ write_exp_elt (BINOP_REM); } break;
# line 283 "expread.y"
{ write_exp_elt_opcode (BINOP_REM); } break;
case 31:
# line 281 "expread.y"
{ write_exp_elt (BINOP_ADD); } break;
# line 287 "expread.y"
{ write_exp_elt_opcode (BINOP_ADD); } break;
case 32:
# line 285 "expread.y"
{ write_exp_elt (BINOP_SUB); } break;
# line 291 "expread.y"
{ write_exp_elt_opcode (BINOP_SUB); } break;
case 33:
# line 289 "expread.y"
{ write_exp_elt (BINOP_LSH); } break;
# line 295 "expread.y"
{ write_exp_elt_opcode (BINOP_LSH); } break;
case 34:
# line 293 "expread.y"
{ write_exp_elt (BINOP_RSH); } break;
# line 299 "expread.y"
{ write_exp_elt_opcode (BINOP_RSH); } break;
case 35:
# line 297 "expread.y"
{ write_exp_elt (BINOP_EQUAL); } break;
# line 303 "expread.y"
{ write_exp_elt_opcode (BINOP_EQUAL); } break;
case 36:
# line 301 "expread.y"
{ write_exp_elt (BINOP_NOTEQUAL); } break;
# line 307 "expread.y"
{ write_exp_elt_opcode (BINOP_NOTEQUAL); } break;
case 37:
# line 305 "expread.y"
{ write_exp_elt (BINOP_LEQ); } break;
# line 311 "expread.y"
{ write_exp_elt_opcode (BINOP_LEQ); } break;
case 38:
# line 309 "expread.y"
{ write_exp_elt (BINOP_GEQ); } break;
# line 315 "expread.y"
{ write_exp_elt_opcode (BINOP_GEQ); } break;
case 39:
# line 313 "expread.y"
{ write_exp_elt (BINOP_LESS); } break;
# line 319 "expread.y"
{ write_exp_elt_opcode (BINOP_LESS); } break;
case 40:
# line 317 "expread.y"
{ write_exp_elt (BINOP_GTR); } break;
# line 323 "expread.y"
{ write_exp_elt_opcode (BINOP_GTR); } break;
case 41:
# line 321 "expread.y"
{ write_exp_elt (BINOP_LOGAND); } break;
# line 327 "expread.y"
{ write_exp_elt_opcode (BINOP_LOGAND); } break;
case 42:
# line 325 "expread.y"
{ write_exp_elt (BINOP_LOGXOR); } break;
# line 331 "expread.y"
{ write_exp_elt_opcode (BINOP_LOGXOR); } break;
case 43:
# line 329 "expread.y"
{ write_exp_elt (BINOP_LOGIOR); } break;
# line 335 "expread.y"
{ write_exp_elt_opcode (BINOP_LOGIOR); } break;
case 44:
# line 333 "expread.y"
{ write_exp_elt (BINOP_AND); } break;
# line 339 "expread.y"
{ write_exp_elt_opcode (BINOP_AND); } break;
case 45:
# line 337 "expread.y"
{ write_exp_elt (BINOP_OR); } break;
# line 343 "expread.y"
{ write_exp_elt_opcode (BINOP_OR); } break;
case 46:
# line 341 "expread.y"
{ write_exp_elt (TERNOP_COND); } break;
# line 347 "expread.y"
{ write_exp_elt_opcode (TERNOP_COND); } break;
case 47:
# line 345 "expread.y"
{ write_exp_elt (BINOP_ASSIGN); } break;
# line 351 "expread.y"
{ write_exp_elt_opcode (BINOP_ASSIGN); } break;
case 48:
# line 349 "expread.y"
{ write_exp_elt (BINOP_ASSIGN_MODIFY);
write_exp_elt (yypvt[-1].opcode);
write_exp_elt (BINOP_ASSIGN_MODIFY); } break;
case 49:
# line 355 "expread.y"
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_long);
write_exp_elt (yypvt[-0].lval);
write_exp_elt (OP_LONG); } break;
{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
write_exp_elt_opcode (yypvt[-1].opcode);
write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); } break;
case 49:
# line 361 "expread.y"
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_long);
write_exp_elt_longcst (yypvt[-0].lval);
write_exp_elt_opcode (OP_LONG); } break;
case 50:
# line 362 "expread.y"
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_char);
write_exp_elt (yypvt[-0].lval);
write_exp_elt (OP_LONG); } break;
# line 368 "expread.y"
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_char);
write_exp_elt_longcst (yypvt[-0].lval);
write_exp_elt_opcode (OP_LONG); } break;
case 51:
# line 369 "expread.y"
{ write_exp_elt (OP_DOUBLE);
write_exp_elt (builtin_type_double);
write_exp_elt2 (yypvt[-0].dval);
write_exp_elt (OP_DOUBLE); } break;
# line 375 "expread.y"
{ write_exp_elt_opcode (OP_DOUBLE);
write_exp_elt_type (builtin_type_double);
write_exp_elt_dblcst (yypvt[-0].dval);
write_exp_elt_opcode (OP_DOUBLE); } break;
case 53:
# line 379 "expread.y"
{ write_exp_elt (OP_LAST);
write_exp_elt (yypvt[-0].lval);
write_exp_elt (OP_LAST); } break;
case 54:
# line 385 "expread.y"
{ write_exp_elt (OP_REGISTER);
write_exp_elt (yypvt[-0].lval);
write_exp_elt (OP_REGISTER); } break;
case 55:
{ write_exp_elt_opcode (OP_LAST);
write_exp_elt_longcst (yypvt[-0].lval);
write_exp_elt_opcode (OP_LAST); } break;
case 54:
# line 391 "expread.y"
{ write_exp_elt (OP_INTERNALVAR);
write_exp_elt (yypvt[-0].ivar);
write_exp_elt (OP_INTERNALVAR); } break;
case 56:
{ write_exp_elt_opcode (OP_REGISTER);
write_exp_elt_longcst (yypvt[-0].lval);
write_exp_elt_opcode (OP_REGISTER); } break;
case 55:
# line 397 "expread.y"
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt ((long) TYPE_LENGTH (yypvt[-1].tval));
write_exp_elt (OP_LONG); } break;
{ write_exp_elt_opcode (OP_INTERNALVAR);
write_exp_elt_intern (yypvt[-0].ivar);
write_exp_elt_opcode (OP_INTERNALVAR); } break;
case 56:
# line 403 "expread.y"
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst ((long) TYPE_LENGTH (yypvt[-1].tval));
write_exp_elt_opcode (OP_LONG); } break;
case 57:
# line 404 "expread.y"
{ write_exp_elt (OP_STRING);
# line 410 "expread.y"
{ write_exp_elt_opcode (OP_STRING);
write_exp_string (yypvt[-0].sval);
write_exp_elt (OP_STRING); } break;
write_exp_elt_opcode (OP_STRING); } break;
case 58:
# line 411 "expread.y"
{ write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS); } break;
# line 417 "expread.y"
{ write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (OP_THIS); } break;
case 59:
# line 418 "expread.y"
# line 424 "expread.y"
{
struct symtab *tem = lookup_symtab (copy_name (yypvt[-0].sval));
struct symbol *sym;
@ -1409,7 +1494,7 @@ case 59:
{
sym = lookup_symbol (copy_name (yypvt[-0].sval),
expression_context_block,
VAR_NAMESPACE);
VAR_NAMESPACE, 0);
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
yyval.bval = SYMBOL_BLOCK_VALUE (sym);
else
@ -1418,29 +1503,25 @@ case 59:
}
} break;
case 60:
# line 439 "expread.y"
{
struct symbol *tem
= lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE);
# line 445 "expread.y"
{ struct symbol *tem
= lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE, 0);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
error ("No function \"%s\" in specified context.",
copy_name (yypvt[-0].sval));
yyval.bval = SYMBOL_BLOCK_VALUE (tem);
} break;
yyval.bval = SYMBOL_BLOCK_VALUE (tem); } break;
case 61:
# line 450 "expread.y"
{
struct symbol *sym;
sym = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE);
# line 454 "expread.y"
{ struct symbol *sym;
sym = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE, 0);
if (sym == 0)
error ("No symbol \"%s\" in specified context.",
copy_name (yypvt[-0].sval));
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
} break;
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); } break;
case 62:
# line 463 "expread.y"
# line 465 "expread.y"
{
struct type *type = yypvt[-2].tval;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
@ -1448,24 +1529,24 @@ case 62:
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
write_exp_elt (OP_SCOPE);
write_exp_elt (type);
write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_type (type);
write_exp_string (yypvt[-0].sval);
write_exp_elt (OP_SCOPE);
write_exp_elt_opcode (OP_SCOPE);
} break;
case 63:
# line 476 "expread.y"
# line 478 "expread.y"
{
char *name = copy_name (yypvt[-0].sval);
struct symbol *sym;
int i;
sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE);
sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
break;
}
for (i = 0; i < misc_function_count; i++)
@ -1474,130 +1555,133 @@ case 63:
if (i < misc_function_count)
{
write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt (misc_function_vector[i].address);
write_exp_elt (OP_LONG);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt (builtin_type_char);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else
if (symtab_list == 0)
if (symtab_list == 0
&& partial_symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
error ("No symbol \"%s\" in current context.", name);
} break;
case 64:
# line 512 "expread.y"
# line 515 "expread.y"
{ struct symbol *sym;
sym = lookup_symbol_1 (copy_name (yypvt[-0].sval),
expression_context_block,
VAR_NAMESPACE);
int is_a_field_of_this;
sym = lookup_symbol (copy_name (yypvt[-0].sval),
expression_context_block,
VAR_NAMESPACE,
&is_a_field_of_this);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
switch (sym->class)
{
case LOC_REGISTER:
case LOC_ARG:
case LOC_LOCAL:
if (innermost_block == 0 ||
contained_in (block_found,
innermost_block))
innermost_block = block_found;
}
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
else if (is_a_field_of_this)
{
/* C++: it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
if (innermost_block == 0 ||
contained_in (block_found, innermost_block))
innermost_block = block_found;
write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (STRUCTOP_PTR);
write_exp_string (yypvt[-0].sval);
write_exp_elt_opcode (STRUCTOP_PTR);
}
else
{
register char *arg = copy_name (yypvt[-0].sval);
register int i;
int v, val;
/* C++: see if it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
v = (int)value_of_this (0);
if (v)
{
val = check_field (v, arg);
if (val)
{
write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS);
write_exp_elt (STRUCTOP_PTR);
write_exp_string (yypvt[-0].sval);
write_exp_elt (STRUCTOP_PTR);
break;
}
}
sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
break; /* YACC-dependent */
}
register char *arg = copy_name (yypvt[-0].sval);
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, arg))
break;
if (i < misc_function_count)
{
write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt (misc_function_vector[i].address);
write_exp_elt (OP_LONG);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt (builtin_type_char);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else if (symtab_list == 0
&& partial_symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
if (symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
error ("No symbol \"%s\" in current context.",
copy_name (yypvt[-0].sval));
error ("No symbol \"%s\" in current context.",
copy_name (yypvt[-0].sval));
}
} break;
case 66:
# line 578 "expread.y"
# line 583 "expread.y"
{ yyval.tval = lookup_pointer_type (yypvt[-1].tval); } break;
case 67:
# line 580 "expread.y"
# line 585 "expread.y"
{ yyval.tval = lookup_reference_type (yypvt[-1].tval); } break;
case 68:
# line 582 "expread.y"
# line 587 "expread.y"
{ yyval.tval = lookup_member_type (builtin_type_int, yypvt[-2].tval); } break;
case 69:
# line 584 "expread.y"
# line 589 "expread.y"
{ yyval.tval = lookup_member_type (yypvt[-5].tval, yypvt[-3].tval); } break;
case 70:
# line 586 "expread.y"
{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-7].tval, 0), yypvt[-5].tval); } break;
# line 591 "expread.y"
{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-7].tval)); } break;
case 71:
# line 588 "expread.y"
{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-8].tval, yypvt[-1].tvec), yypvt[-6].tval);
# line 593 "expread.y"
{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-8].tval));
free (yypvt[-1].tvec); } break;
case 72:
# line 594 "expread.y"
# line 599 "expread.y"
{ yyval.tval = lookup_typename (copy_name (yypvt[-0].sval),
expression_context_block, 0); } break;
case 73:
# line 597 "expread.y"
# line 602 "expread.y"
{ yyval.tval = lookup_struct (copy_name (yypvt[-0].sval),
expression_context_block); } break;
case 74:
# line 600 "expread.y"
# line 605 "expread.y"
{ yyval.tval = lookup_union (copy_name (yypvt[-0].sval),
expression_context_block); } break;
case 75:
# line 603 "expread.y"
# line 608 "expread.y"
{ yyval.tval = lookup_enum (copy_name (yypvt[-0].sval),
expression_context_block); } break;
case 76:
# line 606 "expread.y"
# line 611 "expread.y"
{ yyval.tval = lookup_unsigned_typename (copy_name (yypvt[-0].sval)); } break;
case 77:
# line 611 "expread.y"
# line 616 "expread.y"
{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2);
yyval.tvec[0] = (struct type *)0;
yyval.tvec[1] = yypvt[-0].tval;
} break;
case 78:
# line 616 "expread.y"
# line 621 "expread.y"
{ int len = sizeof (struct type *) * ++(yypvt[-2].ivec[0]);
yyval.tvec = (struct type **)xrealloc (yypvt[-2].tvec, len);
yyval.tvec[yyval.ivec[0]] = yypvt[-0].tval;

View File

@ -41,9 +41,8 @@ static int expout_size;
static int expout_ptr;
static int yylex ();
static yyerror ();
static void yyerror ();
static void write_exp_elt ();
static void write_exp_elt2 ();
static void write_exp_string ();
static void start_arglist ();
static int end_arglist ();
@ -55,6 +54,13 @@ static char *copy_name ();
static struct block *expression_context_block;
/* The innermost context required by the stack and register variables
we've encountered so far. */
struct block *innermost_block;
/* The block in which the most recently discovered symbol was found. */
struct block *block_found;
/* Number of arguments seen so far in innermost function call. */
static int arglist_len;
@ -156,70 +162,70 @@ start : exp1
/* Expressions, including the comma operator. */
exp1 : exp
| exp1 ',' exp
{ write_exp_elt (BINOP_COMMA); }
{ write_exp_elt_opcode (BINOP_COMMA); }
;
/* Expressions, not including the comma operator. */
exp : '*' exp %prec UNARY
{ write_exp_elt (UNOP_IND); }
{ write_exp_elt_opcode (UNOP_IND); }
exp : '&' exp %prec UNARY
{ write_exp_elt (UNOP_ADDR); }
{ write_exp_elt_opcode (UNOP_ADDR); }
exp : '-' exp %prec UNARY
{ write_exp_elt (UNOP_NEG); }
{ write_exp_elt_opcode (UNOP_NEG); }
;
exp : '!' exp %prec UNARY
{ write_exp_elt (UNOP_ZEROP); }
{ write_exp_elt_opcode (UNOP_ZEROP); }
;
exp : '~' exp %prec UNARY
{ write_exp_elt (UNOP_LOGNOT); }
{ write_exp_elt_opcode (UNOP_LOGNOT); }
;
exp : INCREMENT exp %prec UNARY
{ write_exp_elt (UNOP_PREINCREMENT); }
{ write_exp_elt_opcode (UNOP_PREINCREMENT); }
;
exp : DECREMENT exp %prec UNARY
{ write_exp_elt (UNOP_PREDECREMENT); }
{ write_exp_elt_opcode (UNOP_PREDECREMENT); }
;
exp : exp INCREMENT %prec UNARY
{ write_exp_elt (UNOP_POSTINCREMENT); }
{ write_exp_elt_opcode (UNOP_POSTINCREMENT); }
;
exp : exp DECREMENT %prec UNARY
{ write_exp_elt (UNOP_POSTDECREMENT); }
{ write_exp_elt_opcode (UNOP_POSTDECREMENT); }
;
exp : SIZEOF exp %prec UNARY
{ write_exp_elt (UNOP_SIZEOF); }
{ write_exp_elt_opcode (UNOP_SIZEOF); }
;
exp : exp ARROW name
{ write_exp_elt (STRUCTOP_PTR);
{ write_exp_elt_opcode (STRUCTOP_PTR);
write_exp_string ($3);
write_exp_elt (STRUCTOP_PTR); }
write_exp_elt_opcode (STRUCTOP_PTR); }
;
exp : exp ARROW '*' exp
{ write_exp_elt (STRUCTOP_MPTR); }
{ write_exp_elt_opcode (STRUCTOP_MPTR); }
;
exp : exp '.' name
{ write_exp_elt (STRUCTOP_STRUCT);
{ write_exp_elt_opcode (STRUCTOP_STRUCT);
write_exp_string ($3);
write_exp_elt (STRUCTOP_STRUCT); }
write_exp_elt_opcode (STRUCTOP_STRUCT); }
;
exp : exp '.' '*' exp
{ write_exp_elt (STRUCTOP_MEMBER); }
{ write_exp_elt_opcode (STRUCTOP_MEMBER); }
;
exp : exp '[' exp1 ']'
{ write_exp_elt (BINOP_SUBSCRIPT); }
{ write_exp_elt_opcode (BINOP_SUBSCRIPT); }
;
exp : exp '('
@ -227,9 +233,9 @@ exp : exp '('
being accumulated by an outer function call. */
{ start_arglist (); }
arglist ')'
{ write_exp_elt (OP_FUNCALL);
write_exp_elt (end_arglist ());
write_exp_elt (OP_FUNCALL); }
{ write_exp_elt_opcode (OP_FUNCALL);
write_exp_elt_longcst (end_arglist ());
write_exp_elt_opcode (OP_FUNCALL); }
;
arglist :
@ -244,15 +250,15 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
;
exp : '{' type '}' exp %prec UNARY
{ write_exp_elt (UNOP_MEMVAL);
write_exp_elt ($2);
write_exp_elt (UNOP_MEMVAL); }
{ write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type ($2);
write_exp_elt_opcode (UNOP_MEMVAL); }
;
exp : '(' type ')' exp %prec UNARY
{ write_exp_elt (UNOP_CAST);
write_exp_elt ($2);
write_exp_elt (UNOP_CAST); }
{ write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type ($2);
write_exp_elt_opcode (UNOP_CAST); }
;
exp : '(' exp1 ')'
@ -262,154 +268,154 @@ exp : '(' exp1 ')'
/* Binary operators in order of decreasing precedence. */
exp : exp '@' exp
{ write_exp_elt (BINOP_REPEAT); }
{ write_exp_elt_opcode (BINOP_REPEAT); }
;
exp : exp '*' exp
{ write_exp_elt (BINOP_MUL); }
{ write_exp_elt_opcode (BINOP_MUL); }
;
exp : exp '/' exp
{ write_exp_elt (BINOP_DIV); }
{ write_exp_elt_opcode (BINOP_DIV); }
;
exp : exp '%' exp
{ write_exp_elt (BINOP_REM); }
{ write_exp_elt_opcode (BINOP_REM); }
;
exp : exp '+' exp
{ write_exp_elt (BINOP_ADD); }
{ write_exp_elt_opcode (BINOP_ADD); }
;
exp : exp '-' exp
{ write_exp_elt (BINOP_SUB); }
{ write_exp_elt_opcode (BINOP_SUB); }
;
exp : exp LSH exp
{ write_exp_elt (BINOP_LSH); }
{ write_exp_elt_opcode (BINOP_LSH); }
;
exp : exp RSH exp
{ write_exp_elt (BINOP_RSH); }
{ write_exp_elt_opcode (BINOP_RSH); }
;
exp : exp EQUAL exp
{ write_exp_elt (BINOP_EQUAL); }
{ write_exp_elt_opcode (BINOP_EQUAL); }
;
exp : exp NOTEQUAL exp
{ write_exp_elt (BINOP_NOTEQUAL); }
{ write_exp_elt_opcode (BINOP_NOTEQUAL); }
;
exp : exp LEQ exp
{ write_exp_elt (BINOP_LEQ); }
{ write_exp_elt_opcode (BINOP_LEQ); }
;
exp : exp GEQ exp
{ write_exp_elt (BINOP_GEQ); }
{ write_exp_elt_opcode (BINOP_GEQ); }
;
exp : exp '<' exp
{ write_exp_elt (BINOP_LESS); }
{ write_exp_elt_opcode (BINOP_LESS); }
;
exp : exp '>' exp
{ write_exp_elt (BINOP_GTR); }
{ write_exp_elt_opcode (BINOP_GTR); }
;
exp : exp '&' exp
{ write_exp_elt (BINOP_LOGAND); }
{ write_exp_elt_opcode (BINOP_LOGAND); }
;
exp : exp '^' exp
{ write_exp_elt (BINOP_LOGXOR); }
{ write_exp_elt_opcode (BINOP_LOGXOR); }
;
exp : exp '|' exp
{ write_exp_elt (BINOP_LOGIOR); }
{ write_exp_elt_opcode (BINOP_LOGIOR); }
;
exp : exp AND exp
{ write_exp_elt (BINOP_AND); }
{ write_exp_elt_opcode (BINOP_AND); }
;
exp : exp OR exp
{ write_exp_elt (BINOP_OR); }
{ write_exp_elt_opcode (BINOP_OR); }
;
exp : exp '?' exp ':' exp
{ write_exp_elt (TERNOP_COND); }
{ write_exp_elt_opcode (TERNOP_COND); }
;
exp : exp '=' exp
{ write_exp_elt (BINOP_ASSIGN); }
{ write_exp_elt_opcode (BINOP_ASSIGN); }
;
exp : exp ASSIGN_MODIFY exp
{ write_exp_elt (BINOP_ASSIGN_MODIFY);
write_exp_elt ($2);
write_exp_elt (BINOP_ASSIGN_MODIFY); }
{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
write_exp_elt_opcode ($2);
write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
;
exp : INT
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_long);
write_exp_elt ($1);
write_exp_elt (OP_LONG); }
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_long);
write_exp_elt_longcst ($1);
write_exp_elt_opcode (OP_LONG); }
;
exp : CHAR
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_char);
write_exp_elt ($1);
write_exp_elt (OP_LONG); }
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_char);
write_exp_elt_longcst ($1);
write_exp_elt_opcode (OP_LONG); }
;
exp : FLOAT
{ write_exp_elt (OP_DOUBLE);
write_exp_elt (builtin_type_double);
write_exp_elt2 ($1);
write_exp_elt (OP_DOUBLE); }
{ write_exp_elt_opcode (OP_DOUBLE);
write_exp_elt_type (builtin_type_double);
write_exp_elt_dblcst ($1);
write_exp_elt_opcode (OP_DOUBLE); }
;
exp : variable
;
exp : LAST
{ write_exp_elt (OP_LAST);
write_exp_elt ($1);
write_exp_elt (OP_LAST); }
{ write_exp_elt_opcode (OP_LAST);
write_exp_elt_longcst ($1);
write_exp_elt_opcode (OP_LAST); }
;
exp : REGNAME
{ write_exp_elt (OP_REGISTER);
write_exp_elt ($1);
write_exp_elt (OP_REGISTER); }
{ write_exp_elt_opcode (OP_REGISTER);
write_exp_elt_longcst ($1);
write_exp_elt_opcode (OP_REGISTER); }
;
exp : VARIABLE
{ write_exp_elt (OP_INTERNALVAR);
write_exp_elt ($1);
write_exp_elt (OP_INTERNALVAR); }
{ write_exp_elt_opcode (OP_INTERNALVAR);
write_exp_elt_intern ($1);
write_exp_elt_opcode (OP_INTERNALVAR); }
;
exp : SIZEOF '(' type ')'
{ write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt ((long) TYPE_LENGTH ($3));
write_exp_elt (OP_LONG); }
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst ((long) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
;
exp : STRING
{ write_exp_elt (OP_STRING);
{ write_exp_elt_opcode (OP_STRING);
write_exp_string ($1);
write_exp_elt (OP_STRING); }
write_exp_elt_opcode (OP_STRING); }
;
/* C++. */
exp : THIS
{ write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS); }
{ write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (OP_THIS); }
;
/* end of C++. */
@ -425,7 +431,7 @@ block : name
{
sym = lookup_symbol (copy_name ($1),
expression_context_block,
VAR_NAMESPACE);
VAR_NAMESPACE, 0);
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
$$ = SYMBOL_BLOCK_VALUE (sym);
else
@ -436,27 +442,23 @@ block : name
;
block : block COLONCOLON name
{
struct symbol *tem
= lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
{ struct symbol *tem
= lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE, 0);
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
error ("No function \"%s\" in specified context.",
copy_name ($3));
$$ = SYMBOL_BLOCK_VALUE (tem);
}
$$ = SYMBOL_BLOCK_VALUE (tem); }
;
variable: block COLONCOLON name
{
struct symbol *sym;
sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
{ struct symbol *sym;
sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE, 0);
if (sym == 0)
error ("No symbol \"%s\" in specified context.",
copy_name ($3));
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
}
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE); }
;
variable: typebase COLONCOLON name
@ -467,10 +469,10 @@ variable: typebase COLONCOLON name
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
write_exp_elt (OP_SCOPE);
write_exp_elt (type);
write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_type (type);
write_exp_string ($3);
write_exp_elt (OP_SCOPE);
write_exp_elt_opcode (OP_SCOPE);
}
| COLONCOLON name
{
@ -478,12 +480,12 @@ variable: typebase COLONCOLON name
struct symbol *sym;
int i;
sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE);
sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
break;
}
for (i = 0; i < misc_function_count; i++)
@ -492,16 +494,17 @@ variable: typebase COLONCOLON name
if (i < misc_function_count)
{
write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt (misc_function_vector[i].address);
write_exp_elt (OP_LONG);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt (builtin_type_char);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else
if (symtab_list == 0)
if (symtab_list == 0
&& partial_symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
error ("No symbol \"%s\" in current context.", name);
@ -510,65 +513,67 @@ variable: typebase COLONCOLON name
variable: NAME
{ struct symbol *sym;
sym = lookup_symbol_1 (copy_name ($1),
expression_context_block,
VAR_NAMESPACE);
int is_a_field_of_this;
sym = lookup_symbol (copy_name ($1),
expression_context_block,
VAR_NAMESPACE,
&is_a_field_of_this);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
switch (sym->class)
{
case LOC_REGISTER:
case LOC_ARG:
case LOC_LOCAL:
if (innermost_block == 0 ||
contained_in (block_found,
innermost_block))
innermost_block = block_found;
}
write_exp_elt_opcode (OP_VAR_VALUE);
write_exp_elt_sym (sym);
write_exp_elt_opcode (OP_VAR_VALUE);
}
else if (is_a_field_of_this)
{
/* C++: it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
if (innermost_block == 0 ||
contained_in (block_found, innermost_block))
innermost_block = block_found;
write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (OP_THIS);
write_exp_elt_opcode (STRUCTOP_PTR);
write_exp_string ($1);
write_exp_elt_opcode (STRUCTOP_PTR);
}
else
{
register char *arg = copy_name ($1);
register int i;
int v, val;
/* C++: see if it hangs off of `this'. Must
not inadvertently convert from a method call
to data ref. */
v = (int)value_of_this (0);
if (v)
{
val = check_field (v, arg);
if (val)
{
write_exp_elt (OP_THIS);
write_exp_elt (OP_THIS);
write_exp_elt (STRUCTOP_PTR);
write_exp_string ($1);
write_exp_elt (STRUCTOP_PTR);
break;
}
}
sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE);
if (sym)
{
write_exp_elt (OP_VAR_VALUE);
write_exp_elt (sym);
write_exp_elt (OP_VAR_VALUE);
break; /* YACC-dependent */
}
register char *arg = copy_name ($1);
for (i = 0; i < misc_function_count; i++)
if (!strcmp (misc_function_vector[i].name, arg))
break;
if (i < misc_function_count)
{
write_exp_elt (OP_LONG);
write_exp_elt (builtin_type_int);
write_exp_elt (misc_function_vector[i].address);
write_exp_elt (OP_LONG);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt (builtin_type_char);
write_exp_elt (UNOP_MEMVAL);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else if (symtab_list == 0
&& partial_symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
if (symtab_list == 0)
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
else
error ("No symbol \"%s\" in current context.",
copy_name ($1));
error ("No symbol \"%s\" in current context.",
copy_name ($1));
}
}
;
@ -583,9 +588,9 @@ type : typebase
| type '(' typebase COLONCOLON '*' ')'
{ $$ = lookup_member_type ($1, $3); }
| type '(' typebase COLONCOLON '*' ')' '(' ')'
{ $$ = lookup_member_type (lookup_function_type ($1, 0), $3); }
{ $$ = lookup_member_type (lookup_function_type ($1)); }
| type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
{ $$ = lookup_member_type (lookup_function_type ($1, $8), $3);
{ $$ = lookup_member_type (lookup_function_type ($1));
free ($8); }
;
@ -672,16 +677,13 @@ free_funcalls ()
/* Add one element to the end of the expression. */
/* To avoid a bug in the Sun 4 compiler, we pass only things that
can fit into a single register through here. */
/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
a register through here */
static void
write_exp_elt (expelt)
/* union exp_element expelt; */
long expelt;
union exp_element expelt;
{
union exp_element temp;
temp.longconst = expelt;
if (expout_ptr >= expout_size)
{
expout_size *= 2;
@ -689,25 +691,73 @@ write_exp_elt (expelt)
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
}
expout->elts[expout_ptr++] = /* expelt */ temp;
expout->elts[expout_ptr++] = expelt;
}
/* Things that take more space must come through here. */
static void
write_exp_elt2 (expelt)
write_exp_elt_opcode (expelt)
enum exp_opcode expelt;
{
union exp_element tmp;
tmp.opcode = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_sym (expelt)
struct symbol *expelt;
{
union exp_element tmp;
tmp.symbol = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_longcst (expelt)
LONGEST expelt;
{
union exp_element tmp;
tmp.longconst = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_dblcst (expelt)
double expelt;
{
union exp_element temp;
temp.doubleconst = expelt;
union exp_element tmp;
if (expout_ptr >= expout_size)
{
expout_size *= 2;
expout = (struct expression *) xrealloc (expout,
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
}
expout->elts[expout_ptr++] = temp;
tmp.doubleconst = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_type (expelt)
struct type *expelt;
{
union exp_element tmp;
tmp.type = expelt;
write_exp_elt (tmp);
}
static void
write_exp_elt_intern (expelt)
struct internalvar *expelt;
{
union exp_element tmp;
tmp.internalvar = expelt;
write_exp_elt (tmp);
}
/* Add a string constant to the end of the expression.
@ -726,13 +776,13 @@ write_exp_string (str)
if (expout_ptr >= expout_size)
{
expout_size = max (expout_size * 2, expout_ptr + 10);
expout = (struct expression *) xrealloc (expout,
sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
expout = (struct expression *)
xrealloc (expout, (sizeof (struct expression)
+ (expout_size * sizeof (union exp_element))));
}
bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
write_exp_elt (len);
write_exp_elt_longcst (len);
}
/* During parsing of a C expression, the pointer to the next character
@ -799,12 +849,13 @@ parse_number (olen)
while (len-- > 0)
{
c = *p++;
n *= base;
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
if (c != 'l')
n *= base;
if (c >= '0' && c <= '9')
n += c - '0';
else
{
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
if (base == 16 && c >= 'a' && c <= 'f')
n += c - 'a' + 10;
else if (len == 0 && c == 'l')
@ -861,6 +912,29 @@ static struct token tokentab2[] =
{">=", GEQ, BINOP_END}
};
/* assign machine-independent names to certain registers
* (unless overridden by the REGISTER_NAMES table)
*/
struct std_regs {
char *name;
int regnum;
} std_regs[] = {
#ifdef PC_REGNUM
{ "pc", PC_REGNUM },
#endif
#ifdef FP_REGNUM
{ "fp", FP_REGNUM },
#endif
#ifdef SP_REGNUM
{ "sp", SP_REGNUM },
#endif
#ifdef PS_REGNUM
{ "ps", PS_REGNUM },
#endif
};
#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
/* Read one token, getting characters through lexptr. */
static int
@ -1044,7 +1118,7 @@ yylex ()
/* Handle tokens that refer to machine registers:
$ followed by a register name. */
if (*tokstart == '$')
if (*tokstart == '$') {
for (c = 0; c < NUM_REGS; c++)
if (namelen - 1 == strlen (reg_names[c])
&& !strncmp (tokstart + 1, reg_names[c], namelen - 1))
@ -1052,7 +1126,14 @@ yylex ()
yylval.lval = c;
return REGNAME;
}
for (c = 0; c < NUM_STD_REGS; c++)
if (namelen - 1 == strlen (std_regs[c].name)
&& !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
{
yylval.lval = std_regs[c].regnum;
return REGNAME;
}
}
if (namelen == 6 && !strncmp (tokstart, "struct", 6))
{
return STRUCT;
@ -1070,10 +1151,10 @@ yylex ()
{
return ENUM;
}
if (!strncmp (tokstart, "this", 4))
{
return THIS;
}
if (!strncmp (tokstart, "this", 4)
&& lookup_symbol ("$this", expression_context_block,
VAR_NAMESPACE, 0))
return THIS;
}
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
{
@ -1102,7 +1183,7 @@ yylex ()
return NAME;
}
static
static void
yyerror ()
{
error ("Invalid syntax in expression.");
@ -1361,6 +1442,8 @@ parse_c_1 (stringptr, block, comma)
lexptr = *stringptr;
paren_depth = 0;
comma_terminates = comma;
if (lexptr == 0 || *lexptr == 0)
@ -1374,8 +1457,9 @@ parse_c_1 (stringptr, block, comma)
namecopy = (char *) alloca (strlen (lexptr) + 1);
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *) xmalloc (sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
expout = (struct expression *)
xmalloc (sizeof (struct expression)
+ expout_size * sizeof (union exp_element));
make_cleanup (free_current_contents, &expout);
if (yyparse ())
yyerror ();

View File

@ -175,7 +175,7 @@ union exp_element
{
enum exp_opcode opcode;
struct symbol *symbol;
long longconst;
LONGEST longconst;
double doubleconst;
char string;
struct type *type;

View File

@ -19,7 +19,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
@ -27,34 +26,56 @@ anyone else from sharing it farther. Help stamp out software hoarding!
CORE_ADDR read_register ();
START_FILE
/* 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. */
static CORE_ADDR
CORE_ADDR
find_saved_register (frame, regnum)
FRAME frame;
int regnum;
{
struct frame_info fi;
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;
fi = get_prev_frame_info (frame1);
if (fi.frame == 0 || fi.frame == frame)
frame1 = get_prev_frame (frame1);
if (frame1 == 0 || frame1 == frame)
break;
get_frame_saved_regs (&fi, &saved_regs);
fi = get_frame_info (frame1);
get_frame_saved_regs (fi, &saved_regs);
if (saved_regs.regs[regnum])
addr = saved_regs.regs[regnum];
frame1 = fi.frame;
}
return addr;
@ -73,7 +94,7 @@ read_relative_register_raw_bytes (regnum, myaddr)
if (regnum == FP_REGNUM)
{
bcopy (&selected_frame, myaddr, sizeof (CORE_ADDR));
bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
return;
}
@ -102,15 +123,19 @@ value
value_of_register (regnum)
int regnum;
{
register CORE_ADDR addr = find_saved_register (selected_frame, 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, addr);
return value_from_long (builtin_type_int, (LONGEST) addr);
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
}
else
@ -137,6 +162,7 @@ char registers[REGISTER_BYTES];
starting with the REGBYTE'th byte of register data
into memory at MYADDR. */
void
read_register_bytes (regbyte, myaddr, len)
int regbyte;
char *myaddr;
@ -148,6 +174,7 @@ read_register_bytes (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;
@ -211,7 +238,7 @@ read_var_value (var, frame)
{
register value v;
struct frame_info fi;
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
register CORE_ADDR addr = 0;
@ -260,84 +287,178 @@ read_var_value (var, frame)
case LOC_REGISTER:
case LOC_REGPARM:
{
char raw_buffer[MAX_REGISTER_RAW_SIZE];
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
VALUE_REGNO (v) = val;
/* Locate the register's contents in a real register or in core;
read the data in raw format. */
addr = find_saved_register (frame, val);
if (addr == 0)
{
/* Value is really in a register. */
VALUE_LVAL (v) = lval_register;
VALUE_ADDRESS (v) = REGISTER_BYTE (val);
read_register_bytes (REGISTER_BYTE (val),
raw_buffer, REGISTER_RAW_SIZE (val));
}
else
{
/* Value was in a register that has been saved in memory. */
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (val));
VALUE_ADDRESS (v) = addr;
}
/* Convert the raw contents to virtual contents.
(Just copy them if the formats are the same.) */
REGISTER_CONVERT_TO_VIRTUAL (val, raw_buffer, virtual_buffer);
if (REGISTER_CONVERTIBLE (val))
{
/* 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 (val))
{
/* 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 (val));
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. */
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 (val))
{
/* Big-endian, and we want less than full size. */
VALUE_OFFSET (v) = REGISTER_RAW_SIZE (val) - len;
}
bcopy (virtual_buffer + VALUE_OFFSET (v),
VALUE_CONTENTS (v), len);
}
return v;
}
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,
@ -350,7 +471,7 @@ locate_var_value (var, frame)
{
register CORE_ADDR addr = 0;
int val = SYMBOL_VALUE (var);
struct frame_info fi;
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
if (frame == 0) frame = selected_frame;
@ -367,14 +488,12 @@ locate_var_value (var, frame)
addr = find_saved_register (frame, val);
if (addr != 0)
{
union { int i; char c; } test;
int len = TYPE_LENGTH (type);
/* 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))
#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.",
@ -405,11 +524,6 @@ locate_var_value (var, frame)
}
return value_cast (lookup_pointer_type (type),
value_from_long (builtin_type_long, addr));
value_from_long (builtin_type_long, (LONGEST) addr));
}
static
initialize ()
{}
END_FILE

View File

@ -20,22 +20,62 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* Note that frame.h requires param.h! */
#define FRAME CORE_ADDR
/*
* FRAME is the type of the identifier of a specific stack frame. It
* is a pointer to the frame cache item corresponding to this frame.
* Please note that frame id's are *not* constant over calls to the
* inferior. Use frame addresses, which are.
*
* FRAME_ADDR is the type of the address of a specific frame. I
* cannot imagine a case in which this would not be CORE_ADDR, so
* maybe it's silly to give it it's own type. Life's rough.
*
* FRAME_FP is a macro which converts from a frame identifier into a
* frame_address.
*
* FRAME_INFO_ID is a macro which "converts" from a frame info pointer
* to a frame id. This is here in case I or someone else decides to
* change the FRAME type again.
*
* This file and blockframe.c are the only places which are allowed to
* use the equivalence between FRAME and struct frame_info *. EXCEPTION:
* value.h uses CORE_ADDR instead of FRAME_ADDR because the compiler
* will accept that in the absense of this file.
*/
typedef struct frame_info *FRAME;
typedef CORE_ADDR FRAME_ADDR;
#define FRAME_FP(fr) ((fr)->frame)
#define FRAME_INFO_ID(f) (f)
/*
* Caching structure for stack frames. This is also the structure
* used for extended info about stack frames. May add more to this
* structure as it becomes necessary.
*
* Note that the first entry in the cache will always refer to the
* innermost executing frame. This value should be set (is it?
* Check) in something like normal_stop.
*/
struct frame_info
{
/* Nominal address of the frame described. */
FRAME frame;
FRAME_ADDR frame;
/* Address at which execution is occurring in this frame.
For the innermost frame, it's the current pc.
For other frames, it is a pc saved in the next frame. */
CORE_ADDR pc;
/* The frame called by the frame we are describing, or 0. */
FRAME next_frame;
/* The frame called by `next_frame', or 0 if there is none
(or `next_frame' is 0). */
FRAME next_next_frame;
/* The frame called by the frame we are describing, or 0.
This may be set even if there isn't a frame called by the one
we are describing (.->next == 0); in that case it is simply the
bottom of this frame */
FRAME_ADDR next_frame;
/* Anything extra for this structure that may have been defined
in the machine depedent files. */
#ifdef EXTRA_FRAME_INFO
EXTRA_FRAME_INFO
#endif
/* Pointers to the next and previous frame_info's in this stack. */
FRAME next, prev;
};
/* Describe the saved registers of a frame. */
@ -52,13 +92,14 @@ struct frame_saved_regs
extern FRAME selected_frame;
extern struct frame_info get_frame_info ();
extern struct frame_info get_prev_frame_info ();
extern struct frame_info *get_frame_info ();
extern struct frame_info *get_prev_frame_info ();
extern FRAME create_new_frame ();
extern void get_frame_saved_regs ();
extern FRAME get_prev_frame ();
extern FRAME get_current_frame ();
extern struct block *get_frame_block ();
@ -66,3 +107,7 @@ extern struct block *get_current_block ();
extern struct block *get_selected_block ();
extern struct symbol *get_frame_function ();
extern struct symbol *get_pc_function ();
/* In stack.c */
extern FRAME find_relative_frame ();

View File

@ -1,91 +0,0 @@
.TH GDB 1 "13 April 1987"
.UC 4
.SH NAME
gdb \- Project GNU's DeBugger
.SH SYNOPSIS
\fBgdb\fP [ \fBoptions\fP ] See documentation mentioned below.
.SH DESCRIPTION
\fIgdb\fP is a source level symbolic debugger for C programs, created by
Richard M. Stallman (rms) for the GNU Project, and distributed by the
Free Software Foundation. Eventually GNU (Gnu's Not Unix) will be a
complete replacement for Berkeley Unix, all of which everyone will be
able to use freely. See the \fIGNU Emacs\fP man page for pointers to more
information.
.PP
\fIgdb\fP has something of the flavor of \fIdbx\fP,
but has more features and power. It can also be used to debug o/s
kernels, but needs to be configured differently for that task.
.PP
Project GNU isn't using Unix man pages. Its style of complete
documentation can be found by:
.PP
The help and info commands inside \fIgdb\fP.
.PP
In the Info system in \fIGNU Emacs\fP. Type C-h i, and follow the
directions. This is equivalent to the reference manual for
\fIgdb\fP, and has about 55 pages of text.
.PP
\fIgdb\fP could be extended to work with other languages (e.g. Pascal) and
machines (e.g. encores). If you like, copy the sources and give it a
try. When you have it working send \fIdiff -c\fP's of the changed files to
bug-gdb@prep.ai.mit.edu (fuller details below), so they can benefit everyone.
.SH DISTRIBUTION
\fIgdb\fP is free; anyone may redistribute copies of
\fIgdb\fP to anyone under the terms stated in the
\fIgdb\fP General Public License, a copy of which accompanies each copy of
\fIgdb\fP, is readable with the info command inside \fIgdb\fP,
and which also appears in the \fIgdb\fP reference manual.
.PP
Copies of \fIgdb\fP may sometimes be received packaged with
distributions of Unix systems, but it is never included in the scope
of any license covering those systems. Such inclusion would violate
the terms on which distribution is permitted. In fact, the primary
purpose of the General Public License is to prohibit anyone from
attaching any other restrictions to redistribution of \fIgdb\fP.
.PP
You can order printed copies of the \fIgdb\fP reference manual for $10.00/copy
postpaid from the Free Software Foundation, which develops GNU software
(contact them for quantity prices on the manual). Their address is:
.nf
Free Software Foundation
1000 Mass Ave.
Cambridge, MA 02138
.fi
As with all software and publications from FSF, everyone is permitted to
make and distribute copies of the \fIgdb\fP reference manual.
The TeX source to the \fIgdb\fP reference
manual is also included in the \fIGNU Emacs\fP source distribution.
.PP
.SH OPTIONS
See documentation.
.SH EXAMPLES
See documentation.
.SH "SEE ALSO"
adb(1), sdb(1), dbx(1)
.SH BUGS
There is a mailing list, bug-gdb@prep.ai.mit.edu on the internet
(ucbvax!prep.ai.mit.edu!bug-gdb on UUCPnet), for reporting \fIgdb\fP
bugs and fixes. But before reporting something as a bug, please try
to be sure that it really is a bug, not a misunderstanding or a
deliberate feature. We ask you to read the section ``Reporting Emacs
Bugs'' near the end of the \fIGNU Emacs\fP reference manual
(or Info system) for hints
on how and when to report bugs. Also, include the version number of
the \fIgdb\fP you are running in \fIevery\fR bug report that you send in.
.PP
Do not expect a personal answer to a bug report. The purpose of reporting
bugs is to get them fixed for everyone in the next release, if possible.
For personal assistance, look in the SERVICE file
(see the \fIGNU Emacs\fP man page) for
a list of people who offer it.
.PP
Please do not send anything but bug reports to this mailing list.
Send other stuff to gnu@prep.ai.mit.edu (or the
corresponding UUCP address). For more information about GNU mailing
lists, see the file MAILINGLISTS (see the \fIGNU Emacs\fP man page). Bugs tend
actually to be fixed if they can be isolated, so it is in your
interest to report them in such a way that they can be easily
reproduced.
.PP
No bugs are known at this time.

File diff suppressed because it is too large Load Diff

2924
gdb/gdb.texinfo Normal file

File diff suppressed because it is too large Load Diff

68
gdb/gdbcore.h Normal file
View File

@ -0,0 +1,68 @@
/* 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;

25
gdb/getpagesize.h Normal file
View File

@ -0,0 +1,25 @@
#ifdef BSD
#ifndef BSD4_1
#define HAVE_GETPAGESIZE
#endif
#endif
#ifndef HAVE_GETPAGESIZE
#include <sys/param.h>
#ifdef EXEC_PAGESIZE
#define getpagesize() EXEC_PAGESIZE
#else
#ifdef NBPG
#define getpagesize() NBPG * CLSIZE
#ifndef CLSIZE
#define CLSIZE 1
#endif /* no CLSIZE */
#else /* no NBPG */
#define getpagesize() NBPC
#endif /* no NBPG */
#endif /* no EXEC_PAGESIZE */
#endif /* not HAVE_GETPAGESIZE */

View File

@ -192,14 +192,14 @@ print_insn (memaddr, stream)
* Find the number of arguments to a function.
*/
findarg(frame)
struct frame_info frame;
struct frame_info *frame;
{
register struct symbol *func;
register unsigned pc;
#ifdef notdef
/* find starting address of frame function */
pc = get_pc_function_start (frame.pc);
pc = get_pc_function_start (frame->pc);
/* find function symbol info */
func = find_pc_function (pc);
@ -220,29 +220,35 @@ findarg(frame)
* 1.) stored in the code function header xA(Br1).
* 2.) must be careful of recurssion.
*/
FRAME_ADDR
findframe(thisframe)
FRAME thisframe;
{
register FRAME pointer;
struct frame_info frame;
register FRAME_ADDR pointer;
#if 0
struct frame_info *frame;
FRAME_ADDR framechain();
/* Setup toplevel frame structure */
frame.pc = read_pc();
frame.next_frame = 0;
frame.frame = read_register (SP_REGNUM); /* Br2 */
frame->pc = read_pc();
frame->next_frame = 0;
frame->frame = read_register (SP_REGNUM); /* Br2 */
/* Search for this frame (start at current Br2) */
do
{
pointer = framechain(frame);
frame.next_frame = frame.frame;
frame.frame = pointer;
frame.pc = FRAME_SAVED_PC(frame.next_frame);
frame->next_frame = frame->frame;
frame->frame = pointer;
frame->pc = FRAME_SAVED_PC(frame);
}
while (frame.next_frame != thisframe);
while (frame->next_frame != thisframe);
#endif
pointer = framechain (thisframe);
/* stop gap for now, end at __base3 */
if (frame.pc == 0)
if (thisframe->pc == 0)
return 0;
return pointer;
@ -252,20 +258,21 @@ findframe(thisframe)
* Gdb front-end and internal framechain routine.
* Go back up stack one level. Tricky...
*/
FRAME_ADDR
framechain(frame)
register struct frame_info frame;
register struct frame_info *frame;
{
register CORE_ADDR func, prevsp;
register unsigned value;
/* Get real function start address from internal frame address */
func = get_pc_function_start(frame.pc);
func = get_pc_function_start(frame->pc);
/* If no stack given, read register Br1 "(sp)" */
if (!frame.frame)
if (!frame->frame)
prevsp = read_register (SP_REGNUM);
else
prevsp = frame.frame;
prevsp = frame->frame;
/* Check function header, case #2 */
value = read_memory_integer (func, 4);

550
gdb/gould-dep.c Normal file
View File

@ -0,0 +1,550 @@
/* 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"
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <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. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
inferior_died ();
}
/* This is used when GDB is exiting. It gives less chance of error.*/
kill_inferior_fast ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
{
errno = 0;
if (remote_debugging)
remote_resume (step, signal);
else
{
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
}
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;
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;
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
}
/* 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;
}
/* 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 (filename);
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);
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
core_aouthdr.a_magic = 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 (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
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;
FILHDR exec_coffhdr;
val = myread (execchan, &exec_coffhdr, sizeof exec_coffhdr);
if (val < 0)
perror_with_name (filename);
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_coffhdr, exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_coffhdr, 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);
}

132
gdb/hp-include/a.out.h Normal file
View File

@ -0,0 +1,132 @@
/* Special version of <a.out.h> for use under hp-ux.
Copyright (C) 1988 Free Software Foundation, Inc. */
/* The `exec' structure and overall layout must be close to HP's when
we are running on an HP system, otherwise we will not be able to
execute the resulting file. */
/* Allow this file to be included twice. */
#ifndef EXEC_PAGESIZE
struct exec
{
unsigned short a_machtype; /* machine type */
unsigned short a_magic; /* magic number */
unsigned long a_spare1;
unsigned long a_spare2;
unsigned long a_text; /* size of text segment */
unsigned long a_data; /* size of data segment */
unsigned long a_bss; /* size of bss segment */
unsigned long a_trsize; /* text relocation size */
unsigned long a_drsize; /* data relocation size */
unsigned long a_spare3; /* HP = pascal interface size */
unsigned long a_spare4; /* HP = symbol table size */
unsigned long a_spare5; /* HP = debug name table size */
unsigned long a_entry; /* entry point */
unsigned long a_spare6; /* HP = source line table size */
unsigned long a_spare7; /* HP = value table size */
unsigned long a_syms; /* symbol table size */
unsigned long a_spare8;
};
#define OMAGIC 0x107
#define NMAGIC 0x108
#define ZMAGIC 0x10B
#define N_BADTYPE(x) \
((((x) . a_magic) != OMAGIC) \
&& (((x) . a_magic) != NMAGIC) \
&& (((x) . a_magic) != ZMAGIC))
#define HP98x6_ID 0x20A
#define HP9000S200_ID 0x20C
#define N_BADMACH(x) \
((((x) . a_machtype) != HP9000S200_ID) \
&& (((x) . a_machtype) != HP98x6_ID))
#define N_BADMAG(x) ((N_BADTYPE (x)) || (N_BADMACH (x)))
#define EXEC_PAGESIZE 0x1000
#define EXEC_ALIGN(offset) \
(((offset) + (EXEC_PAGESIZE - 1)) & (~ (EXEC_PAGESIZE - 1)))
#define N_TXTOFF(x) \
((((x) . a_magic) == ZMAGIC) \
? (EXEC_ALIGN (sizeof (struct exec))) \
: (sizeof (struct exec)))
#define N_DATOFF(x) \
((((x) . a_magic) == ZMAGIC) \
? ((EXEC_ALIGN (sizeof (struct exec))) \
+ (EXEC_ALIGN ((x) . a_text))) \
: ((sizeof (struct exec)) + ((x) . a_text)))
#define N_TROFF(x) \
((((x) . a_magic) == ZMAGIC) \
? ((EXEC_ALIGN (sizeof (struct exec))) \
+ (EXEC_ALIGN ((x) . a_text)) \
+ (EXEC_ALIGN ((x) . a_data))) \
: ((sizeof (struct exec)) + ((x) . a_text) + ((x) . a_data)))
#define N_SYMOFF(x) ((N_TROFF (x)) + ((x) . a_trsize) + ((x) . a_drsize))
#define N_STROFF(x) ((N_SYMOFF (x)) + ((x) . a_syms))
/* Macros which take exec structures as arguments and tell where the
various pieces will be loaded. */
#define N_TXTADDR(x) 0
#define N_DATADDR(x) \
((((x) . a_magic) == OMAGIC) \
? ((x) . a_text) \
: (EXEC_ALIGN ((x) . a_text)))
#define N_BSSADDR(x) ((N_DATADDR (x)) + ((x) . a_data))
struct relocation_info
{
long r_address; /* address which is relocated */
unsigned int
r_symbolnum : 24, /* local symbol ordinal */
r_pcrel : 1, /* was relocated pc relative already */
r_length : 2, /* 0=byte, 1=word, 2=long */
r_extern : 1, /* does not include value of sym referenced */
: 4; /* nothing, yet */
};
struct nlist
{
union
{
char *n_name; /* for use when in-core */
long n_strx; /* index into file string table */
} n_un;
unsigned char n_type; /* type flag (N_TEXT,..) */
char n_other; /* unused */
short n_desc; /* see <stab.h> */
unsigned long n_value; /* value of symbol (or sdb offset) */
};
/* Simple values for n_type. */
#define N_UNDF 0x00 /* undefined */
#define N_ABS 0x02 /* absolute */
#define N_TEXT 0x04 /* text */
#define N_DATA 0x06 /* data */
#define N_BSS 0x08 /* bss */
#define N_COMM 0x12 /* common (internal to ld) */
#define N_FN 0x1F /* file name symbol */
#define N_EXT 0x01 /* external bit, or'ed in */
#define N_TYPE 0x1E /* mask for all the type bits */
/* dbx entries have some of the N_STAB bits set.
These are given in <stab.h> */
#define N_STAB 0xE0 /* if any of these bits set, a dbx symbol */
/* Format for namelist values. */
#define N_FORMAT "%08x"
#endif /* EXEC_PAGESIZE */

47
gdb/hp-include/stab.h Normal file
View File

@ -0,0 +1,47 @@
/* @(#)stab.h 1.1 86/07/07 SMI; from UCB X.X XX/XX/XX */
/* IF YOU ADD DEFINITIONS, ADD THEM TO nm.c as well */
/*
* This file gives definitions supplementing <a.out.h>
* for permanent symbol table entries.
* These must have one of the N_STAB bits on,
* and are subject to relocation according to the masks in <a.out.h>.
*/
/*
* for symbolic debugger, sdb(1):
*/
#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */
#define N_STSYM 0x26 /* static symbol: name,,0,type,address */
#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */
#define N_MAIN 0x2a /* name of main routine : name,,0,0,0 */
#define N_RSYM 0x40 /* register sym: name,,0,type,register */
#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */
#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
#define N_SO 0x64 /* source file name: name,,0,0,address */
#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
#define N_BINCL 0x82 /* header file: name,,0,0,0 */
#define N_SOL 0x84 /* #included file name: name,,0,0,address */
#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
#define N_EINCL 0xa2 /* end of include file */
#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */
#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */
#define N_EXCL 0xc2 /* excluded include file */
#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */
#define N_BCOMM 0xe2 /* begin common: name,, */
#define N_ECOMM 0xe4 /* end common: name,, */
#define N_ECOML 0xe8 /* end common (local name): ,,address */
#define N_LENG 0xfe /* second stab entry with length information */
/*
* for the berkeley pascal compiler, pc(1):
*/
#define N_PC 0x30 /* global pascal symbol: name,,0,subtype,line */
/*
* for modula-2 compiler only
*/
#define N_M2C 0x42 /* compilation unit stab */
#define N_SCOPE 0xc4 /* scope information */

View File

@ -0,0 +1,73 @@
/* @(#)fcntl.h 1.3 86/07/16 SMI; from UCB 5.1 85/05/30 */
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef __FCNTL_HEADER__
#define __FCNTL_HEADER__
/*
* Flag values accessible to open(2) and fcntl(2)
* (The first three can only be set by open)
*/
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#define O_NDELAY FNDELAY /* Non-blocking I/O */
#define O_APPEND FAPPEND /* append (writes guaranteed at the end) */
#define O_CREAT FCREAT /* open with file create */
#define O_TRUNC FTRUNC /* open with truncation */
#define O_EXCL FEXCL /* error on create if file exists */
/* flags for F_GETFL, F_SETFL-- needed by <sys/file.h> */
#define FNDELAY 00004 /* non-blocking reads */
#define FAPPEND 00010 /* append on each write */
#define FASYNC 00100 /* signal pgrp when data ready */
#define FCREAT 01000 /* create if nonexistant */
#define FTRUNC 02000 /* truncate to zero length */
#define FEXCL 04000 /* error if already created */
/* fcntl(2) requests */
#define F_DUPFD 0 /* Duplicate fildes */
#define F_GETFD 1 /* Get fildes flags */
#define F_SETFD 2 /* Set fildes flags */
#define F_GETFL 3 /* Get file flags */
#define F_SETFL 4 /* Set file flags */
#define F_GETOWN 5 /* Get owner */
#define F_SETOWN 6 /* Set owner */
#define F_GETLK 7 /* Get record-locking information */
#define F_SETLK 8 /* Set or Clear a record-lock (Non-Blocking) */
#define F_SETLKW 9 /* Set or Clear a record-lock (Blocking) */
/* access(2) requests */
#define F_OK 0 /* does file exist */
#define X_OK 1 /* is it executable by caller */
#define W_OK 2 /* writable by caller */
#define R_OK 4 /* readable by caller */
/* System-V record-locking options */
/* lockf(2) requests */
#define F_ULOCK 0 /* Unlock a previously locked region */
#define F_LOCK 1 /* Lock a region for exclusive use */
#define F_TLOCK 2 /* Test and lock a region for exclusive use */
#define F_TEST 3 /* Test a region for other processes locks */
/* fcntl(2) flags (l_type field of flock structure) */
#define F_RDLCK 1 /* read lock */
#define F_WRLCK 2 /* write lock */
#define F_UNLCK 3 /* remove lock(s) */
/* file segment locking set data type - information passed to system by user */
struct flock {
short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */
short l_whence; /* flag to choose starting offset */
long l_start; /* relative offset, in bytes */
long l_len; /* length, in bytes; 0 means lock to EOF */
short l_pid; /* returned with F_GETLK */
short l_xxx; /* reserved for future use */
};
#endif !__FCNTL_HEADER__

643
gdb/hp9k320-dep.c Normal file
View File

@ -0,0 +1,643 @@
/* 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"
#include <stdio.h>
#define WOPR
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/trap.h>
#include <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. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
inferior_died ();
}
/* This is used when GDB is exiting. It gives less chance of error.*/
kill_inferior_fast ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
wait (0);
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
{
errno = 0;
if (remote_debugging)
remote_resume (step, signal);
else
{
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
}
#define INFERIOR_AR0(u) \
((ptrace \
(PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
- KERNEL_U_ADDR)
static void
fetch_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
{
#ifndef HPUX_VERSION_5
if (regno == PS_REGNUM)
{
union { int i; short s[2]; } ps_val;
int regval;
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
regval = ps_val.s[0];
supply_register (regno, &regval);
}
else
#endif /* not HPUX_VERSION_5 */
{
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
return;
}
static void
store_inferior_register_1 (regno, regaddr, value)
int regno;
unsigned int regaddr;
int value;
{
errno = 0;
ptrace (PT_WUAREA, inferior_pid, regaddr, value);
#if 0
/* HP-UX randomly sets errno to non-zero for regno == 25.
However, the value is correctly written, so ignore errno. */
if (errno != 0)
{
char string_buf[64];
sprintf (string_buf, "writing register number %d", regno);
perror_with_name (string_buf);
}
#endif
return;
}
static void
store_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
{
#ifndef HPUX_VERSION_5
if (regno == PS_REGNUM)
{
union { int i; short s[2]; } ps_val;
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
ps_val.s[0] = (read_register (regno));
store_inferior_register_1 (regno, regaddr, ps_val.i);
}
else
#endif /* not HPUX_VERSION_5 */
{
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
extern char registers[];
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
store_inferior_register_1
(regno, regaddr,
(*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
regaddr += sizeof (int);
}
}
return;
}
void
fetch_inferior_registers ()
{
struct user u;
register int regno;
register unsigned int ar0_offset;
ar0_offset = (INFERIOR_AR0 (u));
for (regno = 0; (regno < FP0_REGNUM); regno++)
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
}
/* 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)
register int regno;
{
struct user u;
register unsigned int ar0_offset;
if (regno >= FP0_REGNUM)
{
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
return;
}
ar0_offset = (INFERIOR_AR0 (u));
if (regno >= 0)
{
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
return;
}
for (regno = 0; (regno < FP0_REGNUM); regno++)
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
return;
}
/* 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;
}
/* 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
#ifdef HPUX_VERSION_5
#define e_PS e_regs[PS]
#define e_PC e_regs[PC]
#endif /* HPUX_VERSION_5 */
#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 (filename);
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);
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
core_aouthdr.a_magic = 0;
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
struct exception_stack es;
int val;
val = lseek (corechan, (REGISTER_ADDR (reg_offset, 0)), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, es,
((char *) &es.e_offset - (char *) &es.e_regs[R0]));
if (val < 0)
perror_with_name (filename);
for (regno = 0; (regno < PS_REGNUM); regno++)
supply_register (regno, &es.e_regs[regno + R0]);
val = es.e_PS;
supply_register (regno++, &val);
supply_register (regno++, &es.e_PC);
for (; (regno < NUM_REGS); regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, (FP_REGISTER_ADDR (u, regno)), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
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;
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);
}

1203
gdb/i386-dep.c Normal file

File diff suppressed because it is too large Load Diff

1813
gdb/i386-pinsn.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -19,9 +19,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "initialize.h"
#include "symtab.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
#include "environ.h"
@ -59,7 +58,7 @@ CORE_ADDR stop_pc;
/* Stack frame when program stopped. */
FRAME stop_frame;
FRAME_ADDR stop_frame_address;
/* Number of breakpoint it stopped at, or 0 if none. */
@ -73,6 +72,11 @@ int stop_step;
int stop_stack_dummy;
/* Nonzero if stopped due to a random (unexpected) signal in inferior
process. */
int stopped_by_random_signal;
/* Range to single step within.
If this is nonzero, respond to a single-step signal
by continuing to step if the pc is in this range. */
@ -84,7 +88,7 @@ CORE_ADDR step_range_end; /* Exclusive */
This is how we know when we step into a subroutine call,
and how to set the frame for the breakpoint used to step out. */
CORE_ADDR step_frame;
FRAME_ADDR step_frame_address;
/* 1 means step over all subroutine calls.
-1 means step over calls to undebuggable functions. */
@ -105,7 +109,6 @@ struct environ *inferior_environ;
CORE_ADDR read_pc ();
struct command_line *get_breakpoint_commands ();
START_FILE
int
have_inferior_p ()
@ -150,11 +153,11 @@ run_command (args, from_tty)
if (inferior_pid)
{
if (query ("The program being debugged has been started already.\n\
if (
!query ("The program being debugged has been started already.\n\
Start it from the beginning? "))
kill_inferior ();
else
error ("Program already started.");
error ("Program not restarted.");
kill_inferior ();
}
if (remote_debugging)
@ -200,7 +203,7 @@ cont_command (proc_count_exp, from_tty)
/* If have argument, set proceed count of breakpoint we stopped at. */
if (stop_breakpoint && proc_count_exp)
if (stop_breakpoint > 0 && proc_count_exp)
{
set_ignore_count (stop_breakpoint,
parse_and_eval_address (proc_count_exp) - 1,
@ -261,21 +264,36 @@ step_1 (skip_subroutines, single_inst, count_string)
{
clear_proceed_status ();
step_frame = get_current_frame ();
step_frame_address = FRAME_FP (get_current_frame ());
if (! single_inst)
{
find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
if (step_range_end == 0)
{
int misc;
misc = find_pc_misc_function (stop_pc);
terminal_ours ();
error ("Current function has no line number information.");
printf ("Current function has no line number information.\n");
fflush (stdout);
/* No info or after _etext ("Can't happen") */
if (misc == -1 || misc == misc_function_count - 1)
error ("No data available on pc function.");
printf ("Single stepping until function exit.\n");
fflush (stdout);
step_range_start = misc_function_vector[misc].address;
step_range_end = misc_function_vector[misc + 1].address;
}
}
else
{
/* Say we are stepping, but stop after one insn whatever it does.
Don't step through subroutine calls even to undebuggable functions. */
Don't step through subroutine calls even to undebuggable
functions. */
step_range_start = step_range_end = 1;
if (!skip_subroutines)
step_over_calls = 0;
@ -307,7 +325,7 @@ jump_command (arg, from_tty)
if (!arg)
error_no_arg ("starting address");
sals = decode_line_spec (arg, 1);
sals = decode_line_spec_1 (arg, 1);
if (sals.nelts != 1)
{
error ("Unreasonable jump request");
@ -393,20 +411,6 @@ run_stack_dummy (addr, buffer)
CORE_ADDR addr;
REGISTER_TYPE *buffer;
{
int saved_pc_changed = pc_changed;
int saved_stop_signal = stop_signal;
int saved_stop_pc = stop_pc;
int saved_stop_frame = stop_frame;
int saved_stop_breakpoint = stop_breakpoint;
int saved_stop_step = stop_step;
int saved_stop_stack_dummy = stop_stack_dummy;
FRAME saved_selected_frame;
int saved_selected_level;
struct command_line *saved_breakpoint_commands
= get_breakpoint_commands ();
record_selected_frame (&saved_selected_frame, &saved_selected_level);
/* Now proceed, having reached the desired place. */
clear_proceed_status ();
if (stack_dummy_testing & 4)
@ -419,21 +423,86 @@ run_stack_dummy (addr, buffer)
if (!stop_stack_dummy)
error ("Cannot continue previously requested operation.");
set_breakpoint_commands (saved_breakpoint_commands);
select_frame (saved_selected_frame, saved_selected_level);
stop_signal = saved_stop_signal;
stop_pc = saved_stop_pc;
stop_frame = saved_stop_frame;
stop_breakpoint = saved_stop_breakpoint;
stop_step = saved_stop_step;
stop_stack_dummy = saved_stop_stack_dummy;
pc_changed = saved_pc_changed;
/* On return, the stack dummy has been popped already. */
bcopy (stop_registers, buffer, sizeof stop_registers);
}
/* Proceed until we reach the given line as argument or exit the
function. When called with no argument, proceed until we reach a
different source line with pc greater than our current one or exit
the function. We skip calls in both cases.
The effect of this command with an argument is identical to setting
a momentary breakpoint at the line specified and executing
"finish".
Note that eventually this command should probably be changed so
that only source lines are printed out when we hit the breakpoint
we set. I'm going to postpone this until after a hopeful rewrite
of wait_for_inferior and the proceed status code. -- randy */
void
until_next_command (arg, from_tty)
char *arg;
int from_tty;
{
FRAME frame;
CORE_ADDR pc;
struct symbol *func;
struct symtab_and_line sal;
clear_proceed_status ();
frame = get_current_frame ();
/* Step until either exited from this function or greater
than the current line (if in symbolic section) or pc (if
not). */
pc = read_pc ();
func = find_pc_function (pc);
if (!func)
{
int misc_func = find_pc_misc_function (pc);
if (misc_func != -1)
error ("Execution is not within a known function.");
step_range_start = misc_function_vector[misc_func].address;
step_range_end = pc;
}
else
{
sal = find_pc_line (pc, 0);
step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
step_range_end = sal.end;
}
step_over_calls = 1;
step_frame_address = FRAME_FP (frame);
step_multi = 0; /* Only one call to proceed */
proceed (-1, -1, 1);
}
void
until_command (arg, from_tty)
char *arg;
int from_tty;
{
if (!have_inferior_p ())
error ("The program is not being run.");
if (arg)
until_break_command (arg, from_tty);
else
until_next_command (arg, from_tty);
}
/* "finish": Set a temporary breakpoint at the place
the selected frame will return to, then continue. */
@ -444,8 +513,7 @@ finish_command (arg, from_tty)
{
struct symtab_and_line sal;
register FRAME frame;
struct frame_info fi;
struct frame_info *fi;
register struct symbol *function;
if (!have_inferior_p ())
@ -460,14 +528,14 @@ finish_command (arg, from_tty)
clear_proceed_status ();
fi = get_frame_info (frame);
sal = find_pc_line (fi.pc, 0);
sal.pc = fi.pc;
sal = find_pc_line (fi->pc, 0);
sal.pc = fi->pc;
set_momentary_breakpoint (sal, frame);
/* Find the function we will return from. */
fi = get_frame_info (fi.next_frame, fi.next_next_frame);
function = find_pc_function (fi.pc);
fi = get_frame_info (selected_frame);
function = find_pc_function (fi->pc);
if (from_tty)
{
@ -481,12 +549,22 @@ finish_command (arg, from_tty)
{
struct type *value_type;
register value val;
CORE_ADDR funcaddr;
value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
if (!value_type)
fatal ("internal: finish_command: function has no target type");
if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
return;
val = value_being_returned (value_type, stop_registers);
funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
val = value_being_returned (value_type, stop_registers,
using_struct_return (function,
funcaddr,
value_type));
printf ("Value returned is $%d = ", record_latest_value (val));
value_print (val, stdout, 0);
putchar ('\n');
@ -506,7 +584,7 @@ program_info ()
inferior_pid, stop_pc);
if (stop_step)
printf ("It stopped after being stepped.\n");
else if (stop_breakpoint)
else if (stop_breakpoint > 0)
printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
else if (stop_signal)
printf ("It stopped with signal %d (%s).\n",
@ -540,30 +618,58 @@ set_environment_command (arg)
char *arg;
{
register char *p, *val, *var;
int nullset = 0;
if (arg == 0)
error_no_arg ("environment variable and value");
/* Find seperation between variable name and value */
p = (char *) index (arg, '=');
val = (char *) index (arg, ' ');
if (p != 0 && val != 0)
p = arg + min (p - arg, val - arg);
{
/* We have both a space and an equals. If the space is before the
equals and the only thing between the two is more space, use
the equals */
if (p > val)
while (*val == ' ')
val++;
/* Take the smaller of the two. If there was space before the
"=", they will be the same right now. */
p = arg + min (p - arg, val - arg);
}
else if (val != 0 && p == 0)
p = val;
if (p == 0)
error ("Space or \"=\" must separate variable name and its value");
if (p[1] == 0)
error_no_arg ("value for the variable");
if (p == arg)
error_no_arg ("environment variable to set");
val = p + 1;
while (*val == ' ' || *val == '\t') val++;
if (p == 0 || p[1] == 0)
{
nullset = 1;
if (p == 0)
p = arg + strlen (arg); /* So that savestring below will work */
}
else
{
/* Not setting variable value to null */
val = p + 1;
while (*val == ' ' || *val == '\t')
val++;
}
while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
var = savestring (arg, p - arg);
set_in_environ (inferior_environ, var, val);
if (nullset)
{
printf ("Setting environment variable \"%s\" to null value.\n", var);
set_in_environ (inferior_environ, var, "");
}
else
set_in_environ (inferior_environ, var, val);
free (var);
}
@ -579,6 +685,7 @@ unset_environment_command (var)
/* Read an integer from debugged memory, given address and number of bytes. */
long
read_memory_integer (memaddr, len)
CORE_ADDR memaddr;
int len;
@ -617,6 +724,7 @@ read_pc ()
return (CORE_ADDR) read_register (PC_REGNUM);
}
void
write_pc (val)
CORE_ADDR val;
{
@ -635,6 +743,9 @@ registers_info (addr_exp)
register int i;
int regnum;
if (!have_inferior_p () && !have_core_file_p ())
error ("No inferior or core file");
if (addr_exp)
{
if (*addr_exp >= '0' && *addr_exp <= '9')
@ -669,7 +780,7 @@ registers_info (addr_exp)
{
printf ("--Type Return to print more--");
fflush (stdout);
read_line ();
gdb_read_line (0, 0);
}
/* Get the data in raw format, then convert also to virtual format. */
@ -681,7 +792,8 @@ registers_info (addr_exp)
/* If virtual format is floating, print it that way. */
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
&& ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0, 1);
val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
stdout, 0, 1);
/* Else if virtual format is too long for printf,
print in hex a byte at a time. */
else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long))
@ -824,16 +936,31 @@ detach_command (args, from_tty)
inferior_pid = 0;
}
#endif /* ATTACH_DETACH */
/* ARGUSUED */
static void
float_info (addr_exp)
char *addr_exp;
{
#ifdef FLOAT_INFO
FLOAT_INFO;
#else
printf ("No floating point info available for this processor.\n");
#endif
}
static
initialize ()
extern struct cmd_list_element *setlist, *deletelist;
void
_initialize_infcmd ()
{
add_com ("tty", class_run, tty_command,
"Set terminal for future runs of program being debugged.");
add_com ("set-args", class_run, set_args_command,
add_cmd ("args", class_run, set_args_command,
"Specify arguments to give program being debugged when it is started.\n\
Follow this command with any number of args, to be passed to the program.");
Follow this command with any number of args, to be passed to the program.",
&setlist);
add_info ("environment", environment_info,
"The environment to give the program, or one variable's value.\n\
@ -841,14 +968,17 @@ With an argument VAR, prints the value of environment variable VAR to\n\
give the program being debugged. With no arguments, prints the entire\n\
environment to be given to the program.");
add_com ("unset-environment", class_run, unset_environment_command,
add_cmd ("environment", class_run, unset_environment_command,
"Cancel environment variable VAR for the program.\n\
This does not affect the program until the next \"run\" command.");
add_com ("set-environment", class_run, set_environment_command,
This does not affect the program until the next \"run\" command.",
&deletelist);
add_cmd ("environment", class_run, set_environment_command,
"Set environment variable value to give the program.\n\
Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
VALUES of environment variables are uninterpreted strings.\n\
This does not affect the program until the next \"run\" command.");
This does not affect the program until the next \"run\" command.",
&setlist);
#ifdef ATTACH_DETACH
add_com ("attach", class_run, attach_command,
@ -892,6 +1022,12 @@ Argument N means do this N times (or till program stops for another reason).");
Argument N means do this N times (or till program stops for another reason).");
add_com_alias ("s", "step", class_run, 1);
add_com ("until", class_run, until_command,
"Execute until the program reaches a source line greater than the current\n\
or a specified line or address or function (same args as break command).\n\
Execution will also stop upon exit from the current stack frame.");
add_com_alias ("u", "until", class_run, 1);
add_com ("jump", class_run, jump_command,
"Continue program being debugged at specified line or address.\n\
Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
@ -919,9 +1055,11 @@ Register name as argument means describe only that register.");
add_info ("program", program_info,
"Execution status of the program.");
add_info ("float", float_info,
"Print the status of the floating point unit\n");
inferior_args = savestring (" ", 1); /* By default, no args. */
inferior_environ = make_environ ();
init_environ (inferior_environ);
}
END_FILE

View File

@ -19,6 +19,40 @@ 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!
*/
/*
* Structure in which to save the status of the inferior. Save
* through "save_inferior_status", restore through
* "restore_inferior_status".
* This pair of routines should be called around any transfer of
* control to the inferior which you don't want showing up in your
* control variables.
*/
struct inferior_status {
int pc_changed;
int stop_signal;
int stop_pc;
int stop_frame_address;
int stop_breakpoint;
int stop_step;
int stop_stack_dummy;
int stopped_by_random_signal;
int trap_expected;
CORE_ADDR step_range_start;
CORE_ADDR step_range_end;
FRAME_ADDR step_frame_address;
int step_over_calls;
CORE_ADDR step_resume_break_address;
int stop_after_trap;
int stop_after_attach;
FRAME_ADDR selected_frame_address;
int selected_level;
struct command_line *breakpoint_commands;
char stop_registers[REGISTER_BYTES];
int restore_stack_info;
};
void save_inferior_status (), restore_inferior_status ();
/* File name for default use for standard in/out in the inferior. */
extern char *inferior_io_terminal;
@ -41,7 +75,7 @@ extern CORE_ADDR stop_pc;
/* Stack frame when program stopped. */
extern FRAME stop_frame;
extern FRAME_ADDR stop_frame_address;
/* Number of breakpoint it stopped at, or 0 if none. */
@ -55,6 +89,11 @@ extern int stop_step;
extern int stop_stack_dummy;
/* Nonzero if program stopped due to a random (unexpected) signal in
inferior process. */
extern int stopped_by_random_signal;
/* Range to single step within.
If this is nonzero, respond to a single-step signal
by continuing to step if the pc is in this range. */
@ -66,7 +105,7 @@ extern CORE_ADDR step_range_end; /* Exclusive */
This is how we know when we step into a subroutine call,
and how to set the frame for the breakpoint used to step out. */
extern CORE_ADDR step_frame;
extern FRAME_ADDR step_frame_address;
/* 1 means step over all subroutine calls.
-1 means step over calls to undebuggable functions. */
@ -87,3 +126,6 @@ extern char stop_registers[REGISTER_BYTES];
since the inferior stopped. */
extern int pc_changed;
long read_memory_integer ();

View File

@ -17,40 +17,20 @@ 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 "initialize.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>
#ifndef UMAX_PTRACE
#include <sys/user.h>
#endif
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef UMAX_PTRACE
#include <a.out.h>
#include <sys/ptrace.h>
#define PTRACE_ATTACH PT_ATTACH
#define PTRACE_DETACH PT_FREEPROC
#endif
#ifdef NEW_SUN_PTRACE
#include <sys/ptrace.h>
#include <machine/reg.h>
#endif
#ifdef HP9K320
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/trap.h>
#endif
#ifdef HAVE_TERMIO
#include <termio.h>
@ -62,34 +42,48 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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. */
static int attach_flag;
int attach_flag;
START_FILE
/* 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 TIOCGLTC
#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 /* TIOCGLTC */
#endif
#ifdef TIOCGPGRP
static int pgrp_inferior;
@ -120,11 +114,17 @@ terminal_init_inferior ()
sg_inferior = sg_ours;
tflags_inferior = tflags_ours;
#ifdef TIOCGLTC
#ifdef TIOCGETC
tc_inferior = tc_ours;
#endif
#ifdef TIOCGLTC
ltc_inferior = ltc_ours;
#endif
#ifdef TIOCLGET
lmode_inferior = lmode_ours;
#endif /* TIOCGLTC */
#endif
#ifdef TIOCGPGRP
pgrp_inferior = inferior_pid;
@ -147,18 +147,21 @@ terminal_inferior ()
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
ioctl (0, TIOCSETN, &sg_inferior);
#ifdef TIOCGLTC
#ifdef TIOCGETC
ioctl (0, TIOCSETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_inferior);
#endif /* TIOCGLTC */
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCSPGRP, &pgrp_inferior);
#else
sigint_ours = (signal (SIGINT, SIG_IGN));
sigquit_ours = (signal (SIGQUIT, SIG_IGN));
sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
#endif /* TIOCGPGRP */
}
terminal_is_ours = 0;
@ -222,11 +225,15 @@ terminal_ours_1 (output_only)
tflags_inferior = fcntl (0, F_GETFL, 0);
ioctl (0, TIOCGETP, &sg_inferior);
#ifdef TIOCGLTC
#ifdef TIOCGETC
ioctl (0, TIOCGETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_inferior);
#endif /* TIOCGLTC */
#endif
}
#ifdef HAVE_TERMIO
@ -243,11 +250,15 @@ terminal_ours_1 (output_only)
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
#ifdef TIOCGLTC
#ifdef TIOCGETC
ioctl (0, TIOCSETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_ours);
#endif /* TIOCGLTC */
#endif
#ifdef HAVE_TERMIO
@ -283,18 +294,29 @@ term_status_command ()
#else /* not HAVE_TERMIO */
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);
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 *)&ltc_inferior)[i]);
printf ("\n");
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#endif /* not HAVE_TERMIO */
#ifdef TIOCLGET
printf ("lmode: %x\n", lmode_inferior);
#endif
}
static void
@ -304,11 +326,7 @@ new_tty (ttyname)
register int tty;
register int fd;
#if 0
/* I think it is better not to do this. Then C-z on the GDB terminal
will still stop the program, while C-z on the data terminal
will be input. */
#ifdef TIOCNOTTY
/* Disconnect the child process from our controlling terminal. */
tty = open("/dev/tty", O_RDWR);
if (tty > 0)
@ -317,6 +335,7 @@ new_tty (ttyname)
close(tty);
}
#endif
/* Now open the specified new terminal. */
tty = open(ttyname, O_RDWR);
@ -361,19 +380,29 @@ create_inferior (allargs, env)
/* exec is said to fail if the executable is open. */
close_exec_file ();
pid = vfork ();
pid = fork ();
if (pid < 0)
perror_with_name ("vfork");
perror_with_name ("fork");
if (pid == 0)
{
char *args[4];
#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);
@ -383,14 +412,8 @@ create_inferior (allargs, env)
/*??? signal (SIGQUIT, SIG_DFL);
signal (SIGINT, SIG_DFL); */
ptrace (0);
args[0] = "sh";
args[1] = "-c";
args[2] = shell_command;
args[3] = 0;
execve (SHELL_FILE, args, env);
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");
@ -414,538 +437,17 @@ kill_command ()
kill_inferior ();
}
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);
}
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 (read_register (FP_REGNUM));
}
/* 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
{
#ifdef NO_SINGLE_STEP
if (step)
{
single_step (signal);
}
else ptrace (7, inferior_pid, 1, signal);
#else
ptrace (step ? 9 : 7, inferior_pid, 1, signal);
#endif
if (errno)
perror_with_name ("ptrace");
}
}
#ifdef ATTACH_DETACH
/* Start debugging the process whose number is PID. */
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 */
#ifdef NEW_SUN_PTRACE
void
fetch_inferior_registers ()
{
struct regs inferior_registers;
struct fp_status inferior_fp_registers;
extern char registers[];
if (remote_debugging)
remote_fetch_registers (registers);
else
{
ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
#if defined(sun2) || defined(sun3)
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fps_regs);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
bcopy (&inferior_fp_registers.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
#endif
#if defined(sun4)
registers[REGISTER_BYTE (0)] = 0;
bcopy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (1)], 15 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fpu_fr);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
*(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
*(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
/* *(int *)&registers[REGISTER_BYTE (RP_REGNUM)] =
inferior_registers.r_o7 + 8;
bcopy (&inferior_fp_registers.Fpu_fsr,
&registers[REGISTER_BYTE (FPS_REGNUM)],
sizeof (FPU_FSR_TYPE)); */
read_inferior_memory (inferior_registers.r_sp,
&registers[REGISTER_BYTE (16)],
16*4);
#endif
}
}
/* 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;
{
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 defined(sun2) || defined(sun3)
if (in_regs)
{
bcopy (registers, &inferior_registers, 16 * 4);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
}
if (in_fpregs)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
}
if (in_regs)
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
if (in_fpregs)
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
#endif
#if defined(sun4)
if (regno >= 0)
if (FP0_REGNUM <= regno && regno <= FP0_REGNUM + 32)
in_regs = 0;
else
in_fpregs = 0;
if (in_regs)
{
bcopy (&registers[REGISTER_BYTE (1)], &inferior_registers.r_g1, 15 * 4);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
inferior_registers.r_npc = *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
inferior_registers.r_y = *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
write_inferior_memory (*(int *)&registers[REGISTER_BYTE (SP_REGNUM)],
&registers[REGISTER_BYTE (16)],
16*4);
}
if (in_fpregs)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fpu_fr);
/* bcopy (&registers[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);
#endif
}
}
#else
#ifdef HP9K320
#define FP_REGISTER_ADDR_DIFF(u, regno) \
(((char *) (FP_REGISTER_ADDR (u, regno))) - ((char *) &(u)))
#define INFERIOR_AR0(u) \
((ptrace \
(PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
- KERNEL_U_ADDR)
static void
fetch_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
{
#ifndef HPUX_VERSION_5
if (regno == PS_REGNUM)
{
union { int i; short s[2]; } ps_val;
int regval;
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
regval = ps_val.s[0];
supply_register (regno, &regval);
}
else
#endif /* not HPUX_VERSION_5 */
{
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
return;
}
static void
store_inferior_register_1 (regno, regaddr, value)
int regno;
unsigned int regaddr;
int value;
{
errno = 0;
ptrace (PT_WUAREA, inferior_pid, regaddr, value);
#if 0
/* HP-UX randomly sets errno to non-zero for regno == 25.
However, the value is correctly written, so ignore errno. */
if (errno != 0)
{
char string_buf[64];
sprintf (string_buf, "writing register number %d", regno);
perror_with_name (string_buf);
}
#endif
return;
}
static void
store_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
{
#ifndef HPUX_VERSION_5
if (regno == PS_REGNUM)
{
union { int i; short s[2]; } ps_val;
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
ps_val.s[0] = (read_register (regno));
store_inferior_register_1 (regno, regaddr, ps_val.i);
}
else
#endif /* not HPUX_VERSION_5 */
{
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
extern char registers[];
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
store_inferior_register_1
(regno, regaddr,
(*(int *) &registers[(REGISTER_BYTE (regno)) + i]));
regaddr += sizeof (int);
}
}
return;
}
void
fetch_inferior_registers ()
{
struct user u;
register int regno;
register unsigned int ar0_offset;
ar0_offset = (INFERIOR_AR0 (u));
for (regno = 0; (regno < FP0_REGNUM); regno++)
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
fetch_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
}
/* 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)
register int regno;
{
struct user u;
register unsigned int ar0_offset;
if (regno >= FP0_REGNUM)
{
store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
return;
}
ar0_offset = (INFERIOR_AR0 (u));
if (regno >= 0)
{
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
return;
}
for (regno = 0; (regno < FP0_REGNUM); regno++)
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
return;
}
#else /* not HP9K320 */
void
fetch_inferior_registers ()
{
register int regno;
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
#ifdef UMAX_PTRACE
unsigned int offset = 0;
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
#endif
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];
extern char registers[];
int i;
#ifdef UMAX_PTRACE
unsigned int offset = 0;
#else
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
#endif
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (6, inferior_pid, regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i]);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
else for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (6, inferior_pid, regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i]);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
}
#endif /* not HP9K320 */
#endif /* not NEW_SUN_PTRACE */
/* 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. */
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));
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
{
if (remote_debugging)
buffer[i] = remote_fetch_word (addr);
else
buffer[i] = ptrace (1, inferior_pid, addr, 0);
}
/* Copy appropriate bytes out of the buffer. */
bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
}
/* 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;
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
}
static void
@ -962,8 +464,8 @@ try_writing_regs_command ()
{
QUIT;
errno = 0;
value = ptrace (3, inferior_pid, i, 0);
ptrace (6, inferior_pid, i, value);
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",
@ -974,8 +476,8 @@ try_writing_regs_command ()
}
}
static
initialize ()
void
_initialize_inflow ()
{
add_com ("term-status", class_obscure, term_status_command,
"Print info on inferior's saved terminal status.");
@ -992,11 +494,15 @@ Report which ones can be written.");
ioctl (0, TIOCGETP, &sg_ours);
fcntl (0, F_GETFL, tflags_ours);
#ifdef TIOCGLTC
#ifdef TIOCGETC
ioctl (0, TIOCGETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_ours);
#endif /* TIOCGLTC */
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCGPGRP, &pgrp_ours);
@ -1005,4 +511,3 @@ Report which ones can be written.");
terminal_is_ours = 1;
}
END_FILE

File diff suppressed because it is too large Load Diff

View File

@ -1,134 +0,0 @@
/* Macros to enable automatic execution of an initialization function
in each object file without having to include a list of all object files
anywhere in the source code. This goes with firstfile.c and lastfile.c.
Copyright (C) 1986 Free Software Foundation, Inc.
NO WARRANTY
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "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 PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, 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 ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1986 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file 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:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program 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).
c) 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.
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.
3. You may copy and distribute this program (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:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) 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,
c) 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.)
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.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program 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.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. 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 of our free software and of promoting the sharing and reuse of
software.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
/* Here a machine-specific header file must be included to define
the macro FILEADDR_ROUND which we use to round up from the address
of the end of one object file's text to the start of the next
object file's text. */
#include "m-init.h"
/* This is used to make a file's initialization function.
It calls another function named `initialize', which must
appear later in the file. */
#define START_FILE \
static initialize (), initialize_next_file (); \
static initialize_1 (offset) \
{ initialize (); initialize_next_file (offset); }
/* The argument OFFSET is the size of this function.
By adding it to the address of this function,
we find the next function, which is the next file's
initialization function. */
#define END_FILE \
static initialize_next_file (offset) \
int offset; \
{ long addr = FILEADDR_ROUND ((int) initialize_next_file + offset); \
(*(void (*) ()) addr) (offset); }

View File

@ -1,6 +0,0 @@
/* This ends the chain of files for the purpose of initialization,
because it does not attempt to find the start of the following file. */
initialize_last_file ()
{
}

View File

@ -1,5 +1,5 @@
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
/* 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
@ -18,32 +18,36 @@ 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!
*/
/*
* Configuration file for HP9000/300 series machine running
* University of Utah's 4.3bsd port. This is NOT for HP-UX.
* Problems to hpbsd-bugs@cs.utah.edu
*/
#ifndef hp300
#define hp300
#ifndef aux
#define aux
#endif
/* Watch out for NaNs */
/* It's a USG system */
#define USG
#define IEEE_FLOAT
/* Assembler instructions in USG "SGS" (sw generation system) format */
#define USG_SGS_ASM
/* Get rid of any system-imposed stack limit if possible. */
/* Debugger information will be in COFF format. */
#define COFF_FORMAT
#define COFF_NO_LONG_FILE_NAMES
#define SET_STACK_LIMIT_HUGE
/* Terminal interface via termio */
#define HAVE_TERMIO
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
/* Unisoft fucked up the include files */
#define UNISOFT_ASSHOLES
#define NAMES_HAVE_UNDERSCORE
/* 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
/* Debugger information will be in DBX format. */
#define READ_DBX_FORMAT
/* Floating point is IEEE compatible */
#define IEEE_FLOAT
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -69,36 +73,40 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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. */
#define KERNEL_U_ADDR 0x00917000
/* Address of end of stack space. */
#define STACK_END_ADDR 0xFFF00000
#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, 0x42}
#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
#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) 0 /* Just a first guess; not checked */
#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. */
@ -113,7 +121,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"ps", "pc", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr" }
@ -131,11 +139,31 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define PC_REGNUM 17 /* Contains program counter */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
#define FPS_REGNUM 27 /* 68881 status 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+12)
#define REGISTER_BYTES (16*4+8*12+8+20)
/* Index within `registers' of the first byte of the space for
register N. */
@ -148,6 +176,8 @@ read_memory_integer (read_register (SP_REGNUM), 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)
@ -194,6 +224,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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. */
@ -213,37 +249,6 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Compensate for lack of `vprintf' function. */
#define vprintf(format, ap) _doprnt (format, ap, stdout)
/* 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) \
{ \
if (regno < PS_REGNUM) \
addr = (int) &((struct frame *)(blockend))->f_regs[regno]; \
else if (regno == PS_REGNUM) \
addr = (int) &((struct frame *)(blockend))->f_stackadj; \
else if (regno == PC_REGNUM) \
addr = (int) &((struct frame *)(blockend))->f_pc; \
else if (regno < FPC_REGNUM) \
addr = (int) \
&((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\
else if (regno == FPC_REGNUM) \
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr; \
else if (regno == FPS_REGNUM) \
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr; \
else \
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar; \
}
/* 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). */
@ -258,23 +263,23 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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
/* 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, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_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. */
@ -285,7 +290,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
{ 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 */ \
@ -315,19 +320,19 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; }\
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); \
{ 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; \
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; \
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) \
@ -354,7 +359,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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)) \
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. */ \
@ -371,9 +376,9 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; \
(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. */
@ -399,13 +404,15 @@ read_memory_integer (read_register (SP_REGNUM), 4)
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
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); \
@ -418,7 +425,9 @@ read_memory_integer (read_register (SP_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); \
set_current_frame (read_register (FP_REGNUM)); }
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)
@ -431,7 +440,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp
trap #2
trap #15
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the
@ -442,7 +451,7 @@ 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, 0x4e424e71}
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY_LENGTH 28
@ -451,7 +460,7 @@ taken for the arguments. */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

View File

@ -25,15 +25,18 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* Set flag to indicate whether HP's assembler is in use. */
#ifdef __GNU__
#ifdef __HPUX_ASM__
#define HPUX_ASM
#define USG_SGS_ASM
#endif
#else
#define HPUX_ASM
#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. */
@ -108,6 +111,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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
@ -201,6 +210,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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. */
@ -228,9 +243,11 @@ read_memory_integer (read_register (SP_REGNUM), 4)
: (&((struct exception_stack *) (u_ar0))->e_PC)))
#define FP_REGISTER_ADDR(u, regno) \
(((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 *) \
(((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. */
@ -253,20 +270,20 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* 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, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_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. */
@ -277,7 +294,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
{ 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 */ \
@ -307,19 +324,19 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; }\
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); \
{ 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; \
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; \
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) \
@ -363,9 +380,9 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; \
(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. */
@ -391,13 +408,15 @@ read_memory_integer (read_register (SP_REGNUM), 4)
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
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); \
@ -410,7 +429,9 @@ read_memory_integer (read_register (SP_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); \
set_current_frame (read_register (FP_REGNUM)); }
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)
@ -443,7 +464,7 @@ taken for the arguments. */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

394
gdb/m-i386.h Normal file
View File

@ -0,0 +1,394 @@
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*/
/*
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 i386
#define i386
#endif
/* define USG if you are using sys5 /usr/include's */
#define USG
/* USG systems need these */
#define vfork() fork()
#define MAXPATHLEN 500
/* define this if you don't have the extension to coff that allows
* file names to appear in the string table
* (aux.x_file.x_foff)
*/
#define COFF_NO_LONG_FILE_NAMES
/* turn this on when rest of gdb is ready */
/* #define IEEE_FLOAT */
#define NBPG NBPC
#define UPAGES USIZE
#define HAVE_TERMIO
/* Get rid of any system-imposed stack limit if possible. */
/* #define SET_STACK_LIMIT_HUGE not in sys5 */
/* 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 */
/* Specify debugger information format. */
/* #define READ_DBX_FORMAT */
#define COFF_FORMAT
/* number of traps that happen between exec'ing the shell
* to run an inferior, and when we finally get to
* the inferior code. This is 2 on most implementations.
*/
#define START_INFERIOR_TRAPS_EXPECTED 4
/* 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(frompc) {(frompc) = i386_skip_prologue((frompc));}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
(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. */
#define KERNEL_U_ADDR 0xe0000000
/* Address of end of stack space. */
#define STACK_END_ADDR 0x80000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0xcc}
/* 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 1
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
/* Return 1 if P points to an invalid floating point value.
LEN is the length in bytes -- not relevant on the 386. */
#define INVALID_FLOAT(p, len) (0)
/* code to execute to print interesting information about the
* floating point processor (if any)
* No need to define if there is nothing to do.
*/
#define FLOAT_INFO { i386_float_info (); }
/* 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 16
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
/* the order of the first 8 registers must match the compiler's
* numbering scheme (which is the same as the 386 scheme)
* also, this table must match regmap in i386-pinsn.c.
*/
#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
"esp", "ebp", "esi", "edi", \
"eip", "ps", "cs", "ss", \
"ds", "es", "fs", "gs", \
}
/* 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 5 /* Contains address of executing stack frame */
#define SP_REGNUM 4 /* Contains address of top of stack */
#define PC_REGNUM 8
#define PS_REGNUM 9
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = i386_register_u_addr ((blockend),(regno));
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 4)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N)*4)
/* Number of bytes of storage in the actual machine representation
for register N. */
#define REGISTER_RAW_SIZE(N) (4)
/* Number of bytes of storage in the program's representation
for register N. */
#define REGISTER_VIRTUAL_SIZE(N) (4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 4
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 4
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (0)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 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) (builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ (SP) -= sizeof (ADDR); \
write_memory ((SP), &(ADDR), sizeof (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. */
#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)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
/* on the 386, the instruction following the call could be:
* popl %ecx - one arg
* addl $imm, %esp - imm/4 args; imm may be 8 or 32 bits
* anything else - zero args
*/
#define FRAME_NUM_ARGS(numargs, fi) { \
int retpc; \
unsigned char op; \
struct frame_info *pfi; \
pfi = get_prev_frame_info ((fi)); \
retpc = pfi->pc; \
numargs = 0; \
op = read_memory_integer (retpc, 1); \
if (op == 0x59) \
/* pop %ecx */ \
(numargs) = 1; \
else if (op == 0x83) { \
op = read_memory_integer (retpc+1, 1); \
if (op == 0xc4) \
/* addl $<signed imm 8 bits>, %esp */ \
(numargs) = (read_memory_integer (retpc+2,1)&0xff)/4;\
} else if (op == 0x81) { /* add with 32 bit immediate */\
op = read_memory_integer (retpc+1, 1); \
if (op == 0xc4) \
/* addl $<imm 32>, %esp */ \
(numargs) = read_memory_integer (retpc+2, 4) / 4;\
} \
}
/* 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) \
{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME { i386_pop_frame (); }
/* this is
* call 11223344 (32 bit relative)
* int3
*/
#define CALL_DUMMY { 0x223344e8, 0xcc11 }
#define CALL_DUMMY_LENGTH 8
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ \
int from, to, delta, loc; \
loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
from = loc + 5; \
to = (int)(fun); \
delta = to - from; \
*(int *)((char *)(dummyname) + 1) = delta; \
}
#if 0
/* 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, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0}
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) {}
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR {}
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR {}
/* 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 {}
/* 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 {}
#endif

37
gdb/m-i386gas.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*
* i386gnu: COFF_ENCAPSULATE
*/
/*
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!
*/
#define COFF_ENCAPSULATE
#include "m-i386.h"
#define NAMES_HAVE_UNDERSCORE
#undef COFF_FORMAT
#define READ_DBX_FORMAT

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) ((addr + 7) & -8)

549
gdb/m-isi.h Normal file
View File

@ -0,0 +1,549 @@
/*
Date: Thu, 2 Apr 87 00:02:42 EST
From: crl@maxwell.physics.purdue.edu (Charles R. LaBrec)
Message-Id: <8704020502.AA01744@maxwell.physics.purdue.edu>
To: bug-gdb@prep.ai.mit.edu
Subject: gdb for ISI Optimum V
Here is an m-isi-ov.h file for gdb version 2.1. It supports the 68881
registers, and tracks down the function prologue (since the ISI cc
puts it at the end of the function and branches to it if not
optimizing). Also included are diffs to core.c, findvar.c, and
inflow.c, since the original code assumed that registers are an int in
the user struct, which isn't the case for 68020's with 68881's (and
not using the NEW_SUN_PTRACE). I have not fixed the bugs associated
with the other direction (writing registers back to the user struct).
I have also included a diff that turns m68k-pinsn.c into isi-pinsn.c,
which is needed since the 3.05 release of as does not understand
floating point ops, and it compiles incorrectly under "cc -20"
I have used gdb for a while now, and it seems to work relatively well,
but I do not guarantee that it is perfect. The more that use it, the
faster the bugs will get shaken out. One bug I know of is not in gdb,
but in the assembler. It seems to screw up the .stabs of variables.
For externs, this is not important since gdb uses the global symbol
value, but for statics, this makes gdb unable to find them. I am
currently trying to track it down.
As an aside, I notice that only global functions are used as symbols
to print as relative addresses, i.e. "<function + offset>", and not
static functions, which end up printing as large offsets from the last
global one. Would there be a problem if static functions were also
recorded as misc functions in read_dbx_symtab?
Charles LaBrec
crl @ maxwell.physics.purdue.edu
Definitions to make GDB run on a ISI Optimum V (3.05) under 4.2bsd.
Copyright (C) 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!
*/
/* Identify this machine */
#ifndef ISI68K
#define ISI68K
#endif
/* 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 */ \
else if (op == 0060000) \
pc += 4; /* Skip bra #word */ \
else if (op == 00600377) \
pc += 6; /* skip bra #long */ \
else if ((op & 0177400) == 0060000) \
pc += 2; /* skip bra #char */ \
}
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
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. */
#define KERNEL_U_ADDR 0x10800000
/* Address of end of stack space. */
#define STACK_END_ADDR 0x10000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x4e, 0x4f}
/* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
#define DATAROUND 0x20000
#define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
(hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
/* Text segment starts at sizeof (struct exec) in {N,Z}MAGIC files */
#define N_TXTADDR(hdr) (hdr.a_magic != OMAGIC ? sizeof (struct exec) : 0)
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always.
On the ISI, the kernel resets the pc to the trap instr */
#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. */
#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 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 */
#ifdef BSD43_ISI40D
#define BLOCKFUDGE 0x400000
#else
#define BLOCKFUDGE 0
#endif
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ blockend -= BLOCKFUDGE; \
if (regno < 2) addr = blockend - 0x18 + regno * 4; \
else if (regno < 8) addr = blockend - 0x54 + regno * 4; \
else if (regno < 10) addr = blockend - 0x30 + regno * 4;\
else if (regno < 15) addr = blockend - 0x5c + regno * 4;\
else if (regno < 16) addr = blockend - 0x1c; \
else if (regno < 18) addr = blockend - 0x44 + regno * 4;\
else if (regno < 26) addr = (int) ((struct user *)0)->u_68881_regs \
+ (regno - 18) * 12; \
else if (regno < 29) addr = (int) ((struct user *)0)->u_68881_regs \
+ 8 * 12 + (regno - 26) * 4; \
}
/* 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. */
#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 ISI, 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)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#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; }
/* 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; \
register int insn; \
register int offset; \
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, \
or a branch followed by a link a6 instruction; \
if not we lose. If we win, find the address above the saved \
regs using the amount of storage from the link instruction. */\
retry: \
insn = read_memory_integer (pc, 2); \
if (insn == 044016) \
next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \
else if (insn == 047126) \
next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \
else if ((insn & 0177400) == 060000) /* bra insn */ \
{ offset = insn & 0377; \
pc += 2; /* advance past bra */ \
if (offset == 0) /* bra #word */ \
offset = read_memory_integer (pc, 2), pc += 2; \
else if (offset == 0377) /* bra #long */ \
offset = read_memory_integer (pc, 4), pc += 4; \
pc += offset; \
goto retry; \
} 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) */ \
insn = read_memory_integer (pc, 2), pc += 2; \
regmask = read_memory_integer (pc, 2); \
if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \
(frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \
else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \
(frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \
else if (insn == 0044327) /* moveml mask, (sp) */ \
{ pc += 2; \
/* Regmask's low bit is for register 0, the first written */ \
next_addr -= 4; \
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 4); \
} else if (insn == 0044347) /* moveml mask, -(sp) */ \
{ pc += 2; \
/* 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); } \
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
if (read_memory_integer (pc, 2) == 041147 \
&& read_memory_integer (pc+2, 2) == 042347) \
(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; \
}
/* Compensate for lack of `vprintf' function. */
#define vprintf(format, ap) _doprnt (format, ap, stdout)
/* 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 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 #<f0-f7>,-(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 24 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 ("movl $ 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"); }

View File

@ -1,11 +0,0 @@
/* Customize initialize.h for Integrated Solutions machines. */
/* Define this if you are using system version 4; undefine it for
version 3. This alters the action of m-isi-ov.h as well as this file. */
#define BSD43_ISI40D
#ifdef BSD43_ISI40D
#define FILEADDR_ROUND(addr) (addr)
#else
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
#endif

View File

@ -94,6 +94,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define NS32K_SVC_IMMED_OPERANDS
/* 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
@ -216,6 +222,14 @@ anyone else from sharing it farther. Help stamp out software hoarding!
: 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.
On this machine this is a no-op, as gcc doesn't run on it yet.
This calling convention is not used. */
#define STORE_STRUCT_RETURN(ADDR, SP)
/* 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. */
@ -251,21 +265,21 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* In the case of the Merlin, the frame's nominal address is the FP value,
and at that address is saved previous FP value as a 4-byte word. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
/* compute base of arguments */
#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
@ -276,7 +290,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
int addr_mode; \
int width; \
\
pc = FRAME_SAVED_PC (fi.frame,0); \
pc = FRAME_SAVED_PC (fi); \
insn = read_memory_integer (pc,2); \
addr_mode = (insn >> 11) & 0x1f; \
insn = insn & 0x7ff; \
@ -311,17 +325,17 @@ anyone else from sharing it farther. Help stamp out software hoarding!
CORE_ADDR enter_addr; \
CORE_ADDR next_addr; \
\
enter_addr = get_pc_function_start ((frame_info).pc); \
enter_addr = get_pc_function_start ((frame_info)->pc); \
regmask = read_memory_integer (enter_addr+1, 1); \
localcount = ns32k_localcount (enter_addr); \
next_addr = (frame_info).frame + localcount; \
next_addr = (frame_info)->frame + localcount; \
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
(frame_saved_regs).regs[regnum] \
= (regmask & 1) ? (next_addr -= 4) : 0; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
(frame_saved_regs).regs[FP_REGNUM] \
= read_memory_integer ((frame_info).frame, 4); }
= read_memory_integer ((frame_info)->frame, 4); }
/* Compensate for lack of `vprintf' function. */
#define vprintf(format, ap) _doprnt (format, ap, stdout)
@ -344,18 +358,23 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
struct frame_info *fi; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = 0; regnum < 8; regnum++) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[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
@ -375,7 +394,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ int flipped = fun | 0xc0000000; \
flip_bytes (&flipped, 4); \
*((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \

View File

@ -1,14 +1,17 @@
/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
Probably ths parameters is match as news800, news700 and news900.
Here is an m-news800.h file for gdb version 2.1. It supports the reading
the 68881 registers, but the kernel doesn't know how to write them
and probably cannot write the frame pointer register either.
Here is an m-news800.h file for gdb version 2.6. It supports the 68881
registers.
Now(9/2 '87) NEWS's printf has a bug.
And support Sun assembly format instead of Motorola one.
Probably not well support floating registers from core file rarely that
(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs@uunet.uu.net
and now hikichi@wheaties.ai.mit.edu)
* Now(9/2 '87) NEWS's printf has a bug.
* And support Sun assembly format instead of Motorola one.
* Probably not well support floating registers from core file rarely that
I do not know detail.
(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs%seismo.CSS.GOV)
* Ptrace for handling floating register has a bug(7/3 '87), but not fixed
yet. We cannot write floating register.
Copyright (C) 1987 Free Software Foundation, Inc.
@ -34,6 +37,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define news800
#endif
/* Use GNU assembler instead of standard assembler */
#define USE_GAS
/* Motorola assembly format */
@ -41,16 +45,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define MOTOROLA
#endif
/* bug when printf special number; NAN */
#define PRINTF_BUG
/* 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 info will be in DBX format. */
/* Symbols on this machine are in DBX format. */
#define READ_DBX_FORMAT
/* Offset from address of function to start of its code.
@ -109,6 +109,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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 registers are. */
#define REGISTER_TYPE long
@ -215,27 +221,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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) \
{ if (TYPE_CODE (TYPE) != TYPE_CODE_FLT) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); \
else \
convert_from_68881 (REGBUF + REGISTER_BYTE (FP0_REGNUM), 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) \
{ if (TYPE_CODE (TYPE) != TYPE_CODE_FLT) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); \
else \
{ \
char raw_buffer[12]; \
convert_to_68881 (VALBUF, raw_buffer); \
write_register_bytes (REGISTER_BYTE(FP0_REGNUM), raw_buffer, 12); }}
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,
@ -262,26 +265,26 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the NEWS, 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, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) (fi.frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
{ 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 */ \
@ -311,12 +314,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
register int insn; \
register int offset; \
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; }\
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); \
{ pc = get_pc_function_start ((frame_info)->pc); \
/* Verify we have a link a6 instruction next, \
or a branch followed by a link a6 instruction; \
if not we lose. If we win, find the address above the saved \
@ -324,9 +327,9 @@ read_memory_integer (read_register (SP_REGNUM), 4)
retry: \
insn = read_memory_integer (pc, 2); \
if (insn == 044016) \
next_addr = (frame_info).frame - read_memory_integer (pc += 2, 4), pc+=4; \
next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \
else if (insn == 047126) \
next_addr = (frame_info).frame - read_memory_integer (pc += 2, 2), pc+=2; \
next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \
else if ((insn & 0177400) == 060000) /* bra insn */ \
{ offset = insn & 0377; \
pc += 2; /* advance past bra */ \
@ -366,15 +369,15 @@ retry: \
&& read_memory_integer (pc+2, 2) == 042347) \
(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; \
(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. */
#if 0 /* now these define is not used */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
@ -393,13 +396,15 @@ retry: \
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
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); \
@ -412,8 +417,44 @@ retry: \
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 ())); }
#else /* now ptrace has a bug to write floating register */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
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 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; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
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 ())); }
#endif
/* This sequence of words is the instructions
fmove.m #<f0-f7>,-(sp)
movem.l 0xfffc,-(sp)
@ -445,7 +486,7 @@ taken for the arguments. */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

View File

@ -1,4 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a SONY NEWS. */
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

View File

@ -17,8 +17,8 @@ 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! */
/* Read file headers properly in core.c */
#define gould
/* This code appears in libraries on Gould machines. Ignore it. */
#define IGNORE_SYMBOL(type) (type == N_ENTRY)
/* Macro for text-offset and data info (in NPL a.out format). */
#define TEXTINFO \
@ -169,7 +169,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
the new frame is not set up until the new function executes
some instructions. True on NPL! Return address is in R1.
The true return address is REALLY 4 past that location! */
#define SAVED_PC_AFTER_CALL(frame) \
`#define SAVED_PC_AFTER_CALL(frame) \
(read_register(R1_REGNUM) + 4)
/* Address of U in kernel space */
@ -195,6 +195,12 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
@ -296,6 +302,14 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) (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.
On this machine this is a no-op, because gcc isn't used on it
yet. So this calling convention is not used. */
#define STORE_STRUCT_RETURN(ADDR, SP)
/* Extract from an arrary REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
@ -335,21 +349,21 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
#define FRAME_CHAIN(thisframe) (findframe(thisframe))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && chain != thisframe)
(chain != 0 && chain != (thisframe)->frame)
#define FRAME_CHAIN_COMBINE(chain, thisframe) \
(chain)
/* Define other aspects of the stack frame on NPL. */
#define FRAME_SAVED_PC(frame,ignore) \
(read_memory_integer (frame + 8, 4))
#define FRAME_SAVED_PC(FRAME) \
(read_memory_integer ((FRAME)->frame + 8, 4))
#define FRAME_ARGS_ADDRESS(fi) \
((fi).next_frame ? \
read_memory_integer ((fi).frame + 12, 4) : \
((fi)->next_frame ? \
read_memory_integer ((fi)->frame + 12, 4) : \
read_register (AP_REGNUM))
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame + 80)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame + 80)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
@ -370,11 +384,11 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 8; \
(frame_saved_regs).regs[R4_REGNUM] = (frame_info).frame + 0x30; \
(frame_saved_regs).regs[R5_REGNUM] = (frame_info).frame + 0x34; \
(frame_saved_regs).regs[R6_REGNUM] = (frame_info).frame + 0x38; \
(frame_saved_regs).regs[R7_REGNUM] = (frame_info).frame + 0x3C; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \
(frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \
(frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \
(frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \
(frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \
}
/* Things needed for making the inferior call functions. */
@ -396,12 +410,14 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
struct frame_info *fi; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
@ -410,7 +426,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
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); \
set_current_frame (read_register (FP_REGNUM)); }
flush_cached_frames (); \
set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
read_pc ())); }
/* This sequence of words is the instructions:
halt
@ -443,7 +461,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

View File

@ -1,4 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a NP1. See np1-pinsn.c for rounding function. */
#define FILEADDR_ROUND(addr) (((int)(addr) + 31) & ~0xf)

View File

@ -17,8 +17,8 @@ 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! */
/* Read file headers properly in core.c */
#define gould
/* This code appears in libraries on Gould machines. Ignore it. */
#define IGNORE_SYMBOL(type) (type == N_ENTRY)
/* Macro for text-offset and data info (in PN a.out format). */
#define TEXTINFO \
@ -195,6 +195,12 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
@ -280,6 +286,14 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) (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.
On this machine this is a no-op, because gcc isn't used on it
yet. So this calling convention is not used. */
#define STORE_STRUCT_RETURN(ADDR, SP)
/* Extract from an arrary REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
@ -319,21 +333,21 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
#define FRAME_CHAIN(thisframe) (findframe(thisframe))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && chain != thisframe)
(chain != 0 && chain != (thisframe)->frame)
#define FRAME_CHAIN_COMBINE(chain, thisframe) \
(chain)
/* Define other aspects of the stack frame on NPL. */
#define FRAME_SAVED_PC(frame,ignore) \
(read_memory_integer (frame + 8, 4))
#define FRAME_SAVED_PC(frame) \
(read_memory_integer ((frame)->frame + 8, 4))
#define FRAME_ARGS_ADDRESS(fi) \
((fi).next_frame ? \
read_memory_integer ((fi).frame + 12, 4) : \
((fi)->next_frame ? \
read_memory_integer ((fi)->frame + 12, 4) : \
read_register (AP_REGNUM))
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame + 80)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame + 80)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
@ -354,11 +368,11 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 8; \
(frame_saved_regs).regs[R4_REGNUM] = (frame_info).frame + 0x30; \
(frame_saved_regs).regs[R5_REGNUM] = (frame_info).frame + 0x34; \
(frame_saved_regs).regs[R6_REGNUM] = (frame_info).frame + 0x38; \
(frame_saved_regs).regs[R7_REGNUM] = (frame_info).frame + 0x3C; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \
(frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \
(frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \
(frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \
(frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \
}
/* Things needed for making the inferior call functions. */
@ -380,12 +394,14 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
struct frame_info *fi; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
@ -394,7 +410,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
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); \
set_current_frame (read_register (FP_REGNUM)); }
flush_cached_frames (); \
set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
read_pc ())); }
/* This sequence of words is the instructions:
halt
@ -427,7 +445,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

View File

@ -1,4 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a Concept. See pn-pinsn.c for rounding function. */
#define FILEADDR_ROUND(addr) (((int)(addr) + 7) & ~0x7)

View File

@ -36,6 +36,17 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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. */
@ -56,13 +67,14 @@ anyone else from sharing it farther. Help stamp out software hoarding!
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 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 0xf000000
#define STACK_END_ADDR 0xf8000000
/* Stack grows downward. */
@ -93,6 +105,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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
@ -146,6 +164,19 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* ?? */
#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. */
@ -189,14 +220,21 @@ anyone else from sharing it farther. Help stamp out software hoarding!
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : builtin_type_int)
((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))
bcopy (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
@ -208,7 +246,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
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))
#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. */
@ -227,9 +266,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define READ_GDB_SYMSEGS
/* The SPARC processor has register windows. */
#define HAVE_REGISTER_WINDOWS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@ -253,26 +289,56 @@ anyone else from sharing it farther. Help stamp out software hoarding!
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. */
%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, rw_in[6])
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, 0) >= first_object_file_end))
(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. */
#define FRAME_SAVED_PC(frame, next_frame) frame_saved_pc (frame, next_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_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_STRUCT_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_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. */
@ -291,101 +357,216 @@ anyone else from sharing it farther. Help stamp out software hoarding!
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) \
#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \
{ register int regnum; \
register CORE_ADDR pc; \
FRAME frame = (fi).frame; \
FRAME next_frame = (fi).next_frame; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((fi).pc >= frame - CALL_DUMMY_LENGTH - 0x140 \
&& (fi).pc <= frame) \
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 = 0; regnum < 32; regnum++) \
(frame_saved_regs).regs[regnum+FP0_REGNUM] = frame + regnum * 4 - 0x80;\
for (regnum = 1; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum] = frame + regnum * 4 - 0xa0; \
for (regnum = 0; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum+24] = frame + regnum * 4 - 0xc0; \
for (regnum = 0; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum+64] = frame + regnum * 4 - 0xe0; \
frame = (fi).next_frame ? \
(fi).next_frame : read_register (SP_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 \
{ \
for (regnum = 0; regnum < 16; regnum++) \
(frame_saved_regs).regs[regnum+16] = frame + regnum * 4; \
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 (next_frame == 0) next_frame = read_register (SP_REGNUM); \
for (regnum = 0; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum+8] = next_frame + regnum * 4; \
(frame_saved_regs).regs[FP_REGNUM] = frame + 14*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 will probably have to restore the
/* 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); \
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, &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * 4); \
write_memory (fp - 0x80, &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\
write_memory (fp - 0xa0, &registers[REGISTER_BYTE (0)], 8 * 4); \
write_memory (fp - 0xc0, &registers[REGISTER_BYTE (24)], 8 * 4); \
write_memory (fp - 0xc0, &registers[REGISTER_BYTE (24)], 7 * 4); \
write_memory (fp - 0xa4, &rp, 4); \
write_memory (fp - 0xe0, &registers[REGISTER_BYTE (64)], 8 * 4); \
}
/* Discard from the stack the innermost frame,
restoring all saved registers. */
/* 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 CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
char raw_buffer_fp[REGISTER_BYTES]; \
char raw_buffer_globals[REGISTER_BYTES]; \
char raw_buffer_outs[REGISTER_BYTES]; \
char raw_buffer_xx[REGISTER_BYTES]; \
void do_restore_insn (); \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
if (fsr.regs[FP0_REGNUM]) \
read_memory (fsr.regs[FP0_REGNUM], raw_buffer_fp, 32 * 4); \
if (fsr.regs[1]) \
read_memory (fsr.regs[1], raw_buffer_globals, 7 * 4); \
if (fsr.regs[24]) \
read_memory (fsr.regs[24], raw_buffer_outs, 8 * 4); \
if (fsr.regs[64]) \
read_memory (fsr.regs[64], raw_buffer_xx, 8 * 4); \
do_restore_insn (fsr.regs); \
if (fsr.regs[FP0_REGNUM]) \
write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer_fp, 32 * 4); \
if (fsr.regs[1]) \
write_register_bytes (REGISTER_BYTE (1), raw_buffer_globals, 7 * 4);\
if (fsr.regs[24]) \
write_register_bytes (REGISTER_BYTE (8), raw_buffer_outs, 8 * 4); \
if (fsr.regs[64]) \
write_register_bytes (REGISTER_BYTE (64), raw_buffer_xx, 8 * 4); \
set_current_frame (read_register (FP_REGNUM)); \
}
{ 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
@ -429,15 +610,15 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/..* 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 call instruction. *../
The CALL_DUMMY_START_OFFSET gives the position of
the following ld instruction. *../
ld [%sp+0x58],%o5
ld [%sp+0x44],%o4
ld [%sp+0x54],%o4
ld [%sp+0x50],%o3
ld [%sp+0x4c],%o2
ld [%sp+0x48],%o1
call 0x34343434
call 0x00000000
ld [%sp+0x44],%o0
nop
ta 1
@ -466,7 +647,7 @@ arguments. */
0xf03fbf40, 0x01000000, 0x01000000, 0x01000000, \
0x01000000, 0x91580000, 0xd027bf50, 0x93500000, \
0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000, \
0xd027bf44, 0xda03a058, 0xd803a044, 0xd603a050, \
0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050, \
0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044, \
0x01000000, 0x91d02001, 0x01000000, 0x01000000}
@ -482,12 +663,29 @@ arguments. */
#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) \
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. */

View File

@ -86,6 +86,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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 registers are. */
#define REGISTER_TYPE long
@ -162,6 +168,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define REGISTER_VIRTUAL_TYPE(N) 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. */
@ -181,6 +193,18 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* 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
/* 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
@ -205,20 +229,20 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* 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, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_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. */
@ -229,7 +253,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
{ 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 */ \
@ -258,19 +282,19 @@ read_memory_integer (read_register (SP_REGNUM), 4)
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 \
&& (frame_info).pc <= (frame_info).frame) \
{ next_addr = (frame_info).frame; \
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4; }\
if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 \
&& (frame_info)->pc <= (frame_info)->frame) \
{ next_addr = (frame_info)->frame; \
pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4; }\
else \
{ pc = get_pc_function_start ((frame_info).pc); \
{ 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; \
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; \
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) \
@ -295,9 +319,9 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; \
(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. */
@ -318,12 +342,14 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
struct frame_info *fi; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
@ -332,7 +358,9 @@ read_memory_integer (read_register (SP_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
moveml 0xfffc,-(sp)
@ -364,7 +392,7 @@ taken for the arguments. */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 16) = nargs * 4; \
*(int *)((char *) dummyname + 10) = fun; }

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) (addr)

2
gdb/m-sun2os4.h Normal file
View File

@ -0,0 +1,2 @@
#include "m-sun2.h"
#define SUNOS4

View File

@ -85,6 +85,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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
@ -132,6 +138,8 @@ read_memory_integer (read_register (SP_REGNUM), 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)
@ -178,6 +186,12 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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. */
@ -230,20 +244,20 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* 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, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_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. */
@ -254,7 +268,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
{ 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 */ \
@ -284,19 +298,19 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; }\
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); \
{ 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; \
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; \
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) \
@ -323,7 +337,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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)) \
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. */ \
@ -340,9 +354,9 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; \
(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. */
@ -368,13 +382,15 @@ read_memory_integer (read_register (SP_REGNUM), 4)
restoring all saved registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
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); \
@ -387,7 +403,9 @@ read_memory_integer (read_register (SP_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); \
set_current_frame (read_register (FP_REGNUM)); }
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)
@ -420,7 +438,7 @@ taken for the arguments. */
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

3
gdb/m-sun3os4.h Normal file
View File

@ -0,0 +1,3 @@
#include "m-sun3.h"
#define SUNOS4
#define FPU

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) ((addr + 7) & -8)

3
gdb/m-sun4os4.h Normal file
View File

@ -0,0 +1,3 @@
#include "m-sparc.h"
#define SUNOS4
#define FPU

View File

@ -1,5 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on a sun. */
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

View File

@ -103,6 +103,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
NaF (*(float *) p) : \
NaD (*(double *) p))
/* 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
@ -228,6 +234,14 @@ anyone else from sharing it farther. Help stamp out software hoarding!
builtin_type_int : \
builtin_type_double)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
On this machine this is a no-op, because gcc isn't used on it
yet. So this calling convention is not used. */
#define STORE_STRUCT_RETURN(ADDR, SP)
/* 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. */
@ -263,24 +277,24 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* In the case of the ns32000 series, the frame's nominal address is the FP
value, and at that address is saved previous FP value as a 4-byte word. */
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end))
(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,ignore) (read_memory_integer (frame + 4, 4))
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
/* Compute base of arguments. */
#define FRAME_ARGS_ADDRESS(fi) \
((ns32k_get_enter_addr (fi.pc) > 1) ? \
((fi).frame) : (read_register (SP_REGNUM) - 4))
((ns32k_get_enter_addr ((fi)->pc) > 1) ? \
((fi)->frame) : (read_register (SP_REGNUM) - 4))
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Get the address of the enter opcode for this function, if it is active.
Returns positive address > 1 if pc is between enter/exit,
@ -306,12 +320,12 @@ extern CORE_ADDR ns32k_get_enter_addr ();
int width; \
\
numargs = -1; \
enter_addr = ns32k_get_enter_addr (fi.pc); \
enter_addr = ns32k_get_enter_addr ((fi)->pc); \
if (enter_addr > 0) \
{ \
pc = (enter_addr == 1) ? \
SAVED_PC_AFTER_CALL () : \
FRAME_SAVED_PC (fi.frame,0); \
SAVED_PC_AFTER_CALL (fi) : \
FRAME_SAVED_PC (fi); \
insn = read_memory_integer (pc,2); \
addr_mode = (insn >> 11) & 0x1f; \
insn = insn & 0x7ff; \
@ -350,19 +364,19 @@ extern CORE_ADDR ns32k_get_enter_addr ();
register CORE_ADDR next_addr; \
\
bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
enter_addr = ns32k_get_enter_addr ((frame_info).pc); \
enter_addr = ns32k_get_enter_addr ((frame_info)->pc); \
if (enter_addr > 1) \
{ \
regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
localcount = ns32k_localcount (enter_addr); \
next_addr = (frame_info).frame + localcount; \
next_addr = (frame_info)->frame + localcount; \
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
(frame_saved_regs).regs[regnum] = (regmask & 1) ? \
(next_addr -= 4) : 0; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4;\
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4;\
(frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;\
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;\
(frame_saved_regs).regs[FP_REGNUM] = \
(read_memory_integer ((frame_info).frame, 4));\
(read_memory_integer ((frame_info)->frame, 4));\
} \
else if (enter_addr == 1) \
{ \
@ -393,19 +407,23 @@ extern CORE_ADDR ns32k_get_enter_addr ();
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register CORE_ADDR fp = read_register (FP_REGNUM); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info fi; \
fi = get_frame_info (fp); \
get_frame_saved_regs (&fi, &fsr); \
struct frame_info *fi; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = 0; regnum < 8; regnum++) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[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
enter 0xff,0 82 ff 00
@ -424,7 +442,7 @@ extern CORE_ADDR ns32k_get_enter_addr ();
/* 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, fun, nargs) \
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ \
int flipped; \
flipped = fun | 0xc0000000; \

View File

@ -1,4 +0,0 @@
/* This is how the size of an individual .o file's text segment
is rounded on the multimax. */
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)

Some files were not shown because too many files have changed in this diff Show More