gdb-2.8
This commit is contained in:
parent
7c75bab3d3
commit
3bf57d2108
|
@ -0,0 +1,146 @@
|
|||
|
||||
GDB GENERAL PUBLIC LICENSE
|
||||
(Clarified 11 Feb 1988)
|
||||
|
||||
Copyright (C) 1988 Richard M. Stallman
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license, but changing it is not allowed. You can also
|
||||
use this wording to make the terms for other programs.
|
||||
|
||||
The license agreements of most software companies keep you at the
|
||||
mercy of those companies. By contrast, our general public license is
|
||||
intended to give everyone the right to share GDB. To make sure that
|
||||
you get the rights we want you to have, we need to make restrictions
|
||||
that forbid anyone to deny you these rights or to ask you to surrender
|
||||
the rights. Hence this license agreement.
|
||||
|
||||
Specifically, we want to make sure that you have the right to give
|
||||
away copies of GDB, that you receive source code or else can get it
|
||||
if you want it, that you can change GDB or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To make sure that everyone has such rights, we have to forbid you to
|
||||
deprive anyone else of these rights. For example, if you distribute
|
||||
copies of GDB, you must give the recipients all the rights that you
|
||||
have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must tell them their rights.
|
||||
|
||||
Also, for our own protection, we must make certain that everyone
|
||||
finds out that there is no warranty for GDB. If GDB is modified by
|
||||
someone else and passed on, we want its recipients to know that what
|
||||
they have is not what we distributed, so that any problems introduced
|
||||
by others will not reflect on our reputation.
|
||||
|
||||
Therefore we (Richard Stallman and the Free Software Foundation,
|
||||
Inc.) make the following terms which say what you must do to be
|
||||
allowed to distribute or change GDB.
|
||||
|
||||
|
||||
COPYING POLICIES
|
||||
|
||||
1. You may copy and distribute verbatim copies of GDB source code as
|
||||
you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy a valid copyright notice "Copyright
|
||||
(C) 1988 Free Software Foundation, Inc." (or with whatever year is
|
||||
appropriate); keep intact the notices on all files that refer to this
|
||||
License Agreement and to the absence of any warranty; and give any
|
||||
other recipients of the GDB program a copy of this License Agreement
|
||||
along with the program. You may charge a distribution fee for the
|
||||
physical act of transferring a copy.
|
||||
|
||||
2. You may modify your copy or copies of GDB or any portion of it,
|
||||
and copy and distribute such modifications under the terms of
|
||||
Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of GDB or any
|
||||
part thereof, to be licensed at no charge to all third parties on
|
||||
terms identical to those contained in this License Agreement
|
||||
(except that you may choose to grant more extensive warranty
|
||||
protection to third parties, at your option).
|
||||
|
||||
c) if the modified program serves as a debugger, cause it when
|
||||
started running in the simplest and usual way, to print an
|
||||
announcement including a valid copyright notice "Copyright (C)
|
||||
1988 Free Software Foundation, Inc." (or with the year that is
|
||||
appropriate), saying that there is no warranty (or else, saying
|
||||
that you provide a warranty) and that users may redistribute the
|
||||
program under these conditions, and telling the user how to view a
|
||||
copy of this License Agreement.
|
||||
|
||||
d) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute GDB (or a portion or derivative of it,
|
||||
under Paragraph 2) in object code or executable form under the terms of
|
||||
Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer GDB
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer GDB is void and
|
||||
your rights to use the program under this License agreement shall be
|
||||
automatically terminated. However, parties who have received computer
|
||||
software programs from you with this License Agreement will not have
|
||||
their licenses terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. If you wish to incorporate parts of GDB into other free programs
|
||||
whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not
|
||||
yet worked out a simple rule that can be stated here, but we will
|
||||
often permit this. We will be guided by the two goals of preserving
|
||||
the free status of all derivatives of our free software and of
|
||||
promoting the sharing and reuse of software.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE GDB IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO
|
||||
WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
|
||||
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GDB "AS IS" WITHOUT
|
||||
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF GDB IS WITH YOU. SHOULD GDB PROVE DEFECTIVE, YOU
|
||||
ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
|
||||
WHO MAY MODIFY AND REDISTRIBUTE GDB AS PERMITTED ABOVE, BE LIABLE TO
|
||||
YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER
|
||||
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
|
||||
INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
|
||||
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GDB, EVEN
|
||||
IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR
|
||||
ANY CLAIM BY ANY OTHER PARTY.
|
File diff suppressed because it is too large
Load Diff
48
gdb/Makefile
48
gdb/Makefile
|
@ -1,8 +1,31 @@
|
|||
# Makefile for GDB
|
||||
# Copyright (C) 1986, 1988 Free Software Foundation, Inc.
|
||||
#
|
||||
#GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
#WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
#for the consequences of using it or for whether it serves any
|
||||
#particular purpose or works at all, unless he says so in writing.
|
||||
#Refer to the GDB General Public License for full details.
|
||||
#
|
||||
#Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
#but only under the conditions described in the GDB General Public
|
||||
#License. A copy of this license is supposed to have been given to you
|
||||
#along with GDB so you can know your rights and responsibilities. It
|
||||
#should be in a file named COPYING. Among other things, the copyright
|
||||
#notice and this notice must be preserved on all copies.
|
||||
#
|
||||
#In other words, go ahead and share GDB, but don't try to stop
|
||||
#anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
|
||||
|
||||
# On HPUX, you need to add -Ihpux to CFLAGS.
|
||||
# The headers in the subdir hpux override system headers
|
||||
# and tell GDB to use BSD executable file format.
|
||||
# You also need to add -lGNU to CLIBS, and perhaps CC = gcc.
|
||||
|
||||
# -I. for "#include <obstack.h>"
|
||||
CFLAGS = -g -I.
|
||||
# NOTE!!! -O may FAIL TO WORK! See initialize.h for some weird hacks.
|
||||
CC = cc
|
||||
BISON = bison
|
||||
|
||||
# define this to be "obstack.o" if you don't have the obstack library installed
|
||||
# you must at the same time define OBSTACK1 as "obstack.o"
|
||||
|
@ -10,6 +33,8 @@ BISON = bison
|
|||
OBSTACK = obstack.o
|
||||
OBSTACK1 = obstack.o
|
||||
|
||||
CLIBS = $(OBSTACK)
|
||||
|
||||
STARTOBS = main.o firstfile.o
|
||||
|
||||
OBS = blockframe.o breakpoint.o findvar.o stack.o source.o \
|
||||
|
@ -27,15 +52,15 @@ TSSTART = /lib/crt0.o
|
|||
|
||||
NTSSTART = kdb-start.o
|
||||
|
||||
gdb+: $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) -o gdb+ $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
|
||||
gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) $(LDFLAGS) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS)
|
||||
|
||||
xgdb+ : $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) $(OBSTACK1)
|
||||
$(CC) -o xgdb+ $(STARTOBS) $(OBS) xgdb.o $(TSOBS) $(ENDOBS) \
|
||||
-lXtk11 -lXrm -lX11 -lg $(OBSTACK)
|
||||
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)
|
||||
ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc -lg $(OBSTACK)
|
||||
ld -o kdb $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) -lc $(CLIBS)
|
||||
|
||||
blockframe.o : blockframe.c defs.h initialize.h param.h symtab.h frame.h
|
||||
breakpoint.o : breakpoint.c defs.h initialize.h param.h symtab.h frame.h
|
||||
|
@ -46,8 +71,9 @@ dbxread.o : dbxread.c defs.h initialize.h param.h symtab.h
|
|||
environ.o : environ.c environ.h
|
||||
expprint.o : expprint.c defs.h symtab.h expression.h
|
||||
expread.tab.c : expread.y
|
||||
@echo 'Expect 101 shift/reduce conflicts and 1 reduce/reduce conflict.'
|
||||
$(BISON) -v expread.y
|
||||
@echo 'Expect 96 shift/reduce conflicts.'
|
||||
yacc expread.y
|
||||
mv y.tab.c expread.tab.c
|
||||
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
|
||||
$(CC) -c ${CFLAGS} expread.tab.c
|
||||
mv expread.tab.o expread.o
|
||||
|
@ -74,7 +100,7 @@ symtab.o : symtab.c defs.h initialize.h param.h symtab.h
|
|||
utils.o : utils.c defs.h
|
||||
valarith.o : valarith.c defs.h initialize.h param.h symtab.h value.h expression.h
|
||||
valops.o : valops.c defs.h initialize.h param.h symtab.h value.h
|
||||
valprint.o : valprint.c defs.h initialize.h symtab.h value.h
|
||||
valprint.o : valprint.c defs.h initialize.h param.h symtab.h value.h
|
||||
values.o : values.c defs.h initialize.h param.h symtab.h value.h
|
||||
version.o : version.c
|
||||
xgdb.o : xgdb.c defs.h initialize.h param.h symtab.h frame.h
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
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
|
|
@ -0,0 +1,95 @@
|
|||
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
|
|
@ -0,0 +1,95 @@
|
|||
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
|
|
@ -0,0 +1,32 @@
|
|||
This is GDB, a source-level debugger intended for GNU,
|
||||
presently running under un*x.
|
||||
|
||||
Before compiling GDB, you must set up links to four files according to
|
||||
the kind of machine you are running on. To do this, type `config.gdb
|
||||
machine', where machine is something like `vax' or `sun2'. This
|
||||
creates links named `param.h', `m-init.h', `opcode.h', and `pinsn.c'.
|
||||
(Note: we lack information on certain machines.)
|
||||
|
||||
Also, `Makefile' must be changed to say `OBSTACK = obstack.o' instead
|
||||
of `OBSTACK=-lobstack' (unless you want to install obstack.o as
|
||||
/lib/libobstack.a).
|
||||
|
||||
Once these files are set up, just `make' will do everything,
|
||||
producing an executable `gdb' in this directory.
|
||||
|
||||
About the machine-dependent files...
|
||||
|
||||
m-<machine>.h
|
||||
|
||||
This file contains macro definitions that express information
|
||||
about the machine's registers, stack frame format and instructions.
|
||||
|
||||
m-<machine>init.h
|
||||
|
||||
This file defines one macro, which says how to round up from the
|
||||
address of the end of the text of one .o file to the beginning of
|
||||
the text of the next .o file.
|
||||
|
||||
<machine>-opcode.h, <machine>-pinsn.c
|
||||
These files contain the information necessary to print instructions
|
||||
for your cpu type.
|
|
@ -297,6 +297,10 @@ find_pc_misc_function (pc)
|
|||
|
||||
/* Note that the last thing in the vector is always _etext. */
|
||||
|
||||
/* Above statement is not *always* true - fix for case where there are */
|
||||
/* no misc functions at all (ie no symbol table has been read). */
|
||||
if (hi < 0) return -1; /* no misc functions recorded */
|
||||
|
||||
/* trivial reject range test */
|
||||
if (pc < misc_function_vector[0].address ||
|
||||
pc > misc_function_vector[hi].address)
|
||||
|
|
209
gdb/breakpoint.c
209
gdb/breakpoint.c
|
@ -185,8 +185,11 @@ commands_command (arg)
|
|||
if (b->number == bnum)
|
||||
{
|
||||
if (input_from_terminal_p ())
|
||||
printf ("Type commands for when breakpoint %d is hit, one per line.\n\
|
||||
{
|
||||
printf ("Type commands for when breakpoint %d is hit, one per line.\n\
|
||||
End with a line saying just \"end\".\n", bnum);
|
||||
fflush (stdout);
|
||||
}
|
||||
l = read_command_lines ();
|
||||
free_command_lines (&b->commands);
|
||||
b->commands = l;
|
||||
|
@ -316,6 +319,16 @@ breakpoint_here_p (pc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Evaluate the expression EXP and return 1 if value is zero.
|
||||
This is used inside a catch_errors to evaluate the breakpoint condition. */
|
||||
|
||||
int
|
||||
breakpoint_cond_eval (exp)
|
||||
struct expression *exp;
|
||||
{
|
||||
return value_zerop (evaluate_expression (exp));
|
||||
}
|
||||
|
||||
/* Return 0 if PC is not the address just after a breakpoint,
|
||||
or -1 if breakpoint says do not stop now,
|
||||
or -2 if breakpoint says it has deleted itself and don't stop,
|
||||
|
@ -344,7 +357,9 @@ breakpoint_stop_status (pc, frame)
|
|||
int value_zero;
|
||||
if (b->cond)
|
||||
{
|
||||
value_zero = value_zerop (evaluate_expression (b->cond));
|
||||
value_zero
|
||||
= catch_errors (breakpoint_cond_eval, b->cond,
|
||||
"Error occurred in testing breakpoint condition.");
|
||||
free_all_values ();
|
||||
}
|
||||
if (b->cond && value_zero)
|
||||
|
@ -607,96 +622,63 @@ set_breakpoint (s, line, tempflag)
|
|||
}
|
||||
|
||||
/* Set a breakpoint according to ARG (function, linenum or *address)
|
||||
and make it temporary if TEMPFLAG is nonzero.
|
||||
|
||||
LINE_NUM is for C++. */
|
||||
and make it temporary if TEMPFLAG is nonzero. */
|
||||
|
||||
static void
|
||||
break_command_1 (arg, tempflag, from_tty, line_num)
|
||||
break_command_1 (arg, tempflag, from_tty)
|
||||
char *arg;
|
||||
int tempflag, from_tty, line_num;
|
||||
int tempflag, from_tty;
|
||||
{
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
register struct expression *cond = 0;
|
||||
register struct breakpoint *b;
|
||||
char *save_arg;
|
||||
int i;
|
||||
|
||||
sals.sals = NULL;
|
||||
sals.nelts = 0;
|
||||
|
||||
sal.line = sal.pc = sal.end = 0;
|
||||
sal.symtab = 0;
|
||||
sal.pc = 0;
|
||||
|
||||
if (arg)
|
||||
{
|
||||
CORE_ADDR pc;
|
||||
sals = decode_line_1 (&arg, 1, 0, 0);
|
||||
sal = decode_line_1 (&arg, 1, 0, 0);
|
||||
|
||||
if (! sals.nelts) return;
|
||||
save_arg = arg;
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
if (sal.pc == 0 && sal.symtab != 0)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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.");
|
||||
}
|
||||
}
|
||||
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.");
|
||||
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
{
|
||||
sal = sals.sals[i];
|
||||
sal.line += line_num; /** C++ **/
|
||||
if (line_num != 0)
|
||||
{ /* get the pc for a particular line */
|
||||
sal.pc = find_line_pc (sal.symtab, sal.line);
|
||||
}
|
||||
if (from_tty)
|
||||
describe_other_breakpoints (sal.pc);
|
||||
|
||||
if (from_tty)
|
||||
describe_other_breakpoints (sal.pc);
|
||||
b = set_raw_breakpoint (sal);
|
||||
b->number = ++breakpoint_count;
|
||||
b->cond = cond;
|
||||
if (tempflag)
|
||||
b->enable = temporary;
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -704,7 +686,7 @@ break_command (arg, from_tty)
|
|||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
break_command_1 (arg, 0, from_tty, 0);
|
||||
break_command_1 (arg, 0, from_tty);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -712,7 +694,7 @@ tbreak_command (arg, from_tty)
|
|||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
break_command_1 (arg, 1, from_tty, 0);
|
||||
break_command_1 (arg, 1, from_tty);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -721,72 +703,60 @@ 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)
|
||||
{
|
||||
sals = decode_line_spec (arg, 1);
|
||||
}
|
||||
sal = 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;
|
||||
}
|
||||
|
||||
for (i = 0; i < sals.nelts; i++)
|
||||
/* 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)))
|
||||
{
|
||||
/* 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');
|
||||
b1 = breakpoint_chain;
|
||||
breakpoint_chain = b1->next;
|
||||
b1->next = found;
|
||||
found = b1;
|
||||
}
|
||||
free (sals.sals);
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
|
||||
|
@ -909,13 +879,12 @@ ignore_command (args, from_tty)
|
|||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
register char *p;
|
||||
register char *p = args;
|
||||
register int num;
|
||||
|
||||
if (p == 0)
|
||||
error_no_arg ("a breakpoint number");
|
||||
|
||||
p = args;
|
||||
while (*p >= '0' && *p <= '9') p++;
|
||||
if (*p && *p != ' ' && *p != '\t')
|
||||
error ("First argument must be a breakpoint number.");
|
||||
|
|
1423
gdb/coffread.c
1423
gdb/coffread.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
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
|
@ -370,7 +370,7 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
|
|||
while (*p == '-'
|
||||
|| (*p >= 'a' && *p <= 'z')
|
||||
|| (*p >= 'A' && *p <= 'Z')
|
||||
|| (*p >= '1' && *p <= '9'))
|
||||
|| (*p >= '0' && *p <= '9'))
|
||||
{
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p += 'a' - 'A';
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Shell script to create proper links to machine-dependent files in
|
||||
# preparation for compiling gdb.
|
||||
#
|
||||
# Usage: config.gdb machine
|
||||
#
|
||||
# If config.gdb succeeds, it leaves its status in config.status.
|
||||
# If config.gdb fails after disturbing the status quo,
|
||||
# config.status is removed.
|
||||
#
|
||||
|
||||
progname=$0
|
||||
|
||||
case $# in
|
||||
1)
|
||||
machine=$1
|
||||
paramfile=m-${machine}.h
|
||||
initfile=m-${machine}init.h
|
||||
pinsnfile=${machine}-pinsn.c
|
||||
opcodefile=${machine}-opcode.h
|
||||
|
||||
case $machine in
|
||||
hp9k320)
|
||||
initfile=m-sun3init.h
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
hp9k320bsd)
|
||||
initfile=m-sun3init.h
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
isi)
|
||||
# some version of m68k-pinsn.c should work here
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
merlin)
|
||||
# m-umaxinit.h?
|
||||
initfile=unknown-or-unavailable
|
||||
pinsnfile=ns32k-pinsn.c
|
||||
opcodefile=ns32k-opcode.h
|
||||
;;
|
||||
news)
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
npl)
|
||||
pinsnfile=gld-pinsn.c
|
||||
;;
|
||||
pn)
|
||||
pinsnfile=gld-pinsn.c
|
||||
;;
|
||||
sun2)
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
sun3)
|
||||
pinsnfile=m68k-pinsn.c
|
||||
opcodefile=m68k-opcode.h
|
||||
;;
|
||||
umax)
|
||||
pinsnfile=ns32k-pinsn.c
|
||||
opcodefile=ns32k-opcode.h
|
||||
;;
|
||||
test)
|
||||
paramfile=one
|
||||
initfile=two
|
||||
pinsnfile=three
|
||||
opcodefile=four
|
||||
;;
|
||||
esac
|
||||
|
||||
files="$paramfile $initfile $pinsnfile $opcodefile"
|
||||
links="param.h m-init.h pinsn.c opcode.h"
|
||||
|
||||
while [ -n "$files" ]
|
||||
do
|
||||
# set file to car of files, files to cdr of files
|
||||
set $files; file=$1; shift; files=$*
|
||||
set $links; link=$1; shift; links=$*
|
||||
|
||||
if [ ! -r $file ]
|
||||
then
|
||||
echo "$progname: cannot create a link \`$link',"
|
||||
echo "since the file \`$file' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f $link config.status
|
||||
# Make a symlink if possible, otherwise try a hard link
|
||||
ln -s $file $link 2>/dev/null || ln $file $link
|
||||
|
||||
if [ ! -r $link ]
|
||||
then
|
||||
echo "$progname: unable to link \`$link' to \`$file'."
|
||||
exit 1
|
||||
fi
|
||||
echo "Linked \`$link' to \`$file'."
|
||||
done
|
||||
|
||||
echo "Links are now set up for use with a $machine." \
|
||||
| tee config.status
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $progname machine"
|
||||
echo -n "Where \`machine' is something like "
|
||||
echo "\`vax', \`sun3', \`umax', etc."
|
||||
if [ -r config.status ]
|
||||
then
|
||||
cat config.status
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
84
gdb/core.c
84
gdb/core.c
|
@ -42,8 +42,16 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <sys/ptrace.h>
|
||||
#else /* not UMAX_CORE */
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
#endif /* NEW_SUN_CORE */
|
||||
#ifdef HP9K320
|
||||
#include <sys/reg.h>
|
||||
#include <sys/trap.h>
|
||||
#ifdef HPUX_VERSION_5
|
||||
#define e_PS e_regs[PS]
|
||||
#define e_PC e_regs[PC]
|
||||
#endif /* HPUX_VERSION_5 */
|
||||
#endif /* HP9K320 */
|
||||
#endif /* not UMAX_CORE */
|
||||
#endif /* not NEW_SUN_CORE */
|
||||
|
||||
#ifndef N_TXTADDR
|
||||
#define N_TXTADDR(hdr) 0
|
||||
|
@ -258,6 +266,39 @@ core_file_command (filename, from_tty)
|
|||
/* Read the register values out of the core file and store
|
||||
them where `read_register' will find them. */
|
||||
|
||||
#ifdef HP9K320
|
||||
{
|
||||
register int regno;
|
||||
struct exception_stack es;
|
||||
int val;
|
||||
|
||||
val = lseek (corechan, (REGISTER_ADDR (reg_offset, 0)), 0);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
val = myread (corechan, es,
|
||||
((char *) &es.e_regs[R0] - (char *) &es.e_offset));
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
for (regno = 0; (regno < PS_REGNUM); regno++)
|
||||
supply_register (regno, &es.e_regs[regno + R0]);
|
||||
val = es.e_PS;
|
||||
supply_register (regno++, &val);
|
||||
supply_register (regno++, &es.e_PC);
|
||||
for (; (regno < NUM_REGS); regno++)
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
val = lseek (corechan, (FP_REGISTER_ADDR (u, regno)), 0);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
val = myread (corechan, buf, sizeof buf);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
#else /* not HP9K320 */
|
||||
{
|
||||
register int regno;
|
||||
|
||||
|
@ -275,6 +316,7 @@ core_file_command (filename, from_tty)
|
|||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
#endif /* not HP9K320 */
|
||||
}
|
||||
#endif /* not NEW_SUN_CORE */
|
||||
if (filename[0] == '/')
|
||||
|
@ -357,17 +399,30 @@ exec_file_command (filename, from_tty)
|
|||
{
|
||||
struct stat st_exec;
|
||||
|
||||
#ifdef gould
|
||||
FILHDR exec_coffhdr;
|
||||
|
||||
val = myread (execchan, &exec_coffhdr, sizeof exec_coffhdr);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
#endif
|
||||
val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
|
||||
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
text_start = N_TXTADDR (exec_aouthdr);
|
||||
text_end = text_start + exec_aouthdr.a_text;
|
||||
text_start = N_TXTADDR (exec_aouthdr);
|
||||
exec_data_start = N_DATADDR (exec_aouthdr);
|
||||
#ifdef gould
|
||||
text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr);
|
||||
exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)
|
||||
+ exec_aouthdr.a_text;
|
||||
#else
|
||||
text_offset = N_TXTOFF (exec_aouthdr);
|
||||
exec_data_start = N_DATADDR (exec_aouthdr);
|
||||
exec_data_end = exec_data_start + exec_aouthdr.a_data;
|
||||
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
|
||||
#endif
|
||||
text_end = text_start + exec_aouthdr.a_text;
|
||||
exec_data_end = exec_data_start + exec_aouthdr.a_data;
|
||||
data_start = exec_data_start;
|
||||
data_end += exec_data_start;
|
||||
|
||||
|
@ -383,8 +438,7 @@ exec_file_command (filename, from_tty)
|
|||
|
||||
/* Tell display code (if any) about the changed file name. */
|
||||
if (exec_file_display_hook)
|
||||
(*exec_file_display_hook)
|
||||
(filename ? filename : "No executable specified.\n");
|
||||
(*exec_file_display_hook) (filename);
|
||||
}
|
||||
|
||||
/* Call this to specify the hook for exec_file_command to call back.
|
||||
|
@ -439,10 +493,15 @@ validate_files ()
|
|||
}
|
||||
}
|
||||
|
||||
/* Return the name of the executable file as a string.
|
||||
ERR nonzero means get error if there is none specified;
|
||||
otherwise return 0 in that case. */
|
||||
|
||||
char *
|
||||
get_exec_file ()
|
||||
get_exec_file (err)
|
||||
int err;
|
||||
{
|
||||
if (execfile == 0)
|
||||
if (err && execfile == 0)
|
||||
error ("No executable file specified.\n\
|
||||
Use the \"exec-file\" and \"symbol-file\" commands.");
|
||||
return execfile;
|
||||
|
@ -648,9 +707,10 @@ myread (desc, addr, len)
|
|||
len -= val;
|
||||
addr += val;
|
||||
}
|
||||
return orglen;
|
||||
}
|
||||
|
||||
#ifndef NEW_SUN_CORE
|
||||
#ifdef REGISTER_U_ADDR
|
||||
|
||||
/* Return the address in the core dump or inferior of register REGNO.
|
||||
BLOCKEND is the address of the end of the user structure. */
|
||||
|
@ -670,7 +730,7 @@ register_addr (regno, blockend)
|
|||
return addr;
|
||||
}
|
||||
|
||||
#endif /* not NEW_SUN_CORE */
|
||||
#endif /* REGISTER_U_ADDR */
|
||||
|
||||
static
|
||||
initialize ()
|
||||
|
|
1309
gdb/dbxread.c
1309
gdb/dbxread.c
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
extern char *savestring ();
|
||||
extern char *concat ();
|
||||
extern char *xmalloc (), *xrealloc ();
|
||||
extern char *alloca ();
|
||||
extern int parse_escape ();
|
||||
extern char *reg_names[];
|
||||
|
||||
|
|
408
gdb/eval.c
408
gdb/eval.c
|
@ -136,8 +136,8 @@ evaluate_subexp (exp, pos, noside)
|
|||
{
|
||||
enum exp_opcode op;
|
||||
int tem;
|
||||
register int pc, pc2, *oldpos;
|
||||
register value arg1, arg2, arg3;
|
||||
register int pc;
|
||||
register value arg1, arg2;
|
||||
int nargs;
|
||||
value *argvec;
|
||||
|
||||
|
@ -146,12 +146,6 @@ 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,
|
||||
|
@ -180,6 +174,21 @@ evaluate_subexp (exp, pos, noside)
|
|||
(*pos) += 2;
|
||||
return value_of_internalvar (exp->elts[pc + 1].internalvar);
|
||||
|
||||
case OP_FUNCALL:
|
||||
(*pos) += 2;
|
||||
nargs = exp->elts[pc + 1].longconst;
|
||||
argvec = (value *) alloca (sizeof (value) * (nargs + 1));
|
||||
for (tem = 0; tem <= nargs; tem++)
|
||||
|
||||
/* Ensure that array expressions are coerced into pointer objects. */
|
||||
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
|
||||
return call_function (argvec[0], nargs, argvec + 1);
|
||||
|
||||
case OP_STRING:
|
||||
tem = strlen (&exp->elts[pc + 1].string);
|
||||
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
|
@ -202,146 +211,13 @@ evaluate_subexp (exp, pos, noside)
|
|||
return arg2;
|
||||
}
|
||||
|
||||
case OP_FUNCALL:
|
||||
(*pos) += 2;
|
||||
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 (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 (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 (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)
|
||||
return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
|
||||
return call_function (argvec[0], nargs, argvec + 1);
|
||||
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
|
||||
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
|
||||
"structure");
|
||||
|
||||
case STRUCTOP_PTR:
|
||||
|
@ -350,46 +226,15 @@ evaluate_subexp (exp, pos, noside)
|
|||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
|
||||
return value_struct_elt (arg1, &exp->elts[pc + 1].string,
|
||||
"structure pointer");
|
||||
|
||||
case STRUCTOP_MEMBER:
|
||||
arg1 = evaluate_subexp_for_address (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
/* Now, convert these values to an address.
|
||||
@@ We do not know what type we are looking for,
|
||||
@@ so we must assume that the value requested is a
|
||||
@@ member address (as opposed to a member function 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 (exp, pos, noside);
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
/* Now, convert these values to an address.
|
||||
@@ We do not know what type we are looking for,
|
||||
@@ so we must assume that the value requested is a
|
||||
@@ member address (as opposed to a member function 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);
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_assign (arg1, arg2);
|
||||
return value_assign (arg1, arg2);
|
||||
|
||||
case BINOP_ASSIGN_MODIFY:
|
||||
(*pos) += 2;
|
||||
|
@ -398,9 +243,7 @@ evaluate_subexp (exp, pos, noside)
|
|||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
op = exp->elts[pc + 1].opcode;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op);
|
||||
else if (op == BINOP_ADD)
|
||||
if (op == BINOP_ADD)
|
||||
arg2 = value_add (arg1, arg2);
|
||||
else if (op == BINOP_SUB)
|
||||
arg2 = value_sub (arg1, arg2);
|
||||
|
@ -413,20 +256,14 @@ evaluate_subexp (exp, pos, noside)
|
|||
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_add (arg1, arg2);
|
||||
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;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_sub (arg1, arg2);
|
||||
return value_sub (arg1, arg2);
|
||||
|
||||
case BINOP_MUL:
|
||||
case BINOP_DIV:
|
||||
|
@ -440,142 +277,78 @@ evaluate_subexp (exp, pos, noside)
|
|||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_binop (arg1, arg2, op);
|
||||
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;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
else
|
||||
return value_subscript (arg1, arg2, op);
|
||||
return value_subscript (arg1, arg2, op);
|
||||
|
||||
case BINOP_AND:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (exp, pos,
|
||||
(tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem && !value_zerop (arg2));
|
||||
}
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (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);
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
arg2 = evaluate_subexp (exp, pos, noside);
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (exp, pos,
|
||||
(!tem ? EVAL_SKIP : noside));
|
||||
return value_from_long (builtin_type_int,
|
||||
!tem || !value_zerop (arg2));
|
||||
}
|
||||
tem = value_zerop (arg1);
|
||||
arg2 = evaluate_subexp (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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_equal (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, tem);
|
||||
}
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg1, arg2);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
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);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (binop_must_be_user_defined (arg1, arg2))
|
||||
{
|
||||
return value_x_binop (arg1, arg2, op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
}
|
||||
tem = value_less (arg2, arg1);
|
||||
return value_from_long (builtin_type_int, ! tem);
|
||||
|
||||
case BINOP_REPEAT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
|
@ -592,28 +365,19 @@ evaluate_subexp (exp, pos, noside)
|
|||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (unop_must_be_user_defined (arg1))
|
||||
return value_x_unop (arg1, op, 0);
|
||||
else
|
||||
return value_neg (arg1);
|
||||
return value_neg (arg1);
|
||||
|
||||
case UNOP_LOGNOT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (unop_must_be_user_defined (arg1))
|
||||
return value_x_unop (arg1, op, 0);
|
||||
else
|
||||
return value_lognot (arg1);
|
||||
return value_lognot (arg1);
|
||||
|
||||
case UNOP_ZEROP:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
if (noside == EVAL_SKIP)
|
||||
goto nosideret;
|
||||
if (unop_must_be_user_defined (arg1))
|
||||
return value_x_unop (arg1, op, 0);
|
||||
else
|
||||
return value_from_long (builtin_type_int, value_zerop (arg1));
|
||||
return value_from_long (builtin_type_int, value_zerop (arg1));
|
||||
|
||||
case UNOP_IND:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
|
@ -627,22 +391,7 @@ evaluate_subexp (exp, pos, noside)
|
|||
evaluate_subexp (exp, pos, EVAL_SKIP);
|
||||
goto nosideret;
|
||||
}
|
||||
/* C++: check for and handle pointer to members. */
|
||||
|
||||
op = exp->elts[*pos].opcode;
|
||||
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, 0, name);
|
||||
if (arg1)
|
||||
return arg1;
|
||||
error ("no field `%s' in structure", name);
|
||||
}
|
||||
else
|
||||
return evaluate_subexp_for_address (exp, pos, noside);
|
||||
return evaluate_subexp_for_address (exp, pos, noside);
|
||||
|
||||
case UNOP_SIZEOF:
|
||||
if (noside == EVAL_SKIP)
|
||||
|
@ -668,68 +417,33 @@ evaluate_subexp (exp, pos, noside)
|
|||
|
||||
case UNOP_PREINCREMENT:
|
||||
arg1 = evaluate_subexp (exp, pos, noside);
|
||||
arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
else if (unop_must_be_user_defined (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);
|
||||
}
|
||||
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));
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
else if (unop_must_be_user_defined (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);
|
||||
}
|
||||
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));
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
else if (unop_must_be_user_defined (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;
|
||||
}
|
||||
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));
|
||||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
return arg1;
|
||||
else if (unop_must_be_user_defined (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");
|
||||
value_assign (arg1, arg2);
|
||||
return arg1;
|
||||
}
|
||||
|
||||
nosideret:
|
||||
|
|
|
@ -79,9 +79,7 @@ static struct op_print op_print_tab[] =
|
|||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
|
||||
/* C++ */
|
||||
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}
|
||||
};
|
||||
|
||||
static void print_subexp ();
|
||||
|
@ -121,30 +119,18 @@ print_subexp (exp, pos, stream, prec)
|
|||
opcode = exp->elts[pc].opcode;
|
||||
switch (opcode)
|
||||
{
|
||||
case OP_SCOPE:
|
||||
myprec = PREC_PREFIX;
|
||||
assoc = 0;
|
||||
(*pos) += 2;
|
||||
print_subexp (exp, pos, stream, (int) myprec + assoc);
|
||||
fprintf (stream, " :: ");
|
||||
nargs = strlen (&exp->elts[pc + 2].string);
|
||||
(*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
|
||||
fprintf (stream, &exp->elts[pc + 2].string);
|
||||
return;
|
||||
|
||||
case OP_LONG:
|
||||
(*pos) += 3;
|
||||
value_print (value_from_long (exp->elts[pc + 1].type,
|
||||
exp->elts[pc + 2].longconst),
|
||||
stream);
|
||||
stream, 0);
|
||||
return;
|
||||
|
||||
case OP_DOUBLE:
|
||||
(*pos) += 3;
|
||||
value_print (value_from_double (exp->elts[pc + 1].type,
|
||||
exp->elts[pc + 2].doubleconst),
|
||||
stream);
|
||||
stream, 0);
|
||||
return;
|
||||
|
||||
case OP_VAR_VALUE:
|
||||
|
@ -187,7 +173,7 @@ print_subexp (exp, pos, stream, prec)
|
|||
(*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
|
||||
fprintf (stream, "\"");
|
||||
for (tem = 0; tem < nargs; tem++)
|
||||
printchar ((&exp->elts[pc + 1].string)[tem], stream);
|
||||
printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
|
||||
fprintf (stream, "\"");
|
||||
return;
|
||||
|
||||
|
|
2152
gdb/expread.tab.c
2152
gdb/expread.tab.c
File diff suppressed because it is too large
Load Diff
194
gdb/expread.y
194
gdb/expread.y
|
@ -93,14 +93,10 @@ 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
|
||||
|
@ -126,9 +122,6 @@ struct stoken
|
|||
|
||||
%token <opcode> ASSIGN_MODIFY
|
||||
|
||||
/* C++ */
|
||||
%token THIS
|
||||
|
||||
%left ','
|
||||
%left ABOVE_COMMA
|
||||
%right '=' ASSIGN_MODIFY
|
||||
|
@ -203,20 +196,12 @@ 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); }
|
||||
;
|
||||
|
@ -405,17 +390,8 @@ 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)
|
||||
|
@ -430,88 +406,34 @@ 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 ($1));
|
||||
$$ = SYMBOL_BLOCK_VALUE (tem);
|
||||
}
|
||||
copy_name ($3));
|
||||
$$ = 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);
|
||||
}
|
||||
;
|
||||
|
||||
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);
|
||||
}
|
||||
write_exp_elt (OP_VAR_VALUE); }
|
||||
;
|
||||
|
||||
variable: NAME
|
||||
{ struct symbol *sym;
|
||||
sym = lookup_symbol_1 (copy_name ($1),
|
||||
expression_context_block,
|
||||
VAR_NAMESPACE);
|
||||
sym = lookup_symbol (copy_name ($1),
|
||||
expression_context_block,
|
||||
VAR_NAMESPACE);
|
||||
if (sym)
|
||||
{
|
||||
write_exp_elt (OP_VAR_VALUE);
|
||||
|
@ -522,32 +444,6 @@ 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;
|
||||
|
@ -575,17 +471,6 @@ 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
|
||||
|
@ -605,19 +490,6 @@ 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
|
||||
;
|
||||
|
@ -1032,23 +904,13 @@ yylex ()
|
|||
{
|
||||
return STRUCT;
|
||||
}
|
||||
if (namelen == 5)
|
||||
if (namelen == 5 && !strncmp (tokstart, "union", 5))
|
||||
{
|
||||
if (!strncmp (tokstart, "union", 5))
|
||||
{
|
||||
return UNION;
|
||||
}
|
||||
return UNION;
|
||||
}
|
||||
if (namelen == 4)
|
||||
if (namelen == 4 && !strncmp (tokstart, "enum", 4))
|
||||
{
|
||||
if (!strncmp (tokstart, "enum", 4))
|
||||
{
|
||||
return ENUM;
|
||||
}
|
||||
if (!strncmp (tokstart, "this", 4))
|
||||
{
|
||||
return THIS;
|
||||
}
|
||||
return ENUM;
|
||||
}
|
||||
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
|
||||
{
|
||||
|
@ -1129,20 +991,10 @@ 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;
|
||||
|
@ -1173,6 +1025,7 @@ length_of_subexp (expr, endpos)
|
|||
oplen = 3 + ((expr->elts[endpos - 2].longconst
|
||||
+ sizeof (union exp_element))
|
||||
/ sizeof (union exp_element));
|
||||
|
||||
break;
|
||||
|
||||
case TERNOP_COND:
|
||||
|
@ -1184,11 +1037,6 @@ length_of_subexp (expr, endpos)
|
|||
args = 2;
|
||||
break;
|
||||
|
||||
/* C++ */
|
||||
case OP_THIS:
|
||||
oplen = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
args = 1 + (i < (int) BINOP_END);
|
||||
}
|
||||
|
@ -1226,13 +1074,6 @@ 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;
|
||||
|
@ -1275,11 +1116,6 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
|
|||
args = 2;
|
||||
break;
|
||||
|
||||
/* C++ */
|
||||
case OP_THIS:
|
||||
oplen = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
args = 1 + ((int) opcode < (int) BINOP_END);
|
||||
}
|
||||
|
|
|
@ -60,20 +60,6 @@ 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.
|
||||
|
@ -158,17 +144,6 @@ 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
|
||||
|
|
|
@ -212,9 +212,6 @@ read_var_value (var, frame)
|
|||
int val = SYMBOL_VALUE (var);
|
||||
register int len;
|
||||
|
||||
if (SYMBOL_CLASS (var) == LOC_BLOCK)
|
||||
type = lookup_function_type (type, 0);
|
||||
|
||||
v = allocate_value (type);
|
||||
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
|
||||
len = TYPE_LENGTH (type);
|
||||
|
@ -347,6 +344,7 @@ locate_var_value (var, frame)
|
|||
register CORE_ADDR addr = 0;
|
||||
int val = SYMBOL_VALUE (var);
|
||||
struct frame_info fi;
|
||||
struct type *type = SYMBOL_TYPE (var);
|
||||
|
||||
if (frame == 0) frame = selected_frame;
|
||||
|
||||
|
@ -362,7 +360,7 @@ locate_var_value (var, frame)
|
|||
if (addr != 0)
|
||||
{
|
||||
union { int i; char c; } test;
|
||||
int len = TYPE_LENGTH (SYMBOL_TYPE (var));
|
||||
int len = TYPE_LENGTH (type);
|
||||
/* If var is less than the full size of register, we need to
|
||||
test for a big-endian or little-endian machine. */
|
||||
test.i = 1;
|
||||
|
@ -398,7 +396,7 @@ locate_var_value (var, frame)
|
|||
break;
|
||||
}
|
||||
|
||||
return value_cast (lookup_pointer_type (SYMBOL_TYPE (var)),
|
||||
return value_cast (lookup_pointer_type (type),
|
||||
value_from_long (builtin_type_long, addr));
|
||||
}
|
||||
|
||||
|
|
2795
gdb/gdb+.texinfo
2795
gdb/gdb+.texinfo
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,91 @@
|
|||
.TH GDB 1 "13 April 1987"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
gdb \- Project GNU's DeBugger
|
||||
.SH SYNOPSIS
|
||||
\fBgdb\fP [ \fBoptions\fP ] See documentation mentioned below.
|
||||
.SH DESCRIPTION
|
||||
\fIgdb\fP is a source level symbolic debugger for C programs, created by
|
||||
Richard M. Stallman (rms) for the GNU Project, and distributed by the
|
||||
Free Software Foundation. Eventually GNU (Gnu's Not Unix) will be a
|
||||
complete replacement for Berkeley Unix, all of which everyone will be
|
||||
able to use freely. See the \fIGNU Emacs\fP man page for pointers to more
|
||||
information.
|
||||
.PP
|
||||
\fIgdb\fP has something of the flavor of \fIdbx\fP,
|
||||
but has more features and power. It can also be used to debug o/s
|
||||
kernels, but needs to be configured differently for that task.
|
||||
.PP
|
||||
Project GNU isn't using Unix man pages. Its style of complete
|
||||
documentation can be found by:
|
||||
.PP
|
||||
The help and info commands inside \fIgdb\fP.
|
||||
.PP
|
||||
In the Info system in \fIGNU Emacs\fP. Type C-h i, and follow the
|
||||
directions. This is equivalent to the reference manual for
|
||||
\fIgdb\fP, and has about 55 pages of text.
|
||||
.PP
|
||||
\fIgdb\fP could be extended to work with other languages (e.g. Pascal) and
|
||||
machines (e.g. encores). If you like, copy the sources and give it a
|
||||
try. When you have it working send \fIdiff -c\fP's of the changed files to
|
||||
bug-gdb@prep.ai.mit.edu (fuller details below), so they can benefit everyone.
|
||||
.SH DISTRIBUTION
|
||||
\fIgdb\fP is free; anyone may redistribute copies of
|
||||
\fIgdb\fP to anyone under the terms stated in the
|
||||
\fIgdb\fP General Public License, a copy of which accompanies each copy of
|
||||
\fIgdb\fP, is readable with the info command inside \fIgdb\fP,
|
||||
and which also appears in the \fIgdb\fP reference manual.
|
||||
.PP
|
||||
Copies of \fIgdb\fP may sometimes be received packaged with
|
||||
distributions of Unix systems, but it is never included in the scope
|
||||
of any license covering those systems. Such inclusion would violate
|
||||
the terms on which distribution is permitted. In fact, the primary
|
||||
purpose of the General Public License is to prohibit anyone from
|
||||
attaching any other restrictions to redistribution of \fIgdb\fP.
|
||||
.PP
|
||||
You can order printed copies of the \fIgdb\fP reference manual for $10.00/copy
|
||||
postpaid from the Free Software Foundation, which develops GNU software
|
||||
(contact them for quantity prices on the manual). Their address is:
|
||||
.nf
|
||||
Free Software Foundation
|
||||
1000 Mass Ave.
|
||||
Cambridge, MA 02138
|
||||
.fi
|
||||
As with all software and publications from FSF, everyone is permitted to
|
||||
make and distribute copies of the \fIgdb\fP reference manual.
|
||||
The TeX source to the \fIgdb\fP reference
|
||||
manual is also included in the \fIGNU Emacs\fP source distribution.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
See documentation.
|
||||
.SH EXAMPLES
|
||||
See documentation.
|
||||
.SH "SEE ALSO"
|
||||
adb(1), sdb(1), dbx(1)
|
||||
.SH BUGS
|
||||
There is a mailing list, bug-gdb@prep.ai.mit.edu on the internet
|
||||
(ucbvax!prep.ai.mit.edu!bug-gdb on UUCPnet), for reporting \fIgdb\fP
|
||||
bugs and fixes. But before reporting something as a bug, please try
|
||||
to be sure that it really is a bug, not a misunderstanding or a
|
||||
deliberate feature. We ask you to read the section ``Reporting Emacs
|
||||
Bugs'' near the end of the \fIGNU Emacs\fP reference manual
|
||||
(or Info system) for hints
|
||||
on how and when to report bugs. Also, include the version number of
|
||||
the \fIgdb\fP you are running in \fIevery\fR bug report that you send in.
|
||||
.PP
|
||||
Do not expect a personal answer to a bug report. The purpose of reporting
|
||||
bugs is to get them fixed for everyone in the next release, if possible.
|
||||
For personal assistance, look in the SERVICE file
|
||||
(see the \fIGNU Emacs\fP man page) for
|
||||
a list of people who offer it.
|
||||
.PP
|
||||
Please do not send anything but bug reports to this mailing list.
|
||||
Send other stuff to gnu@prep.ai.mit.edu (or the
|
||||
corresponding UUCP address). For more information about GNU mailing
|
||||
lists, see the file MAILINGLISTS (see the \fIGNU Emacs\fP man page). Bugs tend
|
||||
actually to be fixed if they can be isolated, so it is in your
|
||||
interest to report them in such a way that they can be easily
|
||||
reproduced.
|
||||
.PP
|
||||
No bugs are known at this time.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,284 @@
|
|||
/* Print GOULD RISC instructions for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <a.out.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/* GOULD RISC instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 4
|
||||
|
||||
/* Number of elements in the opcode table. */
|
||||
#define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0])
|
||||
|
||||
|
||||
/* Print the GOULD instruction at address MEMADDR in debugged memory,
|
||||
on STREAM. Returns length of the instruction, in bytes. */
|
||||
|
||||
int
|
||||
print_insn (memaddr, stream)
|
||||
CORE_ADDR memaddr;
|
||||
FILE *stream;
|
||||
{
|
||||
unsigned char buffer[MAXLEN];
|
||||
register int i;
|
||||
register char *d;
|
||||
register int bestmask;
|
||||
unsigned best;
|
||||
int temp, index, bestlen;
|
||||
|
||||
read_memory (memaddr, buffer, MAXLEN);
|
||||
|
||||
bestmask = 0;
|
||||
index = -1;
|
||||
best = 0xffffffff;
|
||||
for (i = 0; i < NOPCODES; i++)
|
||||
{
|
||||
register unsigned int opcode = gld_opcodes[i].opcode;
|
||||
register unsigned int mask = gld_opcodes[i].mask;
|
||||
register unsigned int len = gld_opcodes[i].length;
|
||||
register unsigned int test;
|
||||
|
||||
/* Get possible opcode bytes into integer */
|
||||
test = buffer[0] << 24;
|
||||
test |= buffer[1] << 16;
|
||||
test |= buffer[2] << 8;
|
||||
test |= buffer[3];
|
||||
|
||||
/* Mask with opcode and see if match */
|
||||
if ((opcode & mask) == (test & mask))
|
||||
{
|
||||
/* See if second or third match */
|
||||
if (index >= 0)
|
||||
{
|
||||
/* Take new one if it looks good */
|
||||
if (bestlen == MAXLEN && len == MAXLEN)
|
||||
{
|
||||
/* See if lower bits matched */
|
||||
if (((bestmask & 3) == 0) &&
|
||||
((mask & 3) != 0))
|
||||
{
|
||||
bestmask = mask;
|
||||
bestlen = len;
|
||||
best = test;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First match, save it */
|
||||
bestmask = mask;
|
||||
bestlen = len;
|
||||
best = test;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle undefined instructions. */
|
||||
if (index < 0)
|
||||
{
|
||||
fprintf (stream, "undefined 0%o",(buffer[0]<<8)+buffer[1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Print instruction name */
|
||||
fprintf (stream, "%-12s", gld_opcodes[index].name);
|
||||
|
||||
/* Adjust if short instruction */
|
||||
if (gld_opcodes[index].length < 4)
|
||||
{
|
||||
best >>= 16;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 16;
|
||||
}
|
||||
|
||||
/* Dump out instruction arguments */
|
||||
for (d = gld_opcodes[index].args; *d; ++d)
|
||||
{
|
||||
switch (*d)
|
||||
{
|
||||
case 'f':
|
||||
fprintf (stream, "%d", (best >> (7 + i)) & 7);
|
||||
break;
|
||||
case 'r':
|
||||
fprintf (stream, "r%d", (best >> (7 + i)) & 7);
|
||||
break;
|
||||
case 'R':
|
||||
fprintf (stream, "r%d", (best >> (4 + i)) & 7);
|
||||
break;
|
||||
case 'b':
|
||||
fprintf (stream, "b%d", (best >> (7 + i)) & 7);
|
||||
break;
|
||||
case 'B':
|
||||
fprintf (stream, "b%d", (best >> (4 + i)) & 7);
|
||||
break;
|
||||
case 'v':
|
||||
fprintf (stream, "b%d", (best >> (7 + i)) & 7);
|
||||
break;
|
||||
case 'V':
|
||||
fprintf (stream, "b%d", (best >> (4 + i)) & 7);
|
||||
break;
|
||||
case 'X':
|
||||
temp = (best >> 20) & 7;
|
||||
if (temp)
|
||||
fprintf (stream, "r%d", temp);
|
||||
else
|
||||
putc ('0', stream);
|
||||
break;
|
||||
case 'A':
|
||||
temp = (best >> 16) & 7;
|
||||
if (temp)
|
||||
fprintf (stream, "(b%d)", temp);
|
||||
break;
|
||||
case 'S':
|
||||
fprintf (stream, "#%d", best & 0x1f);
|
||||
break;
|
||||
case 'I':
|
||||
fprintf (stream, "#%x", best & 0xffff);
|
||||
break;
|
||||
case 'O':
|
||||
fprintf (stream, "%x", best & 0xffff);
|
||||
break;
|
||||
case 'h':
|
||||
fprintf (stream, "%d", best & 0xfffe);
|
||||
break;
|
||||
case 'd':
|
||||
fprintf (stream, "%d", best & 0xfffc);
|
||||
break;
|
||||
case 'T':
|
||||
fprintf (stream, "%d", (best >> 8) & 0xff);
|
||||
break;
|
||||
case 'N':
|
||||
fprintf (stream, "%d", best & 0xff);
|
||||
break;
|
||||
default:
|
||||
putc (*d, stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return length of instruction */
|
||||
return (gld_opcodes[index].length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the number of arguments to a function.
|
||||
*/
|
||||
findarg(frame)
|
||||
struct frame_info frame;
|
||||
{
|
||||
register struct symbol *func;
|
||||
register unsigned pc;
|
||||
|
||||
#ifdef notdef
|
||||
/* find starting address of frame function */
|
||||
pc = get_pc_function_start (frame.pc);
|
||||
|
||||
/* find function symbol info */
|
||||
func = find_pc_function (pc);
|
||||
|
||||
/* call blockframe code to look for match */
|
||||
if (func != NULL)
|
||||
return (func->value.block->nsyms / sizeof(int));
|
||||
#endif
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the case of the NPL, the frame's norminal address is Br2 and the
|
||||
* previous routines frame is up the stack X bytes. Finding out what
|
||||
* 'X' is can be tricky.
|
||||
*
|
||||
* 1.) stored in the code function header xA(Br1).
|
||||
* 2.) must be careful of recurssion.
|
||||
*/
|
||||
findframe(thisframe)
|
||||
FRAME thisframe;
|
||||
{
|
||||
register FRAME pointer;
|
||||
struct frame_info frame;
|
||||
|
||||
/* Setup toplevel frame structure */
|
||||
frame.pc = read_pc();
|
||||
frame.next_frame = 0;
|
||||
frame.frame = read_register (SP_REGNUM); /* Br2 */
|
||||
|
||||
/* Search for this frame (start at current Br2) */
|
||||
do
|
||||
{
|
||||
pointer = framechain(frame);
|
||||
frame.next_frame = frame.frame;
|
||||
frame.frame = pointer;
|
||||
frame.pc = FRAME_SAVED_PC(frame.next_frame);
|
||||
}
|
||||
while (frame.next_frame != thisframe);
|
||||
|
||||
/* stop gap for now, end at __base3 */
|
||||
if (frame.pc == 0)
|
||||
return 0;
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gdb front-end and internal framechain routine.
|
||||
* Go back up stack one level. Tricky...
|
||||
*/
|
||||
framechain(frame)
|
||||
register struct frame_info frame;
|
||||
{
|
||||
register CORE_ADDR func, prevsp;
|
||||
register unsigned value;
|
||||
|
||||
/* Get real function start address from internal frame address */
|
||||
func = get_pc_function_start(frame.pc);
|
||||
|
||||
/* If no stack given, read register Br1 "(sp)" */
|
||||
if (!frame.frame)
|
||||
prevsp = read_register (SP_REGNUM);
|
||||
else
|
||||
prevsp = frame.frame;
|
||||
|
||||
/* Check function header, case #2 */
|
||||
value = read_memory_integer (func, 4);
|
||||
if (value)
|
||||
{
|
||||
/* 32bit call push value stored in function header */
|
||||
prevsp += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read half-word from suabr at start of function */
|
||||
prevsp += read_memory_integer (func + 10, 2);
|
||||
}
|
||||
|
||||
return (prevsp);
|
||||
}
|
31
gdb/infcmd.c
31
gdb/infcmd.c
|
@ -172,7 +172,7 @@ Start it from the beginning? "))
|
|||
if (args)
|
||||
set_args_command (args);
|
||||
|
||||
exec_file = (char *) get_exec_file ();
|
||||
exec_file = (char *) get_exec_file (1);
|
||||
if (from_tty)
|
||||
{
|
||||
printf ("Starting program: %s%s\n",
|
||||
|
@ -299,7 +299,6 @@ 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;
|
||||
|
@ -307,14 +306,7 @@ jump_command (arg, from_tty)
|
|||
if (!arg)
|
||||
error_no_arg ("starting address");
|
||||
|
||||
sals = decode_line_spec (arg, 1);
|
||||
if (sals.nelts != 1)
|
||||
{
|
||||
error ("Unreasonable jump request");
|
||||
}
|
||||
|
||||
sal = sals.sals[0];
|
||||
free (sals.sals);
|
||||
sal = decode_line_spec (arg, 1);
|
||||
|
||||
if (sal.symtab == 0 && sal.pc == 0)
|
||||
error ("No source file has been specified.");
|
||||
|
@ -326,7 +318,7 @@ jump_command (arg, from_tty)
|
|||
struct symbol *fn = get_frame_function (get_current_frame ());
|
||||
struct symbol *sfn = find_pc_function (sal.pc);
|
||||
if (fn != 0 && sfn != fn
|
||||
&& ! query ("That is not in function %s. Continue there? ",
|
||||
&& ! query ("Line %d is not in `%s'. Jump anyway? ",
|
||||
sal.line, SYMBOL_NAME (fn)))
|
||||
error ("Not confirmed.");
|
||||
}
|
||||
|
@ -482,14 +474,13 @@ finish_command (arg, from_tty)
|
|||
struct type *value_type;
|
||||
register value val;
|
||||
|
||||
if (TYPE_CODE (SYMBOL_TYPE (function)) != TYPE_CODE_VOID)
|
||||
value_type = SYMBOL_TYPE (function);
|
||||
else
|
||||
value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
|
||||
if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
|
||||
return;
|
||||
|
||||
val = value_being_returned (value_type, stop_registers);
|
||||
printf ("Value returned is $%d = ", record_latest_value (val));
|
||||
value_print (val, stdout);
|
||||
value_print (val, stdout, 0);
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
|
@ -679,7 +670,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);
|
||||
val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0);
|
||||
/* 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))
|
||||
|
@ -743,7 +734,7 @@ attach_command (args, from_tty)
|
|||
{
|
||||
char *exec_file;
|
||||
int pid;
|
||||
int remote;
|
||||
int remote = 0;
|
||||
|
||||
dont_repeat();
|
||||
|
||||
|
@ -765,7 +756,7 @@ attach_command (args, from_tty)
|
|||
error ("Inferior not killed.");
|
||||
}
|
||||
|
||||
exec_file = (char *) get_exec_file ();
|
||||
exec_file = (char *) get_exec_file (1);
|
||||
|
||||
if (from_tty)
|
||||
{
|
||||
|
@ -802,13 +793,15 @@ detach_command (args, from_tty)
|
|||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
char *exec_file = (char *)get_exec_file ();
|
||||
int signal = 0;
|
||||
|
||||
if (!inferior_pid)
|
||||
error ("Not currently tracing a program\n");
|
||||
if (from_tty)
|
||||
{
|
||||
char *exec_file = (char *)get_exec_file (0);
|
||||
if (exec_file == 0)
|
||||
exec_file = "";
|
||||
printf ("Detaching program: %s pid %d\n",
|
||||
exec_file, inferior_pid);
|
||||
fflush (stdout);
|
||||
|
|
343
gdb/inflow.c
343
gdb/inflow.c
|
@ -27,14 +27,18 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#ifndef UMAX_PTRACE
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sgtty.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef UMAX_PTRACE
|
||||
#include <a.out.h>
|
||||
#include <sys/ptrace.h>
|
||||
#define PTRACE_ATTACH PT_ATTACH
|
||||
#define PTRACE_DETACH PT_FREEPROC
|
||||
#endif
|
||||
|
||||
#ifdef NEW_SUN_PTRACE
|
||||
|
@ -42,6 +46,26 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <machine/reg.h>
|
||||
#endif
|
||||
|
||||
#ifdef HP9K320
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/reg.h>
|
||||
#include <sys/trap.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
#include <termio.h>
|
||||
#undef TIOCGETP
|
||||
#define TIOCGETP TCGETA
|
||||
#undef TIOCSETN
|
||||
#define TIOCSETN TCSETA
|
||||
#undef TIOCSETP
|
||||
#define TIOCSETP TCSETAF
|
||||
#define TERMINAL struct termio
|
||||
#else
|
||||
#include <sgtty.h>
|
||||
#define TERMINAL struct sgttyb
|
||||
#endif
|
||||
|
||||
extern int errno;
|
||||
|
||||
/* Nonzero if we are debugging an attached outside process
|
||||
|
@ -53,19 +77,27 @@ START_FILE
|
|||
|
||||
/* Record terminal status separately for debugger and inferior. */
|
||||
|
||||
static struct sgttyb sg_inferior;
|
||||
static struct tchars tc_inferior;
|
||||
static struct ltchars ltc_inferior;
|
||||
static int lmode_inferior;
|
||||
static TERMINAL sg_inferior;
|
||||
static TERMINAL sg_ours;
|
||||
static int tflags_inferior;
|
||||
static int pgrp_inferior;
|
||||
|
||||
static struct sgttyb sg_ours;
|
||||
static struct tchars tc_ours;
|
||||
static struct ltchars ltc_ours;
|
||||
static int lmode_ours;
|
||||
static int tflags_ours;
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
static struct tchars tc_inferior;
|
||||
static struct tchars tc_ours;
|
||||
static struct ltchars ltc_inferior;
|
||||
static struct ltchars ltc_ours;
|
||||
static int lmode_inferior;
|
||||
static int lmode_ours;
|
||||
#endif /* TIOCGLTC */
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
static int pgrp_inferior;
|
||||
static int pgrp_ours;
|
||||
#else
|
||||
static int (*sigint_ours) ();
|
||||
static int (*sigquit_ours) ();
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
/* Copy of inferior_io_terminal when inferior was last started. */
|
||||
static char *inferior_thisrun_terminal;
|
||||
|
@ -86,11 +118,17 @@ terminal_init_inferior ()
|
|||
return;
|
||||
|
||||
sg_inferior = sg_ours;
|
||||
tflags_inferior = tflags_ours;
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
tc_inferior = tc_ours;
|
||||
ltc_inferior = ltc_ours;
|
||||
lmode_inferior = lmode_ours;
|
||||
tflags_inferior = tflags_ours;
|
||||
#endif /* TIOCGLTC */
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
pgrp_inferior = inferior_pid;
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
terminal_is_ours = 1;
|
||||
}
|
||||
|
@ -109,10 +147,19 @@ terminal_inferior ()
|
|||
fcntl (0, F_SETFL, tflags_inferior);
|
||||
fcntl (0, F_SETFL, tflags_inferior);
|
||||
ioctl (0, TIOCSETN, &sg_inferior);
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
ioctl (0, TIOCSETC, &tc_inferior);
|
||||
ioctl (0, TIOCSLTC, <c_inferior);
|
||||
ioctl (0, TIOCLSET, &lmode_inferior);
|
||||
#endif /* TIOCGLTC */
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
ioctl (0, TIOCSPGRP, &pgrp_inferior);
|
||||
#else
|
||||
sigint_ours = (signal (SIGINT, SIG_IGN));
|
||||
sigquit_ours = (signal (SIGQUIT, SIG_IGN));
|
||||
#endif /* TIOCGPGRP */
|
||||
}
|
||||
terminal_is_ours = 0;
|
||||
}
|
||||
|
@ -151,38 +198,63 @@ static void
|
|||
terminal_ours_1 (output_only)
|
||||
int output_only;
|
||||
{
|
||||
#ifdef TIOCGPGRP
|
||||
/* Ignore this signal since it will happen when we try to set the pgrp. */
|
||||
int (*osigttou) ();
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
|
||||
{
|
||||
terminal_is_ours = 1;
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
osigttou = signal (SIGTTOU, SIG_IGN);
|
||||
|
||||
ioctl (0, TIOCGPGRP, &pgrp_inferior);
|
||||
ioctl (0, TIOCSPGRP, &pgrp_ours);
|
||||
|
||||
signal (SIGTTOU, osigttou);
|
||||
#else
|
||||
signal (SIGINT, sigint_ours);
|
||||
signal (SIGQUIT, sigquit_ours);
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
tflags_inferior = fcntl (0, F_GETFL, 0);
|
||||
ioctl (0, TIOCGETP, &sg_inferior);
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
ioctl (0, TIOCGETC, &tc_inferior);
|
||||
ioctl (0, TIOCGLTC, <c_inferior);
|
||||
ioctl (0, TIOCLGET, &lmode_inferior);
|
||||
#endif /* TIOCGLTC */
|
||||
}
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
sg_ours.c_lflag |= ICANON;
|
||||
if (output_only && !(sg_inferior.c_lflag & ICANON))
|
||||
sg_ours.c_lflag &= ~ICANON;
|
||||
#else /* not HAVE_TERMIO */
|
||||
sg_ours.sg_flags &= ~RAW & ~CBREAK;
|
||||
if (output_only)
|
||||
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
|
||||
#endif /* not HAVE_TERMIO */
|
||||
|
||||
fcntl (0, F_SETFL, tflags_ours);
|
||||
fcntl (0, F_SETFL, tflags_ours);
|
||||
ioctl (0, TIOCSETN, &sg_ours);
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
ioctl (0, TIOCSETC, &tc_ours);
|
||||
ioctl (0, TIOCSLTC, <c_ours);
|
||||
ioctl (0, TIOCLSET, &lmode_ours);
|
||||
#endif /* TIOCGLTC */
|
||||
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
sg_ours.c_lflag |= ICANON;
|
||||
#else /* not HAVE_TERMIO */
|
||||
sg_ours.sg_flags &= ~RAW & ~CBREAK;
|
||||
#endif /* not HAVE_TERMIO */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -197,6 +269,20 @@ term_status_command ()
|
|||
}
|
||||
|
||||
printf ("Inferior's terminal status (currently saved by GDB):\n");
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
|
||||
printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
|
||||
tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
|
||||
printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
|
||||
sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
|
||||
printf ("c_cc: ");
|
||||
for (i = 0; (i < NCC); i += 1)
|
||||
printf ("0x%x ", sg_inferior.c_cc[i]);
|
||||
printf ("\n");
|
||||
|
||||
#else /* not HAVE_TERMIO */
|
||||
|
||||
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
|
||||
tflags_inferior, lmode_inferior,
|
||||
sg_inferior.sg_flags, pgrp_inferior);
|
||||
|
@ -207,7 +293,8 @@ term_status_command ()
|
|||
printf ("ltchars: ");
|
||||
for (i = 0; i < sizeof (struct ltchars); i++)
|
||||
printf ("0x%x ", ((char *)<c_inferior)[i]);
|
||||
printf ("\n");
|
||||
|
||||
#endif /* not HAVE_TERMIO */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -243,19 +330,34 @@ new_tty (ttyname)
|
|||
}
|
||||
|
||||
/* Start an inferior process and returns its pid.
|
||||
ALLARGS is a vector of program-name and args.
|
||||
ALLARGS is a string containing shell command to run the program.
|
||||
ENV is the environment vector to pass. */
|
||||
|
||||
#ifndef SHELL_FILE
|
||||
#define SHELL_FILE "/bin/sh"
|
||||
#endif
|
||||
|
||||
int
|
||||
create_inferior (allargs, env)
|
||||
char **allargs;
|
||||
char *allargs;
|
||||
char **env;
|
||||
{
|
||||
int pid;
|
||||
char *shell_command;
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
|
||||
/* If desired, concat something onto the front of ALLARGS.
|
||||
SHELL_COMMAND is the result. */
|
||||
#ifdef SHELL_COMMAND_CONCAT
|
||||
shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
|
||||
strcpy (shell_command, SHELL_COMMAND_CONCAT);
|
||||
strcat (shell_command, allargs);
|
||||
#else
|
||||
shell_command = allargs;
|
||||
#endif
|
||||
|
||||
/* exec is said to fail if the executable is open. */
|
||||
close_exec_file ();
|
||||
|
||||
|
@ -265,8 +367,12 @@ create_inferior (allargs, env)
|
|||
|
||||
if (pid == 0)
|
||||
{
|
||||
char *args[4];
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
/* Run inferior in a separate process group. */
|
||||
setpgrp (getpid (), getpid ());
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
inferior_thisrun_terminal = inferior_io_terminal;
|
||||
if (inferior_io_terminal != 0)
|
||||
|
@ -278,9 +384,15 @@ create_inferior (allargs, env)
|
|||
signal (SIGINT, SIG_DFL); */
|
||||
|
||||
ptrace (0);
|
||||
execle ("/bin/sh", "sh", "-c", allargs, 0, env);
|
||||
|
||||
fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
|
||||
args[0] = "sh";
|
||||
args[1] = "-c";
|
||||
args[2] = shell_command;
|
||||
args[3] = 0;
|
||||
|
||||
execve (SHELL_FILE, args, env);
|
||||
|
||||
fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
|
||||
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
|
||||
fflush (stderr);
|
||||
_exit (0177);
|
||||
|
@ -313,6 +425,18 @@ kill_inferior ()
|
|||
inferior_died ();
|
||||
}
|
||||
|
||||
/* This is used when GDB is exiting. It gives less chance of error.*/
|
||||
|
||||
kill_inferior_fast ()
|
||||
{
|
||||
if (remote_debugging)
|
||||
return;
|
||||
if (inferior_pid == 0)
|
||||
return;
|
||||
ptrace (8, inferior_pid, 0, 0);
|
||||
wait (0);
|
||||
}
|
||||
|
||||
inferior_died ()
|
||||
{
|
||||
inferior_pid = 0;
|
||||
|
@ -343,7 +467,7 @@ resume (step, signal)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef NEW_SUN_PTRACE
|
||||
#ifdef ATTACH_DETACH
|
||||
|
||||
/* Start debugging the process whose number is PID. */
|
||||
|
||||
|
@ -372,7 +496,7 @@ detach (signal)
|
|||
perror_with_name ("ptrace");
|
||||
attach_flag = 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* ATTACH_DETACH */
|
||||
|
||||
#ifdef NEW_SUN_PTRACE
|
||||
|
||||
|
@ -431,6 +555,146 @@ store_inferior_registers (regno)
|
|||
}
|
||||
|
||||
#else
|
||||
#ifdef HP9K320
|
||||
|
||||
#define FP_REGISTER_ADDR_DIFF(u, regno) \
|
||||
(((char *) (FP_REGISTER_ADDR (u, regno))) - ((char *) &(u)))
|
||||
|
||||
#define INFERIOR_AR0(u) \
|
||||
((ptrace \
|
||||
(PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
|
||||
- KERNEL_U_ADDR)
|
||||
|
||||
static void
|
||||
fetch_inferior_register (regno, regaddr)
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
{
|
||||
#ifndef HPUX_VERSION_5
|
||||
if (regno == PS_REGNUM)
|
||||
{
|
||||
union { int i; short s[2]; } ps_val;
|
||||
int regval;
|
||||
|
||||
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
|
||||
regval = ps_val.s[0];
|
||||
supply_register (regno, ®val);
|
||||
}
|
||||
else
|
||||
#endif /* not HPUX_VERSION_5 */
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
*(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
store_inferior_register_1 (regno, regaddr, value)
|
||||
int regno;
|
||||
unsigned int regaddr;
|
||||
int value;
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PT_WUAREA, inferior_pid, regaddr, value);
|
||||
#if 0
|
||||
/* HP-UX randomly sets errno to non-zero for regno == 25.
|
||||
However, the value is correctly written, so ignore errno. */
|
||||
if (errno != 0)
|
||||
{
|
||||
char string_buf[64];
|
||||
|
||||
sprintf (string_buf, "writing register number %d", regno);
|
||||
perror_with_name (string_buf);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
store_inferior_register (regno, regaddr)
|
||||
register int regno;
|
||||
register unsigned int regaddr;
|
||||
{
|
||||
#ifndef HPUX_VERSION_5
|
||||
if (regno == PS_REGNUM)
|
||||
{
|
||||
union { int i; short s[2]; } ps_val;
|
||||
|
||||
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
|
||||
ps_val.s[0] = (read_register (regno));
|
||||
store_inferior_register_1 (regno, regaddr, ps_val.i);
|
||||
}
|
||||
else
|
||||
#endif /* not HPUX_VERSION_5 */
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
extern char registers[];
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
store_inferior_register_1
|
||||
(regno, regaddr,
|
||||
(*(int *) ®isters[(REGISTER_BYTE (regno)) + i]));
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
{
|
||||
struct user u;
|
||||
register int regno;
|
||||
register unsigned int ar0_offset;
|
||||
|
||||
ar0_offset = (INFERIOR_AR0 (u));
|
||||
for (regno = 0; (regno < FP0_REGNUM); regno++)
|
||||
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
for (; (regno < NUM_REGS); regno++)
|
||||
fetch_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
store_inferior_registers (regno)
|
||||
register int regno;
|
||||
{
|
||||
struct user u;
|
||||
register unsigned int ar0_offset;
|
||||
|
||||
if (regno >= FP0_REGNUM)
|
||||
{
|
||||
store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
ar0_offset = (INFERIOR_AR0 (u));
|
||||
if (regno >= 0)
|
||||
{
|
||||
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
for (regno = 0; (regno < FP0_REGNUM); regno++)
|
||||
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
|
||||
for (; (regno < NUM_REGS); regno++)
|
||||
store_inferior_register (regno, (FP_REGISTER_ADDR_DIFF (u, regno)));
|
||||
return;
|
||||
}
|
||||
|
||||
#else /* not HP9K320 */
|
||||
|
||||
void
|
||||
fetch_inferior_registers ()
|
||||
|
@ -469,6 +733,8 @@ store_inferior_registers (regno)
|
|||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[80];
|
||||
extern char registers[];
|
||||
int i;
|
||||
|
||||
#ifdef UMAX_PTRACE
|
||||
unsigned int offset = 0;
|
||||
|
@ -481,27 +747,38 @@ store_inferior_registers (regno)
|
|||
if (regno >= 0)
|
||||
{
|
||||
regaddr = register_addr (regno, offset);
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, regaddr,
|
||||
*(int *) ®isters[REGISTER_BYTE (regno) + i]);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d(%d)", regno, i);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
regaddr += sizeof(int);
|
||||
}
|
||||
}
|
||||
else for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
regaddr = register_addr (regno, offset);
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, regaddr,
|
||||
*(int *) ®isters[REGISTER_BYTE (regno) + i]);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d(%d)", regno, i);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
regaddr += sizeof(int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* not HP9K320 */
|
||||
#endif /* not NEW_SUN_PTRACE */
|
||||
|
||||
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
|
||||
|
@ -641,11 +918,17 @@ Report which ones can be written.");
|
|||
inferior_pid = 0;
|
||||
|
||||
ioctl (0, TIOCGETP, &sg_ours);
|
||||
fcntl (0, F_GETFL, tflags_ours);
|
||||
|
||||
#ifdef TIOCGLTC
|
||||
ioctl (0, TIOCGETC, &tc_ours);
|
||||
ioctl (0, TIOCGLTC, <c_ours);
|
||||
ioctl (0, TIOCLGET, &lmode_ours);
|
||||
fcntl (0, F_GETFL, tflags_ours);
|
||||
#endif /* TIOCGLTC */
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
ioctl (0, TIOCGPGRP, &pgrp_ours);
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
terminal_is_ours = 1;
|
||||
}
|
||||
|
|
88
gdb/infrun.c
88
gdb/infrun.c
|
@ -29,6 +29,7 @@ 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>
|
||||
|
@ -76,6 +77,12 @@ static int step_resume_break_duplicate;
|
|||
|
||||
static int trap_expected;
|
||||
|
||||
/* Nonzero if the next time we try to continue the inferior, it will
|
||||
step one instruction and generate a spurious trace trap.
|
||||
This is used to compensate for a bug in HP-UX. */
|
||||
|
||||
static int trap_expected_after_continue;
|
||||
|
||||
/* Nonzero means expecting a trace trap
|
||||
and should stop the inferior and return silently when it happens. */
|
||||
|
||||
|
@ -168,17 +175,26 @@ proceed (addr, signal, step)
|
|||
so that we do not stop right away. */
|
||||
|
||||
if (!pc_changed && breakpoint_here_p (read_pc ()))
|
||||
{
|
||||
oneproc = 1;
|
||||
/* We will get a trace trap after one instruction.
|
||||
Continue it automatically and insert breakpoints then. */
|
||||
trap_expected = 1;
|
||||
}
|
||||
oneproc = 1;
|
||||
}
|
||||
else
|
||||
write_register (PC_REGNUM, addr);
|
||||
|
||||
if (!oneproc)
|
||||
if (trap_expected_after_continue)
|
||||
{
|
||||
/* If (step == 0), a trap will be automatically generated after
|
||||
the first instruction is executed. Force step one
|
||||
instruction to clear this condition. This should not occur
|
||||
if step is nonzero, but it is harmless in that case. */
|
||||
oneproc = 1;
|
||||
trap_expected_after_continue = 0;
|
||||
}
|
||||
|
||||
if (oneproc)
|
||||
/* We will get a trace trap after one instruction.
|
||||
Continue it automatically and insert breakpoints then. */
|
||||
trap_expected = 1;
|
||||
else
|
||||
{
|
||||
int temp = insert_breakpoints ();
|
||||
if (temp)
|
||||
|
@ -232,6 +248,7 @@ start_inferior ()
|
|||
it will get another trace trap. Then insert breakpoints and continue. */
|
||||
trap_expected = 2;
|
||||
running_in_shell = 0; /* Set to 1 at first SIGTRAP, 0 at second. */
|
||||
trap_expected_after_continue = 0;
|
||||
breakpoints_inserted = 0;
|
||||
mark_breakpoints_out ();
|
||||
|
||||
|
@ -321,10 +338,10 @@ wait_for_inferior ()
|
|||
struct symtab_and_line sal;
|
||||
int prev_pc;
|
||||
|
||||
prev_pc = read_pc ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
prev_pc = read_pc ();
|
||||
|
||||
if (remote_debugging)
|
||||
remote_wait (&w);
|
||||
else
|
||||
|
@ -545,6 +562,9 @@ wait_for_inferior ()
|
|||
{
|
||||
stop_print_frame = 0;
|
||||
stop_stack_dummy = 1;
|
||||
#ifdef HP9K320
|
||||
trap_expected_after_continue = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -611,20 +631,27 @@ wait_for_inferior ()
|
|||
continue to the end of that source line.
|
||||
Otherwise, just go to end of prologue. */
|
||||
if (sal.end && sal.pc != newfun_pc)
|
||||
step_resume_break_address = sal.end;
|
||||
else
|
||||
step_resume_break_address = newfun_pc;
|
||||
newfun_pc = sal.end;
|
||||
|
||||
step_resume_break_duplicate
|
||||
= breakpoint_here_p (step_resume_break_address);
|
||||
if (breakpoints_inserted)
|
||||
insert_step_breakpoint ();
|
||||
/* Do not specify what the fp should be when we stop
|
||||
since on some machines the prologue
|
||||
is where the new fp value is established. */
|
||||
step_frame = 0;
|
||||
/* And make sure stepping stops right away then. */
|
||||
step_range_end = step_range_start;
|
||||
if (newfun_pc == stop_pc)
|
||||
/* We are already there: stop now. */
|
||||
stop_step = 1;
|
||||
else
|
||||
/* Put the step-breakpoint there and go until there. */
|
||||
{
|
||||
step_resume_break_address = newfun_pc;
|
||||
|
||||
step_resume_break_duplicate
|
||||
= breakpoint_here_p (step_resume_break_address);
|
||||
if (breakpoints_inserted)
|
||||
insert_step_breakpoint ();
|
||||
/* Do not specify what the fp should be when we stop
|
||||
since on some machines the prologue
|
||||
is where the new fp value is established. */
|
||||
step_frame = 0;
|
||||
/* And make sure stepping stops right away then. */
|
||||
step_range_end = step_range_start;
|
||||
}
|
||||
}
|
||||
/* No subroutince call; stop now. */
|
||||
else
|
||||
|
@ -635,6 +662,9 @@ wait_for_inferior ()
|
|||
}
|
||||
}
|
||||
|
||||
/* Save the pc before execution, to compare with pc after stop. */
|
||||
prev_pc = read_pc ();
|
||||
|
||||
/* If we did not do break;, it means we should keep
|
||||
running the inferior and not return to debugger. */
|
||||
|
||||
|
@ -723,6 +753,11 @@ Further execution is probably impossible.\n");
|
|||
|
||||
breakpoint_auto_delete (stop_breakpoint);
|
||||
|
||||
/* If an auto-display called a function and that got a signal,
|
||||
delete that auto-display to avoid an infinite recursion. */
|
||||
|
||||
delete_current_display ();
|
||||
|
||||
if (step_multi && stop_step)
|
||||
return;
|
||||
|
||||
|
@ -731,7 +766,13 @@ Further execution is probably impossible.\n");
|
|||
if (running_in_shell)
|
||||
{
|
||||
if (stop_signal == SIGSEGV)
|
||||
printf ("\
|
||||
{
|
||||
char *exec_file = (char *) get_exec_file (1);
|
||||
|
||||
if (access (exec_file, X_OK) != 0)
|
||||
printf ("The file \"%s\" is not executable.\n", exec_file);
|
||||
else
|
||||
printf ("\
|
||||
You have just encountered a bug in \"sh\". GDB starts your program\n\
|
||||
by running \"sh\" with a command to exec your program.\n\
|
||||
This is so that \"sh\" will process wildcards and I/O redirection.\n\
|
||||
|
@ -743,6 +784,7 @@ 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;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ what you give them. Help stamp out software-hoarding! */
|
|||
of the end of one object file's text to the start of the next
|
||||
object file's text. */
|
||||
|
||||
#include "m-suninit.h"
|
||||
#include "m-init.h"
|
||||
|
||||
/* This is used to make a file's initialization function.
|
||||
It calls another function named `initialize', which must
|
||||
|
|
|
@ -0,0 +1,542 @@
|
|||
/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#ifndef HP9K320
|
||||
#define HP9K320
|
||||
#endif
|
||||
|
||||
/* Set flag to indicate whether HP's assembler is in use. */
|
||||
#ifdef __GNU__
|
||||
#ifdef __HPUX_ASM__
|
||||
#define HPUX_ASM
|
||||
#endif
|
||||
#else
|
||||
#define HPUX_ASM
|
||||
#endif
|
||||
|
||||
/* Define this for versions of hp-ux older than 6.0 */
|
||||
/* #define HPUX_VERSION_5 */
|
||||
|
||||
#define HAVE_TERMIO
|
||||
|
||||
/* Get rid of any system-imposed stack limit if possible. */
|
||||
|
||||
/* #define SET_STACK_LIMIT_HUGE */
|
||||
|
||||
/* Define this if the C compiler puts an underscore at the front
|
||||
of external names before giving them to the linker. */
|
||||
|
||||
#define NAMES_HAVE_UNDERSCORE
|
||||
|
||||
/* Debugger information will be in DBX format. */
|
||||
|
||||
#define READ_DBX_FORMAT
|
||||
|
||||
/* Offset from address of function to start of its code.
|
||||
Zero on most machines. */
|
||||
|
||||
#define FUNCTION_START_OFFSET 0
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. */
|
||||
|
||||
#define SKIP_PROLOGUE(pc) \
|
||||
{ register int op = read_memory_integer (pc, 2); \
|
||||
if (op == 0047126) \
|
||||
pc += 4; /* Skip link #word */ \
|
||||
else if (op == 0044016) \
|
||||
pc += 6; /* Skip link #long */ \
|
||||
}
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't go through the frames for this because on some machines
|
||||
the new frame is not set up until the new function executes
|
||||
some instructions. */
|
||||
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
read_memory_integer (read_register (SP_REGNUM), 4)
|
||||
|
||||
/* This is the amount to subtract from u.u_ar0
|
||||
to get the offset in the core file of the register values. */
|
||||
|
||||
#ifdef HPUX_VERSION_5
|
||||
#define KERNEL_U_ADDR 0x00979000
|
||||
#else
|
||||
#define KERNEL_U_ADDR 0x00C01000
|
||||
#endif
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR 0xFFF00000
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0x4e, 0x41}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 29
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
|
||||
#define REGISTER_NAMES \
|
||||
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
|
||||
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
|
||||
"ps", "pc", \
|
||||
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
|
||||
"fpcontrol", "fpstatus", "fpiaddr" }
|
||||
|
||||
/* Register numbers of various important registers.
|
||||
Note that some of these values are "real" register numbers,
|
||||
and correspond to the general registers of the machine,
|
||||
and some are "phony" register numbers which are too large
|
||||
to be actual register numbers as far as the user is concerned
|
||||
but do serve to get the desired values when passed to read_register. */
|
||||
|
||||
#define FP_REGNUM 14 /* Contains address of executing stack frame */
|
||||
#define SP_REGNUM 15 /* Contains address of top of stack */
|
||||
#define PS_REGNUM 16 /* Contains processor status */
|
||||
#define PC_REGNUM 17 /* Contains program counter */
|
||||
#define FP0_REGNUM 18 /* Floating point register 0 */
|
||||
#define FPC_REGNUM 26 /* 68881 control register */
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES (16*4+8*12+8+12)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) \
|
||||
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
|
||||
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
|
||||
: (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 12 bytes. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 8-byte doubles. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_RAW_SIZE 12
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
|
||||
|
||||
/* Convert data from raw format for register REGNUM
|
||||
to virtual format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_from_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_to_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
|
||||
|
||||
/* Extract from an array REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
|
||||
|
||||
/* Write into appropriate registers a function return value
|
||||
of type TYPE, given in virtual format. */
|
||||
|
||||
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
|
||||
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
|
||||
|
||||
/* Extract from an array REGBUF containing the (raw) register state
|
||||
the address in which a function should return its structure value,
|
||||
as a CORE_ADDR (or an expression that can be used as one). */
|
||||
|
||||
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
|
||||
|
||||
#define REGISTER_ADDR(u_ar0, regno) \
|
||||
(((regno) < PS_REGNUM) \
|
||||
? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \
|
||||
: (((regno) == PS_REGNUM) \
|
||||
? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \
|
||||
: (&((struct exception_stack *) (u_ar0))->e_PC)))
|
||||
|
||||
#define FP_REGISTER_ADDR(u, regno) \
|
||||
(((regno) < FPC_REGNUM) \
|
||||
? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
|
||||
: (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))
|
||||
|
||||
/* It is safe to look for symsegs on a Sun, because Sun's ld
|
||||
does not screw up with random garbage at end of file. */
|
||||
|
||||
#define READ_GDB_SYMSEGS
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
|
||||
/* FRAME_CHAIN takes a frame's nominal address
|
||||
and produces the frame's chain-pointer.
|
||||
|
||||
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
|
||||
and produces the nominal address of the caller frame.
|
||||
|
||||
However, if FRAME_CHAIN_VALID returns zero,
|
||||
it means the given frame is the outermost one and has no caller.
|
||||
In that case, FRAME_CHAIN_COMBINE is not used. */
|
||||
|
||||
/* In the case of the Sun, the frame's nominal address
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 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)
|
||||
|
||||
/* Set VAL to the number of args passed to frame described by FI.
|
||||
Can set VAL to -1, meaning no way to tell. */
|
||||
|
||||
/* We can't tell how many args there are
|
||||
now that the C compiler delays popping them. */
|
||||
#define FRAME_NUM_ARGS(val,fi) (val = -1)
|
||||
|
||||
#if 0
|
||||
#define FRAME_NUM_ARGS(val, fi) \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.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
|
||||
|
||||
/* Put here the code to store, into a struct frame_saved_regs,
|
||||
the addresses of the saved registers of frame described by FRAME_INFO.
|
||||
This includes special registers such as pc and fp saved in special
|
||||
ways in the stack frame. sp is even more special:
|
||||
the address we return for it IS the sp for the next frame. */
|
||||
|
||||
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
|
||||
{ register int regnum; \
|
||||
register int regmask; \
|
||||
register CORE_ADDR next_addr; \
|
||||
register CORE_ADDR pc; \
|
||||
int nextinsn; \
|
||||
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
|
||||
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
|
||||
&& (frame_info).pc <= (frame_info).frame) \
|
||||
{ next_addr = (frame_info).frame; \
|
||||
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
|
||||
else \
|
||||
{ pc = get_pc_function_start ((frame_info).pc); \
|
||||
/* Verify we have a link a6 instruction next; \
|
||||
if not we lose. If we win, find the address above the saved \
|
||||
regs using the amount of storage from the link instruction. */\
|
||||
if (044016 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \
|
||||
else if (047126 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \
|
||||
else goto lose; \
|
||||
/* If have an addal #-n, sp next, adjust next_addr. */ \
|
||||
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
|
||||
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
|
||||
} \
|
||||
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
/* But before that can come an fmovem. Check for it. */ \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf227 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xe000) \
|
||||
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
if (0044327 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
|
||||
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
|
||||
else if (0044347 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
|
||||
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
|
||||
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
/* fmovemx to index of sp may follow. */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf236 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xf000) \
|
||||
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
|
||||
if (0x426742e7 == read_memory_integer (pc, 4)) \
|
||||
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
|
||||
lose: ; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
|
||||
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
|
||||
}
|
||||
|
||||
/* Things needed for making the inferior call functions. */
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
#define PUSH_DUMMY_FRAME \
|
||||
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
|
||||
register int regnum; \
|
||||
char raw_buffer[12]; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
|
||||
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
|
||||
sp = push_bytes (sp, raw_buffer, 12); } \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
sp = push_word (sp, read_register (regnum)); \
|
||||
sp = push_word (sp, read_register (PS_REGNUM)); \
|
||||
write_register (SP_REGNUM, sp); }
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
#define POP_FRAME \
|
||||
{ register 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)); }
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
fmovem 0xff,-(sp)
|
||||
moveml 0xfffc,-(sp)
|
||||
clrw -(sp)
|
||||
movew ccr,-(sp)
|
||||
/..* The arguments are pushed at this point by GDB;
|
||||
no code is needed in the dummy for this.
|
||||
The CALL_DUMMY_START_OFFSET gives the position of
|
||||
the following jsr instruction. *../
|
||||
jsr @#32323232
|
||||
addl #69696969,sp
|
||||
bpt
|
||||
nop
|
||||
Note this is 28 bytes.
|
||||
We actually start executing at the jsr, since the pushing of the
|
||||
registers is done by PUSH_DUMMY_FRAME. If this were real code,
|
||||
the arguments for the function called by the jsr would be pushed
|
||||
between the moveml and the jsr, and we could allow it to execute through.
|
||||
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
|
||||
and we cannot allow the moveml to push the registers again lest they be
|
||||
taken for the arguments. */
|
||||
|
||||
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71}
|
||||
|
||||
#define CALL_DUMMY_LENGTH 28
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 12
|
||||
|
||||
/* Insert the specified number of args and function address
|
||||
into a call sequence of the above form stored at DUMMYNAME. */
|
||||
|
||||
#define FIX_CALL_DUMMY(dummyname, 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 }
|
||||
|
||||
#ifndef HPUX_ASM
|
||||
|
||||
/* Start running with a stack stretching from BEG to END.
|
||||
BEG and END should be symbols meaningful to the assembler.
|
||||
This is used only for kdb. */
|
||||
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("movel $ end, sp"); \
|
||||
asm ("clrl fp"); }
|
||||
|
||||
/* Push the frame pointer register on the stack. */
|
||||
#define PUSH_FRAME_PTR \
|
||||
asm ("movel fp, -(sp)");
|
||||
|
||||
/* Copy the top-of-stack to the frame pointer register. */
|
||||
#define POP_FRAME_PTR \
|
||||
asm ("movl (sp), fp");
|
||||
|
||||
/* After KDB is entered by a fault, push all registers
|
||||
that GDB thinks about (all NUM_REGS of them),
|
||||
so that they appear in order of ascending GDB register number.
|
||||
The fault code will be on the stack beyond the last register. */
|
||||
|
||||
#define PUSH_REGISTERS \
|
||||
{ asm ("clrw -(sp)"); \
|
||||
asm ("pea 10(sp)"); \
|
||||
asm ("movem $ 0xfffe,-(sp)"); }
|
||||
|
||||
/* Assuming the registers (including processor status) have been
|
||||
pushed on the stack in order of ascending GDB register number,
|
||||
restore them and return to the address in the saved PC register. */
|
||||
|
||||
#define POP_REGISTERS \
|
||||
{ asm ("subil $8,28(sp)"); \
|
||||
asm ("movem (sp),$ 0xffff"); \
|
||||
asm ("rte"); }
|
||||
|
||||
#else /* HPUX_ASM */
|
||||
|
||||
/* Start running with a stack stretching from BEG to END.
|
||||
BEG and END should be symbols meaningful to the assembler.
|
||||
This is used only for kdb. */
|
||||
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm ("global end"); \
|
||||
asm ("mov.l &end,%sp"); \
|
||||
asm ("clr.l %a6"); }
|
||||
|
||||
/* Push the frame pointer register on the stack. */
|
||||
#define PUSH_FRAME_PTR \
|
||||
asm ("mov.l %fp,-(%sp)");
|
||||
|
||||
/* Copy the top-of-stack to the frame pointer register. */
|
||||
#define POP_FRAME_PTR \
|
||||
asm ("mov.l (%sp),%fp");
|
||||
|
||||
/* After KDB is entered by a fault, push all registers
|
||||
that GDB thinks about (all NUM_REGS of them),
|
||||
so that they appear in order of ascending GDB register number.
|
||||
The fault code will be on the stack beyond the last register. */
|
||||
|
||||
#define PUSH_REGISTERS \
|
||||
{ asm ("clr.w -(%sp)"); \
|
||||
asm ("pea 10(%sp)"); \
|
||||
asm ("movm.l &0xfffe,-(%sp)"); }
|
||||
|
||||
/* Assuming the registers (including processor status) have been
|
||||
pushed on the stack in order of ascending GDB register number,
|
||||
restore them and return to the address in the saved PC register. */
|
||||
|
||||
#define POP_REGISTERS \
|
||||
{ asm ("subi.l &8,28(%sp)"); \
|
||||
asm ("mov.m (%sp),&0xffff"); \
|
||||
asm ("rte"); }
|
||||
|
||||
#endif /* HPUX_ASM */
|
|
@ -0,0 +1,508 @@
|
|||
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configuration file for HP9000/300 series machine running
|
||||
* University of Utah's 4.3bsd port. This is NOT for HP-UX.
|
||||
* Problems to hpbsd-bugs@cs.utah.edu
|
||||
*/
|
||||
|
||||
#ifndef hp300
|
||||
#define hp300
|
||||
#endif
|
||||
|
||||
/* Watch out for NaNs */
|
||||
|
||||
#define IEEE_FLOAT
|
||||
|
||||
/* Get rid of any system-imposed stack limit if possible. */
|
||||
|
||||
#define SET_STACK_LIMIT_HUGE
|
||||
|
||||
/* Define this if the C compiler puts an underscore at the front
|
||||
of external names before giving them to the linker. */
|
||||
|
||||
#define NAMES_HAVE_UNDERSCORE
|
||||
|
||||
/* Debugger information will be in DBX format. */
|
||||
|
||||
#define READ_DBX_FORMAT
|
||||
|
||||
/* Offset from address of function to start of its code.
|
||||
Zero on most machines. */
|
||||
|
||||
#define FUNCTION_START_OFFSET 0
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. */
|
||||
|
||||
#define SKIP_PROLOGUE(pc) \
|
||||
{ register int op = read_memory_integer (pc, 2); \
|
||||
if (op == 0047126) \
|
||||
pc += 4; /* Skip link #word */ \
|
||||
else if (op == 0044016) \
|
||||
pc += 6; /* Skip link #long */ \
|
||||
}
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't go through the frames for this because on some machines
|
||||
the new frame is not set up until the new function executes
|
||||
some instructions. */
|
||||
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
read_memory_integer (read_register (SP_REGNUM), 4)
|
||||
|
||||
/* This is the amount to subtract from u.u_ar0
|
||||
to get the offset in the core file of the register values. */
|
||||
|
||||
#define KERNEL_U_ADDR 0x00917000
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR 0xFFF00000
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0x4e, 0x42}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 29
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
|
||||
#define REGISTER_NAMES \
|
||||
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
|
||||
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "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 */
|
||||
#define FPS_REGNUM 27 /* 68881 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+12)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) \
|
||||
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
|
||||
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
|
||||
: (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 12 bytes. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 8-byte doubles. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_RAW_SIZE 12
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
|
||||
|
||||
/* Convert data from raw format for register REGNUM
|
||||
to virtual format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_from_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_to_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
|
||||
|
||||
/* 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))
|
||||
|
||||
/* Compensate for lack of `vprintf' function. */
|
||||
#define vprintf(format, ap) _doprnt (format, ap, stdout)
|
||||
|
||||
/* This is a piece of magic that is given a register number REGNO
|
||||
and as BLOCKEND the address in the system of the end of the user structure
|
||||
and stores in ADDR the address in the kernel or core dump
|
||||
of that register. */
|
||||
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
{ \
|
||||
if (regno < PS_REGNUM) \
|
||||
addr = (int) &((struct frame *)(blockend))->f_regs[regno]; \
|
||||
else if (regno == PS_REGNUM) \
|
||||
addr = (int) &((struct frame *)(blockend))->f_stackadj; \
|
||||
else if (regno == PC_REGNUM) \
|
||||
addr = (int) &((struct frame *)(blockend))->f_pc; \
|
||||
else if (regno < FPC_REGNUM) \
|
||||
addr = (int) \
|
||||
&((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\
|
||||
else if (regno == FPC_REGNUM) \
|
||||
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr; \
|
||||
else if (regno == FPS_REGNUM) \
|
||||
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr; \
|
||||
else \
|
||||
addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar; \
|
||||
}
|
||||
|
||||
/* It is safe to look for symsegs on a Sun, because Sun's ld
|
||||
does not screw up with random garbage at end of file. */
|
||||
|
||||
#define READ_GDB_SYMSEGS
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
|
||||
/* FRAME_CHAIN takes a frame's nominal address
|
||||
and produces the frame's chain-pointer.
|
||||
|
||||
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
|
||||
and produces the nominal address of the caller frame.
|
||||
|
||||
However, if FRAME_CHAIN_VALID returns zero,
|
||||
it means the given frame is the outermost one and has no caller.
|
||||
In that case, FRAME_CHAIN_COMBINE is not used. */
|
||||
|
||||
/* In the case of the Sun, the frame's nominal address
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 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)
|
||||
|
||||
/* Set VAL to the number of args passed to frame described by FI.
|
||||
Can set VAL to -1, meaning no way to tell. */
|
||||
|
||||
/* We can't tell how many args there are
|
||||
now that the C compiler delays popping them. */
|
||||
#define FRAME_NUM_ARGS(val,fi) (val = -1)
|
||||
|
||||
#if 0
|
||||
#define FRAME_NUM_ARGS(val, fi) \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.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
|
||||
|
||||
/* Put here the code to store, into a struct frame_saved_regs,
|
||||
the addresses of the saved registers of frame described by FRAME_INFO.
|
||||
This includes special registers such as pc and fp saved in special
|
||||
ways in the stack frame. sp is even more special:
|
||||
the address we return for it IS the sp for the next frame. */
|
||||
|
||||
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
|
||||
{ register int regnum; \
|
||||
register int regmask; \
|
||||
register CORE_ADDR next_addr; \
|
||||
register CORE_ADDR pc; \
|
||||
int nextinsn; \
|
||||
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
|
||||
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
|
||||
&& (frame_info).pc <= (frame_info).frame) \
|
||||
{ next_addr = (frame_info).frame; \
|
||||
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
|
||||
else \
|
||||
{ pc = get_pc_function_start ((frame_info).pc); \
|
||||
/* Verify we have a link a6 instruction next; \
|
||||
if not we lose. If we win, find the address above the saved \
|
||||
regs using the amount of storage from the link instruction. */\
|
||||
if (044016 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \
|
||||
else if (047126 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \
|
||||
else goto lose; \
|
||||
/* If have an addal #-n, sp next, adjust next_addr. */ \
|
||||
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
|
||||
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
|
||||
} \
|
||||
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
/* But before that can come an fmovem. Check for it. */ \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf227 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xe000) \
|
||||
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
if (0044327 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
|
||||
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
|
||||
else if (0044347 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
|
||||
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
|
||||
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
/* fmovemx to index of sp may follow. */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf236 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xf000) \
|
||||
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
|
||||
if (0x426742e7 == read_memory_integer (pc, 4)) \
|
||||
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
|
||||
lose: ; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
|
||||
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
|
||||
}
|
||||
|
||||
/* Things needed for making the inferior call functions. */
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
#define PUSH_DUMMY_FRAME \
|
||||
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
|
||||
register int regnum; \
|
||||
char raw_buffer[12]; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
|
||||
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
|
||||
sp = push_bytes (sp, raw_buffer, 12); } \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
sp = push_word (sp, read_register (regnum)); \
|
||||
sp = push_word (sp, read_register (PS_REGNUM)); \
|
||||
write_register (SP_REGNUM, sp); }
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
#define POP_FRAME \
|
||||
{ register 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)); }
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
fmovem 0xff,-(sp)
|
||||
moveml 0xfffc,-(sp)
|
||||
clrw -(sp)
|
||||
movew ccr,-(sp)
|
||||
/..* The arguments are pushed at this point by GDB;
|
||||
no code is needed in the dummy for this.
|
||||
The CALL_DUMMY_START_OFFSET gives the position of
|
||||
the following jsr instruction. *../
|
||||
jsr @#32323232
|
||||
addl #69696969,sp
|
||||
trap #2
|
||||
nop
|
||||
Note this is 28 bytes.
|
||||
We actually start executing at the jsr, since the pushing of the
|
||||
registers is done by PUSH_DUMMY_FRAME. If this were real code,
|
||||
the arguments for the function called by the jsr would be pushed
|
||||
between the moveml and the jsr, and we could allow it to execute through.
|
||||
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
|
||||
and we cannot allow the moveml to push the registers again lest they be
|
||||
taken for the arguments. */
|
||||
|
||||
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e424e71}
|
||||
|
||||
#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 ("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"); }
|
|
@ -137,7 +137,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
|
@ -175,8 +175,14 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
#define FP0_REGNUM 18 /* Floating point register 0 */
|
||||
#define FPC_REGNUM 26 /* 68881 control register */
|
||||
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
{ if (regno < 2) addr = blockend - 0x18 + regno * 4; \
|
||||
#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;\
|
||||
|
@ -392,6 +398,9 @@ retry: \
|
|||
(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. */
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/* Customize initialize.h for Integrated Solutions machines. */
|
||||
|
||||
/* Define this if you are using system version 4; undefine it for
|
||||
version 3. This alters the action of m-isi-ov.h as well as this file. */
|
||||
#define BSD43_ISI40D
|
||||
|
||||
#ifdef BSD43_ISI40D
|
||||
#define FILEADDR_ROUND(addr) (addr)
|
||||
#else
|
||||
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
|
||||
#endif
|
|
@ -0,0 +1,440 @@
|
|||
/* Definitions to make GDB run on a merlin under utek 2.1
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#ifndef ns16000
|
||||
#define ns16000
|
||||
#endif
|
||||
|
||||
# include <machine/reg.h>
|
||||
|
||||
/* 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, 1); \
|
||||
if (op == 0x82) \
|
||||
{ op = read_memory_integer (pc+2,1); \
|
||||
if ((op & 0x80) == 0) pc += 3; \
|
||||
else if ((op & 0xc0) == 0x80) pc += 4; \
|
||||
else pc += 6; \
|
||||
}}
|
||||
|
||||
/* 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 (0xfef000)
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR (0x800000)
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0xf2}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, len) 0
|
||||
|
||||
/* Define this to say that the "svc" insn is followed by
|
||||
codes in memory saying which kind of system call it is. */
|
||||
|
||||
#define NS32K_SVC_IMMED_OPERANDS
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 25
|
||||
|
||||
#define NUM_GENERAL_REGS 8
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
|
||||
#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"pc", "sp", "fp", "ps", \
|
||||
"fsr", \
|
||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
|
||||
"l0", "l1", "l2", "l3", "l4", \
|
||||
}
|
||||
|
||||
/* 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 AP_REGNUM FP_REGNUM
|
||||
#define FP_REGNUM 10 /* Contains address of executing stack frame */
|
||||
#define SP_REGNUM 9 /* Contains address of top of stack */
|
||||
#define PC_REGNUM 8 /* Contains program counter */
|
||||
#define PS_REGNUM 11 /* Contains processor status */
|
||||
#define FPS_REGNUM 12 /* Floating point status register */
|
||||
#define FP0_REGNUM 13 /* Floating point register 0 */
|
||||
#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
|
||||
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
{ \
|
||||
switch (regno) { \
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
|
||||
addr = blockend + (R0 - regno) * sizeof (int); break; \
|
||||
case PC_REGNUM: \
|
||||
addr = blockend + PC * sizeof (int); break; \
|
||||
case SP_REGNUM: \
|
||||
addr = blockend + SP * sizeof (int); break; \
|
||||
case FP_REGNUM: \
|
||||
addr = blockend + FP * sizeof (int); break; \
|
||||
case PS_REGNUM: \
|
||||
addr = blockend + 12 * sizeof (int); break; \
|
||||
case FPS_REGNUM: \
|
||||
addr = 108; break; \
|
||||
case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
|
||||
case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
|
||||
case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
|
||||
case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
|
||||
addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break; \
|
||||
case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
|
||||
case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
|
||||
addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break; \
|
||||
default: \
|
||||
printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
|
||||
abort (); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
|
||||
LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the 32000, all regs are 4 bytes
|
||||
except for the doubled floating registers. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the 32000, all regs are 4 bytes
|
||||
except for the doubled floating registers. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 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), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
((N) >= FP0_REGNUM ? \
|
||||
((N) >= LP0_REGNUM ? \
|
||||
builtin_type_double \
|
||||
: 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))
|
||||
|
||||
/* 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 Merlin, the frame's nominal address is the FP value,
|
||||
and at that address is saved previous FP value as a 4-byte word. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_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))
|
||||
|
||||
/* compute base of arguments */
|
||||
#define FRAME_ARGS_ADDRESS(fi) ((fi).frame)
|
||||
|
||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
|
||||
|
||||
/* Return number of args passed to a frame.
|
||||
Can return -1, meaning no way to tell. */
|
||||
|
||||
#define FRAME_NUM_ARGS(numargs, fi) \
|
||||
{ CORE_ADDR pc; \
|
||||
int insn; \
|
||||
int addr_mode; \
|
||||
int width; \
|
||||
\
|
||||
pc = FRAME_SAVED_PC (fi.frame); \
|
||||
insn = read_memory_integer (pc,2); \
|
||||
addr_mode = (insn >> 11) & 0x1f; \
|
||||
insn = insn & 0x7ff; \
|
||||
if ((insn & 0x7fc) == 0x57c \
|
||||
&& addr_mode == 0x14) /* immediate */ \
|
||||
{ if (insn == 0x57c) /* adjspb */ \
|
||||
width = 1; \
|
||||
else if (insn == 0x57d) /* adjspw */ \
|
||||
width = 2; \
|
||||
else if (insn == 0x57f) /* adjspd */ \
|
||||
width = 4; \
|
||||
numargs = read_memory_integer (pc+2,width); \
|
||||
if (width > 1) \
|
||||
flip_bytes (&numargs, width); \
|
||||
numargs = - sign_extend (numargs, width*8) / 4; } \
|
||||
else numargs = -1; \
|
||||
}
|
||||
|
||||
/* 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) \
|
||||
{ int regmask,regnum; \
|
||||
int localcount; \
|
||||
CORE_ADDR enter_addr; \
|
||||
CORE_ADDR next_addr; \
|
||||
\
|
||||
enter_addr = get_pc_function_start ((frame_info).pc); \
|
||||
regmask = read_memory_integer (enter_addr+1, 1); \
|
||||
localcount = ns32k_localcount (enter_addr); \
|
||||
next_addr = (frame_info).frame + localcount; \
|
||||
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
|
||||
(frame_saved_regs).regs[regnum] \
|
||||
= (regmask & 1) ? (next_addr -= 4) : 0; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
|
||||
(frame_saved_regs).regs[FP_REGNUM] \
|
||||
= read_memory_integer ((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; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = 0; regnum < 8; regnum++) \
|
||||
sp = push_word (sp, read_register (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; \
|
||||
fi = get_frame_info (fp); \
|
||||
get_frame_saved_regs (&fi, &fsr); \
|
||||
for (regnum = 0; regnum < 8; regnum++) \
|
||||
if (fsr.regs[regnum]) \
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
|
||||
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
|
||||
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
|
||||
write_register (SP_REGNUM, fp + 8); \
|
||||
}
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
enter 0xff,0 82 ff 00
|
||||
jsr @0x00010203 7f ae c0 01 02 03
|
||||
adjspd 0x69696969 7f a5 01 02 03 04
|
||||
bpt f2
|
||||
Note this is 16 bytes. */
|
||||
|
||||
#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 3
|
||||
#define CALL_DUMMY_LENGTH 16
|
||||
#define CALL_DUMMY_ADDR 5
|
||||
#define CALL_DUMMY_NARGS 11
|
||||
|
||||
/* 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 flipped = fun | 0xc0000000; \
|
||||
flip_bytes (&flipped, 4); \
|
||||
*((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
|
||||
flipped = - nargs * 4; \
|
||||
flip_bytes (&flipped, 4); \
|
||||
*((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
/* Interface definitions for kernel debugger KDB. */
|
||||
|
||||
/* Map machine fault codes into signal numbers.
|
||||
First subtract 0, divide by 4, then index in a table.
|
||||
Faults for which the entry in this table is 0
|
||||
are not handled by KDB; the program's own trap handler
|
||||
gets to handle then. */
|
||||
|
||||
#define FAULT_CODE_ORIGIN 0
|
||||
#define FAULT_CODE_UNITS 4
|
||||
#define FAULT_TABLE \
|
||||
{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
|
||||
0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0}
|
||||
|
||||
/* Start running with a stack stretching from BEG to END.
|
||||
BEG and END should be symbols meaningful to the assembler.
|
||||
This is used only for kdb. */
|
||||
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("movl $ end, sp"); \
|
||||
asm ("clrl fp"); }
|
||||
|
||||
/* Push the frame pointer register on the stack. */
|
||||
#define PUSH_FRAME_PTR \
|
||||
asm ("pushl fp");
|
||||
|
||||
/* Copy the top-of-stack to the frame pointer register. */
|
||||
#define POP_FRAME_PTR \
|
||||
asm ("movl (sp), fp");
|
||||
|
||||
/* After KDB is entered by a fault, push all registers
|
||||
that GDB thinks about (all NUM_REGS of them),
|
||||
so that they appear in order of ascending GDB register number.
|
||||
The fault code will be on the stack beyond the last register. */
|
||||
|
||||
#define PUSH_REGISTERS \
|
||||
{ asm ("pushl 8(sp)"); \
|
||||
asm ("pushl 8(sp)"); \
|
||||
asm ("pushal 0x14(sp)"); \
|
||||
asm ("pushr $037777"); }
|
||||
|
||||
/* 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 ("popr $037777"); \
|
||||
asm ("subl2 $8,(sp)"); \
|
||||
asm ("movl (sp),sp"); \
|
||||
asm ("rei"); }
|
||||
#endif
|
|
@ -0,0 +1,534 @@
|
|||
/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
|
||||
|
||||
Here is an m-news800.h file for gdb version 2.1. It supports the reading
|
||||
the 68881 registers, but the kernel doesn't know how to write them
|
||||
and probably cannot write the frame pointer register either.
|
||||
|
||||
Now(9/2 '87) NEWS's printf has a bug.
|
||||
And support Sun assembly format instead of Motorola one.
|
||||
Probably not well support floating registers from core file rarely that
|
||||
I do not know detail.
|
||||
(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs%seismo.CSS.GOV)
|
||||
|
||||
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 news800
|
||||
#define news800
|
||||
#endif
|
||||
|
||||
#define USE_GAS
|
||||
|
||||
/* Motorola assembly format */
|
||||
#ifndef USE_GAS
|
||||
#define MOTOROLA
|
||||
#endif
|
||||
|
||||
/* bug when printf special number; NAN */
|
||||
#define PRINTF_BUG
|
||||
|
||||
/* Define this if the C compiler puts an underscore at the front
|
||||
of external names before giving them to the linker. */
|
||||
|
||||
#define NAMES_HAVE_UNDERSCORE
|
||||
|
||||
/* Debugger info will be in DBX format. */
|
||||
|
||||
#define READ_DBX_FORMAT
|
||||
|
||||
/* Offset from address of function to start of its code.
|
||||
Zero on most machines. */
|
||||
|
||||
#define FUNCTION_START_OFFSET 0
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. */
|
||||
|
||||
#define SKIP_PROLOGUE(pc) \
|
||||
{ register int op = read_memory_integer (pc, 2); \
|
||||
if (op == 0047126) \
|
||||
pc += 4; /* Skip link #word */ \
|
||||
else if (op == 0044016) \
|
||||
pc += 6; /* Skip link #long */ \
|
||||
}
|
||||
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't 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 UADDR
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR (0x80000000 - ctob(UPAGES + 1))
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0x4e, 0x4f}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
|
||||
|
||||
/* 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", \
|
||||
"pc", "ps", \
|
||||
"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 PC_REGNUM 16 /* Contains program counter */
|
||||
#define PS_REGNUM 17 /* Contains processor status */
|
||||
#define FP0_REGNUM 18 /* Floating point register 0 */
|
||||
#define FPC_REGNUM 26 /* 68881 control register */
|
||||
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
{ if (regno <= FP_REGNUM) \
|
||||
addr = blockend + 4 + regno * 4; \
|
||||
else if (regno == SP_REGNUM) \
|
||||
addr = blockend - 4 * 4; \
|
||||
else if (regno <= PS_REGNUM) \
|
||||
addr = blockend + (regno - PS_REGNUM) * 4; \
|
||||
else if (regno < FPC_REGNUM) \
|
||||
addr = blockend + 4 + 4 * 14 + 4 * 5 + (regno - FP0_REGNUM) * 12; \
|
||||
else \
|
||||
addr = blockend + 4 + 4 * 16 + (regno - FPC_REGNUM) * 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+12)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) \
|
||||
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
|
||||
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
|
||||
: (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 12 bytes. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the 68000, all regs are 4 bytes
|
||||
except the floating point regs which are 8-byte doubles. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_RAW_SIZE 12
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
|
||||
|
||||
/* Convert data from raw format for register REGNUM
|
||||
to virtual format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_from_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
|
||||
convert_to_68881 ((FROM), (TO)); \
|
||||
else \
|
||||
bcopy ((FROM), (TO), 4); }
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
|
||||
|
||||
/* Extract from an array REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
{ if (TYPE_CODE (TYPE) != TYPE_CODE_FLT) \
|
||||
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); \
|
||||
else \
|
||||
convert_from_68881 (REGBUF + REGISTER_BYTE (FP0_REGNUM), VALBUF); }
|
||||
|
||||
/* Write into appropriate registers a function return value
|
||||
of type TYPE, given in virtual format. */
|
||||
|
||||
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
|
||||
{ if (TYPE_CODE (TYPE) != TYPE_CODE_FLT) \
|
||||
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); \
|
||||
else \
|
||||
{ \
|
||||
char raw_buffer[12]; \
|
||||
convert_to_68881 (VALBUF, raw_buffer); \
|
||||
write_register_bytes (REGISTER_BYTE(FP0_REGNUM), raw_buffer, 12); }}
|
||||
|
||||
/* 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))
|
||||
|
||||
/* Compensate for lack of `vprintf' function. */
|
||||
#define vprintf(format, ap) _doprnt (format, ap, stdout)
|
||||
|
||||
/* 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 NEWS, the frame's nominal address
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_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; \
|
||||
}
|
||||
|
||||
/* 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
|
||||
fmove.m #<f0-f7>,-(sp)
|
||||
movem.l 0xfffc,-(sp)
|
||||
clr.w -(sp)
|
||||
move.w 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. *../
|
||||
jbsr (#32323232)
|
||||
add.l #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. */
|
||||
|
||||
#ifdef MOTOROLA
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("move.l $ end, sp"); \
|
||||
asm ("clr.l fp"); }
|
||||
#else
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("movel $ end, sp"); \
|
||||
asm ("clrl fp"); }
|
||||
#endif
|
||||
|
||||
/* Push the frame pointer register on the stack. */
|
||||
#ifdef MOTOROLA
|
||||
#define PUSH_FRAME_PTR \
|
||||
asm ("move.l fp, -(sp)");
|
||||
#else
|
||||
#define PUSH_FRAME_PTR \
|
||||
asm ("movel fp, -(sp)");
|
||||
#endif
|
||||
|
||||
/* Copy the top-of-stack to the frame pointer register. */
|
||||
#ifdef MOTOROLA
|
||||
#define POP_FRAME_PTR \
|
||||
asm ("move.l (sp), fp");
|
||||
#else
|
||||
#define POP_FRAME_PTR \
|
||||
asm ("movl (sp), fp");
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef MOTOROLA
|
||||
#define PUSH_REGISTERS \
|
||||
{ asm ("clr.w -(sp)"); \
|
||||
asm ("pea (10,sp)"); \
|
||||
asm ("movem $ 0xfffe,-(sp)"); }
|
||||
#else
|
||||
#define PUSH_REGISTERS \
|
||||
{ asm ("clrw -(sp)"); \
|
||||
asm ("pea 10(sp)"); \
|
||||
asm ("movem $ 0xfffe,-(sp)"); }
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef MOTOROLA
|
||||
#define POP_REGISTERS \
|
||||
{ asm ("subi.l $8,28(sp)"); \
|
||||
asm ("movem (sp),$ 0xffff"); \
|
||||
asm ("rte"); }
|
||||
#else
|
||||
#define POP_REGISTERS \
|
||||
{ asm ("subil $8,28(sp)"); \
|
||||
asm ("movem (sp),$ 0xffff"); \
|
||||
asm ("rte"); }
|
||||
#endif
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/* This is how the size of an individual .o file's text segment
|
||||
is rounded on a SONY NEWS. */
|
||||
|
||||
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
|
|
@ -0,0 +1,502 @@
|
|||
/* Parameters for execution on a Gould NP1, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding! */
|
||||
|
||||
/* Read file headers properly in core.c */
|
||||
#define gould
|
||||
|
||||
/* Macro for text-offset and data info (in NPL a.out format). */
|
||||
#define TEXTINFO \
|
||||
text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); \
|
||||
exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)\
|
||||
+ exec_aouthdr.a_text
|
||||
|
||||
/* Macro for number of symbol table entries */
|
||||
#define END_OF_TEXT_DEFAULT \
|
||||
(0xffffff)
|
||||
|
||||
/* Macro for number of symbol table entries */
|
||||
#define NUMBER_OF_SYMBOLS \
|
||||
(coffhdr.f_nsyms)
|
||||
|
||||
/* Macro for file-offset of symbol table (in NPL a.out format). */
|
||||
#define SYMBOL_TABLE_OFFSET \
|
||||
N_SYMOFF (coffhdr)
|
||||
|
||||
/* Macro for file-offset of string table (in NPL a.out format). */
|
||||
#define STRING_TABLE_OFFSET \
|
||||
(N_STROFF (coffhdr) + sizeof(int))
|
||||
|
||||
/* Macro to store the length of the string table data in INTO. */
|
||||
#define READ_STRING_TABLE_SIZE(INTO) \
|
||||
{ INTO = hdr.a_stsize; }
|
||||
|
||||
/* Macro to declare variables to hold the file's header data. */
|
||||
#define DECLARE_FILE_HEADERS struct exec hdr; \
|
||||
FILHDR coffhdr
|
||||
|
||||
/* Macro to read the header data from descriptor DESC and validate it.
|
||||
NAME is the file name, for error messages. */
|
||||
#define READ_FILE_HEADERS(DESC, NAME) \
|
||||
{ val = myread (DESC, &coffhdr, sizeof coffhdr); \
|
||||
if (val < 0) \
|
||||
perror_with_name (NAME); \
|
||||
val = myread (DESC, &hdr, sizeof hdr); \
|
||||
if (val < 0) \
|
||||
perror_with_name (NAME); \
|
||||
if (coffhdr.f_magic != GNP1MAGIC) \
|
||||
error ("File \"%s\" not in coff executable format.", NAME); \
|
||||
if (N_BADMAG (hdr)) \
|
||||
error ("File \"%s\" not in executable format.", NAME); }
|
||||
|
||||
/* Define COFF and other symbolic names needed on NP1 */
|
||||
#define NS32GMAGIC GNP1MAGIC
|
||||
#define NS32SMAGIC GPNMAGIC
|
||||
#define vprintf printf
|
||||
|
||||
/* 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 8
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. One NPL we can have one two startup
|
||||
sequences depending on the size of the local stack:
|
||||
|
||||
Either:
|
||||
"suabr b2, #"
|
||||
of
|
||||
"lil r4, #", "suabr b2, #(r4)"
|
||||
|
||||
"lwbr b6, #", "stw r1, 8(b2)"
|
||||
Optional "stwbr b3, c(b2)"
|
||||
Optional "trr r2,r7" (Gould first argument register passing)
|
||||
or
|
||||
Optional "stw r2,8(b3)" (Gould first argument register passing)
|
||||
*/
|
||||
#define SKIP_PROLOGUE(pc) { \
|
||||
register int op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0xFA0B0000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x59400000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x5F000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xD4820008) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0x5582000C) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xd5030008) { \
|
||||
pc += 4; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if ((op & 0xffff0000) == 0x59000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x5F000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xD4820008) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0x5582000C) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xd5030008) { \
|
||||
pc += 4; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 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. True on NPL! Return address is in R1.
|
||||
The true return address is REALLY 4 past that location! */
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
(read_register(R1_REGNUM) + 4)
|
||||
|
||||
/* Address of U in kernel space */
|
||||
#define KERNEL_U_ADDR 0x7fffc000
|
||||
|
||||
/* Address of end of stack space. */
|
||||
#define STACK_END_ADDR 0x7fffc000
|
||||
|
||||
/* Stack grows downward. */
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
#define BREAKPOINT {0x28, 0x09}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0x40100004)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Size of bytes of vector register (NP1 only), 32 elements * sizeof(int) */
|
||||
#define VR_SIZE 128
|
||||
|
||||
/* Number of machine registers */
|
||||
#define NUM_REGS 27
|
||||
#define NUM_GEN_REGS 16
|
||||
#define NUM_CPU_REGS 4
|
||||
#define NUM_VECTOR_REGS 7
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
#define REGISTER_NAMES { \
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
|
||||
"sp", "ps", "pc", "ve", \
|
||||
"v1", "v2", "v3", "v4", "v5", "v6", "v7", \
|
||||
}
|
||||
|
||||
/* 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 R1_REGNUM 1 /* Gr1 => return address of caller */
|
||||
#define R4_REGNUM 4 /* Gr4 => register save area */
|
||||
#define R5_REGNUM 5 /* Gr5 => register save area */
|
||||
#define R6_REGNUM 6 /* Gr6 => register save area */
|
||||
#define R7_REGNUM 7 /* Gr7 => register save area */
|
||||
#define B1_REGNUM 9 /* Br1 => start of this code routine */
|
||||
#define FP_REGNUM 10 /* Br2 == (sp) */
|
||||
#define AP_REGNUM 11 /* Br3 == (ap) */
|
||||
#define SP_REGNUM 16 /* A copy of Br2 saved in trap */
|
||||
#define PS_REGNUM 17 /* Contains processor status */
|
||||
#define PC_REGNUM 18 /* Contains program counter */
|
||||
#define VE_REGNUM 19 /* Vector end (user setup) register */
|
||||
#define V1_REGNUM 20 /* First vector register */
|
||||
#define V7_REGNUM 27 /* First vector register */
|
||||
|
||||
/* This is a piece of magic that is given a register number REGNO
|
||||
and as BLOCKEND the address in the system of the end of the user structure
|
||||
and stores in ADDR the address in the kernel or core dump
|
||||
of that register. */
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) { \
|
||||
addr = blockend + regno * 4; \
|
||||
if (regno == VE_REGNUM) addr = blockend - 9 * 4; \
|
||||
if (regno == PC_REGNUM) addr = blockend - 8 * 4; \
|
||||
if (regno == PS_REGNUM) addr = blockend - 7 * 4; \
|
||||
if (regno == SP_REGNUM) addr = blockend - 6 * 4; \
|
||||
if (regno >= V1_REGNUM) \
|
||||
addr = blockend + 16 * 4 + (regno - V1_REGNUM) * VR_SIZE; \
|
||||
}
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES \
|
||||
(NUM_GEN_REGS*4 + NUM_VECTOR_REGS*VR_SIZE + NUM_CPU_REGS*4)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
#define REGISTER_BYTE(N) \
|
||||
(((N) < V1_REGNUM) ? ((N) * 4) : (((N) - V1_REGNUM) * VR_SIZE) + 80)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the NP1, all normal regs are 4 bytes, but
|
||||
the vector registers are VR_SIZE*4 bytes long. */
|
||||
#define REGISTER_RAW_SIZE(N) \
|
||||
(((N) < V1_REGNUM) ? 4 : VR_SIZE)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the NP1, all regs are 4 bytes. */
|
||||
#define REGISTER_VIRTUAL_SIZE(N) \
|
||||
(((N) < V1_REGNUM) ? 4 : VR_SIZE)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
#define MAX_REGISTER_RAW_SIZE VR_SIZE
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE VR_SIZE
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
#define REGISTER_CONVERTIBLE(N) (0)
|
||||
|
||||
/* Convert data from raw format for register REGNUM
|
||||
to virtual format for register REGNUM. */
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
|
||||
|
||||
/* Extract from an arrary REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#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 NPL, the frame's norminal address is Br2 and the
|
||||
previous routines frame is up the stack X bytes, where X is the
|
||||
value stored in the code function header xA(Br1). */
|
||||
#define FRAME_CHAIN(thisframe) (findframe(thisframe))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && chain != thisframe)
|
||||
|
||||
#define FRAME_CHAIN_COMBINE(chain, thisframe) \
|
||||
(chain)
|
||||
|
||||
/* Define other aspects of the stack frame on NPL. */
|
||||
#define FRAME_SAVED_PC(frame) \
|
||||
(read_memory_integer (frame + 8, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
((fi).next_frame ? \
|
||||
read_memory_integer ((fi).frame + 12, 4) : \
|
||||
read_register (AP_REGNUM))
|
||||
|
||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame + 80)
|
||||
|
||||
/* Set VAL to the number of args passed to frame described by FI.
|
||||
Can set VAL to -1, meaning no way to tell. */
|
||||
|
||||
/* We can check the stab info to see how
|
||||
many arg we have. No info in stack will tell us */
|
||||
#define FRAME_NUM_ARGS(val,fi) (val = findarg(fi))
|
||||
|
||||
/* 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) \
|
||||
{ \
|
||||
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 8; \
|
||||
(frame_saved_regs).regs[R4_REGNUM] = (frame_info).frame + 0x30; \
|
||||
(frame_saved_regs).regs[R5_REGNUM] = (frame_info).frame + 0x34; \
|
||||
(frame_saved_regs).regs[R6_REGNUM] = (frame_info).frame + 0x38; \
|
||||
(frame_saved_regs).regs[R7_REGNUM] = (frame_info).frame + 0x3C; \
|
||||
}
|
||||
|
||||
/* 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; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
sp = push_word (sp, read_register (regnum)); \
|
||||
sp = push_word (sp, read_register (PS_REGNUM)); \
|
||||
write_register (SP_REGNUM, sp); }
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all 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; \
|
||||
fi = get_frame_info (fp); \
|
||||
get_frame_saved_regs (&fi, &fsr); \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
if (fsr.regs[regnum]) \
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
|
||||
if (fsr.regs[PS_REGNUM]) \
|
||||
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
|
||||
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
|
||||
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
|
||||
write_register (SP_REGNUM, fp + 8); \
|
||||
set_current_frame (read_register (FP_REGNUM)); }
|
||||
|
||||
/* This sequence of words is the instructions:
|
||||
halt
|
||||
halt
|
||||
halt
|
||||
halt
|
||||
suabr b2, #<stacksize>
|
||||
lwbr b6, #con
|
||||
stw r1, 8(b2) - save caller address, do we care?
|
||||
lw r2, 60(b2) - arg1
|
||||
labr b3, 50(b2)
|
||||
std r4, 30(b2) - save r4-r7
|
||||
std r6, 38(b2)
|
||||
lwbr b1, #<func> - load function call address
|
||||
brlnk r1, 8(b1) - call function
|
||||
halt
|
||||
halt
|
||||
ld r4, 30(b2) - restore r4-r7
|
||||
ld r6, 38(b2)
|
||||
|
||||
Setup our stack frame, load argumemts, call and then restore registers.
|
||||
*/
|
||||
|
||||
#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; }
|
||||
|
||||
/*
|
||||
* No KDB support, Yet! */
|
||||
/* Interface definitions for kernel debugger KDB. */
|
||||
|
||||
/* Map machine fault codes into signal numbers.
|
||||
First subtract 0, divide by 4, then index in a table.
|
||||
Faults for which the entry in this table is 0
|
||||
are not handled by KDB; the program's own trap handler
|
||||
gets to handle then. */
|
||||
|
||||
#define FAULT_CODE_ORIGIN 0
|
||||
#define FAULT_CODE_UNITS 4
|
||||
#define FAULT_TABLE \
|
||||
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
|
||||
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
SIGILL }
|
||||
|
||||
/* Start running with a stack stretching from BEG to END.
|
||||
BEG and END should be symbols meaningful to the assembler.
|
||||
This is used only for kdb. */
|
||||
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("movel $ end, sp"); \
|
||||
asm ("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"); }
|
|
@ -0,0 +1,4 @@
|
|||
/* This is how the size of an individual .o file's text segment
|
||||
is rounded on a NP1. See np1-pinsn.c for rounding function. */
|
||||
|
||||
#define FILEADDR_ROUND(addr) (((int)(addr) + 31) & ~0xf)
|
|
@ -0,0 +1,486 @@
|
|||
/* Parameters for execution on a Gould PN, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding! */
|
||||
|
||||
/* Read file headers properly in core.c */
|
||||
#define gould
|
||||
|
||||
/* Macro for text-offset and data info (in PN a.out format). */
|
||||
#define TEXTINFO \
|
||||
text_offset = N_TXTOFF (exec_coffhdr); \
|
||||
exec_data_offset = N_TXTOFF (exec_coffhdr) \
|
||||
+ exec_aouthdr.a_text
|
||||
|
||||
/* Macro for number of symbol table entries */
|
||||
#define END_OF_TEXT_DEFAULT \
|
||||
(0xffffff)
|
||||
|
||||
/* Macro for number of symbol table entries */
|
||||
#define NUMBER_OF_SYMBOLS \
|
||||
(coffhdr.f_nsyms)
|
||||
|
||||
/* Macro for file-offset of symbol table (in usual a.out format). */
|
||||
#define SYMBOL_TABLE_OFFSET \
|
||||
N_SYMOFF (coffhdr)
|
||||
|
||||
/* Macro for file-offset of string table (in usual a.out format). */
|
||||
#define STRING_TABLE_OFFSET \
|
||||
(N_STROFF (coffhdr) + sizeof(int))
|
||||
|
||||
/* Macro to store the length of the string table data in INTO. */
|
||||
#define READ_STRING_TABLE_SIZE(INTO) \
|
||||
{ INTO = hdr.a_stsize; }
|
||||
|
||||
/* Macro to declare variables to hold the file's header data. */
|
||||
#define DECLARE_FILE_HEADERS struct old_exec hdr; \
|
||||
FILHDR coffhdr
|
||||
|
||||
/* Macro to read the header data from descriptor DESC and validate it.
|
||||
NAME is the file name, for error messages. */
|
||||
#define READ_FILE_HEADERS(DESC, NAME) \
|
||||
{ val = myread (DESC, &coffhdr, sizeof coffhdr); \
|
||||
if (val < 0) \
|
||||
perror_with_name (NAME); \
|
||||
val = myread (DESC, &hdr, sizeof hdr); \
|
||||
if (val < 0) \
|
||||
perror_with_name (NAME); \
|
||||
if (coffhdr.f_magic != GNP1MAGIC) \
|
||||
error ("File \"%s\" not in coff executable format.", NAME); \
|
||||
if (N_BADMAG (hdr)) \
|
||||
error ("File \"%s\" not in executable format.", NAME); }
|
||||
|
||||
/* Define COFF and other symbolic names needed on NP1 */
|
||||
#define NS32GMAGIC GDPMAGIC
|
||||
#define NS32SMAGIC PN_MAGIC
|
||||
#define vprintf printf
|
||||
|
||||
/* 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 4
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. One PN we can have one or two startup
|
||||
sequences depending on the size of the local stack:
|
||||
|
||||
Either:
|
||||
"suabr b2, #"
|
||||
of
|
||||
"lil r4, #", "suabr b2, #(r4)"
|
||||
|
||||
"lwbr b6, #", "stw r1, 8(b2)"
|
||||
Optional "stwbr b3, c(b2)"
|
||||
Optional "trr r2,r7" (Gould first argument register passing)
|
||||
or
|
||||
Optional "stw r2,8(b3)" (Gould first argument register passing)
|
||||
*/
|
||||
#define SKIP_PROLOGUE(pc) { \
|
||||
register int op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x580B0000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x59400000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x5F000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xD4820008) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0x5582000C) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xd5030008) { \
|
||||
pc += 4; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if ((op & 0xffff0000) == 0x59000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if ((op & 0xffff0000) == 0x5F000000) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xD4820008) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0x5582000C) { \
|
||||
pc += 4; \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 4); \
|
||||
if (op == 0xd5030008) { \
|
||||
pc += 4; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
op = read_memory_integer ((pc), 2); \
|
||||
if (op == 0x2fa0) { \
|
||||
pc += 2; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 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. True on PN! Return address is in R1.
|
||||
Note: true return location is 4 bytes past R1! */
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
(read_register(R1_REGNUM) + 4)
|
||||
|
||||
/* Address of U in kernel space */
|
||||
#define KERNEL_U_ADDR 0x3fc000
|
||||
|
||||
/* Address of end of stack space. */
|
||||
#define STACK_END_ADDR 0x480000
|
||||
|
||||
/* Stack grows downward. */
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
#define BREAKPOINT {0x28, 0x09}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0xEC100004)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
#define NUM_REGS 19
|
||||
#define NUM_GEN_REGS 16
|
||||
#define NUM_CPU_REGS 3
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
#define REGISTER_NAMES { \
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
|
||||
"sp", "ps", "pc", \
|
||||
}
|
||||
|
||||
/* 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 R1_REGNUM 1 /* Gr1 => return address of caller */
|
||||
#define R4_REGNUM 4 /* Gr4 => register save area */
|
||||
#define R5_REGNUM 5 /* Gr5 => register save area */
|
||||
#define R6_REGNUM 6 /* Gr6 => register save area */
|
||||
#define R7_REGNUM 7 /* Gr7 => register save area */
|
||||
#define B1_REGNUM 9 /* Br1 => start of this code routine */
|
||||
#define FP_REGNUM 10 /* Br2 == (sp) */
|
||||
#define AP_REGNUM 11 /* Br3 == (ap) */
|
||||
#define SP_REGNUM 16 /* A copy of Br2 saved in trap */
|
||||
#define PS_REGNUM 17 /* Contains processor status */
|
||||
#define PC_REGNUM 18 /* Contains program counter */
|
||||
|
||||
/* This is a piece of magic that is given a register number REGNO
|
||||
and as BLOCKEND the address in the system of the end of the user structure
|
||||
and stores in ADDR the address in the kernel or core dump
|
||||
of that register. */
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) { \
|
||||
addr = blockend + regno * 4; \
|
||||
if (regno == PC_REGNUM) addr = blockend - 8 * 4; \
|
||||
if (regno == PS_REGNUM) addr = blockend - 7 * 4; \
|
||||
if (regno == SP_REGNUM) addr = blockend - 6 * 4; \
|
||||
}
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES (NUM_GEN_REGS*4 + NUM_CPU_REGS*4)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
#define REGISTER_BYTE(N) ((N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the PN, all normal 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 PN, all regs are 4 bytes. */
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (4)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
#define MAX_REGISTER_RAW_SIZE (4)
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE (4)
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
#define REGISTER_CONVERTIBLE(N) (0)
|
||||
|
||||
/* Convert data from raw format for register REGNUM
|
||||
to virtual format for register REGNUM. */
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
|
||||
|
||||
/* Extract from an arrary REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#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 NPL, the frame's norminal address is Br2 and the
|
||||
previous routines frame is up the stack X bytes, where X is the
|
||||
value stored in the code function header xA(Br1). */
|
||||
#define FRAME_CHAIN(thisframe) (findframe(thisframe))
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 && chain != thisframe)
|
||||
|
||||
#define FRAME_CHAIN_COMBINE(chain, thisframe) \
|
||||
(chain)
|
||||
|
||||
/* Define other aspects of the stack frame on NPL. */
|
||||
#define FRAME_SAVED_PC(frame) \
|
||||
(read_memory_integer (frame + 8, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
((fi).next_frame ? \
|
||||
read_memory_integer ((fi).frame + 12, 4) : \
|
||||
read_register (AP_REGNUM))
|
||||
|
||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame + 80)
|
||||
|
||||
/* Set VAL to the number of args passed to frame described by FI.
|
||||
Can set VAL to -1, meaning no way to tell. */
|
||||
|
||||
/* We can check the stab info to see how
|
||||
many arg we have. No info in stack will tell us */
|
||||
#define FRAME_NUM_ARGS(val,fi) (val = findarg(fi))
|
||||
|
||||
/* 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) \
|
||||
{ \
|
||||
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 8; \
|
||||
(frame_saved_regs).regs[R4_REGNUM] = (frame_info).frame + 0x30; \
|
||||
(frame_saved_regs).regs[R5_REGNUM] = (frame_info).frame + 0x34; \
|
||||
(frame_saved_regs).regs[R6_REGNUM] = (frame_info).frame + 0x38; \
|
||||
(frame_saved_regs).regs[R7_REGNUM] = (frame_info).frame + 0x3C; \
|
||||
}
|
||||
|
||||
/* 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; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
sp = push_word (sp, read_register (regnum)); \
|
||||
sp = push_word (sp, read_register (PS_REGNUM)); \
|
||||
write_register (SP_REGNUM, sp); }
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all 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; \
|
||||
fi = get_frame_info (fp); \
|
||||
get_frame_saved_regs (&fi, &fsr); \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
if (fsr.regs[regnum]) \
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
|
||||
if (fsr.regs[PS_REGNUM]) \
|
||||
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
|
||||
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
|
||||
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
|
||||
write_register (SP_REGNUM, fp + 8); \
|
||||
set_current_frame (read_register (FP_REGNUM)); }
|
||||
|
||||
/* This sequence of words is the instructions:
|
||||
halt
|
||||
halt
|
||||
halt
|
||||
halt
|
||||
suabr b2, #<stacksize>
|
||||
lwbr b6, #con
|
||||
stw r1, 8(b2) - save caller address, do we care?
|
||||
lw r2, 60(b2) - arg1
|
||||
labr b3, 50(b2)
|
||||
std r4, 30(b2) - save r4-r7
|
||||
std r6, 38(b2)
|
||||
lwbr b1, #<func> - load function call address
|
||||
brlnk r1, 8(b1) - call function
|
||||
halt
|
||||
halt
|
||||
ld r4, 30(b2) - restore r4-r7
|
||||
ld r6, 38(b2)
|
||||
|
||||
Setup our stack frame, load argumemts, call and then restore registers.
|
||||
*/
|
||||
|
||||
#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; }
|
||||
|
||||
/*
|
||||
* No KDB support, Yet! */
|
||||
/* Interface definitions for kernel debugger KDB. */
|
||||
|
||||
/* Map machine fault codes into signal numbers.
|
||||
First subtract 0, divide by 4, then index in a table.
|
||||
Faults for which the entry in this table is 0
|
||||
are not handled by KDB; the program's own trap handler
|
||||
gets to handle then. */
|
||||
|
||||
#define FAULT_CODE_ORIGIN 0
|
||||
#define FAULT_CODE_UNITS 4
|
||||
#define FAULT_TABLE \
|
||||
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
|
||||
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
SIGILL }
|
||||
|
||||
/* Start running with a stack stretching from BEG to END.
|
||||
BEG and END should be symbols meaningful to the assembler.
|
||||
This is used only for kdb. */
|
||||
|
||||
#define INIT_STACK(beg, end) \
|
||||
{ asm (".globl end"); \
|
||||
asm ("movel $ end, sp"); \
|
||||
asm ("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"); }
|
|
@ -0,0 +1,4 @@
|
|||
/* This is how the size of an individual .o file's text segment
|
||||
is rounded on a Concept. See pn-pinsn.c for rounding function. */
|
||||
|
||||
#define FILEADDR_ROUND(addr) (((int)(addr) + 7) & ~0x7)
|
|
@ -80,7 +80,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -79,7 +79,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
|
|||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e76)
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -0,0 +1,436 @@
|
|||
/* Definitions to make GDB run on an encore under umax 4.2
|
||||
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!
|
||||
*/
|
||||
|
||||
#ifndef ns16000
|
||||
#define ns16000
|
||||
#endif
|
||||
|
||||
#define HAVE_WAIT_STRUCT
|
||||
|
||||
/* Encore's modifications to ptrace format */
|
||||
|
||||
#define UMAX_PTRACE
|
||||
|
||||
/* Encore's modifications to core-file format */
|
||||
|
||||
#define UMAX_CORE
|
||||
|
||||
/* Do implement the attach and detach commands. */
|
||||
|
||||
#define ATTACH_DETACH
|
||||
|
||||
/* 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
|
||||
|
||||
/* Exec files and symbol tables are in COFF format */
|
||||
|
||||
#define COFF_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 unsigned char op = read_memory_integer (pc, 1); \
|
||||
if (op == 0x82) { op = read_memory_integer (pc+2,1); \
|
||||
if ((op & 0x80) == 0) pc += 3; \
|
||||
else if ((op & 0xc0) == 0x80) pc += 4; \
|
||||
else pc += 6; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR (0xfffff000)
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0xf2}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 0
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
|
||||
|
||||
#ifndef NaN
|
||||
#include <nan.h>
|
||||
#endif NaN
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, s) \
|
||||
((s == sizeof (float))? \
|
||||
NaF (*(float *) p) : \
|
||||
NaD (*(double *) p))
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 25
|
||||
|
||||
#define NUM_GENERAL_REGS 8
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
|
||||
#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
|
||||
"sp", "fp", "pc", "ps", \
|
||||
"fsr", \
|
||||
"l0", "l1", "l2", "l3", "xx", \
|
||||
}
|
||||
|
||||
/* 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 FP0_REGNUM 8 /* Floating point register 0 */
|
||||
#define SP_REGNUM 16 /* Contains address of top of stack */
|
||||
#define AP_REGNUM FP_REGNUM
|
||||
#define FP_REGNUM 17 /* Contains address of executing stack frame */
|
||||
#define PC_REGNUM 18 /* Contains program counter */
|
||||
#define PS_REGNUM 19 /* Contains processor status */
|
||||
#define FPS_REGNUM 20 /* Floating point status register */
|
||||
#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
|
||||
|
||||
/* called from register_addr() -- blockend not used for now */
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
{ \
|
||||
switch (regno) { \
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
|
||||
addr = PU_R0 - (regno * sizeof (int)); break; \
|
||||
case SP_REGNUM: \
|
||||
addr = PU_SP; break; \
|
||||
case PC_REGNUM: \
|
||||
addr = PU_PC; break; \
|
||||
case FP_REGNUM: \
|
||||
addr = PU_FP; break; \
|
||||
case PS_REGNUM: \
|
||||
addr = PU_PSL; break; \
|
||||
case FPS_REGNUM: \
|
||||
addr = PU_FSR; break; \
|
||||
case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
|
||||
case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
|
||||
case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
|
||||
case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
|
||||
addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break; \
|
||||
case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
|
||||
case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
|
||||
addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break; \
|
||||
default: \
|
||||
printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
|
||||
abort (); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
|
||||
LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. On the 32000, all regs are 4 bytes
|
||||
except for the doubled floating registers. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. On the 32000, all regs are 4 bytes
|
||||
except for the doubled floating registers. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 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), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Convert data from virtual format for register REGNUM
|
||||
to raw format for register REGNUM. */
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
|
||||
bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
(((N) < FP0_REGNUM) ? \
|
||||
builtin_type_int : \
|
||||
((N) < FP0_REGNUM + 8) ? \
|
||||
builtin_type_float : \
|
||||
((N) < LP0_REGNUM) ? \
|
||||
builtin_type_int : \
|
||||
builtin_type_double)
|
||||
|
||||
/* Extract from an array REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
|
||||
|
||||
/* Write into appropriate registers a function return value
|
||||
of type TYPE, given in virtual format. */
|
||||
|
||||
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
|
||||
write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 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 ns32000 series, the frame's nominal address is the FP
|
||||
value, and at that address is saved previous FP value as a 4-byte word. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4))
|
||||
|
||||
#define FRAME_CHAIN_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))
|
||||
|
||||
/* Compute base of arguments. */
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
((ns32k_get_enter_addr (fi.pc) > 1) ? \
|
||||
((fi).frame) : (read_register (SP_REGNUM) - 4))
|
||||
|
||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi).frame)
|
||||
|
||||
/* Get the address of the enter opcode for this function, if it is active.
|
||||
Returns positive address > 1 if pc is between enter/exit,
|
||||
1 if pc before enter or after exit, 0 otherwise. */
|
||||
|
||||
#ifndef CORE_ADDR
|
||||
#include "defs.h" /* Make sure CORE_ADDR is defined. */
|
||||
#endif
|
||||
|
||||
extern CORE_ADDR ns32k_get_enter_addr ();
|
||||
|
||||
/* Return number of args passed to a frame.
|
||||
Can return -1, meaning no way to tell.
|
||||
Encore's C compiler often reuses same area on stack for args,
|
||||
so this will often not work properly. If the arg names
|
||||
are known, it's likely most of them will be printed. */
|
||||
|
||||
#define FRAME_NUM_ARGS(numargs, fi) \
|
||||
{ CORE_ADDR pc; \
|
||||
CORE_ADDR enter_addr; \
|
||||
unsigned int insn; \
|
||||
unsigned int addr_mode; \
|
||||
int width; \
|
||||
\
|
||||
numargs = -1; \
|
||||
enter_addr = ns32k_get_enter_addr (fi.pc); \
|
||||
if (enter_addr > 0) \
|
||||
{ \
|
||||
pc = (enter_addr == 1) ? \
|
||||
SAVED_PC_AFTER_CALL () : \
|
||||
FRAME_SAVED_PC (fi.frame); \
|
||||
insn = read_memory_integer (pc,2); \
|
||||
addr_mode = (insn >> 11) & 0x1f; \
|
||||
insn = insn & 0x7ff; \
|
||||
if ((insn & 0x7fc) == 0x57c && \
|
||||
addr_mode == 0x14) /* immediate */ \
|
||||
{ \
|
||||
if (insn == 0x57c) /* adjspb */ \
|
||||
width = 1; \
|
||||
else if (insn == 0x57d) /* adjspw */ \
|
||||
width = 2; \
|
||||
else if (insn == 0x57f) /* adjspd */ \
|
||||
width = 4; \
|
||||
numargs = read_memory_integer (pc+2,width); \
|
||||
if (width > 1) \
|
||||
flip_bytes (&numargs, width); \
|
||||
numargs = - sign_extend (numargs, width*8) / 4;\
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Return number of bytes at start of arglist that are not really args. */
|
||||
|
||||
#define FRAME_ARGS_SKIP 8
|
||||
|
||||
/* Put here the code to store, into a struct frame_saved_regs,
|
||||
the addresses of the saved registers of frame described by FRAME_INFO.
|
||||
This includes special registers such as pc and fp saved in special
|
||||
ways in the stack frame. sp is even more special:
|
||||
the address we return for it IS the sp for the next frame. */
|
||||
|
||||
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
|
||||
{ \
|
||||
register int regmask, regnum; \
|
||||
int localcount; \
|
||||
register CORE_ADDR enter_addr; \
|
||||
register CORE_ADDR next_addr; \
|
||||
\
|
||||
bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
|
||||
enter_addr = ns32k_get_enter_addr ((frame_info).pc); \
|
||||
if (enter_addr > 1) \
|
||||
{ \
|
||||
regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
|
||||
localcount = ns32k_localcount (enter_addr); \
|
||||
next_addr = (frame_info).frame + localcount; \
|
||||
for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
|
||||
(frame_saved_regs).regs[regnum] = (regmask & 1) ? \
|
||||
(next_addr -= 4) : 0; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 4;\
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4;\
|
||||
(frame_saved_regs).regs[FP_REGNUM] = \
|
||||
(read_memory_integer ((frame_info).frame, 4));\
|
||||
} \
|
||||
else if (enter_addr == 1) \
|
||||
{ \
|
||||
CORE_ADDR sp = read_register (SP_REGNUM); \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = sp; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = sp + 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; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = 0; regnum < 8; regnum++) \
|
||||
sp = push_word (sp, read_register (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; \
|
||||
fi = get_frame_info (fp); \
|
||||
get_frame_saved_regs (&fi, &fsr); \
|
||||
for (regnum = 0; regnum < 8; regnum++) \
|
||||
if (fsr.regs[regnum]) \
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
|
||||
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
|
||||
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
|
||||
write_register (SP_REGNUM, fp + 8); \
|
||||
}
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
enter 0xff,0 82 ff 00
|
||||
jsr @0x00010203 7f ae c0 01 02 03
|
||||
adjspd 0x69696969 7f a5 01 02 03 04
|
||||
bpt f2
|
||||
Note this is 16 bytes. */
|
||||
|
||||
#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 3
|
||||
#define CALL_DUMMY_LENGTH 16
|
||||
#define CALL_DUMMY_ADDR 5
|
||||
#define CALL_DUMMY_NARGS 11
|
||||
|
||||
/* 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 flipped; \
|
||||
flipped = fun | 0xc0000000; \
|
||||
flip_bytes (&flipped, 4); \
|
||||
*((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
|
||||
flipped = - nargs * 4; \
|
||||
flip_bytes (&flipped, 4); \
|
||||
*((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/* This is how the size of an individual .o file's text segment
|
||||
is rounded on the multimax. */
|
||||
|
||||
#define FILEADDR_ROUND(addr) ((addr + 3) & -4)
|
|
@ -189,6 +189,9 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
as a CORE_ADDR (or an expression that can be used as one). */
|
||||
|
||||
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
|
||||
|
||||
/* Compensate for lack of `vprintf' function. */
|
||||
#define vprintf(format, ap) _doprnt (format, ap, stdout)
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
|
|
|
@ -406,8 +406,8 @@ struct m68k_opcode m68k_opcodes[] =
|
|||
{"muls", one(0140700), one(0170700), ";wDd"},
|
||||
{"mulul", two(0046000, 000000), two(0177700, 0107770), ";lD1"},
|
||||
{"mulul", two(0046000, 002000), two(0177700, 0107770), ";lD3D1"},
|
||||
{"muluw", one(0140300), one(0170700), ";lDd"},
|
||||
{"mulu", one(0140300), one(0170700), ";lDd"},
|
||||
{"muluw", one(0140300), one(0170700), ";wDd"},
|
||||
{"mulu", one(0140300), one(0170700), ";wDd"},
|
||||
{"nbcd", one(0044000), one(0177700), "$s"},
|
||||
{"negb", one(0042000), one(0177700), "$s"},
|
||||
{"negl", one(0042200), one(0177700), "$s"},
|
||||
|
@ -875,8 +875,8 @@ struct m68k_opcode m68k_opcodes[] =
|
|||
{"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7"}, /* fmove from <ea> to fp<n> */
|
||||
{"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l"}, /* fmove from fp<n> to <ea> */
|
||||
/* JF for the assembler */
|
||||
{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"},
|
||||
{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii@ss8"},
|
||||
{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%l"},
|
||||
{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8"},
|
||||
/* JF {"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from <ea> to fp<n> */
|
||||
{"fmovep", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7@pkC"}, /* fmove.p with k-factors: */
|
||||
{"fmovep", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7@pDk"}, /* fmove.p with k-factors: */
|
||||
|
|
|
@ -23,7 +23,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "m68k-opcode.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/* 68k instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 22
|
||||
|
@ -714,6 +714,12 @@ convert_from_68881 (from, to)
|
|||
char *from;
|
||||
double *to;
|
||||
{
|
||||
#ifdef HPUX_ASM
|
||||
asm ("mov.l 8(%a6),%a0");
|
||||
asm ("mov.l 12(%a6),%a1");
|
||||
asm ("fmove.x (%a0),%fp0");
|
||||
asm ("fmove.d %fp0,(%a1)");
|
||||
#else /* not HPUX_ASM */
|
||||
#if 0
|
||||
asm ("movl a6@(8),a0");
|
||||
asm ("movl a6@(12),a1");
|
||||
|
@ -729,6 +735,7 @@ convert_from_68881 (from, to)
|
|||
asm (".long 0xf2104800");
|
||||
asm (".long 0xf2117400");
|
||||
#endif
|
||||
#endif /* not HPUX_ASM */
|
||||
}
|
||||
|
||||
/* The converse: convert the double *FROM to an extended float
|
||||
|
@ -738,6 +745,12 @@ convert_to_68881 (from, to)
|
|||
double *from;
|
||||
char *to;
|
||||
{
|
||||
#ifdef HPUX_ASM
|
||||
asm ("mov.l 8(%a6),%a0");
|
||||
asm ("mov.l 12(%a6),%a1");
|
||||
asm ("fmove.d (%a0),%fp0");
|
||||
asm ("fmove.x %fp0,(%a1)");
|
||||
#else /* not HPUX_ASM */
|
||||
#if 0
|
||||
asm ("movl a6@(8),a0");
|
||||
asm ("movl a6@(12),a1");
|
||||
|
@ -752,4 +765,5 @@ convert_to_68881 (from, to)
|
|||
asm (".long 0xf2105400");
|
||||
asm (".long 0xf2116800");
|
||||
#endif
|
||||
#endif /* not HPUX_ASM */
|
||||
}
|
||||
|
|
167
gdb/main.c
167
gdb/main.c
|
@ -1,5 +1,5 @@
|
|||
/* Top level for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
|
@ -52,13 +52,19 @@ FILE *instream;
|
|||
|
||||
char *current_directory;
|
||||
|
||||
/* The directory name is actually stored here. */
|
||||
/* The directory name is actually stored here (usually). */
|
||||
static char dirbuf[MAXPATHLEN];
|
||||
|
||||
/* Nonzero if we should refrain from using an X window. */
|
||||
|
||||
int inhibit_windows = 0;
|
||||
|
||||
/* Hook for window manager argument parsing. */
|
||||
|
||||
int *win_argc;
|
||||
char **win_argv;
|
||||
char *win_prgm;
|
||||
|
||||
/* Function to call before reading a command, if nonzero.
|
||||
The function receives two args: an input stream,
|
||||
and a prompt string. */
|
||||
|
@ -82,7 +88,7 @@ static char *prompt;
|
|||
|
||||
char *line;
|
||||
int linesize;
|
||||
|
||||
|
||||
/* This is how `error' returns to command level. */
|
||||
|
||||
jmp_buf to_top_level;
|
||||
|
@ -93,9 +99,48 @@ return_to_top_level ()
|
|||
immediate_quit = 0;
|
||||
clear_breakpoint_commands ();
|
||||
clear_momentary_breakpoints ();
|
||||
delete_current_display ();
|
||||
do_cleanups (0);
|
||||
longjmp (to_top_level, 1);
|
||||
}
|
||||
|
||||
/* Call FUNC with arg ARG, catching any errors.
|
||||
If there is no error, return the value returned by FUNC.
|
||||
If there is an error, return zero after printing ERRSTRING
|
||||
(which is in addition to the specific error message already printed). */
|
||||
|
||||
int
|
||||
catch_errors (func, arg, errstring)
|
||||
int (*func) ();
|
||||
int arg;
|
||||
char *errstring;
|
||||
{
|
||||
jmp_buf saved;
|
||||
int val;
|
||||
|
||||
bcopy (to_top_level, saved, sizeof (jmp_buf));
|
||||
|
||||
if (setjmp (to_top_level) == 0)
|
||||
val = (*func) (arg);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s\n", errstring);
|
||||
val = 0;
|
||||
}
|
||||
|
||||
bcopy (saved, to_top_level, sizeof (jmp_buf));
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Handler for SIGHUP. */
|
||||
|
||||
static void
|
||||
disconnect ()
|
||||
{
|
||||
kill_inferior_fast ();
|
||||
signal (SIGHUP, SIG_DFL);
|
||||
kill (getpid (), SIGHUP);
|
||||
}
|
||||
|
||||
main (argc, argv, envp)
|
||||
int argc;
|
||||
|
@ -117,6 +162,10 @@ main (argc, argv, envp)
|
|||
getwd (dirbuf);
|
||||
current_directory = dirbuf;
|
||||
|
||||
win_argc = &argc;
|
||||
win_argv = argv;
|
||||
win_prgm = argv[0];
|
||||
|
||||
#ifdef SET_STACK_LIMIT_HUGE
|
||||
{
|
||||
struct rlimit rlim;
|
||||
|
@ -129,8 +178,6 @@ main (argc, argv, envp)
|
|||
}
|
||||
#endif /* SET_STACK_LIMIT_HUGE */
|
||||
|
||||
/* Run the init function of each source file */
|
||||
|
||||
/* Look for flag arguments. */
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
|
@ -141,10 +188,10 @@ main (argc, argv, envp)
|
|||
inhibit_gdbinit = 1;
|
||||
else if (!strcmp (argv[i], "-nw"))
|
||||
inhibit_windows = 1;
|
||||
else if (!strcmp (argv[i], "-fullname"))
|
||||
frame_file_full_name = 1;
|
||||
else if (!strcmp (argv[i], "-batch"))
|
||||
batch = 1, quiet = 1;
|
||||
else if (!strcmp (argv[i], "-fullname"))
|
||||
frame_file_full_name = 1;
|
||||
else if (argv[i][0] == '-')
|
||||
i++;
|
||||
}
|
||||
|
@ -156,6 +203,8 @@ main (argc, argv, envp)
|
|||
|
||||
signal (SIGINT, request_quit);
|
||||
signal (SIGQUIT, SIG_IGN);
|
||||
if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
|
||||
signal (SIGHUP, disconnect);
|
||||
|
||||
if (!quiet)
|
||||
print_gdb_version ();
|
||||
|
@ -206,6 +255,17 @@ main (argc, argv, envp)
|
|||
else if (!strcmp (arg, "-d") || !strcmp (arg, "-dir")
|
||||
|| !strcmp (arg, "-directory"))
|
||||
directory_command (argv[i], 0);
|
||||
/* -cd FOO: specify current directory as FOO.
|
||||
GDB remembers the precise string FOO as the dirname. */
|
||||
else if (!strcmp (arg, "-cd"))
|
||||
{
|
||||
int len = strlen (argv[i]);
|
||||
current_directory = argv[i];
|
||||
if (len > 1 && current_directory[len - 1] == '/')
|
||||
current_directory = savestring (current_directory, len-1);
|
||||
chdir (current_directory);
|
||||
init_source_path ();
|
||||
}
|
||||
/* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */
|
||||
else if (!strcmp (arg, "-t") || !strcmp (arg, "-tty"))
|
||||
tty_command (argv[i], 0);
|
||||
|
@ -292,8 +352,7 @@ execute_command (p, from_tty)
|
|||
else if (c->class == (int) class_user)
|
||||
{
|
||||
if (*p)
|
||||
error ("User-defined commands cannot take command-line arguments: \"%s\"",
|
||||
p);
|
||||
error ("User-defined commands cannot take arguments.");
|
||||
cmdlines = (struct command_line *) c->function;
|
||||
if (cmdlines == (struct command_line *) 0)
|
||||
/* Null command */
|
||||
|
@ -339,6 +398,7 @@ command_loop ()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef SIGTSTP
|
||||
static void
|
||||
stop_sig ()
|
||||
{
|
||||
|
@ -352,6 +412,7 @@ stop_sig ()
|
|||
/* Forget about any previous command -- null line now will do nothing. */
|
||||
*line = 0;
|
||||
}
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
/* Commands call this if they do not want to be repeated by null lines. */
|
||||
|
||||
|
@ -378,17 +439,25 @@ read_line (repeat)
|
|||
/* Control-C quits instantly if typed while in this loop
|
||||
since it should not wait until the user types a newline. */
|
||||
immediate_quit++;
|
||||
#ifdef SIGTSTP
|
||||
signal (SIGTSTP, stop_sig);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
c = fgetc (instream);
|
||||
if (c == -1 || c == '\n')
|
||||
break;
|
||||
/* Ignore backslash-newline; keep adding to the same line. */
|
||||
else if (c == '\\')
|
||||
if ((c = fgetc (instream)) == '\n')
|
||||
continue;
|
||||
else ungetc (c, instream);
|
||||
{
|
||||
int c1 = fgetc (instream);
|
||||
if (c1 == '\n')
|
||||
continue;
|
||||
else
|
||||
ungetc (c1, instream);
|
||||
}
|
||||
|
||||
if (p - line == linesize - 1)
|
||||
{
|
||||
linesize *= 2;
|
||||
|
@ -398,7 +467,10 @@ read_line (repeat)
|
|||
}
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
#ifdef SIGTSTP
|
||||
signal (SIGTSTP, SIG_DFL);
|
||||
#endif
|
||||
immediate_quit--;
|
||||
|
||||
/* If we just got an empty line, and that is supposed
|
||||
|
@ -573,7 +645,7 @@ validate_comname (comname)
|
|||
{
|
||||
if (!(*p >= 'A' && *p <= 'Z')
|
||||
&& !(*p >= 'a' && *p <= 'z')
|
||||
&& !(*p >= '1' && *p <= '9')
|
||||
&& !(*p >= '0' && *p <= '9')
|
||||
&& *p != '-')
|
||||
error ("Junk in argument list: \"%s\"", p);
|
||||
p++;
|
||||
|
@ -668,7 +740,7 @@ copying_info ()
|
|||
{
|
||||
immediate_quit++;
|
||||
printf (" GDB GENERAL PUBLIC LICENSE\n\
|
||||
\n (Clarified 11 Feb 1988)\
|
||||
(Clarified 11 Feb 1988)\n\
|
||||
\n\
|
||||
Copyright (C) 1988 Richard M. Stallman\n\
|
||||
Everyone is permitted to copy and distribute verbatim copies\n\
|
||||
|
@ -862,6 +934,17 @@ version_info ()
|
|||
immediate_quit--;
|
||||
}
|
||||
|
||||
/* xgdb calls this to reprint the usual GDB prompt. */
|
||||
|
||||
void
|
||||
print_prompt ()
|
||||
{
|
||||
printf ("%s", prompt);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
/* Command to specify a prompt string instead of "(gdb) ". */
|
||||
|
||||
static void
|
||||
set_prompt_command (text)
|
||||
char *text;
|
||||
|
@ -930,7 +1013,13 @@ pwd_command (arg, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
|
||||
printf ("Working directory %s.\n", dirbuf);
|
||||
getwd (dirbuf);
|
||||
|
||||
if (strcmp (dirbuf, current_directory))
|
||||
printf ("Working directory %s\n (canonically %s).\n",
|
||||
current_directory, dirbuf);
|
||||
else
|
||||
printf ("Working directory %s.\n", current_directory);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -938,16 +1027,57 @@ cd_command (dir, from_tty)
|
|||
char *dir;
|
||||
int from_tty;
|
||||
{
|
||||
int len;
|
||||
int change;
|
||||
|
||||
if (dir == 0)
|
||||
error_no_arg ("new working directory");
|
||||
|
||||
len = strlen (dir);
|
||||
dir = savestring (dir, len - (len > 1 && dir[len-1] == '/'));
|
||||
if (dir[0] == '/')
|
||||
current_directory = dir;
|
||||
else
|
||||
{
|
||||
current_directory = concat (current_directory, "/", dir);
|
||||
free (dir);
|
||||
}
|
||||
|
||||
/* Now simplify any occurrences of `.' and `..' in the pathname. */
|
||||
|
||||
change = 1;
|
||||
while (change)
|
||||
{
|
||||
char *p;
|
||||
change = 0;
|
||||
|
||||
for (p = current_directory; *p;)
|
||||
{
|
||||
if (!strncmp (p, "/./", 2)
|
||||
&& (p[2] == 0 || p[2] == '/'))
|
||||
strcpy (p, p + 2);
|
||||
else if (!strncmp (p, "/..", 3)
|
||||
&& (p[3] == 0 || p[3] == '/')
|
||||
&& p != current_directory)
|
||||
{
|
||||
char *q = p;
|
||||
while (q != current_directory && q[-1] != '/') q--;
|
||||
if (q != current_directory)
|
||||
{
|
||||
strcpy (q-1, p+3);
|
||||
p = q-1;
|
||||
}
|
||||
}
|
||||
else p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir (dir) < 0)
|
||||
perror_with_name (dir);
|
||||
getwd (dirbuf);
|
||||
|
||||
if (from_tty)
|
||||
pwd_command ((char *) 0, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Clean up on error during a "source" command.
|
||||
Close the file opened by the command
|
||||
|
@ -1019,12 +1149,11 @@ dump_me_command ()
|
|||
kill (getpid (), SIGQUIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
initialize_main ()
|
||||
{
|
||||
prompt = savestring ("(gdb+) ", 7);
|
||||
prompt = savestring ("(gdb) ", 6);
|
||||
|
||||
/* Define the classes of commands.
|
||||
They will appear in the help list in the reverse of this order. */
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
/* Print GOULD NPL instructions for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
struct gld_opcode
|
||||
{
|
||||
char *name;
|
||||
unsigned long opcode;
|
||||
unsigned long mask;
|
||||
char *args;
|
||||
int length;
|
||||
};
|
||||
|
||||
/* We store four bytes of opcode for all opcodes because that
|
||||
is the most any of them need. The actual length of an instruction
|
||||
is always at least 2 bytes, and at most four. The length of the
|
||||
instruction is based on the opcode.
|
||||
|
||||
The mask component is a mask saying which bits must match
|
||||
particular opcode in order for an instruction to be an instance
|
||||
of that opcode.
|
||||
|
||||
The args component is a string containing characters
|
||||
that are used to format the arguments to the instruction. */
|
||||
|
||||
/* Kinds of operands:
|
||||
r Register in first field
|
||||
R Register in second field
|
||||
b Base register in first field
|
||||
B Base register in second field
|
||||
v Vector register in first field
|
||||
V Vector register in first field
|
||||
A Optional address register (base register)
|
||||
X Optional index register
|
||||
I Immediate data (16bits signed)
|
||||
O Offset field (16bits signed)
|
||||
h Offset field (15bits signed)
|
||||
d Offset field (14bits signed)
|
||||
S Shift count field
|
||||
|
||||
any other characters are printed as is...
|
||||
*/
|
||||
|
||||
/* The assembler requires that this array be sorted as follows:
|
||||
all instances of the same mnemonic must be consecutive.
|
||||
All instances of the same mnemonic with the same number of operands
|
||||
must be consecutive.
|
||||
*/
|
||||
struct gld_opcode gld_opcodes[] =
|
||||
{
|
||||
{ "lb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lnb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lbs", 0xec080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "lnh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "lw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lnw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "ld", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "lnd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "li", 0xf8000000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "lpa", 0x50080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "la", 0x50000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "lbp", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lhp", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "lwp", 0x90000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "ldp", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "lf", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lfbr", 0xbc080000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stfbr", 0xdc080000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "zmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "zmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "zmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "zmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "stbp", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sthp", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "stwp", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stdp", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "lil", 0xf8080000, 0xfc7f0000, "r,D", 4 },
|
||||
{ "lwsl1", 0xec000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lwsl2", 0xfc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lwsl3", 0xfc080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
|
||||
{ "lvb", 0xb0080000, 0xfc080000, "v,xOA,X", 4 },
|
||||
{ "lvh", 0xb0000001, 0xfc080001, "v,xOA,X", 4 },
|
||||
{ "lvw", 0xb0000000, 0xfc080000, "v,xOA,X", 4 },
|
||||
{ "lvd", 0xb0000002, 0xfc080002, "v,xOA,X", 4 },
|
||||
{ "liv", 0x3c040000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "livf", 0x3c080000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "stvb", 0xd0080000, 0xfc080000, "v,xOA,X", 4 },
|
||||
{ "stvh", 0xd0000001, 0xfc080001, "v,xOA,X", 4 },
|
||||
{ "stvw", 0xd0000000, 0xfc080000, "v,xOA,X", 4 },
|
||||
{ "stvd", 0xd0000002, 0xfc080002, "v,xOA,X", 4 },
|
||||
|
||||
{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trnd", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trabs", 0x2c010000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trabsd", 0x2c090000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "xcr", 0x28040000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "cxcr", 0x2c060000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "cxcrd", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
|
||||
{ "trbr", 0x28030000, 0xfc0f0000, "b,R", 2 },
|
||||
{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
|
||||
{ "tbrbr", 0x28010000, 0xfc0f0000, "b,B", 2 },
|
||||
|
||||
{ "trvv", 0x28050000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "trvvn", 0x2c050000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "trvvnd", 0x2c0d0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "trvab", 0x2c070000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "trvabd", 0x2c0f0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "cmpv", 0x14060000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "expv", 0x14070000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvvlt", 0x10030000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvvle", 0x10040000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvvgt", 0x14030000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvvge", 0x14040000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvveq", 0x10050000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvvne", 0x10050000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mrvrlt", 0x100d0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mrvrle", 0x100e0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mrvrgt", 0x140d0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mrvrge", 0x140e0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mrvreq", 0x100f0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mrvrne", 0x140f0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "trvr", 0x140b0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "trrv", 0x140c0000, 0xfc0f0000, "v,R", 2 },
|
||||
|
||||
{ "bu", 0x40000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bns", 0x70080000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bnco", 0x70880000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bge", 0x71080000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bne", 0x71880000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bunge", 0x72080000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bunle", 0x72880000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bgt", 0x73080000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bnany", 0x73880000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bs" , 0x70000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bco", 0x70800000, 0xff880000, "xOA,X", 4 },
|
||||
{ "blt", 0x71000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "beq", 0x71800000, 0xff880000, "xOA,X", 4 },
|
||||
{ "buge", 0x72000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bult", 0x72800000, 0xff880000, "xOA,X", 4 },
|
||||
{ "ble", 0x73000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bany", 0x73800000, 0xff880000, "xOA,X", 4 },
|
||||
{ "brlnk", 0x44000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bib", 0x48000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bih", 0x48080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "biw", 0x4c000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bid", 0x4c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bivb", 0x60000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bivh", 0x60080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bivw", 0x64000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bivd", 0x64080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bvsb", 0x68000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bvsh", 0x68080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bvsw", 0x6c000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bvsd", 0x6c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
|
||||
{ "camb", 0x80080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "camh", 0x80000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "camw", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "camd", 0x80000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "card", 0x14000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ci", 0xf8050000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "chkbnd", 0x5c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
|
||||
{ "cavv", 0x10010000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "cavr", 0x10020000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "cavvd", 0x10090000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "cavrd", 0x100b0000, 0xfc0f0000, "v,R", 2 },
|
||||
|
||||
{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ani", 0xf8080000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "ormb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "ormh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "ormw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "ormd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "oi", 0xf8090000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "eoi", 0xf80a0000, 0xfc7f0000, "r,I", 4 },
|
||||
|
||||
{ "anvv", 0x04010000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "anvr", 0x04020000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "orvv", 0x08010000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "orvr", 0x08020000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "eovv", 0x0c010000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "eovr", 0x0c020000, 0xfc0f0000, "v,R", 2 },
|
||||
|
||||
{ "sacz", 0x100c0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
|
||||
{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
|
||||
{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
|
||||
{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
|
||||
{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
|
||||
{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
|
||||
{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
|
||||
{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
|
||||
{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
|
||||
{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
|
||||
{ "sda", 0x3c030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sdl", 0x3c020000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sdc", 0x3c010000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sdad", 0x3c0b0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sdld", 0x3c0a0000, 0xfc0f0000, "r,R", 2 },
|
||||
|
||||
{ "svda", 0x3c070000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "svdl", 0x3c060000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "svdc", 0x3c050000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "svdad", 0x3c0e0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "svdld", 0x3c0d0000, 0xfc0f0000, "v,R", 2 },
|
||||
|
||||
{ "sbm", 0xac080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "zbm", 0xac000000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "tbm", 0xa8080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "incmb", 0xa0000000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "incmh", 0xa0080000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "incmw", 0xa4000000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "incmd", 0xa4080000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "sbmd", 0x7c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "zbmd", 0x7c000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "tbmd", 0x78080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
|
||||
{ "ssm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "zsm", 0x9c000000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "tsm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
|
||||
{ "admb", 0xc8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "admh", 0xc8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "admw", 0xc8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "admd", 0xc8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "adi", 0xf8010000, 0xfc0f0000, "r,I", 4 },
|
||||
{ "sumb", 0xcc080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sumh", 0xcc000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "sumw", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sumd", 0xcc000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sui", 0xf8020000, 0xfc0f0000, "r,I", 4 },
|
||||
{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mprd", 0x3c0f0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mpi", 0xf8030000, 0xfc0f0000, "r,I", 4 },
|
||||
{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "dvi", 0xf8040000, 0xfc0f0000, "r,I", 4 },
|
||||
{ "exs", 0x38080000, 0xfc0f0000, "r,R", 2 },
|
||||
|
||||
{ "advv", 0x30000000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "advvd", 0x30080000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "adrv", 0x34000000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "adrvd", 0x34080000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "suvv", 0x30010000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "suvvd", 0x30090000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "surv", 0x34010000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "survd", 0x34090000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mpvv", 0x30020000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mprv", 0x34020000, 0xfc0f0000, "v,R", 2 },
|
||||
|
||||
{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "surfw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "surfd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "surfd", 0x380b0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "rfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "rfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "rrfw", 0x0c0e0000, 0xfc0f0000, "r", 2 },
|
||||
{ "rrfd", 0x0c0f0000, 0xfc0f0000, "r", 2 },
|
||||
|
||||
{ "advvfw", 0x30040000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "advvfd", 0x300c0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "adrvfw", 0x34040000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "adrvfd", 0x340c0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "suvvfw", 0x30050000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "suvvfd", 0x300d0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "survfw", 0x34050000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "survfd", 0x340d0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mpvvfw", 0x30060000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mpvvfd", 0x300e0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "mprvfw", 0x34060000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "mprvfd", 0x340e0000, 0xfc0f0000, "v,R", 2 },
|
||||
{ "rvfw", 0x30070000, 0xfc0f0000, "v", 2 },
|
||||
{ "rvfd", 0x300f0000, 0xfc0f0000, "v", 2 },
|
||||
|
||||
{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "cfpds", 0x3c090000, 0xfc0f0000, "r,R", 2 },
|
||||
|
||||
{ "fltvw", 0x080d0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "fltvd", 0x080f0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "fixvw", 0x080c0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "fixvd", 0x080e0000, 0xfc0f0000, "v,V", 2 },
|
||||
{ "cfpvds", 0x0c0d0000, 0xfc0f0000, "v,V", 2 },
|
||||
|
||||
{ "orvrn", 0x000a0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "andvrn", 0x00080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "frsteq", 0x04090000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "sigma", 0x0c080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "sigmad", 0x0c0a0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "sigmf", 0x08080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "sigmfd", 0x080a0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "prodf", 0x04080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "prodfd", 0x040a0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "maxv", 0x10080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "maxvd", 0x100a0000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "minv", 0x14080000, 0xfc0f0000, "r,V", 2 },
|
||||
{ "minvd", 0x140a0000, 0xfc0f0000, "r,V", 2 },
|
||||
|
||||
{ "lpsd", 0xf0000000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "ldc", 0xf0080000, 0xfc080000, "xOA,X", 4 },
|
||||
{ "spm", 0x040c0000, 0xfc0f0000, "r", 2 },
|
||||
{ "rpm", 0x040d0000, 0xfc0f0000, "r", 2 },
|
||||
{ "tritr", 0x00070000, 0xfc0f0000, "r", 2 },
|
||||
{ "trrit", 0x00060000, 0xfc0f0000, "r", 2 },
|
||||
{ "rpswt", 0x04080000, 0xfc0f0000, "r", 2 },
|
||||
{ "exr", 0xf8070000, 0xfc0f0000, "", 4 },
|
||||
{ "halt", 0x00000000, 0xfc0f0000, "", 2 },
|
||||
{ "wait", 0x00010000, 0xfc0f0000, "", 2 },
|
||||
{ "nop", 0x00020000, 0xfc0f0000, "", 2 },
|
||||
{ "eiae", 0x00030000, 0xfc0f0000, "", 2 },
|
||||
{ "efae", 0x000d0000, 0xfc0f0000, "", 2 },
|
||||
{ "diae", 0x000e0000, 0xfc0f0000, "", 2 },
|
||||
{ "dfae", 0x000f0000, 0xfc0f0000, "", 2 },
|
||||
{ "spvc", 0xf8060000, 0xfc0f0000, "r,T,N", 4 },
|
||||
{ "rdsts", 0x00090000, 0xfc0f0000, "r", 2 },
|
||||
{ "setcpu", 0x000c0000, 0xfc0f0000, "r", 2 },
|
||||
{ "cmc", 0x000b0000, 0xfc0f0000, "r", 2 },
|
||||
{ "trrcu", 0x00040000, 0xfc0f0000, "r", 2 },
|
||||
{ "attnio", 0x00050000, 0xfc0f0000, "", 2 },
|
||||
{ "fudit", 0x28080000, 0xfc0f0000, "", 2 },
|
||||
{ "break", 0x28090000, 0xfc0f0000, "", 2 },
|
||||
{ "frzss", 0x280a0000, 0xfc0f0000, "", 2 },
|
||||
{ "ripi", 0x04040000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "xcp", 0x04050000, 0xfc0f0000, "r", 2 },
|
||||
{ "block", 0x04060000, 0xfc0f0000, "", 2 },
|
||||
{ "unblock", 0x04070000, 0xfc0f0000, "", 2 },
|
||||
{ "trsc", 0x08060000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "tscr", 0x08070000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fq", 0x04080000, 0xfc0f0000, "r", 2 },
|
||||
{ "flupte", 0x2c080000, 0xfc0f0000, "r", 2 },
|
||||
{ "rviu", 0x040f0000, 0xfc0f0000, "", 2 },
|
||||
{ "ldel", 0x280c0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ldu", 0x280d0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "stdecc", 0x280b0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trpc", 0x08040000, 0xfc0f0000, "r", 2 },
|
||||
{ "tpcr", 0x08050000, 0xfc0f0000, "r", 2 },
|
||||
{ "ghalt", 0x0c050000, 0xfc0f0000, "r", 2 },
|
||||
{ "grun", 0x0c040000, 0xfc0f0000, "", 2 },
|
||||
{ "tmpr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trmp", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
|
||||
|
||||
{ "trrve", 0x28060000, 0xfc0f0000, "r", 2 },
|
||||
{ "trver", 0x28070000, 0xfc0f0000, "r", 2 },
|
||||
{ "trvlr", 0x280f0000, 0xfc0f0000, "r", 2 },
|
||||
|
||||
{ "linkfl", 0x18000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "linkbl", 0x18020000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "linkfp", 0x18010000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "linkbp", 0x18030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "linkpl", 0x18040000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ulinkl", 0x18080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ulinkp", 0x18090000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ulinktl", 0x180a0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ulinktp", 0x180b0000, 0xfc0f0000, "r,R", 2 },
|
||||
};
|
||||
|
||||
int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
|
||||
|
||||
struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
|
||||
sizeof(gld_opcodes[0]);
|
|
@ -0,0 +1,307 @@
|
|||
/* ns32k-opcode.h */
|
||||
|
||||
#ifndef ns32k_opcodeT
|
||||
#define ns32k_opcodeT int
|
||||
#endif /* no ns32k_opcodeT */
|
||||
|
||||
struct not_wot /* ns32k opcode table: wot to do with this */
|
||||
/* particular opcode */
|
||||
{
|
||||
int obits; /* number of opcode bits */
|
||||
int ibits; /* number of instruction bits */
|
||||
ns32k_opcodeT code; /* op-code (may be > 8 bits!) */
|
||||
char *args; /* how to compile said opcode */
|
||||
};
|
||||
|
||||
struct not /* ns32k opcode text */
|
||||
{
|
||||
char * name; /* opcode name: lowercase string [key] */
|
||||
struct not_wot detail; /* rest of opcode table [datum] */
|
||||
};
|
||||
|
||||
/* F : 32 bit float
|
||||
* L : 64 bit float
|
||||
* B : byte
|
||||
* W : word
|
||||
* D : double-word
|
||||
* Q : quad-word
|
||||
* d : displacement
|
||||
* q : quick
|
||||
* i : immediate (8 bits)
|
||||
* r : register number (3 bits)
|
||||
* p : displacement - pc relative addressing
|
||||
*/
|
||||
static struct not
|
||||
notstrs[] =
|
||||
{
|
||||
{ "absf", 14,24, 0x35be, "1F2F" },
|
||||
{ "absl", 14,24, 0x34be, "1L2L" },
|
||||
{ "absb", 14,24, 0x304e, "1B2B" },
|
||||
{ "absw", 14,24, 0x314e, "1W2W" },
|
||||
{ "absd", 14,24, 0x334e, "1D2D" },
|
||||
{ "acbb", 7,16, 0x4c, "2B1q3p" },
|
||||
{ "addf", 14,24, 0x01be, "1F2F" },
|
||||
{ "addl", 14,24, 0x00be, "1L2L" },
|
||||
{ "addb", 6,16, 0x00, "1B2B" },
|
||||
{ "addw", 6,16, 0x01, "1W2W" },
|
||||
{ "addd", 6,16, 0x03, "1D2D" },
|
||||
{ "addcb", 6,16, 0x10, "1B2B" },
|
||||
{ "addcw", 6,16, 0x11, "1W2W" },
|
||||
{ "addcd", 6,16, 0x13, "1D2D" },
|
||||
{ "addpb", 14,24, 0x3c4e, "1B2B" },
|
||||
{ "addpw", 14,24, 0x3d4e, "1W2W" },
|
||||
{ "addpd", 14,24, 0x3f4e, "1D2D" },
|
||||
{ "addqb", 7,16, 0x0c, "2B1q" },
|
||||
{ "addqw", 7,16, 0x0d, "2W1q" },
|
||||
{ "addqd", 7,16, 0x0f, "2D1q" },
|
||||
{ "addr", 6,16, 0x27, "1D2D" },
|
||||
{ "adjspb", 11,16, 0x057c, "1B" },
|
||||
{ "adjspw", 11,16, 0x057d, "1W" },
|
||||
{ "adjspd", 11,16, 0x057f, "1D" },
|
||||
{ "andb", 6,16, 0x28, "1B2B" },
|
||||
{ "andw", 6,16, 0x29, "1W2W" },
|
||||
{ "andd", 6,16, 0x2b, "1D2D" },
|
||||
{ "ashb", 14,24, 0x044e, "1B2B" },
|
||||
{ "ashw", 14,24, 0x054e, "1B2W" },
|
||||
{ "ashd", 14,24, 0x074e, "1B2D" },
|
||||
{ "beq", 8,8, 0x0a, "1p" },
|
||||
{ "bne", 8,8, 0x1a, "1p" },
|
||||
{ "bcs", 8,8, 0x2a, "1p" },
|
||||
{ "bcc", 8,8, 0x3a, "1p" },
|
||||
{ "bhi", 8,8, 0x4a, "1p" },
|
||||
{ "bls", 8,8, 0x5a, "1p" },
|
||||
{ "bgt", 8,8, 0x6a, "1p" },
|
||||
{ "ble", 8,8, 0x7a, "1p" },
|
||||
{ "bfs", 8,8, 0x8a, "1p" },
|
||||
{ "bfc", 8,8, 0x9a, "1p" },
|
||||
{ "blo", 8,8, 0xaa, "1p" },
|
||||
{ "bhs", 8,8, 0xba, "1p" },
|
||||
{ "blt", 8,8, 0xca, "1p" },
|
||||
{ "bge", 8,8, 0xda, "1p" },
|
||||
{ "bicb", 6,16, 0x08, "1B2B" },
|
||||
{ "bicw", 6,16, 0x09, "1W2W" },
|
||||
{ "bicd", 6,16, 0x0b, "1D2D" },
|
||||
{ "bicpsrb", 11,16, 0x17c, "1B" },
|
||||
{ "bicpsrw", 11,16, 0x17d, "1W" },
|
||||
{ "bispsrb", 11,16, 0x37c, "1B" },
|
||||
{ "bispsrw", 11,16, 0x37d, "1W" },
|
||||
{ "bpt", 8,8, 0xf2, "" },
|
||||
{ "br", 8,8, 0xea, "1p" },
|
||||
{ "bsr", 8,8, 0x02, "1p" },
|
||||
{ "caseb", 11,16, 0x77c, "1B" },
|
||||
{ "casew", 11,16, 0x77d, "1W" },
|
||||
{ "cased", 11,16, 0x77f, "1D" },
|
||||
{ "cbitb", 14,24, 0x084e, "1B2D" },
|
||||
{ "cbitw", 14,24, 0x094e, "1W2D" },
|
||||
{ "cbitd", 14,24, 0x0b4e, "1D2D" },
|
||||
{ "cbitib", 14,24, 0x0c4e, "1B2D" },
|
||||
{ "cbitiw", 14,24, 0x0d4e, "1W2D" },
|
||||
{ "cbitid", 14,24, 0x0f4e, "1D2D" },
|
||||
{ "checkb", 11,24, 0x0ee, "2A3B1r" },
|
||||
{ "checkw", 11,24, 0x1ee, "2A3B1r" },
|
||||
{ "checkd", 11,24, 0x3ee, "2A3D1r" },
|
||||
{ "cmpf", 14,24, 0x09be, "1F2F" },
|
||||
{ "cmpl", 14,24, 0x08be, "1L2L" },
|
||||
{ "cmpb", 6,16, 0x04, "1B2B" },
|
||||
{ "cmpw", 6,16, 0x05, "1W2W" },
|
||||
{ "cmpd", 6,16, 0x07, "1D2D" },
|
||||
{ "cmpmb", 14,24, 0x04ce, "1D2D3d" },
|
||||
{ "cmpmw", 14,24, 0x05ce, "1D2D3d" },
|
||||
{ "cmpmd", 14,24, 0x07ce, "1D2D3d" },
|
||||
{ "cmpqb", 7,16, 0x1c, "2B1q" },
|
||||
{ "cmpqw", 7,16, 0x1d, "2W1q" },
|
||||
{ "cmpqd", 7,16, 0x1f, "2D1q" },
|
||||
{ "cmpsb", 16,16, 0x040e, "1i" },
|
||||
{ "cmpsw", 16,16, 0x050e, "1i" },
|
||||
{ "cmpsd", 16,16, 0x070e, "1i" },
|
||||
{ "cmpst", 16,16, 0x840e, "1i" },
|
||||
{ "comb", 14,24, 0x344e, "1B2B" },
|
||||
{ "comw", 14,24, 0x354e, "1W2W" },
|
||||
{ "comd", 14,24, 0x374e, "1D2D" },
|
||||
{ "cvtp", 11,24, 0x036e, "2D3D1r" },
|
||||
{ "cxp", 8,8, 0x22, "1p" },
|
||||
{ "cxpd", 11,16, 0x07f, "1D" },
|
||||
{ "deib", 14,24, 0x2cce, "1B2W" },
|
||||
{ "deiw", 14,24, 0x2cce, "1W2D" },
|
||||
{ "deid", 14,24, 0x2cce, "1D2Q" },
|
||||
{ "dia", 8,8, 0xc2, "" },
|
||||
{ "divf", 14,24, 0x21be, "1F2F" },
|
||||
{ "divl", 14,24, 0x20be, "1L2L" },
|
||||
{ "divb", 14,24, 0x3cce, "1B2B" },
|
||||
{ "divw", 14,24, 0x3dce, "1W2W" },
|
||||
{ "divd", 14,24, 0x3fce, "1D2D" },
|
||||
{ "enter", 8,8, 0x82, "1i2d" },
|
||||
{ "exit", 8,8, 0x92, "1i" },
|
||||
{ "extb", 11,24, 0x02e, "2D3B1r4d" },
|
||||
{ "extw", 11,24, 0x12e, "2D3W1r4d" },
|
||||
{ "extd", 11,24, 0x32e, "2D3D1r4d" },
|
||||
{ "extsb", 14,24, 0x0cce, "1D2B3i" },
|
||||
{ "extsw", 14,24, 0x0dce, "1D2W3i" },
|
||||
{ "extsd", 14,24, 0x0fce, "1D2D3i" },
|
||||
{ "ffsb", 14,24, 0x046e, "1B2B" },
|
||||
{ "ffsw", 14,24, 0x056e, "1W2B" },
|
||||
{ "ffsd", 14,24, 0x076e, "1D2B" },
|
||||
{ "flag", 8,8, 0xd2, "" },
|
||||
{ "floorfb", 14,24, 0x3c3e, "1F2B" },
|
||||
{ "floorfw", 14,24, 0x3d3e, "1F2W" },
|
||||
{ "floorfd", 14,24, 0x3f3e, "1F2D" },
|
||||
{ "floorlb", 14,24, 0x383e, "1L2B" },
|
||||
{ "floorlw", 14,24, 0x393e, "1L2W" },
|
||||
{ "floorld", 14,24, 0x3b3e, "1L2D" },
|
||||
{ "ibitb", 14,24, 0x384e, "1B2D" },
|
||||
{ "ibitw", 14,24, 0x394e, "1W2D" },
|
||||
{ "ibitd", 14,24, 0x3b4e, "1D2D" },
|
||||
{ "indexb", 11,24, 0x42e, "2B3B1r" },
|
||||
{ "indexw", 11,24, 0x52e, "2W3W1r" },
|
||||
{ "indexd", 11,24, 0x72e, "2D3D1r" },
|
||||
{ "insb", 11,24, 0x0ae, "2B3B1r4d" },
|
||||
{ "insw", 11,24, 0x1ae, "2W3W1r4d" },
|
||||
{ "insd", 11,24, 0x3ae, "2D3D1r4d" },
|
||||
{ "inssb", 14,24, 0x08ce, "1B2D3i" },
|
||||
{ "inssw", 14,24, 0x09ce, "1W2D3i" },
|
||||
{ "inssd", 14,24, 0x0bce, "1D2D3i" },
|
||||
{ "jsr", 11,16, 0x67f, "1A" },
|
||||
{ "jump", 11,16, 0x27f, "1A" },
|
||||
{ "lfsr", 19,24, 0x00f3e,"1D" },
|
||||
{ "lmr", 15,24, 0x0b1e, "2D1q" },
|
||||
{ "lprb", 7,16, 0x6c, "2B1q" },
|
||||
{ "lprw", 7,16, 0x6d, "2W1q" },
|
||||
{ "lprd", 7,16, 0x6f, "2D1q" },
|
||||
{ "lshb", 14,24, 0x144e, "1B2B" },
|
||||
{ "lshw", 14,24, 0x154e, "1B2W" },
|
||||
{ "lshd", 14,24, 0x174e, "1B2D" },
|
||||
{ "meib", 14,24, 0x24ce, "1B2W" },
|
||||
{ "meiw", 14,24, 0x25ce, "1W2D" },
|
||||
{ "meid", 14,24, 0x27ce, "1D2Q" },
|
||||
{ "modb", 14,24, 0x38ce, "1B2B" },
|
||||
{ "modw", 14,24, 0x39ce, "1W2W" },
|
||||
{ "modd", 14,24, 0x3bce, "1D2D" },
|
||||
{ "movf", 14,24, 0x05be, "1F2F" },
|
||||
{ "movl", 14,24, 0x04be, "1L2L" },
|
||||
{ "movb", 6,16, 0x14, "1B2B" },
|
||||
{ "movw", 6,16, 0x15, "1W2W" },
|
||||
{ "movd", 6,16, 0x17, "1D2D" },
|
||||
{ "movbf", 14,24, 0x043e, "1B2F" },
|
||||
{ "movwf", 14,24, 0x053e, "1W2F" },
|
||||
{ "movdf", 14,24, 0x073e, "1D2F" },
|
||||
{ "movbl", 14,24, 0x003e, "1B2L" },
|
||||
{ "movwl", 14,24, 0x013e, "1W2L" },
|
||||
{ "movdl", 14,24, 0x033e, "1D2L" },
|
||||
{ "movfl", 14,24, 0x1b3e, "1F2L" },
|
||||
{ "movlf", 14,24, 0x163e, "1L2F" },
|
||||
{ "movmb", 14,24, 0x00ce, "1D2D3d" },
|
||||
{ "movmw", 14,24, 0x00de, "1D2D3d" },
|
||||
{ "movmd", 14,24, 0x00fe, "1D2D3d" },
|
||||
{ "movqb", 7,16, 0x5c, "2B1q" },
|
||||
{ "movqw", 7,16, 0x5d, "2B1q" },
|
||||
{ "movqd", 7,16, 0x5f, "2B1q" },
|
||||
{ "movsb", 16,16, 0x000e, "1i" },
|
||||
{ "movsw", 16,16, 0x010e, "1i" },
|
||||
{ "movsd", 16,16, 0x030e, "1i" },
|
||||
{ "movst", 16,16, 0x800e, "1i" },
|
||||
{ "movsub", 14,24, 0x0cae, "1A1A" },
|
||||
{ "movsuw", 14,24, 0x0dae, "1A1A" },
|
||||
{ "movsud", 14,24, 0x0fae, "1A1A" },
|
||||
{ "movusb", 14,24, 0x1cae, "1A1A" },
|
||||
{ "movusw", 14,24, 0x1dae, "1A1A" },
|
||||
{ "movusd", 14,24, 0x1fae, "1A1A" },
|
||||
{ "movxbd", 14,24, 0x1cce, "1B2D" },
|
||||
{ "movxwd", 14,24, 0x1dce, "1W2D" },
|
||||
{ "movxbw", 14,24, 0x10ce, "1B2W" },
|
||||
{ "movzbd", 14,24, 0x18ce, "1B2D" },
|
||||
{ "movzwd", 14,24, 0x19ce, "1W2D" },
|
||||
{ "movzbw", 14,24, 0x14ce, "1B2W" },
|
||||
{ "mulf", 14,24, 0x31be, "1F2F" },
|
||||
{ "mull", 14,24, 0x30be, "1L2L" },
|
||||
{ "mulb", 14,24, 0x20ce, "1B2B" },
|
||||
{ "mulw", 14,24, 0x21ce, "1W2W" },
|
||||
{ "muld", 14,24, 0x23ce, "1D2D" },
|
||||
{ "negf", 14,24, 0x15be, "1F2F" },
|
||||
{ "negl", 14,24, 0x14be, "1L2L" },
|
||||
{ "negb", 14,24, 0x204e, "1B2B" },
|
||||
{ "negw", 14,24, 0x214e, "1W2W" },
|
||||
{ "negd", 14,24, 0x234e, "1D2D" },
|
||||
{ "nop", 8,8, 0xa2, "" },
|
||||
{ "notb", 14,24, 0x244e, "1B2B" },
|
||||
{ "notw", 14,24, 0x254e, "1W2W" },
|
||||
{ "notd", 14,24, 0x274e, "1D2D" },
|
||||
{ "orb", 6,16, 0x18, "1B1B" },
|
||||
{ "orw", 6,16, 0x19, "1W1W" },
|
||||
{ "ord", 6,16, 0x1b, "1D1D" },
|
||||
{ "quob", 14,24, 0x30ce, "1B2B" },
|
||||
{ "quow", 14,24, 0x31ce, "1W2W" },
|
||||
{ "quod", 14,24, 0x33ce, "1D2D" },
|
||||
{ "rdval", 19,24, 0x0031e,"1A" },
|
||||
{ "remb", 14,24, 0x34ce, "1B2B" },
|
||||
{ "remw", 14,24, 0x35ce, "1W2W" },
|
||||
{ "remd", 14,24, 0x37ce, "1D2D" },
|
||||
{ "restore", 8,8, 0x72, "1i" },
|
||||
{ "ret", 8,8, 0x12, "1d" },
|
||||
{ "reti", 8,8, 0x52, "" },
|
||||
{ "rett", 8,8, 0x42, "" },
|
||||
{ "rotb", 14,24, 0x004e, "1B2B" },
|
||||
{ "rotw", 14,24, 0x014e, "1B2W" },
|
||||
{ "rotd", 14,24, 0x034e, "1B2D" },
|
||||
{ "roundfb", 14,24, 0x243e, "1F2B" },
|
||||
{ "roundfw", 14,24, 0x253e, "1F2W" },
|
||||
{ "roundfd", 14,24, 0x273e, "1F2D" },
|
||||
{ "roundlb", 14,24, 0x203e, "1L2B" },
|
||||
{ "roundlw", 14,24, 0x213e, "1L2W" },
|
||||
{ "roundld", 14,24, 0x233e, "1L2D" },
|
||||
{ "rxp", 8,8, 0x32, "1d" },
|
||||
{ "sCONDb", 7,16, 0x3c, "2B1q" },
|
||||
{ "sCONDw", 7,16, 0x3d, "2D1q" },
|
||||
{ "sCONDd", 7,16, 0x3f, "2D1q" },
|
||||
{ "save", 8,8, 0x62, "1i" },
|
||||
{ "sbitb", 14,24, 0x184e, "1B2A" },
|
||||
{ "sbitw", 14,24, 0x194e, "1W2A" },
|
||||
{ "sbitd", 14,24, 0x1b4e, "1D2A" },
|
||||
{ "sbitib", 14,24, 0x1c4e, "1B2A" },
|
||||
{ "sbitiw", 14,24, 0x1d4e, "1W2A" },
|
||||
{ "sbitid", 14,24, 0x1f4e, "1D2A" },
|
||||
{ "setcfg", 15,24, 0x0b0e, "5D1q" },
|
||||
{ "sfsr", 14,24, 0x673e, "5D1D" },
|
||||
{ "skpsb", 16,16, 0x0c0e, "1i" },
|
||||
{ "skpsw", 16,16, 0x0d0e, "1i" },
|
||||
{ "skpsd", 16,16, 0x0f0e, "1i" },
|
||||
{ "skpst", 16,16, 0x8c0e, "1i" },
|
||||
{ "smr", 15,24, 0x0f1e, "2D1q" },
|
||||
{ "sprb", 7,16, 0x2c, "2B1q" },
|
||||
{ "sprw", 7,16, 0x2d, "2W1q" },
|
||||
{ "sprd", 7,16, 0x2f, "2D1q" },
|
||||
{ "subf", 14,24, 0x11be, "1F2F" },
|
||||
{ "subl", 14,24, 0x10be, "1L2L" },
|
||||
{ "subb", 6,16, 0x20, "1B2B" },
|
||||
{ "subw", 6,16, 0x21, "1W2W" },
|
||||
{ "subd", 6,16, 0x23, "1D2D" },
|
||||
{ "subcb", 6,16, 0x30, "1B2B" },
|
||||
{ "subcw", 6,16, 0x31, "1W2W" },
|
||||
{ "subcd", 6,16, 0x33, "1D2D" },
|
||||
{ "subpb", 14,24, 0x2c4e, "1B2B" },
|
||||
{ "subpw", 14,24, 0x2d4e, "1W2W" },
|
||||
{ "subpd", 14,24, 0x2f4e, "1D2D" },
|
||||
#ifndef NS32K_SVC_IMMED_OPERANDS
|
||||
{ "svc", 8,8, 0xe2, "2i1i" }, /* not really, but unix uses it */
|
||||
#else
|
||||
{ "svc", 8,8, 0xe2, "" }, /* not really, but unix uses it */
|
||||
#endif
|
||||
{ "tbitb", 6,16, 0x34, "1B2A" },
|
||||
{ "tbitw", 6,16, 0x35, "1W2A" },
|
||||
{ "tbitd", 6,16, 0x37, "1D2A" },
|
||||
{ "truncfb", 14,24, 0x2c3e, "1F2B" },
|
||||
{ "truncfw", 14,24, 0x2d3e, "1F2W" },
|
||||
{ "truncfd", 14,24, 0x2f3e, "1F2D" },
|
||||
{ "trunclb", 14,24, 0x283e, "1L2B" },
|
||||
{ "trunclw", 14,24, 0x293e, "1L2W" },
|
||||
{ "truncld", 14,24, 0x2b3e, "1L2D" },
|
||||
{ "wait", 8,8, 0xb2, "" },
|
||||
{ "wrval", 19,24, 0x0071e,"1A" },
|
||||
{ "xorb", 6,16, 0x38, "1B2B" },
|
||||
{ "xorw", 6,16, 0x39, "1W2W" },
|
||||
{ "xord", 6,16, 0x3b, "1D2D" },
|
||||
}; /* notstrs */
|
||||
|
||||
/* end: ns32k.opcode.h */
|
||||
|
||||
#define MAX_ARGS 4
|
||||
#define ARG_LEN 50
|
|
@ -0,0 +1,457 @@
|
|||
/* Print 32000 instructions for GDB, the GNU debugger.
|
||||
Copyright (C) 1986,1988 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/* 32000 instructions are never longer than this. */
|
||||
#define MAXLEN 62
|
||||
|
||||
/* Number of elements in the opcode table. */
|
||||
#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
|
||||
|
||||
extern char *reg_names[];
|
||||
|
||||
#define NEXT_IS_ADDR '|'
|
||||
|
||||
/*
|
||||
* extract "count" bits starting "offset" bits
|
||||
* into buffer
|
||||
*/
|
||||
|
||||
int
|
||||
bit_extract (buffer, offset, count)
|
||||
char *buffer;
|
||||
int offset;
|
||||
int count;
|
||||
{
|
||||
int result;
|
||||
int mask;
|
||||
int bit;
|
||||
|
||||
buffer += offset >> 3;
|
||||
offset &= 7;
|
||||
bit = 1;
|
||||
result = 0;
|
||||
while (count--)
|
||||
{
|
||||
if ((*buffer & (1 << offset)))
|
||||
result |= bit;
|
||||
if (++offset == 8)
|
||||
{
|
||||
offset = 0;
|
||||
buffer++;
|
||||
}
|
||||
bit <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float
|
||||
fbit_extract (buffer, offset, count)
|
||||
{
|
||||
union {
|
||||
int ival;
|
||||
float fval;
|
||||
} foo;
|
||||
|
||||
foo.ival = bit_extract (buffer, offset, 32);
|
||||
return foo.fval;
|
||||
}
|
||||
|
||||
double
|
||||
dbit_extract (buffer, offset, count)
|
||||
{
|
||||
union {
|
||||
struct {int low, high; } ival;
|
||||
double dval;
|
||||
} foo;
|
||||
|
||||
foo.ival.low = bit_extract (buffer, offset, 32);
|
||||
foo.ival.high = bit_extract (buffer, offset+32, 32);
|
||||
return foo.dval;
|
||||
}
|
||||
|
||||
sign_extend (value, bits)
|
||||
{
|
||||
value = value & ((1 << bits) - 1);
|
||||
return (value & (1 << (bits-1))
|
||||
? value | (~((1 << bits) - 1))
|
||||
: value);
|
||||
}
|
||||
|
||||
flip_bytes (ptr, count)
|
||||
char *ptr;
|
||||
int count;
|
||||
{
|
||||
char tmp;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
tmp = *ptr;
|
||||
ptr[0] = ptr[count-1];
|
||||
ptr[count-1] = tmp;
|
||||
ptr++;
|
||||
count -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print the 32000 instruction at address MEMADDR in debugged memory,
|
||||
on STREAM. Returns length of the instruction, in bytes. */
|
||||
|
||||
int
|
||||
print_insn (memaddr, stream)
|
||||
CORE_ADDR memaddr;
|
||||
FILE *stream;
|
||||
{
|
||||
unsigned char buffer[MAXLEN];
|
||||
register int i;
|
||||
register unsigned char *p;
|
||||
register char *d;
|
||||
unsigned short first_word;
|
||||
int gen, disp;
|
||||
int ioffset; /* bits into instruction */
|
||||
int aoffset; /* bits into arguments */
|
||||
char arg_bufs[MAX_ARGS+1][ARG_LEN];
|
||||
int argnum;
|
||||
int maxarg;
|
||||
|
||||
read_memory (memaddr, buffer, MAXLEN);
|
||||
|
||||
first_word = *(unsigned short *) buffer;
|
||||
for (i = 0; i < NOPCODES; i++)
|
||||
if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
|
||||
== notstrs[i].detail.code)
|
||||
break;
|
||||
|
||||
/* Handle undefined instructions. */
|
||||
if (i == NOPCODES)
|
||||
{
|
||||
fprintf (stream, "0%o", buffer[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf (stream, "%s", notstrs[i].name);
|
||||
|
||||
ioffset = notstrs[i].detail.ibits;
|
||||
aoffset = notstrs[i].detail.ibits;
|
||||
d = notstrs[i].detail.args;
|
||||
|
||||
if (*d)
|
||||
{
|
||||
fputc ('\t', stream);
|
||||
|
||||
maxarg = 0;
|
||||
while (*d)
|
||||
{
|
||||
argnum = *d - '1';
|
||||
d++;
|
||||
if (argnum > maxarg && argnum < MAX_ARGS)
|
||||
maxarg = argnum;
|
||||
ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
|
||||
memaddr, arg_bufs[argnum]);
|
||||
d++;
|
||||
}
|
||||
for (argnum = 0; argnum <= maxarg; argnum++)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
char *ch, *index ();
|
||||
for (ch = arg_bufs[argnum]; *ch;)
|
||||
{
|
||||
if (*ch == NEXT_IS_ADDR)
|
||||
{
|
||||
++ch;
|
||||
addr = atoi (ch);
|
||||
print_address (addr, stream);
|
||||
while (*ch && *ch != NEXT_IS_ADDR)
|
||||
++ch;
|
||||
if (*ch)
|
||||
++ch;
|
||||
}
|
||||
else
|
||||
putc (*ch++, stream);
|
||||
}
|
||||
if (argnum < maxarg)
|
||||
fprintf (stream, ", ");
|
||||
}
|
||||
}
|
||||
return aoffset / 8;
|
||||
}
|
||||
|
||||
print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result)
|
||||
char d;
|
||||
int ioffset, *aoffsetp;
|
||||
char *buffer;
|
||||
CORE_ADDR addr;
|
||||
char *result;
|
||||
{
|
||||
int addr_mode;
|
||||
float Fvalue;
|
||||
double Lvalue;
|
||||
int Ivalue;
|
||||
int disp1, disp2;
|
||||
int index;
|
||||
|
||||
switch (d)
|
||||
{
|
||||
case 'F':
|
||||
case 'L':
|
||||
case 'B':
|
||||
case 'W':
|
||||
case 'D':
|
||||
case 'A':
|
||||
addr_mode = bit_extract (buffer, ioffset-5, 5);
|
||||
ioffset -= 5;
|
||||
switch (addr_mode)
|
||||
{
|
||||
case 0x0: case 0x1: case 0x2: case 0x3:
|
||||
case 0x4: case 0x5: case 0x6: case 0x7:
|
||||
switch (d)
|
||||
{
|
||||
case 'F':
|
||||
case 'L':
|
||||
sprintf (result, "f%d", addr_mode);
|
||||
break;
|
||||
default:
|
||||
sprintf (result, "r%d", addr_mode);
|
||||
}
|
||||
break;
|
||||
case 0x8: case 0x9: case 0xa: case 0xb:
|
||||
case 0xc: case 0xd: case 0xe: case 0xf:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
|
||||
break;
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
disp2 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "%d(%d(%s))", disp2, disp1,
|
||||
addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
|
||||
break;
|
||||
case 0x13:
|
||||
sprintf (result, "reserved");
|
||||
break;
|
||||
case 0x14:
|
||||
switch (d)
|
||||
{
|
||||
case 'B':
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 8);
|
||||
Ivalue = sign_extend (Ivalue, 8);
|
||||
*aoffsetp += 8;
|
||||
sprintf (result, "$%d", Ivalue);
|
||||
break;
|
||||
case 'W':
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 16);
|
||||
flip_bytes (&Ivalue, 2);
|
||||
*aoffsetp += 16;
|
||||
Ivalue = sign_extend (Ivalue, 16);
|
||||
sprintf (result, "$%d", Ivalue);
|
||||
break;
|
||||
case 'D':
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 32);
|
||||
flip_bytes (&Ivalue, 4);
|
||||
*aoffsetp += 32;
|
||||
sprintf (result, "$%d", Ivalue);
|
||||
break;
|
||||
case 'A':
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 32);
|
||||
flip_bytes (&Ivalue, 4);
|
||||
*aoffsetp += 32;
|
||||
sprintf (result, "$|%d|", Ivalue);
|
||||
break;
|
||||
case 'F':
|
||||
Fvalue = fbit_extract (buffer, *aoffsetp, 32);
|
||||
flip_bytes (&Fvalue, 4);
|
||||
*aoffsetp += 32;
|
||||
sprintf (result, "$%g", Fvalue);
|
||||
break;
|
||||
case 'L':
|
||||
Lvalue = dbit_extract (buffer, *aoffsetp, 64);
|
||||
flip_bytes (&Lvalue, 8);
|
||||
*aoffsetp += 64;
|
||||
sprintf (result, "$%g", Lvalue);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x15:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "@|%d|", disp1);
|
||||
break;
|
||||
case 0x16:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
disp2 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "EXT(%d) + %d", disp1, disp2);
|
||||
break;
|
||||
case 0x17:
|
||||
sprintf (result, "tos");
|
||||
break;
|
||||
case 0x18:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "%d(fp)", disp1);
|
||||
break;
|
||||
case 0x19:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "%d(sp)", disp1);
|
||||
break;
|
||||
case 0x1a:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "%d(sb)", disp1);
|
||||
break;
|
||||
case 0x1b:
|
||||
disp1 = get_displacement (buffer, aoffsetp);
|
||||
sprintf (result, "|%d|", addr + disp1);
|
||||
break;
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
index = bit_extract (buffer, *aoffsetp, 8);
|
||||
*aoffsetp += 8;
|
||||
print_insn_arg (d, *aoffsetp, aoffsetp, buffer, addr,
|
||||
result);
|
||||
{
|
||||
static char *ind[] = {"b", "w", "d", "q"};
|
||||
char *off;
|
||||
|
||||
off = result + strlen (result);
|
||||
sprintf (off, "[r%d:%s]", index & 7,
|
||||
ind[addr_mode & 3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
Ivalue = bit_extract (buffer, ioffset-4, 4);
|
||||
Ivalue = sign_extend (Ivalue, 4);
|
||||
sprintf (result, "%d", Ivalue);
|
||||
ioffset -= 4;
|
||||
break;
|
||||
case 'r':
|
||||
Ivalue = bit_extract (buffer, ioffset-3, 3);
|
||||
sprintf (result, "r%d", Ivalue&7);
|
||||
ioffset -= 3;
|
||||
break;
|
||||
case 'd':
|
||||
sprintf (result, "%d", get_displacement (buffer, aoffsetp));
|
||||
break;
|
||||
case 'p':
|
||||
sprintf (result, "%c%d%c", NEXT_IS_ADDR,
|
||||
addr + get_displacement (buffer, aoffsetp),
|
||||
NEXT_IS_ADDR);
|
||||
break;
|
||||
case 'i':
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 8);
|
||||
*aoffsetp += 8;
|
||||
sprintf (result, "0x%x", Ivalue);
|
||||
break;
|
||||
}
|
||||
return ioffset;
|
||||
}
|
||||
|
||||
get_displacement (buffer, aoffsetp)
|
||||
char *buffer;
|
||||
int *aoffsetp;
|
||||
{
|
||||
int Ivalue;
|
||||
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 8);
|
||||
switch (Ivalue & 0xc0)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x40:
|
||||
Ivalue = sign_extend (Ivalue, 7);
|
||||
*aoffsetp += 8;
|
||||
break;
|
||||
case 0x80:
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 16);
|
||||
flip_bytes (&Ivalue, 2);
|
||||
Ivalue = sign_extend (Ivalue, 14);
|
||||
*aoffsetp += 16;
|
||||
break;
|
||||
case 0xc0:
|
||||
Ivalue = bit_extract (buffer, *aoffsetp, 32);
|
||||
flip_bytes (&Ivalue, 4);
|
||||
Ivalue = sign_extend (Ivalue, 30);
|
||||
*aoffsetp += 32;
|
||||
break;
|
||||
}
|
||||
return Ivalue;
|
||||
}
|
||||
|
||||
/* Return the number of locals in the current frame given a pc
|
||||
pointing to the enter instruction. This is used in the macro
|
||||
FRAME_FIND_SAVED_REGS. */
|
||||
|
||||
ns32k_localcount (enter_pc)
|
||||
CORE_ADDR enter_pc;
|
||||
{
|
||||
unsigned char localtype;
|
||||
int localcount;
|
||||
|
||||
localtype = read_memory_integer (enter_pc+2, 1);
|
||||
if ((localtype & 0x80) == 0)
|
||||
localcount = localtype;
|
||||
else if ((localtype & 0xc0) == 0x80)
|
||||
localcount = (((localtype & 0x3f) << 8)
|
||||
| (read_memory_integer (enter_pc+3, 1) & 0xff));
|
||||
else
|
||||
localcount = (((localtype & 0x3f) << 24)
|
||||
| ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
|
||||
| ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
|
||||
| (read_memory_integer (enter_pc+5, 1) & 0xff));
|
||||
return localcount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the address of the enter opcode for the function
|
||||
* containing PC, if there is an enter for the function,
|
||||
* and if the pc is between the enter and exit.
|
||||
* Returns positive address if pc is between enter/exit,
|
||||
* 1 if pc before enter or after exit, 0 otherwise.
|
||||
*/
|
||||
|
||||
CORE_ADDR
|
||||
ns32k_get_enter_addr (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
CORE_ADDR enter_addr;
|
||||
unsigned char op;
|
||||
|
||||
if (ABOUT_TO_RETURN (pc))
|
||||
return 1; /* after exit */
|
||||
|
||||
enter_addr = get_pc_function_start (pc);
|
||||
|
||||
if (pc == enter_addr)
|
||||
return 1; /* before enter */
|
||||
|
||||
op = read_memory_integer (enter_addr, 1);
|
||||
|
||||
if (op != 0x82)
|
||||
return 0; /* function has no enter/exit */
|
||||
|
||||
return enter_addr; /* pc is between enter and exit */
|
||||
}
|
|
@ -57,9 +57,9 @@ Mere aggregation of another unrelated program with this program (or its
|
|||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the terms
|
||||
of Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
3. You may copy and distribute this program or any portion of it in
|
||||
compiled, executable or object code form under the terms of Paragraphs
|
||||
1 and 2 above provided that you do the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
|
@ -111,13 +111,30 @@ what you give them. Help stamp out software-hoarding! */
|
|||
#define POINTER char *
|
||||
#endif
|
||||
|
||||
/* Determine default alignment. */
|
||||
struct fooalign {char x; double d;};
|
||||
#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
|
||||
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
|
||||
But in fact it might be less smart and round addresses to as much as
|
||||
DEFAULT_ROUNDING. So we prepare for it to do that. */
|
||||
union fooround {long x; double d;};
|
||||
#define DEFAULT_ROUNDING (sizeof (union fooround))
|
||||
|
||||
/* When we copy a long block of data, this is the unit to do it with.
|
||||
On some machines, copying successive ints does not work;
|
||||
in such a case, redefine COPYING_UNIT to `long' (if that works)
|
||||
or `char' as a last resort. */
|
||||
#ifndef COPYING_UNIT
|
||||
#define COPYING_UNIT int
|
||||
#endif
|
||||
|
||||
/* The non-GNU-C macros copy the obstack into this global variable
|
||||
to avoid multiple evaluation. */
|
||||
|
||||
struct obstack *_obstack;
|
||||
|
||||
/* Initialize an obstack H for use. Specify chunk size SIZE.
|
||||
Objects start on multiples of ALIGNMENT.
|
||||
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
|
||||
Objects start on multiples of ALIGNMENT (0 means use default).
|
||||
CHUNKFUN is the function to use to allocate chunks,
|
||||
and FREEFUN the function to free them. */
|
||||
|
||||
|
@ -129,7 +146,21 @@ _obstack_begin (h, size, alignment, chunkfun, freefun)
|
|||
POINTER (*chunkfun) ();
|
||||
void (*freefun) ();
|
||||
{
|
||||
register struct _obstack_chunk* chunk; /* points to new chunk */
|
||||
register struct _obstack_chunk* chunk; /* points to new chunk */
|
||||
|
||||
if (alignment == 0)
|
||||
alignment = DEFAULT_ALIGNMENT;
|
||||
if (size == 0)
|
||||
/* Default size is what GNU malloc can fit in a 4096-byte block.
|
||||
Pick a number small enough that when rounded up to DEFAULT_ROUNDING
|
||||
it is still smaller than 4096 - 4. */
|
||||
{
|
||||
int extra = 4;
|
||||
if (extra < DEFAULT_ROUNDING)
|
||||
extra = DEFAULT_ROUNDING;
|
||||
size = 4096 - extra;
|
||||
}
|
||||
|
||||
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
|
||||
h->freefun = freefun;
|
||||
h->chunk_size = size;
|
||||
|
@ -172,8 +203,10 @@ _obstack_newchunk (h, length)
|
|||
/* Move the existing object to the new chunk.
|
||||
Word at a time is fast and is safe because these
|
||||
structures are aligned at least that much. */
|
||||
for (i = (obj_size + sizeof (int) - 1) / sizeof (int); i >= 0; i--)
|
||||
((int *)new_chunk->contents)[i] = ((int *)h->object_base)[i];
|
||||
for (i = (obj_size + sizeof (COPYING_UNIT) - 1) / sizeof (COPYING_UNIT) - 1;
|
||||
i >= 0; i--)
|
||||
((COPYING_UNIT *)new_chunk->contents)[i]
|
||||
= ((COPYING_UNIT *)h->object_base)[i];
|
||||
|
||||
h->object_base = new_chunk->contents;
|
||||
h->next_free = h->object_base + obj_size;
|
||||
|
@ -214,6 +247,10 @@ _obstack_free (h, obj)
|
|||
abort ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* These are now turned off because the applications do not use it
|
||||
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
|
||||
|
||||
/* Now define the functional versions of the obstack macros.
|
||||
Define them to simply use the corresponding macros to do the job. */
|
||||
|
||||
|
@ -322,3 +359,5 @@ POINTER (obstack_copy0) (obstack, pointer, length)
|
|||
}
|
||||
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#endif /* 0 */
|
||||
|
|
102
gdb/obstack.h
102
gdb/obstack.h
|
@ -1,5 +1,5 @@
|
|||
/* obstack.h - object stack macros
|
||||
Copyright (C) 1986, 1988 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
|
@ -30,7 +30,7 @@ DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
|
|||
1. You may copy and distribute verbatim copies of this source file
|
||||
as you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy a valid copyright notice "Copyright
|
||||
(C) 1988 Free Software Foundation, Inc."; and include following the
|
||||
(C) 1988 Free Software Foundation, Inc."; and include following the
|
||||
copyright notice a verbatim copy of the above disclaimer of warranty
|
||||
and of this License. You may charge a distribution fee for the
|
||||
physical act of transferring a copy.
|
||||
|
@ -57,9 +57,9 @@ Mere aggregation of another unrelated program with this program (or its
|
|||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute this program (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the terms
|
||||
of Paragraphs 1 and 2 above provided that you also do one of the following:
|
||||
3. You may copy and distribute this program or any portion of it in
|
||||
compiled, executable or object code form under the terms of Paragraphs
|
||||
1 and 2 above provided that you do the following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
|
@ -191,9 +191,42 @@ Summary:
|
|||
#ifndef __OBSTACKS__
|
||||
#define __OBSTACKS__
|
||||
|
||||
/* We use subtraction of (char *)0 instead of casting to int
|
||||
because on word-addressable machines a simple cast to int
|
||||
may ignore the byte-within-word field of the pointer. */
|
||||
|
||||
#ifndef __PTR_TO_INT
|
||||
#define __PTR_TO_INT(P) ((P) - (char *)0)
|
||||
#endif
|
||||
|
||||
#ifndef __INT_TO_PTR
|
||||
#define __INT_TO_PTR(P) ((P) + (char *)0)
|
||||
#endif
|
||||
|
||||
struct _obstack_chunk /* Lives at front of each chunk. */
|
||||
{
|
||||
char *limit; /* 1 past end of this chunk */
|
||||
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
|
||||
char contents[4]; /* objects begin here */
|
||||
};
|
||||
|
||||
struct obstack /* control current object in current chunk */
|
||||
{
|
||||
long chunk_size; /* preferred size to allocate chunks in */
|
||||
struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
|
||||
char *object_base; /* address of object we are building */
|
||||
char *next_free; /* where to add next char to current object */
|
||||
char *chunk_limit; /* address of char after current chunk */
|
||||
int temp; /* Temporary for some macros. */
|
||||
int alignment_mask; /* Mask of alignment for each object. */
|
||||
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
|
||||
void (*freefun) (); /* User's function to free a chunk. */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
|
||||
/* Do the function-declarations before defining the macros. */
|
||||
/* Do the function-declarations after the structs
|
||||
but before defining the macros. */
|
||||
|
||||
void obstack_init (struct obstack *obstack);
|
||||
|
||||
|
@ -219,8 +252,8 @@ int obstack_room (struct obstack *obstack);
|
|||
void obstack_1grow_fast (struct obstack *obstack, int data_char);
|
||||
void obstack_blank_fast (struct obstack *obstack, int size);
|
||||
|
||||
void * object_base (struct obstack *obstack);
|
||||
void * object_next_free (struct obstack *obstack);
|
||||
void * obstack_base (struct obstack *obstack);
|
||||
void * obstack_next_free (struct obstack *obstack);
|
||||
int obstack_alignment_mask (struct obstack *obstack);
|
||||
int obstack_chunk_size (struct obstack *obstack);
|
||||
|
||||
|
@ -229,26 +262,6 @@ int obstack_chunk_size (struct obstack *obstack);
|
|||
/* Non-ANSI C cannot really support alternative functions for these macros,
|
||||
so we do not declare them. */
|
||||
|
||||
struct _obstack_chunk /* Lives at front of each chunk. */
|
||||
{
|
||||
char *limit; /* 1 past end of this chunk */
|
||||
struct _obstack_chunk *prev; /* address of prior chunk or NULL */
|
||||
char contents[4]; /* objects begin here */
|
||||
};
|
||||
|
||||
struct obstack /* control current object in current chunk */
|
||||
{
|
||||
long chunk_size; /* preferred size to allocate chunks in */
|
||||
struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
|
||||
char *object_base; /* address of object we are building */
|
||||
char *next_free; /* where to add next char to current object */
|
||||
char *chunk_limit; /* address of char after current chunk */
|
||||
int temp; /* Temporary for some macros. */
|
||||
int alignment_mask; /* Mask of alignment for each object. */
|
||||
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
|
||||
void (*freefun) (); /* User's function to free a chunk. */
|
||||
};
|
||||
|
||||
/* Pointer to beginning of object being allocated or to be allocated next.
|
||||
Note that this might not be the final address of the object
|
||||
because a new chunk might be needed to hold the final size. */
|
||||
|
@ -268,23 +281,20 @@ struct obstack /* control current object in current chunk */
|
|||
#define obstack_alignment_mask(h) ((h)->alignment_mask)
|
||||
|
||||
#define obstack_init(h) \
|
||||
_obstack_begin ((h), 4096 - 4, 4, obstack_chunk_alloc, obstack_chunk_free)
|
||||
_obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
|
||||
|
||||
#define obstack_begin(h, size) \
|
||||
_obstack_begin ((h), (size), 4, obstack_chunk_alloc, obstack_chunk_free)
|
||||
_obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
|
||||
|
||||
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
|
||||
|
||||
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
|
||||
|
||||
#if defined (__GNU__) && defined (__STDC__)
|
||||
#ifdef __GNUC__
|
||||
|
||||
/* For GNU C we can define these macros to compute all args only once
|
||||
without using a global variable.
|
||||
Also, we can avoid using the `temp' slot, to make faster code.
|
||||
|
||||
By checking both __GNU__ and __STDC__, we can make sure
|
||||
both GNU language extensions and ANSI preprocessing are available. */
|
||||
Also, we can avoid using the `temp' slot, to make faster code. */
|
||||
|
||||
#define obstack_object_size(OBSTACK) \
|
||||
({ struct obstack *__o = (OBSTACK); \
|
||||
|
@ -347,11 +357,11 @@ struct obstack /* control current object in current chunk */
|
|||
({ struct obstack *__o = (OBSTACK); \
|
||||
void *value = (void *) __o->object_base; \
|
||||
__o->next_free \
|
||||
= (char*)((int)(__o->next_free+__o->alignment_mask) \
|
||||
& ~ (__o->alignment_mask)); \
|
||||
= __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
|
||||
& ~ (__o->alignment_mask)); \
|
||||
((__o->next_free - (char *)__o->chunk \
|
||||
> __o->chunk_limit - (char *)__o->chunk) \
|
||||
? __o->next_free = __o->chunk_limit : 0); \
|
||||
? (__o->next_free = __o->chunk_limit) : 0); \
|
||||
__o->object_base = __o->next_free; \
|
||||
value; })
|
||||
|
||||
|
@ -362,7 +372,7 @@ struct obstack /* control current object in current chunk */
|
|||
__o->next_free = __o->object_base = __obj; \
|
||||
else (obstack_free) (__o, __obj); })
|
||||
|
||||
#else /* not __GNU__ */
|
||||
#else /* not __GNUC__ */
|
||||
|
||||
/* The non-GNU macros copy the obstack-pointer into this global variable
|
||||
to avoid multiple evaluation. */
|
||||
|
@ -411,15 +421,15 @@ extern struct obstack *_obstack;
|
|||
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
|
||||
|
||||
#define obstack_finish(h) \
|
||||
( (h)->temp = (int) (h)->object_base, \
|
||||
( (h)->temp = __PTR_TO_INT ((h)->object_base), \
|
||||
(h)->next_free \
|
||||
= (char*)((int)((h)->next_free+(h)->alignment_mask) \
|
||||
& ~ ((h)->alignment_mask)), \
|
||||
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
|
||||
& ~ ((h)->alignment_mask)), \
|
||||
(((h)->next_free - (char *)(h)->chunk \
|
||||
> (h)->chunk_limit - (char *)(h)->chunk) \
|
||||
? (h)->next_free = (h)->chunk_limit : 0), \
|
||||
? ((h)->next_free = (h)->chunk_limit) : 0), \
|
||||
(h)->object_base = (h)->next_free, \
|
||||
(char *) (h)->temp)
|
||||
__INT_TO_PTR ((h)->temp))
|
||||
|
||||
#ifdef __STDC__
|
||||
#define obstack_free(h,obj) \
|
||||
|
@ -427,7 +437,7 @@ extern struct obstack *_obstack;
|
|||
(((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
|
||||
? (int) ((h)->next_free = (h)->object_base \
|
||||
= (h)->temp + (char *) (h)->chunk) \
|
||||
: (int) (obstack_free) ((h), (h)->temp + (char *) (h)->chunk)))
|
||||
: ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
|
||||
#else
|
||||
#define obstack_free(h,obj) \
|
||||
( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
|
||||
|
@ -437,7 +447,7 @@ extern struct obstack *_obstack;
|
|||
: (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
|
||||
#endif
|
||||
|
||||
#endif /* not __GNU__ */
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
#endif /* not __OBSTACKS__ */
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
478
gdb/param.h
478
gdb/param.h
|
@ -1 +1,477 @@
|
|||
#include "m-sun3.h"
|
||||
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#ifndef sun3
|
||||
#define sun3
|
||||
#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) \
|
||||
{ register int op = read_memory_integer (pc, 2); \
|
||||
if (op == 0047126) \
|
||||
pc += 4; /* Skip link #word */ \
|
||||
else if (op == 0044016) \
|
||||
pc += 6; /* Skip link #long */ \
|
||||
}
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't go through the frames for this because on some machines
|
||||
the new frame is not set up until the new function executes
|
||||
some instructions. */
|
||||
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
read_memory_integer (read_register (SP_REGNUM), 4)
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR 0xf000000
|
||||
|
||||
/* Stack grows downward. */
|
||||
|
||||
#define INNER_THAN <
|
||||
|
||||
/* Sequence of bytes for breakpoint instruction. */
|
||||
|
||||
#define BREAKPOINT {0x4e, 0x4f}
|
||||
|
||||
/* Amount PC must be decremented by after a breakpoint.
|
||||
This is often the number of bytes in BREAKPOINT
|
||||
but not always. */
|
||||
|
||||
#define DECR_PC_AFTER_BREAK 2
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
|
||||
|
||||
/* Return 1 if P points to an invalid floating point value. */
|
||||
|
||||
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
|
||||
|
||||
/* Say how long (ordinary) registers are. */
|
||||
|
||||
#define REGISTER_TYPE long
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 31
|
||||
|
||||
/* 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" }
|
||||
|
||||
/* Register numbers of various important registers.
|
||||
Note that some of these values are "real" register numbers,
|
||||
and correspond to the general registers of the machine,
|
||||
and some are "phony" register numbers which are too large
|
||||
to be actual register numbers as far as the user is concerned
|
||||
but do serve to get the desired values when passed to read_register. */
|
||||
|
||||
#define FP_REGNUM 14 /* Contains address of executing stack frame */
|
||||
#define SP_REGNUM 15 /* Contains address of top of stack */
|
||||
#define PS_REGNUM 16 /* Contains processor status */
|
||||
#define PC_REGNUM 17 /* Contains program counter */
|
||||
#define FP0_REGNUM 18 /* Floating point register 0 */
|
||||
#define FPC_REGNUM 26 /* 68881 control register */
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
#define REGISTER_BYTES (16*4+8*12+8+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))
|
||||
|
||||
/* Enable use of alternate code to read and write registers. */
|
||||
|
||||
#define NEW_SUN_PTRACE
|
||||
|
||||
/* Enable use of alternate code for Sun's format of core dump file. */
|
||||
|
||||
#define NEW_SUN_CORE
|
||||
|
||||
/* Do implement the attach and detach commands. */
|
||||
|
||||
#define ATTACH_DETACH
|
||||
|
||||
/* It is safe to look for symsegs on a Sun, because Sun's ld
|
||||
does not screw up with random garbage at end of file. */
|
||||
|
||||
#define READ_GDB_SYMSEGS
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
|
||||
/* FRAME_CHAIN takes a frame's nominal address
|
||||
and produces the frame's chain-pointer.
|
||||
|
||||
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
|
||||
and produces the nominal address of the caller frame.
|
||||
|
||||
However, if FRAME_CHAIN_VALID returns zero,
|
||||
it means the given frame is the outermost one and has no caller.
|
||||
In that case, FRAME_CHAIN_COMBINE is not used. */
|
||||
|
||||
/* In the case of the Sun, the frame's nominal address
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 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)
|
||||
|
||||
/* Set VAL to the number of args passed to frame described by FI.
|
||||
Can set VAL to -1, meaning no way to tell. */
|
||||
|
||||
/* We can't tell how many args there are
|
||||
now that the C compiler delays popping them. */
|
||||
#define FRAME_NUM_ARGS(val,fi) (val = -1)
|
||||
|
||||
#if 0
|
||||
#define FRAME_NUM_ARGS(val, fi) \
|
||||
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.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
|
||||
|
||||
/* Put here the code to store, into a struct frame_saved_regs,
|
||||
the addresses of the saved registers of frame described by FRAME_INFO.
|
||||
This includes special registers such as pc and fp saved in special
|
||||
ways in the stack frame. sp is even more special:
|
||||
the address we return for it IS the sp for the next frame. */
|
||||
|
||||
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
|
||||
{ register int regnum; \
|
||||
register int regmask; \
|
||||
register CORE_ADDR next_addr; \
|
||||
register CORE_ADDR pc; \
|
||||
int nextinsn; \
|
||||
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
|
||||
if ((frame_info).pc >= (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
|
||||
&& (frame_info).pc <= (frame_info).frame) \
|
||||
{ next_addr = (frame_info).frame; \
|
||||
pc = (frame_info).frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
|
||||
else \
|
||||
{ pc = get_pc_function_start ((frame_info).pc); \
|
||||
/* Verify we have a link a6 instruction next; \
|
||||
if not we lose. If we win, find the address above the saved \
|
||||
regs using the amount of storage from the link instruction. */\
|
||||
if (044016 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 4), pc+=4; \
|
||||
else if (047126 == read_memory_integer (pc, 2)) \
|
||||
next_addr = (frame_info).frame + read_memory_integer (pc += 2, 2), pc+=2; \
|
||||
else goto lose; \
|
||||
/* If have an addal #-n, sp next, adjust next_addr. */ \
|
||||
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
|
||||
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
|
||||
} \
|
||||
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
/* But before that can come an fmovem. Check for it. */ \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf227 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xe000) \
|
||||
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
if (0044327 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
|
||||
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
|
||||
else if (0044347 == read_memory_integer (pc, 2)) \
|
||||
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
|
||||
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
|
||||
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
|
||||
/* fmovemx to index of sp may follow. */ \
|
||||
regmask = read_memory_integer (pc + 2, 2); \
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2); \
|
||||
if (0xf236 == nextinsn \
|
||||
&& (regmask & 0xff00) == 0xf000) \
|
||||
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
|
||||
if (regmask & 1) \
|
||||
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
|
||||
regmask = read_memory_integer (pc + 2, 2); } \
|
||||
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
|
||||
if (0x426742e7 == read_memory_integer (pc, 4)) \
|
||||
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
|
||||
lose: ; \
|
||||
(frame_saved_regs).regs[SP_REGNUM] = (frame_info).frame + 8; \
|
||||
(frame_saved_regs).regs[FP_REGNUM] = (frame_info).frame; \
|
||||
(frame_saved_regs).regs[PC_REGNUM] = (frame_info).frame + 4; \
|
||||
}
|
||||
|
||||
/* Things needed for making the inferior call functions. */
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
#define PUSH_DUMMY_FRAME \
|
||||
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
|
||||
register int regnum; \
|
||||
char raw_buffer[12]; \
|
||||
sp = push_word (sp, read_register (PC_REGNUM)); \
|
||||
sp = push_word (sp, read_register (FP_REGNUM)); \
|
||||
write_register (FP_REGNUM, sp); \
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
|
||||
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
|
||||
sp = push_bytes (sp, raw_buffer, 12); } \
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
|
||||
sp = push_word (sp, read_register (regnum)); \
|
||||
sp = push_word (sp, read_register (PS_REGNUM)); \
|
||||
write_register (SP_REGNUM, sp); }
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
#define POP_FRAME \
|
||||
{ register 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)); }
|
||||
|
||||
/* This sequence of words is the instructions
|
||||
fmovem 0xff,-(sp)
|
||||
moveml 0xfffc,-(sp)
|
||||
clrw -(sp)
|
||||
movew ccr,-(sp)
|
||||
/..* The arguments are pushed at this point by GDB;
|
||||
no code is needed in the dummy for this.
|
||||
The CALL_DUMMY_START_OFFSET gives the position of
|
||||
the following jsr instruction. *../
|
||||
jsr @#32323232
|
||||
addl #69696969,sp
|
||||
trap #15
|
||||
nop
|
||||
Note this is 28 bytes.
|
||||
We actually start executing at the jsr, since the pushing of the
|
||||
registers is done by PUSH_DUMMY_FRAME. If this were real code,
|
||||
the arguments for the function called by the jsr would be pushed
|
||||
between the moveml and the jsr, and we could allow it to execute through.
|
||||
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
|
||||
and we cannot allow the moveml to push the registers again lest they be
|
||||
taken for the arguments. */
|
||||
|
||||
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
|
||||
|
||||
#define CALL_DUMMY_LENGTH 28
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 12
|
||||
|
||||
/* Insert the specified number of args and function address
|
||||
into a call sequence of the above form stored at DUMMYNAME. */
|
||||
|
||||
#define FIX_CALL_DUMMY(dummyname, 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 ("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"); }
|
||||
|
|
126
gdb/parent.c
126
gdb/parent.c
|
@ -1,126 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
class math_stuff
|
||||
{
|
||||
char name[40];
|
||||
int value;
|
||||
|
||||
public:
|
||||
|
||||
void bla();
|
||||
|
||||
math_stuff(char*);
|
||||
|
||||
~math_stuff();
|
||||
|
||||
void add(int);
|
||||
|
||||
void print_value(char*);
|
||||
};
|
||||
|
||||
void math_stuff::bla()
|
||||
{
|
||||
printf("bla\n");
|
||||
}
|
||||
|
||||
math_stuff::math_stuff(char* new_name)
|
||||
{
|
||||
sprintf((char *)this->name,(char *)"MATH_STUFF_%s",new_name);
|
||||
value = 0;
|
||||
}
|
||||
|
||||
math_stuff::~math_stuff()
|
||||
{
|
||||
printf((char *)"Deleting MATH_STUFF instance '%s'\n",this->name);
|
||||
}
|
||||
|
||||
void math_stuff::add(int x)
|
||||
{
|
||||
this->value += x;
|
||||
}
|
||||
|
||||
void math_stuff::print_value(char *where)
|
||||
{
|
||||
printf((char *)"current value of '%s' at '%s' = %d\n", this->name, where, this->value);
|
||||
}
|
||||
|
||||
class derived : public math_stuff
|
||||
{
|
||||
char *dname;
|
||||
int val;
|
||||
|
||||
public:
|
||||
math_stuff stuff;
|
||||
derived(char*);
|
||||
~derived();
|
||||
void print_all(char*);
|
||||
};
|
||||
|
||||
derived::derived(char *der_name)
|
||||
: ((char *)"hello, world!"), stuff("derived stuff"), val(10)
|
||||
{
|
||||
printf((char *)"derived name = %s\n", der_name);
|
||||
dname = der_name;
|
||||
stuff.add(6);
|
||||
stuff.print_value ((char *)"grind");
|
||||
}
|
||||
|
||||
derived::~derived()
|
||||
{
|
||||
printf ((char *)"Good bye! \n");
|
||||
}
|
||||
|
||||
derived::print_all(char *msg)
|
||||
{
|
||||
printf((char *)"Here's the lowdown:\n");
|
||||
printf((char *)"My name is %s\n", dname);
|
||||
printf((char *)"My value = %d\n", val);
|
||||
stuff.print_value ((char *)"low");
|
||||
this->print_value((char *)"down");
|
||||
printf((char *)"That's all you get tonight.\n\n");
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
int pid;
|
||||
int i;
|
||||
|
||||
pid = vfork();
|
||||
if (pid > 0)
|
||||
printf(" the inferior pid of the child is %d\n",pid);
|
||||
if (pid == 0)
|
||||
{
|
||||
/* execl ("/bin/sh", "sh", "-c",argv[1],0);*/
|
||||
|
||||
math_stuff* a;
|
||||
derived* d;
|
||||
math_stuff b $ (" no gnus are good gnus ");
|
||||
int child;
|
||||
child = getpid();
|
||||
printf( " the child from parent.c is %d\n",child);
|
||||
ptrace (0);
|
||||
|
||||
a = new math_stuff((char *)"a");
|
||||
|
||||
d = new derived((char *)"two words");
|
||||
|
||||
a->add(2);
|
||||
a->add(4);
|
||||
a->add(5);
|
||||
a->print_value((char *)"here");
|
||||
a->add(7);
|
||||
a->print_value((char *)"there");
|
||||
a->add(3);
|
||||
a->add(1);
|
||||
a->print_value((char *)"end");
|
||||
|
||||
d->print_all ((char *)"all");
|
||||
|
||||
delete a;
|
||||
delete d;
|
||||
exit(0);
|
||||
}
|
||||
i = 5;
|
||||
i = 6;
|
||||
i = 7;
|
||||
}
|
770
gdb/pinsn.c
770
gdb/pinsn.c
|
@ -1 +1,769 @@
|
|||
#include "m68k-pinsn.c"
|
||||
/* Print m68k instructions for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/* 68k instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 22
|
||||
|
||||
/* Number of elements in the opcode table. */
|
||||
#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
|
||||
|
||||
extern char *reg_names[];
|
||||
char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
|
||||
"fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
|
||||
|
||||
static unsigned char *print_insn_arg ();
|
||||
static unsigned char *print_indexed ();
|
||||
static void print_base ();
|
||||
static int fetch_arg ();
|
||||
|
||||
#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
|
||||
|
||||
#define NEXTWORD(p) \
|
||||
(p += 2, ((((char *)p)[-2]) << 8) + p[-1])
|
||||
|
||||
#define NEXTLONG(p) \
|
||||
(p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
|
||||
|
||||
#define NEXTSINGLE(p) \
|
||||
(p += 4, *((float *)(p - 4)))
|
||||
|
||||
#define NEXTDOUBLE(p) \
|
||||
(p += 8, *((double *)(p - 8)))
|
||||
|
||||
#define NEXTEXTEND(p) \
|
||||
(p += 12, 0.0) /* Need a function to convert from extended to double
|
||||
precision... */
|
||||
|
||||
#define NEXTPACKED(p) \
|
||||
(p += 12, 0.0) /* Need a function to convert from packed to double
|
||||
precision. Actually, it's easier to print a
|
||||
packed number than a double anyway, so maybe
|
||||
there should be a special case to handle this... */
|
||||
|
||||
/* Print the m68k instruction at address MEMADDR in debugged memory,
|
||||
on STREAM. Returns length of the instruction, in bytes. */
|
||||
|
||||
int
|
||||
print_insn (memaddr, stream)
|
||||
CORE_ADDR memaddr;
|
||||
FILE *stream;
|
||||
{
|
||||
unsigned char buffer[MAXLEN];
|
||||
register int i;
|
||||
register unsigned char *p;
|
||||
register char *d;
|
||||
register int bestmask;
|
||||
int best;
|
||||
|
||||
read_memory (memaddr, buffer, MAXLEN);
|
||||
|
||||
bestmask = 0;
|
||||
best = -1;
|
||||
for (i = 0; i < NOPCODES; i++)
|
||||
{
|
||||
register unsigned int opcode = m68k_opcodes[i].opcode;
|
||||
register unsigned int match = m68k_opcodes[i].match;
|
||||
if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
|
||||
&& ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
|
||||
&& ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
|
||||
&& ((0xff & buffer[3] & match) == (0xff & opcode)))
|
||||
{
|
||||
/* Don't use for printout the variants of divul and divsl
|
||||
that have the same register number in two places.
|
||||
The more general variants will match instead. */
|
||||
for (d = m68k_opcodes[i].args; *d; d += 2)
|
||||
if (d[1] == 'D')
|
||||
break;
|
||||
|
||||
/* Don't use for printout the variants of most floating
|
||||
point coprocessor instructions which use the same
|
||||
register number in two places, as above. */
|
||||
if (*d == 0)
|
||||
for (d = m68k_opcodes[i].args; *d; d += 2)
|
||||
if (d[1] == 't')
|
||||
break;
|
||||
|
||||
if (*d == 0 && match > bestmask)
|
||||
{
|
||||
best = i;
|
||||
bestmask = match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle undefined instructions. */
|
||||
if (best < 0)
|
||||
{
|
||||
fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
fprintf (stream, "%s", m68k_opcodes[best].name);
|
||||
|
||||
/* Point at first word of argument data,
|
||||
and at descriptor for first argument. */
|
||||
p = buffer + 2;
|
||||
|
||||
/* Why do this this way? -MelloN */
|
||||
for (d = m68k_opcodes[best].args; *d; d += 2)
|
||||
{
|
||||
if (d[0] == '#')
|
||||
{
|
||||
if (d[1] == 'l' && p - buffer < 6)
|
||||
p = buffer + 6;
|
||||
else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
|
||||
p = buffer + 4;
|
||||
}
|
||||
if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
|
||||
p = buffer + 4;
|
||||
if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
|
||||
p = buffer + 6;
|
||||
}
|
||||
|
||||
d = m68k_opcodes[best].args;
|
||||
|
||||
if (*d)
|
||||
fputc (' ', stream);
|
||||
|
||||
while (*d)
|
||||
{
|
||||
p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
|
||||
d += 2;
|
||||
if (*d && *(d - 2) != 'I' && *d != 'k')
|
||||
fprintf (stream, ",");
|
||||
}
|
||||
return p - buffer;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
print_insn_arg (d, buffer, p, addr, stream)
|
||||
char *d;
|
||||
unsigned char *buffer;
|
||||
register unsigned char *p;
|
||||
CORE_ADDR addr; /* PC for this arg to be relative to */
|
||||
FILE *stream;
|
||||
{
|
||||
register int val;
|
||||
register int place = d[1];
|
||||
int regno;
|
||||
register char *regname;
|
||||
register unsigned char *p1;
|
||||
register double flval;
|
||||
int flt_p;
|
||||
|
||||
switch (*d)
|
||||
{
|
||||
case 'C':
|
||||
fprintf (stream, "ccr");
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
fprintf (stream, "sr");
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
fprintf (stream, "usp");
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
{
|
||||
static struct { char *name; int value; } names[]
|
||||
= {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
|
||||
{"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
|
||||
{"msp", 0x803}, {"isp", 0x804}};
|
||||
|
||||
val = fetch_arg (buffer, place, 12);
|
||||
for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
|
||||
if (names[regno].value == val)
|
||||
{
|
||||
fprintf (stream, names[regno].name);
|
||||
break;
|
||||
}
|
||||
if (regno < 0)
|
||||
fprintf (stream, "%d", val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
val = fetch_arg (buffer, place, 3);
|
||||
if (val == 0) val = 8;
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
val = fetch_arg (buffer, place, 8);
|
||||
if (val & 0x80)
|
||||
val = val - 0x100;
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
val = fetch_arg (buffer, place, 4);
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
val = fetch_arg (buffer, place, 6);
|
||||
if (val & 0x20)
|
||||
fprintf (stream, "%s", reg_names [val & 7]);
|
||||
else
|
||||
fprintf (stream, "%d", val);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]);
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
if (place == 'k')
|
||||
fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
|
||||
else if (place == 'C')
|
||||
{
|
||||
val = fetch_arg (buffer, place, 7);
|
||||
if ( val > 63 ) /* This is a signed constant. */
|
||||
val -= 128;
|
||||
fprintf (stream, "{#%d}", val);
|
||||
}
|
||||
else
|
||||
error ("Invalid arg format in opcode table: \"%c%c\".",
|
||||
*d, place);
|
||||
break;
|
||||
|
||||
case '#':
|
||||
p1 = buffer + 2;
|
||||
if (place == 's')
|
||||
val = fetch_arg (buffer, place, 4);
|
||||
else if (place == 'C')
|
||||
val = fetch_arg (buffer, place, 7);
|
||||
else if (place == '8')
|
||||
val = fetch_arg (buffer, place, 3);
|
||||
else if (place == '3')
|
||||
val = fetch_arg (buffer, place, 8);
|
||||
else if (place == 'b')
|
||||
val = NEXTBYTE (p1);
|
||||
else if (place == 'w')
|
||||
val = NEXTWORD (p1);
|
||||
else if (place == 'l')
|
||||
val = NEXTLONG (p1);
|
||||
else
|
||||
error ("Invalid arg format in opcode table: \"%c%c\".",
|
||||
*d, place);
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
if (place == 's')
|
||||
val = fetch_arg (buffer, place, 4);
|
||||
else if (place == 'C')
|
||||
val = fetch_arg (buffer, place, 7);
|
||||
else if (place == '8')
|
||||
val = fetch_arg (buffer, place, 3);
|
||||
else if (place == 'b')
|
||||
val = NEXTBYTE (p);
|
||||
else if (place == 'w')
|
||||
val = NEXTWORD (p);
|
||||
else if (place == 'l')
|
||||
val = NEXTLONG (p);
|
||||
else
|
||||
error ("Invalid arg format in opcode table: \"%c%c\".",
|
||||
*d, place);
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if (place == 'b')
|
||||
val = NEXTBYTE (p);
|
||||
else if (place == 'w')
|
||||
val = NEXTWORD (p);
|
||||
else if (place == 'l')
|
||||
val = NEXTLONG (p);
|
||||
else if (place == 'g')
|
||||
{
|
||||
val = ((char *)buffer)[1];
|
||||
if (val == 0)
|
||||
val = NEXTWORD (p);
|
||||
else if (val == -1)
|
||||
val = NEXTLONG (p);
|
||||
}
|
||||
else if (place == 'c')
|
||||
{
|
||||
if (buffer[1] & 0x40) /* If bit six is one, long offset */
|
||||
val = NEXTLONG (p);
|
||||
else
|
||||
val = NEXTWORD (p);
|
||||
}
|
||||
else
|
||||
error ("Invalid arg format in opcode table: \"%c%c\".",
|
||||
*d, place);
|
||||
|
||||
print_address (addr + val, stream);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
val = NEXTWORD (p);
|
||||
fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
|
||||
if (val != 1) /* Unusual coprocessor ID? */
|
||||
fprintf (stream, "(cpid=%d) ", val);
|
||||
if (place == 'i')
|
||||
p += 2; /* Skip coprocessor extended operands */
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '~':
|
||||
case '%':
|
||||
case ';':
|
||||
case '@':
|
||||
case '!':
|
||||
case '$':
|
||||
case '?':
|
||||
case '/':
|
||||
case '&':
|
||||
|
||||
if (place == 'd')
|
||||
{
|
||||
val = fetch_arg (buffer, 'x', 6);
|
||||
val = ((val & 7) << 3) + ((val >> 3) & 7);
|
||||
}
|
||||
else
|
||||
val = fetch_arg (buffer, 's', 6);
|
||||
|
||||
/* Get register number assuming address register. */
|
||||
regno = (val & 7) + 8;
|
||||
regname = reg_names[regno];
|
||||
switch (val >> 3)
|
||||
{
|
||||
case 0:
|
||||
fprintf (stream, "%s", reg_names[val]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf (stream, "%s", regname);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf (stream, "(%s)", regname);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf (stream, "(%s)+", regname);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
fprintf (stream, "-(%s)", regname);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
val = NEXTWORD (p);
|
||||
fprintf (stream, "%d(%s)", val, regname);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
p = print_indexed (regno, p, addr, stream);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
switch (val & 7)
|
||||
{
|
||||
case 0:
|
||||
val = NEXTWORD (p);
|
||||
fprintf (stream, "@#");
|
||||
print_address (val, stream);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
val = NEXTLONG (p);
|
||||
fprintf (stream, "@#");
|
||||
print_address (val, stream);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = NEXTWORD (p);
|
||||
print_address (addr + val, stream);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
p = print_indexed (-1, p, addr, stream);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
flt_p = 1; /* Assume it's a float... */
|
||||
switch( place )
|
||||
{
|
||||
case 'b':
|
||||
val = NEXTBYTE (p);
|
||||
flt_p = 0;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
val = NEXTWORD (p);
|
||||
flt_p = 0;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
val = NEXTLONG (p);
|
||||
flt_p = 0;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
flval = NEXTSINGLE(p);
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
flval = NEXTDOUBLE(p);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
flval = NEXTEXTEND(p);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
flval = NEXTPACKED(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid arg format in opcode table: \"%c%c\".",
|
||||
*d, place);
|
||||
}
|
||||
if ( flt_p ) /* Print a float? */
|
||||
fprintf (stream, "#%g", flval);
|
||||
else
|
||||
fprintf (stream, "#%d", val);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stream, "<invalid address mode 0%o>", val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid arg format in opcode table: \"%c\".", *d);
|
||||
}
|
||||
|
||||
return (unsigned char *) p;
|
||||
}
|
||||
|
||||
/* Fetch BITS bits from a position in the instruction specified by CODE.
|
||||
CODE is a "place to put an argument", or 'x' for a destination
|
||||
that is a general address (mode and register).
|
||||
BUFFER contains the instruction. */
|
||||
|
||||
static int
|
||||
fetch_arg (buffer, code, bits)
|
||||
unsigned char *buffer;
|
||||
char code;
|
||||
int bits;
|
||||
{
|
||||
register int val;
|
||||
switch (code)
|
||||
{
|
||||
case 's':
|
||||
val = buffer[1];
|
||||
break;
|
||||
|
||||
case 'd': /* Destination, for register or quick. */
|
||||
val = (buffer[0] << 8) + buffer[1];
|
||||
val >>= 9;
|
||||
break;
|
||||
|
||||
case 'x': /* Destination, for general arg */
|
||||
val = (buffer[0] << 8) + buffer[1];
|
||||
val >>= 6;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
val = (buffer[3] >> 4);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
val = buffer[3];
|
||||
break;
|
||||
|
||||
case '1':
|
||||
val = (buffer[2] << 8) + buffer[3];
|
||||
val >>= 12;
|
||||
break;
|
||||
|
||||
case '2':
|
||||
val = (buffer[2] << 8) + buffer[3];
|
||||
val >>= 6;
|
||||
break;
|
||||
|
||||
case '3':
|
||||
case 'j':
|
||||
val = (buffer[2] << 8) + buffer[3];
|
||||
break;
|
||||
|
||||
case '4':
|
||||
val = (buffer[4] << 8) + buffer[5];
|
||||
val >>= 12;
|
||||
break;
|
||||
|
||||
case '5':
|
||||
val = (buffer[4] << 8) + buffer[5];
|
||||
val >>= 6;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
val = (buffer[4] << 8) + buffer[5];
|
||||
break;
|
||||
|
||||
case '7':
|
||||
val = (buffer[2] << 8) + buffer[3];
|
||||
val >>= 7;
|
||||
break;
|
||||
|
||||
case '8':
|
||||
val = (buffer[2] << 8) + buffer[3];
|
||||
val >>= 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
switch (bits)
|
||||
{
|
||||
case 3:
|
||||
return val & 7;
|
||||
case 4:
|
||||
return val & 017;
|
||||
case 5:
|
||||
return val & 037;
|
||||
case 6:
|
||||
return val & 077;
|
||||
case 7:
|
||||
return val & 0177;
|
||||
case 8:
|
||||
return val & 0377;
|
||||
case 12:
|
||||
return val & 07777;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Print an indexed argument. The base register is BASEREG (-1 for pc).
|
||||
P points to extension word, in buffer.
|
||||
ADDR is the nominal core address of that extension word. */
|
||||
|
||||
static unsigned char *
|
||||
print_indexed (basereg, p, addr, stream)
|
||||
int basereg;
|
||||
unsigned char *p;
|
||||
FILE *stream;
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
register int word;
|
||||
static char *scales[] = {"", "*2", "*4", "*8"};
|
||||
register int base_disp;
|
||||
register int outer_disp;
|
||||
char buf[40];
|
||||
|
||||
word = NEXTWORD (p);
|
||||
|
||||
/* Generate the text for the index register.
|
||||
Where this will be output is not yet determined. */
|
||||
sprintf (buf, "[%s.%c%s]",
|
||||
reg_names[(word >> 12) & 0xf],
|
||||
(word & 0x800) ? 'l' : 'w',
|
||||
scales[(word >> 9) & 3]);
|
||||
|
||||
/* Handle the 68000 style of indexing. */
|
||||
|
||||
if ((word & 0x100) == 0)
|
||||
{
|
||||
print_base (basereg,
|
||||
((word & 0x80) ? word | 0xff00 : word & 0xff)
|
||||
+ ((basereg == -1) ? addr : 0),
|
||||
stream);
|
||||
fprintf (stream, "%s", buf);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Handle the generalized kind. */
|
||||
/* First, compute the displacement to add to the base register. */
|
||||
|
||||
if (word & 0200)
|
||||
basereg = -2;
|
||||
if (word & 0100)
|
||||
buf[0] = 0;
|
||||
base_disp = 0;
|
||||
switch ((word >> 4) & 3)
|
||||
{
|
||||
case 2:
|
||||
base_disp = NEXTWORD (p);
|
||||
break;
|
||||
case 3:
|
||||
base_disp = NEXTLONG (p);
|
||||
}
|
||||
if (basereg == -1)
|
||||
base_disp += addr;
|
||||
|
||||
/* Handle single-level case (not indirect) */
|
||||
|
||||
if ((word & 7) == 0)
|
||||
{
|
||||
print_base (basereg, base_disp, stream);
|
||||
fprintf (stream, "%s", buf);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Two level. Compute displacement to add after indirection. */
|
||||
|
||||
outer_disp = 0;
|
||||
switch (word & 3)
|
||||
{
|
||||
case 2:
|
||||
outer_disp = NEXTWORD (p);
|
||||
break;
|
||||
case 3:
|
||||
outer_disp = NEXTLONG (p);
|
||||
}
|
||||
|
||||
fprintf (stream, "%d(", outer_disp);
|
||||
print_base (basereg, base_disp, stream);
|
||||
|
||||
/* If postindexed, print the closeparen before the index. */
|
||||
if (word & 4)
|
||||
fprintf (stream, ")%s", buf);
|
||||
/* If preindexed, print the closeparen after the index. */
|
||||
else
|
||||
fprintf (stream, "%s)", buf);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Print a base register REGNO and displacement DISP, on STREAM.
|
||||
REGNO = -1 for pc, -2 for none (suppressed). */
|
||||
|
||||
static void
|
||||
print_base (regno, disp, stream)
|
||||
int regno;
|
||||
int disp;
|
||||
FILE *stream;
|
||||
{
|
||||
if (regno == -2)
|
||||
fprintf (stream, "%d", disp);
|
||||
else if (regno == -1)
|
||||
fprintf (stream, "0x%x", disp);
|
||||
else
|
||||
fprintf (stream, "%d(%s)", disp, reg_names[regno]);
|
||||
}
|
||||
|
||||
/* This is not part of insn printing, but it is machine-specific,
|
||||
so this is a convenient place to put it.
|
||||
|
||||
Convert a 68881 extended float to a double.
|
||||
FROM is the address of the extended float.
|
||||
Store the double in *TO. */
|
||||
|
||||
convert_from_68881 (from, to)
|
||||
char *from;
|
||||
double *to;
|
||||
{
|
||||
#ifdef HPUX_ASM
|
||||
asm ("mov.l 8(%a6),%a0");
|
||||
asm ("mov.l 12(%a6),%a1");
|
||||
asm ("fmove.x (%a0),%fp0");
|
||||
asm ("fmove.d %fp0,(%a1)");
|
||||
#else /* not HPUX_ASM */
|
||||
#if 0
|
||||
asm ("movl a6@(8),a0");
|
||||
asm ("movl a6@(12),a1");
|
||||
asm ("fmovex a0@,fp0");
|
||||
asm ("fmoved fp0,a1@");
|
||||
#else
|
||||
/* Hand-assemble those insns since some assemblers lose
|
||||
and some have different syntax. */
|
||||
asm (".word 020156");
|
||||
asm (".word 8");
|
||||
asm (".word 021156");
|
||||
asm (".word 12");
|
||||
asm (".long 0xf2104800");
|
||||
asm (".long 0xf2117400");
|
||||
#endif
|
||||
#endif /* not HPUX_ASM */
|
||||
}
|
||||
|
||||
/* The converse: convert the double *FROM to an extended float
|
||||
and store where TO points. */
|
||||
|
||||
convert_to_68881 (from, to)
|
||||
double *from;
|
||||
char *to;
|
||||
{
|
||||
#ifdef HPUX_ASM
|
||||
asm ("mov.l 8(%a6),%a0");
|
||||
asm ("mov.l 12(%a6),%a1");
|
||||
asm ("fmove.d (%a0),%fp0");
|
||||
asm ("fmove.x %fp0,(%a1)");
|
||||
#else /* not HPUX_ASM */
|
||||
#if 0
|
||||
asm ("movl a6@(8),a0");
|
||||
asm ("movl a6@(12),a1");
|
||||
asm ("fmoved a0@,fp0");
|
||||
asm ("fmovex fp0,a1@");
|
||||
#else
|
||||
/* Hand-assemble those insns since some assemblers lose. */
|
||||
asm (".word 020156");
|
||||
asm (".word 8");
|
||||
asm (".word 021156");
|
||||
asm (".word 12");
|
||||
asm (".long 0xf2105400");
|
||||
asm (".long 0xf2116800");
|
||||
#endif
|
||||
#endif /* not HPUX_ASM */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
/* Print PN instructions for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
struct gld_opcode
|
||||
{
|
||||
char *name;
|
||||
unsigned long opcode;
|
||||
unsigned long mask;
|
||||
char *args;
|
||||
int length;
|
||||
};
|
||||
|
||||
/* We store four bytes of opcode for all opcodes because that
|
||||
is the most any of them need. The actual length of an instruction
|
||||
is always at least 2 bytes, and at most four. The length of the
|
||||
instruction is based on the opcode.
|
||||
|
||||
The mask component is a mask saying which bits must match
|
||||
particular opcode in order for an instruction to be an instance
|
||||
of that opcode.
|
||||
|
||||
The args component is a string containing characters
|
||||
that are used to format the arguments to the instruction. */
|
||||
|
||||
/* Kinds of operands:
|
||||
r Register in first field
|
||||
R Register in second field
|
||||
b Base register in first field
|
||||
B Base register in second field
|
||||
v Vector register in first field
|
||||
V Vector register in first field
|
||||
A Optional address register (base register)
|
||||
X Optional index register
|
||||
I Immediate data (16bits signed)
|
||||
O Offset field (16bits signed)
|
||||
h Offset field (15bits signed)
|
||||
d Offset field (14bits signed)
|
||||
S Shift count field
|
||||
|
||||
any other characters are printed as is...
|
||||
*/
|
||||
|
||||
/* The assembler requires that this array be sorted as follows:
|
||||
all instances of the same mnemonic must be consecutive.
|
||||
All instances of the same mnemonic with the same number of operands
|
||||
must be consecutive.
|
||||
*/
|
||||
struct gld_opcode gld_opcodes[] =
|
||||
{
|
||||
{ "abm", 0xa0080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "abr", 0x18080000, 0xfc0c0000, "r,f", 2 },
|
||||
{ "aci", 0xfc770000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "adi", 0xc8010000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "admb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "admd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "admh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "admw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "adrm", 0x38080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "ai", 0xfc030000, 0xfc07ffff, "I", 4 },
|
||||
{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "bcf", 0xf0000000, 0xfc080000, "I,xOA,X", 4 },
|
||||
{ "bct", 0xec000000, 0xfc080000, "I,xOA,X", 4 },
|
||||
{ "bei", 0x00060000, 0xffff0000, "", 2 },
|
||||
{ "bft", 0xf0000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bib", 0xf4000000, 0xfc780000, "r,xOA", 4 },
|
||||
{ "bid", 0xf4600000, 0xfc780000, "r,xOA", 4 },
|
||||
{ "bih", 0xf4200000, 0xfc780000, "r,xOA", 4 },
|
||||
{ "biw", 0xf4400000, 0xfc780000, "r,xOA", 4 },
|
||||
{ "bl", 0xf8800000, 0xff880000, "xOA,X", 4 },
|
||||
{ "bsub", 0x5c080000, 0xff8f0000, "", 2 },
|
||||
{ "bsubm", 0x28080000, 0xfc080000, "", 4 },
|
||||
{ "bu", 0xec000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "call", 0x28080000, 0xfc0f0000, "", 2 },
|
||||
{ "callm", 0x5c080000, 0xff880000, "", 4 },
|
||||
{ "camb", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "camd", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "camh", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "camw", 0x90000000, 0xfc080000, "r.xOA,X", 4 },
|
||||
{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "cd", 0xfc060000, 0xfc070000, "r,f", 4 },
|
||||
{ "cea", 0x000f0000, 0xffff0000, "", 2 },
|
||||
{ "ci", 0xc8050000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "cmc", 0x040a0000, 0xfc7f0000, "r", 2 },
|
||||
{ "cmmb", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "cmmd", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "cmmh", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "cmmw", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "cmr", 0x14000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "daci", 0xfc7f0000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "dae", 0x000e0000, 0xffff0000, "", 2 },
|
||||
{ "dai", 0xfc040000, 0xfc07ffff, "I", 4 },
|
||||
{ "dci", 0xfc6f0000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "di", 0xfc010000, 0xfc07ffff, "I", 4 },
|
||||
{ "dvfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "dvfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "dvi", 0xc8040000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "dvrfd", 0x380c0000, 0xfc0f0000, "r,R", 4 },
|
||||
{ "dvrfw", 0x38040000, 0xfc0f0000, "r,xOA,X", 4 },
|
||||
{ "eae", 0x00080000, 0xffff0000, "", 2 },
|
||||
{ "eci", 0xfc670000, 0xfc7f8080, "r,I", 4 },
|
||||
{ "ecwcs", 0xfc4f0000, 0xfc7f8000, "", 4 },
|
||||
{ "ei", 0xfc000000, 0xfc07ffff, "I", 4 },
|
||||
{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "eorm", 0x0c080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "es", 0x00040000, 0xfc7f0000, "r", 2 },
|
||||
{ "exm", 0xa8000000, 0xff880000, "xOA,X", 4 },
|
||||
{ "exr", 0xc8070000, 0xfc7f0000, "r", 2 },
|
||||
{ "exrr", 0xc8070002, 0xfc7f0002, "r", 2 },
|
||||
{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "grio", 0xfc3f0000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "halt", 0x00000000, 0xffff0000, "", 2 },
|
||||
{ "hio", 0xfc370000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "jwcs", 0xfa080000, 0xff880000, "xOA,X", 4 },
|
||||
{ "la", 0x50000000, 0xfc000000, "r,xOA,X", 4 },
|
||||
{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "lb", 0xac080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lcs", 0x00030000, 0xfc7f0000, "r", 2 },
|
||||
{ "ld", 0xac000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "lear", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lf", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lfbr", 0xcc080000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "lh", 0xac000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "li", 0xc8000000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "lmap", 0x2c070000, 0xfc7f0000, "r", 2 },
|
||||
{ "lmb", 0xb0080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lmd", 0xb0000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "lmh", 0xb0000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "lmw", 0xb0000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lnb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lnd", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "lnh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "lnw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lpsd", 0xf9800000, 0xff880000, "r,xOA,X", 4 },
|
||||
{ "lpsdcm", 0xfa800000, 0xff880000, "r,xOA,X", 4 },
|
||||
{ "lw", 0xac000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpi", 0xc8030000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "nop", 0x00020000, 0xffff0000, "", 2 },
|
||||
{ "ormb", 0x88080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "ormd", 0x88000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "ormh", 0x88000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "ormw", 0x88000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "orrm", 0x08080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "rdsts", 0x00090000, 0xfc7f0000, "r", 2 },
|
||||
{ "return", 0x280e0000, 0xfc7f0000, "", 2 },
|
||||
{ "ri", 0xfc020000, 0xfc07ffff, "I", 4 },
|
||||
{ "rnd", 0x00050000, 0xfc7f0000, "r", 2 },
|
||||
{ "rpswt", 0x040b0000, 0xfc7f0000, "r", 2 },
|
||||
{ "rschnl", 0xfc2f0000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "rsctl", 0xfc470000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "rwcs", 0x000b0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sacz", 0x10080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "sbm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "sbr", 0x18000000, 0xfc0c0000, "r,f", 4 },
|
||||
{ "sea", 0x000d0000, 0xffff0000, "", 2 },
|
||||
{ "setcpu", 0x2c090000, 0xfc7f0000, "r", 2 },
|
||||
{ "sio", 0xfc170000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "sipu", 0x000a0000, 0xffff0000, "", 2 },
|
||||
{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
|
||||
{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
|
||||
{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
|
||||
{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
|
||||
{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
|
||||
{ "smc", 0x04070000, 0xfc070000, "", 2 },
|
||||
{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
|
||||
{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
|
||||
{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
|
||||
{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
|
||||
{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
|
||||
{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stfbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "stmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "stmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "stmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stpio", 0xfc270000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
|
||||
{ "sufd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "sufw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sui", 0xc8020000, 0xfc7f0000, "r,I", 4 },
|
||||
{ "sumb", 0xbc080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sumd", 0xbc000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "sumh", 0xbc000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "sumw", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "surfd", 0x380b0000, 0xfc0f0000, "r,xOA,X", 4 },
|
||||
{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "surm", 0x3c080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "svc", 0xc8060000, 0xffff0000, "", 4 },
|
||||
{ "tbm", 0xa4080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "tbr", 0x180c0000, 0xfc0c0000, "r,f", 2 },
|
||||
{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
|
||||
{ "tccr", 0x28040000, 0xfc7f0000, "", 2 },
|
||||
{ "td", 0xfc050000, 0xfc070000, "r,f", 4 },
|
||||
{ "tio", 0xfc1f0000, 0xfc7f8000, "r,I", 4 },
|
||||
{ "tmapr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "tpcbr", 0x280c0000, 0xfc7f0000, "r", 2 },
|
||||
{ "trbr", 0x2c010000, 0xfc0f0000, "b,R", 2 },
|
||||
{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trcc", 0x28050000, 0xfc7f0000, "", 2 },
|
||||
{ "trcm", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trnm", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trrm", 0x2c080000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trsc", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "trsw", 0x28000000, 0xfc7f0000, "r", 2 },
|
||||
{ "tscr", 0x2c0f0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "uei", 0x00070000, 0xffff0000, "", 2 },
|
||||
{ "wait", 0x00010000, 0xffff0000, "", 2 },
|
||||
{ "wcwcs", 0xfc5f0000, 0xfc7f8000, "", 4 },
|
||||
{ "wwcs", 0x000c0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
|
||||
{ "xcr", 0x2c050000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "xcrm", 0x2c0d0000, 0xfc0f0000, "r,R", 2 },
|
||||
{ "zbm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
|
||||
{ "zbr", 0x18040000, 0xfc0c0000, "r,f", 2 },
|
||||
{ "zmb", 0xf8080000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "zmd", 0xf8000002, 0xfc080002, "r,xOA,X", 4 },
|
||||
{ "zmh", 0xf8000001, 0xfc080001, "r,xOA,X", 4 },
|
||||
{ "zmw", 0xf8000000, 0xfc080000, "r,xOA,X", 4 },
|
||||
{ "zr", 0x0c000000, 0xfc0f0000, "r", 2 },
|
||||
};
|
||||
|
||||
int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
|
||||
|
||||
struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
|
||||
sizeof(gld_opcodes[0]);
|
415
gdb/printcmd.c
415
gdb/printcmd.c
|
@ -1,4 +1,4 @@
|
|||
/* Print values for GNU debugger gdb.
|
||||
/* Print values for GNU debugger GDB.
|
||||
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
|
@ -54,8 +54,17 @@ static CORE_ADDR last_examine_address;
|
|||
|
||||
static value last_examine_value;
|
||||
|
||||
/* Number of auto-display expression currently being displayed.
|
||||
So that we can deleted it if we get an error or a signal within it.
|
||||
-1 when not doing one. */
|
||||
|
||||
int current_display_number;
|
||||
|
||||
static void do_one_display ();
|
||||
|
||||
void do_displays ();
|
||||
void print_address ();
|
||||
void print_scalar_formatted ();
|
||||
|
||||
START_FILE
|
||||
|
||||
|
@ -123,25 +132,11 @@ print_formatted (val, format, size)
|
|||
if (VALUE_LVAL (val) == lval_memory)
|
||||
next_address = VALUE_ADDRESS (val) + len;
|
||||
|
||||
if (format && format != 's')
|
||||
{
|
||||
val_long = value_as_long (val);
|
||||
|
||||
/* If value is unsigned, truncate it in case negative. */
|
||||
if (format != 'd')
|
||||
{
|
||||
if (len == sizeof (char))
|
||||
val_long &= (1 << 8 * sizeof(char)) - 1;
|
||||
else if (len == sizeof (short))
|
||||
val_long &= (1 << 8 * sizeof(short)) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 's':
|
||||
next_address = VALUE_ADDRESS (val)
|
||||
+ value_print (value_addr (val), stdout);
|
||||
+ value_print (value_addr (val), stdout, 0);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
|
@ -149,6 +144,49 @@ print_formatted (val, format, size)
|
|||
+ print_insn (VALUE_ADDRESS (val), stdout);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (format == 0
|
||||
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY
|
||||
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION)
|
||||
value_print (val, stdout, format);
|
||||
else
|
||||
print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val),
|
||||
format, size, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
|
||||
according to letters FORMAT and SIZE on STREAM.
|
||||
FORMAT may not be zero. Formats s and i are not supported at this level.
|
||||
|
||||
This is how the elements of an array or structure are printed
|
||||
with a format. */
|
||||
|
||||
void
|
||||
print_scalar_formatted (valaddr, type, format, size, stream)
|
||||
char *valaddr;
|
||||
struct type *type;
|
||||
char format;
|
||||
int size;
|
||||
FILE *stream;
|
||||
{
|
||||
long val_long;
|
||||
int len = TYPE_LENGTH (type);
|
||||
|
||||
val_long = unpack_long (type, valaddr);
|
||||
|
||||
/* If value is unsigned, truncate it in case negative. */
|
||||
if (format != 'd')
|
||||
{
|
||||
if (len == sizeof (char))
|
||||
val_long &= (1 << 8 * sizeof(char)) - 1;
|
||||
else if (len == sizeof (short))
|
||||
val_long &= (1 << 8 * sizeof(short)) - 1;
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 'x':
|
||||
switch (size)
|
||||
{
|
||||
|
@ -186,31 +224,30 @@ print_formatted (val, format, size)
|
|||
break;
|
||||
|
||||
case 'a':
|
||||
print_address (val_long, stdout);
|
||||
print_address (val_long, stream);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
value_print (value_cast (builtin_type_char, val), stdout);
|
||||
value_print (value_from_long (builtin_type_char, val_long), stream, 0);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (float))
|
||||
VALUE_TYPE (val) = builtin_type_float;
|
||||
if (TYPE_LENGTH (VALUE_TYPE (val)) == sizeof (double))
|
||||
VALUE_TYPE (val) = builtin_type_double;
|
||||
if (len == sizeof (float))
|
||||
type = builtin_type_float;
|
||||
if (len == sizeof (double))
|
||||
type = builtin_type_double;
|
||||
#ifdef IEEE_FLOAT
|
||||
if (is_nan (value_as_double (val)))
|
||||
if (is_nan (unpack_double (type, valaddr)))
|
||||
{
|
||||
printf ("Nan");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
printf ("%g", value_as_double (val));
|
||||
printf ("%g", unpack_double (type, valaddr));
|
||||
break;
|
||||
|
||||
case 0:
|
||||
value_print (val, stdout);
|
||||
break;
|
||||
abort ();
|
||||
|
||||
default:
|
||||
error ("Undefined output format \"%c\".", format);
|
||||
|
@ -364,7 +401,6 @@ print_command (exp)
|
|||
else
|
||||
val = access_value_history (0);
|
||||
|
||||
if (!val) return; /* C++ */
|
||||
histindex = record_latest_value (val);
|
||||
printf ("$%d = ", histindex);
|
||||
|
||||
|
@ -414,41 +450,17 @@ set_command (exp)
|
|||
do_cleanups (old_chain);
|
||||
}
|
||||
|
||||
/* C++: Modified to give useful information about variable which
|
||||
hang off of `this'. */
|
||||
static void
|
||||
address_info (exp)
|
||||
char *exp;
|
||||
{
|
||||
register struct symbol *sym;
|
||||
register CORE_ADDR val;
|
||||
struct block *block, *get_selected_block ();
|
||||
|
||||
if (exp == 0)
|
||||
error ("Argument required.");
|
||||
|
||||
block = get_selected_block ();
|
||||
sym = lookup_symbol_1 (exp, block, VAR_NAMESPACE);
|
||||
if (! sym)
|
||||
{
|
||||
value v;
|
||||
|
||||
/* C++: see if it hangs off of `this'. Must
|
||||
not inadvertently convert from a method call
|
||||
to data ref. */
|
||||
v = value_of_this (0);
|
||||
if (v)
|
||||
{
|
||||
val = check_field (v, exp);
|
||||
if (val)
|
||||
{
|
||||
printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
sym = lookup_symbol_2 (exp, 0, VAR_NAMESPACE);
|
||||
}
|
||||
sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE);
|
||||
if (sym == 0)
|
||||
{
|
||||
register int i;
|
||||
|
@ -572,12 +584,9 @@ whatis_command (exp)
|
|||
else
|
||||
val = access_value_history (0);
|
||||
|
||||
if (val != 0)
|
||||
{
|
||||
printf ("type = ");
|
||||
type_print (VALUE_TYPE (val), "", stdout, 1);
|
||||
printf ("\n");
|
||||
}
|
||||
printf ("type = ");
|
||||
type_print (VALUE_TYPE (val), "", stdout, 1);
|
||||
printf ("\n");
|
||||
|
||||
if (exp)
|
||||
do_cleanups (old_chain);
|
||||
|
@ -639,143 +648,6 @@ ptype_command (typename)
|
|||
type_print (type, "", stdout, 1);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* Print all the methods that correspond to the name METHOD.
|
||||
Can optionally qualify the method with a CLASSNAME, as
|
||||
in CLASSNAME :: METHODNAME. This routine does not call
|
||||
parse_c_expression, so the input must conform to one of
|
||||
these two forms. */
|
||||
|
||||
static void
|
||||
pmethod_command (exp)
|
||||
char *exp;
|
||||
{
|
||||
# if 0
|
||||
struct expression *expr;
|
||||
register value val;
|
||||
register struct cleanup *old_chain;
|
||||
char *classname, *methodname;
|
||||
|
||||
methodname = exp;
|
||||
while (*exp++ <= ' ') ; /* remove leading whitespace */
|
||||
if (exp[-1] == ':')
|
||||
if (*exp == ':')
|
||||
classname = (char *)1;
|
||||
else error ("Invalid syntax: \"%s\"", methodname);
|
||||
else
|
||||
{
|
||||
classname = exp-1;
|
||||
while (*exp++ != ':') ;
|
||||
exp[-1] = '\0';
|
||||
if (*exp == ':')
|
||||
{
|
||||
while (*exp++ <= ' ') ; /* remove leading 2nd whitespace */
|
||||
methodname = exp-1;
|
||||
while (((*exp | 0x20) >= 'a' && ((*exp | 0x20) <= 'z')) || *exp == '_')
|
||||
exp++;
|
||||
if (*exp)
|
||||
{
|
||||
*exp++ = '\0';
|
||||
while (*exp)
|
||||
if (*exp > ' ') error ("junk after method name");
|
||||
}
|
||||
}
|
||||
else error ("Invalid syntax: \"%s\"", methodname);
|
||||
}
|
||||
if (classname)
|
||||
{
|
||||
if (classname != (char *)1)
|
||||
classtype = lookup_typename (classname);
|
||||
else
|
||||
{
|
||||
register struct symtab *s;
|
||||
register struct blockvector *bv;
|
||||
struct blockvector *prev_bv = 0;
|
||||
register struct block *b;
|
||||
register int i, j;
|
||||
register struct symbol *sym;
|
||||
char *val;
|
||||
int found_in_file;
|
||||
static char *classnames[]
|
||||
= {"variable", "function", "type", "method"};
|
||||
int print_count = 0;
|
||||
|
||||
if (regexp)
|
||||
if (val = (char *) re_comp (regexp))
|
||||
error ("Invalid regexp: %s", val);
|
||||
|
||||
printf (regexp
|
||||
? "All %ss matching regular expression \"%s\":\n"
|
||||
: "All defined %ss:\n",
|
||||
classnames[class],
|
||||
regexp);
|
||||
|
||||
for (s = symtab_list; s; s = s->next)
|
||||
{
|
||||
found_in_file = 0;
|
||||
bv = BLOCKVECTOR (s);
|
||||
/* Often many files share a blockvector.
|
||||
Scan each blockvector only once so that
|
||||
we don't get every symbol many times.
|
||||
It happens that the first symtab in the list
|
||||
for any given blockvector is the main file. */
|
||||
if (bv != prev_bv)
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bv, i);
|
||||
for (j = 0; j < BLOCK_NSYMS (b); j++)
|
||||
{
|
||||
QUIT;
|
||||
sym = BLOCK_SYM (b, j);
|
||||
if ((regexp == 0 || re_exec (SYMBOL_NAME (sym)))
|
||||
&& ((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 == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
|
||||
{
|
||||
if (!found_in_file)
|
||||
{
|
||||
printf ("\nFile %s:\n", s->filename);
|
||||
print_count += 2;
|
||||
}
|
||||
found_in_file = 1;
|
||||
MORE;
|
||||
if (i == 1)
|
||||
printf ("static ");
|
||||
|
||||
type_print (SYMBOL_TYPE (sym),
|
||||
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
|
||||
? "" : SYMBOL_NAME (sym)),
|
||||
stdout, 0);
|
||||
printf (";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_bv = bv;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exp)
|
||||
{
|
||||
expr = parse_c_expression (exp);
|
||||
old_chain = make_cleanup (free_current_contents, &expr);
|
||||
val = evaluate_type (expr);
|
||||
}
|
||||
else
|
||||
val = access_value_history (0);
|
||||
|
||||
if (val != 0)
|
||||
{
|
||||
printf ("type = ");
|
||||
type_print (VALUE_TYPE (val), "", stdout, 1);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
if (exp)
|
||||
do_cleanups (old_chain);
|
||||
# endif
|
||||
}
|
||||
|
||||
struct display
|
||||
{
|
||||
|
@ -802,8 +674,9 @@ static int display_number;
|
|||
Specify the expression. */
|
||||
|
||||
static void
|
||||
display_command (exp)
|
||||
display_command (exp, from_tty)
|
||||
char *exp;
|
||||
int from_tty;
|
||||
{
|
||||
struct format_data fmt;
|
||||
register struct expression *expr;
|
||||
|
@ -841,6 +714,9 @@ display_command (exp)
|
|||
new->format = fmt;
|
||||
display_chain = new;
|
||||
|
||||
if (from_tty)
|
||||
do_one_display (new);
|
||||
|
||||
dont_repeat ();
|
||||
}
|
||||
|
||||
|
@ -869,6 +745,38 @@ clear_displays ()
|
|||
}
|
||||
}
|
||||
|
||||
/* Delete the auto-display number NUM. */
|
||||
|
||||
void
|
||||
delete_display (num)
|
||||
int num;
|
||||
{
|
||||
register struct display *d1, *d;
|
||||
|
||||
if (!display_chain)
|
||||
error ("No display number %d.", num);
|
||||
|
||||
if (display_chain->number == num)
|
||||
{
|
||||
d1 = display_chain;
|
||||
display_chain = d1->next;
|
||||
free_display (d1);
|
||||
}
|
||||
else
|
||||
for (d = display_chain; ; d = d->next)
|
||||
{
|
||||
if (d->next == 0)
|
||||
error ("No display number %d.", num);
|
||||
if (d->next->number == num)
|
||||
{
|
||||
d1 = d->next;
|
||||
d->next = d1->next;
|
||||
free_display (d1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete some values from the auto-display chain.
|
||||
Specify the element numbers. */
|
||||
|
||||
|
@ -898,25 +806,7 @@ undisplay_command (args)
|
|||
|
||||
num = atoi (p);
|
||||
|
||||
if (display_chain->number == num)
|
||||
{
|
||||
d1 = display_chain;
|
||||
display_chain = d1->next;
|
||||
free_display (d1);
|
||||
}
|
||||
else
|
||||
for (d = display_chain; ; d = d->next)
|
||||
{
|
||||
if (d->next == 0)
|
||||
error ("No display number %d.", num);
|
||||
if (d->next->number == num)
|
||||
{
|
||||
d1 = d->next;
|
||||
d->next = d1->next;
|
||||
free_display (d1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete_display (num);
|
||||
|
||||
p = p1;
|
||||
while (*p == ' ' || *p == '\t') p++;
|
||||
|
@ -924,6 +814,47 @@ undisplay_command (args)
|
|||
dont_repeat ();
|
||||
}
|
||||
|
||||
/* Display a single auto-display. */
|
||||
|
||||
static void
|
||||
do_one_display (d)
|
||||
struct display *d;
|
||||
{
|
||||
current_display_number = d->number;
|
||||
|
||||
printf ("%d: ", d->number);
|
||||
if (d->format.size)
|
||||
{
|
||||
printf ("x/");
|
||||
if (d->format.count != 1)
|
||||
printf ("%d", d->format.count);
|
||||
printf ("%c", d->format.format);
|
||||
if (d->format.format != 'i' && d->format.format != 's')
|
||||
printf ("%c", d->format.size);
|
||||
printf (" ");
|
||||
print_expression (d->exp, stdout);
|
||||
if (d->format.count != 1)
|
||||
printf ("\n");
|
||||
else
|
||||
printf (" ");
|
||||
do_examine (d->format,
|
||||
value_as_long (evaluate_expression (d->exp)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d->format.format)
|
||||
printf ("/%c ", d->format.format);
|
||||
print_expression (d->exp, stdout);
|
||||
printf (" = ");
|
||||
print_formatted (evaluate_expression (d->exp),
|
||||
d->format.format, d->format.size);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
current_display_number = -1;
|
||||
}
|
||||
|
||||
/* Display all of the values on the auto-display chain. */
|
||||
|
||||
void
|
||||
|
@ -932,37 +863,22 @@ do_displays ()
|
|||
register struct display *d;
|
||||
|
||||
for (d = display_chain; d; d = d->next)
|
||||
do_one_display (d);
|
||||
}
|
||||
|
||||
/* Delete the auto-display which we were in the process of displaying.
|
||||
This is done when there is an error or a signal. */
|
||||
|
||||
void
|
||||
delete_current_display ()
|
||||
{
|
||||
if (current_display_number >= 0)
|
||||
{
|
||||
printf ("%d: ", d->number);
|
||||
if (d->format.size)
|
||||
{
|
||||
printf ("x/");
|
||||
if (d->format.count != 1)
|
||||
printf ("%d", d->format.count);
|
||||
printf ("%c", d->format.format);
|
||||
if (d->format.format != 'i' && d->format.format != 's')
|
||||
printf ("%c", d->format.size);
|
||||
printf (" ");
|
||||
print_expression (d->exp, stdout);
|
||||
if (d->format.count != 1)
|
||||
printf ("\n");
|
||||
else
|
||||
printf (" ");
|
||||
do_examine (d->format,
|
||||
value_as_long (evaluate_expression (d->exp)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d->format.format)
|
||||
printf ("/%c ", d->format.format);
|
||||
print_expression (d->exp, stdout);
|
||||
printf (" = ");
|
||||
print_formatted (evaluate_expression (d->exp),
|
||||
d->format.format, d->format.size);
|
||||
printf ("\n");
|
||||
}
|
||||
fflush (stdout);
|
||||
delete_display (current_display_number);
|
||||
fprintf (stderr, "Deleting display %d to avoid infinite recursion.\n",
|
||||
current_display_number);
|
||||
}
|
||||
current_display_number = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -998,7 +914,7 @@ print_variable_value (var, frame, stream)
|
|||
FILE *stream;
|
||||
{
|
||||
value val = read_var_value (var, frame);
|
||||
value_print (val, stream);
|
||||
value_print (val, stream, 0);
|
||||
}
|
||||
|
||||
/* Print the arguments of a stack frame, given the function FUNC
|
||||
|
@ -1057,7 +973,7 @@ print_frame_args (func, addr, num, stream)
|
|||
if (! first)
|
||||
fprintf (stream, ", ");
|
||||
fprintf (stream, "%s=", SYMBOL_NAME (sym));
|
||||
value_print (val, stream);
|
||||
value_print (val, stream, 0);
|
||||
first = 0;
|
||||
last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym));
|
||||
/* Round up address of next arg to multiple of size of int. */
|
||||
|
@ -1255,6 +1171,8 @@ printf_command (arg)
|
|||
static
|
||||
initialize ()
|
||||
{
|
||||
current_display_number = -1;
|
||||
|
||||
add_info ("address", address_info,
|
||||
"Describe where variable VAR is stored.");
|
||||
|
||||
|
@ -1281,11 +1199,6 @@ The selected stack frame's lexical context is used to look up the name.");
|
|||
add_com ("whatis", class_vars, whatis_command,
|
||||
"Print data type of expression EXP.");
|
||||
|
||||
add_com ("pmethod", class_vars, pmethod_command,
|
||||
"Print definitions of method METHOD.\n\
|
||||
Argument must resolve to a method name within the containing scope.\n\
|
||||
All definitions found go into history array.");
|
||||
|
||||
add_info ("display", display_info,
|
||||
"Expressions to display when program stops, with code numbers.");
|
||||
add_com ("undisplay", class_vars, undisplay_command,
|
||||
|
|
28
gdb/remote.c
28
gdb/remote.c
|
@ -71,11 +71,24 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include "wait.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#ifdef HAVE_TERMIO
|
||||
#include <termio.h>
|
||||
#undef TIOCGETP
|
||||
#define TIOCGETP TCGETA
|
||||
#undef TIOCSETN
|
||||
#define TIOCSETN TCSETA
|
||||
#undef TIOCSETP
|
||||
#define TIOCSETP TCSETAF
|
||||
#define TERMINAL struct termio
|
||||
#else
|
||||
#include <sgtty.h>
|
||||
#define TERMINAL struct sgttyb
|
||||
#endif
|
||||
|
||||
int kiodebug;
|
||||
|
||||
|
@ -101,7 +114,7 @@ remote_open (name, from_tty)
|
|||
char *name;
|
||||
int from_tty;
|
||||
{
|
||||
struct sgttyb sg;
|
||||
TERMINAL sg;
|
||||
|
||||
remote_debugging = 0;
|
||||
dcache_init ();
|
||||
|
@ -111,7 +124,11 @@ remote_open (name, from_tty)
|
|||
perror_with_name (name);
|
||||
|
||||
ioctl (remote_desc, TIOCGETP, &sg);
|
||||
#ifdef HAVE_TERMIO
|
||||
sg.c_lflag &= ~ICANON;
|
||||
#else
|
||||
sg.sg_flags = RAW;
|
||||
#endif
|
||||
ioctl (remote_desc, TIOCSETP, &sg);
|
||||
|
||||
if (from_tty)
|
||||
|
@ -165,18 +182,17 @@ remote_resume (step, signal)
|
|||
|
||||
int
|
||||
remote_wait (status)
|
||||
union wait *status;
|
||||
WAITTYPE *status;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
|
||||
status->w_status = 0;
|
||||
WSETEXIT ((*status), 0);
|
||||
getpkt (buf);
|
||||
if (buf[0] == 'E')
|
||||
error ("Remote failure reply: %s", buf);
|
||||
if (buf[0] != 'S')
|
||||
error ("Invalid remote reply: %s", buf);
|
||||
status->w_stopval = WSTOPPED;
|
||||
status->w_stopsig = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
|
||||
WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
|
||||
}
|
||||
|
||||
/* Read the remote registers into the block REGS. */
|
||||
|
|
116
gdb/source.c
116
gdb/source.c
|
@ -59,16 +59,13 @@ 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))
|
||||
{
|
||||
sals = decode_line_spec ("main", 1);
|
||||
sal = sals.sals[0];
|
||||
free (sals.sals);
|
||||
sal = decode_line_spec ("main", 1);
|
||||
current_source_symtab = sal.symtab;
|
||||
current_source_line = sal.line - 9;
|
||||
return;
|
||||
|
@ -96,15 +93,12 @@ directories_info ()
|
|||
printf ("Source directories searched: %s\n", source_path);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
init_source_path ()
|
||||
{
|
||||
register struct symtab *s;
|
||||
char wd[MAXPATHLEN];
|
||||
if (getwd (wd) == NULL)
|
||||
perror_with_name ("getwd");
|
||||
|
||||
source_path = savestring (wd, strlen (wd));
|
||||
source_path = savestring (current_directory, strlen (current_directory));
|
||||
|
||||
/* Forget what we learned about line positions in source files;
|
||||
must check again now since files may be found in
|
||||
|
@ -124,13 +118,9 @@ directory_command (dirname, from_tty)
|
|||
{
|
||||
char *old = source_path;
|
||||
|
||||
char wd[MAXPATHLEN];
|
||||
if (getwd (wd) == NULL)
|
||||
perror_with_name ("getwd");
|
||||
|
||||
if (dirname == 0)
|
||||
{
|
||||
if (query ("Reinitialize source path to %s? ", wd))
|
||||
if (query ("Reinitialize source path to %s? ", current_directory))
|
||||
{
|
||||
init_source_path ();
|
||||
free (old);
|
||||
|
@ -154,7 +144,7 @@ directory_command (dirname, from_tty)
|
|||
if (len == 1)
|
||||
{
|
||||
/* "." => getwd () */
|
||||
dirname = wd;
|
||||
dirname = current_directory;
|
||||
goto append;
|
||||
}
|
||||
else if (dirname[len - 2] == '/')
|
||||
|
@ -176,7 +166,7 @@ directory_command (dirname, from_tty)
|
|||
}
|
||||
|
||||
if (dirname[0] != '/')
|
||||
dirname = concat (wd, "/", dirname);
|
||||
dirname = concat (current_directory, "/", dirname);
|
||||
else
|
||||
dirname = savestring (dirname, len);
|
||||
make_cleanup (free, dirname);
|
||||
|
@ -302,7 +292,7 @@ find_source_lines (s, desc)
|
|||
extern int exec_mtime;
|
||||
|
||||
fstat (desc, &st);
|
||||
if (get_exec_file () != 0 && exec_mtime < st.st_mtime)
|
||||
if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime)
|
||||
printf ("Source file is more recent than executable.\n");
|
||||
|
||||
data = (char *) alloca (st.st_size);
|
||||
|
@ -313,11 +303,16 @@ find_source_lines (s, desc)
|
|||
nlines = 1;
|
||||
while (p != end)
|
||||
{
|
||||
if (*p++ == '\n')
|
||||
if (*p++ == '\n'
|
||||
/* A newline at the end does not start a new line. */
|
||||
&& p != end)
|
||||
{
|
||||
if (nlines == lines_allocated)
|
||||
line_charpos = (int *) xrealloc (line_charpos,
|
||||
sizeof (int) * (lines_allocated *= 2));
|
||||
{
|
||||
lines_allocated *= 2;
|
||||
line_charpos = (int *) xrealloc (line_charpos,
|
||||
sizeof (int) * lines_allocated);
|
||||
}
|
||||
line_charpos[nlines++] = p - data;
|
||||
}
|
||||
}
|
||||
|
@ -396,18 +391,27 @@ get_filename_and_charpos (s, line, fullname)
|
|||
The text starts with two Ctrl-z so that the Emacs-GDB interface
|
||||
can easily find it.
|
||||
|
||||
MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
|
||||
|
||||
Return 1 if successful, 0 if could not find the file. */
|
||||
|
||||
int
|
||||
identify_source_line (s, line)
|
||||
identify_source_line (s, line, mid_statement)
|
||||
struct symtab *s;
|
||||
int line;
|
||||
int mid_statement;
|
||||
{
|
||||
if (s->line_charpos == 0)
|
||||
get_filename_and_charpos (s, line, 0);
|
||||
if (s->fullname == 0)
|
||||
return 0;
|
||||
printf ("\032\032%s:%d:%d\n", s->fullname, line, s->line_charpos[line - 1]);
|
||||
printf ("\032\032%s:%d:%d:%s\n", s->fullname,
|
||||
line, s->line_charpos[line - 1],
|
||||
mid_statement ? "middle" : "beg");
|
||||
current_source_line = line;
|
||||
first_line_listed = line;
|
||||
last_line_listed = line;
|
||||
current_source_symtab = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -415,9 +419,10 @@ identify_source_line (s, line)
|
|||
starting with line number LINE and stopping before line number STOPLINE. */
|
||||
|
||||
void
|
||||
print_source_lines (s, line, stopline)
|
||||
print_source_lines (s, line, stopline, noerror)
|
||||
struct symtab *s;
|
||||
int line, stopline;
|
||||
int noerror;
|
||||
{
|
||||
register int c;
|
||||
register int desc;
|
||||
|
@ -426,12 +431,18 @@ print_source_lines (s, line, stopline)
|
|||
|
||||
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
|
||||
if (desc < 0)
|
||||
perror_with_name (s->filename);
|
||||
{
|
||||
extern int errno;
|
||||
if (! noerror)
|
||||
perror_with_name (s->filename);
|
||||
print_sys_errmsg (s->filename, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->line_charpos == 0)
|
||||
find_source_lines (s, desc);
|
||||
|
||||
if (line < 1 || line >= s->nlines)
|
||||
if (line < 1 || line > s->nlines)
|
||||
{
|
||||
close (desc);
|
||||
error ("Line number out of range; %s has %d lines.",
|
||||
|
@ -479,7 +490,6 @@ 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;
|
||||
|
@ -499,7 +509,7 @@ list_command (arg, from_tty)
|
|||
if (current_source_symtab == 0)
|
||||
error ("No default source file yet. Do \"help list\".");
|
||||
print_source_lines (current_source_symtab, current_source_line,
|
||||
current_source_line + 10);
|
||||
current_source_line + 10, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -510,7 +520,7 @@ list_command (arg, from_tty)
|
|||
error ("No default source file yet. Do \"help list\".");
|
||||
print_source_lines (current_source_symtab,
|
||||
max (first_line_listed - 10, 1),
|
||||
first_line_listed);
|
||||
first_line_listed, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -524,18 +534,7 @@ list_command (arg, from_tty)
|
|||
if (*arg1 == ',')
|
||||
dummy_beg = 1;
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
sal = decode_line_1 (&arg1, 0, 0, 0);
|
||||
|
||||
/* Record whether the BEG arg is all digits. */
|
||||
|
||||
|
@ -552,16 +551,10 @@ 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
|
||||
{
|
||||
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);
|
||||
}
|
||||
sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
|
||||
}
|
||||
|
||||
if (*arg1)
|
||||
|
@ -607,14 +600,15 @@ list_command (arg, from_tty)
|
|||
error ("No default source file yet. Do \"help list\".");
|
||||
if (dummy_beg)
|
||||
print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
|
||||
sal_end.line + 1);
|
||||
sal_end.line + 1, 0);
|
||||
else if (sal.symtab == 0)
|
||||
error ("No default source file yet. Do \"help list\".");
|
||||
else if (no_end)
|
||||
print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5);
|
||||
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);
|
||||
dummy_end ? sal.line + 10 : sal_end.line + 1,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Print info on range of pc's in a specified line. */
|
||||
|
@ -624,7 +618,6 @@ 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;
|
||||
|
||||
|
@ -635,15 +628,8 @@ line_info (arg, from_tty)
|
|||
}
|
||||
else
|
||||
{
|
||||
sals = decode_line_spec (arg);
|
||||
sal = decode_line_spec (arg, 0);
|
||||
|
||||
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. */
|
||||
|
||||
|
@ -701,7 +687,7 @@ forward_search_command (regex, from_tty)
|
|||
if (current_source_symtab->line_charpos == 0)
|
||||
find_source_lines (current_source_symtab, desc);
|
||||
|
||||
if (line < 1 || line >= current_source_symtab->nlines)
|
||||
if (line < 1 || line > current_source_symtab->nlines)
|
||||
{
|
||||
close (desc);
|
||||
error ("Expression not found");
|
||||
|
@ -733,7 +719,7 @@ forward_search_command (regex, from_tty)
|
|||
/* Match! */
|
||||
fclose (stream);
|
||||
print_source_lines (current_source_symtab,
|
||||
line, line+1);
|
||||
line, line+1, 0);
|
||||
current_source_line = max (line - 5, 1);
|
||||
return;
|
||||
}
|
||||
|
@ -771,7 +757,7 @@ reverse_search_command (regex, from_tty)
|
|||
if (current_source_symtab->line_charpos == 0)
|
||||
find_source_lines (current_source_symtab, desc);
|
||||
|
||||
if (line < 1 || line >= current_source_symtab->nlines)
|
||||
if (line < 1 || line > current_source_symtab->nlines)
|
||||
{
|
||||
close (desc);
|
||||
error ("Expression not found");
|
||||
|
@ -804,7 +790,7 @@ reverse_search_command (regex, from_tty)
|
|||
/* Match! */
|
||||
fclose (stream);
|
||||
print_source_lines (current_source_symtab,
|
||||
line, line+1);
|
||||
line, line+1, 0);
|
||||
current_source_line = max (line - 5, 1);
|
||||
return;
|
||||
}
|
||||
|
|
14
gdb/stack.c
14
gdb/stack.c
|
@ -120,12 +120,15 @@ print_frame_info (fi, level, source, args)
|
|||
if (source != 0 && sal.symtab)
|
||||
{
|
||||
int done = 0;
|
||||
if (source < 0 && fi->pc != sal.pc)
|
||||
printf ("0x%x\t", fi->pc);
|
||||
int mid_statement = source < 0 && fi->pc != sal.pc;
|
||||
if (frame_file_full_name)
|
||||
done = identify_source_line (sal.symtab, sal.line);
|
||||
done = identify_source_line (sal.symtab, sal.line, mid_statement);
|
||||
if (!done)
|
||||
print_source_lines (sal.symtab, sal.line, sal.line + 1);
|
||||
{
|
||||
if (mid_statement)
|
||||
printf ("0x%x\t", fi->pc);
|
||||
print_source_lines (sal.symtab, sal.line, sal.line + 1, 1);
|
||||
}
|
||||
current_source_line = max (sal.line - 5, 1);
|
||||
}
|
||||
if (source != 0)
|
||||
|
@ -278,7 +281,8 @@ print_block_frame_locals (b, frame, stream)
|
|||
{
|
||||
sym = BLOCK_SYM (b, i);
|
||||
if (SYMBOL_CLASS (sym) == LOC_LOCAL
|
||||
|| SYMBOL_CLASS (sym) == LOC_REGISTER)
|
||||
|| SYMBOL_CLASS (sym) == LOC_REGISTER
|
||||
|| SYMBOL_CLASS (sym) == LOC_STATIC)
|
||||
{
|
||||
fprintf (stream, "%s = ", SYMBOL_NAME (sym));
|
||||
print_variable_value (sym, frame, stream);
|
||||
|
|
|
@ -341,7 +341,8 @@ core_file_command ()
|
|||
{}
|
||||
|
||||
char *
|
||||
get_exec_file ()
|
||||
get_exec_file (err)
|
||||
int err;
|
||||
{
|
||||
/* Makes one printout look reasonable; value does not matter otherwise. */
|
||||
return "run";
|
||||
|
|
|
@ -397,6 +397,8 @@ print_symtabs (filename)
|
|||
if (filename == 0)
|
||||
error_no_arg ("file to write symbol data in");
|
||||
outfile = fopen (filename, "w");
|
||||
if (outfile == 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
cleanups = make_cleanup (fclose, outfile);
|
||||
immediate_quit++;
|
||||
|
|
85
gdb/symseg.h
85
gdb/symseg.h
|
@ -1,6 +1,5 @@
|
|||
/* 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
|
||||
|
@ -118,10 +117,6 @@ 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. */
|
||||
|
@ -149,22 +144,11 @@ 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:
|
||||
TYPE_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. */
|
||||
struct type *main_variant;
|
||||
|
||||
/* Flags about this type. */
|
||||
short flags;
|
||||
/* Number of fields described for this type */
|
||||
|
@ -201,75 +185,6 @@ struct type
|
|||
Zero for range bounds and array domains. */
|
||||
char *name;
|
||||
} *fields;
|
||||
|
||||
/* C++ */
|
||||
int *private_field_bits;
|
||||
int *protected_field_bits;
|
||||
|
||||
/* Some flags to make life easier. */
|
||||
unsigned char has_constructor;
|
||||
unsigned char has_destructor;
|
||||
|
||||
/* Number of methods described for this type */
|
||||
short nfn_fields;
|
||||
|
||||
/* 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;
|
||||
|
||||
unsigned char via_protected;
|
||||
unsigned char via_public;
|
||||
|
||||
/* 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 a base class, put it here.
|
||||
If this type is a pointer type, the chain of member pointer
|
||||
types goes here.
|
||||
Unused otherwise. */
|
||||
struct type *baseclass;
|
||||
};
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
|
|
592
gdb/symtab.c
592
gdb/symtab.c
|
@ -139,7 +139,7 @@ lookup_struct (name, block)
|
|||
if (sym == 0)
|
||||
error ("No struct type named %s.", name);
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
|
||||
error ("This context has class, union or enum %s, not a struct.", name);
|
||||
error ("This context has union or enum %s, not a struct.", name);
|
||||
return SYMBOL_TYPE (sym);
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ lookup_union (name, block)
|
|||
if (sym == 0)
|
||||
error ("No union type named %s.", name);
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
|
||||
error ("This context has class, struct or enum %s, not a union.", name);
|
||||
error ("This context has struct or enum %s, not a union.", name);
|
||||
return SYMBOL_TYPE (sym);
|
||||
}
|
||||
|
||||
|
@ -171,22 +171,19 @@ lookup_enum (name, block)
|
|||
if (sym == 0)
|
||||
error ("No enum type named %s.", name);
|
||||
if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
|
||||
error ("This context has class, struct or union %s, not an enum.", name);
|
||||
error ("This context has struct or union %s, not an enum.", name);
|
||||
return SYMBOL_TYPE (sym);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
||||
C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer
|
||||
to member types under control. */
|
||||
May need to construct such a type if this is the first use. */
|
||||
|
||||
struct type *
|
||||
lookup_pointer_type (type)
|
||||
struct type *type;
|
||||
{
|
||||
register struct type *ptype = TYPE_POINTER_TYPE (type);
|
||||
if (ptype) return TYPE_MAIN_VARIANT (ptype);
|
||||
if (ptype) return ptype;
|
||||
|
||||
/* This is the first time anyone wanted a pointer to a TYPE. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
|
@ -196,7 +193,6 @@ 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. */
|
||||
|
@ -208,91 +204,12 @@ 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 (type, domain)
|
||||
struct type *type, *domain;
|
||||
{
|
||||
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_CHAIN (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));
|
||||
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;
|
||||
|
||||
/* Now splice in the new member pointer type. */
|
||||
if (main_type)
|
||||
{
|
||||
/* This type was not "smashed". */
|
||||
TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
|
||||
TYPE_CHAIN (main_type) = mtype;
|
||||
}
|
||||
|
||||
return mtype;
|
||||
}
|
||||
|
||||
/* 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, argtypes)
|
||||
lookup_function_type (type)
|
||||
struct type *type;
|
||||
struct type **argtypes;
|
||||
{
|
||||
register struct type *ptype = TYPE_FUNCTION_TYPE (type);
|
||||
if (ptype) return ptype;
|
||||
|
@ -330,8 +247,6 @@ 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))
|
||||
{
|
||||
|
@ -339,46 +254,6 @@ 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. */
|
||||
|
@ -406,62 +281,6 @@ 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;
|
||||
|
@ -505,7 +324,7 @@ lookup_symbol (name, block, namespace)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Look for a symbol in block BLOCK using binary search. */
|
||||
/* Look for a symbol in block BLOCK. */
|
||||
|
||||
static struct symbol *
|
||||
lookup_block_symbol (block, name, namespace)
|
||||
|
@ -519,39 +338,67 @@ lookup_block_symbol (block, name, namespace)
|
|||
top = BLOCK_NSYMS (block);
|
||||
bot = 0;
|
||||
|
||||
/* First, advance BOT to not far before
|
||||
the first symbol whose name is NAME. */
|
||||
/* If the blocks's symbols were sorted, start with a binary search. */
|
||||
|
||||
while (1)
|
||||
if (BLOCK_SHOULD_SORT (block))
|
||||
{
|
||||
inc = (top - bot + 1);
|
||||
/* No need to keep binary searching for the last few bits worth. */
|
||||
if (inc < 7)
|
||||
break;
|
||||
inc >>= 1;
|
||||
sym = BLOCK_SYM (block, bot + inc);
|
||||
if (strcmp (SYMBOL_NAME (sym), name) < 0)
|
||||
bot += inc;
|
||||
else
|
||||
top = bot + inc;
|
||||
/* First, advance BOT to not far before
|
||||
the first symbol whose name is NAME. */
|
||||
|
||||
while (1)
|
||||
{
|
||||
inc = (top - bot + 1);
|
||||
/* No need to keep binary searching for the last few bits worth. */
|
||||
if (inc < 4)
|
||||
break;
|
||||
inc = (inc >> 1) + bot;
|
||||
sym = BLOCK_SYM (block, inc);
|
||||
if (SYMBOL_NAME (sym)[0] < name[0])
|
||||
bot = inc;
|
||||
else if (SYMBOL_NAME (sym)[0] > name[0])
|
||||
top = inc;
|
||||
else if (strcmp (SYMBOL_NAME (sym), name) < 0)
|
||||
bot = inc;
|
||||
else
|
||||
top = inc;
|
||||
}
|
||||
|
||||
/* Now scan forward until we run out of symbols,
|
||||
find one whose name is greater than NAME,
|
||||
or find one we want.
|
||||
If there is more than one symbol with the right name and namespace,
|
||||
we return the first one. dbxread.c is careful to make sure
|
||||
that if one is a register then it comes first. */
|
||||
|
||||
top = BLOCK_NSYMS (block);
|
||||
while (bot < top)
|
||||
{
|
||||
sym = BLOCK_SYM (block, bot);
|
||||
inc = SYMBOL_NAME (sym)[0] - name[0];
|
||||
if (inc == 0)
|
||||
inc = strcmp (SYMBOL_NAME (sym), name);
|
||||
if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
|
||||
return sym;
|
||||
if (inc > 0)
|
||||
return 0;
|
||||
bot++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now scan forward until we run out of symbols,
|
||||
find one whose name is greater than NAME,
|
||||
or find one we want.
|
||||
If there is more than one symbol with the right name and namespace,
|
||||
we return the first one. dbxread.c is careful to make sure
|
||||
that if one is a register then it comes first. */
|
||||
/* Here if block isn't sorted.
|
||||
This loop is equivalent to the loop above,
|
||||
but hacked greatly for speed. */
|
||||
|
||||
top = BLOCK_NSYMS (block);
|
||||
inc = name[0];
|
||||
while (bot < top)
|
||||
{
|
||||
sym = BLOCK_SYM (block, bot);
|
||||
inc = strcmp (SYMBOL_NAME (sym), name);
|
||||
if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
|
||||
if (SYMBOL_NAME (sym)[0] == inc
|
||||
&& !strcmp (SYMBOL_NAME (sym), name)
|
||||
&& SYMBOL_NAMESPACE (sym) == namespace)
|
||||
return sym;
|
||||
if (inc > 0)
|
||||
return 0;
|
||||
bot++;
|
||||
}
|
||||
return 0;
|
||||
|
@ -895,15 +742,13 @@ 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 symtabs_and_lines
|
||||
struct symtab_and_line
|
||||
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;
|
||||
|
@ -911,14 +756,7 @@ 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. */
|
||||
|
||||
if (default_symtab == 0)
|
||||
|
@ -933,11 +771,9 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
{
|
||||
(*argptr)++;
|
||||
pc = parse_and_eval_address_1 (argptr);
|
||||
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;
|
||||
value = find_pc_line (pc, 0);
|
||||
value.pc = pc;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
|
||||
|
@ -953,125 +789,6 @@ 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)
|
||||
{
|
||||
int constructor_p;
|
||||
|
||||
class_name = TYPE_NAME (t);
|
||||
while (*class_name++ != ' ');
|
||||
|
||||
constructor_p = ! strcmp (class_name, copy);
|
||||
|
||||
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 + constructor_p);
|
||||
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++;
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS(t);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1138,10 +855,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
s = default_symtab;
|
||||
value.symtab = s;
|
||||
value.pc = 0;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Arg token is not digits => try it as a function name
|
||||
|
@ -1168,10 +882,7 @@ 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;
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
if (sym)
|
||||
|
@ -1186,10 +897,7 @@ 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);
|
||||
values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
|
||||
values.sals[0] = value;
|
||||
values.nelts = 1;
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
if (symtab_list == 0)
|
||||
|
@ -1197,114 +905,19 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
|||
error ("Function %s not defined.", copy);
|
||||
}
|
||||
|
||||
struct symtabs_and_lines
|
||||
struct symtab_and_line
|
||||
decode_line_spec (string, funfirstline)
|
||||
char *string;
|
||||
int funfirstline;
|
||||
{
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
if (string == 0)
|
||||
error ("Empty line specification.");
|
||||
sals = decode_line_1 (&string, funfirstline,
|
||||
current_source_symtab, current_source_line);
|
||||
sal = decode_line_1 (&string, funfirstline,
|
||||
current_source_symtab, current_source_line);
|
||||
if (*string)
|
||||
error ("Junk at end of line specification: %s", string);
|
||||
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 sal;
|
||||
}
|
||||
|
||||
/* Return the index of misc function named NAME. */
|
||||
|
@ -1369,6 +982,8 @@ sources_info ()
|
|||
fflush (stdout); \
|
||||
read_line (); } }
|
||||
|
||||
static void sort_block_syms ();
|
||||
|
||||
static void
|
||||
list_symbols (regexp, class)
|
||||
char *regexp;
|
||||
|
@ -1383,7 +998,7 @@ list_symbols (regexp, class)
|
|||
char *val;
|
||||
int found_in_file;
|
||||
static char *classnames[]
|
||||
= {"variable", "function", "type", "method"};
|
||||
= {"variable", "function", "type"};
|
||||
int print_count = 0;
|
||||
|
||||
if (regexp)
|
||||
|
@ -1409,6 +1024,9 @@ list_symbols (regexp, class)
|
|||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bv, i);
|
||||
/* Skip the sort if this block is always sorted. */
|
||||
if (!BLOCK_SHOULD_SORT (b))
|
||||
sort_block_syms (b);
|
||||
for (j = 0; j < BLOCK_NSYMS (b); j++)
|
||||
{
|
||||
QUIT;
|
||||
|
@ -1417,8 +1035,7 @@ 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 == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
|
||||
|| (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)))
|
||||
{
|
||||
if (!found_in_file)
|
||||
{
|
||||
|
@ -1433,30 +1050,17 @@ list_symbols (regexp, class)
|
|||
&& SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
|
||||
printf ("typedef ");
|
||||
|
||||
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
|
||||
}
|
||||
type_print (SYMBOL_TYPE (sym),
|
||||
(SYMBOL_CLASS (sym) == LOC_TYPEDEF
|
||||
? "" : SYMBOL_NAME (sym)),
|
||||
stdout, 0);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1484,12 +1088,27 @@ types_info (regexp)
|
|||
{
|
||||
list_symbols (regexp, 2);
|
||||
}
|
||||
|
||||
/* Call sort_block_syms to sort alphabetically the symbols of one block. */
|
||||
|
||||
static int
|
||||
compare_symbols (s1, s2)
|
||||
struct symbol **s1, **s2;
|
||||
{
|
||||
/* Names that are less should come first. */
|
||||
register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2));
|
||||
if (namediff != 0) return namediff;
|
||||
/* For symbols of the same name, registers should come first. */
|
||||
return ((SYMBOL_CLASS (*s2) == LOC_REGISTER)
|
||||
- (SYMBOL_CLASS (*s1) == LOC_REGISTER));
|
||||
}
|
||||
|
||||
static void
|
||||
methods_info (regexp)
|
||||
char *regexp;
|
||||
sort_block_syms (b)
|
||||
register struct block *b;
|
||||
{
|
||||
list_symbols (regexp, 3);
|
||||
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
|
||||
sizeof (struct symbol *), compare_symbols);
|
||||
}
|
||||
|
||||
/* Initialize the standard C scalar types. */
|
||||
|
@ -1505,7 +1124,6 @@ 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;
|
||||
|
@ -1513,9 +1131,6 @@ init_type (code, length, uns, name)
|
|||
TYPE_NFIELDS (type) = 0;
|
||||
TYPE_NAME (type) = name;
|
||||
|
||||
/* C++ fancies. */
|
||||
TYPE_NFN_FIELDS (type) = 0;
|
||||
TYPE_BASECLASS (type) = 0;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -1528,11 +1143,6 @@ 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.");
|
||||
|
||||
|
|
78
gdb/symtab.h
78
gdb/symtab.h
|
@ -53,8 +53,8 @@ int misc_function_count;
|
|||
|
||||
#include "symseg.h"
|
||||
|
||||
/* Each source file is represented by a struct symtab. */
|
||||
/* These objects are chained through the `next' field. */
|
||||
/* Each source file is represented by a struct symtab.
|
||||
These objects are chained through the `next' field. */
|
||||
|
||||
struct symtab
|
||||
{
|
||||
|
@ -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 of storage to be freed, if nonzero. */
|
||||
/* Pointer to one block storage to be freed, if nonzero. */
|
||||
char *free_ptr;
|
||||
/* Total number of lines found in source file. */
|
||||
int nlines;
|
||||
|
@ -132,6 +132,9 @@ int current_source_line;
|
|||
#define BLOCK_FUNCTION(bl) (bl)->function
|
||||
#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
|
||||
|
||||
/* Nonzero if symbols of block BL should be sorted alphabetically. */
|
||||
#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40)
|
||||
|
||||
#define SYMBOL_NAME(symbol) (symbol)->name
|
||||
#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
|
||||
#define SYMBOL_CLASS(symbol) (symbol)->class
|
||||
|
@ -145,34 +148,16 @@ 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_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_BASECLASS(thistype) (thistype)->baseclass
|
||||
#define TYPE_VIA_PUBLIC(thistype) (thistype)->via_public
|
||||
#define TYPE_VIA_PROTECTED(thistype) (thistype)->via_protected
|
||||
#define TYPE_CHAIN(thistype) (thistype)->baseclass
|
||||
|
||||
#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
|
||||
#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
|
||||
|
@ -181,46 +166,11 @@ 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)->has_destructor)
|
||||
#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->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 ();
|
||||
|
@ -232,12 +182,6 @@ 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;
|
||||
|
@ -258,12 +202,6 @@ 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. */
|
||||
|
@ -273,5 +211,5 @@ struct symtab_and_line find_pc_line ();
|
|||
/* Given a string, return the line specified by it.
|
||||
For commands like "list" and "breakpoint". */
|
||||
|
||||
struct symtabs_and_lines decode_line_spec ();
|
||||
struct symtabs_and_lines decode_line_1 ();
|
||||
struct symtab_and_line decode_line_spec ();
|
||||
struct symtab_and_line decode_line_1 ();
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/user.h>
|
||||
#include <stdio.h>
|
||||
|
||||
main ()
|
||||
{
|
||||
struct user u;
|
||||
printf ("&u.u_ar0 - &u = %d, 0%o\n", (int) &u.u_ar0 - (int) &u,
|
||||
(int) &u.u_ar0 - (int) &u);
|
||||
printf ("sizeof (struct pcb) = %d, 0%o\n",
|
||||
sizeof (struct pcb), sizeof (struct pcb));
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
struct foo
|
||||
{
|
||||
unsigned bar : 1;
|
||||
unsigned lose : 1;
|
||||
};
|
||||
|
||||
main ()
|
||||
{
|
||||
struct foo *win;
|
||||
|
||||
printf ("%d, %d\n", win->bar, win->lose);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* Run this program straight. Then set a breakpoint in `dump',
|
||||
run it again, and continue the program. Diff the outputs
|
||||
and you will see what the supplied debugger does for a breakpoint. */
|
||||
|
||||
int dump ();
|
||||
int after_dump ();
|
||||
|
||||
main ()
|
||||
{
|
||||
printf ("main = 0x%x\ndump = 0x%x\nend = 0x%x\n", main, dump, after_dump);
|
||||
|
||||
dump (main, after_dump);
|
||||
}
|
||||
|
||||
int dump (p, q)
|
||||
int *p;
|
||||
int *q;
|
||||
{
|
||||
int cnt = 0;
|
||||
printf ("dump: 0x%x-0x%x\n", p, q);
|
||||
|
||||
while (p < q)
|
||||
{
|
||||
if ((cnt++ & 3) == 0)
|
||||
printf ("\n0x%08x: ", p);
|
||||
printf ("0x%08x ", *p++);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
after_dump ()
|
||||
{
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
main()
|
||||
{
|
||||
printf("foo\n");
|
||||
}
|
21
gdb/utils.c
21
gdb/utils.c
|
@ -19,8 +19,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#ifdef HAVE_TERMIO
|
||||
#include <termio.h>
|
||||
#endif
|
||||
|
||||
void error ();
|
||||
void fatal ();
|
||||
|
@ -191,8 +196,16 @@ void
|
|||
quit ()
|
||||
{
|
||||
fflush (stdout);
|
||||
#ifdef HAVE_TERMIO
|
||||
ioctl (fileno (stdout), TCFLSH, 1);
|
||||
#else /* not HAVE_TERMIO */
|
||||
ioctl (fileno (stdout), TIOCFLUSH, 0);
|
||||
#endif /* not HAVE_TERMIO */
|
||||
#ifdef TIOCGPGRP
|
||||
error ("Quit");
|
||||
#else
|
||||
error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
|
||||
#endif /* TIOCGPGRP */
|
||||
}
|
||||
|
||||
/* Control C comes here */
|
||||
|
@ -386,10 +399,14 @@ parse_escape (string_ptr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Print the character CH on STREAM as part of the contents
|
||||
of a literal string whose delimiter is QUOTER. */
|
||||
|
||||
void
|
||||
printchar (ch, stream)
|
||||
printchar (ch, stream, quoter)
|
||||
unsigned char ch;
|
||||
FILE *stream;
|
||||
int quoter;
|
||||
{
|
||||
register int c = ch;
|
||||
if (c < 040 || c >= 0177)
|
||||
|
@ -413,7 +430,7 @@ printchar (ch, stream)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (c == '\\' || c == '"' || c == '\'')
|
||||
if (c == '\\' || c == quoter)
|
||||
fputc ('\\', stream);
|
||||
fputc (c, stream);
|
||||
}
|
||||
|
|
163
gdb/valarith.c
163
gdb/valarith.c
|
@ -107,162 +107,7 @@ 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 */
|
||||
|
||||
int
|
||||
binop_must_be_user_defined (arg1, arg2)
|
||||
value arg1, arg2;
|
||||
{
|
||||
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 */
|
||||
|
||||
int unop_must_be_user_defined (arg1)
|
||||
value arg1;
|
||||
{
|
||||
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. */
|
||||
|
@ -374,14 +219,6 @@ 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.");
|
||||
}
|
||||
|
|
452
gdb/valops.c
452
gdb/valops.c
|
@ -17,7 +17,7 @@ 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 "initialize.h"
|
||||
#include "param.h"
|
||||
|
@ -60,9 +60,7 @@ value_cast (type, arg2)
|
|||
return arg2;
|
||||
}
|
||||
else if (VALUE_LVAL (arg2) == lval_memory)
|
||||
{
|
||||
return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
|
||||
}
|
||||
return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
|
||||
else
|
||||
error ("Invalid cast.");
|
||||
}
|
||||
|
@ -280,9 +278,6 @@ value_ind (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,
|
||||
|
@ -290,9 +285,6 @@ 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.");
|
||||
}
|
||||
|
||||
|
@ -419,14 +411,6 @@ call_function (function, nargs, args)
|
|||
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)
|
||||
{
|
||||
|
@ -568,24 +552,16 @@ 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.
|
||||
|
||||
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. */
|
||||
ERR is used in the error message if ARG1's type is wrong. */
|
||||
|
||||
value
|
||||
value_struct_elt (arg1, args, name, err)
|
||||
register value arg1, *args;
|
||||
value_struct_elt (arg1, name, err)
|
||||
register value arg1;
|
||||
char *name;
|
||||
char *err;
|
||||
{
|
||||
register struct type *t;
|
||||
register int i;
|
||||
int found = 0;
|
||||
|
||||
struct type *baseclass;
|
||||
|
||||
COERCE_ARRAY (arg1);
|
||||
|
||||
|
@ -593,428 +569,28 @@ value_struct_elt (arg1, args, name, err)
|
|||
|
||||
/* Follow pointers until we get to a non-pointer. */
|
||||
|
||||
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
|
||||
while (TYPE_CODE (t) == TYPE_CODE_PTR)
|
||||
{
|
||||
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)
|
||||
&&
|
||||
TYPE_CODE (t) != TYPE_CODE_UNION)
|
||||
error ("Attempt to extract a component of a value that is not a %s.", err);
|
||||
|
||||
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);
|
||||
|
||||
t = TYPE_BASECLASS (t);
|
||||
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);
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
error("there is no field named %s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (destructor_name_p (name, t))
|
||||
for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
|
||||
{
|
||||
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");
|
||||
}
|
||||
if (!strcmp (TYPE_FIELD_NAME (t, i), name))
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 (i < 0)
|
||||
error ("Structure has no component named %s.", name);
|
||||
|
||||
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))
|
||||
{
|
||||
/* 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 (t);
|
||||
|
||||
if (TYPE_VPTR_FIELDNO (t) < 0)
|
||||
TYPE_VPTR_FIELDNO (t)
|
||||
= fill_in_vptr_fieldno (t);
|
||||
|
||||
vtbl = value_field (arg1, TYPE_VPTR_FIELDNO (t));
|
||||
vfn = value_subscript (vtbl, vi);
|
||||
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
|
||||
return vfn;
|
||||
}
|
||||
else
|
||||
return (value)value_fn_field (arg1, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
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);
|
||||
|
||||
t = TYPE_BASECLASS (t);
|
||||
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;
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
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;
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
}
|
||||
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_member_type (TYPE_FIELD_TYPE (t, i), baseclass);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
}
|
||||
|
||||
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_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
t = TYPE_BASECLASS (t);
|
||||
}
|
||||
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);
|
||||
return value_field (arg1, i);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
458
gdb/valprint.c
458
gdb/valprint.c
|
@ -1,5 +1,5 @@
|
|||
/* Print values for GNU debugger gdb.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 1988 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
|
@ -21,6 +21,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "initialize.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "value.h"
|
||||
|
||||
|
@ -32,7 +33,6 @@ 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
|
||||
|
||||
|
@ -41,12 +41,14 @@ char **signed_type_table;
|
|||
char **float_type_table;
|
||||
|
||||
/* Print the value VAL in C-ish syntax on stream STREAM.
|
||||
FORMAT is a format-letter, or 0 for print in natural format of data type.
|
||||
If the object printed is a string pointer, returns
|
||||
the number of string bytes printed. */
|
||||
|
||||
value_print (val, stream)
|
||||
value_print (val, stream, format)
|
||||
value val;
|
||||
FILE *stream;
|
||||
char format;
|
||||
{
|
||||
register int i, n, typelen;
|
||||
|
||||
|
@ -60,14 +62,14 @@ value_print (val, stream)
|
|||
typelen = TYPE_LENGTH (VALUE_TYPE (val));
|
||||
fputc ('{', stream);
|
||||
/* Print arrays of characters using string syntax. */
|
||||
if (VALUE_TYPE (val) == builtin_type_char
|
||||
|| VALUE_TYPE (val) == builtin_type_unsigned_char)
|
||||
if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
|
||||
&& format == 0)
|
||||
{
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < n && i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
printchar (VALUE_CONTENTS (val)[i], stream);
|
||||
printchar (VALUE_CONTENTS (val)[i], stream, '"');
|
||||
}
|
||||
if (i < n)
|
||||
fprintf (stream, "...");
|
||||
|
@ -80,7 +82,7 @@ value_print (val, stream)
|
|||
if (i)
|
||||
fprintf (stream, ", ");
|
||||
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i,
|
||||
VALUE_ADDRESS (val) + typelen * i, stream);
|
||||
VALUE_ADDRESS (val) + typelen * i, stream, format);
|
||||
}
|
||||
if (i < n)
|
||||
fprintf (stream, "...");
|
||||
|
@ -89,10 +91,8 @@ value_print (val, stream)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* If it is a pointer, indicate what it points to.
|
||||
|
||||
C++: if it is a member pointer, we will take care
|
||||
of that when we print it. */
|
||||
/* A simple (nonrepeated) value */
|
||||
/* If it is a pointer, indicate what it points to. */
|
||||
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
|
||||
{
|
||||
fprintf (stream, "(");
|
||||
|
@ -100,24 +100,25 @@ value_print (val, stream)
|
|||
fprintf (stream, ") ");
|
||||
}
|
||||
return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
|
||||
VALUE_ADDRESS (val), stream);
|
||||
VALUE_ADDRESS (val), stream, format);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print on STREAM data stored in debugger at address VALADDR
|
||||
according to the format of type TYPE.
|
||||
ADDRESS is the location in the inferior that the data
|
||||
is supposed to have come from.
|
||||
/* Print data of type TYPE located at VALADDR (within GDB),
|
||||
which came from the inferior at address ADDRESS,
|
||||
onto stdio stream STREAM according to FORMAT
|
||||
(a letter or 0 for natural format).
|
||||
|
||||
If the data are a string pointer, returns the number of
|
||||
sting characters printed. */
|
||||
|
||||
int
|
||||
val_print (type, valaddr, address, stream)
|
||||
val_print (type, valaddr, address, stream, format)
|
||||
struct type *type;
|
||||
char *valaddr;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
char format;
|
||||
{
|
||||
register int i;
|
||||
int len;
|
||||
|
@ -138,14 +139,14 @@ val_print (type, valaddr, address, stream)
|
|||
len = TYPE_LENGTH (type) / eltlen;
|
||||
fprintf (stream, "{");
|
||||
/* For an array of chars, print with string syntax. */
|
||||
if (elttype == builtin_type_char
|
||||
|| elttype == builtin_type_unsigned_char)
|
||||
if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
|
||||
&& format == 0)
|
||||
{
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < len && i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
printchar (valaddr[i], stream);
|
||||
printchar (valaddr[i], stream, '"');
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "...");
|
||||
|
@ -157,7 +158,7 @@ val_print (type, valaddr, address, stream)
|
|||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
val_print (elttype, valaddr + i * eltlen,
|
||||
0, stream);
|
||||
0, stream, format);
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "...");
|
||||
|
@ -168,208 +169,68 @@ val_print (type, valaddr, address, stream)
|
|||
/* Array of unspecified length: treat like pointer. */
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
|
||||
if (format)
|
||||
{
|
||||
struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
|
||||
struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
|
||||
struct fn_field *f;
|
||||
int j, len2;
|
||||
char *kind = "";
|
||||
|
||||
val = unpack_long (builtin_type_int, valaddr);
|
||||
if (TYPE_CODE (target) == TYPE_CODE_FUNC)
|
||||
{
|
||||
if (val < 128)
|
||||
{
|
||||
len = TYPE_NFN_FIELDS (domain);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
f = TYPE_FN_FIELDLIST1 (domain, i);
|
||||
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
if (TYPE_FN_FIELD_VOFFSET (f, j) == val)
|
||||
{
|
||||
kind = "virtual";
|
||||
goto common;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct symbol *sym = find_pc_function (val);
|
||||
if (sym == 0)
|
||||
error ("invalid pointer to member function");
|
||||
len = TYPE_NFN_FIELDS (domain);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
f = TYPE_FN_FIELDLIST1 (domain, i);
|
||||
len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
|
||||
goto common;
|
||||
}
|
||||
}
|
||||
}
|
||||
common:
|
||||
if (i < len)
|
||||
{
|
||||
fputc ('&', stream);
|
||||
type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
|
||||
fprintf (stream, kind);
|
||||
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
|
||||
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
|
||||
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
|
||||
else
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j), "",
|
||||
TYPE_FN_FIELDLIST_NAME (domain, i), stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* VAL is a byte offset into the structure type DOMAIN.
|
||||
Find the name of the field for that offset and
|
||||
print it. */
|
||||
int extra = 0;
|
||||
int bits = 0;
|
||||
len = TYPE_NFIELDS (domain);
|
||||
val <<= 3; /* @@ Make VAL into bit offset */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
int bitpos = TYPE_FIELD_BITPOS (domain, i);
|
||||
QUIT;
|
||||
if (val == bitpos)
|
||||
break;
|
||||
if (val < bitpos && i > 0)
|
||||
{
|
||||
int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
|
||||
/* Somehow pointing into a field. */
|
||||
i -= 1;
|
||||
extra = (val - TYPE_FIELD_BITPOS (domain, i));
|
||||
if (extra & 0x3)
|
||||
bits = 1;
|
||||
else
|
||||
extra >>= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
fputc ('&', stream);
|
||||
type_print_base (domain, stream, 0, 0);
|
||||
fprintf (stream, "::");
|
||||
fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
|
||||
if (extra)
|
||||
fprintf (stream, " + %d bytes", extra);
|
||||
if (bits)
|
||||
fprintf (stream, " (offset in bits)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
fputc ('(', stream);
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf (stream, ") %d", val >> 3);
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
fprintf (stream, "0x%x", * (int *) valaddr);
|
||||
/* For a pointer to char or unsigned char,
|
||||
also print the string pointed to, unless pointer is null. */
|
||||
if ((TYPE_TARGET_TYPE (type) == builtin_type_char
|
||||
|| TYPE_TARGET_TYPE (type) == builtin_type_unsigned_char)
|
||||
&& unpack_long (type, valaddr) != 0)
|
||||
fputc (' ', stream);
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < print_max; i++)
|
||||
{
|
||||
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);
|
||||
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 (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr);
|
||||
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
|
||||
VALUE_ADDRESS (val), stream);
|
||||
}
|
||||
else
|
||||
fprintf (stream, "???");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
if (TYPE_BASECLASS (type))
|
||||
{
|
||||
i = 1;
|
||||
fprintf (stream, "<%s> = ", TYPE_NAME (TYPE_BASECLASS (type)));
|
||||
val_print (TYPE_FIELD_TYPE (type, 0),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, 0) / 8,
|
||||
0, stream);
|
||||
|
||||
}
|
||||
else i = 0;
|
||||
for (; i < len; i++)
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
|
||||
/* check if static field */
|
||||
if (TYPE_FIELD_STATIC (type, i))
|
||||
{
|
||||
value v;
|
||||
|
||||
v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
VALUE_CONTENTS (v), 0, stream);
|
||||
}
|
||||
else if (TYPE_FIELD_PACKED (type, i))
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
val = unpack_field_as_long (type, valaddr, i);
|
||||
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream);
|
||||
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format);
|
||||
}
|
||||
else
|
||||
{
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
|
||||
0, stream);
|
||||
}
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
|
||||
0, stream, format);
|
||||
}
|
||||
fprintf (stream, "}");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (builtin_type_int, valaddr);
|
||||
for (i = 0; i < len; i++)
|
||||
|
@ -385,6 +246,11 @@ val_print (type, valaddr, address, stream)
|
|||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
fprintf (stream, "{");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf (stream, "} ");
|
||||
|
@ -392,19 +258,28 @@ val_print (type, valaddr, address, stream)
|
|||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
fprintf (stream,
|
||||
TYPE_UNSIGNED (type) ? "%u" : "%d",
|
||||
unpack_long (type, valaddr));
|
||||
if (type == builtin_type_char
|
||||
|| type == builtin_type_unsigned_char)
|
||||
if (TYPE_LENGTH (type) == 1)
|
||||
{
|
||||
fprintf (stream, " '");
|
||||
printchar (unpack_long (type, valaddr), stream);
|
||||
printchar (unpack_long (type, valaddr), stream, '\'');
|
||||
fputc ('\'', stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
#ifdef IEEE_FLOAT
|
||||
if (is_nan (unpack_double (type, valaddr)))
|
||||
{
|
||||
|
@ -492,46 +367,13 @@ 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_MEMBER
|
||||
|| code == TYPE_CODE_REF)))
|
||||
|| code == TYPE_CODE_ARRAY)))
|
||||
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, ")");
|
||||
}
|
||||
|
||||
/* Print any asterisks or open-parentheses needed before the
|
||||
variable name (to describe its type).
|
||||
|
||||
|
@ -547,6 +389,9 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr)
|
|||
int show;
|
||||
int passed_a_ptr;
|
||||
{
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
return;
|
||||
|
||||
|
@ -559,30 +404,12 @@ 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:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fputc ('(', stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,6 +424,9 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr)
|
|||
int show;
|
||||
int passed_a_ptr;
|
||||
{
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
return;
|
||||
|
||||
|
@ -605,8 +435,9 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr)
|
|||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf (stream, ")");
|
||||
fprintf (stream, "[");
|
||||
if (TYPE_LENGTH (type) >= 0)
|
||||
fprintf (stream, "%d",
|
||||
|
@ -614,20 +445,12 @@ 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;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr);
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf (stream, ")");
|
||||
fprintf (stream, "()");
|
||||
|
@ -662,6 +485,12 @@ type_print_base (type, stream, show, level)
|
|||
|
||||
QUIT;
|
||||
|
||||
if (type == 0)
|
||||
{
|
||||
fprintf (stream, "type unknown");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
{
|
||||
fprintf (stream, TYPE_NAME (type));
|
||||
|
@ -672,8 +501,6 @@ 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;
|
||||
|
@ -694,83 +521,46 @@ type_print_base (type, stream, show, level)
|
|||
fprintf (stream, "{...}");
|
||||
else
|
||||
{
|
||||
struct type *basetype, *dtype;
|
||||
|
||||
dtype = type;
|
||||
basetype = TYPE_BASECLASS (type);
|
||||
while (basetype)
|
||||
{
|
||||
if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
|
||||
{
|
||||
while (*name != ' ') name++;
|
||||
fprintf (stream, ": %s %s ",
|
||||
TYPE_VIA_PUBLIC (dtype) ? "public" : "private",
|
||||
name + 1);
|
||||
}
|
||||
dtype = basetype;
|
||||
basetype = TYPE_BASECLASS (basetype);
|
||||
}
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
if (len) fprintf (stream, "\n");
|
||||
else fprintf (stream, "<no data fields>\n");
|
||||
|
||||
/* If there is a base class for this type,
|
||||
do not print the field that it occupies. */
|
||||
for (i = !! TYPE_BASECLASS (type); i < len; i++)
|
||||
fprintf (stream, "\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
/* Don't print out virtual function table. */
|
||||
if (! strncmp (TYPE_FIELD_NAME (type, i),
|
||||
"_vptr$", 6))
|
||||
continue;
|
||||
|
||||
print_spaces (level + 4, stream);
|
||||
if (TYPE_FIELD_STATIC (type, i))
|
||||
|
||||
/* If this is a bit-field and there is a gap before it,
|
||||
print a nameless field to account for the gap. */
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
fprintf (stream, "static ");
|
||||
int gap = (TYPE_FIELD_BITPOS (type, i)
|
||||
- (i > 0
|
||||
? (TYPE_FIELD_BITPOS (type, i - 1)
|
||||
+ (TYPE_FIELD_PACKED (type, i - 1)
|
||||
? TYPE_FIELD_BITSIZE (type, i - 1)
|
||||
: TYPE_LENGTH (TYPE_FIELD_TYPE (type, i - 1)) * 8))
|
||||
: 0));
|
||||
if (gap != 0)
|
||||
{
|
||||
fprintf (stream, "int : %d;\n", gap);
|
||||
print_spaces (level + 4, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the declaration of this field. */
|
||||
|
||||
type_print_1 (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
if (!TYPE_FIELD_STATIC (type, i)
|
||||
&& TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
/* ??? don't know what to put here ??? */;
|
||||
}
|
||||
|
||||
/* Print the field width. */
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
fprintf (stream, " : %d", TYPE_FIELD_BITSIZE (type, i));
|
||||
|
||||
fprintf (stream, ";\n");
|
||||
}
|
||||
|
||||
/* C++: print out the methods */
|
||||
len = TYPE_NFN_FIELDS (type);
|
||||
if (len) fprintf (stream, "\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
|
||||
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
QUIT;
|
||||
print_spaces (level + 4, stream);
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
fprintf (stream, "virtual ");
|
||||
type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0);
|
||||
if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
|
||||
&& TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
|
||||
TYPE_FN_FIELDLIST_NAME (type, i), stream);
|
||||
else
|
||||
type_print_method_args
|
||||
(TYPE_FN_FIELD_ARGS (f, j), "",
|
||||
TYPE_FN_FIELDLIST_NAME (type, i), stream);
|
||||
|
||||
fprintf (stream, ";\n");
|
||||
}
|
||||
if (len2) fprintf (stream, "\n");
|
||||
}
|
||||
|
||||
print_spaces (level, stream);
|
||||
fputc ('}', stream);
|
||||
}
|
||||
|
|
22
gdb/value.h
22
gdb/value.h
|
@ -56,14 +56,10 @@ 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.
|
||||
|
||||
References are dereferenced. */
|
||||
If ARG is an enum, convert it to an integer. */
|
||||
|
||||
#define COERCE_ARRAY(arg) \
|
||||
{ if (TYPE_CODE (arg) == TYPE_CODE_REF) \
|
||||
arg = value_ind (arg); \
|
||||
if (VALUE_REPEATED (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) \
|
||||
|
@ -73,9 +69,7 @@ typedef struct value *value;
|
|||
/* If ARG is an enum, convert it to an integer. */
|
||||
|
||||
#define COERCE_ENUM(arg) \
|
||||
{ if (TYPE_CODE (arg) == TYPE_CODE_REF) \
|
||||
arg = value_ind (arg); \
|
||||
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
|
||||
{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
|
||||
arg = value_cast (builtin_type_unsigned_int, arg); \
|
||||
}
|
||||
|
||||
|
@ -114,7 +108,7 @@ value value_addr ();
|
|||
value value_assign ();
|
||||
value value_neg ();
|
||||
value value_lognot ();
|
||||
value value_struct_elt (), value_struct_elt_for_address ();
|
||||
value value_struct_elt ();
|
||||
value value_field ();
|
||||
value value_cast ();
|
||||
value value_repeat ();
|
||||
|
@ -135,11 +129,3 @@ 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_must_be_user_defined ();
|
||||
int unop_must_be_user_defined ();
|
||||
|
|
119
gdb/values.c
119
gdb/values.c
|
@ -286,7 +286,7 @@ history_info (num_exp)
|
|||
{
|
||||
val = access_value_history (i);
|
||||
printf ("$%d = ", i);
|
||||
value_print (val, stdout);
|
||||
value_print (val, stdout, 0);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +330,7 @@ value_of_internalvar (var)
|
|||
register value val = value_copy (var->value);
|
||||
VALUE_LVAL (val) = lval_internalvar;
|
||||
VALUE_INTERNALVAR (val) = var;
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -397,7 +398,7 @@ use \"set\" as in \"set $foo = 5\" to define them.\n");
|
|||
for (var = internalvars; var; var = var->next)
|
||||
{
|
||||
printf ("$%s: ", var->name);
|
||||
value_print (var->value, stdout);
|
||||
value_print (var->value, stdout, 0);
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
@ -424,12 +425,7 @@ 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.
|
||||
|
||||
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. */
|
||||
and can convert between fixed and floating point. */
|
||||
|
||||
long
|
||||
unpack_long (type, valaddr)
|
||||
|
@ -478,14 +474,11 @@ unpack_long (type, valaddr)
|
|||
if (len == sizeof (long))
|
||||
return * (long *) valaddr;
|
||||
}
|
||||
else if (code == TYPE_CODE_PTR
|
||||
|| code == TYPE_CODE_REF)
|
||||
else if (code == TYPE_CODE_PTR)
|
||||
{
|
||||
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.");
|
||||
}
|
||||
|
@ -508,7 +501,13 @@ unpack_double (type, valaddr)
|
|||
return * (float *) valaddr;
|
||||
|
||||
if (len == sizeof (double))
|
||||
return * (double *) valaddr;
|
||||
{
|
||||
/* Some machines require doubleword alignment for doubles.
|
||||
This code works on them, and on other machines. */
|
||||
double temp;
|
||||
bcopy ((char *) valaddr, (char *) &temp, sizeof (double));
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
else if (code == TYPE_CODE_INT && nosign)
|
||||
{
|
||||
|
@ -544,9 +543,7 @@ 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.
|
||||
|
||||
For C++, must also be able to return values from static fields */
|
||||
FIELDNO says which field. */
|
||||
|
||||
value
|
||||
value_field (arg1, fieldno)
|
||||
|
@ -584,96 +581,6 @@ 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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -23,7 +23,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "vax-opcode.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/* Vax instructions are never longer than this. */
|
||||
#define MAXLEN 62
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* Define the current version number of GDB. */
|
||||
|
||||
char *version = "2.5.3 (GNU C++ 1.22.0 compatible)";
|
||||
char *version = "2.8";
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define WSTOPSIG(w) ((w) >> 8)
|
||||
#define WCOREDUMP(w) (((w)&0200) != 0)
|
||||
#define WTERMSIG(w) ((w) & 0177)
|
||||
#define WSETEXIT(w, status) ((w) = (status))
|
||||
#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
|
@ -20,6 +21,7 @@
|
|||
#define WSTOPSIG(w) (w).w_stopsig
|
||||
#define WCOREDUMP(w) (w).w_coredump
|
||||
#define WTERMSIG(w) (w).w_termsig
|
||||
#define WSETEXIT(w, status) ((w).w_status = (status))
|
||||
#define WSETSTOP(w,sig) \
|
||||
((w).stopsig = (sig), (w).coredump = 0, (w).termsig = 0177)
|
||||
((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
|
||||
#endif
|
||||
|
|
638
gdb/xgdb.c
638
gdb/xgdb.c
|
@ -26,16 +26,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
|
|||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xresource.h>
|
||||
#include <X11/Atoms.h>
|
||||
#include <X11/TopLevel.h>
|
||||
#include <X11/VPane.h>
|
||||
#include <X11/IntrinsicP.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <X11/Label.h>
|
||||
#include <X11/Text.h>
|
||||
#include <X11/Command.h>
|
||||
#include <X11/ButtonBox.h>
|
||||
#include <X11/TextP.h>
|
||||
#include <X11/Box.h>
|
||||
#include <X11/VPaned.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -63,21 +60,27 @@ static short gdb_mask_bits[] = {
|
|||
|
||||
/* The X display on which the window appears. */
|
||||
|
||||
Display *screen_display;
|
||||
|
||||
/* The graphics context. */
|
||||
|
||||
GC default_gc;
|
||||
static Display *screen_display;
|
||||
|
||||
/* Windows manipulated by this package. */
|
||||
|
||||
static Window icon_window;
|
||||
static Widget main_widget;
|
||||
static Widget containing_widget;
|
||||
static Widget title_widget;
|
||||
static Widget source_name_widget;
|
||||
static Widget source_text_widget;
|
||||
static Widget exec_name_widget;
|
||||
static Widget button_box_widget;
|
||||
|
||||
#ifdef VTFD
|
||||
/* Interaction Window */
|
||||
|
||||
static Widget interactive_widget;
|
||||
XtTextSource PseudoDiskSourceCreate();
|
||||
XtTextSource TSource;
|
||||
static int vtfd[2], vifd[2];
|
||||
#endif
|
||||
|
||||
/* Source text display. */
|
||||
|
||||
static struct symtab *source_window_symtab = 0;
|
||||
|
@ -88,14 +91,27 @@ static Widget create_text_widget ();
|
|||
|
||||
START_FILE
|
||||
|
||||
/* Return number of text lines displayed in text widget W. */
|
||||
|
||||
int /* was XtTextPosition */
|
||||
XtTextLines (w)
|
||||
Widget w;
|
||||
{
|
||||
TextWidget ctx = (TextWidget)w;
|
||||
|
||||
return ctx->text.lt.lines;
|
||||
}
|
||||
|
||||
/* Display an appropriate piece of source code in the source window. */
|
||||
|
||||
xgdb_display_source ()
|
||||
{
|
||||
char *filename;
|
||||
static Arg labelArgs[1];
|
||||
Arg args[1];
|
||||
Arg labelArgs[1];
|
||||
int linenumbers_changed = 0;
|
||||
static int new = 1;
|
||||
int must_scroll = 0;
|
||||
int height = XtTextLines (source_text_widget);
|
||||
|
||||
struct symtab_and_line get_selected_frame_sal ();
|
||||
struct symtab_and_line sal;
|
||||
|
@ -132,12 +148,18 @@ xgdb_display_source ()
|
|||
|
||||
if (linenumbers_changed || source_window_symtab != sal.symtab)
|
||||
{
|
||||
static Arg fileArgs[1];
|
||||
new = 1;
|
||||
Arg fileArgs[1];
|
||||
XtTextSource src;
|
||||
|
||||
must_scroll = 1;
|
||||
source_window_symtab = sal.symtab;
|
||||
|
||||
src = XtTextGetSource (source_text_widget);
|
||||
XtDiskSourceDestroy (src);
|
||||
|
||||
XtSetArg (fileArgs[0], XtNfile, filename);
|
||||
XtSetValues (source_text_widget, fileArgs, XtNumber (fileArgs));
|
||||
src = XtDiskSourceCreate (source_text_widget->core.parent, fileArgs, 1);
|
||||
XtTextSetSource (source_text_widget, src, 0);
|
||||
|
||||
XtSetArg (labelArgs[0], XtNlabel,
|
||||
filename ? filename : "No source displayed.");
|
||||
|
@ -148,46 +170,38 @@ xgdb_display_source ()
|
|||
/* Update display and cursor positions as necessary.
|
||||
Cursor should be placed on line sal.line. */
|
||||
|
||||
{
|
||||
static int top_line_number, bottom_line_number;
|
||||
int current_top;
|
||||
Arg textArgs[1];
|
||||
/* Find out where the display is positioned (in case user scrolled it). */
|
||||
|
||||
if (! new)
|
||||
{
|
||||
int new_top;
|
||||
if (! must_scroll)
|
||||
{
|
||||
int top_line_number;
|
||||
|
||||
/* Get positions of start of display, and caret */
|
||||
XtSetArg (textArgs[0], XtNdisplayPosition, NULL);
|
||||
XtGetValues (source_text_widget, textArgs, XtNumber (textArgs));
|
||||
new_top = source_charpos_line (source_window_symtab,
|
||||
(int) textArgs[0].value);
|
||||
bottom_line_number += new_top - top_line_number;
|
||||
top_line_number = new_top;
|
||||
}
|
||||
XtSetArg (args[0], XtNdisplayPosition, NULL);
|
||||
XtGetValues (source_text_widget, args, 1);
|
||||
top_line_number = source_charpos_line (source_window_symtab,
|
||||
(int) args[0].value);
|
||||
/* If desired position is off screen, we must scroll. */
|
||||
if (sal.line < top_line_number
|
||||
|| sal.line >= top_line_number + height)
|
||||
must_scroll = 1;
|
||||
}
|
||||
|
||||
/* If appropriate, scroll the text display. */
|
||||
if (sal.line < top_line_number
|
||||
|| sal.line > bottom_line_number
|
||||
|| new)
|
||||
{
|
||||
/* yes, these magic numbers are ugly, but I don't know how
|
||||
* to get the height of a text widget in a V11-portable way
|
||||
*/
|
||||
top_line_number = (sal.line > 15) ? sal.line - 15 : 0;
|
||||
bottom_line_number = top_line_number + 35;
|
||||
|
||||
XtSetArg (textArgs[0], XtNdisplayPosition,
|
||||
source_line_charpos (source_window_symtab, top_line_number));
|
||||
XtSetValues (source_text_widget, textArgs, XtNumber (textArgs));
|
||||
}
|
||||
/* If appropriate, scroll the text display. */
|
||||
|
||||
/* Set the text display cursor position within the text. */
|
||||
if (must_scroll)
|
||||
{
|
||||
int top_line_number = (sal.line > height/3) ? sal.line - height/3 : 1;
|
||||
|
||||
XtSetArg (textArgs[0], XtNinsertPosition,
|
||||
source_line_charpos (source_window_symtab, sal.line));
|
||||
XtSetValues (source_text_widget, textArgs, XtNumber (textArgs));
|
||||
}
|
||||
XtSetArg (args[0], XtNdisplayPosition,
|
||||
source_line_charpos (source_window_symtab, top_line_number));
|
||||
XtSetValues (source_text_widget, args, 1);
|
||||
}
|
||||
|
||||
/* Set the text display cursor position within the text. */
|
||||
|
||||
XtSetArg (args[0], XtNinsertPosition,
|
||||
source_line_charpos (source_window_symtab, sal.line));
|
||||
XtSetValues (source_text_widget, args, 1);
|
||||
}
|
||||
|
||||
/* Display FILENAME in the title bar at bottom of window. */
|
||||
|
@ -209,7 +223,10 @@ static void
|
|||
print_prompt ()
|
||||
{
|
||||
if (prompt_string)
|
||||
printf ("%s", prompt_string);
|
||||
{
|
||||
printf ("%s", prompt_string);
|
||||
fflush (stdout);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handlers for buttons. */
|
||||
|
@ -219,16 +236,17 @@ print_prompt ()
|
|||
Get the "selection" from X and use it as the operand of a print command. */
|
||||
|
||||
static void
|
||||
print_1 (starflag)
|
||||
print_button (w, starflag, call_data)
|
||||
Widget w;
|
||||
int starflag;
|
||||
caddr_t call_data;
|
||||
{
|
||||
int selected_length;
|
||||
char *selected_text;
|
||||
|
||||
char *cmd = starflag ? "print * " : "print ";
|
||||
register int cmdlen = strlen (cmd);
|
||||
|
||||
selected_text = XFetchBytes (&selected_length);
|
||||
selected_text = XFetchBytes (screen_display, &selected_length);
|
||||
if (selected_length)
|
||||
{
|
||||
char *line = xmalloc (cmdlen + selected_length + 1);
|
||||
|
@ -245,29 +263,20 @@ print_1 (starflag)
|
|||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
print_button ()
|
||||
{
|
||||
print_1 (0);
|
||||
}
|
||||
|
||||
static void
|
||||
print_star_button ()
|
||||
{
|
||||
print_1 (1);
|
||||
}
|
||||
|
||||
/* Subroutine used by "stop at" and "go till" buttons.
|
||||
Set a breakpoint at the position indicated by the "selection"
|
||||
in the source window, and, if RUNFLAG is nonzero, continue. */
|
||||
|
||||
static void
|
||||
breakpoint_button_1 (runflag)
|
||||
breakpoint_button (w, runflag, call_data)
|
||||
Widget w;
|
||||
int runflag;
|
||||
caddr_t call_data;
|
||||
{
|
||||
XtTextPosition start, finish;
|
||||
|
||||
XtTextGetSelectionPos (screen_display, source_text_widget, &start, &finish);
|
||||
XtTextGetSelectionPos (source_text_widget, &start, &finish);
|
||||
if (!source_window_symtab)
|
||||
printf ("No source file displayed.\n");
|
||||
else
|
||||
|
@ -284,18 +293,6 @@ breakpoint_button_1 (runflag)
|
|||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
breakpoint_button ()
|
||||
{
|
||||
breakpoint_button_1 (0);
|
||||
}
|
||||
|
||||
static void
|
||||
until_button ()
|
||||
{
|
||||
breakpoint_button_1 (1);
|
||||
}
|
||||
|
||||
/* decide if a character is trash */
|
||||
static int
|
||||
garbage (c)
|
||||
|
@ -342,92 +339,50 @@ explicit_breakpoint_button ()
|
|||
print_prompt ();
|
||||
}
|
||||
|
||||
/* Various trivial buttons,
|
||||
most of which just run one GDB command with no arg. */
|
||||
/* Handle a button by running the command COMMAND. */
|
||||
|
||||
static void
|
||||
next_button ()
|
||||
do_command (w, command, call_data)
|
||||
Widget w;
|
||||
char *command;
|
||||
caddr_t call_data;
|
||||
{
|
||||
execute_command ("next", 0);
|
||||
execute_command (command, 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
step_button ()
|
||||
redisplay_button()
|
||||
{
|
||||
execute_command ("step", 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
cont_button ()
|
||||
{
|
||||
execute_command ("cont", 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
finish_button ()
|
||||
{
|
||||
execute_command ("finish", 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
deiconify_button ()
|
||||
{
|
||||
XUnmapWindow (screen_display, icon_window);
|
||||
XMapWindow (screen_display, containing_widget);
|
||||
}
|
||||
|
||||
static void
|
||||
iconify_button ()
|
||||
{
|
||||
#if 0
|
||||
static Arg iconArgs[1];
|
||||
XtSetArg (iconArgs[0], XtNlabel, prompt_string);
|
||||
XtCommandSetValues (icon_window, iconArgs, XtNumber (iconArgs));
|
||||
#endif 0
|
||||
XUnmapWindow (screen_display, containing_widget);
|
||||
XMapWindow (screen_display, icon_window);
|
||||
}
|
||||
#endif 0
|
||||
|
||||
static void
|
||||
up_button ()
|
||||
{
|
||||
execute_command ("up", 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
}
|
||||
|
||||
static void
|
||||
down_button ()
|
||||
{
|
||||
execute_command ("down", 0);
|
||||
xgdb_display_source ();
|
||||
print_prompt ();
|
||||
xgdb_display_source();
|
||||
}
|
||||
|
||||
/* Define and display all the buttons. */
|
||||
|
||||
static void
|
||||
addbutton (parent, name, function)
|
||||
addbutton (parent, name, function, closure)
|
||||
Widget parent;
|
||||
char *name;
|
||||
void (*function) ();
|
||||
caddr_t closure;
|
||||
{
|
||||
static Arg commandArgs[2];
|
||||
static XtCallbackRec Callback[] =
|
||||
{
|
||||
{NULL, (caddr_t)NULL},
|
||||
{NULL, (caddr_t)NULL},
|
||||
};
|
||||
static Arg commandArgs[] =
|
||||
{
|
||||
{XtNlabel, (XtArgVal)NULL},
|
||||
{XtNcallback, (XtArgVal)Callback},
|
||||
};
|
||||
|
||||
XtSetArg (commandArgs[0], XtNlabel, name);
|
||||
XtSetArg (commandArgs[1], XtNfunction, function);
|
||||
XtCreateWidget (name, commandWidgetClass, parent,
|
||||
commandArgs, XtNumber (commandArgs));
|
||||
Callback[0].callback = (XtCallbackProc)function;
|
||||
Callback[0].closure = (caddr_t)closure;
|
||||
commandArgs[0].value = (XtArgVal)name;
|
||||
XtCreateManagedWidget (name, commandWidgetClass, parent,
|
||||
commandArgs, XtNumber(commandArgs));
|
||||
}
|
||||
|
||||
/* Create the button windows and store them in `buttons'. */
|
||||
|
@ -436,22 +391,25 @@ static void
|
|||
create_buttons (parent)
|
||||
Widget parent;
|
||||
{
|
||||
addbutton (parent, "Brk At", breakpoint_button);
|
||||
addbutton (parent, "Brk In", explicit_breakpoint_button);
|
||||
addbutton (parent, "Go 'til", until_button);
|
||||
addbutton (parent, "run", do_command, "run");
|
||||
addbutton (parent, "quit", do_command, "quit");
|
||||
|
||||
addbutton (parent, "Print", print_button);
|
||||
addbutton (parent, "Print*", print_star_button);
|
||||
addbutton (parent, "break in", explicit_breakpoint_button, NULL);
|
||||
addbutton (parent, "break at", breakpoint_button, 0);
|
||||
addbutton (parent, "go until", breakpoint_button, 1);
|
||||
|
||||
addbutton (parent, "Next", next_button);
|
||||
addbutton (parent, "Step", step_button);
|
||||
addbutton (parent, "Cont", cont_button);
|
||||
addbutton (parent, "Finish", finish_button);
|
||||
addbutton (parent, "print", print_button, 0);
|
||||
addbutton (parent, "print*", print_button, 1);
|
||||
|
||||
addbutton (parent, "next", do_command, "next");
|
||||
addbutton (parent, "step", do_command, "step");
|
||||
addbutton (parent, "cont", do_command, "cont");
|
||||
addbutton (parent, "finish", do_command, "finish");
|
||||
|
||||
addbutton (parent, "Up", up_button);
|
||||
addbutton (parent, "Down", down_button);
|
||||
addbutton (parent, "up", do_command, "up");
|
||||
addbutton (parent, "down", do_command, "down");
|
||||
|
||||
/* addbutton (parent, "Iconify", iconify_button); */
|
||||
addbutton (parent, "redisplay", redisplay_button, NULL);
|
||||
}
|
||||
|
||||
/* Create a "label window" that just displays the string LABEL. */
|
||||
|
@ -460,12 +418,16 @@ static Widget
|
|||
create_label (name, label)
|
||||
char *name, *label;
|
||||
{
|
||||
static Arg labelArgs[2];
|
||||
Arg labelArgs[2];
|
||||
Widget w;
|
||||
|
||||
XtSetArg (labelArgs[0], XtNname, name);
|
||||
XtSetArg (labelArgs[1], XtNlabel, label);
|
||||
return XtCreateWidget ("label1", labelWidgetClass, containing_widget,
|
||||
labelArgs, XtNumber (labelArgs));
|
||||
|
||||
w = XtCreateManagedWidget ("label", labelWidgetClass, containing_widget,
|
||||
labelArgs, XtNumber (labelArgs));
|
||||
XtPanedSetMinMax (w, w->core.height, w->core.height);
|
||||
return w;
|
||||
}
|
||||
|
||||
/* Create a subwindow of PARENT that displays and scrolls the contents
|
||||
|
@ -473,143 +435,138 @@ create_label (name, label)
|
|||
|
||||
static Widget
|
||||
create_text_widget (parent, filename)
|
||||
Window parent;
|
||||
Widget parent;
|
||||
char *filename;
|
||||
{
|
||||
static Arg fileArgs[2];
|
||||
|
||||
static Arg fileArgs[3];
|
||||
XtTextSource src;
|
||||
XtTextSink sink;
|
||||
|
||||
XtSetArg (fileArgs[0], XtNfile, filename);
|
||||
XtSetArg (fileArgs[1], XtNtextOptions, scrollVertical);
|
||||
return XtTextDiskCreate (parent, fileArgs, XtNumber (fileArgs));
|
||||
src = XtDiskSourceCreate(parent, fileArgs, 1);
|
||||
sink = XtAsciiSinkCreate(parent, NULL, 0);
|
||||
|
||||
XtSetArg (fileArgs[0], XtNtextOptions, scrollVertical);
|
||||
XtSetArg (fileArgs[1], XtNtextSource, src);
|
||||
XtSetArg (fileArgs[2], XtNtextSink, sink);
|
||||
return XtCreateManagedWidget ("disk", textWidgetClass, parent,
|
||||
fileArgs, XtNumber (fileArgs));
|
||||
|
||||
#if 0 /* This is tucker's method. */
|
||||
|
||||
/* Create an empty source-display window and add to containing_widget */
|
||||
XtSetArg (argl[0], XtNfile, "/dev/null");
|
||||
XtSetArg (argl[1], XtNtextOptions, scrollVertical);
|
||||
XtSetArg (argl[2], XtNheight, (XtArgVal)sheight);
|
||||
source_text_widget = XtCreateManagedWidget (NULL, asciiDiskWidgetClass,
|
||||
containing_widget, argl,
|
||||
XtNumber (argl));
|
||||
|
||||
/* Create NULL disk source */
|
||||
XtSetArg (argl[0], XtNfile, "/dev/null");
|
||||
NullSource = XtDiskSourceCreate (source_text_widget, argl, ONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Entry point to create the widgets representing our display. */
|
||||
/* window manager argument parsing */
|
||||
extern int *win_argc;
|
||||
extern char **win_argv;
|
||||
|
||||
/* Entry point to create the widgets representing our display. */
|
||||
int
|
||||
xgdb_create_window ()
|
||||
{
|
||||
static Arg frameArgs[]= {
|
||||
{XtNwidth, (XtArgVal) 600},
|
||||
{XtNheight, (XtArgVal) 700},
|
||||
};
|
||||
int width, height;
|
||||
int sheight;
|
||||
Arg argl[3];
|
||||
|
||||
XrmResourceDataBase db;
|
||||
FILE *rdb_file;
|
||||
XGCValues dummy;
|
||||
|
||||
/* Init and database stuff. */
|
||||
screen_display = XOpenDisplay (NULL);
|
||||
if (screen_display == 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot connect to X server");
|
||||
return 0;
|
||||
}
|
||||
/* initialize toolkit, setup defaults */
|
||||
main_widget = XtInitialize ("gdb", "gdb", NULL, 0, win_argc, win_argv);
|
||||
screen_display = XtDisplay (main_widget);
|
||||
|
||||
/* Find out what size the user specified. */
|
||||
|
||||
XtSetArg (argl[0], XtNwidth, (XtArgVal)&width);
|
||||
XtSetArg (argl[1], XtNheight, (XtArgVal)&height);
|
||||
XtGetValues (main_widget, argl, XtNumber(argl));
|
||||
|
||||
/* If none specified, set a default size. */
|
||||
|
||||
if (!width || !height)
|
||||
{
|
||||
width = 500, height = 700;
|
||||
XtSetArg (argl[0], XtNwidth, (XtArgVal)width);
|
||||
XtSetArg (argl[1], XtNheight, (XtArgVal)height);
|
||||
XtSetValues (main_widget, argl, XtNumber(argl));
|
||||
}
|
||||
sheight = (float)height / 2.5;
|
||||
|
||||
/* Create the (toplevel) main_widget */
|
||||
XtSetArg (argl[0], XtNwidth, (XtArgVal)width);
|
||||
XtSetArg (argl[1], XtNheight, (XtArgVal)height);
|
||||
containing_widget
|
||||
= XtCreateManagedWidget ("vpaned", vPanedWidgetClass,
|
||||
main_widget, argl, XtNumber (argl));
|
||||
XtPanedSetRefigureMode (containing_widget, FALSE);
|
||||
|
||||
/* Create title */
|
||||
{
|
||||
char *dummy1[1];
|
||||
dummy1[0] = 0;
|
||||
XtInitialize ("gdb", "gdb", 0, 0, 0, dummy1);
|
||||
char buf[200];
|
||||
extern char *version;
|
||||
sprintf (buf, "GDB %s", version);
|
||||
title_widget =
|
||||
create_label ("Title", buf);
|
||||
}
|
||||
|
||||
/* should be checking .Xdefaults in $HOME */
|
||||
rdb_file = fopen (".Xresources", "r");
|
||||
if (rdb_file != NULL)
|
||||
{
|
||||
XrmGetDataBase (rdb_file, &db);
|
||||
XrmSetCurrentDataBase (db);
|
||||
fclose (rdb_file);
|
||||
}
|
||||
|
||||
/* Create the containing_widget. */
|
||||
/* Create exec file name window and add */
|
||||
exec_name_widget =
|
||||
create_label ("Executable", "No executable specified");
|
||||
|
||||
containing_widget = XtCreateWidget ("frame", vPaneWidgetClass, 0,
|
||||
frameArgs, XtNumber (frameArgs));
|
||||
|
||||
default_gc = XCreateGC (screen_display, containing_widget, 0, dummy);
|
||||
/* Create window full of buttons. */
|
||||
button_box_widget = XtCreateManagedWidget ("buttons", boxWidgetClass,
|
||||
containing_widget, NULL, 0);
|
||||
create_buttons (button_box_widget);
|
||||
|
||||
/* Create source file name window and add to containing_widget */
|
||||
source_name_widget
|
||||
= create_label ("Source File", "No source file yet.");
|
||||
source_name_widget =
|
||||
create_label ("Source File", "No source file yet.");
|
||||
|
||||
/* Create an empty source-display window and add to containing_widget */
|
||||
source_text_widget = create_text_widget (containing_widget, "/dev/null");
|
||||
|
||||
/* Create window full of buttons. */
|
||||
button_box_widget = XtCreateWidget ("Buttons", buttonBoxWidgetClass,
|
||||
containing_widget, NULL, 0);
|
||||
create_buttons (button_box_widget);
|
||||
|
||||
/* Create exec file name window and add */
|
||||
exec_name_widget = create_label ("Executable", "No executable specified.");
|
||||
|
||||
#if 0
|
||||
/* Create icon window. */
|
||||
#ifdef VFTD
|
||||
/* Create Fake Text source */
|
||||
{
|
||||
static Arg iconArgs[2];
|
||||
void (*compiler_bug) () = deiconify_button;
|
||||
XtSetArg (iconArgs[0], XtNlabel, "(gdb)");
|
||||
XtSetArg (iconArgs[1], XtNfunction, compiler_bug);
|
||||
icon_window = XtCommandCreate (DefaultRootWindow (screen_display),
|
||||
iconArgs, XtNumber (iconArgs));
|
||||
XMoveWindow (screen_display, icon_window, 100, 100); /* HACK */
|
||||
#if 0
|
||||
XSetIconWindow (screen_display, containing_widget, icon_window);
|
||||
#endif 0
|
||||
extern XtTextSource TCreateApAsSource();
|
||||
TSource = TCreateApAsSource();
|
||||
}
|
||||
#endif 0
|
||||
|
||||
/* Create interactive box */
|
||||
XtSetArg (argl[0], XtNtextSource, (XtArgVal)TSource);
|
||||
XtSetArg (argl[1], XtNtextSink,
|
||||
(XtArgVal)XtAsciiSinkCreate(containing_widget, NULL, 0));
|
||||
XtSetArg (argl[2], XtNtextOptions,
|
||||
(XtArgVal)(scrollVertical | wordBreak));
|
||||
interactive_widget = XtCreateManagedWidget ("gdbWindow", textWidgetClass,
|
||||
containing_widget, argl, THREE);
|
||||
#endif
|
||||
|
||||
/* Put them one screen */
|
||||
XtPanedSetRefigureMode(containing_widget, TRUE);
|
||||
XtRealizeWidget (main_widget);
|
||||
|
||||
/* Define GDB cursor */
|
||||
#if 0
|
||||
/* Now make the whole thing appear on the display. */
|
||||
{
|
||||
Pixmap pm1, pm2;
|
||||
XImage image;
|
||||
Cursor curse;
|
||||
XDefineCursor (screen_display, XtWindow (main_widget),
|
||||
XCreateFontCursor (screen_display, XC_circle));
|
||||
#endif
|
||||
|
||||
image.width = gdb_width;
|
||||
image.height = gdb_height;
|
||||
image.xoffset = 0;
|
||||
image.format = XYBitmap;
|
||||
image.byte_order = LSBFirst;
|
||||
image.bitmap_unit = 16;
|
||||
image.bitmap_bit_order = LSBFirst;
|
||||
image.depth = 1;
|
||||
image.bytes_per_line = 2;
|
||||
image.bits_per_pixel = 1;
|
||||
|
||||
pm1 = XCreatePixmap (screen_display, DefaultScreen (screen_display),
|
||||
gdb_width, gdb_height, 1);
|
||||
pm2 = XCreatePixmap (screen_display, DefaultScreen (screen_display),
|
||||
gdb_width, gdb_height, 1);
|
||||
|
||||
image.data = (char *) gdb_bits;
|
||||
XPutImage (screen_display, pm1, default_gc, &image, 0, 0, 0, 0,
|
||||
gdb_width, gdb_height);
|
||||
|
||||
image.data = (char *) gdb_mask_bits;
|
||||
XPutImage (screen_display, pm2, default_gc, &image, 0, 0, 0, 0,
|
||||
gdb_width, gdb_height);
|
||||
|
||||
curse = XCreatePixmapCursor (screen_display, pm1, pm2,
|
||||
BlackPixel (screen_display,
|
||||
DefaultScreen (screen_display)),
|
||||
WhitePixel (screen_display,
|
||||
DefaultScreen (screen_display)),
|
||||
gdb_x_hot, gdb_y_hot);
|
||||
|
||||
XFreePixmap (screen_display, pm1);
|
||||
XFreePixmap (screen_display, pm2);
|
||||
|
||||
XDefineCursor (screen_display, containing_widget, curse);
|
||||
XDefineCursor (screen_display, icon_window, curse);
|
||||
}
|
||||
#endif 0
|
||||
|
||||
XtRealizeWidget (containing_widget);
|
||||
XFlush (screen_display);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_XGDB_READ 128
|
||||
|
||||
/* xgdb_dispatch -- Loop, dispatching on window events,
|
||||
until data is available on FP (which is normally stdin).
|
||||
Then return, so the data on FP can be processed. */
|
||||
|
@ -624,13 +581,20 @@ xgdb_dispatch (fp)
|
|||
int nfds;
|
||||
XEvent ev;
|
||||
int pend;
|
||||
|
||||
int nread;
|
||||
char buf[1024];
|
||||
int ipmask;
|
||||
|
||||
#ifdef VTFD
|
||||
ipmask = 1 << vtfd[0];
|
||||
#endif
|
||||
|
||||
while (! (rfds & inmask))
|
||||
{
|
||||
pend = XPending ();
|
||||
pend = XPending (screen_display);
|
||||
if (!pend)
|
||||
{
|
||||
rfds = inmask | xmask;
|
||||
rfds = inmask | xmask | ipmask;
|
||||
/* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */
|
||||
nfds = select (32, &rfds, 0, 0, (struct timeval *) 0);
|
||||
}
|
||||
|
@ -639,9 +603,132 @@ xgdb_dispatch (fp)
|
|||
XNextEvent (screen_display, &ev);
|
||||
XtDispatchEvent (&ev);
|
||||
}
|
||||
|
||||
#ifdef VTFD
|
||||
/* Handle I/O through the command window. */
|
||||
if (pend == 0 && (rfds & ipmask))
|
||||
{
|
||||
nread = read (vtfd[0], buf, sizeof(buf));
|
||||
xgdb_write (buf, nread);
|
||||
}
|
||||
nread = xgdb_read (buf, MAX_XGDB_READ);
|
||||
if (pend == 0 && nread > 0)
|
||||
{
|
||||
write (vifd[1], buf, nread);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VTFD
|
||||
|
||||
static int output_size;
|
||||
static int used_size;
|
||||
static char *output_string;
|
||||
|
||||
static void
|
||||
xgdb_init_text ()
|
||||
{
|
||||
Arg args[2];
|
||||
|
||||
output_size = 1000;
|
||||
output_string = (char *) xmalloc (output_size);
|
||||
used_size = 0;
|
||||
|
||||
XtSetArg (args[0], XtNstring, (XtArgVal) output_string);
|
||||
XtSetArg (args[1], XtNlength, (XtArgVal) output_size);
|
||||
TSource
|
||||
= XtStringSourceCreate (toplevel, args, 2);
|
||||
|
||||
XtSetArg (args[0], XtNtextSource, TSource);
|
||||
XtSetValues (interaction_widget, Args, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
xgdb_grow_text (size)
|
||||
int size;
|
||||
{
|
||||
if (output_size < used_size + size + 200)
|
||||
{
|
||||
Arg args[2];
|
||||
|
||||
XtStringSourceDestroy (TSource);
|
||||
|
||||
output_size = (used_size + size + 1010 + 512) / 1010 * 1010;
|
||||
output_string = xrealloc (output_string, output_size);
|
||||
|
||||
XtSetArg (args[0], XtNstring, (XtArgVal) output_string);
|
||||
XtSetArg (args[1], XtNlength, (XtArgVal) output_size);
|
||||
TSource
|
||||
= XtStringSourceCreate (toplevel, args, 2);
|
||||
|
||||
XtSetArg (args[0], XtNtextSource, TSource);
|
||||
XtSetValues (interaction_widget, Args, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
xgdb_printf (fmt, arg1, arg2, arg3, arg4)
|
||||
char *fmt;
|
||||
{
|
||||
char buf[1024];
|
||||
XtTextBlock text;
|
||||
XtTextPosition pos;
|
||||
|
||||
/* ??? This will crash on the wrong data. */
|
||||
pos = (*TSource->Scan)(TSource, 0, XtstAll, XtsdRight, 1, 0);
|
||||
sprintf (buf, fmt, arg1, arg2, arg3, arg4);
|
||||
text.length = strlen (buf);
|
||||
text.ptr = buf;
|
||||
xgdb_grow_text (text.length);
|
||||
used_size += text.length;
|
||||
XtTextReplace (interactive_widget, pos, pos, &text);
|
||||
XtTextSetInsertionPoint (interactive_widget, pos + text.length);
|
||||
XFlush (screen_display);
|
||||
}
|
||||
|
||||
int
|
||||
xgdb_write (buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
XtTextBlock text;
|
||||
XtTextPosition pos;
|
||||
|
||||
pos = (*TSource->Scan)(TSource, 0, XtstAll, XtsdRight, 1, 0);
|
||||
text.length = len;
|
||||
text.ptr = buf;
|
||||
xgdb_grow_text (text.length);
|
||||
used_size += text.length;
|
||||
XtTextReplace (interactive_widget, pos, pos, &text);
|
||||
XtTextSetInsertionPoint (interactive_widget, pos + text.length);
|
||||
XFlush (screen_display);
|
||||
}
|
||||
|
||||
int
|
||||
xgdb_read (buf, maxlen)
|
||||
char *buf;
|
||||
int maxlen;
|
||||
{
|
||||
XtTextBlock text;
|
||||
XtTextPosition endpos;
|
||||
int length = 0;
|
||||
|
||||
xgdb_grow_text (maxlen);
|
||||
endpos = XtTextGetInsertionPoint (interactive_widget);
|
||||
length = endpos - used_size;
|
||||
if (length > 0)
|
||||
{
|
||||
(*TSource->Read) (TSource, lastpos, &text, maxlen - 10);
|
||||
length = text.length;
|
||||
strncpy(buf, text.ptr, length);
|
||||
buf[length] = NULL;
|
||||
used_size += length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
#endif /* VTFD */
|
||||
|
||||
/* If we use an X window, the GDB command loop is told to call this function
|
||||
before reading a command from stdin.
|
||||
PROMPT is saved for later use so buttons can print a prompt-string. */
|
||||
|
@ -670,3 +757,4 @@ initialize ()
|
|||
}
|
||||
|
||||
END_FILE
|
||||
|
||||
|
|
Loading…
Reference in New Issue