gdb-2.8.1

This commit is contained in:
gdb-2.8.1 1988-12-16 00:00:00 +00:00 committed by Pedro Alves
parent 3bf57d2108
commit bb7592f010
64 changed files with 9841 additions and 5861 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

936
gdb/TAGS

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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
View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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).

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
View File

@ -0,0 +1 @@
Links are now set up for use with a sun4.

View File

@ -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 *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
*(int *)&registers[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,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
#endif
#if defined(sun4)
/* G0 *always* holds 0. */
*(int *)&registers[REGISTER_BYTE (0)] = 0;
/* The globals and output registers. I don't know where
to get the locals and input registers from the core file. */
bcopy (&corestr.c_regs.r_g1, registers, 15 * 4);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
*(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc;
*(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y;
bcopy (corestr.c_fpu.fpu_regs,
&registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof corestr.c_fpu.fpu_regs);
#ifdef FPU
bcopy (&corestr.c_fpu.fpu_fsr,
&registers[REGISTER_BYTE (FPS_REGNUM)],
sizeof (FPU_FSR_TYPE));
#endif
#endif
bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));

View File

@ -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

View 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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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

View File

@ -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 *) &registers[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)
{

View File

@ -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. */

View File

@ -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'.


View File

@ -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))

View File

@ -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, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fps_regs);
@ -522,6 +531,25 @@ fetch_inferior_registers ()
bcopy (&inferior_fp_registers.fps_control,
&registers[REGISTER_BYTE (FPC_REGNUM)],
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
#endif
#if defined(sun4)
registers[REGISTER_BYTE (0)] = 0;
bcopy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (1)], 15 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.fpu_fr);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
*(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
*(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
/* *(int *)&registers[REGISTER_BYTE (RP_REGNUM)] =
inferior_registers.r_o7 + 8;
bcopy (&inferior_fp_registers.Fpu_fsr,
&registers[REGISTER_BYTE (FPS_REGNUM)],
sizeof (FPU_FSR_TYPE)); */
read_inferior_memory (inferior_registers.r_sp,
&registers[REGISTER_BYTE (16)],
16*4);
#endif
}
}
@ -540,17 +568,61 @@ store_inferior_registers (regno)
remote_store_registers (registers);
else
{
bcopy (registers, &inferior_registers, 16 * 4);
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
bcopy (&registers[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 *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
}
if (in_fpregs)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fps_regs);
bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
&inferior_fp_registers.fps_control,
sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
}
if (in_regs)
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
if (in_fpregs)
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
#endif
#if defined(sun4)
if (regno >= 0)
if (FP0_REGNUM <= regno && regno <= FP0_REGNUM + 32)
in_regs = 0;
else
in_fpregs = 0;
if (in_regs)
{
bcopy (&registers[REGISTER_BYTE (1)], &inferior_registers.r_g1, 15 * 4);
inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
inferior_registers.r_npc = *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
inferior_registers.r_y = *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
write_inferior_memory (*(int *)&registers[REGISTER_BYTE (SP_REGNUM)],
&registers[REGISTER_BYTE (16)],
16*4);
}
if (in_fpregs)
{
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
sizeof inferior_fp_registers.fpu_fr);
/* bcopy (&registers[REGISTER_BYTE (FPS_REGNUM)],
&inferior_fp_registers.Fpu_fsr,
sizeof (FPU_FSR_TYPE));
****/
}
if (in_regs)
ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
if (in_fpregs)
ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
#endif
}
}

View File

@ -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

View 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 */ \

View File

@ -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 */ \

View File

@ -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)

View File

@ -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"); }

View File

@ -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; \

View File

@ -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 */ \

View File

@ -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) \

View File

@ -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) \

View File

@ -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 */ \

View File

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

View File

@ -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; \

View File

@ -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

View File

@ -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. */

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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
View File

@ -0,0 +1 @@
/* This file is empty. */

811
gdb/sparc-pinsn.c Normal file
View 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);
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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.");

View File

@ -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
View File

@ -0,0 +1,6 @@
#include <Rational.h>
main ()
{
Rational r = Rational (PI);
}

40
gdb/test4.c Normal file
View 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
View 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);
}

View File

@ -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.");
}

View File

@ -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

View File

@ -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);
}

View File

@ -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 ();

View File

@ -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;

View File

@ -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)";