gdb-2.8.1
This commit is contained in:
parent
3bf57d2108
commit
bb7592f010
64 changed files with 9841 additions and 5861 deletions
10
gdb/Makefile
10
gdb/Makefile
|
@ -52,11 +52,11 @@ TSSTART = /lib/crt0.o
|
|||
|
||||
NTSSTART = kdb-start.o
|
||||
|
||||
gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) $(LDFLAGS) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS)
|
||||
gdb+ : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) $(LDFLAGS) -o gdb+ $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS)
|
||||
|
||||
xgdb : $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) $(LDFLAGS) -o xgdb $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) \
|
||||
xgdb+ : $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) $(LDFLAGS) -o xgdb+ $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) \
|
||||
-lXaw -lXt -lX11 $(CLIBS)
|
||||
|
||||
kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
|
@ -89,7 +89,7 @@ main.o : main.c defs.h command.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
|
||||
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
|
||||
|
|
16
gdb/ORIGIN
16
gdb/ORIGIN
|
@ -1,16 +0,0 @@
|
|||
Host akbar.cac.washington.edu (128.95.112.1)
|
||||
Last updated 17:04 11 Nov 1990
|
||||
Location: local/emacs.pmax/info
|
||||
FILE rw-rw-r-- 2515 Feb 12 1988 gdb
|
||||
Location: local/emacs.pmax.old
|
||||
DIRECTORY rwxr-xr-x 2048 Sep 11 01:16 gdb
|
||||
Location: local/emacs.pmax.old/info
|
||||
FILE rw-rw-r-- 2515 Feb 12 1988 gdb
|
||||
Location: local/emacs.pmax4.0
|
||||
DIRECTORY rwxr-xr-x 2048 Aug 11 01:16 gdb
|
||||
Location: local/emacs.pmax4.0/info
|
||||
FILE rw-r--r-- 2515 Feb 12 1988 gdb
|
||||
Location: local/emacs.sun386
|
||||
DIRECTORY rwxr-xr-x 2048 May 23 01:17 gdb
|
||||
Location: local/emacs.sun386/info
|
||||
FILE rw-rw-r-- 2515 Feb 12 1988 gdb
|
|
@ -1,95 +0,0 @@
|
|||
total 1304
|
||||
drwxr-xr-x 2 bin system 2048 May 23 1990 .
|
||||
drwxr-xr-x 11 bin system 512 May 23 1990 ..
|
||||
-rw-rw-r-- 2 5057 staff 7517 Feb 11 1988 COPYING
|
||||
-rw-rw-r-- 2 5057 staff 58620 Sep 3 1988 ChangeLog
|
||||
-rw-rw-r-- 2 5057 staff 4698 Sep 3 1988 Makefile
|
||||
-rw-rw-r-- 2 5057 staff 1168 Jul 8 1988 README
|
||||
-rw-rw-r-- 2 5057 staff 30273 May 6 1988 TAGS
|
||||
-rw-rw-r-- 2 5057 staff 8285 Mar 24 1988 blockframe.c
|
||||
-rw-rw-r-- 2 5057 staff 28258 Jun 9 1988 breakpoint.c
|
||||
-rw-r--r-- 2 5057 staff 12288 Dec 20 1988 coffread.c
|
||||
-rw-rw-r-- 2 5057 staff 14515 Mar 25 1988 command.c
|
||||
-rw-rw-r-- 2 5057 staff 7397 Feb 11 1988 command.h
|
||||
-rwxrwxr-x 2 5057 staff 2273 Sep 1 1988 config.gdb
|
||||
-rw-rw-r-- 2 5057 staff 19678 May 3 1988 core.c
|
||||
-rw-rw-r-- 2 5057 staff 69156 Jul 6 1988 dbxread.c
|
||||
-rw-rw-r-- 2 5057 staff 2499 May 22 1988 defs.h
|
||||
-rw-rw-r-- 2 5057 staff 8436 Feb 11 1988 environ.c
|
||||
-rw-rw-r-- 2 5057 staff 615 Jul 15 1986 environ.h
|
||||
-rw-rw-r-- 2 5057 staff 16501 Feb 3 1988 eval.c
|
||||
-rw-rw-r-- 2 5057 staff 9484 May 30 1988 expprint.c
|
||||
-rw-rw-r-- 2 5057 staff 27745 Apr 30 1988 expread.y
|
||||
-rw-rw-r-- 2 5057 staff 6455 Nov 22 1986 expression.h
|
||||
-rw-rw-r-- 2 5057 staff 10805 Jun 27 1988 findvar.c
|
||||
-rw-rw-r-- 2 5057 staff 7052 Feb 11 1988 firstfile.c
|
||||
-rw-rw-r-- 2 5057 staff 2287 Sep 30 1986 frame.h
|
||||
-rw-rw-r-- 2 5057 staff 4006 Apr 13 1987 gdb.1
|
||||
-rw-rw-r-- 2 5057 staff 41892 Sep 2 1988 gdb.ideas
|
||||
-rw-rw-r-- 2 5057 staff 6759 Jun 21 1988 gld-pinsn.c
|
||||
-rw-rw-r-- 2 5057 staff 23615 Jun 27 1988 infcmd.c
|
||||
-rw-rw-r-- 2 5057 staff 2820 Feb 3 1988 inferior.h
|
||||
-rw-rw-r-- 2 5057 staff 23111 Sep 3 1988 inflow.c
|
||||
-rw-rw-r-- 2 5057 staff 29393 Jun 25 1988 infrun.c
|
||||
-rw-rw-r-- 2 5057 staff 6545 Jun 21 1988 initialize.h
|
||||
-rw-rw-r-- 2 5057 staff 409 Jul 15 1986 kdb-start.c
|
||||
-rw-rw-r-- 2 5057 staff 172 Jul 15 1986 lastfile.c
|
||||
-rw-rw-r-- 2 5057 staff 20054 Apr 11 1988 m-hp9k320.h
|
||||
-rw-rw-r-- 2 5057 staff 19325 Sep 1 1988 m-hp9k320bsd.h
|
||||
-rw-rw-r-- 4 5057 staff 141 Feb 6 1988 m-init.h
|
||||
-rw-rw-r-- 2 5057 staff 20411 Apr 6 1988 m-isi.h
|
||||
-rw-rw-r-- 2 5057 staff 348 Mar 20 1988 m-isiinit.h
|
||||
-rw-rw-r-- 2 5057 staff 15011 Mar 24 1988 m-merlin.h
|
||||
-rw-rw-r-- 2 5057 staff 19335 Aug 30 1988 m-news.h
|
||||
-rw-rw-r-- 2 5057 staff 146 Jan 15 1988 m-newsinit.h
|
||||
-rw-rw-r-- 2 5057 staff 18267 Jun 17 1988 m-npl.h
|
||||
-rw-rw-r-- 2 5057 staff 189 Jun 16 1988 m-nplinit.h
|
||||
-rw-rw-r-- 2 5057 staff 17503 Jun 17 1988 m-pn.h
|
||||
-rw-rw-r-- 2 5057 staff 191 Jun 16 1988 m-pninit.h
|
||||
-rw-rw-r-- 2 5057 staff 15507 Apr 6 1988 m-sun2.h
|
||||
-rw-rw-r-- 2 5057 staff 130 Jul 15 1986 m-sun2init.h
|
||||
-rw-rw-r-- 4 5057 staff 18051 Apr 6 1988 m-sun3.h
|
||||
-rw-rw-r-- 4 5057 staff 141 Feb 6 1988 m-sun3init.h
|
||||
-rw-rw-r-- 2 5057 staff 14711 Jun 17 1988 m-umax.h
|
||||
-rw-rw-r-- 2 5057 staff 147 Apr 9 1988 m-umaxinit.h
|
||||
-rw-rw-r-- 2 5057 staff 13590 Mar 24 1988 m-vax.h
|
||||
-rw-rw-r-- 2 5057 staff 141 Sep 24 1986 m-vaxinit.h
|
||||
-rw-rw-r-- 4 5057 staff 68314 Apr 8 1988 m68k-opcode.h
|
||||
-rw-rw-r-- 4 5057 staff 17695 Jun 21 1988 m68k-pinsn.c
|
||||
-rw-rw-r-- 2 5057 staff 34227 Jul 20 1988 main.c
|
||||
-rw-rw-r-- 2 5057 staff 18362 Jun 16 1988 npl-opcode.h
|
||||
-rw-rw-r-- 2 5057 staff 10621 Nov 25 1987 ns32k-opcode.h
|
||||
-rw-rw-r-- 2 5057 staff 10662 Jun 21 1988 ns32k-pinsn.c
|
||||
-rw-rw-r-- 2 5057 staff 12230 Jun 17 1988 obstack.c
|
||||
-rw-rw-r-- 2 5057 staff 18478 Jul 24 1988 obstack.h
|
||||
-rw-rw-r-- 4 5057 staff 68314 Apr 8 1988 opcode.h
|
||||
-rw-rw-r-- 4 5057 staff 18051 Apr 6 1988 param.h
|
||||
-rw-rw-r-- 4 5057 staff 17695 Jun 21 1988 pinsn.c
|
||||
-rw-rw-r-- 2 5057 staff 12573 Jun 16 1988 pn-opcode.h
|
||||
-rw-rw-r-- 2 5057 staff 31150 Jul 22 1988 printcmd.c
|
||||
-rw-rw-r-- 2 5057 staff 13024 Apr 7 1988 remote.c
|
||||
-rw-rw-r-- 2 5057 staff 22485 May 23 1988 source.c
|
||||
-rw-rw-r-- 2 5057 staff 16743 May 23 1988 stack.c
|
||||
-rw-rw-r-- 2 5057 staff 12067 May 3 1988 standalone.c
|
||||
-rw-rw-r-- 2 5057 staff 5366 Sep 30 1986 stuff.c
|
||||
-rw-rw-r-- 2 5057 staff 15537 Jul 26 1988 symmisc.c
|
||||
-rw-rw-r-- 2 5057 staff 13976 Feb 17 1988 symseg.h
|
||||
-rw-rw-r-- 2 5057 staff 30879 Apr 8 1988 symtab.c
|
||||
-rw-rw-r-- 2 5057 staff 8030 Apr 8 1988 symtab.h
|
||||
-rw-rw-r-- 2 5057 staff 303 Jul 15 1986 test2.c
|
||||
-rw-rw-r-- 2 5057 staff 602 Apr 9 1988 testbpt.c
|
||||
-rw-rw-r-- 2 5057 staff 205 Jan 2 1988 testfun.c
|
||||
-rw-rw-r-- 2 5057 staff 79 Jul 15 1986 testrec.c
|
||||
-rw-rw-r-- 2 5057 staff 365 Jul 15 1986 testreg.c
|
||||
-rw-rw-r-- 2 5057 staff 387 Dec 3 1987 testregs.c
|
||||
-rw-rw-r-- 2 5057 staff 9872 May 30 1988 utils.c
|
||||
-rw-rw-r-- 2 5057 staff 8374 Dec 17 1987 valarith.c
|
||||
-rw-rw-r-- 2 5057 staff 16436 Jan 7 1988 valops.c
|
||||
-rw-rw-r-- 2 5057 staff 17003 Sep 3 1988 valprint.c
|
||||
-rw-rw-r-- 2 5057 staff 3799 Feb 6 1988 value.h
|
||||
-rw-rw-r-- 2 5057 staff 19062 May 20 1988 values.c
|
||||
-rw-rw-r-- 2 5057 staff 12750 Jul 15 1986 vax-opcode.h
|
||||
-rw-rw-r-- 2 5057 staff 5681 Jun 21 1988 vax-pinsn.c
|
||||
-rw-rw-r-- 2 5057 staff 73 Sep 8 1988 version.c
|
||||
-rw-rw-r-- 2 5057 staff 961 May 1 1988 wait.h
|
||||
-rw-rw-r-- 2 5057 staff 19446 Jul 20 1988 xgdb.c
|
|
@ -1,95 +0,0 @@
|
|||
total 1338
|
||||
drwxr-xr-x 2 bin system 2048 Aug 11 01:16 .
|
||||
drwxr-xr-x 11 bin system 512 Sep 5 01:14 ..
|
||||
-rw-r--r-- 2 5057 staff 7517 Feb 11 1988 COPYING
|
||||
-rw-r--r-- 2 5057 staff 58620 Sep 3 1988 ChangeLog
|
||||
-rw-r--r-- 2 5057 staff 4698 Sep 3 1988 Makefile
|
||||
-rw-r--r-- 2 5057 staff 1168 Jul 8 1988 README
|
||||
-rw-r--r-- 2 5057 staff 30273 May 6 1988 TAGS
|
||||
-rw-r--r-- 2 5057 staff 8285 Mar 24 1988 blockframe.c
|
||||
-rw-r--r-- 2 5057 staff 28258 Jun 9 1988 breakpoint.c
|
||||
-rw-r--r-- 2 5057 staff 46897 Jul 12 1988 coffread.c
|
||||
-rw-r--r-- 2 5057 staff 14515 Mar 25 1988 command.c
|
||||
-rw-r--r-- 2 5057 staff 7397 Feb 11 1988 command.h
|
||||
-rwxr-xr-x 2 5057 staff 2273 Sep 1 1988 config.gdb
|
||||
-rw-r--r-- 2 5057 staff 19678 May 3 1988 core.c
|
||||
-rw-r--r-- 2 5057 staff 69156 Jul 6 1988 dbxread.c
|
||||
-rw-r--r-- 2 5057 staff 2499 May 22 1988 defs.h
|
||||
-rw-r--r-- 2 5057 staff 8436 Feb 11 1988 environ.c
|
||||
-rw-r--r-- 2 5057 staff 615 Jul 15 1986 environ.h
|
||||
-rw-r--r-- 2 5057 staff 16501 Feb 3 1988 eval.c
|
||||
-rw-r--r-- 2 5057 staff 9484 May 30 1988 expprint.c
|
||||
-rw-r--r-- 2 5057 staff 27745 Apr 30 1988 expread.y
|
||||
-rw-r--r-- 2 5057 staff 6455 Nov 22 1986 expression.h
|
||||
-rw-r--r-- 2 5057 staff 10805 Jun 27 1988 findvar.c
|
||||
-rw-r--r-- 2 5057 staff 7052 Feb 11 1988 firstfile.c
|
||||
-rw-r--r-- 2 5057 staff 2287 Sep 30 1986 frame.h
|
||||
-rw-r--r-- 2 5057 staff 4006 Apr 13 1987 gdb.1
|
||||
-rw-r--r-- 2 5057 staff 41892 Sep 2 1988 gdb.ideas
|
||||
-rw-r--r-- 2 5057 staff 6759 Jun 21 1988 gld-pinsn.c
|
||||
-rw-r--r-- 2 5057 staff 23615 Jun 27 1988 infcmd.c
|
||||
-rw-r--r-- 2 5057 staff 2820 Feb 3 1988 inferior.h
|
||||
-rw-r--r-- 2 5057 staff 23111 Sep 3 1988 inflow.c
|
||||
-rw-r--r-- 2 5057 staff 29393 Jun 25 1988 infrun.c
|
||||
-rw-r--r-- 2 5057 staff 6545 Jun 21 1988 initialize.h
|
||||
-rw-r--r-- 2 5057 staff 409 Jul 15 1986 kdb-start.c
|
||||
-rw-r--r-- 2 5057 staff 172 Jul 15 1986 lastfile.c
|
||||
-rw-r--r-- 2 5057 staff 20054 Apr 11 1988 m-hp9k320.h
|
||||
-rw-r--r-- 2 5057 staff 19325 Sep 1 1988 m-hp9k320bsd.h
|
||||
-rw-r--r-- 4 5057 staff 141 Feb 6 1988 m-init.h
|
||||
-rw-r--r-- 2 5057 staff 20411 Apr 6 1988 m-isi.h
|
||||
-rw-r--r-- 2 5057 staff 348 Mar 20 1988 m-isiinit.h
|
||||
-rw-r--r-- 2 5057 staff 15011 Mar 24 1988 m-merlin.h
|
||||
-rw-r--r-- 2 5057 staff 19335 Aug 30 1988 m-news.h
|
||||
-rw-r--r-- 2 5057 staff 146 Jan 15 1988 m-newsinit.h
|
||||
-rw-r--r-- 2 5057 staff 18267 Jun 17 1988 m-npl.h
|
||||
-rw-r--r-- 2 5057 staff 189 Jun 16 1988 m-nplinit.h
|
||||
-rw-r--r-- 2 5057 staff 17503 Jun 17 1988 m-pn.h
|
||||
-rw-r--r-- 2 5057 staff 191 Jun 16 1988 m-pninit.h
|
||||
-rw-r--r-- 2 5057 staff 15507 Apr 6 1988 m-sun2.h
|
||||
-rw-r--r-- 2 5057 staff 130 Jul 15 1986 m-sun2init.h
|
||||
-rw-r--r-- 4 5057 staff 18051 Apr 6 1988 m-sun3.h
|
||||
-rw-r--r-- 4 5057 staff 141 Feb 6 1988 m-sun3init.h
|
||||
-rw-r--r-- 2 5057 staff 14711 Jun 17 1988 m-umax.h
|
||||
-rw-r--r-- 2 5057 staff 147 Apr 9 1988 m-umaxinit.h
|
||||
-rw-r--r-- 2 5057 staff 13590 Mar 24 1988 m-vax.h
|
||||
-rw-r--r-- 2 5057 staff 141 Sep 24 1986 m-vaxinit.h
|
||||
-rw-r--r-- 4 5057 staff 68314 Apr 8 1988 m68k-opcode.h
|
||||
-rw-r--r-- 4 5057 staff 17695 Jun 21 1988 m68k-pinsn.c
|
||||
-rw-r--r-- 2 5057 staff 34227 Jul 20 1988 main.c
|
||||
-rw-r--r-- 2 5057 staff 18362 Jun 16 1988 npl-opcode.h
|
||||
-rw-r--r-- 2 5057 staff 10621 Nov 25 1987 ns32k-opcode.h
|
||||
-rw-r--r-- 2 5057 staff 10662 Jun 21 1988 ns32k-pinsn.c
|
||||
-rw-r--r-- 2 5057 staff 12230 Jun 17 1988 obstack.c
|
||||
-rw-r--r-- 2 5057 staff 18478 Jul 24 1988 obstack.h
|
||||
-rw-r--r-- 4 5057 staff 68314 Apr 8 1988 opcode.h
|
||||
-rw-r--r-- 4 5057 staff 18051 Apr 6 1988 param.h
|
||||
-rw-r--r-- 4 5057 staff 17695 Jun 21 1988 pinsn.c
|
||||
-rw-r--r-- 2 5057 staff 12573 Jun 16 1988 pn-opcode.h
|
||||
-rw-r--r-- 2 5057 staff 31150 Jul 22 1988 printcmd.c
|
||||
-rw-r--r-- 2 5057 staff 13024 Apr 7 1988 remote.c
|
||||
-rw-r--r-- 2 5057 staff 22485 May 23 1988 source.c
|
||||
-rw-r--r-- 2 5057 staff 16743 May 23 1988 stack.c
|
||||
-rw-r--r-- 2 5057 staff 12067 May 3 1988 standalone.c
|
||||
-rw-r--r-- 2 5057 staff 5366 Sep 30 1986 stuff.c
|
||||
-rw-r--r-- 2 5057 staff 15537 Jul 26 1988 symmisc.c
|
||||
-rw-r--r-- 2 5057 staff 13976 Feb 17 1988 symseg.h
|
||||
-rw-r--r-- 2 5057 staff 30879 Apr 8 1988 symtab.c
|
||||
-rw-r--r-- 2 5057 staff 8030 Apr 8 1988 symtab.h
|
||||
-rw-r--r-- 2 5057 staff 303 Jul 15 1986 test2.c
|
||||
-rw-r--r-- 2 5057 staff 602 Apr 9 1988 testbpt.c
|
||||
-rw-r--r-- 2 5057 staff 205 Jan 2 1988 testfun.c
|
||||
-rw-r--r-- 2 5057 staff 79 Jul 15 1986 testrec.c
|
||||
-rw-r--r-- 2 5057 staff 365 Jul 15 1986 testreg.c
|
||||
-rw-r--r-- 2 5057 staff 387 Dec 3 1987 testregs.c
|
||||
-rw-r--r-- 2 5057 staff 9872 May 30 1988 utils.c
|
||||
-rw-r--r-- 2 5057 staff 8374 Dec 17 1987 valarith.c
|
||||
-rw-r--r-- 2 5057 staff 16436 Jan 7 1988 valops.c
|
||||
-rw-r--r-- 2 5057 staff 17003 Sep 3 1988 valprint.c
|
||||
-rw-r--r-- 2 5057 staff 3799 Feb 6 1988 value.h
|
||||
-rw-r--r-- 2 5057 staff 19062 May 20 1988 values.c
|
||||
-rw-r--r-- 2 5057 staff 12750 Jul 15 1986 vax-opcode.h
|
||||
-rw-r--r-- 2 5057 staff 5681 Jun 21 1988 vax-pinsn.c
|
||||
-rw-r--r-- 2 5057 staff 73 Sep 8 1988 version.c
|
||||
-rw-r--r-- 2 5057 staff 961 May 1 1988 wait.h
|
||||
-rw-r--r-- 2 5057 staff 19446 Jul 20 1988 xgdb.c
|
|
@ -92,7 +92,7 @@ get_frame_info (frame)
|
|||
{
|
||||
struct frame_info val;
|
||||
FRAME current = get_current_frame ();
|
||||
register FRAME frame1;
|
||||
register FRAME frame1, frame2;
|
||||
|
||||
val.frame = frame;
|
||||
|
||||
|
@ -100,17 +100,21 @@ get_frame_info (frame)
|
|||
{
|
||||
val.pc = read_pc ();
|
||||
val.next_frame = 0;
|
||||
val.next_next_frame = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (frame1 = current; frame1; frame1 = get_prev_frame (frame1))
|
||||
for (frame1 = current, frame2 = 0;
|
||||
frame1;
|
||||
frame2 = frame1, frame1 = get_prev_frame (frame1))
|
||||
{
|
||||
QUIT;
|
||||
if (frame1 == frame)
|
||||
break;
|
||||
|
||||
val.pc = FRAME_SAVED_PC (frame1);
|
||||
val.pc = FRAME_SAVED_PC (frame1, frame2);
|
||||
val.next_frame = frame1;
|
||||
val.next_next_frame = frame2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,22 +129,23 @@ get_frame_info (frame)
|
|||
to find the frame called by the one being described -- that is FRAME. */
|
||||
|
||||
struct frame_info
|
||||
get_prev_frame_info (next_frame)
|
||||
FRAME next_frame;
|
||||
get_prev_frame_info (next_frame, next_next_frame)
|
||||
FRAME next_frame, next_next_frame;
|
||||
{
|
||||
struct frame_info val;
|
||||
register FRAME frame = get_prev_frame (next_frame);
|
||||
|
||||
val.frame = frame;
|
||||
val.next_frame = next_frame;
|
||||
val.next_next_frame = next_next_frame;
|
||||
|
||||
if (next_frame == 0)
|
||||
{
|
||||
val.pc = read_pc ();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
val.pc = FRAME_SAVED_PC (next_frame);
|
||||
val.pc = FRAME_SAVED_PC (next_frame, next_next_frame);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
|
185
gdb/breakpoint.c
185
gdb/breakpoint.c
|
@ -622,63 +622,96 @@ set_breakpoint (s, line, tempflag)
|
|||
}
|
||||
|
||||
/* Set a breakpoint according to ARG (function, linenum or *address)
|
||||
and make it temporary if TEMPFLAG is nonzero. */
|
||||
and make it temporary if TEMPFLAG is nonzero.
|
||||
|
||||
LINE_NUM is for C++. */
|
||||
|
||||
static void
|
||||
break_command_1 (arg, tempflag, from_tty)
|
||||
break_command_1 (arg, tempflag, from_tty, line_num)
|
||||
char *arg;
|
||||
int tempflag, from_tty;
|
||||
int tempflag, from_tty, line_num;
|
||||
{
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
register struct expression *cond = 0;
|
||||
register struct breakpoint *b;
|
||||
char *save_arg;
|
||||
int i;
|
||||
|
||||
sal.pc = 0;
|
||||
sals.sals = NULL;
|
||||
sals.nelts = 0;
|
||||
|
||||
sal.line = sal.pc = sal.end = 0;
|
||||
sal.symtab = 0;
|
||||
|
||||
if (arg)
|
||||
{
|
||||
sal = decode_line_1 (&arg, 1, 0, 0);
|
||||
CORE_ADDR pc;
|
||||
sals = decode_line_1 (&arg, 1, 0, 0);
|
||||
|
||||
if (sal.pc == 0 && sal.symtab != 0)
|
||||
if (! sals.nelts) return;
|
||||
save_arg = arg;
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 (sal.pc), 0);
|
||||
else
|
||||
error ("Junk at end of arguments.");
|
||||
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;
|
||||
}
|
||||
}
|
||||
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.");
|
||||
|
||||
if (from_tty)
|
||||
describe_other_breakpoints (sal.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);
|
||||
}
|
||||
|
||||
b = set_raw_breakpoint (sal);
|
||||
b->number = ++breakpoint_count;
|
||||
b->cond = cond;
|
||||
if (tempflag)
|
||||
b->enable = temporary;
|
||||
if (from_tty)
|
||||
describe_other_breakpoints (sal.pc);
|
||||
|
||||
printf ("Breakpoint %d at 0x%x", b->number, b->address);
|
||||
if (b->symtab)
|
||||
printf (": file %s, line %d.", b->symtab->filename, b->line_number);
|
||||
printf ("\n");
|
||||
b = set_raw_breakpoint (sal);
|
||||
b->number = ++breakpoint_count;
|
||||
b->cond = cond;
|
||||
if (tempflag)
|
||||
b->enable = temporary;
|
||||
|
||||
printf ("Breakpoint %d at 0x%x", b->number, b->address);
|
||||
if (b->symtab)
|
||||
printf (": file %s, line %d.", b->symtab->filename, b->line_number);
|
||||
printf ("\n");
|
||||
}
|
||||
free (sals.sals);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -686,7 +719,7 @@ break_command (arg, from_tty)
|
|||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
break_command_1 (arg, 0, from_tty);
|
||||
break_command_1 (arg, 0, from_tty, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -694,7 +727,7 @@ tbreak_command (arg, from_tty)
|
|||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
break_command_1 (arg, 1, from_tty);
|
||||
break_command_1 (arg, 1, from_tty, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -703,60 +736,70 @@ clear_command (arg, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
register struct breakpoint *b, *b1;
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
register struct breakpoint *found;
|
||||
int i;
|
||||
|
||||
if (arg)
|
||||
sal = decode_line_spec (arg, 1);
|
||||
sals = decode_line_spec (arg, 1);
|
||||
else
|
||||
{
|
||||
sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line));
|
||||
sal.line = default_breakpoint_line;
|
||||
sal.symtab = default_breakpoint_symtab;
|
||||
sal.pc = 0;
|
||||
if (sal.symtab == 0)
|
||||
error ("No source file specified.");
|
||||
|
||||
sals.sals[0] = sal;
|
||||
sals.nelts = 1;
|
||||
}
|
||||
|
||||
/* If exact pc given, clear bpts at that pc.
|
||||
But if sal.pc is zero, clear all bpts on specified line. */
|
||||
|
||||
found = (struct breakpoint *) 0;
|
||||
while (breakpoint_chain
|
||||
&& (sal.pc ? breakpoint_chain->address == sal.pc
|
||||
: (breakpoint_chain->symtab == sal.symtab
|
||||
&& breakpoint_chain->line_number == sal.line)))
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
{
|
||||
b1 = breakpoint_chain;
|
||||
breakpoint_chain = b1->next;
|
||||
b1->next = found;
|
||||
found = b1;
|
||||
/* If exact pc given, clear bpts at that pc.
|
||||
But if sal.pc is zero, clear all bpts on specified line. */
|
||||
sal = sals.sals[i];
|
||||
found = (struct breakpoint *) 0;
|
||||
while (breakpoint_chain
|
||||
&& (sal.pc ? breakpoint_chain->address == sal.pc
|
||||
: (breakpoint_chain->symtab == sal.symtab
|
||||
&& breakpoint_chain->line_number == sal.line)))
|
||||
{
|
||||
b1 = breakpoint_chain;
|
||||
breakpoint_chain = b1->next;
|
||||
b1->next = found;
|
||||
found = b1;
|
||||
}
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
while (b->next
|
||||
&& (sal.pc ? b->next->address == sal.pc
|
||||
: (b->next->symtab == sal.symtab
|
||||
&& b->next->line_number == sal.line)))
|
||||
{
|
||||
b1 = b->next;
|
||||
b->next = b1->next;
|
||||
b1->next = found;
|
||||
found = b1;
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
error ("No breakpoint at %s.", arg);
|
||||
|
||||
if (found->next) from_tty = 1; /* Always report if deleted more than one */
|
||||
if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
|
||||
while (found)
|
||||
{
|
||||
if (from_tty) printf ("%d ", found->number);
|
||||
b1 = found->next;
|
||||
delete_breakpoint (found);
|
||||
found = b1;
|
||||
}
|
||||
if (from_tty) putchar ('\n');
|
||||
}
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
while (b->next
|
||||
&& (sal.pc ? b->next->address == sal.pc
|
||||
: (b->next->symtab == sal.symtab
|
||||
&& b->next->line_number == sal.line)))
|
||||
{
|
||||
b1 = b->next;
|
||||
b->next = b1->next;
|
||||
b1->next = found;
|
||||
found = b1;
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
error ("No breakpoint at %s.", arg);
|
||||
|
||||
if (found->next) from_tty = 1; /* Alwats report if deleted more than one */
|
||||
if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : "");
|
||||
while (found)
|
||||
{
|
||||
if (from_tty) printf ("%d ", found->number);
|
||||
b1 = found->next;
|
||||
delete_breakpoint (found);
|
||||
found = b1;
|
||||
}
|
||||
if (from_tty) putchar ('\n');
|
||||
free (sals.sals);
|
||||
}
|
||||
|
||||
/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
|
||||
|
|
14
gdb/c.h
Normal file
14
gdb/c.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "b.h"
|
||||
|
||||
inline c ()
|
||||
{
|
||||
Foo x = 1;
|
||||
{
|
||||
Foo y = 2;
|
||||
{
|
||||
b ();
|
||||
}
|
||||
Foo z = 3;
|
||||
}
|
||||
Foo w = 4;
|
||||
}
|
1427
gdb/coffread.c
1427
gdb/coffread.c
File diff suppressed because it is too large
Load diff
|
@ -1,12 +0,0 @@
|
|||
coffread.c is truncated.
|
||||
|
||||
It ends on a 4096-byte boundary, which makes me think it got chopped
|
||||
in a disk operation, so the modification date probably doesn't reflect
|
||||
the date of the damage.
|
||||
|
||||
We checked the backups of Sep 8, 1992 and June 3, 1991, and in both
|
||||
cases it was truncated. So we would appear to be out of luck.
|
||||
|
||||
Someone found gdb-assorted on a dump of /s3 from cygint on November
|
||||
19, 1990, but no gdb-2.8. The guess is that gdb-2.8 moved there after
|
||||
/s3 moved to /work (which was apparently a new 1gig disk at the time).
|
1851
gdb/coffread.c.pmax
1851
gdb/coffread.c.pmax
File diff suppressed because it is too large
Load diff
|
@ -106,6 +106,10 @@ what you give them. Help stamp out software-hoarding! */
|
|||
#include "command.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef sparc
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
extern char *xmalloc ();
|
||||
|
||||
static char *savestring ();
|
||||
|
|
4
gdb/config.gdb
Normal file → Executable file
4
gdb/config.gdb
Normal file → Executable file
|
@ -61,6 +61,10 @@ case $# in
|
|||
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
|
||||
|
|
1
gdb/config.status
Normal file
1
gdb/config.status
Normal file
|
@ -0,0 +1 @@
|
|||
Links are now set up for use with a sun4.
|
21
gdb/core.c
21
gdb/core.c
|
@ -201,6 +201,7 @@ core_file_command (filename, from_tty)
|
|||
data_offset = sizeof corestr;
|
||||
stack_offset = sizeof corestr + corestr.c_dsize;
|
||||
|
||||
#if defined(sun2) || defined(sun3)
|
||||
bcopy (&corestr.c_regs, registers, 16 * 4);
|
||||
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
|
||||
|
@ -210,6 +211,26 @@ core_file_command (filename, from_tty)
|
|||
bcopy (&corestr.c_fpstatus.fps_control,
|
||||
®isters[REGISTER_BYTE (FPC_REGNUM)],
|
||||
sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
|
||||
#endif
|
||||
#if defined(sun4)
|
||||
/* G0 *always* holds 0. */
|
||||
*(int *)®isters[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 *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
|
||||
*(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc;
|
||||
*(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y;
|
||||
bcopy (corestr.c_fpu.fpu_regs,
|
||||
®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof corestr.c_fpu.fpu_regs);
|
||||
#ifdef FPU
|
||||
bcopy (&corestr.c_fpu.fpu_fsr,
|
||||
®isters[REGISTER_BYTE (FPS_REGNUM)],
|
||||
sizeof (FPU_FSR_TYPE));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
|
||||
|
||||
|
|
775
gdb/dbxread.c
775
gdb/dbxread.c
|
@ -1,5 +1,6 @@
|
|||
/* Read dbx symbol tables and convert to internal format, for GDB.
|
||||
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
|
||||
Hacked 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
|
||||
|
@ -51,6 +52,9 @@ static void hash_symsegs ();
|
|||
extern struct symtab *read_symsegs ();
|
||||
extern void free_all_symtabs ();
|
||||
|
||||
/* C++ */
|
||||
static struct type **read_args ();
|
||||
|
||||
/* Macro for number of symbol table entries (in usual a.out format).
|
||||
Some machines override this definition. */
|
||||
#ifndef NUMBER_OF_SYMBOLS
|
||||
|
@ -561,6 +565,8 @@ dbx_alloc_type (typenums)
|
|||
type = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
bzero (type, sizeof (struct type));
|
||||
TYPE_VPTR_FIELDNO (type) = -1;
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
*type_addr = type;
|
||||
}
|
||||
return type;
|
||||
|
@ -1197,6 +1203,7 @@ sort_syms ()
|
|||
if (BLOCK_SHOULD_SORT (b))
|
||||
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
|
||||
sizeof (struct symbol *), compare_symbols);
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
int lastindex = BLOCK_NSYMS (b) - 1;
|
||||
|
@ -1209,6 +1216,7 @@ sort_syms ()
|
|||
BLOCK_SYM (b, lastindex - j) = sym;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1667,7 +1675,14 @@ process_one_symbol (type, desc, value, name)
|
|||
if (type == N_ENTRY)
|
||||
/* This code appears in libraries on Gould machines. */
|
||||
return;
|
||||
error ("Invalid symbol data: does not start by identifying a source file.");
|
||||
|
||||
if (type == N_SLINE && desc == -1)
|
||||
/* This code is used by the Sun4 coimpiler; ignore it. */
|
||||
return;
|
||||
|
||||
/* This should give an aborting error. */
|
||||
printf ("Invalid symbol data: does not start by identifying a source file.\ntype == %d\n\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
|
@ -1678,7 +1693,7 @@ process_one_symbol (type, desc, value, name)
|
|||
a new function. We must process its "name" normally for dbx,
|
||||
but also record the start of a new lexical context, and possibly
|
||||
also the end of the lexical context for the previous function. */
|
||||
|
||||
|
||||
within_function = 1;
|
||||
if (context_stack_depth > 0)
|
||||
{
|
||||
|
@ -1806,6 +1821,316 @@ process_one_symbol (type, desc, value, name)
|
|||
}
|
||||
}
|
||||
|
||||
/************************ READ_ADDL_SYM() ***********************************/
|
||||
|
||||
static void
|
||||
read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
|
||||
int desc;
|
||||
register char *stringtab;
|
||||
register int nlistlen;
|
||||
unsigned text_addr;
|
||||
int text_size;
|
||||
{
|
||||
FILE *stream = fdopen (desc, "r");
|
||||
register char *namestring;
|
||||
register struct symbol *sym, *prev;
|
||||
int hash;
|
||||
int num_object_files = 0;
|
||||
|
||||
#ifdef N_BINCL
|
||||
subfile_stack = 0;
|
||||
#endif
|
||||
|
||||
last_source_file = 0;
|
||||
bzero (global_sym_chain, sizeof global_sym_chain);
|
||||
symtab_input_desc = desc;
|
||||
stringtab_global = stringtab;
|
||||
fill_symbuf ();
|
||||
|
||||
for (symnum = 0; symnum < nlistlen; symnum++)
|
||||
{
|
||||
struct nlist *bufp;
|
||||
int type;
|
||||
|
||||
QUIT; /* allow this to be interruptable */
|
||||
if (symbuf_idx == symbuf_end)
|
||||
fill_symbuf ();
|
||||
bufp = &symbuf[symbuf_idx++];
|
||||
type = bufp->n_type & N_TYPE;
|
||||
namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : "";
|
||||
|
||||
if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) )
|
||||
{
|
||||
/* Relocate this file's symbol table information
|
||||
to the address it has been loaded into. */
|
||||
bufp->n_value += text_addr;
|
||||
}
|
||||
|
||||
type = bufp->n_type;
|
||||
|
||||
if (type & N_STAB)
|
||||
process_one_symbol (type, bufp->n_desc,
|
||||
bufp->n_value, namestring);
|
||||
/* A static text symbol whose name ends in ".o"
|
||||
can only mean the start of another object file.
|
||||
So end the symtab of the source file we have been processing.
|
||||
This is how we avoid counting the libraries as part
|
||||
or the last source file.
|
||||
Also this way we find end of first object file (crt0). */
|
||||
else if ((type == N_TEXT
|
||||
#ifdef N_NBTEXT
|
||||
|| type == N_NBTEXT
|
||||
#endif
|
||||
)
|
||||
&& (!strcmp (namestring + strlen (namestring) - 2, ".o"))
|
||||
|| ! strcmp (namestring, "-l", 2))
|
||||
{
|
||||
if (num_object_files++ == 1)
|
||||
first_object_file_end = bufp->n_value;
|
||||
if (last_source_file)
|
||||
end_symtab (bufp->n_value);
|
||||
}
|
||||
else if (type & N_EXT || type == N_TEXT
|
||||
#ifdef N_NBTEXT
|
||||
|| type == N_NBTEXT
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int used_up = 0;
|
||||
|
||||
/* Record the location of _etext. */
|
||||
if (type == (N_TEXT | N_EXT)
|
||||
&& !strcmp (namestring, "_etext"))
|
||||
end_of_text_addr = bufp->n_value;
|
||||
|
||||
/* Global symbol: see if we came across a dbx definition
|
||||
for a corresponding symbol. If so, store the value.
|
||||
Remove syms from the chain when their values are stored,
|
||||
but search the whole chain, as there may be several syms
|
||||
from different files with the same name. */
|
||||
if (type & N_EXT)
|
||||
{
|
||||
prev = 0;
|
||||
#ifdef NAMES_HAVE_UNDERSCORE
|
||||
hash = hashname (namestring + 1);
|
||||
#else /* not NAMES_HAVE_UNDERSCORE */
|
||||
hash = hashname (namestring);
|
||||
#endif /* not NAMES_HAVE_UNDERSCORE */
|
||||
for (sym = global_sym_chain[hash];
|
||||
sym;)
|
||||
{
|
||||
if (
|
||||
#ifdef NAMES_HAVE_UNDERSCORE
|
||||
*namestring == '_'
|
||||
&& namestring[1] == SYMBOL_NAME (sym)[0]
|
||||
&&
|
||||
!strcmp (namestring + 2, SYMBOL_NAME (sym) + 1)
|
||||
#else /* NAMES_HAVE_UNDERSCORE */
|
||||
namestring[0] == SYMBOL_NAME (sym)[0]
|
||||
&&
|
||||
!strcmp (namestring + 1, SYMBOL_NAME (sym) + 1)
|
||||
#endif /* NAMES_HAVE_UNDERSCORE */
|
||||
)
|
||||
{
|
||||
if (prev)
|
||||
SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
|
||||
else
|
||||
global_sym_chain[hash]
|
||||
= (struct symbol *) SYMBOL_VALUE (sym);
|
||||
SYMBOL_VALUE (sym) = bufp->n_value;
|
||||
if (prev)
|
||||
sym = (struct symbol *) SYMBOL_VALUE (prev);
|
||||
else
|
||||
sym = global_sym_chain[hash];
|
||||
|
||||
used_up = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = sym;
|
||||
sym = (struct symbol *) SYMBOL_VALUE (sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Defined global or text symbol: record as a misc function
|
||||
if it didn't give its address to a debugger symbol above. */
|
||||
if (type <= (N_TYPE | N_EXT)
|
||||
&& type != N_EXT
|
||||
&& ! used_up)
|
||||
record_misc_function (namestring, bufp->n_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (last_source_file)
|
||||
end_symtab (text_addr + text_size);
|
||||
|
||||
fclose (stream);
|
||||
}
|
||||
|
||||
/***************************** CONDENSE_ADDL_MISC_BUNCHES *******************/
|
||||
|
||||
static void
|
||||
condense_addl_misc_bunches ()
|
||||
{
|
||||
register int i, j;
|
||||
register struct misc_bunch *bunch;
|
||||
#ifdef NAMES_HAVE_UNDERSCORE
|
||||
int offset = 1;
|
||||
#else
|
||||
int offset = 0;
|
||||
#endif
|
||||
|
||||
misc_function_vector
|
||||
= (struct misc_function *) xrealloc (misc_function_vector,
|
||||
(misc_count + misc_function_count) * sizeof (struct misc_function));
|
||||
|
||||
j = misc_function_count;
|
||||
bunch = misc_bunch;
|
||||
while (bunch)
|
||||
{
|
||||
for (i = 0; i < misc_bunch_index; i++)
|
||||
{
|
||||
misc_function_vector[j] = bunch->contents[i];
|
||||
misc_function_vector[j].name
|
||||
= concat (misc_function_vector[j].name
|
||||
+ (misc_function_vector[j].name[0] == '_' ? offset : 0),
|
||||
"", "");
|
||||
j++;
|
||||
}
|
||||
bunch = bunch->next;
|
||||
misc_bunch_index = MISC_BUNCH_SIZE;
|
||||
}
|
||||
|
||||
misc_function_count += misc_count;
|
||||
|
||||
/* Sort the misc functions by address. */
|
||||
|
||||
qsort (misc_function_vector, misc_function_count,
|
||||
sizeof (struct misc_function), compare_misc_functions);
|
||||
}
|
||||
|
||||
/**************************** ADD_FILE_COMMAND() ****************************/
|
||||
/* This function allows the addition of incrementally linked object files. */
|
||||
|
||||
void
|
||||
add_file_command (arg_string)
|
||||
char* arg_string;
|
||||
{
|
||||
register int desc;
|
||||
struct exec hdr;
|
||||
struct nlist *nlist;
|
||||
char *stringtab;
|
||||
long buffer;
|
||||
register int val;
|
||||
extern void close ();
|
||||
struct cleanup *old_chain;
|
||||
char* name;
|
||||
unsigned text_addr;
|
||||
|
||||
if (arg_string == 0)
|
||||
error ("add-file takes a file name and an address");
|
||||
|
||||
for( ; *arg_string == ' '; arg_string++ );
|
||||
name = arg_string;
|
||||
for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
|
||||
*arg_string++ = (char) 0;
|
||||
|
||||
if (name[0] == 0)
|
||||
error ("add-file takes a file name and an address");
|
||||
|
||||
text_addr = parse_and_eval_address (arg_string);
|
||||
|
||||
dont_repeat ();
|
||||
|
||||
if (query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", name, text_addr))
|
||||
{
|
||||
desc = open (name, O_RDONLY);
|
||||
if (desc < 0)
|
||||
perror_with_name (name);
|
||||
|
||||
old_chain = make_cleanup (close, desc);
|
||||
make_cleanup (free_current_contents, &name);
|
||||
|
||||
val = myread (desc, &hdr, sizeof hdr);
|
||||
if (val < 0)
|
||||
perror_with_name (name);
|
||||
|
||||
if (N_BADMAG (hdr))
|
||||
error ("File \"%s\" has a bad header.", name);
|
||||
|
||||
if (hdr.a_syms == 0)
|
||||
{
|
||||
printf ("%s does not have a symbol-table.\n", name);
|
||||
fflush (stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now read the string table, all at once. */
|
||||
val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0);
|
||||
if (val < 0)
|
||||
perror_with_name (name);
|
||||
val = myread (desc, &buffer, sizeof buffer);
|
||||
if (val < 0)
|
||||
perror_with_name (name);
|
||||
stringtab = (char *) alloca (buffer);
|
||||
bcopy (&buffer, stringtab, sizeof buffer);
|
||||
val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer);
|
||||
if (val < 0)
|
||||
perror_with_name (name);
|
||||
|
||||
/* That puts us at the symsegs. Read them. ########## Also need other
|
||||
changes if they exist. */
|
||||
|
||||
/* Position to read the symbol table. Do not read it all at once. */
|
||||
val = lseek (desc, N_SYMOFF (hdr), 0);
|
||||
if (val < 0)
|
||||
perror_with_name (name);
|
||||
|
||||
printf ("Reading symbol data from %s...", name);
|
||||
fflush (stdout);
|
||||
|
||||
init_misc_functions ();
|
||||
make_cleanup (discard_misc_bunches, 0);
|
||||
init_header_files ();
|
||||
make_cleanup (free_header_files, 0);
|
||||
|
||||
read_addl_syms (desc, stringtab, hdr.a_syms / sizeof(struct nlist),
|
||||
text_addr, hdr.a_text) ;
|
||||
|
||||
/* Sort symbols alphabetically within each block. */
|
||||
|
||||
sort_syms ();
|
||||
|
||||
/* Go over the all misc functions and install them in vector. */
|
||||
|
||||
condense_addl_misc_bunches ();
|
||||
|
||||
/* Don't allow char * to have a typename (else would get caddr_t.) */
|
||||
|
||||
TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0;
|
||||
|
||||
/* Make a default for file to list. */
|
||||
|
||||
select_source_symtab (symtab_list);
|
||||
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/* Free the symtabs made by read_symsegs, but not their contents,
|
||||
which have been copied into symtabs on symtab_list. */
|
||||
while (symseg_chain)
|
||||
{
|
||||
register struct symtab *s = symseg_chain->next;
|
||||
free (symseg_chain);
|
||||
symseg_chain = s;
|
||||
}
|
||||
|
||||
printf ("done.\n");
|
||||
fflush (stdout);
|
||||
}
|
||||
else error ("Not confirmed.");
|
||||
}
|
||||
|
||||
static struct symbol *
|
||||
define_symbol (value, string, desc)
|
||||
int value;
|
||||
|
@ -1955,6 +2280,13 @@ define_symbol (value, string, desc)
|
|||
SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
SYMBOL_CLASS (sym) = LOC_REGPARM;
|
||||
SYMBOL_VALUE (sym) = value;
|
||||
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
|
||||
add_symbol_to_list (sym, &local_symbols);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
SYMBOL_CLASS (sym) = LOC_REGISTER;
|
||||
SYMBOL_VALUE (sym) = value;
|
||||
|
@ -1979,6 +2311,20 @@ define_symbol (value, string, desc)
|
|||
TYPE_NAME (SYMBOL_TYPE (sym)) =
|
||||
obsavestring (SYMBOL_NAME (sym),
|
||||
strlen (SYMBOL_NAME (sym)));
|
||||
/* C++ vagaries: we may have a type which is derived from
|
||||
a base type which did not have its name defined when the
|
||||
derived class was output. We fill in the derived class's
|
||||
base part member's name here in that case. */
|
||||
else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
|
||||
&& TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
|
||||
{
|
||||
int i;
|
||||
for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--)
|
||||
if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) == 0)
|
||||
TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
|
||||
}
|
||||
|
||||
add_symbol_to_list (sym, &file_symbols);
|
||||
break;
|
||||
|
||||
|
@ -2082,7 +2428,11 @@ read_type (pp)
|
|||
break;
|
||||
}
|
||||
/* Skip the name the cross-ref points to. */
|
||||
*pp = (char *) index (*pp, ',');
|
||||
/* Note: for C++, the cross reference may be to a base type which
|
||||
has not yet been seen. In this case, we skip to the comma,
|
||||
which will mark the end of the base class name. (The ':'
|
||||
at the end of the base class name will be skipped as well.) */
|
||||
*pp = (char *) index (*pp, ':') + 1;
|
||||
/* Just allocate the type and leave it zero if nothing known */
|
||||
return dbx_alloc_type (typenums);
|
||||
|
||||
|
@ -2110,6 +2460,27 @@ read_type (pp)
|
|||
smash_to_pointer_type (type, read_type (pp));
|
||||
break;
|
||||
|
||||
case '@':
|
||||
{
|
||||
struct type *domain = read_type (pp);
|
||||
char c;
|
||||
struct type *memtype;
|
||||
|
||||
if (*(*pp)++ != ',')
|
||||
error ("invalid member type data format, at symtab pos %d.",
|
||||
symnum);
|
||||
|
||||
memtype = read_type (pp);
|
||||
type = dbx_alloc_type (typenums);
|
||||
smash_to_member_type (type, domain, memtype);
|
||||
}
|
||||
break;
|
||||
|
||||
case '&':
|
||||
type = dbx_alloc_type (typenums);
|
||||
smash_to_reference_type (type, read_type (pp));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
type = dbx_alloc_type (typenums);
|
||||
smash_to_function_type (type, read_type (pp));
|
||||
|
@ -2203,9 +2574,23 @@ read_struct_type (pp, type)
|
|||
struct nextfield
|
||||
{
|
||||
struct nextfield *next;
|
||||
int visibility;
|
||||
struct field field;
|
||||
};
|
||||
|
||||
struct next_fnfield
|
||||
{
|
||||
struct next_fnfield *next;
|
||||
int visibility;
|
||||
struct fn_field fn_field;
|
||||
};
|
||||
|
||||
struct next_fnfieldlist
|
||||
{
|
||||
struct next_fnfieldlist *next;
|
||||
struct fn_fieldlist fn_fieldlist;
|
||||
};
|
||||
|
||||
register struct nextfield *list = 0;
|
||||
struct nextfield *new;
|
||||
int totalsize;
|
||||
|
@ -2214,20 +2599,95 @@ read_struct_type (pp, type)
|
|||
int nfields = 0;
|
||||
register int n;
|
||||
|
||||
register struct next_fnfieldlist *mainlist = 0;
|
||||
int nfn_fields = 0;
|
||||
struct type *baseclass = NULL;
|
||||
int read_possible_virtual_info = 0;
|
||||
|
||||
TYPE_CODE (type) = TYPE_CODE_STRUCT;
|
||||
|
||||
/* First comes the total size in bytes. */
|
||||
|
||||
TYPE_LENGTH (type) = read_number (pp, 0);
|
||||
|
||||
/* Now come the fields, as NAME:TYPENUM,BITPOS,BITSIZE; for each one.
|
||||
At the end, we see a semicolon instead of a field. */
|
||||
/* C++: Now, if the class is a derived class, then the next character
|
||||
will be a '!', followed by the number of base classes derived from.
|
||||
Each element in the list contains visibility information,
|
||||
the offset of this base class in the derived structure,
|
||||
and then the base type. */
|
||||
if (**pp == '!')
|
||||
{
|
||||
int i, n_baseclasses, offset;
|
||||
struct type **baseclass_vec;
|
||||
struct type *baseclass;
|
||||
int via_public, via_virtual;
|
||||
*pp += 1;
|
||||
|
||||
n_baseclasses = read_number (pp, ',');
|
||||
baseclass_vec = (struct type **)
|
||||
obstack_alloc (symbol_obstack,
|
||||
(n_baseclasses) * sizeof (struct type **)) - 1;
|
||||
for (i = 1; i <= n_baseclasses; i++)
|
||||
{
|
||||
if (**pp == '\\') *pp = next_symbol_text ();
|
||||
switch (*(*pp)++)
|
||||
{
|
||||
case '0':
|
||||
via_virtual = 0;
|
||||
break;
|
||||
case '1':
|
||||
via_virtual = 1;
|
||||
break;
|
||||
default:
|
||||
error ("Invalid symbol data: bad visibility format at symtab pos %d.",
|
||||
symnum);
|
||||
}
|
||||
switch (*(*pp)++)
|
||||
{
|
||||
case '0':
|
||||
via_public = 0;
|
||||
break;
|
||||
case '2':
|
||||
via_public = 1;
|
||||
break;
|
||||
default:
|
||||
error ("Invalid symbol data: bad visibility format at symtab pos %d.",
|
||||
symnum);
|
||||
}
|
||||
offset = read_number (pp, ',');
|
||||
baseclass = read_type (pp);
|
||||
*pp += 1; /* skip trailing ';' */
|
||||
baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
|
||||
|
||||
/* Make this baseclass visible for structure-printing purposes. */
|
||||
new = (struct nextfield *) alloca (sizeof (struct nextfield));
|
||||
new->next = list;
|
||||
list = new;
|
||||
list->field.type = baseclass_vec[i];
|
||||
list->field.name = TYPE_NAME (baseclass_vec[i]);
|
||||
list->field.bitpos = offset;
|
||||
list->field.bitsize = 0; /* this should be an unpacked field! */
|
||||
nfields++;
|
||||
}
|
||||
TYPE_N_BASECLASSES (type) = n_baseclasses;
|
||||
TYPE_BASECLASSES (type) = baseclass_vec;
|
||||
}
|
||||
|
||||
/* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one.
|
||||
At the end, we see a semicolon instead of a field.
|
||||
|
||||
In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
|
||||
a static field.
|
||||
|
||||
The `?' is a placeholder for one of '+' (public visibility),
|
||||
'0' (protected visibility), and '-' (private visibility). */
|
||||
|
||||
while (**pp != ';')
|
||||
{
|
||||
int visibility;
|
||||
|
||||
/* Check for and handle cretinous dbx symbol name continuation! */
|
||||
if (**pp == '\\')
|
||||
*pp = next_symbol_text ();
|
||||
if (**pp == '\\') *pp = next_symbol_text ();
|
||||
|
||||
/* Get space to record the next field's data. */
|
||||
new = (struct nextfield *) alloca (sizeof (struct nextfield));
|
||||
|
@ -2238,9 +2698,49 @@ read_struct_type (pp, type)
|
|||
p = *pp;
|
||||
while (*p != ':') p++;
|
||||
list->field.name = obsavestring (*pp, p - *pp);
|
||||
|
||||
/* C++: Check to see if we have hit the methods yet. */
|
||||
if (p[1] == ':')
|
||||
break;
|
||||
|
||||
*pp = p + 1;
|
||||
|
||||
/* This means we have a visibility for a field coming. */
|
||||
if (**pp == '/')
|
||||
{
|
||||
switch (*++*pp)
|
||||
{
|
||||
case '0':
|
||||
visibility = 0;
|
||||
*pp += 1;
|
||||
break;
|
||||
|
||||
case '1':
|
||||
visibility = 1;
|
||||
*pp += 1;
|
||||
break;
|
||||
|
||||
case '2':
|
||||
visibility = 2;
|
||||
*pp += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* else normal dbx-style format. */
|
||||
|
||||
list->field.type = read_type (pp);
|
||||
if (**pp != ',')
|
||||
if (**pp == ':')
|
||||
{
|
||||
/* read a static member. */
|
||||
list->field.bitpos = (long)-1;
|
||||
p = ++(*pp);
|
||||
while (*p != ';') p++;
|
||||
list->field.bitsize = (long) savestring (*pp, p - *pp);
|
||||
*pp = p + 1;
|
||||
nfields++;
|
||||
continue;
|
||||
}
|
||||
else if (**pp != ',')
|
||||
error ("Invalid symbol data: bad structure-type format at symtab pos %d.",
|
||||
symnum);
|
||||
(*pp)++; /* Skip the comma. */
|
||||
|
@ -2262,18 +2762,216 @@ read_struct_type (pp, type)
|
|||
nfields++;
|
||||
}
|
||||
|
||||
(*pp)++; /* Skip the terminating ';'. */
|
||||
/* Now come the method fields, as NAME::methods
|
||||
where each method is of the form TYPENUM,ARGS,...:PHYSNAME;
|
||||
At the end, we see a semicolon instead of a field.
|
||||
|
||||
For the case of overloaded operators, the format is
|
||||
OPERATOR::*.methods, where OPERATOR is the string "operator",
|
||||
`*' holds the place for an operator name (such as `+=')
|
||||
and `.' marks the end of the operator name. */
|
||||
if (p[1] == ':')
|
||||
{
|
||||
/* Now, read in the methods. To simplify matters, we
|
||||
"unread" the name that has been read, so that we can
|
||||
start from the top. */
|
||||
|
||||
p = *pp;
|
||||
|
||||
/* chill the list of fields: the last entry (at the head)
|
||||
is a partially constructed entry which we now scrub. */
|
||||
list = list->next;
|
||||
|
||||
/* For each list of method lists... */
|
||||
do
|
||||
{
|
||||
int i;
|
||||
struct next_fnfield *sublist = 0;
|
||||
struct fn_field *fn_fields = 0;
|
||||
int length = 0;
|
||||
struct next_fnfieldlist *new_mainlist =
|
||||
(struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist));
|
||||
|
||||
/* read in the name. */
|
||||
while (*p != ':') p++;
|
||||
if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$')
|
||||
{
|
||||
static char opname[32] = "operator ";
|
||||
char *o = opname + 9;
|
||||
|
||||
/* Skip past '::'. */
|
||||
p += 2;
|
||||
while (*p != '.')
|
||||
*o++ = *p++;
|
||||
new_mainlist->fn_fieldlist.name = savestring (opname, o - opname);
|
||||
/* Skip past '.' */
|
||||
*pp = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp);
|
||||
/* Skip past '::'. */
|
||||
*pp = p + 2;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
struct next_fnfield *new_sublist =
|
||||
(struct next_fnfield *)alloca (sizeof (struct next_fnfield));
|
||||
|
||||
/* Check for and handle cretinous dbx symbol name continuation! */
|
||||
if (**pp == '\\') *pp = next_symbol_text ();
|
||||
|
||||
new_sublist->fn_field.type = read_type (pp);
|
||||
new_sublist->fn_field.args = read_args (pp, ':');
|
||||
p = *pp;
|
||||
while (*p != ';') p++;
|
||||
new_sublist->fn_field.physname = savestring (*pp, p - *pp);
|
||||
*pp = p + 1;
|
||||
new_sublist->visibility = *(*pp)++ - '0';
|
||||
if (**pp == '\\') *pp = next_symbol_text ();
|
||||
|
||||
if (*(*pp)++ == '*')
|
||||
new_sublist->fn_field.voffset = read_number (pp, ';') + 1;
|
||||
else
|
||||
new_sublist->fn_field.voffset = 0;
|
||||
|
||||
new_sublist->next = sublist;
|
||||
sublist = new_sublist;
|
||||
length++;
|
||||
}
|
||||
while (**pp != ';');
|
||||
|
||||
*pp += 1;
|
||||
|
||||
new_mainlist->fn_fieldlist.fn_fields =
|
||||
(struct fn_field *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct fn_field) * length);
|
||||
TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) =
|
||||
(int *) obstack_alloc (symbol_obstack,
|
||||
sizeof (int) * (1 + (length >> 5)));
|
||||
|
||||
TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
|
||||
(int *) obstack_alloc (symbol_obstack,
|
||||
sizeof (int) * (1 + (length >> 5)));
|
||||
|
||||
for (i = length; sublist; sublist = sublist->next)
|
||||
{
|
||||
new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field;
|
||||
if (sublist->visibility == 0)
|
||||
B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i);
|
||||
else if (sublist->visibility == 1)
|
||||
B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i);
|
||||
}
|
||||
|
||||
new_mainlist->fn_fieldlist.length = length;
|
||||
new_mainlist->next = mainlist;
|
||||
mainlist = new_mainlist;
|
||||
nfn_fields++;
|
||||
}
|
||||
while (**pp != ';');
|
||||
}
|
||||
*pp += 1;
|
||||
|
||||
/* Now create the vector of fields, and record how big it is. */
|
||||
|
||||
TYPE_NFIELDS (type) = nfields;
|
||||
TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct field) * nfields);
|
||||
TYPE_FIELD_PRIVATE_BITS (type) =
|
||||
(int *) obstack_alloc (symbol_obstack,
|
||||
sizeof (int) * (1 + (nfields >> 5)));
|
||||
TYPE_FIELD_PROTECTED_BITS (type) =
|
||||
(int *) obstack_alloc (symbol_obstack,
|
||||
sizeof (int) * (1 + (nfields >> 5)));
|
||||
|
||||
TYPE_NFN_FIELDS (type) = nfn_fields;
|
||||
TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields;
|
||||
if (baseclass)
|
||||
TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass);
|
||||
|
||||
TYPE_FN_FIELDLISTS (type) =
|
||||
(struct fn_fieldlist *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct fn_fieldlist) * nfn_fields);
|
||||
|
||||
/* Copy the saved-up fields into the field vector. */
|
||||
|
||||
for (n = nfields; list; list = list->next)
|
||||
TYPE_FIELD (type, --n) = list->field;
|
||||
{
|
||||
TYPE_FIELD (type, --n) = list->field;
|
||||
if (list->visibility == 0)
|
||||
SET_TYPE_FIELD_PRIVATE (type, n);
|
||||
else if (list->visibility == 1)
|
||||
SET_TYPE_FIELD_PROTECTED (type, n);
|
||||
}
|
||||
|
||||
for (n = nfn_fields; mainlist; mainlist = mainlist->next)
|
||||
TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist;
|
||||
|
||||
if (**pp == '~')
|
||||
{
|
||||
*pp += 1;
|
||||
|
||||
if (**pp == '=')
|
||||
{
|
||||
TYPE_FLAGS (type)
|
||||
|= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
|
||||
*pp += 1;
|
||||
}
|
||||
else if (**pp == '+')
|
||||
{
|
||||
TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
|
||||
*pp += 1;
|
||||
}
|
||||
else if (**pp == '-')
|
||||
{
|
||||
TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
|
||||
*pp += 1;
|
||||
}
|
||||
|
||||
/* Read either a '%' or the final ';'. */
|
||||
if (*(*pp)++ == '%')
|
||||
{
|
||||
/* Now we must record the virtual function table pointer's
|
||||
field information. */
|
||||
|
||||
struct type *t;
|
||||
int i;
|
||||
|
||||
t = read_type (pp);
|
||||
p = (*pp)++;
|
||||
while (*p != ';') p++;
|
||||
TYPE_VPTR_BASETYPE (type) = t;
|
||||
if (type == t)
|
||||
{
|
||||
if (TYPE_FIELD_NAME (t, 0) == 0)
|
||||
TYPE_VPTR_FIELDNO (type) = i = 0;
|
||||
else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i)
|
||||
if (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
|
||||
strlen (TYPE_FIELD_NAME (t, i))))
|
||||
{
|
||||
TYPE_VPTR_FIELDNO (type) = i;
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
error ("virtual function table field not found");
|
||||
}
|
||||
else
|
||||
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1));
|
||||
*pp = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TYPE_VPTR_BASETYPE (type) = 0;
|
||||
TYPE_VPTR_FIELDNO (type) = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TYPE_VPTR_BASETYPE (type) = 0;
|
||||
TYPE_VPTR_FIELDNO (type) = -1;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
@ -2309,8 +3007,7 @@ read_enum_type (pp, type)
|
|||
while (**pp && **pp != ';')
|
||||
{
|
||||
/* Check for and handle cretinous dbx symbol name continuation! */
|
||||
if (**pp == '\\')
|
||||
*pp = next_symbol_text ();
|
||||
if (**pp == '\\') *pp = next_symbol_text ();
|
||||
|
||||
p = *pp;
|
||||
while (*p != ':') p++;
|
||||
|
@ -2492,6 +3189,57 @@ read_number (pp, end)
|
|||
return n * sign;
|
||||
}
|
||||
|
||||
/* Read in an argument list. This is a list of types. It is terminated with
|
||||
a ':', FYI. Return the list of types read in. */
|
||||
static struct type **
|
||||
read_args (pp, end)
|
||||
char **pp;
|
||||
int end;
|
||||
{
|
||||
struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
|
||||
int n = 0;
|
||||
|
||||
while (**pp != end)
|
||||
{
|
||||
if (**pp != ',')
|
||||
error ("Invalid argument list: no ',', at symtab pos %d", symnum);
|
||||
*pp += 1;
|
||||
/* Check for and handle cretinous dbx symbol name continuation! */
|
||||
if (**pp == '\\')
|
||||
*pp = next_symbol_text ();
|
||||
|
||||
types[n++] = read_type (pp);
|
||||
}
|
||||
*pp += 1; /* get past `end' (the ':' character) */
|
||||
|
||||
if (n == 1)
|
||||
{
|
||||
rval = (struct type **) xmalloc (2 * sizeof (struct type *));
|
||||
}
|
||||
else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
|
||||
{
|
||||
rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
|
||||
bzero (rval + n, sizeof (struct type *));
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = (struct type **) xmalloc (n * sizeof (struct type *));
|
||||
}
|
||||
bcopy (types, rval, n * sizeof (struct type *));
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* This function is really horrible, but to avoid it, there would need
|
||||
to be more filling in of forward references. */
|
||||
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);
|
||||
}
|
||||
|
||||
static
|
||||
initialize ()
|
||||
{
|
||||
|
@ -2499,6 +3247,9 @@ initialize ()
|
|||
|
||||
add_com ("symbol-file", class_files, symbol_file_command,
|
||||
"Load symbol table (in dbx format) from executable file FILE.");
|
||||
|
||||
add_com ("add-file", class_files, add_file_command,
|
||||
"Load the symbols from FILE, assuming its codes is at TEXT_START.") ;
|
||||
}
|
||||
|
||||
END_FILE
|
||||
|
|
|
@ -26,7 +26,6 @@ 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[];
|
||||
|
||||
|
@ -78,3 +77,7 @@ struct command_line *read_command_lines ();
|
|||
/* String containing the current directory (what getwd would return). */
|
||||
|
||||
char *current_directory;
|
||||
|
||||
#ifdef sparc
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
|
494
gdb/eval.c
494
gdb/eval.c
|
@ -114,7 +114,7 @@ evaluate_expression (exp)
|
|||
struct expression *exp;
|
||||
{
|
||||
int pc = 0;
|
||||
return evaluate_subexp (exp, &pc, EVAL_NORMAL);
|
||||
return evaluate_subexp (0, exp, &pc, EVAL_NORMAL);
|
||||
}
|
||||
|
||||
/* Evaluate an expression, avoiding all memory references
|
||||
|
@ -125,19 +125,20 @@ evaluate_type (exp)
|
|||
struct expression *exp;
|
||||
{
|
||||
int pc = 0;
|
||||
return evaluate_subexp (exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
|
||||
return evaluate_subexp (0, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
|
||||
}
|
||||
|
||||
static value
|
||||
evaluate_subexp (exp, pos, noside)
|
||||
evaluate_subexp (expect_type, exp, pos, noside)
|
||||
struct type *expect_type;
|
||||
register struct expression *exp;
|
||||
register int *pos;
|
||||
enum noside noside;
|
||||
{
|
||||
enum exp_opcode op;
|
||||
int tem;
|
||||
register int pc;
|
||||
register value arg1, arg2;
|
||||
register int pc, pc2, *oldpos;
|
||||
register value arg1, arg2, arg3;
|
||||
int nargs;
|
||||
value *argvec;
|
||||
|
||||
|
@ -146,6 +147,12 @@ evaluate_subexp (exp, pos, noside)
|
|||
|
||||
switch (op)
|
||||
{
|
||||
case OP_SCOPE:
|
||||
tem = strlen (&exp->elts[pc + 2].string);
|
||||
(*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
return value_static_field (exp->elts[pc + 1].type,
|
||||
&exp->elts[pc + 2].string, -1);
|
||||
|
||||
case OP_LONG:
|
||||
(*pos) += 3;
|
||||
return value_from_long (exp->elts[pc + 1].type,
|
||||
|
@ -176,13 +183,131 @@ evaluate_subexp (exp, pos, noside)
|
|||
|
||||
case OP_FUNCALL:
|
||||
(*pos) += 2;
|
||||
nargs = exp->elts[pc + 1].longconst;
|
||||
argvec = (value *) alloca (sizeof (value) * (nargs + 1));
|
||||
for (tem = 0; tem <= nargs; tem++)
|
||||
op = exp->elts[*pos].opcode;
|
||||
if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
|
||||
{
|
||||
int fnptr;
|
||||
int tem2;
|
||||
|
||||
nargs = exp->elts[pc + 1].longconst + 1;
|
||||
/* First, evaluate the structure into arg2 */
|
||||
pc2 = (*pos)++;
|
||||
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
|
||||
if (op == STRUCTOP_MEMBER)
|
||||
{
|
||||
arg2 = evaluate_subexp_for_address (exp, pos, noside);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
}
|
||||
|
||||
/* If the function is a virtual function, then the
|
||||
aggregate value (providing the structure) plays
|
||||
its part by providing the vtable. Otherwise,
|
||||
it is just along for the ride: call the function
|
||||
directly. */
|
||||
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
|
||||
fnptr = value_as_long (arg1);
|
||||
if (fnptr < 128)
|
||||
{
|
||||
struct type *basetype;
|
||||
int i, j;
|
||||
basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
|
||||
basetype = TYPE_VPTR_BASETYPE (basetype);
|
||||
for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
|
||||
{
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
|
||||
/* If one is virtual, then all are virtual. */
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
|
||||
for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
|
||||
if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr)
|
||||
{
|
||||
value vtbl;
|
||||
value base = value_ind (arg2);
|
||||
struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
|
||||
|
||||
if (TYPE_VPTR_FIELDNO (basetype) < 0)
|
||||
TYPE_VPTR_FIELDNO (basetype)
|
||||
= fill_in_vptr_fieldno (basetype);
|
||||
|
||||
VALUE_TYPE (base) = basetype;
|
||||
vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
|
||||
VALUE_TYPE (vtbl) = lookup_pointer_type (fntype);
|
||||
VALUE_TYPE (arg1) = builtin_type_int;
|
||||
arg1 = value_subscript (vtbl, arg1);
|
||||
VALUE_TYPE (arg1) = fntype;
|
||||
goto got_it;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
error ("virtual function at index %d not found", fnptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
|
||||
}
|
||||
got_it:
|
||||
|
||||
/* Now, say which argument to start evaluating from */
|
||||
tem = 2;
|
||||
}
|
||||
else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
|
||||
{
|
||||
/* Hair for method invocations */
|
||||
int tem2;
|
||||
|
||||
nargs = exp->elts[pc + 1].longconst + 1;
|
||||
/* First, evaluate the structure into arg2 */
|
||||
pc2 = (*pos)++;
|
||||
tem2 = strlen (&exp->elts[pc2 + 1].string);
|
||||
*pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
|
||||
if (op == STRUCTOP_STRUCT)
|
||||
{
|
||||
arg2 = evaluate_subexp_for_address (exp, pos, noside);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
}
|
||||
/* Now, say which argument to start evaluating from */
|
||||
tem = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
nargs = exp->elts[pc + 1].longconst;
|
||||
tem = 0;
|
||||
}
|
||||
argvec = (value *) alloca (sizeof (value) * (nargs + 2));
|
||||
for (; tem <= nargs; tem++)
|
||||
/* Ensure that array expressions are coerced into pointer objects. */
|
||||
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
|
||||
/* signal end of arglist */
|
||||
argvec[tem] = 0;
|
||||
|
||||
if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
|
||||
{
|
||||
argvec[1] = arg2;
|
||||
argvec[0] =
|
||||
value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
|
||||
op == STRUCTOP_STRUCT
|
||||
? "structure" : "structure pointer");
|
||||
}
|
||||
else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
|
||||
{
|
||||
argvec[1] = arg2;
|
||||
argvec[0] = arg1;
|
||||
}
|
||||
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
|
@ -198,52 +323,79 @@ evaluate_subexp (exp, pos, noside)
|
|||
|
||||
case TERNOP_COND:
|
||||
/* Skip third and second args to evaluate the first one. */
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (value_zerop (arg1))
|
||||
{
|
||||
evaluate_subexp (exp, pos, EVAL_SKIP);
|
||||
return evaluate_subexp (exp, pos, noside);
|
||||
evaluate_subexp (0, exp, pos, EVAL_SKIP);
|
||||
return evaluate_subexp (0, exp, pos, noside);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
evaluate_subexp (exp, pos, EVAL_SKIP);
|
||||
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);
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
|
||||
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
|
||||
"structure");
|
||||
|
||||
case STRUCTOP_PTR:
|
||||
tem = strlen (&exp->elts[pc + 1].string);
|
||||
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
|
||||
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
|
||||
"structure pointer");
|
||||
|
||||
case STRUCTOP_MEMBER:
|
||||
arg1 = evaluate_subexp_for_address (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
/* Now, convert these values to an address. */
|
||||
arg3 = value_from_long (builtin_type_long,
|
||||
value_as_long (arg1) + value_as_long (arg2));
|
||||
VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
|
||||
return value_ind (arg3);
|
||||
|
||||
case STRUCTOP_MPTR:
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
/* Now, convert these values to an address. */
|
||||
arg3 = value_from_long (builtin_type_long,
|
||||
value_as_long (arg1) + value_as_long (arg2));
|
||||
VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
|
||||
return value_ind (arg3);
|
||||
|
||||
case BINOP_ASSIGN:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
return value_assign (arg1, arg2);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_assign (arg1, arg2);
|
||||
|
||||
case BINOP_ASSIGN_MODIFY:
|
||||
(*pos) += 2;
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
op = exp->elts[pc + 1].opcode;
|
||||
if (op == BINOP_ADD)
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op);
|
||||
else if (op == BINOP_ADD)
|
||||
arg2 = value_add (arg1, arg2);
|
||||
else if (op == BINOP_SUB)
|
||||
arg2 = value_sub (arg1, arg2);
|
||||
|
@ -256,14 +408,20 @@ evaluate_subexp (exp, pos, noside)
|
|||
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_add (arg1, arg2);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_add (arg1, arg2);
|
||||
|
||||
case BINOP_SUB:
|
||||
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_sub (arg1, arg2);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_sub (arg1, arg2);
|
||||
|
||||
case BINOP_MUL:
|
||||
case BINOP_DIV:
|
||||
|
@ -273,177 +431,311 @@ evaluate_subexp (exp, pos, noside)
|
|||
case BINOP_LOGAND:
|
||||
case BINOP_LOGIOR:
|
||||
case BINOP_LOGXOR:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_binop (arg1, arg2, op);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_binop (arg1, arg2, op);
|
||||
|
||||
case BINOP_SUBSCRIPT:
|
||||
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_subscript (arg1, arg2, op);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_subscript (arg1, arg2, op);
|
||||
|
||||
case BINOP_AND:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (exp, pos,
|
||||
(tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem && !value_zerop (arg2));
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (0, exp, pos,
|
||||
(tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem && !value_zerop (arg2));
|
||||
}
|
||||
|
||||
case BINOP_OR:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (exp, pos,
|
||||
(!tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem || !value_zerop (arg2));
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (0, exp, pos,
|
||||
(!tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem || !value_zerop (arg2));
|
||||
}
|
||||
|
||||
case BINOP_EQUAL:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
|
||||
case BINOP_NOTEQUAL:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
|
||||
case BINOP_LESS:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
|
||||
case BINOP_GTR:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
|
||||
case BINOP_GEQ:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
|
||||
case BINOP_LEQ:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
if (binop_user_defined_p (op, arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
|
||||
case BINOP_REPEAT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
arg2 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_repeat (arg1, value_as_long (arg2));
|
||||
|
||||
case BINOP_COMMA:
|
||||
evaluate_subexp (exp, pos, noside);
|
||||
return evaluate_subexp (exp, pos, noside);
|
||||
evaluate_subexp (0, exp, pos, noside);
|
||||
return evaluate_subexp (0, exp, pos, noside);
|
||||
|
||||
case UNOP_NEG:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_neg (arg1);
|
||||
if (unop_user_defined_p (op, arg1))
|
||||
return value_x_unop (arg1, op, 0);
|
||||
else
|
||||
return value_neg (arg1);
|
||||
|
||||
case UNOP_LOGNOT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_lognot (arg1);
|
||||
if (unop_user_defined_p (op, arg1))
|
||||
return value_x_unop (arg1, op, 0);
|
||||
else
|
||||
return value_lognot (arg1);
|
||||
|
||||
case UNOP_ZEROP:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (0, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_from_long (builtin_type_int, value_zerop (arg1));
|
||||
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));
|
||||
|
||||
case UNOP_IND:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
|
||||
expect_type = TYPE_TARGET_TYPE (expect_type);
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_ind (arg1);
|
||||
|
||||
case UNOP_ADDR:
|
||||
/* C++: check for and handle pointer to members. */
|
||||
|
||||
op = exp->elts[*pos].opcode;
|
||||
|
||||
if (noside == EVAL_SKIP)
|
||||
{
|
||||
evaluate_subexp (exp, pos, EVAL_SKIP);
|
||||
if (op == OP_SCOPE)
|
||||
{
|
||||
char *name = &exp->elts[pc+3].string;
|
||||
int tem = strlen (name);
|
||||
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
}
|
||||
else
|
||||
evaluate_subexp (expect_type, exp, pos, EVAL_SKIP);
|
||||
goto nosideret;
|
||||
}
|
||||
return evaluate_subexp_for_address (exp, pos, noside);
|
||||
|
||||
if (op == OP_SCOPE)
|
||||
{
|
||||
char *name = &exp->elts[pc+3].string;
|
||||
int tem = strlen (name);
|
||||
struct type *domain = exp->elts[pc+2].type;
|
||||
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
arg1 = value_struct_elt_for_address (domain, expect_type, name);
|
||||
if (arg1)
|
||||
return arg1;
|
||||
error ("no field `%s' in structure", name);
|
||||
}
|
||||
else
|
||||
return evaluate_subexp_for_address (exp, pos, noside);
|
||||
|
||||
case UNOP_SIZEOF:
|
||||
if (noside == EVAL_SKIP)
|
||||
{
|
||||
evaluate_subexp (exp, pos, EVAL_SKIP);
|
||||
evaluate_subexp (0, exp, pos, EVAL_SKIP);
|
||||
goto nosideret;
|
||||
}
|
||||
return evaluate_subexp_for_sizeof (exp, pos);
|
||||
|
||||
case UNOP_CAST:
|
||||
(*pos) += 2;
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_cast (exp->elts[pc + 1].type, arg1);
|
||||
|
||||
case UNOP_MEMVAL:
|
||||
(*pos) += 2;
|
||||
arg1 = evaluate_subexp (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));
|
||||
|
||||
case UNOP_PREINCREMENT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
return value_assign (arg1, arg2);
|
||||
else if (unop_user_defined_p (op, arg1))
|
||||
{
|
||||
return value_x_unop (arg1, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
|
||||
return value_assign (arg1, arg2);
|
||||
}
|
||||
|
||||
case UNOP_PREDECREMENT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
return value_assign (arg1, arg2);
|
||||
else if (unop_user_defined_p (op, arg1))
|
||||
{
|
||||
return value_x_unop (arg1, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
|
||||
return value_assign (arg1, arg2);
|
||||
}
|
||||
|
||||
case UNOP_POSTINCREMENT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
value_assign (arg1, arg2);
|
||||
return arg1;
|
||||
else if (unop_user_defined_p (op, arg1))
|
||||
{
|
||||
return value_x_unop (arg1, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
|
||||
value_assign (arg1, arg2);
|
||||
return arg1;
|
||||
}
|
||||
|
||||
case UNOP_POSTDECREMENT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
|
||||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
value_assign (arg1, arg2);
|
||||
return arg1;
|
||||
else if (unop_user_defined_p (op, arg1))
|
||||
{
|
||||
return value_x_unop (arg1, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
|
||||
value_assign (arg1, arg2);
|
||||
return arg1;
|
||||
}
|
||||
|
||||
case OP_THIS:
|
||||
(*pos) += 1;
|
||||
return value_of_this (1);
|
||||
|
||||
default:
|
||||
error ("internal error: I dont know how to evaluation what you gave me");
|
||||
}
|
||||
|
||||
nosideret:
|
||||
|
@ -473,19 +765,19 @@ evaluate_subexp_for_address (exp, pos, noside)
|
|||
{
|
||||
case UNOP_IND:
|
||||
(*pos)++;
|
||||
return evaluate_subexp (exp, pos, noside);
|
||||
return evaluate_subexp (0, exp, pos, noside);
|
||||
|
||||
case UNOP_MEMVAL:
|
||||
(*pos) += 3;
|
||||
return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
|
||||
evaluate_subexp (exp, pos, noside));
|
||||
evaluate_subexp (0, exp, pos, noside));
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
(*pos) += 3;
|
||||
return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
|
||||
|
||||
default:
|
||||
return value_addr (evaluate_subexp (exp, pos, noside));
|
||||
return value_addr (evaluate_subexp (0, exp, pos, noside));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,7 +811,7 @@ evaluate_subexp_with_coercion (exp, pos, noside)
|
|||
}
|
||||
}
|
||||
|
||||
return evaluate_subexp (exp, pos, noside);
|
||||
return evaluate_subexp (0, exp, pos, noside);
|
||||
}
|
||||
|
||||
/* Evaluate a subexpression of EXP, at index *POS,
|
||||
|
@ -546,7 +838,7 @@ evaluate_subexp_for_sizeof (exp, pos)
|
|||
create a value unnecessarily. */
|
||||
case UNOP_IND:
|
||||
(*pos)++;
|
||||
val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
|
||||
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))));
|
||||
|
||||
|
@ -561,7 +853,7 @@ evaluate_subexp_for_sizeof (exp, pos)
|
|||
TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
|
||||
|
||||
default:
|
||||
val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
|
||||
val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
|
||||
return value_from_long (builtin_type_int,
|
||||
TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
}
|
||||
|
|
1608
gdb/expread.tab.c
Normal file
1608
gdb/expread.tab.c
Normal file
File diff suppressed because it is too large
Load diff
223
gdb/expread.y
223
gdb/expread.y
|
@ -43,6 +43,7 @@ static int expout_ptr;
|
|||
static int yylex ();
|
||||
static yyerror ();
|
||||
static void write_exp_elt ();
|
||||
static void write_exp_elt2 ();
|
||||
static void write_exp_string ();
|
||||
static void start_arglist ();
|
||||
static int end_arglist ();
|
||||
|
@ -93,10 +94,14 @@ struct stoken
|
|||
struct block *bval;
|
||||
enum exp_opcode opcode;
|
||||
struct internalvar *ivar;
|
||||
|
||||
struct type **tvec;
|
||||
int *ivec;
|
||||
}
|
||||
|
||||
%type <voidval> exp exp1 start variable
|
||||
%type <tval> type typebase
|
||||
%type <tvec> nonempty_typelist
|
||||
%type <bval> block
|
||||
|
||||
%token <lval> INT CHAR
|
||||
|
@ -122,6 +127,9 @@ struct stoken
|
|||
|
||||
%token <opcode> ASSIGN_MODIFY
|
||||
|
||||
/* C++ */
|
||||
%token THIS
|
||||
|
||||
%left ','
|
||||
%left ABOVE_COMMA
|
||||
%right '=' ASSIGN_MODIFY
|
||||
|
@ -196,12 +204,20 @@ exp : exp ARROW name
|
|||
write_exp_elt (STRUCTOP_PTR); }
|
||||
;
|
||||
|
||||
exp : exp ARROW '*' exp
|
||||
{ write_exp_elt (STRUCTOP_MPTR); }
|
||||
;
|
||||
|
||||
exp : exp '.' name
|
||||
{ write_exp_elt (STRUCTOP_STRUCT);
|
||||
write_exp_string ($3);
|
||||
write_exp_elt (STRUCTOP_STRUCT); }
|
||||
;
|
||||
|
||||
exp : exp '.' '*' exp
|
||||
{ write_exp_elt (STRUCTOP_MEMBER); }
|
||||
;
|
||||
|
||||
exp : exp '[' exp1 ']'
|
||||
{ write_exp_elt (BINOP_SUBSCRIPT); }
|
||||
;
|
||||
|
@ -352,7 +368,7 @@ exp : CHAR
|
|||
exp : FLOAT
|
||||
{ write_exp_elt (OP_DOUBLE);
|
||||
write_exp_elt (builtin_type_double);
|
||||
write_exp_elt ($1);
|
||||
write_exp_elt2 ($1);
|
||||
write_exp_elt (OP_DOUBLE); }
|
||||
;
|
||||
|
||||
|
@ -390,8 +406,17 @@ exp : STRING
|
|||
write_exp_elt (OP_STRING); }
|
||||
;
|
||||
|
||||
/* C++. */
|
||||
exp : THIS
|
||||
{ write_exp_elt (OP_THIS);
|
||||
write_exp_elt (OP_THIS); }
|
||||
;
|
||||
|
||||
/* end of C++. */
|
||||
|
||||
block : name
|
||||
{ struct symtab *tem = lookup_symtab (copy_name ($1));
|
||||
{
|
||||
struct symtab *tem = lookup_symtab (copy_name ($1));
|
||||
struct symbol *sym;
|
||||
|
||||
if (tem)
|
||||
|
@ -406,34 +431,88 @@ block : name
|
|||
else
|
||||
error ("No file or function \"%s\".",
|
||||
copy_name ($1));
|
||||
}}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
block : block COLONCOLON name
|
||||
{ struct symbol *tem
|
||||
{
|
||||
struct symbol *tem
|
||||
= lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
|
||||
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;
|
||||
{
|
||||
struct symbol *sym;
|
||||
sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE);
|
||||
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 (OP_VAR_VALUE);
|
||||
}
|
||||
;
|
||||
|
||||
variable: typebase COLONCOLON name
|
||||
{
|
||||
struct type *type = $1;
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
error ("`%s' is not defined as an aggregate type.",
|
||||
TYPE_NAME (type));
|
||||
|
||||
write_exp_elt (OP_SCOPE);
|
||||
write_exp_elt (type);
|
||||
write_exp_string ($3);
|
||||
write_exp_elt (OP_SCOPE);
|
||||
}
|
||||
| COLONCOLON name
|
||||
{
|
||||
char *name = copy_name ($2);
|
||||
struct symbol *sym;
|
||||
int i;
|
||||
|
||||
sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE);
|
||||
if (sym)
|
||||
{
|
||||
write_exp_elt (OP_VAR_VALUE);
|
||||
write_exp_elt (sym);
|
||||
write_exp_elt (OP_VAR_VALUE);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < misc_function_count; i++)
|
||||
if (!strcmp (misc_function_vector[i].name, name))
|
||||
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);
|
||||
}
|
||||
else
|
||||
if (symtab_list == 0)
|
||||
error ("No symbol table is loaded. Use the \"symbol-file\" command.");
|
||||
else
|
||||
error ("No symbol \"%s\" in current context.", name);
|
||||
}
|
||||
;
|
||||
|
||||
variable: NAME
|
||||
{ struct symbol *sym;
|
||||
sym = lookup_symbol (copy_name ($1),
|
||||
expression_context_block,
|
||||
VAR_NAMESPACE);
|
||||
sym = lookup_symbol_1 (copy_name ($1),
|
||||
expression_context_block,
|
||||
VAR_NAMESPACE);
|
||||
if (sym)
|
||||
{
|
||||
write_exp_elt (OP_VAR_VALUE);
|
||||
|
@ -444,6 +523,32 @@ variable: NAME
|
|||
{
|
||||
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 */
|
||||
}
|
||||
for (i = 0; i < misc_function_count; i++)
|
||||
if (!strcmp (misc_function_vector[i].name, arg))
|
||||
break;
|
||||
|
@ -471,6 +576,17 @@ variable: NAME
|
|||
type : typebase
|
||||
| type '*'
|
||||
{ $$ = lookup_pointer_type ($1); }
|
||||
| type '&'
|
||||
{ $$ = lookup_reference_type ($1); }
|
||||
| typebase COLONCOLON '*'
|
||||
{ $$ = lookup_member_type (builtin_type_int, $1); }
|
||||
| type '(' typebase COLONCOLON '*' ')'
|
||||
{ $$ = lookup_member_type ($1, $3); }
|
||||
| type '(' typebase COLONCOLON '*' ')' '(' ')'
|
||||
{ $$ = lookup_member_type (lookup_function_type ($1, 0), $3); }
|
||||
| type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
|
||||
{ $$ = lookup_member_type (lookup_function_type ($1, $8), $3);
|
||||
free ($8); }
|
||||
;
|
||||
|
||||
typebase
|
||||
|
@ -490,6 +606,19 @@ typebase
|
|||
{ $$ = lookup_unsigned_typename (copy_name ($2)); }
|
||||
;
|
||||
|
||||
nonempty_typelist
|
||||
: type
|
||||
{ $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
|
||||
$$[0] = (struct type *)0;
|
||||
$$[1] = $1;
|
||||
}
|
||||
| nonempty_typelist ',' type
|
||||
{ int len = sizeof (struct type *) * ++($<ivec>1[0]);
|
||||
$$ = (struct type **)xrealloc ($1, len);
|
||||
$$[$<ivec>$[0]] = $3;
|
||||
}
|
||||
;
|
||||
|
||||
name : NAME
|
||||
| TYPENAME
|
||||
;
|
||||
|
@ -543,10 +672,16 @@ 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. */
|
||||
static void
|
||||
write_exp_elt (expelt)
|
||||
union exp_element expelt;
|
||||
/* union exp_element expelt; */
|
||||
long expelt;
|
||||
{
|
||||
union exp_element temp;
|
||||
temp.longconst = expelt;
|
||||
|
||||
if (expout_ptr >= expout_size)
|
||||
{
|
||||
expout_size *= 2;
|
||||
|
@ -554,7 +689,25 @@ write_exp_elt (expelt)
|
|||
sizeof (struct expression)
|
||||
+ expout_size * sizeof (union exp_element));
|
||||
}
|
||||
expout->elts[expout_ptr++] = expelt;
|
||||
expout->elts[expout_ptr++] = /* expelt */ temp;
|
||||
}
|
||||
|
||||
/* Things that take more space must come through here. */
|
||||
static void
|
||||
write_exp_elt2 (expelt)
|
||||
double expelt;
|
||||
{
|
||||
union exp_element temp;
|
||||
temp.doubleconst = expelt;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Add a string constant to the end of the expression.
|
||||
|
@ -904,13 +1057,23 @@ yylex ()
|
|||
{
|
||||
return STRUCT;
|
||||
}
|
||||
if (namelen == 5 && !strncmp (tokstart, "union", 5))
|
||||
if (namelen == 5)
|
||||
{
|
||||
return UNION;
|
||||
if (!strncmp (tokstart, "union", 5))
|
||||
{
|
||||
return UNION;
|
||||
}
|
||||
}
|
||||
if (namelen == 4 && !strncmp (tokstart, "enum", 4))
|
||||
if (namelen == 4)
|
||||
{
|
||||
return ENUM;
|
||||
if (!strncmp (tokstart, "enum", 4))
|
||||
{
|
||||
return ENUM;
|
||||
}
|
||||
if (!strncmp (tokstart, "this", 4))
|
||||
{
|
||||
return THIS;
|
||||
}
|
||||
}
|
||||
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
|
||||
{
|
||||
|
@ -991,10 +1154,20 @@ length_of_subexp (expr, endpos)
|
|||
register int args = 0;
|
||||
register int i;
|
||||
|
||||
if (endpos < 0)
|
||||
error ("?error in length_of_subexp");
|
||||
|
||||
i = (int) expr->elts[endpos - 1].opcode;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
/* C++ */
|
||||
case OP_SCOPE:
|
||||
oplen = 4 + ((expr->elts[endpos - 2].longconst
|
||||
+ sizeof (union exp_element))
|
||||
/ sizeof (union exp_element));
|
||||
break;
|
||||
|
||||
case OP_LONG:
|
||||
case OP_DOUBLE:
|
||||
oplen = 4;
|
||||
|
@ -1025,7 +1198,6 @@ length_of_subexp (expr, endpos)
|
|||
oplen = 3 + ((expr->elts[endpos - 2].longconst
|
||||
+ sizeof (union exp_element))
|
||||
/ sizeof (union exp_element));
|
||||
|
||||
break;
|
||||
|
||||
case TERNOP_COND:
|
||||
|
@ -1037,6 +1209,11 @@ length_of_subexp (expr, endpos)
|
|||
args = 2;
|
||||
break;
|
||||
|
||||
/* C++ */
|
||||
case OP_THIS:
|
||||
oplen = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
args = 1 + (i < (int) BINOP_END);
|
||||
}
|
||||
|
@ -1074,6 +1251,13 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
|
|||
opcode = inexpr->elts[inend - 1].opcode;
|
||||
switch (opcode)
|
||||
{
|
||||
/* C++ */
|
||||
case OP_SCOPE:
|
||||
oplen = 4 + ((inexpr->elts[inend - 2].longconst
|
||||
+ sizeof (union exp_element))
|
||||
/ sizeof (union exp_element));
|
||||
break;
|
||||
|
||||
case OP_LONG:
|
||||
case OP_DOUBLE:
|
||||
oplen = 4;
|
||||
|
@ -1116,6 +1300,11 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
|
|||
args = 2;
|
||||
break;
|
||||
|
||||
/* C++ */
|
||||
case OP_THIS:
|
||||
oplen = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
args = 1 + ((int) opcode < (int) BINOP_END);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,20 @@ enum exp_opcode
|
|||
BINOP_COMMA, /* , */
|
||||
BINOP_SUBSCRIPT, /* x[y] */
|
||||
BINOP_EXP, /* Exponentiation */
|
||||
|
||||
/* C++. */
|
||||
BINOP_MIN, /* <? */
|
||||
BINOP_MAX, /* >? */
|
||||
BINOP_SCOPE, /* :: */
|
||||
|
||||
/* STRUCTOP_MEMBER is used for pointer-to-member constructs.
|
||||
X . * Y translates into X STRUCTOP_MEMBER Y. */
|
||||
STRUCTOP_MEMBER,
|
||||
/* STRUCTOP_MPTR is used for pointer-to-member constructs
|
||||
when X is a pointer instead of an aggregate. */
|
||||
STRUCTOP_MPTR,
|
||||
/* end of C++. */
|
||||
|
||||
BINOP_END,
|
||||
|
||||
BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
|
||||
|
@ -144,6 +158,17 @@ enum exp_opcode
|
|||
(after the string), followed by another STRUCTOP_... code. */
|
||||
STRUCTOP_STRUCT,
|
||||
STRUCTOP_PTR,
|
||||
|
||||
/* C++ */
|
||||
/* OP_THIS is just a placeholder for the class instance variable.
|
||||
It just comes in a tight (OP_THIS, OP_THIS) pair. */
|
||||
OP_THIS,
|
||||
|
||||
/* OP_SCOPE surrounds a type name and a field name. The type
|
||||
name is encoded as one element, but the field name stays as
|
||||
a string, which, of course, is variable length. */
|
||||
OP_SCOPE,
|
||||
|
||||
};
|
||||
|
||||
union exp_element
|
||||
|
|
|
@ -176,6 +176,12 @@ write_register (regno, val)
|
|||
int regno, val;
|
||||
{
|
||||
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
|
||||
#if defined(sun4)
|
||||
/* This is a no-op on a Sun 4. */
|
||||
if (regno == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
*(int *) ®isters[REGISTER_BYTE (regno)] = val;
|
||||
|
||||
if (have_inferior_p ())
|
||||
|
@ -253,6 +259,7 @@ read_var_value (var, frame)
|
|||
return v;
|
||||
|
||||
case LOC_REGISTER:
|
||||
case LOC_REGPARM:
|
||||
{
|
||||
char raw_buffer[MAX_REGISTER_RAW_SIZE];
|
||||
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
|
||||
|
@ -356,6 +363,7 @@ locate_var_value (var, frame)
|
|||
SYMBOL_NAME (var));
|
||||
|
||||
case LOC_REGISTER:
|
||||
case LOC_REGPARM:
|
||||
addr = find_saved_register (frame, val);
|
||||
if (addr != 0)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,10 @@ struct frame_info
|
|||
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;
|
||||
};
|
||||
|
||||
/* Describe the saved registers of a frame. */
|
||||
|
|
243
gdb/gdb.ideas
243
gdb/gdb.ideas
|
@ -1031,247 +1031,4 @@ if the symbols proved not to be static,
|
|||
and an auto-display should be disabled automatically when it is
|
||||
not in the block where the results would be meaningful.
|
||||
|
||||
|
||||
1,,
|
||||
Received: from ai.ai.mit.edu by wheaties.ai.mit.edu; Sun, 8 May 88 12:52:31 EDT
|
||||
Received: from prep.ai.mit.edu (TCP 20015020016) by AI.AI.MIT.EDU 8 May 88 05:38:21 EDT
|
||||
Received: from lilac.Berkeley.EDU by prep.ai.mit.edu; Sun, 8 May 88 04:12:02 EST
|
||||
Received: from web5h.berkeley.edu
|
||||
by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.18)
|
||||
id AA27424; Sun, 8 May 88 02:33:06 PDT
|
||||
Received: by web5h.berkeley.edu (3.2/SMI-3.0DEV3.8MXl)
|
||||
id AA05599; Sun, 8 May 88 02:33:41 PDT
|
||||
Date: Sun, 8 May 88 02:33:41 PDT
|
||||
From: phr%widow.Berkeley.EDU@lilac.berkeley.edu
|
||||
Message-Id: <8805080933.AA05599@web5h.berkeley.edu>
|
||||
To: bug-gdb@prep.ai.mit.edu
|
||||
Subject: suggestion (gdb 2.4): print function names
|
||||
|
||||
*** EOOH ***
|
||||
Date: Sun, 8 May 88 02:33:41 PDT
|
||||
From: phr%widow.Berkeley.EDU@lilac.berkeley.edu
|
||||
To: bug-gdb@prep.ai.mit.edu
|
||||
Subject: suggestion (gdb 2.4): print function names
|
||||
|
||||
If p is a pointer to function, "print p" should print the name
|
||||
of the function that p points to, as well as the numeric value.
|
||||
Dbx does this.
|
||||
|
||||
|
||||
|
||||
1,,
|
||||
Received: from lilac.berkeley.edu by wheaties.ai.mit.edu; Wed, 11 May 88 23:14:39 EDT
|
||||
Received: from web8e.berkeley.edu
|
||||
by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.18)
|
||||
id AA11864; Wed, 11 May 88 20:11:12 PDT
|
||||
Received: by web8e.berkeley.edu (3.2/SMI-3.0DEV3.8MXl)
|
||||
id AA06549; Wed, 11 May 88 20:11:44 PDT
|
||||
Date: Wed, 11 May 88 20:11:44 PDT
|
||||
From: phr%widow.Berkeley.EDU@lilac.berkeley.edu
|
||||
Message-Id: <8805120311.AA06549@web8e.berkeley.edu>
|
||||
To: rms@wheaties.ai.mit.edu
|
||||
Subject: gdb suggestion
|
||||
|
||||
*** EOOH ***
|
||||
Date: Wed, 11 May 88 20:11:44 PDT
|
||||
From: phr%widow.Berkeley.EDU@lilac.berkeley.edu
|
||||
To: rms@wheaties.ai.mit.edu
|
||||
Subject: gdb suggestion
|
||||
|
||||
If the process signal mask of a program is saved in the core dump,
|
||||
then gdb should have a way to read it. I have an xemacs that hangs
|
||||
in a blocking read from XCreateWindow when I run it from the csh,
|
||||
but works fine when run under gdb. (Does this mean a gdb bug?).
|
||||
|
||||
|
||||
1, answered,,
|
||||
Return-Path: <tmb@wheaties.ai.mit.edu>
|
||||
Received: by sugar-smacks.ai.mit.edu; Tue, 24 May 88 00:34:01 EDT
|
||||
Date: Tue, 24 May 88 00:34:01 EDT
|
||||
From: tmb@wheaties.ai.mit.edu (Thomas M. Breuel)
|
||||
Message-Id: <8805240434.AA02268@sugar-smacks.ai.mit.edu>
|
||||
To: rms
|
||||
Subject: problem with gdb...
|
||||
|
||||
*** EOOH ***
|
||||
Return-Path: <tmb@wheaties.ai.mit.edu>
|
||||
Date: Tue, 24 May 88 00:34:01 EDT
|
||||
From: tmb@wheaties.ai.mit.edu (Thomas M. Breuel)
|
||||
To: rms
|
||||
Subject: problem with gdb...
|
||||
|
||||
When tracing a program that forks, the breakpoints aren't removed in the
|
||||
child and it dies with a trace/bpt trap. Isn't there a more proper way to
|
||||
handle this?
|
||||
|
||||
Thomas.
|
||||
|
||||
|
||||
1, forwarded, answered,,
|
||||
Received: from ATHENA (ATHENA.MIT.EDU) by wheaties.ai.mit.edu; Sat, 25 Jun 88 04:02:57 EDT
|
||||
From: jbs@athena.mit.edu
|
||||
Received: by ATHENA.MIT.EDU (5.45/4.7) id AA21892; Sat, 25 Jun 88 04:00:11 EDT
|
||||
Received: by BRIDGETOWN.MIT.EDU (5.45/4.7) id AA13640; Sat, 25 Jun 88 03:59:57 EDT
|
||||
Date: Sat, 25 Jun 88 03:59:57 EDT
|
||||
Message-Id: <8806250759.AA13640@BRIDGETOWN.MIT.EDU>
|
||||
To: rms@wheaties.ai.mit.edu
|
||||
Subject: gdb suggestion
|
||||
|
||||
*** EOOH ***
|
||||
From: jbs@athena.mit.edu
|
||||
Date: Sat, 25 Jun 88 03:59:57 EDT
|
||||
To: rms@wheaties.ai.mit.edu
|
||||
Subject: gdb suggestion
|
||||
|
||||
Debugging X toolkit stuff involves looking at structures that fill up
|
||||
several screens. GDB would be a lot easier to use if it supported
|
||||
some sort of pretty-printing of these structures.
|
||||
|
||||
Jeff
|
||||
|
||||
|
||||
1, forwarded,,
|
||||
Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Thu, 23 Jun 88 04:32:12 EDT
|
||||
Received: from ic.Berkeley.EDU by prep.ai.mit.edu; Thu, 23 Jun 88 03:19:27 EST
|
||||
Received: by ic.berkeley.edu (5.57/1.28)
|
||||
id AA02077; Thu, 23 Jun 88 01:28:08 PDT
|
||||
Date: Thu, 23 Jun 88 01:28:08 PDT
|
||||
From: faustus@ic.berkeley.edu (Wayne A. Christopher)
|
||||
Message-Id: <8806230828.AA02077@ic.berkeley.edu>
|
||||
To: rms@prep.ai.mit.edu
|
||||
Subject: gdb request
|
||||
|
||||
*** EOOH ***
|
||||
Date: Thu, 23 Jun 88 01:28:08 PDT
|
||||
From: faustus@ic.berkeley.edu (Wayne A. Christopher)
|
||||
To: rms@prep.ai.mit.edu
|
||||
Subject: gdb request
|
||||
|
||||
One suggestion for future versions of gdb -- the trace command of dbx is very
|
||||
useful, and a lot easier to use than the "commands" feature in gdb. Although
|
||||
it's not necessary, it would be nice to have it.
|
||||
|
||||
Wayne
|
||||
|
||||
|
||||
1, forwarded,,
|
||||
Return-Path: <faustus@scruff.berkeley.edu>
|
||||
Received: from prep.ai.mit.edu by life.ai.mit.edu; Sun, 24 Jul 88 03:40:33 EDT
|
||||
Received: from scruff.Berkeley.EDU by prep.ai.mit.edu; Sun, 24 Jul 88 02:17:27 EST
|
||||
Received: by scruff.berkeley.edu (5.57/1.28)
|
||||
id AA19389; Sun, 24 Jul 88 00:35:41 PDT
|
||||
Date: Sun, 24 Jul 88 00:35:41 PDT
|
||||
From: faustus@scruff.berkeley.edu (Wayne A. Christopher)
|
||||
Message-Id: <8807240735.AA19389@scruff.berkeley.edu>
|
||||
To: rms@prep.ai.mit.edu
|
||||
Subject: gdb feature
|
||||
|
||||
*** EOOH ***
|
||||
Return-Path: <faustus@scruff.berkeley.edu>
|
||||
Date: Sun, 24 Jul 88 00:35:41 PDT
|
||||
From: faustus@scruff.berkeley.edu (Wayne A. Christopher)
|
||||
To: rms@prep.ai.mit.edu
|
||||
Subject: gdb feature
|
||||
|
||||
It would be nice if I could stop and background a process running under
|
||||
gdb. Now gdb lets the process get the ^Z and gives me a prompt, instead
|
||||
of stopping also.
|
||||
|
||||
Wayne
|
||||
|
||||
|
||||
1,,
|
||||
Return-Path: <wesommer@athena.mit.edu>
|
||||
Received: from prep.ai.mit.edu by life.ai.mit.edu; Tue, 30 Aug 88 23:18:51 EDT
|
||||
Received: from ATHENA.MIT.EDU by prep.ai.mit.edu; Tue, 30 Aug 88 21:44:58 EST
|
||||
Received: by ATHENA.MIT.EDU (5.45/4.7) id AA29972; Tue, 30 Aug 88 23:16:03 EDT
|
||||
Received: by E40-342A-3 (5.45/4.7)
|
||||
id AA10004; Tue, 30 Aug 88 23:15:58 EDT
|
||||
Date: Tue, 30 Aug 88 23:15:58 EDT
|
||||
From: Bill Sommerfeld <wesommer@athena.mit.edu>
|
||||
Message-Id: <8808310315.AA10004@E40-342A-3>
|
||||
To: bug-gdb@prep.ai.mit.edu
|
||||
Subject: SET_STACK_LIMIT_HUGE.
|
||||
|
||||
*** EOOH ***
|
||||
Return-Path: <wesommer@athena.mit.edu>
|
||||
Date: Tue, 30 Aug 88 23:15:58 EDT
|
||||
From: Bill Sommerfeld <wesommer@athena.mit.edu>
|
||||
To: bug-gdb@prep.ai.mit.edu
|
||||
Subject: SET_STACK_LIMIT_HUGE.
|
||||
|
||||
I just had the pleasure of figuring out why a program which worked
|
||||
under GDB failed (with a segv) when run under the shell. It turns out
|
||||
that it was allocating too much space in the stack, and dying with a
|
||||
segmentation violation when it overran the stack.
|
||||
|
||||
I note that gdb/main.c unlimits the stack, presumably to allow gdb to
|
||||
use alloca to its heart's content. This is well and good, but in the
|
||||
interests of making the execution and debugging environments
|
||||
functionally identical, could it at least set the limit back down to
|
||||
what it used to be when it starts the child process?
|
||||
|
||||
- Bill
|
||||
|
||||
|
||||
1, answered,,
|
||||
Return-Path: <randy@wheaties.ai.mit.edu>
|
||||
Received: from hobbes.ai.mit.edu by wheaties.ai.mit.edu; Thu, 1 Sep 88 23:13:03 EDT
|
||||
Received: from localhost.ARPA by hobbes.ai.mit.edu; Thu, 1 Sep 88 23:08:41 est
|
||||
Message-Id: <8809020408.AA09913@hobbes.ai.mit.edu>
|
||||
To: rms@wheaties.ai.mit.edu (Richard Stallman)
|
||||
Cc: randy@wheaties.ai.mit.edu
|
||||
Subject: Re: GDB work that needs to be done
|
||||
In-Reply-To: Your message of Thu, 01 Sep 88 19:23:47 -0400.
|
||||
<8809012323.AA01639@sugar-bombs.ai.mit.edu>
|
||||
Date: Thu, 01 Sep 88 23:08:39 +0900
|
||||
From: randy@wheaties.ai.mit.edu
|
||||
|
||||
*** EOOH ***
|
||||
Return-Path: <randy@wheaties.ai.mit.edu>
|
||||
To: rms@wheaties.ai.mit.edu (Richard Stallman)
|
||||
Cc: randy@wheaties.ai.mit.edu
|
||||
Subject: Re: GDB work that needs to be done
|
||||
In-Reply-To: Your message of Thu, 01 Sep 88 19:23:47 -0400.
|
||||
<8809012323.AA01639@sugar-bombs.ai.mit.edu>
|
||||
Date: Thu, 01 Sep 88 23:08:39 +0900
|
||||
From: randy@wheaties.ai.mit.edu
|
||||
|
||||
|
||||
Also:
|
||||
|
||||
5. Step until past current line or out of stack frame.
|
||||
|
||||
|
||||
1,,
|
||||
Return-Path: <rms@wheaties.ai.mit.edu>
|
||||
Received: by sugar-bombs.ai.mit.edu; Fri, 2 Sep 88 12:43:28 EDT
|
||||
Date: Fri, 2 Sep 88 12:43:28 EDT
|
||||
From: rms@wheaties.ai.mit.edu (Richard Stallman)
|
||||
Message-Id: <8809021643.AA00263@sugar-bombs.ai.mit.edu>
|
||||
To: randy@wheaties.ai.mit.edu
|
||||
Cc: rms
|
||||
In-Reply-To: randy@wheaties.ai.mit.edu's message of Thu, 01 Sep 88 23:08:39 +0900 <8809020408.AA09913@hobbes.ai.mit.edu>
|
||||
Subject: GDB work that needs to be done
|
||||
|
||||
*** EOOH ***
|
||||
Return-Path: <rms@wheaties.ai.mit.edu>
|
||||
Date: Fri, 2 Sep 88 12:43:28 EDT
|
||||
From: rms@wheaties.ai.mit.edu (Richard Stallman)
|
||||
To: randy@wheaties.ai.mit.edu
|
||||
Cc: rms
|
||||
In-Reply-To: randy@wheaties.ai.mit.edu's message of Thu, 01 Sep 88 23:08:39 +0900 <8809020408.AA09913@hobbes.ai.mit.edu>
|
||||
Subject: GDB work that needs to be done
|
||||
|
||||
Step until past current line or out of stack frame.
|
||||
|
||||
I think this should be a command called `until':
|
||||
|
||||
until LINE run until line LINE.
|
||||
until run until reach the following line.
|
||||
|
||||
It can work by setting a temporary (delete when hit) breakpoint
|
||||
at the specified destination and then doing `finish'.
|
||||
|
||||
|
||||
|
17
gdb/infcmd.c
17
gdb/infcmd.c
|
@ -299,6 +299,7 @@ jump_command (arg, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
register CORE_ADDR addr;
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
|
||||
ERROR_NO_INFERIOR;
|
||||
|
@ -306,7 +307,14 @@ jump_command (arg, from_tty)
|
|||
if (!arg)
|
||||
error_no_arg ("starting address");
|
||||
|
||||
sal = decode_line_spec (arg, 1);
|
||||
sals = decode_line_spec (arg, 1);
|
||||
if (sals.nelts != 1)
|
||||
{
|
||||
error ("Unreasonable jump request");
|
||||
}
|
||||
|
||||
sal = sals.sals[0];
|
||||
free (sals.sals);
|
||||
|
||||
if (sal.symtab == 0 && sal.pc == 0)
|
||||
error ("No source file has been specified.");
|
||||
|
@ -458,7 +466,7 @@ finish_command (arg, from_tty)
|
|||
|
||||
/* Find the function we will return from. */
|
||||
|
||||
fi = get_frame_info (fi.next_frame);
|
||||
fi = get_frame_info (fi.next_frame, fi.next_next_frame);
|
||||
function = find_pc_function (fi.pc);
|
||||
|
||||
if (from_tty)
|
||||
|
@ -613,6 +621,9 @@ write_pc (val)
|
|||
CORE_ADDR val;
|
||||
{
|
||||
write_register (PC_REGNUM, (long) val);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (NPC_REGNUM, (long) val+4);
|
||||
#endif
|
||||
}
|
||||
|
||||
char *reg_names[] = REGISTER_NAMES;
|
||||
|
@ -670,7 +681,7 @@ 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);
|
||||
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))
|
||||
|
|
92
gdb/inflow.c
92
gdb/inflow.c
|
@ -461,7 +461,15 @@ resume (step, signal)
|
|||
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");
|
||||
}
|
||||
|
@ -514,6 +522,7 @@ fetch_inferior_registers ()
|
|||
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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
|
@ -522,6 +531,25 @@ fetch_inferior_registers ()
|
|||
bcopy (&inferior_fp_registers.fps_control,
|
||||
®isters[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, ®isters[REGISTER_BYTE (1)], 15 * 4);
|
||||
bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.fpu_fr);
|
||||
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
|
||||
*(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
|
||||
*(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
|
||||
*(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
|
||||
/* *(int *)®isters[REGISTER_BYTE (RP_REGNUM)] =
|
||||
inferior_registers.r_o7 + 8;
|
||||
bcopy (&inferior_fp_registers.Fpu_fsr,
|
||||
®isters[REGISTER_BYTE (FPS_REGNUM)],
|
||||
sizeof (FPU_FSR_TYPE)); */
|
||||
read_inferior_memory (inferior_registers.r_sp,
|
||||
®isters[REGISTER_BYTE (16)],
|
||||
16*4);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -540,17 +568,61 @@ store_inferior_registers (regno)
|
|||
remote_store_registers (registers);
|
||||
else
|
||||
{
|
||||
bcopy (registers, &inferior_registers, 16 * 4);
|
||||
bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
|
||||
&inferior_fp_registers.fps_control,
|
||||
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
|
||||
int in_regs = 1, in_fpregs = 1, in_fparegs, in_cpregs = 1;
|
||||
|
||||
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
|
||||
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
|
||||
#if defined(sun2) || defined(sun3)
|
||||
if (in_regs)
|
||||
{
|
||||
bcopy (registers, &inferior_registers, 16 * 4);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
}
|
||||
if (in_fpregs)
|
||||
{
|
||||
bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fps_regs);
|
||||
bcopy (®isters[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 (®isters[REGISTER_BYTE (1)], &inferior_registers.r_g1, 15 * 4);
|
||||
inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
inferior_registers.r_npc = *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
|
||||
inferior_registers.r_y = *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
|
||||
write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)],
|
||||
®isters[REGISTER_BYTE (16)],
|
||||
16*4);
|
||||
}
|
||||
if (in_fpregs)
|
||||
{
|
||||
bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof inferior_fp_registers.fpu_fr);
|
||||
/* bcopy (®isters[REGISTER_BYTE (FPS_REGNUM)],
|
||||
&inferior_fp_registers.Fpu_fsr,
|
||||
sizeof (FPU_FSR_TYPE));
|
||||
****/
|
||||
}
|
||||
|
||||
if (in_regs)
|
||||
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
|
||||
if (in_fpregs)
|
||||
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
182
gdb/infrun.c
182
gdb/infrun.c
|
@ -29,7 +29,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#ifdef UMAX_PTRACE
|
||||
#include <sys/param.h>
|
||||
|
@ -117,6 +116,14 @@ static int running_in_shell;
|
|||
|
||||
static int stop_print_frame;
|
||||
|
||||
#ifdef NO_SINGLE_STEP
|
||||
/* Non-zero if we just simulated a single-step ptrace call. This is
|
||||
needed because we cannot remove the breakpoints in the inferior
|
||||
process until after the `wait' in `wait_for_inferior'.
|
||||
Used for sun4. */
|
||||
int one_stepped;
|
||||
#endif /* NO_SINGLE_STEP */
|
||||
|
||||
static void insert_step_breakpoint ();
|
||||
static void remove_step_breakpoint ();
|
||||
static void wait_for_inferior ();
|
||||
|
@ -178,7 +185,12 @@ proceed (addr, signal, step)
|
|||
oneproc = 1;
|
||||
}
|
||||
else
|
||||
write_register (PC_REGNUM, addr);
|
||||
{
|
||||
write_register (PC_REGNUM, addr);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (NPC_REGNUM, addr+4);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (trap_expected_after_continue)
|
||||
{
|
||||
|
@ -351,6 +363,13 @@ wait_for_inferior ()
|
|||
continue;
|
||||
}
|
||||
|
||||
#ifdef NO_SINGLE_STEP
|
||||
if (one_stepped)
|
||||
{
|
||||
single_step (0);
|
||||
}
|
||||
#endif /* NO_SINGLE_STEP */
|
||||
|
||||
pc_changed = 0;
|
||||
fetch_inferior_registers ();
|
||||
stop_pc = read_pc ();
|
||||
|
@ -451,6 +470,9 @@ wait_for_inferior ()
|
|||
{
|
||||
stop_pc -= DECR_PC_AFTER_BREAK;
|
||||
write_register (PC_REGNUM, stop_pc);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (NPC_REGNUM, stop_pc + 4);
|
||||
#endif
|
||||
pc_changed = 0;
|
||||
}
|
||||
}
|
||||
|
@ -463,6 +485,9 @@ wait_for_inferior ()
|
|||
{
|
||||
stop_pc -= DECR_PC_AFTER_BREAK;
|
||||
write_register (PC_REGNUM, stop_pc);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (PC_REGNUM, stop_pc + 4);
|
||||
#endif
|
||||
pc_changed = 0;
|
||||
}
|
||||
}
|
||||
|
@ -766,13 +791,7 @@ Further execution is probably impossible.\n");
|
|||
if (running_in_shell)
|
||||
{
|
||||
if (stop_signal == SIGSEGV)
|
||||
{
|
||||
char *exec_file = (char *) get_exec_file (1);
|
||||
|
||||
if (access (exec_file, X_OK) != 0)
|
||||
printf ("The file \"%s\" is not executable.\n", exec_file);
|
||||
else
|
||||
printf ("\
|
||||
printf ("\
|
||||
You have just encountered a bug in \"sh\". GDB starts your program\n\
|
||||
by running \"sh\" with a command to exec your program.\n\
|
||||
This is so that \"sh\" will process wildcards and I/O redirection.\n\
|
||||
|
@ -784,7 +803,6 @@ some variables whose values are large; then do \"run\" again.\n\
|
|||
\n\
|
||||
If that works, you might want to put those \"unset-env\" commands\n\
|
||||
into a \".gdbinit\" file in this directory so they will happen every time.\n");
|
||||
}
|
||||
/* Don't confuse user with his program's symbols on sh's data. */
|
||||
stop_print_frame = 0;
|
||||
}
|
||||
|
@ -1026,4 +1044,148 @@ Pass and Stop may be combined.");
|
|||
#endif /* SIGURG */
|
||||
}
|
||||
|
||||
#ifdef NO_SINGLE_STEP
|
||||
/* This code was written by Gary Beihl (beihl@mcc.com).
|
||||
It was modified by Michael Tiemann (tiemann@corto.inria.fr). */
|
||||
|
||||
/* Simulate single-step ptrace call for sun4. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
b_error, not_branch, bicc, bicca, ba, baa, ticc, ta,
|
||||
} branch_type;
|
||||
|
||||
static CORE_ADDR next_pc, pc8, target;
|
||||
static int brkpc8, brktrg;
|
||||
typedef char binsn_quantum[sizeof break_insn];
|
||||
static binsn_quantum break_mem[3];
|
||||
|
||||
int
|
||||
single_step (signal)
|
||||
int signal;
|
||||
{
|
||||
branch_type br, isabranch();
|
||||
|
||||
next_pc = read_register (NPC_REGNUM);
|
||||
pc8 = read_register (PC_REGNUM) + 8; /* branch not taken */
|
||||
|
||||
if (!one_stepped)
|
||||
{
|
||||
/* Always set breakpoint for NPC. */
|
||||
read_memory (next_pc, break_mem[0], sizeof break_insn);
|
||||
write_memory (next_pc, break_insn, sizeof break_insn);
|
||||
|
||||
/* printf ("set break at %x\n",next_pc); */
|
||||
br = isabranch (pc8 - 8, &target);
|
||||
brkpc8 = brktrg = 0;
|
||||
|
||||
if (br == bicca && pc8 != next_pc)
|
||||
{
|
||||
/* Handle branches with care */
|
||||
brkpc8 = 1;
|
||||
read_memory (pc8, break_mem[1], sizeof break_insn);
|
||||
write_memory (pc8, break_insn, sizeof break_insn);
|
||||
}
|
||||
else if (br == baa && target != next_pc)
|
||||
{
|
||||
brktrg = 1;
|
||||
read_memory (target, break_mem[2], sizeof break_insn);
|
||||
write_memory (target, break_insn, sizeof break_insn);
|
||||
}
|
||||
|
||||
/* Let it go */
|
||||
ptrace (7, inferior_pid, 1, signal);
|
||||
one_stepped = 1;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove breakpoints */
|
||||
write_memory (next_pc, break_mem[0], sizeof break_insn);
|
||||
|
||||
if (brkpc8)
|
||||
{
|
||||
write_memory (pc8, break_mem[1], sizeof break_insn);
|
||||
}
|
||||
if (brktrg)
|
||||
{
|
||||
write_memory (target, break_mem[2], sizeof break_insn);
|
||||
}
|
||||
one_stepped = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NO_SINGLE_STEP */
|
||||
|
||||
static int save_insn_opcodes[] = { 0x03000000, 0x82007ee0, 0x9de38001, 0x03000000, 0x82007ee0, 0x91d02001, 0x01000000 };
|
||||
|
||||
void
|
||||
do_save_insn (size)
|
||||
int size;
|
||||
{
|
||||
int g1 = read_register (1);
|
||||
CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
CORE_ADDR pc = read_register (PC_REGNUM);
|
||||
#ifdef NPC_REGNUM
|
||||
CORE_ADDR npc = read_register (NPC_REGNUM);
|
||||
#endif
|
||||
CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes);
|
||||
save_insn_opcodes[0] = 0x03000000 | ((-size >> 12) & 0x3fffff);
|
||||
save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff);
|
||||
save_insn_opcodes[3] = 0x03000000 | ((g1 >> 12) & 0x3fffff);
|
||||
save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff);
|
||||
write_memory (fake_pc, save_insn_opcodes, sizeof (save_insn_opcodes));
|
||||
clear_proceed_status ();
|
||||
stop_after_trap = 1;
|
||||
|
||||
proceed (fake_pc, 0, 0);
|
||||
|
||||
write_register (PC_REGNUM, pc);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (NPC_REGNUM, npc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 };
|
||||
|
||||
void
|
||||
do_restore_insn (raw_buffer)
|
||||
char raw_buffer[];
|
||||
{
|
||||
CORE_ADDR pc = read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)], 4);
|
||||
CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
#ifdef NPC_REGNUM
|
||||
CORE_ADDR npc = *(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)] != 0
|
||||
? read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)], 4) : pc + 4;
|
||||
#endif
|
||||
CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes);
|
||||
int saved_stop_stack_dummy = stop_stack_dummy;
|
||||
|
||||
if (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)] == 0)
|
||||
abort ();
|
||||
|
||||
write_memory (fake_pc, restore_insn_opcodes, sizeof (restore_insn_opcodes));
|
||||
clear_proceed_status ();
|
||||
stop_after_trap = 1;
|
||||
|
||||
proceed (fake_pc, 0, 0);
|
||||
|
||||
stop_stack_dummy = saved_stop_stack_dummy;
|
||||
write_register (PC_REGNUM, pc);
|
||||
#ifdef NPC_REGNUM
|
||||
write_register (NPC_REGNUM, npc);
|
||||
#endif
|
||||
|
||||
/* Select innermost stack frame except on return from a stack dummy routine,
|
||||
or if the program has exited. */
|
||||
if (!stop_stack_dummy)
|
||||
{
|
||||
select_frame (stop_frame, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
select_frame (read_register (FP_REGNUM), 0);
|
||||
}
|
||||
}
|
||||
|
||||
END_FILE
|
||||
|
|
|
@ -256,13 +256,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
|
||||
|
||||
|
@ -277,7 +277,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); \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
register int insn = 0177777 & read_memory_integer (pc, 2); \
|
||||
val = 0; \
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
|
||||
|
|
|
@ -264,13 +264,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
|
||||
|
||||
|
@ -285,7 +285,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); \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
register int insn = 0177777 & read_memory_integer (pc, 2); \
|
||||
val = 0; \
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
/* 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)
|
||||
#define FILEADDR_ROUND(addr) ((addr + 7) & -8)
|
||||
|
|
533
gdb/m-isi.h
533
gdb/m-isi.h
|
@ -1,533 +0,0 @@
|
|||
/*
|
||||
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 */
|
||||
|
||||
/* 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)
|
||||
|
||||
/* 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, 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 + 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.frame); \
|
||||
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 CORE_ADDR fp = read_register (FP_REGNUM); \
|
||||
register int regnum; \
|
||||
struct frame_saved_regs fsr; \
|
||||
struct frame_info fi; \
|
||||
char raw_buffer[12]; \
|
||||
fi = get_frame_info (fp); \
|
||||
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); \
|
||||
}
|
||||
|
||||
/* 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, fun, nargs) \
|
||||
{ *(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"); }
|
|
@ -254,13 +254,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
/* compute base of arguments */
|
||||
#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
|
||||
|
@ -276,7 +276,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
int addr_mode; \
|
||||
int width; \
|
||||
\
|
||||
pc = FRAME_SAVED_PC (fi.frame); \
|
||||
pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
insn = read_memory_integer (pc,2); \
|
||||
addr_mode = (insn >> 11) & 0x1f; \
|
||||
insn = insn & 0x7ff; \
|
||||
|
|
|
@ -265,13 +265,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
|
||||
|
||||
|
@ -281,7 +281,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
Can return -1, meaning no way to tell. */
|
||||
|
||||
#define FRAME_NUM_ARGS(val, fi) \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
register int insn = 0177777 & read_memory_integer (pc, 2); \
|
||||
val = 0; \
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
|
||||
|
|
|
@ -341,7 +341,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
|
|||
(chain)
|
||||
|
||||
/* Define other aspects of the stack frame on NPL. */
|
||||
#define FRAME_SAVED_PC(frame) \
|
||||
#define FRAME_SAVED_PC(frame,ignore) \
|
||||
(read_memory_integer (frame + 8, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
|
|
|
@ -325,7 +325,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
|
|||
(chain)
|
||||
|
||||
/* Define other aspects of the stack frame on NPL. */
|
||||
#define FRAME_SAVED_PC(frame) \
|
||||
#define FRAME_SAVED_PC(frame,ignore) \
|
||||
(read_memory_integer (frame + 8, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
|
|
|
@ -208,13 +208,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
|
||||
|
||||
|
@ -229,7 +229,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); \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
register int insn = 0177777 & read_memory_integer (pc, 2); \
|
||||
val = 0; \
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
|
||||
|
|
|
@ -233,13 +233,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) (fi.frame)
|
||||
|
||||
|
@ -254,7 +254,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); \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \
|
||||
register int insn = 0177777 & read_memory_integer (pc, 2); \
|
||||
val = 0; \
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
|
||||
|
|
493
gdb/m-sun4.h
Normal file
493
gdb/m-sun4.h
Normal file
|
@ -0,0 +1,493 @@
|
|||
/* 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
|
||||
|
||||
/* 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 0xf000000
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 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)
|
||||
|
||||
/* 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)
|
||||
|
||||
/* 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
|
||||
|
||||
/* The SPARC processor has register windows. */
|
||||
|
||||
#define HAVE_REGISTER_WINDOWS
|
||||
|
||||
/* 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. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) \
|
||||
GET_RWINDOW_REG (thisframe, rw_in[6])
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe, 0) >= first_object_file_end))
|
||||
|
||||
#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)
|
||||
|
||||
/* 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.
|
||||
|
||||
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 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) \
|
||||
{ \
|
||||
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); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
for (regnum = 0; regnum < 16; regnum++) \
|
||||
(frame_saved_regs).regs[regnum+16] = frame + regnum * 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; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = frame; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \
|
||||
}
|
||||
|
||||
/* Things needed for making the inferior call functions. */
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
/* NOTE: to be perfectly correct, we will probably have to restore the
|
||||
IN registers (which were the OUT registers of the calling frame). */
|
||||
|
||||
#define PUSH_DUMMY_FRAME \
|
||||
{ extern char registers[]; \
|
||||
register int regnum; \
|
||||
CORE_ADDR fp = read_register (FP_REGNUM); \
|
||||
CORE_ADDR pc = read_register (PC_REGNUM); \
|
||||
void do_save_insn (); \
|
||||
supply_register (RP_REGNUM, &pc); \
|
||||
do_save_insn (0x140); \
|
||||
fp = read_register (FP_REGNUM); \
|
||||
write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4); \
|
||||
write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \
|
||||
write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 8 * 4); \
|
||||
write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \
|
||||
}
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
#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)); \
|
||||
}
|
||||
|
||||
/* 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 call instruction. *../
|
||||
|
||||
ld [%sp+0x58],%o5
|
||||
ld [%sp+0x44],%o4
|
||||
ld [%sp+0x50],%o3
|
||||
ld [%sp+0x4c],%o2
|
||||
ld [%sp+0x48],%o1
|
||||
call 0x34343434
|
||||
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, 0xd803a044, 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
|
||||
|
||||
/* KDB stuff flushed for now. */
|
5
gdb/m-sun4init.h
Normal file
5
gdb/m-sun4init.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
/* 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)
|
5
gdb/m-suninit.h
Normal file
5
gdb/m-suninit.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
/* 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)
|
|
@ -266,13 +266,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4))
|
||||
|
||||
/* Compute base of arguments. */
|
||||
|
||||
|
@ -311,7 +311,7 @@ extern CORE_ADDR ns32k_get_enter_addr ();
|
|||
{ \
|
||||
pc = (enter_addr == 1) ? \
|
||||
SAVED_PC_AFTER_CALL () : \
|
||||
FRAME_SAVED_PC (fi.frame); \
|
||||
FRAME_SAVED_PC (fi.frame,0); \
|
||||
insn = read_memory_integer (pc,2); \
|
||||
addr_mode = (insn >> 11) & 0x1f; \
|
||||
insn = insn & 0x7ff; \
|
||||
|
|
|
@ -54,7 +54,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. */
|
||||
|
||||
#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
|
||||
#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame,0)
|
||||
|
||||
/* This is the amount to subtract from u.u_ar0
|
||||
to get the offset in the core file of the register values. */
|
||||
|
@ -212,13 +212,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe + 12, 4))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe,ignore) >= 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 + 16, 4))
|
||||
#define FRAME_SAVED_PC(frame, ignore) (read_memory_integer (frame + 16, 4), 0)
|
||||
|
||||
/* Cannot find the AP register value directly from the FP value.
|
||||
Must find it saved in the frame called by this one, or in the AP register
|
||||
|
|
|
@ -1153,7 +1153,7 @@ dump_me_command ()
|
|||
static void
|
||||
initialize_main ()
|
||||
{
|
||||
prompt = savestring ("(gdb) ", 6);
|
||||
prompt = savestring ("(gdb+) ", 7);
|
||||
|
||||
/* Define the classes of commands.
|
||||
They will appear in the help list in the reverse of this order. */
|
||||
|
|
1273
gdb/opcode.h
1273
gdb/opcode.h
File diff suppressed because it is too large
Load diff
502
gdb/param.h
502
gdb/param.h
|
@ -1,5 +1,6 @@
|
|||
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
|
||||
/* 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
|
||||
|
@ -18,8 +19,8 @@ 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 sun3
|
||||
#define sun3
|
||||
#ifndef sun4
|
||||
#define sun4
|
||||
#endif
|
||||
|
||||
/* Get rid of any system-imposed stack limit if possible. */
|
||||
|
@ -43,21 +44,21 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
/* 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 */ \
|
||||
}
|
||||
#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. */
|
||||
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
read_memory_integer (read_register (SP_REGNUM), 4)
|
||||
/* 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. */
|
||||
|
||||
|
@ -67,19 +68,26 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Stack has strict alignment. */
|
||||
|
||||
#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0x4e, 0x4f}
|
||||
#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 2
|
||||
#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".
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
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. */
|
||||
|
||||
|
@ -91,17 +99,23 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 31
|
||||
#define NUM_REGS 72
|
||||
|
||||
/* 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", "fpcode", "fpflags" }
|
||||
{ "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,
|
||||
|
@ -110,40 +124,45 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
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 */
|
||||
#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 (16*4+8*12+8+20)
|
||||
#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) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
|
||||
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
|
||||
: (N) * 4)
|
||||
/* ?? */
|
||||
#define REGISTER_BYTE(N) ((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. */
|
||||
for register N. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
|
||||
/* 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 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 8-byte doubles. */
|
||||
for register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
|
||||
/* 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 12
|
||||
#define MAX_REGISTER_RAW_SIZE 8
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
|
||||
|
@ -152,50 +171,44 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
|
||||
#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) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_from_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
#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) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_to_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
{ 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)
|
||||
((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : builtin_type_int)
|
||||
|
||||
/* 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))
|
||||
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 (0, VALBUF, TYPE_LENGTH (TYPE))
|
||||
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) (*(int *)(REGBUF))
|
||||
#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. */
|
||||
|
||||
|
@ -213,9 +226,17 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
does not screw up with random garbage at end of file. */
|
||||
|
||||
#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). */
|
||||
#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.
|
||||
|
@ -227,22 +248,30 @@ 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
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
/* In the case of the Sun 4, the frame-chain's nominal address
|
||||
is held in the frame pointer register.
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
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. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) \
|
||||
GET_RWINDOW_REG (thisframe, rw_in[6])
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
|
||||
(chain != 0 && (FRAME_SAVED_PC (thisframe, 0) >= 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 + 4, 4))
|
||||
#define FRAME_SAVED_PC(frame, next_frame) frame_saved_pc (frame, next_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.
|
||||
|
@ -252,226 +281,213 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
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.frame); \
|
||||
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
|
||||
#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. */
|
||||
the address we return for it IS the sp for the next frame.
|
||||
|
||||
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
|
||||
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 int regmask; \
|
||||
register CORE_ADDR next_addr; \
|
||||
register CORE_ADDR pc; \
|
||||
int nextinsn; \
|
||||
FRAME frame = (fi).frame; \
|
||||
FRAME next_frame = (fi).next_frame; \
|
||||
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; \
|
||||
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); \
|
||||
} \
|
||||
/* 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; \
|
||||
else \
|
||||
{ \
|
||||
for (regnum = 0; regnum < 16; regnum++) \
|
||||
(frame_saved_regs).regs[regnum+16] = frame + regnum * 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; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = frame; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \
|
||||
}
|
||||
|
||||
/* Things needed for making the inferior call functions. */
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
/* NOTE: to be perfectly correct, we will probably have to restore the
|
||||
IN registers (which were the OUT registers of the calling frame). */
|
||||
|
||||
#define PUSH_DUMMY_FRAME \
|
||||
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
|
||||
{ extern char registers[]; \
|
||||
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); }
|
||||
CORE_ADDR fp = read_register (FP_REGNUM); \
|
||||
CORE_ADDR pc = read_register (PC_REGNUM); \
|
||||
void do_save_insn (); \
|
||||
supply_register (RP_REGNUM, &pc); \
|
||||
do_save_insn (0x140); \
|
||||
fp = read_register (FP_REGNUM); \
|
||||
write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4); \
|
||||
write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \
|
||||
write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 8 * 4); \
|
||||
write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \
|
||||
}
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
#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[12]; \
|
||||
fi = get_frame_info (fp); \
|
||||
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); \
|
||||
set_current_frame (read_register (FP_REGNUM)); }
|
||||
{ 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)); \
|
||||
}
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
fmovem 0xff,-(sp)
|
||||
moveml 0xfffc,-(sp)
|
||||
clrw -(sp)
|
||||
movew ccr,-(sp)
|
||||
|
||||
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 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. */
|
||||
the following call instruction. *../
|
||||
|
||||
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
|
||||
ld [%sp+0x58],%o5
|
||||
ld [%sp+0x44],%o4
|
||||
ld [%sp+0x50],%o3
|
||||
ld [%sp+0x4c],%o2
|
||||
ld [%sp+0x48],%o1
|
||||
call 0x34343434
|
||||
ld [%sp+0x44],%o0
|
||||
nop
|
||||
ta 1
|
||||
nop
|
||||
|
||||
#define CALL_DUMMY_LENGTH 28
|
||||
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).
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 12
|
||||
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, 0xd803a044, 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, fun, nargs) \
|
||||
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
|
||||
*(int *)((char *) dummyname + 14) = fun; }
|
||||
#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); \
|
||||
}
|
||||
|
||||
/* Interface definitions for kernel debugger KDB. */
|
||||
/* Sparc has no reliable single step ptrace call */
|
||||
|
||||
/* 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 NO_SINGLE_STEP 1
|
||||
|
||||
#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"); }
|
||||
/* KDB stuff flushed for now. */
|
||||
|
|
1418
gdb/pinsn.c
1418
gdb/pinsn.c
File diff suppressed because it is too large
Load diff
|
@ -499,6 +499,10 @@ address_info (exp)
|
|||
printf ("static at address 0x%x", val);
|
||||
break;
|
||||
|
||||
case LOC_REGPARM:
|
||||
printf ("an argument in register %s", reg_names[val]);
|
||||
break;
|
||||
|
||||
case LOC_ARG:
|
||||
printf ("an argument at offset %d", val);
|
||||
break;
|
||||
|
@ -934,6 +938,7 @@ print_frame_args (func, addr, num, stream)
|
|||
int first = 1;
|
||||
register int i;
|
||||
register int last_offset = FRAME_ARGS_SKIP;
|
||||
register int last_regparm = 0;
|
||||
register struct symbol *sym, *nextsym;
|
||||
register value val;
|
||||
|
||||
|
@ -951,31 +956,73 @@ print_frame_args (func, addr, num, stream)
|
|||
{
|
||||
QUIT;
|
||||
sym = BLOCK_SYM (b, i);
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG
|
||||
&& SYMBOL_VALUE (sym) >= last_offset
|
||||
&& (nextsym == 0
|
||||
|| SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym)))
|
||||
nextsym = sym;
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG)
|
||||
{
|
||||
if (SYMBOL_VALUE (sym) >= last_offset
|
||||
&& (nextsym == 0
|
||||
|| SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym)))
|
||||
nextsym = sym;
|
||||
}
|
||||
else if (SYMBOL_CLASS (sym) == LOC_REGPARM)
|
||||
{
|
||||
if (SYMBOL_VALUE (sym) >= last_regparm
|
||||
&& (nextsym == 0
|
||||
|| SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym)))
|
||||
nextsym = sym;
|
||||
}
|
||||
}
|
||||
if (nextsym == 0)
|
||||
break;
|
||||
sym = nextsym;
|
||||
/* Print any nameless args between the last arg printed
|
||||
and the next arg. */
|
||||
if (last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int))
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG
|
||||
&& last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int))
|
||||
{
|
||||
print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym),
|
||||
stream);
|
||||
first = 0;
|
||||
}
|
||||
/* Print the next arg. */
|
||||
val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym));
|
||||
if (SYMBOL_CLASS (sym) == LOC_REGPARM)
|
||||
{
|
||||
unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
|
||||
unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
|
||||
|
||||
read_relative_register_raw_bytes (SYMBOL_VALUE (sym), raw_buffer);
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT)
|
||||
val = value_from_double (SYMBOL_TYPE (sym), *(double *)raw_buffer);
|
||||
else if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
|
||||
|| TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM)
|
||||
val = value_from_long (SYMBOL_TYPE (sym), *(int *)raw_buffer);
|
||||
else if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR)
|
||||
{
|
||||
if (sizeof (char *) == sizeof (int))
|
||||
val = value_from_long (builtin_type_int, *(int *)raw_buffer);
|
||||
else if (sizeof (char *) == sizeof (long))
|
||||
val = value_from_long (builtin_type_long, *(long *)raw_buffer);
|
||||
else
|
||||
error ("pointer size not sizeof (int) or sizeof (long)");
|
||||
VALUE_TYPE (val) = SYMBOL_TYPE (sym);
|
||||
}
|
||||
else
|
||||
error ("can't extract non-scalar from register");
|
||||
}
|
||||
else
|
||||
val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym));
|
||||
|
||||
if (! first)
|
||||
fprintf (stream, ", ");
|
||||
fprintf (stream, "%s=", SYMBOL_NAME (sym));
|
||||
value_print (val, stream, 0);
|
||||
first = 0;
|
||||
last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG)
|
||||
last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
|
||||
else
|
||||
{
|
||||
last_regparm = SYMBOL_VALUE (sym) + 1;
|
||||
last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym));
|
||||
}
|
||||
/* Round up address of next arg to multiple of size of int. */
|
||||
last_offset
|
||||
= ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int);
|
||||
|
|
44
gdb/source.c
44
gdb/source.c
|
@ -59,13 +59,16 @@ select_source_symtab (s)
|
|||
{
|
||||
if (s)
|
||||
{
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
|
||||
/* Make the default place to list be the function `main'
|
||||
if one exists. */
|
||||
if (lookup_symbol ("main", 0, VAR_NAMESPACE))
|
||||
{
|
||||
sal = decode_line_spec ("main", 1);
|
||||
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;
|
||||
|
@ -490,6 +493,7 @@ 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;
|
||||
|
@ -534,7 +538,18 @@ list_command (arg, from_tty)
|
|||
if (*arg1 == ',')
|
||||
dummy_beg = 1;
|
||||
else
|
||||
sal = decode_line_1 (&arg1, 0, 0, 0);
|
||||
{
|
||||
sals = decode_line_1 (&arg1, 0, 0, 0);
|
||||
|
||||
if (! sals.nelts) return; /* C++ */
|
||||
if (sals.nelts != 1)
|
||||
{
|
||||
error ("Unreasonable listing request");
|
||||
}
|
||||
|
||||
sal = sals.sals[0];
|
||||
free (sals.sals);
|
||||
}
|
||||
|
||||
/* Record whether the BEG arg is all digits. */
|
||||
|
||||
|
@ -551,10 +566,16 @@ list_command (arg, from_tty)
|
|||
arg1++;
|
||||
if (*arg1 == 0)
|
||||
dummy_end = 1;
|
||||
else if (dummy_beg)
|
||||
sal_end = decode_line_1 (&arg1, 0, 0, 0);
|
||||
else
|
||||
sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
|
||||
{
|
||||
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) return; /* C++ */
|
||||
sal_end = sals_end.sals[0];
|
||||
free (sals_end.sals);
|
||||
}
|
||||
}
|
||||
|
||||
if (*arg1)
|
||||
|
@ -607,8 +628,7 @@ list_command (arg, from_tty)
|
|||
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);
|
||||
dummy_end ? sal.line + 10 : sal_end.line + 1, 0);
|
||||
}
|
||||
|
||||
/* Print info on range of pc's in a specified line. */
|
||||
|
@ -618,6 +638,7 @@ 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;
|
||||
|
||||
|
@ -628,8 +649,15 @@ line_info (arg, from_tty)
|
|||
}
|
||||
else
|
||||
{
|
||||
sal = decode_line_spec (arg, 0);
|
||||
sals = decode_line_spec (arg);
|
||||
|
||||
if (sals.nelts == 0)
|
||||
return; /* C++ */
|
||||
if (sals.nelts != 1)
|
||||
error ("unreasonable line info request");
|
||||
|
||||
sal = sals.sals[0];
|
||||
free (sals.sals);
|
||||
/* If this command is repeated with RET,
|
||||
turn it into the no-arg variant. */
|
||||
|
||||
|
|
1
gdb/sparc-opcode.h
Normal file
1
gdb/sparc-opcode.h
Normal file
|
@ -0,0 +1 @@
|
|||
/* This file is empty. */
|
811
gdb/sparc-pinsn.c
Normal file
811
gdb/sparc-pinsn.c
Normal file
|
@ -0,0 +1,811 @@
|
|||
/* Print sparc instructions 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!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "sparc-opcode.h"
|
||||
|
||||
/* sparc instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 4
|
||||
|
||||
/* Print the sparc instruction at address MEMADDR in debugged memory,
|
||||
on STREAM. Returns length of the instruction, in bytes, which
|
||||
is always 4. */
|
||||
|
||||
struct op1_fmt
|
||||
{
|
||||
unsigned op1 : 2;
|
||||
unsigned dummy : 30;
|
||||
};
|
||||
|
||||
struct op2_fmt
|
||||
{
|
||||
unsigned dummy1 : 7;
|
||||
unsigned op2 : 3;
|
||||
unsigned dummy2 : 22;
|
||||
};
|
||||
|
||||
struct op3_fmt
|
||||
{
|
||||
unsigned dummy1 : 7;
|
||||
unsigned op3 : 6;
|
||||
unsigned dummy2 : 19;
|
||||
};
|
||||
|
||||
struct call_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned disp : 30;
|
||||
};
|
||||
|
||||
struct sethi_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned rd : 5;
|
||||
unsigned op2 : 3;
|
||||
unsigned imm : 22;
|
||||
};
|
||||
|
||||
struct branch_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned a : 1;
|
||||
unsigned cond : 4;
|
||||
unsigned op2 : 3;
|
||||
unsigned disp : 22; /* this should really be signed. */
|
||||
};
|
||||
|
||||
struct ldst_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned rd : 5;
|
||||
unsigned op3 : 6;
|
||||
unsigned rs1 : 5;
|
||||
unsigned i : 1;
|
||||
unsigned asi : 8;
|
||||
unsigned rs2 : 5;
|
||||
};
|
||||
|
||||
struct arith_imm_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned rd : 5;
|
||||
unsigned op3 : 6;
|
||||
unsigned rs1 : 5;
|
||||
unsigned i : 1;
|
||||
unsigned simm : 13;
|
||||
};
|
||||
|
||||
struct arith_fmt
|
||||
{
|
||||
unsigned op : 2;
|
||||
unsigned rd : 5;
|
||||
unsigned op3 : 6;
|
||||
unsigned rs1 : 5;
|
||||
unsigned i : 1;
|
||||
unsigned opf : 8;
|
||||
unsigned rs2 : 5;
|
||||
};
|
||||
|
||||
union insn_fmt
|
||||
{
|
||||
struct op1_fmt op1;
|
||||
struct op2_fmt op2;
|
||||
struct op3_fmt op3;
|
||||
struct call_fmt call;
|
||||
struct sethi_fmt sethi;
|
||||
struct branch_fmt branch;
|
||||
struct ldst_fmt ldst;
|
||||
struct arith_imm_fmt arith_imm;
|
||||
struct arith_fmt arith;
|
||||
int intval;
|
||||
float floatval; /* ?? */
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
|
||||
} branch_type;
|
||||
|
||||
static char *icc_name[] =
|
||||
{ "~", "eq", "le", "lt", "leu", "ltu", "neg", "vs",
|
||||
"", "ne", "gt", "ge", "gtu", "geu", "pos", "vc"};
|
||||
|
||||
static char *fcc_name[] =
|
||||
{ "~fb", "fbne", "fblg", "fbul", "fbl", "fbug", "fbg", "fbu",
|
||||
"fb", "fbe", "fbue", "fbge", "fbuge", "fble", "fbule", "fbo"};
|
||||
|
||||
static char *ccc_name[] =
|
||||
{ "~cb", "cb123", "cb12", "cb13", "cb1", "cb23", "cb2", "cb3",
|
||||
"cb", "cb0", "cb03", "cb02", "cb023", "cb01", "cb013", "cb012"};
|
||||
|
||||
static char *arith_name[] =
|
||||
{ "add", "and", "or", "xor", "sub", "andn", "orn", "xnor",
|
||||
"addx", 0, 0, 0, "subx", 0, 0, 0};
|
||||
|
||||
static char *xarith_name[] =
|
||||
{ "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra"};
|
||||
|
||||
static char *state_reg_name[] =
|
||||
{ "%y", "%psr", "%wim", "%tbr", 0, 0, 0, 0};
|
||||
|
||||
static char *ldst_i_name[] =
|
||||
{ "ld", "ldub", "lduh", "ldd", "st", "stb", "sth", "std",
|
||||
0, "ldsb", "ldsh", 0, 0, "ldstub", 0, "swap",
|
||||
"lda", "lduba", "lduha", "ldda", "sta", "stba", "stha", "stda",
|
||||
0, "ldsba", "ldsha", 0, 0, "ldstuba", 0, "swapa"};
|
||||
|
||||
static char *ldst_f_name[] =
|
||||
{ "ldf", "ldfsr", 0, "lddf", "stf", "stfsr", "stdfq", "stdf"};
|
||||
|
||||
static char *ldst_c_name[] =
|
||||
{ "ldc", "ldcsr", 0, "lddc", "stc", "stcsr", "stdcq", "stdc"};
|
||||
|
||||
static int this_sethi_target = -1;
|
||||
static int last_sethi_target = -1;
|
||||
static int sethi_value = 0;
|
||||
|
||||
static void fprint_addr1 ();
|
||||
static void fprint_ldst ();
|
||||
static void fprint_f_ldst ();
|
||||
static void fprint_c_ldst ();
|
||||
static void fprint_fpop ();
|
||||
|
||||
int
|
||||
print_insn (memaddr, stream)
|
||||
CORE_ADDR memaddr;
|
||||
FILE *stream;
|
||||
{
|
||||
union insn_fmt insn;
|
||||
int disp22;
|
||||
|
||||
read_memory (memaddr, &insn, MAXLEN);
|
||||
|
||||
this_sethi_target = -1;
|
||||
switch (insn.op1.op1)
|
||||
{
|
||||
case 1:
|
||||
/* CALL format. */
|
||||
fprintf (stream, "call ");
|
||||
print_address (memaddr + (insn.call.disp << 2), stream);
|
||||
break;
|
||||
case 0:
|
||||
/* Bicc, FBfcc, CBccc, SETHI format. */
|
||||
switch (insn.op2.op2)
|
||||
{
|
||||
case 0:
|
||||
fprintf (stream, "unimp");
|
||||
break;
|
||||
case 2:
|
||||
/* Bicc. */
|
||||
fprintf (stream, "b%s", icc_name[insn.branch.cond]);
|
||||
if (insn.branch.a) fprintf (stream, ",a ");
|
||||
else fprintf (stream, " ");
|
||||
disp22 = insn.branch.disp;
|
||||
disp22 = ((disp22 << 10) >> 10);
|
||||
print_address (memaddr + (disp22 << 2), stream);
|
||||
break;
|
||||
case 4:
|
||||
/* SETHI. */
|
||||
fprintf (stream, "sethi %%hi(0x%x),%s",
|
||||
insn.sethi.imm << 10, reg_names[insn.sethi.rd]);
|
||||
this_sethi_target = insn.sethi.rd;
|
||||
sethi_value = insn.sethi.imm << 12;
|
||||
break;
|
||||
case 6:
|
||||
/* FBdfcc. */
|
||||
fprintf (stream, "fb%s", fcc_name[insn.branch.cond]);
|
||||
if (insn.branch.a) fprintf (stream, ",a ");
|
||||
else fprintf (stream, " ");
|
||||
disp22 = insn.branch.disp;
|
||||
disp22 = ((disp22 << 10) >> 10);
|
||||
print_address (memaddr + (disp22 << 2), stream);
|
||||
break;
|
||||
case 7:
|
||||
/* CBccc. */
|
||||
fprintf (stream, "cb%s", ccc_name[insn.branch.cond]);
|
||||
if (insn.branch.a) fprintf (stream, ",a ");
|
||||
else fprintf (stream, " ");
|
||||
disp22 = insn.branch.disp;
|
||||
disp22 = ((disp22 << 10) >> 10);
|
||||
print_address (memaddr + (disp22 << 2), stream);
|
||||
break;
|
||||
default:
|
||||
fprintf (stream, "0x%x (illegal op2 format)", insn.intval);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
/* vaguely arithmetic insns. */
|
||||
char *rd = reg_names[insn.arith.rd];
|
||||
char *rs1 = reg_names[insn.arith.rs1];
|
||||
|
||||
if (insn.op3.op3 <= 28)
|
||||
{
|
||||
/* Arithmetic insns, with a few unimplemented. */
|
||||
register int affect_cc = insn.op3.op3 & 16;
|
||||
char *name = arith_name[insn.op3.op3 ^ affect_cc];
|
||||
char *tmp = affect_cc ? "cc" : "";
|
||||
|
||||
if (name == 0)
|
||||
{
|
||||
fprintf (stream, "0x%08x (unimplemented arithmetic insn)",
|
||||
insn.intval);
|
||||
}
|
||||
else if (insn.arith.i)
|
||||
{
|
||||
fprintf (stream, "%s%s %s,0x%x,%s",
|
||||
name, tmp, rs1, insn.arith_imm.simm, rd);
|
||||
if (last_sethi_target == insn.arith.rd)
|
||||
{
|
||||
fprintf (stream, "\t! ");
|
||||
print_address (sethi_value + insn.arith_imm.simm);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s%s %s,%s,%s",
|
||||
name, tmp, rs1, reg_names[insn.arith.rs2], rd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (insn.op3.op3 < 32)
|
||||
{
|
||||
fprintf (stream, "0x%08x (unimplemented arithmetic insn)",
|
||||
insn.intval);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int op = insn.op3.op3 ^ 32;
|
||||
|
||||
if (op < 8)
|
||||
{
|
||||
char *name = xarith_name[op];
|
||||
/* tagged add/sub insns and shift insns. */
|
||||
if (insn.arith.i)
|
||||
{
|
||||
int i = insn.arith_imm.simm;
|
||||
if (op > 4)
|
||||
/* Its a shift insn. */
|
||||
i &= 31;
|
||||
|
||||
fprintf (stream, "%s %s,0x%x,%s",
|
||||
name, rs1, i, rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s %s,%s,%s",
|
||||
name, rs1, reg_names[insn.arith.rs2], rd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (op < 20)
|
||||
{
|
||||
/* read/write state registers. */
|
||||
char *sr = state_reg_name[op & 7];
|
||||
if (sr == 0)
|
||||
fprintf (stream, "0x%08x (unimplemented state register insn",
|
||||
insn.intval);
|
||||
else
|
||||
fprintf (stream, "%s %s,%s", op & 16 ? "wr" : "rd", sr, rd);
|
||||
break;
|
||||
}
|
||||
if (op < 22)
|
||||
{
|
||||
/* floating point insns. */
|
||||
int opcode = insn.arith.opf;
|
||||
|
||||
fprint_fpop (stream, insn, op & 3, opcode);
|
||||
break;
|
||||
}
|
||||
if (op < 24)
|
||||
{
|
||||
/* coprocessor insns. */
|
||||
char *rs2 = reg_names[insn.arith.rs2];
|
||||
int opcode = insn.arith.opf;
|
||||
|
||||
fprintf (stream, "cpop%d rs1=%s,rs2=%s,op=0x%x,rd=%s",
|
||||
op & 1, rs1, rs2, opcode, rd);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
char *rndop_ptr;
|
||||
|
||||
case 24:
|
||||
fprint_addr1 (stream, "jumpl", insn);
|
||||
break;
|
||||
case 25:
|
||||
fprint_addr1 (stream, "rett", insn);
|
||||
break;
|
||||
case 26:
|
||||
{
|
||||
char rndop_buf[32];
|
||||
sprintf (rndop_buf, "t%s", icc_name[insn.branch.cond]);
|
||||
fprint_addr1 (stream, rndop_buf, insn);
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
fprint_addr1 (stream, "iflush", insn);
|
||||
break;
|
||||
|
||||
case 28:
|
||||
rndop_ptr = "save";
|
||||
case 29:
|
||||
if (op == 29)
|
||||
rndop_ptr = "restore";
|
||||
|
||||
if (insn.arith.i)
|
||||
{
|
||||
fprintf (stream, "%s %s,0x%x,%s",
|
||||
rndop_ptr, rs1,
|
||||
((insn.arith_imm.simm << 19) >> 19), rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s %s,%s,%s",
|
||||
rndop_ptr, rs1, reg_names[insn.arith.rs2], rd);
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
case 31:
|
||||
fprintf (stream, "0x%08x (unimplemented op3 insn)",
|
||||
insn.intval);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case 3:
|
||||
/* load and store insns. */
|
||||
{
|
||||
char *rd = reg_names[insn.arith.rd];
|
||||
char *rs1 = reg_names[insn.arith.rs1];
|
||||
int op = insn.arith.op3;
|
||||
|
||||
if ((op & 32) == 0)
|
||||
{
|
||||
/* Integer ops. */
|
||||
fprint_ldst (stream, insn, op);
|
||||
break;
|
||||
}
|
||||
if ((op & 16) == 0)
|
||||
{
|
||||
/* Float ops. */
|
||||
op ^= 32;
|
||||
if (op <= 7)
|
||||
{
|
||||
fprint_f_ldst (stream, insn, op);
|
||||
}
|
||||
else
|
||||
fprintf (stream, "0x%08x (unimplemented float load/store insn)",
|
||||
insn.intval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Coprocessor ops. */
|
||||
op ^= (32+16);
|
||||
if (op <= 7)
|
||||
{
|
||||
fprint_c_ldst (stream, insn, op);
|
||||
}
|
||||
else
|
||||
fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)",
|
||||
insn.intval);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* It would be nice if this routine could print out a symbolic address
|
||||
when appropriate. */
|
||||
static void
|
||||
fprint_addr1 (stream, name, insn)
|
||||
FILE *stream;
|
||||
char *name;
|
||||
union insn_fmt insn;
|
||||
{
|
||||
char *rs1 = reg_names[insn.arith.rs1];
|
||||
char *rd = reg_names[insn.arith.rd];
|
||||
|
||||
if (insn.arith.i)
|
||||
{
|
||||
fprintf (stream, "%s %s,0x%x,%s",
|
||||
name, rs1, insn.arith_imm.simm, rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s %s,%s,%s",
|
||||
name, rs1, reg_names[insn.arith.rs2], rd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_mem (stream, insn)
|
||||
FILE *stream;
|
||||
union insn_fmt insn;
|
||||
{
|
||||
char *reg_name = reg_names[insn.arith.rs1];
|
||||
if (insn.arith.i)
|
||||
{
|
||||
if (insn.arith_imm.simm == 0)
|
||||
fprintf (stream, "[%s]", reg_name);
|
||||
else if (insn.arith_imm.simm & 0x1000)
|
||||
fprintf (stream, "[%s-0x%x]", reg_name,
|
||||
- (insn.arith_imm.simm | 0xffffe000));
|
||||
else
|
||||
fprintf (stream, "[%s+0x%x]", reg_name, insn.arith_imm.simm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (insn.arith.rs2 == 0)
|
||||
fprintf (stream, "[%s]", reg_name);
|
||||
else
|
||||
fprintf (stream, "[%s,%s]", reg_names[insn.arith.rs2], reg_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_ldst (stream, insn, op)
|
||||
FILE *stream;
|
||||
union insn_fmt insn;
|
||||
int op;
|
||||
{
|
||||
char *name = ldst_i_name[op];
|
||||
char *rd = reg_names[insn.arith.rd];
|
||||
|
||||
if (name)
|
||||
{
|
||||
if (name[0] == 's')
|
||||
{
|
||||
fprintf (stream, "%s %s,", name, rd);
|
||||
fprint_mem (stream, insn);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s ", name);
|
||||
fprint_mem (stream, insn);
|
||||
fprintf (stream, ",%s", rd);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf (stream, "0x%08x (unimplemented load/store insn)", insn.intval);
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_f_ldst (stream, insn, op)
|
||||
FILE *stream;
|
||||
union insn_fmt insn;
|
||||
int op;
|
||||
{
|
||||
char *name = ldst_f_name[op];
|
||||
if (name)
|
||||
{
|
||||
char *rd = reg_names[insn.arith.rd + 32];
|
||||
|
||||
if (name[0] == 's')
|
||||
{
|
||||
fprintf (stream, "%s %s,", name, rd);
|
||||
fprint_mem (stream, insn);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s ", name);
|
||||
fprint_mem (stream, insn);
|
||||
fprintf (stream, ",%s", rd);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf (stream, "0x%08x (unimplemented float load/store insn)", insn.intval);
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_c_ldst (stream, insn, op)
|
||||
FILE *stream;
|
||||
union insn_fmt insn;
|
||||
int op;
|
||||
{
|
||||
char *name = ldst_c_name[op];
|
||||
if (name)
|
||||
{
|
||||
if (name[0] == 's')
|
||||
{
|
||||
fprintf (stream, "%s %%cpreg(%d),", name, insn.arith.rs1);
|
||||
fprint_mem (stream, insn);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "%s ");
|
||||
fprint_mem (stream, insn);
|
||||
fprintf (stream, ",%%cpreg(%d)", insn.arith.rd);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)",
|
||||
insn.intval);
|
||||
}
|
||||
|
||||
static void
|
||||
fprint_fpop (stream, insn, op, opcode)
|
||||
FILE *stream;
|
||||
union insn_fmt insn;
|
||||
int op, opcode;
|
||||
{
|
||||
char *name;
|
||||
char *rs1, *rs2, *rd;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
rs2 = reg_names[insn.arith.rs2 + 32];
|
||||
rd = reg_names[insn.arith.rd + 32];
|
||||
if ((opcode ^ 0x2f) <= 0x2f)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x1:
|
||||
name = "fmovs";
|
||||
break;
|
||||
case 0x5:
|
||||
name = "fnegs";
|
||||
break;
|
||||
case 0x9:
|
||||
name = "fabss";
|
||||
break;
|
||||
case 0x29:
|
||||
name = "fsqrts";
|
||||
break;
|
||||
case 0x2a:
|
||||
name = "fsqrtd";
|
||||
break;
|
||||
case 0x2b:
|
||||
name = "fsqrtx";
|
||||
break;
|
||||
}
|
||||
fprintf (stream, "%s %s,%s", name, rs2, rd);
|
||||
return;
|
||||
}
|
||||
if ((opcode ^ 0x5f) <= 0x5f)
|
||||
{
|
||||
rs1 = reg_names[insn.arith.rs1 + 32];
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x41:
|
||||
name = "fadds";
|
||||
break;
|
||||
case 0x42:
|
||||
name = "faddd";
|
||||
break;
|
||||
case 0x43:
|
||||
name = "faddx";
|
||||
break;
|
||||
case 0x45:
|
||||
name = "fsubs";
|
||||
break;
|
||||
case 0x46:
|
||||
name = "fsubd";
|
||||
break;
|
||||
case 0x47:
|
||||
name = "fsubx";
|
||||
break;
|
||||
case 0x49:
|
||||
name = "fmuls";
|
||||
break;
|
||||
case 0x4a:
|
||||
name = "fmuld";
|
||||
break;
|
||||
case 0x4b:
|
||||
name = "fmulx";
|
||||
break;
|
||||
case 0x4d:
|
||||
name = "fdivs";
|
||||
break;
|
||||
case 0x4e:
|
||||
name = "fdivd";
|
||||
break;
|
||||
case 0x4f:
|
||||
name = "fdivx";
|
||||
break;
|
||||
default:
|
||||
goto unimplemented;
|
||||
}
|
||||
if ((opcode & 0x10) == 0)
|
||||
fprintf (stream, "%s %s,%s,%s", name, rs1, rs2, rd);
|
||||
else
|
||||
fprintf (stream, "%s %s,%s", name, rs1, rs2);
|
||||
return;
|
||||
}
|
||||
if ((opcode ^ 0xdf) <= 0xdf)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 0xc4:
|
||||
name = "fitos";
|
||||
break;
|
||||
case 0xc8:
|
||||
name = "fitod";
|
||||
break;
|
||||
case 0xcc:
|
||||
name = "fitox";
|
||||
break;
|
||||
case 0xd1:
|
||||
name = "fstoi";
|
||||
break;
|
||||
case 0xd2:
|
||||
name = "fdtoi";
|
||||
break;
|
||||
case 0xd3:
|
||||
name = "fxtoi";
|
||||
break;
|
||||
case 0xc9:
|
||||
name = "fstod";
|
||||
break;
|
||||
case 0xcd:
|
||||
name = "fstox";
|
||||
break;
|
||||
case 0xc6:
|
||||
name = "fdtos";
|
||||
break;
|
||||
case 0xce:
|
||||
name = "fdtox";
|
||||
break;
|
||||
case 0xc7:
|
||||
name = "fxtos";
|
||||
break;
|
||||
case 0xcb:
|
||||
name = "fxtod";
|
||||
break;
|
||||
default:
|
||||
goto unimplemented;
|
||||
}
|
||||
fprintf (stream, "%s %s,%s", name, rs2, rd);
|
||||
return;
|
||||
}
|
||||
goto unimplemented;
|
||||
|
||||
case 1:
|
||||
rs1 = reg_names[insn.arith.rs1 + 32];
|
||||
rs2 = reg_names[insn.arith.rs2 + 32];
|
||||
if ((opcode ^ 0x57) <= 0x57)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x51:
|
||||
name = "fcmps";
|
||||
break;
|
||||
case 0x52:
|
||||
name = "fcmpd";
|
||||
break;
|
||||
case 0x53:
|
||||
name = "fcmpx";
|
||||
break;
|
||||
case 0x55:
|
||||
name = "fcmpes";
|
||||
break;
|
||||
case 0x56:
|
||||
name = "fcmped";
|
||||
break;
|
||||
case 0x57:
|
||||
name = "fcmpex";
|
||||
break;
|
||||
default:
|
||||
goto unimplemented;
|
||||
}
|
||||
fprintf (stream, "%s %s,%s", name, rs1, rs2);
|
||||
return;
|
||||
}
|
||||
else goto unimplemented;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
goto unimplemented;
|
||||
}
|
||||
unimplemented:
|
||||
fprintf (stream, "0x%08x (unimplemented fpop insn)", insn.intval);
|
||||
}
|
||||
|
||||
/* Set *target if we find a branch */
|
||||
branch_type
|
||||
isabranch (addr, target)
|
||||
CORE_ADDR addr, *target;
|
||||
{
|
||||
union insn_fmt instr;
|
||||
branch_type val = not_branch;
|
||||
long offset; /* Must be signed for sign-extend */
|
||||
|
||||
*target = 0;
|
||||
instr.intval = read_memory_integer (addr, 4);
|
||||
/* printf("intval = %x\n",instr.intval); */
|
||||
switch (instr.op1.op1)
|
||||
{
|
||||
case 0: /* Format 2 */
|
||||
switch(instr.op2.op2)
|
||||
{
|
||||
case 2: case 6: /* BICC & FBCC */
|
||||
if (instr.branch.cond == 8)
|
||||
val = instr.branch.a ? baa : ba;
|
||||
else
|
||||
val = instr.branch.a ? bicca : bicc;
|
||||
/* 22 bits, sign extended */
|
||||
offset = ((instr.branch.disp << 10) >> 10);
|
||||
*target = addr + offset;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*printf("isabranch ret: %d\n",val); */
|
||||
return val;
|
||||
}
|
||||
|
||||
CORE_ADDR skip_prologue (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
union
|
||||
{
|
||||
struct insn_fmt insn;
|
||||
int i;
|
||||
} x;
|
||||
int dest = -1;
|
||||
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
if (x.insn.sethi.op == 0 && x.insn.sethi.op2 == 4)
|
||||
{
|
||||
dest = x.insn.sethi.rd;
|
||||
pc += 4;
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
}
|
||||
if (x.insn.arith_imm.op == 2 && x.insn.arith_imm.i == 1
|
||||
&& (x.insn.arith_imm.rd == 1 || x.insn.arith_imm.rd == dest))
|
||||
{
|
||||
pc += 4;
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
}
|
||||
if (x.insn.arith.op == 2 && (x.insn.arith.op3 ^ 32) == 28)
|
||||
{
|
||||
pc += 4;
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
frame_saved_pc (frame, next_frame)
|
||||
CORE_ADDR frame;
|
||||
CORE_ADDR next_frame;
|
||||
{
|
||||
CORE_ADDR prev_pc;
|
||||
|
||||
if (next_frame)
|
||||
prev_pc = GET_RWINDOW_REG (next_frame, rw_in[7]);
|
||||
else if (frame)
|
||||
prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]);
|
||||
else
|
||||
error ("frame_saved_pc called without a frame");
|
||||
|
||||
return PC_ADJUST (prev_pc);
|
||||
}
|
|
@ -196,7 +196,7 @@ frame_info (addr_exp)
|
|||
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));
|
||||
printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame, fi.next_frame));
|
||||
if (calling_frame)
|
||||
printf (" called by frame at 0x%x", calling_frame);
|
||||
if (fi.next_frame && calling_frame)
|
||||
|
@ -347,7 +347,7 @@ print_frame_arg_vars (frame, stream)
|
|||
for (i = 0; i < nsyms; i++)
|
||||
{
|
||||
sym = BLOCK_SYM (b, i);
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG)
|
||||
if (SYMBOL_CLASS (sym) == LOC_ARG || SYMBOL_CLASS (sym) == LOC_REGPARM)
|
||||
{
|
||||
fprintf (stream, "%s = ", SYMBOL_NAME (sym));
|
||||
print_variable_value (sym, frame, stream);
|
||||
|
@ -433,7 +433,7 @@ find_relative_frame (frame, level_offset_ptr)
|
|||
/* 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 algotithm is linear. */
|
||||
The following algorithm is linear. */
|
||||
if (*level_offset_ptr < 0)
|
||||
{
|
||||
/* First put frame1 at innermost frame
|
||||
|
|
|
@ -521,6 +521,10 @@ print_symbol (symbol, depth, outfile)
|
|||
fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
|
||||
break;
|
||||
|
||||
case LOC_REGPARM:
|
||||
fprintf (outfile, "parmameter register %d,", SYMBOL_VALUE (symbol));
|
||||
break;
|
||||
|
||||
case LOC_LOCAL:
|
||||
fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
|
||||
break;
|
||||
|
|
84
gdb/symseg.h
84
gdb/symseg.h
|
@ -1,5 +1,6 @@
|
|||
/* GDB symbol table format definitions.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
Hacked 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
|
||||
|
@ -117,6 +118,10 @@ enum type_code
|
|||
TYPE_CODE_SET, /* Pascal sets */
|
||||
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
|
||||
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
|
||||
|
||||
/* C++ */
|
||||
TYPE_CODE_MEMBER, /* Member type */
|
||||
TYPE_CODE_REF, /* C++ Reference types */
|
||||
};
|
||||
|
||||
/* This appears in a type's flags word for an unsigned integer type. */
|
||||
|
@ -124,6 +129,11 @@ enum type_code
|
|||
|
||||
/* Other flag bits are used with GDB. */
|
||||
|
||||
#define TYPE_FLAG_HAS_CONSTRUCTOR 256
|
||||
#define TYPE_FLAG_HAS_DESTRUCTOR 512
|
||||
#define TYPE_FLAG_VIA_PUBLIC 1024
|
||||
#define TYPE_FLAG_VIA_VIRTUAL 2048
|
||||
|
||||
struct type
|
||||
{
|
||||
/* Code for kind of type */
|
||||
|
@ -144,11 +154,23 @@ struct type
|
|||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *pointer_type;
|
||||
/* C++: also need a reference type. */
|
||||
struct type *reference_type;
|
||||
/* Type that is a function returning this type.
|
||||
Zero if no such function type is known here.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *function_type;
|
||||
|
||||
/* Handling of pointers to members:
|
||||
MAIN_VARIANT is used for pointer and pointer
|
||||
to member types. Normally it the value of the address of its
|
||||
containing type. However, for pointers to members, we must be
|
||||
able to allocate pointer to member types and look them up
|
||||
from some place of reference.
|
||||
NEXT_VARIANT is the next element in the chain. */
|
||||
struct type *main_variant, *next_variant;
|
||||
|
||||
/* Flags about this type. */
|
||||
short flags;
|
||||
/* Number of fields described for this type */
|
||||
|
@ -185,6 +207,67 @@ struct type
|
|||
Zero for range bounds and array domains. */
|
||||
char *name;
|
||||
} *fields;
|
||||
|
||||
/* C++ */
|
||||
int *private_field_bits;
|
||||
int *protected_field_bits;
|
||||
|
||||
/* Number of methods described for this type */
|
||||
short nfn_fields;
|
||||
/* Number of base classes this type derives from. */
|
||||
short n_baseclasses;
|
||||
|
||||
/* Number of methods described for this type plus all the
|
||||
methods that it derives from. */
|
||||
int nfn_fields_total;
|
||||
|
||||
/* For classes, structures, and unions, a description of each field,
|
||||
which consists of an overloaded name, followed by the types of
|
||||
arguments that the method expects, and then the name after it
|
||||
has been renamed to make it distinct. */
|
||||
struct fn_fieldlist
|
||||
{
|
||||
/* The overloaded name. */
|
||||
char *name;
|
||||
/* The number of methods with this name. */
|
||||
int length;
|
||||
/* The list of methods. */
|
||||
struct fn_field
|
||||
{
|
||||
#if 0
|
||||
/* The overloaded name */
|
||||
char *name;
|
||||
#endif
|
||||
/* The type of the argument */
|
||||
struct type *type;
|
||||
/* The argument list */
|
||||
struct type **args;
|
||||
/* The name after it has been processed */
|
||||
char *physname;
|
||||
/* If this is a virtual function, the offset into the vtbl-1,
|
||||
else 0. */
|
||||
int voffset;
|
||||
} *fn_fields;
|
||||
|
||||
int *private_fn_field_bits;
|
||||
int *protected_fn_field_bits;
|
||||
|
||||
} *fn_fieldlists;
|
||||
|
||||
/* For types with virtual functions, VPTR_BASETYPE is the base class which
|
||||
defined the virtual function table pointer. VPTR_FIELDNO is
|
||||
the field number of that pointer in the structure.
|
||||
|
||||
For types that are pointer to member types, VPTR_BASETYPE
|
||||
ifs the type that this pointer is a member of.
|
||||
|
||||
Unused otherwise. */
|
||||
struct type *vptr_basetype;
|
||||
|
||||
int vptr_fieldno;
|
||||
|
||||
/* If this type has base classes, put them here. */
|
||||
struct type **baseclasses;
|
||||
};
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
|
@ -287,6 +370,7 @@ enum address_class
|
|||
LOC_STATIC, /* Value is at fixed address */
|
||||
LOC_REGISTER, /* Value is in register */
|
||||
LOC_ARG, /* Value is at spec'd position in arglist */
|
||||
LOC_REGPARM, /* Value is at spec'd position in register window */
|
||||
LOC_LOCAL, /* Value is at spec'd pos in stack frame */
|
||||
LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
|
||||
Symbols in the namespace STRUCT_NAMESPACE
|
||||
|
|
548
gdb/symtab.c
548
gdb/symtab.c
|
@ -28,6 +28,9 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
|
||||
START_FILE
|
||||
|
||||
static int find_line_common();
|
||||
static int lookup_misc_func();
|
||||
|
||||
/* Allocate an obstack to hold objects that should be freed
|
||||
when we load a new symbol table.
|
||||
This includes the symbols made by dbxread
|
||||
|
@ -176,14 +179,17 @@ lookup_enum (name, block)
|
|||
}
|
||||
|
||||
/* Given a type TYPE, return a type of pointers to that type.
|
||||
May need to construct such a type if this is the first use. */
|
||||
May need to construct such a type if this is the first use.
|
||||
|
||||
C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer
|
||||
to member types under control. */
|
||||
|
||||
struct type *
|
||||
lookup_pointer_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *ptype = TYPE_POINTER_TYPE (type);
|
||||
if (ptype) return ptype;
|
||||
if (ptype) return TYPE_MAIN_VARIANT (ptype);
|
||||
|
||||
/* This is the first time anyone wanted a pointer to a TYPE. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
|
@ -193,6 +199,7 @@ lookup_pointer_type (type)
|
|||
sizeof (struct type));
|
||||
|
||||
bzero (ptype, sizeof (struct type));
|
||||
TYPE_MAIN_VARIANT (ptype) = ptype;
|
||||
TYPE_TARGET_TYPE (ptype) = type;
|
||||
TYPE_POINTER_TYPE (type) = ptype;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
|
@ -204,12 +211,150 @@ lookup_pointer_type (type)
|
|||
return ptype;
|
||||
}
|
||||
|
||||
struct type *
|
||||
lookup_reference_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *rtype = TYPE_REFERENCE_TYPE (type);
|
||||
if (rtype) return TYPE_MAIN_VARIANT (rtype);
|
||||
|
||||
/* This is the first time anyone wanted a pointer to a TYPE. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
rtype = (struct type *) xmalloc (sizeof (struct type));
|
||||
else
|
||||
rtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
|
||||
bzero (rtype, sizeof (struct type));
|
||||
TYPE_MAIN_VARIANT (rtype) = rtype;
|
||||
TYPE_TARGET_TYPE (rtype) = type;
|
||||
TYPE_REFERENCE_TYPE (type) = rtype;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (rtype) |= TYPE_FLAG_PERM;
|
||||
/* We assume the machine has only one representation for pointers! */
|
||||
TYPE_LENGTH (rtype) = sizeof (char *);
|
||||
TYPE_CODE (rtype) = TYPE_CODE_REF;
|
||||
return rtype;
|
||||
}
|
||||
|
||||
/* Implement direct support for MEMBER_TYPE in GNU C++.
|
||||
May need to construct such a type if this is the first use.
|
||||
The TYPE is the type of the member. The DOMAIN is the type
|
||||
of the aggregate that the member belongs to. */
|
||||
|
||||
struct type *
|
||||
lookup_member_type (domain, type)
|
||||
struct type *domain, *type;
|
||||
{
|
||||
register struct type *mtype = TYPE_MAIN_VARIANT (type);
|
||||
struct type *main_type;
|
||||
|
||||
main_type = mtype;
|
||||
while (mtype)
|
||||
{
|
||||
if (TYPE_DOMAIN_TYPE (mtype) == domain)
|
||||
return mtype;
|
||||
mtype = TYPE_NEXT_VARIANT (mtype);
|
||||
}
|
||||
|
||||
/* This is the first time anyone wanted this member type. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
mtype = (struct type *) xmalloc (sizeof (struct type));
|
||||
else
|
||||
mtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
|
||||
bzero (mtype, sizeof (struct type));
|
||||
if (main_type == 0) main_type = mtype;
|
||||
else
|
||||
{
|
||||
TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
|
||||
TYPE_NEXT_VARIANT (main_type) = mtype;
|
||||
}
|
||||
TYPE_MAIN_VARIANT (mtype) = main_type;
|
||||
TYPE_TARGET_TYPE (mtype) = type;
|
||||
TYPE_DOMAIN_TYPE (mtype) = domain;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
|
||||
|
||||
/* In practice, this is never used. */
|
||||
TYPE_LENGTH (mtype) = 1;
|
||||
TYPE_CODE (mtype) = TYPE_CODE_MEMBER;
|
||||
|
||||
return mtype;
|
||||
}
|
||||
|
||||
/* Given a type TYPE, return a type which has offset OFFSET,
|
||||
via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC.
|
||||
May need to construct such a type if none exists. */
|
||||
struct type *
|
||||
lookup_basetype_type (type, offset, via_virtual, via_public)
|
||||
struct type *type;
|
||||
int offset;
|
||||
int via_virtual, via_public;
|
||||
{
|
||||
register struct type *btype = TYPE_MAIN_VARIANT (type);
|
||||
struct type *main_type;
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
printf ("type offset non-zero in lookup_basetype_type");
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
main_type = btype;
|
||||
while (btype)
|
||||
{
|
||||
if (/* TYPE_OFFSET (btype) == offset
|
||||
&& */ TYPE_VIA_PUBLIC (btype) == via_public
|
||||
&& TYPE_VIA_VIRTUAL (btype) == via_virtual)
|
||||
return btype;
|
||||
btype = TYPE_NEXT_VARIANT (btype);
|
||||
}
|
||||
|
||||
/* This is the first time anyone wanted this member type. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
btype = (struct type *) xmalloc (sizeof (struct type));
|
||||
else
|
||||
btype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
|
||||
if (main_type == 0)
|
||||
{
|
||||
main_type = btype;
|
||||
bzero (btype, sizeof (struct type));
|
||||
TYPE_MAIN_VARIANT (btype) = main_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
bcopy (main_type, btype, sizeof (struct type));
|
||||
TYPE_NEXT_VARIANT (main_type) = btype;
|
||||
}
|
||||
/* TYPE_OFFSET (btype) = offset; */
|
||||
if (via_public)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_PUBLIC;
|
||||
if (via_virtual)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_VIRTUAL;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_PERM;
|
||||
|
||||
/* In practice, this is never used. */
|
||||
TYPE_LENGTH (btype) = 1;
|
||||
TYPE_CODE (btype) = TYPE_CODE_STRUCT;
|
||||
|
||||
return btype;
|
||||
}
|
||||
|
||||
/* Given a type TYPE, return a type of functions that return that type.
|
||||
May need to construct such a type if this is the first use. */
|
||||
|
||||
struct type *
|
||||
lookup_function_type (type)
|
||||
lookup_function_type (type, argtypes)
|
||||
struct type *type;
|
||||
struct type **argtypes;
|
||||
{
|
||||
register struct type *ptype = TYPE_FUNCTION_TYPE (type);
|
||||
if (ptype) return ptype;
|
||||
|
@ -247,6 +392,8 @@ smash_to_pointer_type (type, to_type)
|
|||
TYPE_LENGTH (type) = sizeof (char *);
|
||||
TYPE_CODE (type) = TYPE_CODE_PTR;
|
||||
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
|
||||
if (TYPE_POINTER_TYPE (to_type) == 0
|
||||
&& !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
|
||||
{
|
||||
|
@ -254,6 +401,46 @@ smash_to_pointer_type (type, to_type)
|
|||
}
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. */
|
||||
|
||||
void
|
||||
smash_to_member_type (type, domain, to_type)
|
||||
struct type *type, *domain, *to_type;
|
||||
{
|
||||
bzero (type, sizeof (struct type));
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
TYPE_DOMAIN_TYPE (type) = domain;
|
||||
|
||||
/* In practice, this is never needed. */
|
||||
TYPE_LENGTH (type) = 1;
|
||||
TYPE_CODE (type) = TYPE_CODE_MEMBER;
|
||||
|
||||
TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type);
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of reference to TO_TYPE.
|
||||
If TO_TYPE is not permanent and has no pointer-type yet,
|
||||
record TYPE as its pointer-type. */
|
||||
|
||||
void
|
||||
smash_to_reference_type (type, to_type)
|
||||
struct type *type, *to_type;
|
||||
{
|
||||
bzero (type, sizeof (struct type));
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
/* We assume the machine has only one representation for pointers! */
|
||||
TYPE_LENGTH (type) = sizeof (char *);
|
||||
TYPE_CODE (type) = TYPE_CODE_REF;
|
||||
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
|
||||
if (TYPE_REFERENCE_TYPE (to_type) == 0
|
||||
&& !(TYPE_FLAGS (type) & TYPE_FLAG_PERM))
|
||||
{
|
||||
TYPE_REFERENCE_TYPE (to_type) = type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of functions returning TO_TYPE.
|
||||
If TO_TYPE is not permanent and has no function-type yet,
|
||||
record TYPE as its function-type. */
|
||||
|
@ -281,6 +468,62 @@ static struct symbol *lookup_block_symbol ();
|
|||
in namespace NAMESPACE, visible from lexical block BLOCK.
|
||||
Returns the struct symbol pointer, or zero if no symbol is found. */
|
||||
|
||||
struct symbol *
|
||||
lookup_symbol_1 (name, block, namespace)
|
||||
char *name;
|
||||
register struct block *block;
|
||||
enum namespace namespace;
|
||||
{
|
||||
register int i, n;
|
||||
register struct symbol *sym;
|
||||
register struct symtab *s;
|
||||
struct blockvector *bv;
|
||||
|
||||
/* Search specified block and its superiors. */
|
||||
|
||||
while (block != 0)
|
||||
{
|
||||
sym = lookup_block_symbol (block, name, namespace);
|
||||
if (sym) return sym;
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct symbol *
|
||||
lookup_symbol_2 (name, block, namespace)
|
||||
char *name;
|
||||
register struct block *block; /* ignored as parameter */
|
||||
enum namespace namespace;
|
||||
{
|
||||
register int i, n;
|
||||
register struct symbol *sym;
|
||||
register struct symtab *s;
|
||||
struct blockvector *bv;
|
||||
|
||||
/* Now search all symtabs' global blocks. */
|
||||
|
||||
for (s = symtab_list; s; s = s->next)
|
||||
{
|
||||
bv = BLOCKVECTOR (s);
|
||||
block = BLOCKVECTOR_BLOCK (bv, 0);
|
||||
sym = lookup_block_symbol (block, name, namespace);
|
||||
if (sym) return sym;
|
||||
}
|
||||
|
||||
/* Now search all symtabs' per-file blocks.
|
||||
Not strictly correct, but more useful than an error. */
|
||||
|
||||
for (s = symtab_list; s; s = s->next)
|
||||
{
|
||||
bv = BLOCKVECTOR (s);
|
||||
block = BLOCKVECTOR_BLOCK (bv, 1);
|
||||
sym = lookup_block_symbol (block, name, namespace);
|
||||
if (sym) return sym;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct symbol *
|
||||
lookup_symbol (name, block, namespace)
|
||||
char *name;
|
||||
|
@ -742,13 +985,15 @@ find_pc_line_pc_range (pc, startptr, endptr)
|
|||
if no file is validly specified. Callers must check that.
|
||||
Also, the line number returned may be invalid. */
|
||||
|
||||
struct symtab_and_line
|
||||
struct symtabs_and_lines
|
||||
decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
||||
char **argptr;
|
||||
int funfirstline;
|
||||
struct symtab *default_symtab;
|
||||
int default_line;
|
||||
{
|
||||
struct symtabs_and_lines decode_line_2 ();
|
||||
struct symtabs_and_lines values;
|
||||
struct symtab_and_line value;
|
||||
register char *p, *p1;
|
||||
register struct symtab *s;
|
||||
|
@ -756,6 +1001,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
register CORE_ADDR pc;
|
||||
register int i;
|
||||
char *copy;
|
||||
struct symbol *sym_class;
|
||||
char *class_name, *method_name, *phys_name;
|
||||
int method_counter;
|
||||
int i1;
|
||||
struct symbol **sym_arr;
|
||||
struct type *t, *field;
|
||||
char **physnames;
|
||||
|
||||
/* Defaults have defaults. */
|
||||
|
||||
|
@ -771,9 +1023,11 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
{
|
||||
(*argptr)++;
|
||||
pc = parse_and_eval_address_1 (argptr);
|
||||
value = find_pc_line (pc, 0);
|
||||
value.pc = pc;
|
||||
return value;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.nelts = 1;
|
||||
values.sals[0] = find_pc_line (pc, 0);
|
||||
values.sals[0].pc = pc;
|
||||
return values;
|
||||
}
|
||||
|
||||
/* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
|
||||
|
@ -789,6 +1043,121 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
|
||||
if (p[0] == ':')
|
||||
{
|
||||
/* C++ */
|
||||
if (p[1] ==':')
|
||||
{
|
||||
/* Extract the class name. */
|
||||
p1 = p;
|
||||
while (p != *argptr && p[-1] == ' ') --p;
|
||||
copy = (char *) alloca (p - *argptr + 1);
|
||||
bcopy (*argptr, copy, p - *argptr);
|
||||
copy[p - *argptr] = 0;
|
||||
|
||||
/* Discard the class name from the arg. */
|
||||
p = p1 + 2;
|
||||
while (*p == ' ' || *p == '\t') p++;
|
||||
*argptr = p;
|
||||
|
||||
sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE);
|
||||
|
||||
if (sym_class &&
|
||||
(TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
|
||||
{
|
||||
/* Arg token is not digits => try it as a function name
|
||||
Find the next token (everything up to end or next whitespace). */
|
||||
p = *argptr;
|
||||
while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++;
|
||||
copy = (char *) alloca (p - *argptr + 1);
|
||||
bcopy (*argptr, copy, p - *argptr);
|
||||
copy[p - *argptr] = '\0';
|
||||
|
||||
/* no line number may be specified */
|
||||
while (*p == ' ' || *p == '\t') p++;
|
||||
*argptr = p;
|
||||
|
||||
sym = 0;
|
||||
i1 = 0; /* counter for the symbol array */
|
||||
t = SYMBOL_TYPE (sym_class);
|
||||
sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*));
|
||||
physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*));
|
||||
|
||||
if (destructor_name_p (copy, t))
|
||||
{
|
||||
/* destructors are a special case. */
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
|
||||
int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
|
||||
phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
|
||||
physnames[i1] = (char *)alloca (strlen (phys_name) + 1);
|
||||
strcpy (physnames[i1], phys_name);
|
||||
sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE);
|
||||
if (sym_arr[i1]) i1++;
|
||||
}
|
||||
else while (t)
|
||||
{
|
||||
class_name = TYPE_NAME (t);
|
||||
while (*class_name++ != ' ');
|
||||
|
||||
sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE);
|
||||
for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1;
|
||||
method_counter >= 0;
|
||||
--method_counter)
|
||||
{
|
||||
int field_counter;
|
||||
struct fn_field *f =
|
||||
TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter);
|
||||
|
||||
method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter);
|
||||
if (!strcmp (copy, method_name))
|
||||
for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1;
|
||||
field_counter >= 0;
|
||||
--field_counter)
|
||||
{
|
||||
phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
|
||||
physnames[i1] = (char*) alloca (strlen (phys_name) + 1);
|
||||
strcpy (physnames[i1], phys_name);
|
||||
sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE);
|
||||
if (sym_arr[i1]) i1++;
|
||||
}
|
||||
}
|
||||
if (TYPE_N_BASECLASSES (t))
|
||||
t = TYPE_BASECLASS(t, 1);
|
||||
else break;
|
||||
}
|
||||
|
||||
if (i1 == 1)
|
||||
{
|
||||
sym = sym_arr[0];
|
||||
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||
{
|
||||
/* Arg is the name of a function */
|
||||
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET;
|
||||
if (funfirstline)
|
||||
SKIP_PROLOGUE (pc);
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.nelts = 1;
|
||||
values.sals[0] = find_pc_line (pc, 0);
|
||||
values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc;
|
||||
}
|
||||
else
|
||||
{
|
||||
values.nelts = 0;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
if (i1 > 0)
|
||||
{
|
||||
return decode_line_2 (argptr, sym_arr, physnames, i1, funfirstline);
|
||||
}
|
||||
else
|
||||
error ("that class does not have any method named %s",copy);
|
||||
}
|
||||
else
|
||||
error("no class, struct, or union named %s", copy );
|
||||
}
|
||||
/* end of C++ */
|
||||
|
||||
/* Extract the file name. */
|
||||
p1 = p;
|
||||
while (p != *argptr && p[-1] == ' ') --p;
|
||||
|
@ -855,7 +1224,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
s = default_symtab;
|
||||
value.symtab = s;
|
||||
value.pc = 0;
|
||||
return value;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
}
|
||||
|
||||
/* Arg token is not digits => try it as a function name
|
||||
|
@ -882,7 +1254,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
SKIP_PROLOGUE (pc);
|
||||
value = find_pc_line (pc, 0);
|
||||
value.pc = (value.end && value.pc != pc) ? value.end : pc;
|
||||
return value;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
}
|
||||
|
||||
if (sym)
|
||||
|
@ -897,7 +1272,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
|
||||
if (funfirstline)
|
||||
SKIP_PROLOGUE (value.pc);
|
||||
return value;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
}
|
||||
|
||||
if (symtab_list == 0)
|
||||
|
@ -905,19 +1283,114 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
error ("Function %s not defined.", copy);
|
||||
}
|
||||
|
||||
struct symtab_and_line
|
||||
struct symtabs_and_lines
|
||||
decode_line_spec (string, funfirstline)
|
||||
char *string;
|
||||
int funfirstline;
|
||||
{
|
||||
struct symtab_and_line sal;
|
||||
struct symtabs_and_lines sals;
|
||||
if (string == 0)
|
||||
error ("Empty line specification.");
|
||||
sal = decode_line_1 (&string, funfirstline,
|
||||
current_source_symtab, current_source_line);
|
||||
sals = decode_line_1 (&string, funfirstline,
|
||||
current_source_symtab, current_source_line);
|
||||
if (*string)
|
||||
error ("Junk at end of line specification: %s", string);
|
||||
return sal;
|
||||
return sals;
|
||||
}
|
||||
|
||||
struct symtabs_and_lines
|
||||
decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline)
|
||||
char **argptr;
|
||||
struct symbol *sym_arr[];
|
||||
char *physnames[];
|
||||
int nelts;
|
||||
int funfirstline;
|
||||
{
|
||||
char *getenv();
|
||||
struct symtabs_and_lines values, return_values;
|
||||
register CORE_ADDR pc;
|
||||
char *args, *arg1, *read_line ();
|
||||
int i;
|
||||
char *prompt;
|
||||
|
||||
values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line));
|
||||
return_values.sals = (struct symtab_and_line *) malloc (nelts * sizeof(struct symtab_and_line));
|
||||
|
||||
i = 0;
|
||||
printf("[0] cancel\n[1] all\n");
|
||||
while (i < nelts)
|
||||
{
|
||||
if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
|
||||
{
|
||||
/* Arg is the name of a function */
|
||||
pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i]))
|
||||
+ FUNCTION_START_OFFSET;
|
||||
if (funfirstline)
|
||||
SKIP_PROLOGUE (pc);
|
||||
values.sals[i] = find_pc_line (pc, 0);
|
||||
printf("[%d] file:%s; line number:%d\n",
|
||||
(i+2), values.sals[i].symtab->filename, values.sals[i].line);
|
||||
}
|
||||
else printf ("?HERE\n");
|
||||
i++;
|
||||
}
|
||||
|
||||
if ((prompt = getenv ("PS2")) == NULL)
|
||||
{
|
||||
prompt = ">";
|
||||
}
|
||||
printf("%s ",prompt);
|
||||
fflush(stdout);
|
||||
|
||||
args = read_line (0);
|
||||
|
||||
if (args == 0)
|
||||
error_no_arg ("one or more choice numbers");
|
||||
|
||||
i = 0;
|
||||
while (*args)
|
||||
{
|
||||
int num;
|
||||
|
||||
arg1 = args;
|
||||
while (*arg1 >= '0' && *arg1 <= '9') arg1++;
|
||||
if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
|
||||
error ("Arguments must be choice numbers.");
|
||||
|
||||
num = atoi (args);
|
||||
|
||||
if (num == 0)
|
||||
error ("cancelled");
|
||||
else if (num == 1)
|
||||
{
|
||||
bcopy (values.sals, return_values.sals, (nelts * sizeof(struct symtab_and_line)));
|
||||
return_values.nelts = nelts;
|
||||
return return_values;
|
||||
}
|
||||
|
||||
if (num > nelts + 2)
|
||||
{
|
||||
printf ("No choice number %d.\n", num);
|
||||
}
|
||||
else
|
||||
{
|
||||
num -= 2;
|
||||
if (values.sals[num].pc)
|
||||
{
|
||||
return_values.sals[i++] = values.sals[num];
|
||||
values.sals[num].pc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("duplicate request for %d ignored.\n", num);
|
||||
}
|
||||
}
|
||||
|
||||
args = arg1;
|
||||
while (*args == ' ' || *args == '\t') args++;
|
||||
}
|
||||
return_values.nelts = i;
|
||||
return return_values;
|
||||
}
|
||||
|
||||
/* Return the index of misc function named NAME. */
|
||||
|
@ -998,7 +1471,7 @@ list_symbols (regexp, class)
|
|||
char *val;
|
||||
int found_in_file;
|
||||
static char *classnames[]
|
||||
= {"variable", "function", "type"};
|
||||
= {"variable", "function", "type", "method"};
|
||||
int print_count = 0;
|
||||
|
||||
if (regexp)
|
||||
|
@ -1035,7 +1508,8 @@ list_symbols (regexp, class)
|
|||
&& ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
|
||||
&& SYMBOL_CLASS (sym) != LOC_BLOCK)
|
||||
|| (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))
|
||||
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||
|| (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
|
||||
{
|
||||
if (!found_in_file)
|
||||
{
|
||||
|
@ -1050,17 +1524,30 @@ list_symbols (regexp, class)
|
|||
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
|
||||
printf ("typedef ");
|
||||
|
||||
type_print (SYMBOL_TYPE (sym),
|
||||
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
|
||||
? "" : SYMBOL_NAME (sym)),
|
||||
stdout, 0);
|
||||
if (class < 3)
|
||||
{
|
||||
type_print (SYMBOL_TYPE (sym),
|
||||
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
|
||||
? "" : SYMBOL_NAME (sym)),
|
||||
stdout, 0);
|
||||
printf (";\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[1024];
|
||||
# if 0
|
||||
type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0);
|
||||
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0);
|
||||
sprintf (buf, " %s::", TYPE_NAME (t));
|
||||
type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout);
|
||||
# endif
|
||||
}
|
||||
if (class == 2
|
||||
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE
|
||||
&& (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0
|
||||
|| 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))),
|
||||
SYMBOL_NAME (sym))))
|
||||
printf (" %s", SYMBOL_NAME (sym));
|
||||
printf (";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1088,6 +1575,13 @@ types_info (regexp)
|
|||
{
|
||||
list_symbols (regexp, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
methods_info (regexp)
|
||||
char *regexp;
|
||||
{
|
||||
list_symbols (regexp, 3);
|
||||
}
|
||||
|
||||
/* Call sort_block_syms to sort alphabetically the symbols of one block. */
|
||||
|
||||
|
@ -1124,6 +1618,7 @@ init_type (code, length, uns, name)
|
|||
|
||||
type = (struct type *) xmalloc (sizeof (struct type));
|
||||
bzero (type, sizeof *type);
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
TYPE_CODE (type) = code;
|
||||
TYPE_LENGTH (type) = length;
|
||||
TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0;
|
||||
|
@ -1131,6 +1626,10 @@ init_type (code, length, uns, name)
|
|||
TYPE_NFIELDS (type) = 0;
|
||||
TYPE_NAME (type) = name;
|
||||
|
||||
/* C++ fancies. */
|
||||
TYPE_NFN_FIELDS (type) = 0;
|
||||
TYPE_N_BASECLASSES (type) = 0;
|
||||
TYPE_BASECLASSES (type) = 0;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -1143,6 +1642,11 @@ initialize ()
|
|||
"All function names, or those matching REGEXP.");
|
||||
add_info ("types", types_info,
|
||||
"All types names, or those matching REGEXP.");
|
||||
add_info ("methods", methods_info,
|
||||
"All method names, or those matching REGEXP::REGEXP.\n\
|
||||
If the class qualifier is ommited, it is assumed to be the current scope.\n\
|
||||
If the first REGEXP is ommited, then all methods matching the second REGEXP\n\
|
||||
are listed.");
|
||||
add_info ("sources", sources_info,
|
||||
"Source files in the program.");
|
||||
|
||||
|
|
74
gdb/symtab.h
74
gdb/symtab.h
|
@ -75,7 +75,7 @@ struct symtab
|
|||
free_linetable => free just the linetable. */
|
||||
enum free_code {free_nothing, free_contents, free_linetable}
|
||||
free_code;
|
||||
/* Pointer to one block storage to be freed, if nonzero. */
|
||||
/* Pointer to one block of storage to be freed, if nonzero. */
|
||||
char *free_ptr;
|
||||
/* Total number of lines found in source file. */
|
||||
int nlines;
|
||||
|
@ -148,16 +148,36 @@ int current_source_line;
|
|||
These types are never freed. */
|
||||
#define TYPE_FLAG_PERM 4
|
||||
|
||||
/* Some macros for bitfields. */
|
||||
#define B_SET(a,x) (a[x>>5] |= (1 << (x&31)))
|
||||
#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31)))
|
||||
#define B_TST(a,x) (a[x>>5] & (1 << (x&31)))
|
||||
|
||||
#define TYPE_NAME(thistype) (thistype)->name
|
||||
#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
|
||||
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
|
||||
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
|
||||
#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
|
||||
#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant
|
||||
#define TYPE_NEXT_VARIANT(thistype) (thistype)->next_variant
|
||||
#define TYPE_LENGTH(thistype) (thistype)->length
|
||||
#define TYPE_FLAGS(thistype) (thistype)->flags
|
||||
#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
|
||||
#define TYPE_CODE(thistype) (thistype)->code
|
||||
#define TYPE_NFIELDS(thistype) (thistype)->nfields
|
||||
#define TYPE_FIELDS(thistype) (thistype)->fields
|
||||
/* C++ */
|
||||
#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
|
||||
#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
|
||||
#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
|
||||
#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields
|
||||
#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields
|
||||
#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total
|
||||
#define TYPE_BASECLASSES(thistype) (thistype)->baseclasses
|
||||
#define TYPE_BASECLASS(thistype,index) (thistype)->baseclasses[index]
|
||||
#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses
|
||||
#define TYPE_VIA_PUBLIC(thistype) ((thistype)->flags & TYPE_FLAG_VIA_PUBLIC)
|
||||
#define TYPE_VIA_VIRTUAL(thistype) ((thistype)->flags & TYPE_FLAG_VIA_VIRTUAL)
|
||||
|
||||
#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
|
||||
#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
|
||||
|
@ -166,11 +186,46 @@ int current_source_line;
|
|||
#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
|
||||
#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
|
||||
#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
|
||||
|
||||
#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits
|
||||
#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits
|
||||
#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n))
|
||||
#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n))
|
||||
#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n))
|
||||
#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n))
|
||||
|
||||
#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_DESTRUCTOR)
|
||||
#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_CONSTRUCTOR)
|
||||
|
||||
#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
|
||||
#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
|
||||
|
||||
#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists
|
||||
#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n]
|
||||
#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields
|
||||
#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name
|
||||
#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length
|
||||
|
||||
#define TYPE_FN_FIELD(thistype) (thistype)[n]
|
||||
#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name
|
||||
#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
|
||||
#define TYPE_FN_FIELD_ARGS(thistype, n) (thistype)[n].args
|
||||
#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
|
||||
#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) (thistype)[n].voffset
|
||||
#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
|
||||
|
||||
#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
|
||||
#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits
|
||||
#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n)
|
||||
#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n)
|
||||
#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n)
|
||||
#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n)
|
||||
|
||||
/* Functions that work on the objects described above */
|
||||
|
||||
extern struct symtab *lookup_symtab ();
|
||||
extern struct symbol *lookup_symbol ();
|
||||
extern struct symbol *lookup_symbol_1 (), *lookup_symbol_2 ();
|
||||
extern struct type *lookup_typename ();
|
||||
extern struct type *lookup_unsigned_typename ();
|
||||
extern struct type *lookup_struct ();
|
||||
|
@ -178,10 +233,17 @@ extern struct type *lookup_union ();
|
|||
extern struct type *lookup_enum ();
|
||||
extern struct type *lookup_pointer_type ();
|
||||
extern struct type *lookup_function_type ();
|
||||
extern struct type *lookup_basetype_type ();
|
||||
extern struct symbol *block_function ();
|
||||
extern struct symbol *find_pc_function ();
|
||||
extern int find_pc_misc_function ();
|
||||
|
||||
/* C++ stuff. */
|
||||
extern struct type *lookup_reference_type ();
|
||||
extern struct type *lookup_member_type ();
|
||||
extern struct type *lookup_class ();
|
||||
/* end of C++ stuff. */
|
||||
|
||||
extern struct type *builtin_type_void;
|
||||
extern struct type *builtin_type_char;
|
||||
extern struct type *builtin_type_short;
|
||||
|
@ -202,6 +264,12 @@ struct symtab_and_line
|
|||
CORE_ADDR end;
|
||||
};
|
||||
|
||||
struct symtabs_and_lines
|
||||
{
|
||||
struct symtab_and_line *sals;
|
||||
int nelts;
|
||||
};
|
||||
|
||||
/* Given a pc value, return line number it is in.
|
||||
Second arg nonzero means if pc is on the boundary
|
||||
use the previous statement's line number. */
|
||||
|
@ -211,5 +279,5 @@ struct symtab_and_line find_pc_line ();
|
|||
/* Given a string, return the line specified by it.
|
||||
For commands like "list" and "breakpoint". */
|
||||
|
||||
struct symtab_and_line decode_line_spec ();
|
||||
struct symtab_and_line decode_line_1 ();
|
||||
struct symtabs_and_lines decode_line_spec ();
|
||||
struct symtabs_and_lines decode_line_1 ();
|
||||
|
|
6
gdb/test.c
Normal file
6
gdb/test.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <Rational.h>
|
||||
|
||||
main ()
|
||||
{
|
||||
Rational r = Rational (PI);
|
||||
}
|
40
gdb/test4.c
Normal file
40
gdb/test4.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
main()
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
i = 100;
|
||||
j = 101;
|
||||
k = foo(0,1,2,3,4,5,6,7,8);
|
||||
}
|
||||
|
||||
int f3 (x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
int f2 (x)
|
||||
{
|
||||
return f3 (x+1);
|
||||
}
|
||||
|
||||
int f1 (x)
|
||||
{
|
||||
return f2 (x+1);
|
||||
}
|
||||
|
||||
foo(a,b,c,d,e,f,g,h,i)
|
||||
int a,b,c,d,e,f,g,h,i;
|
||||
{
|
||||
int r;
|
||||
r = a + b + c + d + e + f + g + h + i;
|
||||
if (f1 (11))
|
||||
return r;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bar(ind)
|
||||
int ind;
|
||||
{
|
||||
printf("this is a test\n");
|
||||
}
|
111
gdb/teststruct.c
Normal file
111
gdb/teststruct.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
struct small
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
struct med
|
||||
{
|
||||
struct small s1, s2;
|
||||
};
|
||||
|
||||
struct large
|
||||
{
|
||||
struct med m1, m2;
|
||||
};
|
||||
|
||||
struct xlarge
|
||||
{
|
||||
struct large l1, l2;
|
||||
};
|
||||
|
||||
struct small ret_small ();
|
||||
struct med ret_med ();
|
||||
struct large ret_large ();
|
||||
struct xlarge ret_xlarge ();
|
||||
|
||||
void print_small ();
|
||||
void print_med ();
|
||||
void print_large ();
|
||||
void print_xlarge ();
|
||||
|
||||
main ()
|
||||
{
|
||||
struct small s;
|
||||
struct med m;
|
||||
struct large l;
|
||||
struct xlarge x;
|
||||
|
||||
s = ret_small (1);
|
||||
m = ret_med (s,s);
|
||||
l = ret_large (m, m);
|
||||
x = ret_xlarge (l, l);
|
||||
|
||||
print_small (s);
|
||||
print_med (m);
|
||||
print_large (l);
|
||||
print_xlarge (x);
|
||||
}
|
||||
|
||||
struct small ret_small (i)
|
||||
int i;
|
||||
{
|
||||
struct small s;
|
||||
s.i = i;
|
||||
return s;
|
||||
}
|
||||
|
||||
struct med ret_med (s1, s2)
|
||||
struct small s1, s2;
|
||||
{
|
||||
struct med m;
|
||||
m.s1 = s1;
|
||||
m.s2 = s2;
|
||||
return m;
|
||||
}
|
||||
|
||||
struct large ret_large (m1, m2)
|
||||
struct med m1, m2;
|
||||
{
|
||||
struct large l;
|
||||
l.m1 = m1;
|
||||
l.m2 = m2;
|
||||
return l;
|
||||
}
|
||||
|
||||
struct xlarge ret_xlarge (l1, l2)
|
||||
struct large l1, l2;
|
||||
{
|
||||
struct xlarge x;
|
||||
x.l1 = l1;
|
||||
x.l2 = l2;
|
||||
return x;
|
||||
}
|
||||
|
||||
void print_small (s)
|
||||
struct small s;
|
||||
{
|
||||
printf ("small: s.i = %d\n", s.i);
|
||||
}
|
||||
|
||||
void print_med (m)
|
||||
struct med m;
|
||||
{
|
||||
printf ("med: m.s1.i = %d; m.s2.i = %d\n", m.s1.i, m.s2.i);
|
||||
}
|
||||
|
||||
void print_large (l)
|
||||
struct large l;
|
||||
{
|
||||
printf ("large: l.m1.s1.i = %d; l.m1.s2.i = %d; l.m2.s1.i = %d; l.m2.s2.i = %d\n",
|
||||
l.m1.s1.i, l.m1.s2.i, l.m2.s1.i, l.m2.s2.i);
|
||||
}
|
||||
|
||||
void print_xlarge (x)
|
||||
struct xlarge x;
|
||||
{
|
||||
printf ("xlarge: x.l1: ");
|
||||
print_large (x.l1);
|
||||
printf ("xlarge: x.l2: ");
|
||||
print_large (x.l2);
|
||||
}
|
||||
|
175
gdb/valarith.c
175
gdb/valarith.c
|
@ -27,6 +27,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
|
||||
START_FILE
|
||||
|
||||
value value_x_binop ();
|
||||
|
||||
value
|
||||
value_add (arg1, arg2)
|
||||
value arg1, arg2;
|
||||
|
@ -107,7 +109,172 @@ value_subscript (array, idx)
|
|||
{
|
||||
return value_ind (value_add (array, idx));
|
||||
}
|
||||
|
||||
/* Check to see if either argument is a structure. This is called so
|
||||
we know whether to go ahead with the normal binop or look for a
|
||||
user defined function instead.
|
||||
|
||||
For now, we do not overload the `=' operator. */
|
||||
|
||||
int
|
||||
binop_user_defined_p (op, arg1, arg2)
|
||||
enum exp_opcode op;
|
||||
value arg1, arg2;
|
||||
{
|
||||
if (op == BINOP_ASSIGN)
|
||||
return 0;
|
||||
return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT
|
||||
|| (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
|
||||
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT)
|
||||
|| (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF
|
||||
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT));
|
||||
}
|
||||
|
||||
/* Check to see if argument is a structure. This is called so
|
||||
we know whether to go ahead with the normal unop or look for a
|
||||
user defined function instead.
|
||||
|
||||
For now, we do not overload the `&' operator. */
|
||||
|
||||
int unop_user_defined_p (op, arg1)
|
||||
enum exp_opcode op;
|
||||
value arg1;
|
||||
{
|
||||
if (op == UNOP_ADDR)
|
||||
return 0;
|
||||
return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT
|
||||
|| (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
|
||||
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT));
|
||||
}
|
||||
|
||||
/* We know either arg1 or arg2 is a structure, so try to find the right
|
||||
user defined function. Create an argument vector that calls
|
||||
arg1.operator @ (arg1,arg2) and return that value (where '@' is any
|
||||
binary operator which is legal for GNU C++). */
|
||||
|
||||
value
|
||||
value_x_binop (arg1, arg2, op, otherop)
|
||||
value arg1, arg2;
|
||||
int op, otherop;
|
||||
{
|
||||
value * argvec;
|
||||
char *ptr;
|
||||
char tstr[13];
|
||||
|
||||
COERCE_ENUM (arg1);
|
||||
COERCE_ENUM (arg2);
|
||||
|
||||
/* now we know that what we have to do is construct our
|
||||
arg vector and find the right function to call it with. */
|
||||
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
|
||||
error ("friend functions not implemented yet");
|
||||
|
||||
argvec = (value *) alloca (sizeof (value) * 4);
|
||||
argvec[1] = value_addr (arg1);
|
||||
argvec[2] = arg2;
|
||||
argvec[3] = 0;
|
||||
|
||||
/* make the right function name up */
|
||||
strcpy(tstr, "operator __");
|
||||
ptr = tstr+9;
|
||||
switch (op)
|
||||
{
|
||||
case BINOP_ADD: strcpy(ptr,"+"); break;
|
||||
case BINOP_SUB: strcpy(ptr,"-"); break;
|
||||
case BINOP_MUL: strcpy(ptr,"*"); break;
|
||||
case BINOP_DIV: strcpy(ptr,"/"); break;
|
||||
case BINOP_REM: strcpy(ptr,"%"); break;
|
||||
case BINOP_LSH: strcpy(ptr,"<<"); break;
|
||||
case BINOP_RSH: strcpy(ptr,">>"); break;
|
||||
case BINOP_LOGAND: strcpy(ptr,"&"); break;
|
||||
case BINOP_LOGIOR: strcpy(ptr,"|"); break;
|
||||
case BINOP_LOGXOR: strcpy(ptr,"^"); break;
|
||||
case BINOP_AND: strcpy(ptr,"&&"); break;
|
||||
case BINOP_OR: strcpy(ptr,"||"); break;
|
||||
case BINOP_MIN: strcpy(ptr,"<?"); break;
|
||||
case BINOP_MAX: strcpy(ptr,">?"); break;
|
||||
case BINOP_ASSIGN: strcpy(ptr,"="); break;
|
||||
case BINOP_ASSIGN_MODIFY:
|
||||
switch (otherop)
|
||||
{
|
||||
case BINOP_ADD: strcpy(ptr,"+="); break;
|
||||
case BINOP_SUB: strcpy(ptr,"-="); break;
|
||||
case BINOP_MUL: strcpy(ptr,"*="); break;
|
||||
case BINOP_DIV: strcpy(ptr,"/="); break;
|
||||
case BINOP_REM: strcpy(ptr,"%="); break;
|
||||
case BINOP_LOGAND: strcpy(ptr,"&="); break;
|
||||
case BINOP_LOGIOR: strcpy(ptr,"|="); break;
|
||||
case BINOP_LOGXOR: strcpy(ptr,"^="); break;
|
||||
default:
|
||||
error ("Invalid binary operation specified.");
|
||||
}
|
||||
break;
|
||||
case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break;
|
||||
case BINOP_EQUAL: strcpy(ptr,"=="); break;
|
||||
case BINOP_NOTEQUAL: strcpy(ptr,"!="); break;
|
||||
case BINOP_LESS: strcpy(ptr,"<"); break;
|
||||
case BINOP_GTR: strcpy(ptr,">"); break;
|
||||
case BINOP_GEQ: strcpy(ptr,">="); break;
|
||||
case BINOP_LEQ: strcpy(ptr,"<="); break;
|
||||
default:
|
||||
error ("Invalid binary operation specified.");
|
||||
}
|
||||
argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure");
|
||||
if (argvec[0])
|
||||
return call_function (argvec[0], 2, argvec + 1);
|
||||
else error ("member function %s not found", tstr);
|
||||
}
|
||||
|
||||
/* We know that arg1 is a structure, so try to find a unary user
|
||||
defined operator that matches the operator in question.
|
||||
Create an argument vector that calls arg1.operator @ (arg1)
|
||||
and return that value (where '@' is (almost) any unary operator which
|
||||
is legal for GNU C++). */
|
||||
|
||||
value
|
||||
value_x_unop (arg1, op)
|
||||
value arg1;
|
||||
int op;
|
||||
{
|
||||
value * argvec;
|
||||
char *ptr;
|
||||
char tstr[13];
|
||||
|
||||
COERCE_ENUM (arg1);
|
||||
|
||||
/* now we know that what we have to do is construct our
|
||||
arg vector and find the right function to call it with. */
|
||||
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT)
|
||||
error ("friend functions not implemented yet");
|
||||
|
||||
argvec = (value *) alloca (sizeof (value) * 3);
|
||||
argvec[1] = value_addr (arg1);
|
||||
argvec[2] = 0;
|
||||
|
||||
/* make the right function name up */
|
||||
strcpy(tstr,"operator __");
|
||||
ptr = tstr+9;
|
||||
switch (op)
|
||||
{
|
||||
case UNOP_PREINCREMENT: strcpy(ptr,"++"); break;
|
||||
case UNOP_PREDECREMENT: strcpy(ptr,"++"); break;
|
||||
case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break;
|
||||
case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break;
|
||||
case UNOP_ZEROP: strcpy(ptr,"!"); break;
|
||||
case UNOP_LOGNOT: strcpy(ptr,"~"); break;
|
||||
case UNOP_NEG: strcpy(ptr,"-"); break;
|
||||
default:
|
||||
error ("Invalid binary operation specified.");
|
||||
}
|
||||
argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure");
|
||||
if (argvec[0])
|
||||
return call_function (argvec[0], 1, argvec + 1);
|
||||
else error ("member function %s not found", tstr);
|
||||
}
|
||||
|
||||
/* Perform a binary operation on two integers or two floats.
|
||||
Does not support addition and subtraction on pointers;
|
||||
use value_add or value_sub if you want to handle those possibilities. */
|
||||
|
@ -219,6 +386,14 @@ value_binop (arg1, arg2, op)
|
|||
v = v1 || v2;
|
||||
break;
|
||||
|
||||
case BINOP_MIN:
|
||||
v = v1 < v2 ? v1 : v2;
|
||||
break;
|
||||
|
||||
case BINOP_MAX:
|
||||
v = v1 > v2 ? v1 : v2;
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid binary operation on numbers.");
|
||||
}
|
||||
|
|
517
gdb/valops.c
517
gdb/valops.c
|
@ -276,8 +276,17 @@ value
|
|||
value_ind (arg1)
|
||||
value arg1;
|
||||
{
|
||||
/* Must do this before COERCE_ARRAY, otherwise an infinite loop
|
||||
will result. */
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
|
||||
return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
|
||||
(CORE_ADDR) value_as_long (arg1));
|
||||
|
||||
COERCE_ARRAY (arg1);
|
||||
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MEMBER)
|
||||
error ("not implemented: member types in value_ind");
|
||||
|
||||
/* Allow * on an integer so we can cast it to whatever we want. */
|
||||
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
|
||||
return value_at (builtin_type_long,
|
||||
|
@ -285,6 +294,9 @@ value_ind (arg1)
|
|||
else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
|
||||
return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
|
||||
(CORE_ADDR) value_as_long (arg1));
|
||||
else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
|
||||
return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
|
||||
(CORE_ADDR) value_as_long (arg1));
|
||||
error ("Attempt to take contents of a non-pointer value.");
|
||||
}
|
||||
|
||||
|
@ -406,11 +418,29 @@ call_function (function, nargs, args)
|
|||
|
||||
PUSH_DUMMY_FRAME;
|
||||
|
||||
old_sp = sp = read_register (SP_REGNUM);
|
||||
|
||||
#if 1 INNER_THAN 2 /* Stack grows down */
|
||||
sp -= sizeof dummy;
|
||||
start_sp = sp;
|
||||
#else /* Stack grows up */
|
||||
start_sp = sp;
|
||||
sp += sizeof dummy;
|
||||
#endif
|
||||
|
||||
{
|
||||
register CORE_ADDR funaddr;
|
||||
register struct type *ftype = VALUE_TYPE (function);
|
||||
register enum type_code code = TYPE_CODE (ftype);
|
||||
|
||||
/* If it's a member function, just look at the function
|
||||
part of it. */
|
||||
if (code == TYPE_CODE_MEMBER)
|
||||
{
|
||||
ftype = TYPE_TARGET_TYPE (ftype);
|
||||
code = TYPE_CODE (ftype);
|
||||
}
|
||||
|
||||
/* Determine address to call. */
|
||||
if (code == TYPE_CODE_FUNC)
|
||||
{
|
||||
|
@ -444,24 +474,40 @@ call_function (function, nargs, args)
|
|||
/* Create a call sequence customized for this function
|
||||
and the number of arguments for it. */
|
||||
bcopy (dummy, dummy1, sizeof dummy);
|
||||
#ifdef sun4
|
||||
FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, value_type);
|
||||
#else
|
||||
FIX_CALL_DUMMY (dummy1, funaddr, nargs);
|
||||
#endif
|
||||
}
|
||||
|
||||
old_sp = sp = read_register (SP_REGNUM);
|
||||
write_memory (start_sp, dummy1, sizeof dummy);
|
||||
|
||||
#ifdef STACK_ALIGN
|
||||
/* If stack grows down, we must leave a hole at the top. */
|
||||
{
|
||||
int len = 0;
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
len += TYPE_LENGTH (VALUE_TYPE (args[i]));
|
||||
len += CALL_DUMMY_STACK_ADJUST;
|
||||
#if 1 INNER_THAN 2
|
||||
sp -= STACK_ALIGN (len) - len;
|
||||
#else
|
||||
sp += STACK_ALIGN (len) - len;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1 INNER_THAN 2 /* Stack grows down */
|
||||
sp -= sizeof dummy;
|
||||
write_memory (sp, dummy1, sizeof dummy);
|
||||
start_sp = sp;
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
sp = value_arg_push (sp, args[i]);
|
||||
#else /* Stack grows up */
|
||||
start_sp = sp;
|
||||
write_memory (sp, dummy1, sizeof dummy);
|
||||
sp += sizeof dummy;
|
||||
for (i = 0; i < nargs; i++)
|
||||
sp = value_arg_push (sp, args[i]);
|
||||
#endif /* Stack grows up */
|
||||
|
||||
#ifdef CALL_DUMMY_STACK_ADJUST
|
||||
#if 1 INNER_THAN 2
|
||||
sp -= CALL_DUMMY_STACK_ADJUST;
|
||||
#else
|
||||
sp += CALL_DUMMY_STACK_ADJUST;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
write_register (SP_REGNUM, sp);
|
||||
|
||||
|
@ -552,16 +598,24 @@ value_string (ptr, len)
|
|||
/* Given ARG1, a value of type (pointer to a)* structure/union,
|
||||
extract the component named NAME from the ultimate target structure/union
|
||||
and return it as a value with its appropriate type.
|
||||
ERR is used in the error message if ARG1's type is wrong. */
|
||||
|
||||
ERR is used in the error message if ARG1's type is wrong.
|
||||
|
||||
C++: ARGS is a list of argument types to aid in the selection of
|
||||
an appropriate method. Also, handle derived types.
|
||||
|
||||
ERR is an error message to be printed in case the field is not found. */
|
||||
|
||||
value
|
||||
value_struct_elt (arg1, name, err)
|
||||
register value arg1;
|
||||
value_struct_elt (arg1, args, name, err)
|
||||
register value arg1, *args;
|
||||
char *name;
|
||||
char *err;
|
||||
{
|
||||
register struct type *t;
|
||||
register int i;
|
||||
int found = 0;
|
||||
|
||||
struct type *baseclass;
|
||||
|
||||
COERCE_ARRAY (arg1);
|
||||
|
||||
|
@ -569,28 +623,443 @@ value_struct_elt (arg1, name, err)
|
|||
|
||||
/* Follow pointers until we get to a non-pointer. */
|
||||
|
||||
while (TYPE_CODE (t) == TYPE_CODE_PTR)
|
||||
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
|
||||
{
|
||||
arg1 = value_ind (arg1);
|
||||
COERCE_ARRAY (arg1);
|
||||
t = VALUE_TYPE (arg1);
|
||||
}
|
||||
|
||||
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
|
||||
error ("not implemented: member type in value_struct_elt");
|
||||
|
||||
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&&
|
||||
TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error ("Attempt to extract a component of a value that is not a %s.", err);
|
||||
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
break;
|
||||
baseclass = t;
|
||||
|
||||
if (!args)
|
||||
{
|
||||
/* if there are no arguments ...do this... */
|
||||
|
||||
/* Try as a variable first, because if we succeed, there
|
||||
is less work to be done. */
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
return TYPE_FIELD_STATIC (t, i)
|
||||
? value_static_field (t, name, i) : value_field (arg1, i);
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
}
|
||||
|
||||
/* C++: If it was not found as a data field, then try to
|
||||
return it as a pointer to a method. */
|
||||
t = baseclass;
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
|
||||
if (destructor_name_p (name, t))
|
||||
error ("use `info method' command to print out value of destructor");
|
||||
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
|
||||
{
|
||||
if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
|
||||
{
|
||||
error ("use `info method' command to print value of method \"%s\"", name);
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
error("there is no field named %s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
error ("Structure has no component named %s.", name);
|
||||
if (destructor_name_p (name, t))
|
||||
{
|
||||
if (!args[1])
|
||||
{
|
||||
/* destructors are a special case. */
|
||||
return (value)value_fn_field (arg1, 0, TYPE_FN_FIELDLIST_LENGTH (t, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("destructor should not have any argument");
|
||||
}
|
||||
}
|
||||
|
||||
return value_field (arg1, i);
|
||||
/* This following loop is for methods with arguments. */
|
||||
while (t)
|
||||
{
|
||||
/* Look up as method first, because that is where we
|
||||
expect to find it first. */
|
||||
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
|
||||
|
||||
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
|
||||
{
|
||||
int j;
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
|
||||
|
||||
found = 1;
|
||||
for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --j)
|
||||
{
|
||||
if (!typecmp (TYPE_FN_FIELD_ARGS (f, j), args))
|
||||
{
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
return (value)value_virtual_fn_field (arg1, f, j, t);
|
||||
else
|
||||
return (value)value_fn_field (arg1, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
error ("Structure method %s not defined for arglist.", name);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* See if user tried to invoke data as function */
|
||||
t = baseclass;
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 0)
|
||||
return TYPE_FIELD_STATIC (t, i)
|
||||
? value_static_field (t, name, i) : value_field (arg1, i);
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
}
|
||||
error ("Structure has no component named %s.", name);
|
||||
}
|
||||
}
|
||||
|
||||
/* C++: return 1 is NAME is a legitimate name for the destructor
|
||||
of type TYPE. If TYPE does not have a destructor, or
|
||||
if NAME is inappropriate for TYPE, an error is signaled. */
|
||||
int
|
||||
destructor_name_p (name, type)
|
||||
char *name;
|
||||
struct type *type;
|
||||
{
|
||||
/* destructors are a special case. */
|
||||
char *dname = TYPE_NAME (type);
|
||||
|
||||
if (name[0] == '~')
|
||||
{
|
||||
if (! TYPE_HAS_DESTRUCTOR (type))
|
||||
error ("type `%s' does not have destructor defined",
|
||||
TYPE_NAME (type));
|
||||
/* Skip past the "struct " at the front. */
|
||||
while (*dname++ != ' ') ;
|
||||
if (strcmp (dname, name+1))
|
||||
error ("destructor specification error");
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
|
||||
return 1 if the component named NAME from the ultimate
|
||||
target structure/union is defined, otherwise, return 0. */
|
||||
|
||||
int
|
||||
check_field (arg1, name)
|
||||
register value arg1;
|
||||
char *name;
|
||||
{
|
||||
register struct type *t;
|
||||
register int i;
|
||||
int found = 0;
|
||||
|
||||
struct type *baseclass;
|
||||
|
||||
COERCE_ARRAY (arg1);
|
||||
|
||||
t = VALUE_TYPE (arg1);
|
||||
|
||||
/* Follow pointers until we get to a non-pointer. */
|
||||
|
||||
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
|
||||
{
|
||||
arg1 = value_ind (arg1);
|
||||
COERCE_ARRAY (arg1);
|
||||
t = VALUE_TYPE (arg1);
|
||||
}
|
||||
|
||||
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
|
||||
error ("not implemented: member type in check_field");
|
||||
|
||||
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error ("Internal error: `this' is not an aggregate");
|
||||
|
||||
baseclass = t;
|
||||
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
}
|
||||
|
||||
/* C++: If it was not found as a data field, then try to
|
||||
return it as a pointer to a method. */
|
||||
t = baseclass;
|
||||
VALUE_TYPE (arg1) = t; /* side effect! */
|
||||
|
||||
/* Destructors are a special case. */
|
||||
if (destructor_name_p (name, t))
|
||||
return 1;
|
||||
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
|
||||
{
|
||||
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C++: Given an aggregate type DOMAIN, and a member name NAME,
|
||||
return the address of this member as a pointer to member
|
||||
type. If INTYPE is non-null, then it will be the type
|
||||
of the member we are looking for. This will help us resolve
|
||||
pointers to member functions. */
|
||||
|
||||
value
|
||||
value_struct_elt_for_address (domain, intype, name)
|
||||
struct type *domain, *intype;
|
||||
char *name;
|
||||
{
|
||||
register struct type *t = domain;
|
||||
register int i;
|
||||
int found = 0;
|
||||
value v;
|
||||
|
||||
struct type *baseclass;
|
||||
|
||||
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error ("Internal error: non-aggregate type to value_struct_elt_for_address");
|
||||
|
||||
baseclass = t;
|
||||
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
{
|
||||
if (TYPE_FIELD_PACKED (t, i))
|
||||
error ("pointers to bitfield members not allowed");
|
||||
|
||||
v = value_from_long (builtin_type_int, TYPE_FIELD_BITPOS (t, i) >> 3);
|
||||
VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
|
||||
/* C++: If it was not found as a data field, then try to
|
||||
return it as a pointer to a method. */
|
||||
t = baseclass;
|
||||
|
||||
/* Destructors are a special case. */
|
||||
if (destructor_name_p (name, t))
|
||||
{
|
||||
error ("pointers to destructors not implemented yet");
|
||||
}
|
||||
|
||||
/* Perform all necessary dereferencing. */
|
||||
while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
|
||||
intype = TYPE_TARGET_TYPE (intype);
|
||||
|
||||
while (t)
|
||||
{
|
||||
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
|
||||
{
|
||||
if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
|
||||
{
|
||||
int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
|
||||
|
||||
if (intype == 0 && j > 1)
|
||||
error ("non-unique member `%s' requires type instantiation", name);
|
||||
if (intype)
|
||||
{
|
||||
while (j--)
|
||||
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
|
||||
break;
|
||||
if (j < 0)
|
||||
error ("no member function matches that type instantiation");
|
||||
}
|
||||
else
|
||||
j = 0;
|
||||
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
{
|
||||
v = value_from_long (builtin_type_long,
|
||||
TYPE_FN_FIELD_VOFFSET (f, j));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
|
||||
0, VAR_NAMESPACE);
|
||||
v = locate_var_value (s, 0);
|
||||
}
|
||||
VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_N_BASECLASSES (t) == 0)
|
||||
break;
|
||||
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compare two argument lists and return the position in which they differ,
|
||||
or zero if equal. Note that we ignore the first argument, which is
|
||||
the type of the instance variable. This is because we want to handle
|
||||
derived classes. This is not entirely correct: we should actually
|
||||
check to make sure that a requested operation is type secure,
|
||||
shouldn't we? */
|
||||
int typecmp(t1, t2)
|
||||
struct type *t1[];
|
||||
value t2[];
|
||||
{
|
||||
int i;
|
||||
|
||||
if (t1[0]->code == TYPE_CODE_VOID) return 0;
|
||||
if (!t1[1]) return 0;
|
||||
for (i = 1; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++)
|
||||
{
|
||||
if (! t2[i]
|
||||
|| t1[i]->code != t2[i]->type->code
|
||||
|| t1[i]->target_type != t2[i]->type->target_type)
|
||||
{
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
if (!t1[i]) return 0;
|
||||
return t2[i] ? i+1 : 0;
|
||||
}
|
||||
|
||||
#ifndef FRAME
|
||||
#include "frame.h"
|
||||
#endif
|
||||
|
||||
/* C++: return the value of the class instance variable, if one exists.
|
||||
Flag COMPLAIN signals an error if the request is made in an
|
||||
inappropriate context. */
|
||||
value
|
||||
value_of_this (complain)
|
||||
int complain;
|
||||
{
|
||||
extern FRAME selected_frame;
|
||||
struct symbol *func, *sym;
|
||||
char *funname = 0;
|
||||
struct block *b;
|
||||
int i;
|
||||
|
||||
if (selected_frame == 0)
|
||||
if (complain)
|
||||
error ("no frame selected");
|
||||
else return 0;
|
||||
|
||||
func = get_frame_function (selected_frame);
|
||||
if (func)
|
||||
funname = SYMBOL_NAME (func);
|
||||
else
|
||||
if (complain)
|
||||
error ("no `this' in nameless context");
|
||||
else return 0;
|
||||
|
||||
b = SYMBOL_BLOCK_VALUE (func);
|
||||
i = BLOCK_NSYMS (b);
|
||||
if (i <= 0)
|
||||
if (complain)
|
||||
error ("no args, no `this'");
|
||||
else return 0;
|
||||
|
||||
sym = BLOCK_SYM (b, 0);
|
||||
if (strncmp ("$this", SYMBOL_NAME (sym), 5))
|
||||
if (complain)
|
||||
error ("current stack frame not in method");
|
||||
else return 0;
|
||||
|
||||
return read_var_value (sym, selected_frame);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
395
gdb/valprint.c
395
gdb/valprint.c
|
@ -33,6 +33,7 @@ static int print_max;
|
|||
static void type_print_varspec_suffix ();
|
||||
static void type_print_varspec_prefix ();
|
||||
static void type_print_base ();
|
||||
static void type_print_method_args ();
|
||||
|
||||
START_FILE
|
||||
|
||||
|
@ -82,7 +83,7 @@ value_print (val, stream, format)
|
|||
if (i)
|
||||
fprintf (stream, ", ");
|
||||
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i,
|
||||
VALUE_ADDRESS (val) + typelen * i, stream, format);
|
||||
VALUE_ADDRESS (val) + typelen * i, stream, format, 1);
|
||||
}
|
||||
if (i < n)
|
||||
fprintf (stream, "...");
|
||||
|
@ -92,15 +93,21 @@ value_print (val, stream, format)
|
|||
else
|
||||
{
|
||||
/* A simple (nonrepeated) value */
|
||||
/* If it is a pointer, indicate what it points to. */
|
||||
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
|
||||
/* If it is a pointer, indicate what it points to.
|
||||
|
||||
C++: print type also if it is a reference.
|
||||
|
||||
If it is a member pointer, we will take care
|
||||
of that when we print it. */
|
||||
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR
|
||||
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
|
||||
{
|
||||
fprintf (stream, "(");
|
||||
type_print (VALUE_TYPE (val), "", stream, -1);
|
||||
fprintf (stream, ") ");
|
||||
}
|
||||
return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
|
||||
VALUE_ADDRESS (val), stream, format);
|
||||
VALUE_ADDRESS (val), stream, format, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,18 +117,22 @@ value_print (val, stream, format)
|
|||
(a letter or 0 for natural format).
|
||||
|
||||
If the data are a string pointer, returns the number of
|
||||
sting characters printed. */
|
||||
sting characters printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references,
|
||||
otherwise just print them like pointers. */
|
||||
|
||||
int
|
||||
val_print (type, valaddr, address, stream, format)
|
||||
val_print (type, valaddr, address, stream, format, deref_ref)
|
||||
struct type *type;
|
||||
char *valaddr;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
char format;
|
||||
int deref_ref;
|
||||
{
|
||||
register int i;
|
||||
int len;
|
||||
int len, n_baseclasses;
|
||||
struct type *elttype;
|
||||
int eltlen;
|
||||
int val;
|
||||
|
@ -158,7 +169,7 @@ val_print (type, valaddr, address, stream, format)
|
|||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
val_print (elttype, valaddr + i * eltlen,
|
||||
0, stream, format);
|
||||
0, stream, format, deref_ref);
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "...");
|
||||
|
@ -174,53 +185,205 @@ val_print (type, valaddr, address, stream, format)
|
|||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
fprintf (stream, "0x%x", * (int *) valaddr);
|
||||
/* For a pointer to char or unsigned char,
|
||||
also print the string pointed to, unless pointer is null. */
|
||||
|
||||
/* For an array of chars, print with string syntax. */
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
|
||||
&& format == 0
|
||||
&& unpack_long (type, valaddr) != 0)
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
|
||||
{
|
||||
fputc (' ', stream);
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < print_max; i++)
|
||||
struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
|
||||
struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
|
||||
struct fn_field *f;
|
||||
int j, len2;
|
||||
char *kind = "";
|
||||
|
||||
val = unpack_long (builtin_type_int, valaddr);
|
||||
if (TYPE_CODE (target) == TYPE_CODE_FUNC)
|
||||
{
|
||||
QUIT;
|
||||
read_memory (unpack_long (type, valaddr) + i, &c, 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
printchar (c, stream, '"');
|
||||
if (val < 128)
|
||||
{
|
||||
len = TYPE_NFN_FIELDS (domain);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
f = TYPE_FN_FIELDLIST1 (domain, i);
|
||||
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
|
||||
{
|
||||
kind = "virtual";
|
||||
goto common;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct symbol *sym = find_pc_function (val);
|
||||
if (sym == 0)
|
||||
error ("invalid pointer to member function");
|
||||
len = TYPE_NFN_FIELDS (domain);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
f = TYPE_FN_FIELDLIST1 (domain, i);
|
||||
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
|
||||
goto common;
|
||||
}
|
||||
}
|
||||
}
|
||||
common:
|
||||
if (i < len)
|
||||
{
|
||||
fputc ('&', stream);
|
||||
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
|
||||
fprintf (stream, kind);
|
||||
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
|
||||
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
|
||||
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
|
||||
else
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j), "",
|
||||
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fputc ('"', stream);
|
||||
if (i == print_max)
|
||||
fprintf (stream, "...");
|
||||
fflush (stream);
|
||||
/* Return number of characters printed, plus one for the
|
||||
terminating null if we have "reached the end". */
|
||||
return i + (i != print_max);
|
||||
else
|
||||
{
|
||||
/* VAL is a byte offset into the structure type DOMAIN.
|
||||
Find the name of the field for that offset and
|
||||
print it. */
|
||||
int extra = 0;
|
||||
int bits = 0;
|
||||
len = TYPE_NFIELDS (domain);
|
||||
val <<= 3; /* @@ Make VAL into bit offset */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
int bitpos = TYPE_FIELD_BITPOS (domain, i);
|
||||
QUIT;
|
||||
if (val == bitpos)
|
||||
break;
|
||||
if (val < bitpos && i > 0)
|
||||
{
|
||||
int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
|
||||
/* Somehow pointing into a field. */
|
||||
i -= 1;
|
||||
extra = (val - TYPE_FIELD_BITPOS (domain, i));
|
||||
if (extra & 0x3)
|
||||
bits = 1;
|
||||
else
|
||||
extra >>= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
fputc ('&', stream);
|
||||
type_print_base (domain, stream, 0, 0);
|
||||
fprintf (stream, "::");
|
||||
fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
|
||||
if (extra)
|
||||
fprintf (stream, " + %d bytes", extra);
|
||||
if (bits)
|
||||
fprintf (stream, " (offset in bits)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
fputc ('(', stream);
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf (stream, ") %d", val >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stream, "0x%x", * (int *) valaddr);
|
||||
/* For a pointer to char or unsigned char,
|
||||
also print the string pointed to, unless pointer is null. */
|
||||
|
||||
/* For an array of chars, print with string syntax. */
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
|
||||
&& format == 0
|
||||
&& unpack_long (type, valaddr) != 0)
|
||||
{
|
||||
fputc (' ', stream);
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
read_memory (unpack_long (type, valaddr) + i, &c, 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
printchar (c, stream, '"');
|
||||
}
|
||||
fputc ('"', stream);
|
||||
if (i == print_max)
|
||||
fprintf (stream, "...");
|
||||
fflush (stream);
|
||||
/* Return number of characters printed, plus one for the
|
||||
terminating null if we have "reached the end". */
|
||||
return i + (i != print_max);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
error ("not implemented: member type in val_print");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
fprintf (stream, "0x%x", * (int *) valaddr);
|
||||
/* De-reference the reference. */
|
||||
if (deref_ref)
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr);
|
||||
fprintf (stream, " = ");
|
||||
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
|
||||
VALUE_ADDRESS (val), stream, format, deref_ref);
|
||||
}
|
||||
else
|
||||
fprintf (stream, " = ???");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
n_baseclasses = TYPE_N_BASECLASSES (type);
|
||||
for (i = 1; i <= n_baseclasses; i++)
|
||||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i)));
|
||||
val_print (TYPE_FIELD_TYPE (type, 0),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
|
||||
0, stream, 0, 0);
|
||||
}
|
||||
if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type));
|
||||
for (i -= 1; i < len; i++)
|
||||
{
|
||||
if (i > n_baseclasses) fprintf (stream, ", ");
|
||||
fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
/* check if static field */
|
||||
if (TYPE_FIELD_STATIC (type, i))
|
||||
{
|
||||
value v;
|
||||
|
||||
v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
VALUE_CONTENTS (v), 0, stream, format, deref_ref);
|
||||
}
|
||||
else if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
val = unpack_field_as_long (type, valaddr, i);
|
||||
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format);
|
||||
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format, deref_ref);
|
||||
}
|
||||
else
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
|
||||
0, stream, format);
|
||||
0, stream, format, deref_ref);
|
||||
}
|
||||
fprintf (stream, "}");
|
||||
break;
|
||||
|
@ -367,13 +530,96 @@ type_print_1 (type, varstring, stream, show, level)
|
|||
((show > 0 || TYPE_NAME (type) == 0)
|
||||
&&
|
||||
(code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
|
||||
|| code == TYPE_CODE_ARRAY)))
|
||||
|| code == TYPE_CODE_ARRAY
|
||||
|| code == TYPE_CODE_MEMBER
|
||||
|| code == TYPE_CODE_REF)))
|
||||
fprintf (stream, " ");
|
||||
type_print_varspec_prefix (type, stream, show, 0);
|
||||
fprintf (stream, "%s", varstring);
|
||||
type_print_varspec_suffix (type, stream, show, 0);
|
||||
}
|
||||
|
||||
/* Print the method arguments ARGS to the file STREAM. */
|
||||
static void
|
||||
type_print_method_args (args, prefix, varstring, stream)
|
||||
struct type **args;
|
||||
char *prefix, *varstring;
|
||||
FILE *stream;
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf (stream, " %s%s (", prefix, varstring);
|
||||
if (args[1] && args[1]->code != TYPE_CODE_VOID)
|
||||
{
|
||||
i = 1; /* skip the class variable */
|
||||
while (1)
|
||||
{
|
||||
type_print (args[i++], "", stream, 0);
|
||||
if (!args[i])
|
||||
{
|
||||
fprintf (stream, " ...");
|
||||
break;
|
||||
}
|
||||
else if (args[i]->code != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf (stream, ", ");
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
fprintf (stream, ")");
|
||||
}
|
||||
|
||||
/* If TYPE is a derived type, then print out derivation
|
||||
information. Print out all layers of the type heirarchy
|
||||
until we encounter one with multiple inheritance.
|
||||
At that point, print out that ply, and return. */
|
||||
static void
|
||||
type_print_derivation_info (stream, type)
|
||||
FILE *stream;
|
||||
struct type *type;
|
||||
{
|
||||
char *name;
|
||||
int i, n_baseclasses = TYPE_N_BASECLASSES (type);
|
||||
struct type *basetype = 0;
|
||||
|
||||
while (type && n_baseclasses == 1)
|
||||
{
|
||||
basetype = TYPE_BASECLASS (type, 1);
|
||||
if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
|
||||
{
|
||||
while (*name != ' ') name++;
|
||||
fprintf (stream, ": %s%s %s ",
|
||||
TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
|
||||
TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "",
|
||||
name + 1);
|
||||
}
|
||||
n_baseclasses = TYPE_N_BASECLASSES (basetype);
|
||||
type = basetype;
|
||||
}
|
||||
|
||||
if (type)
|
||||
{
|
||||
if (n_baseclasses != 0)
|
||||
fprintf (stream, ": ");
|
||||
for (i = 1; i <= n_baseclasses; i++)
|
||||
{
|
||||
basetype = TYPE_BASECLASS (type, i);
|
||||
if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
|
||||
{
|
||||
while (*name != ' ') name++;
|
||||
fprintf (stream, "%s%s %s",
|
||||
TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
|
||||
TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "",
|
||||
name + 1);
|
||||
}
|
||||
if (i < n_baseclasses)
|
||||
fprintf (stream, ", ");
|
||||
}
|
||||
putc (' ', stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print any asterisks or open-parentheses needed before the
|
||||
variable name (to describe its type).
|
||||
|
||||
|
@ -404,6 +650,20 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr)
|
|||
fputc ('*', stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
fputc (' ', stream);
|
||||
type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
fprintf (stream, "::");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
fputc ('&', stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
|
@ -445,7 +705,14 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr)
|
|||
fprintf (stream, "]");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
if (passed_a_ptr)
|
||||
fputc (')', stream);
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_REF:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
break;
|
||||
|
||||
|
@ -501,6 +768,8 @@ type_print_base (type, stream, show, level)
|
|||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_REF:
|
||||
case TYPE_CODE_FUNC:
|
||||
type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
@ -521,12 +790,23 @@ type_print_base (type, stream, show, level)
|
|||
fprintf (stream, "{...}");
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
type_print_derivation_info (stream, type);
|
||||
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
fprintf (stream, "\n");
|
||||
for (i = 0; i < len; i++)
|
||||
if (len) fprintf (stream, "\n");
|
||||
else fprintf (stream, "<no data fields>\n");
|
||||
|
||||
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
/* Don't print out virtual function table. */
|
||||
if (! strncmp (TYPE_FIELD_NAME (type, i),
|
||||
"_vptr$", 6))
|
||||
continue;
|
||||
|
||||
print_spaces (level + 4, stream);
|
||||
|
||||
/* If this is a bit-field and there is a gap before it,
|
||||
|
@ -550,6 +830,10 @@ type_print_base (type, stream, show, level)
|
|||
|
||||
/* Print the declaration of this field. */
|
||||
|
||||
if (TYPE_FIELD_STATIC (type, i))
|
||||
{
|
||||
fprintf (stream, "static ");
|
||||
}
|
||||
type_print_1 (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
|
@ -561,6 +845,37 @@ type_print_base (type, stream, show, level)
|
|||
|
||||
fprintf (stream, ";\n");
|
||||
}
|
||||
|
||||
/* C++: print out the methods */
|
||||
len = TYPE_NFN_FIELDS (type);
|
||||
if (len) fprintf (stream, "\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
print_spaces (level + 4, stream);
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
fprintf (stream, "virtual ");
|
||||
type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0);
|
||||
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
|
||||
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
|
||||
TYPE_FN_FIELDLIST_NAME (type, i), stream);
|
||||
else
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j), "",
|
||||
TYPE_FN_FIELDLIST_NAME (type, i), stream);
|
||||
|
||||
fprintf (stream, ";\n");
|
||||
}
|
||||
if (len2) fprintf (stream, "\n");
|
||||
}
|
||||
|
||||
print_spaces (level, stream);
|
||||
fputc ('}', stream);
|
||||
}
|
||||
|
|
22
gdb/value.h
22
gdb/value.h
|
@ -56,10 +56,14 @@ typedef struct value *value;
|
|||
#define VALUE_REGNO(val) (val)->regno
|
||||
|
||||
/* If ARG is an array, convert it to a pointer.
|
||||
If ARG is an enum, convert it to an integer. */
|
||||
If ARG is an enum, convert it to an integer.
|
||||
|
||||
References are dereferenced. */
|
||||
|
||||
#define COERCE_ARRAY(arg) \
|
||||
{ if (VALUE_REPEATED (arg) \
|
||||
{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF) \
|
||||
arg = value_ind (arg); \
|
||||
if (VALUE_REPEATED (arg) \
|
||||
|| TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) \
|
||||
arg = value_coerce_array (arg); \
|
||||
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
|
||||
|
@ -69,7 +73,9 @@ typedef struct value *value;
|
|||
/* If ARG is an enum, convert it to an integer. */
|
||||
|
||||
#define COERCE_ENUM(arg) \
|
||||
{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
|
||||
{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF) \
|
||||
arg = value_ind (arg); \
|
||||
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
|
||||
arg = value_cast (builtin_type_unsigned_int, arg); \
|
||||
}
|
||||
|
||||
|
@ -108,7 +114,7 @@ value value_addr ();
|
|||
value value_assign ();
|
||||
value value_neg ();
|
||||
value value_lognot ();
|
||||
value value_struct_elt ();
|
||||
value value_struct_elt (), value_struct_elt_for_address ();
|
||||
value value_field ();
|
||||
value value_cast ();
|
||||
value value_repeat ();
|
||||
|
@ -129,3 +135,11 @@ struct internalvar *lookup_internalvar ();
|
|||
int value_equal ();
|
||||
int value_less ();
|
||||
int value_zerop ();
|
||||
|
||||
/* C++ */
|
||||
value value_of_this ();
|
||||
value value_static_field ();
|
||||
value value_x_binop ();
|
||||
value value_x_unop ();
|
||||
int binop_user_defined_p ();
|
||||
int unop_user_defined_p ();
|
||||
|
|
148
gdb/values.c
148
gdb/values.c
|
@ -425,7 +425,12 @@ value_as_double (val)
|
|||
/* Unpack raw data (copied from debugee) at VALADDR
|
||||
as a long, or as a double, assuming the raw data is described
|
||||
by type TYPE. Knows how to convert different sizes of values
|
||||
and can convert between fixed and floating point. */
|
||||
and can convert between fixed and floating point.
|
||||
|
||||
C++: It is assumed that the front-end has taken care of
|
||||
all matters concerning pointers to members. A pointer
|
||||
to member which reaches here is considered to be equivalent
|
||||
to an INT (or some size). After all, it is only an offset. */
|
||||
|
||||
long
|
||||
unpack_long (type, valaddr)
|
||||
|
@ -474,11 +479,14 @@ unpack_long (type, valaddr)
|
|||
if (len == sizeof (long))
|
||||
return * (long *) valaddr;
|
||||
}
|
||||
else if (code == TYPE_CODE_PTR)
|
||||
else if (code == TYPE_CODE_PTR
|
||||
|| code == TYPE_CODE_REF)
|
||||
{
|
||||
if (len == sizeof (char *))
|
||||
return (CORE_ADDR) * (char **) valaddr;
|
||||
}
|
||||
else if (code == TYPE_CODE_MEMBER)
|
||||
error ("not impelmented: member types in unpack_long");
|
||||
|
||||
error ("Value not integer or pointer.");
|
||||
}
|
||||
|
@ -543,7 +551,9 @@ unpack_double (type, valaddr)
|
|||
|
||||
/* Given a value ARG1 of a struct or union type,
|
||||
extract and return the value of one of its fields.
|
||||
FIELDNO says which field. */
|
||||
FIELDNO says which field.
|
||||
|
||||
For C++, must also be able to return values from static fields. */
|
||||
|
||||
value
|
||||
value_field (arg1, fieldno)
|
||||
|
@ -581,6 +591,138 @@ value_field (arg1, fieldno)
|
|||
return v;
|
||||
}
|
||||
|
||||
value
|
||||
value_fn_field (arg1, fieldno, subfieldno)
|
||||
register value arg1;
|
||||
register int fieldno;
|
||||
{
|
||||
register value v;
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
|
||||
register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
|
||||
struct symbol *sym;
|
||||
|
||||
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
|
||||
0, VAR_NAMESPACE);
|
||||
if (! sym) error ("Internal error: could not find physical method named %s",
|
||||
TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
|
||||
|
||||
v = allocate_value (type);
|
||||
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
|
||||
VALUE_TYPE (v) = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Return a virtual function as a value.
|
||||
ARG1 is the object which provides the virtual function
|
||||
table pointer.
|
||||
F is the list of member functions which contains the desired virtual
|
||||
function.
|
||||
J is an index into F which provides the desired virtual function.
|
||||
TYPE is the basetype which first provides the virtual function table. */
|
||||
value
|
||||
value_virtual_fn_field (arg1, f, j, type)
|
||||
value arg1;
|
||||
struct fn_field *f;
|
||||
int j;
|
||||
struct type *type;
|
||||
{
|
||||
/* First, get the virtual function table pointer. That comes
|
||||
with a strange type, so cast it to type `pointer to long' (which
|
||||
should serve just fine as a function type). Then, index into
|
||||
the table, and convert final value to appropriate function type. */
|
||||
value vfn, vtbl;
|
||||
value vi = value_from_long (builtin_type_int, TYPE_FN_FIELD_VOFFSET (f, j));
|
||||
VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type);
|
||||
|
||||
/* This type may have been defined before its virtual function table
|
||||
was. If so, fill in the virtual function table entry for the
|
||||
type now. */
|
||||
if (TYPE_VPTR_FIELDNO (type) < 0)
|
||||
TYPE_VPTR_FIELDNO (type)
|
||||
= fill_in_vptr_fieldno (type);
|
||||
|
||||
/* Pretend that this array is just an array of pointers to integers.
|
||||
This will have to change for multiple inheritance. */
|
||||
vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type)));
|
||||
VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int);
|
||||
|
||||
/* Index into the virtual function table. */
|
||||
vfn = value_subscript (vtbl, vi);
|
||||
|
||||
/* Reinstantiate the function pointer with the correct type. */
|
||||
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
|
||||
return vfn;
|
||||
}
|
||||
|
||||
/* The value of a static class member does not depend
|
||||
on its instance, only on its type. If FIELDNO >= 0,
|
||||
then fieldno is a valid field number and is used directly.
|
||||
Otherwise, FIELDNAME is the name of the field we are
|
||||
searching for. If it is not a static field name, an
|
||||
error is signaled. TYPE is the type in which we look for the
|
||||
static field member. */
|
||||
value
|
||||
value_static_field (type, fieldname, fieldno)
|
||||
register struct type *type;
|
||||
char *fieldname;
|
||||
register int fieldno;
|
||||
{
|
||||
register value v;
|
||||
struct symbol *sym;
|
||||
|
||||
if (fieldno < 0)
|
||||
{
|
||||
register struct type *t = type;
|
||||
/* Look for static field. */
|
||||
while (t)
|
||||
{
|
||||
int i;
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
|
||||
{
|
||||
if (TYPE_FIELD_STATIC (t, i))
|
||||
{
|
||||
fieldno = i;
|
||||
goto found;
|
||||
}
|
||||
else
|
||||
error ("field `%s' is not static");
|
||||
}
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
|
||||
t = type;
|
||||
|
||||
if (destructor_name_p (fieldname, t))
|
||||
error ("use `info method' command to print out value of destructor");
|
||||
|
||||
while (t)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
|
||||
{
|
||||
error ("use `info method' command to print value of method \"%s\"", fieldname);
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t, 1);
|
||||
}
|
||||
error("there is no field named %s", fieldname);
|
||||
}
|
||||
|
||||
found:
|
||||
|
||||
sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno),
|
||||
0, VAR_NAMESPACE);
|
||||
if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno));
|
||||
|
||||
type = TYPE_FIELD_TYPE (type, fieldno);
|
||||
v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
|
||||
return v;
|
||||
}
|
||||
|
||||
long
|
||||
unpack_field_as_long (type, valaddr, fieldno)
|
||||
struct type *type;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* Define the current version number of GDB. */
|
||||
|
||||
char *version = "2.8";
|
||||
char *version = "2.8.1 (GNU C++ 1.31.0 compatible)";
|
||||
|
|
Loading…
Reference in a new issue