This commit is contained in:
gdb-3.3 1989-09-30 00:00:00 +00:00 committed by Pedro Alves
parent e91b87a368
commit 4187119d59
167 changed files with 39992 additions and 35871 deletions

View File

@ -1,3 +1,5 @@
echo Setting up the environment for debugging gdb.\n
b fatal
b info_command

View File

@ -1,86 +1,106 @@
GDB GENERAL PUBLIC LICENSE
(Clarified 11 Feb 1988)
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1988 Richard M. Stallman
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
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.
of this license document, but changing it is not allowed.
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.
Preamble
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.
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
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
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
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.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
COPYING POLICIES
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
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.
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a 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:
2. You may modify your copy or copies of the Program 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
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).
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
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.
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
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 General
Public License.
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.
d) You may charge a 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
Mere aggregation of another independent work with the 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
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
@ -88,8 +108,8 @@ Paragraphs 1 and 2 above provided that you also do one of the following:
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
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
@ -98,49 +118,132 @@ Paragraphs 1 and 2 above provided that you also do one of the following:
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.
Source code for a work means the preferred form of the work for making
modifications to it. 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, or for standard header files or definitions files that
accompany that operating system.
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.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License 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.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
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!
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
NO WARRANTY
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
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.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision 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 generally.
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.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

File diff suppressed because it is too large Load Diff

163
gdb/Convex.notes Normal file
View File

@ -0,0 +1,163 @@
@node Convex,,, Top
@appendix Convex-specific info
@cindex Convex notes
Scalar registers are 64 bits long, which is a pain since
left half of an S register frequently contains noise.
Therefore there are two ways to obtain the value of an S register.
@table @kbd
@item $s0
returns the low half of the register as an int
@item $S0
returns the whole register as a long long
@end table
You can print the value in floating point by using @samp{p/f $s0} or @samp{p/f $S0}
to print a single or double precision value.
@cindex vector registers
Vector registers are handled similarly, with @samp{$V0} denoting the whole
64-bit register and @kbd{$v0} denoting the 32-bit low half; @samp{p/f $v0}
or @samp{p/f $V0} can be used to examine the register in floating point.
The length of the vector registers is taken from @samp{$vl}.
Individual elements of a vector register are denoted in the obvious way;
@samp{print $v3[9]} prints the tenth element of register @kbd{v3}, and
@samp{set $v3[9] = 1234} alters it.
@kbd{$vl} and @kbd{$vs} are int, and @kbd{$vm} is an int vector.
Elements of @kbd{$vm} can't be assigned to.
@cindex communication registers
@kindex info comm-registers
Communication registers have names @kbd{$C0 .. $C63}, with @kbd{$c0 .. $c63}
denoting the low-order halves. @samp{info comm-registers} will print them
all out, and tell which are locked. (A communication register is
locked when a value is sent to it, and unlocked when the value is
received.) Communication registers are, of course, global to all
threads, so it does not matter what the currently selected thread is.
@samp{info comm-reg @var{name}} prints just that one communication
register; @samp{name} may also be a communication register number
@samp{nn} or @samp{0xnn}.
@samp{info comm-reg @var{address}} prints the contents of the resource
structure at that address.
@kindex info psw
The command @samp{info psw} prints the processor status word @kbd{$ps}
bit by bit.
@kindex set base
GDB normally prints all integers in base 10, but the leading
@kbd{0x80000000} of pointers is intolerable in decimal, so the default
output radix has been changed to try to print addresses appropriately.
The @samp{set base} command can be used to change this.
@table @code
@item set base 10
Integer values always print in decimal.
@item set base 16
Integer values always print in hex.
@item set base
Go back to the initial state, which prints integer values in hex if they
look like pointers (specifically, if they start with 0x8 or 0xf in the
stack), otherwise in decimal.
@end table
@kindex set pipeline
When an exception such as a bus error or overflow happens, usually the PC
is several instructions ahead by the time the exception is detected.
The @samp{set pipe} command will disable this.
@table @code
@item set pipeline off
Forces serial execution of instructions; no vector chaining and no
scalar instruction overlap. With this, exceptions are detected with
the PC pointing to the instruction after the one in error.
@item set pipeline on
Returns to normal, fast, execution. This is the default.
@end table
@cindex parallel
In a parallel program, multiple threads may be executing, each
with its own registers, stack, and local memory. When one of them
hits a breakpoint, that thread is selected. Other threads do
not run while the thread is in the breakpoint.
@kindex 1cont
The selected thread can be single-stepped, given signals, and so
on. Any other threads remain stopped. When a @samp{cont} command is given,
all threads are resumed. To resume just the selected thread, use
the command @samp{1cont}.
@kindex thread
The @samp{thread} command will show the active threads and the
instruction they are about to execute. The selected thread is marked
with an asterisk. The command @samp{thread @var{n}} will select thread @var{n},
shifting the debugger's attention to it for single-stepping,
registers, local memory, and so on.
@kindex info threads
The @samp{info threads} command will show what threads, if any, have
invisibly hit breakpoints or signals and are waiting to be noticed.
@kindex set parallel
The @samp{set parallel} command controls how many threads can be active.
@table @code
@item set parallel off
One thread. Requests by the program that other threads join in
(spawn and pfork instructions) do not cause other threads to start up.
This does the same thing as the @samp{limit concurrency 1} command.
@item set parallel fixed
All CPUs are assigned to your program whenever it runs. When it
executes a pfork or spawn instruction, it begins parallel execution
immediately. This does the same thing as the @samp{mpa -f} command.
@item set parallel on
One or more threads. Spawn and pfork cause CPUs to join in when and if
they are free. This is the default. It is very good for system
throughput, but not very good for finding bugs in parallel code. If you
suspect a bug in parallel code, you probably want @samp{set parallel fixed.}
@end table
@subsection Limitations
WARNING: Convex GDB evaluates expressions in long long, because S
registers are 64 bits long. However, GDB expression semantics are not
exactly C semantics. This is a bug, strictly speaking, but it's not one I
know how to fix. If @samp{x} is a program variable of type int, then it
is also type int to GDB, but @samp{x + 1} is long long, as is @samp{x + y}
or any other expression requiring computation. So is the expression
@samp{1}, or any other constant. You only really have to watch out for
calls. The innocuous expression @samp{list_node (0x80001234)} has an
argument of type long long. You must explicitly cast it to int.
It is not possible to continue after an uncaught fatal signal by using
@samp{signal 0}, @samp{return}, @samp{jump}, or anything else. The difficulty is with
Unix, not GDB.
I have made no big effort to make such things as single-stepping a
@kbd{join} instruction do something reasonable. If the program seems to
hang when doing this, type @kbd{ctrl-c} and @samp{cont}, or use
@samp{thread} to shift to a live thread. Single-stepping a @kbd{spawn}
instruction apparently causes new threads to be born with their T bit set;
this is not handled gracefully. When a thread has hit a breakpoint, other
threads may have invisibly hit the breakpoint in the background; if you
clear the breakpoint gdb will be surprised when threads seem to continue
to stop at it. All of these situations produce spurious signal 5 traps;
if this happens, just type @samp{cont}. If it becomes a nuisance, use
@samp{handle 5 nostop}. (It will ask if you are sure. You are.)
There is no way in GDB to store a float in a register, as with
@kbd{set $s0 = 3.1416}. The identifier @kbd{$s0} denotes an integer,
and like any C expression which assigns to an integer variable, the
right-hand side is casted to type int. If you should need to do
something like this, you can assign the value to @kbd{@{float@} ($sp-4)}
and then do @kbd{set $s0 = $sp[-4]}. Same deal with @kbd{set $v0[69] = 6.9}.

View File

@ -1,240 +0,0 @@
# On HPUX, you need to add -Ihp-include to CFLAGS.
# The headers in the directory hp-include override system headers
# and tell GDB to use BSD executable file format.
# You must also define REGEX & REGEX1 below and ALLOCA & ALLOCA1 (get
# alloca.c from the emacs distribution) to the CLIBS.
# If you compile GDB with GCC on HPUX, you must make sure that the "nm" used
# in "munch" is GNU's nm. This is because gcc uses a different .o
# file format than the native HPUX compiler.
# On USG (System V) machines, you must make sure to setup REGEX &
# REGEX1 to point at regex.o and use the USG version of CLIBS.
# If your system has a broken alloca() -- most do -- then get
# alloca.c from the GNU Emacs distribution and set ALLOCA & ALLOCA1.
# Also, if you compile gdb with a compiler which uses the coff
# encapsulation feature (this is a function of the compiler used, NOT
# of the m-?.h file selected by config.gdb), you must make sure that
# the GNU nm is the one that is used by munch.
# On Sunos 4.0 machines, make sure to compile *without* shared
# libraries if you want to run gdb on itself. Make sure to compile
# any program on which you want to run gdb without shared libraries.
# If you are compiling with GCC, make sure that either 1) You use the
# -traditional flag, or 2) You have the fixed include files where GCC
# can reach them. Otherwise the ioctl calls in inflow.c will be
# incorrectly compiled. The "fixincludes" script in the gcc
# distribution will probably fix your include files up.
CC=cc
SHELL=/bin/sh
# Set this up with gcc if you have gnu ld and the loader will print out
# line numbers for undefinded refs.
CC-LD=${CC}
# -I. for "#include <obstack.h>". Possibly regex.h also.
#CFLAGS = -g -pg -I. -O
CFLAGS = -I. -g
#LDFLAGS = -pg -g
LDFLAGS = -g
# define this to be "obstack.o" if you don't have the obstack library installed
# you must at the same time define OBSTACK1 as "obstack.o"
# so that the dependencies work right. Similarly with REGEX and "regex.o".
# You must define REGEX and REGEX1 on USG machines.
# If your system is missing alloca(), or, more likely, it's there but it
# doesn't work, define ALLOCA and ALLOCA1.
OBSTACK = obstack.o
OBSTACK1 = obstack.o
REGEX = regex.o
REGEX1 = regex.o
ALLOCA = alloca.o
ALLOCA1 = alloca.o
ADD_FILES = $(OBSTACK) $(REGEX) $(ALLOCA) $(GNU_MALLOC)
ADD_DEPS = $(OBSTACK1) $(REGEX1) $(ALLOCA1) $(GNU_MALLOC)
#
# define this to be "malloc.o" if you want to use the gnu malloc routine
# (useful for debugging memory allocation problems in gdb). Otherwise, leave
# it blank.
GNU_MALLOC =
#GNU_MALLOC = malloc.o
# Flags to be used in compiling malloc.o
# Specify range checking for storage allocation.
MALLOC_FLAGS =
#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS
# for BSD
CLIBS = $(ADD_FILES)
# for USG
#CLIBS= $(ADD_FILES) -lPW
SFILES = blockframe.c breakpoint.c coffread.c command.c core.c dbxread.c \
environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
kdb-start.c main.c printcmd.c \
remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
xgdb.c
DEPFILES = convex-dep.c umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
sparc-dep.c hp9k320-dep.c news-dep.c i386-dep.c
PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
ns32k-pinsn.c
HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
inferior.h symseg.h symtab.h value.h wait.h \
a.out.encap.h a.out.gnu.h stab.gnu.h
OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
ns32k-opcode.h
MFILES = m-hp9k320.h m-i386.h m-i386gas.h m-isi.h m-merlin.h m-news.h \
m-npl.h m-pn.h m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h
POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c
TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
OTHERS = Makefile createtags munch config.gdb ChangeLog README TAGS \
gdb.texinfo .gdbinit COPYING expread.tab.c stab.def hp-include
TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
${POSSLIBS}
TARFILES = ${TAGFILES} ${OTHERS}
OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
command.o utils.o expread.o expprint.o pinsn.o environ.o version.o
TSOBS = core.o inflow.o dep.o
NTSOBS = standalone.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
gdb : $(OBS) $(TSOBS) $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(TSOBS) > init.c
${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) $(CLIBS)
xgdb : $(OBS) $(TSOBS) xgdb.o $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(TSOBS) xgdb.o > init.c
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXt -lX11 $(CLIBS)
kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(NTSOBS) > init.c
$(CC-LD) $(LDFLAGS) -c init.c $(CLIBS)
ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o -lc $(CLIBS)
# If it can figure out the appropriate order, createtags will make sure
# that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
# in the tags list. It will attempt to do the same for dbxread.c and
# coffread.c. This makes using M-. on machine dependent routines much
# easier.
#
TAGS: ${TAGFILES}
createtags ${TAGFILES}
tags: TAGS
gdb.tar: ${TARFILES}
rm -f gdb.tar
mkdir dist-gdb
cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
tar chf gdb.tar dist-gdb
rm -rf dist-gdb
gdb.tar.Z: gdb.tar
compress gdb.tar
clean:
-rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX}
-rm -f init.c init.o
-rm -f gdb
realclean: clean
-rm -f expread.tab.c tags TAGS
xgdb.o : xgdb.c defs.h param.h symtab.h frame.h
$(CC) -c $(CFLAGS) xgdb.c -o $@
expread.tab.c : expread.y
@echo 'Expect 101 shift/reduce conflicts and 1 reduce/reduce conflict.'
yacc expread.y
mv y.tab.c expread.tab.c
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
#
# Only useful if you are using the gnu malloc routines.
#
malloc.o : malloc.c
${CC} -c ${MALLOC_FLAGS} malloc.c
#
# dep.o depends on ALL the dep files since we don't know which one
# is really being used.
#
dep.o : ${DEPFILES} defs.h param.h frame.h inferior.h obstack.h \
a.out.encap.h
# pinsn.o depends on ALL the opcode printers
# since we don't know which one is really being used.
pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \
${OPCODES}
#
# The rest of this is a standard dependencies list (hand edited output of
# cpp -M). It does not include dependencies of .o files on .c files.
#
blockframe.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
breakpoint.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
coffread.o : defs.h param.h
command.o : command.h defs.h
core.o : defs.h param.h a.out.encap.h
dbxread.o : param.h defs.h symtab.h obstack.h symseg.h a.out.encap.h \
stab.gnu.h
environ.o : environ.h
eval.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h
expprint.o : defs.h symtab.h obstack.h symseg.h param.h expression.h
findvar.o : defs.h param.h symtab.h obstack.h symseg.h frame.h value.h
infcmd.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \
environ.h value.h
inflow.o : defs.h param.h frame.h inferior.h
infrun.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \
wait.h
kdb-start.o : defs.h param.h
main.o : defs.h command.h param.h
malloc.o : getpagesize.h
obstack.o : obstack.h
printcmd.o : defs.h param.h frame.h symtab.h obstack.h symseg.h value.h \
expression.h
regex.o : regex.h
remote.o : defs.h param.h frame.h inferior.h wait.h
source.o : defs.h symtab.h obstack.h symseg.h param.h
stack.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
standalone.o : defs.h param.h symtab.h obstack.h symseg.h frame.h \
inferior.h wait.h
symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
symtab.o : defs.h symtab.h obstack.h symseg.h param.h obstack.h
utils.o : defs.h param.h
valarith.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h
valops.o : defs.h param.h symtab.h obstack.h symseg.h value.h frame.h \
inferior.h
valprint.o : defs.h param.h symtab.h obstack.h symseg.h value.h
values.o : defs.h param.h symtab.h obstack.h symseg.h value.h
robotussin.h : getpagesize.h
symtab.h : obstack.h symseg.h
a.out.encap.h : a.out.gnu.h

351
gdb/Makefile.dist Normal file
View File

@ -0,0 +1,351 @@
/* This file should be run through the C preprocessor by config.gdb
to produce the Makefile. */
/* System V:
If your system has a broken alloca(), define ALLOCA & ALLOCA1 below.
Also, if you compile gdb with a compiler which uses the coff
encapsulation feature (this is a function of the compiler used, NOT
of the m-?.h file selected by config.gdb), you must make sure that
the GNU nm is the one that is used by munch. */
/* If you are compiling with GCC, make sure that either 1) You use the
-traditional flag, or 2) You have the fixed include files where GCC
can reach them. Otherwise the ioctl calls in inflow.c and readline.c
will be incorrectly compiled. The "fixincludes" script in the gcc
distribution will fix your include files up. */
/* CC=gcc -traditional */
CC=cc
/* It is also possible that you will need to add -I/usr/include/sys to the
CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
is where it should be according to Posix). */
YACC=bison -y -v
/* YACC=yacc */
SHELL=/bin/sh
MAKE=make
/* Set this up with gcc if you have gnu ld and the loader will print out
line numbers for undefinded refs. */
/* CC-LD=gcc -static */
CC-LD=${CC}
/* If you are using the GNU C library, uncomment the following line. */
/* HAVE_VPRINTF_DEFINE = -DHAVE_VPRINTF */
/* -I. for "#include <obstack.h>". Possibly regex.h also. */
/* M_CFLAGS, if defined, has system-dependent CFLAGS. */
#if !defined(M_CFLAGS)
#define M_CFLAGS
#endif
CFLAGS = -g -I. ${HAVE_VPRINTF_DEFINE} M_CFLAGS
/* CFLAGS = -I. -g -pg ${HAVE_VPRINTF_DEFINE} */
/* None of the things in CFLAGS will do any harm, and on some systems
(e.g. SunOS4) it is important to use the M_CFLAGS. */
LDFLAGS = $(CFLAGS)
/*
define this to be "obstack.o" if you don't have the obstack library installed
you must at the same time define OBSTACK1 as "obstack.o"
so that the dependencies work right. Similarly with REGEX and "regex.o".
You must define REGEX and REGEX1 on USG machines.
If your sysyem is missing alloca(), or, more likely, it's there but
it doesn't work, define ALLOCA & ALLOCA1 */
OBSTACK = obstack.o
OBSTACK1 = obstack.o
#ifdef M_REGEX
REGEX = M_REGEX
REGEX1 = M_REGEX
#else
REGEX =
REGEX1 =
#endif
#ifdef M_ALLOCA
ALLOCA = M_ALLOCA
ALLOCA1 = M_ALLOCA
#else
ALLOCA =
ALLOCA1 =
#endif
/*
define this to be "malloc.o" if you want to use the gnu malloc routine
(useful for debugging memory allocation problems in gdb). Otherwise, leave
it blank. */
/* GNU_MALLOC = */
GNU_MALLOC = malloc.o
/* Flags to be used in compiling malloc.o
Specify range checking for storage allocation. */
/* MALLOC_FLAGS = ${CFLAGS} */
MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal_dump_core -DMSTATS
/* Define SYSV if compiling on a system V or HP machine. */
#ifdef M_SYSV
SYSV_DEFINE = -DSYSV
#else
SYSV_DEFINE =
#endif
/* MUNCH_DEFINE should be -DSYSV if have System V-style nm,
or null if have BSD-style nm. */
#ifdef M_BSD_NM
MUNCH_DEFINE =
#else
MUNCH_DEFINE = ${SYSV_DEFINE}
#endif
/* Flags that describe where you can find the termcap library.
You may need to make other arrangements for USG. */
TERMCAP = -ltermcap
/* M_CLIBS, if defined, has system-dependent libs
For example, -lPW for System V */
#ifndef M_CLIBS
#define M_CLIBS
#endif
CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC}
ADD_DEPS = ${OBSTACK1} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC}
SFILES = blockframe.c breakpoint.c dbxread.c coffread.c command.c core.c \
environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
kdb-start.c main.c printcmd.c \
remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
xgdb.c
DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
sparc-dep.c hp9k320-dep.c hp300bsd-dep.c news-dep.c i386-dep.c \
symmetry-dep.c convex-dep.c altos-dep.c
PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
ns32k-pinsn.c convex-pinsn.c
HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
inferior.h symseg.h symtab.h value.h wait.h \
a.out.encap.h a.out.gnu.h stab.gnu.h
OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
ns32k-opcode.h convex-opcode.h
MFILES = m-hp9k320.h m-hp300bsd.h m-i386.h m-i386gas.h \
m-i386-sysv3.2.h m-i386gas-sysv3.2.h m-isi.h m-merlin.h \
m-altos.h m-news.h m-newsos3.h m-npl.h m-pn.h \
m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h m-symmetry.h m-convex.h
/* This list of files really shouldn't be in this makefile, but I can't think
of any good way to get the readline makefile to tell us what files
to put in our tarfile. */
READLINE = readline.c history.c funmap.c \
emacs_keymap.c vi_keymap.c vi_mode.c keymaps.c \
readline.h history.h keymaps.h chardefs.h \
inc-readline.texinfo inc-history.texinfo \
Makefile ChangeLog
REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c alloca.c
TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
OTHERS = Makefile.dist createtags munch config.gdb ChangeLog README TAGS \
gdb.texinfo .gdbinit COPYING expread.tab.c stab.def \
XGDB-README copying.c Projects Convex.notes copying.awk hp-include
TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
${POSSLIBS}
TARFILES = ${TAGFILES} ${OTHERS} ${REMOTE_EXAMPLES}
OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
copying.o ${READLINEOBS}
TSOBS = core.o inflow.o dep.o
NTSOBS = standalone.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
RL_LIB = readline/libreadline.a
/* Do some fancy trickery to produce a line like
-DM_MAKEDEFINE="-DM_SYSV -DM_BSD_NM".
*/
MD=M_MAKEDEFINE
/* Avoid funny things that Sun's make throws in for us. */
/* TARGET_ARCH is supposed to get around it putting in the machine type.
If the "things" up there really is plural, we'll need to do something
else as well. */
/*.c.o:
${CC} -c ${CFLAGS} $< */
TARGET_ARCH=
gdb : $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) ${RL_LIB} $(CLIBS)
/* This is useful when debugging GDB, because Unix doesn't let you run GDB
on itself without copying the executable. So "make gdb1" will make
gdb and put a copy in gdb1, and you can run it with "gdb gdb1". */
gdb1 : gdb
cp gdb gdb1
Makefile : Makefile.dist
cp Makefile.dist tmp.c
/* This did not work-- -Usparc became "-Usparc" became "-Usparc.
Or something like that. */
/* $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=\"$(MD)\"" */
$(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=$(MD)"
-rm tmp.c
xgdb : $(OBS) $(TSOBS) xgdb.o ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) xgdb.o > init.c
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXmu -lXt -lX11 ${RL_LIB} $(CLIBS)
/* Old (pre R3) xgdb comp.
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXt -lX11 $(CLIBS) */
kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB}
rm -f init.c
./munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
$(CC) $(LDFLAGS) -c init.c $(CLIBS)
ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o ${RL_LIB} -lc $(CLIBS)
/* If it can figure out the appropriate order, createtags will make sure
that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
in the tags list. It will attempt to do the same for dbxread.c and
coffread.c. This makes using M-. on machine dependent routines much
easier. */
TAGS: ${TAGFILES}
createtags ${TAGFILES}
tags: TAGS
gdb.tar: ${TARFILES}
rm -f gdb.tar
mkdir dist-gdb
cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
mkdir dist-gdb/readline
cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s ../../readline/$$i . ; done
tar chf gdb.tar dist-gdb
rm -rf dist-gdb
/* Remove gdb.tar.Z so stupid compress doesn't ask whether we want to
overwrite it. compress -f is not what we want, because we do want
to know if compress would not make it smaller. */
gdb.tar.Z: gdb.tar
if [ -f gdb.tar.Z ]; then rm -f gdb.tar.Z; fi
compress gdb.tar
clean:
rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} ${GNU_MALLOC}
rm -f init.c init.o
rm -f gdb core gdb.tar gdb.tar.Z make.log
rm -f gdb[0-9]
cd readline ; make clean
distclean: clean expread.tab.c TAGS
rm -f dep.c opcode.h param.h pinsn.c config.status
rm -f y.output yacc.acts yacc.tmp
rm -f ${TESTS} Makefile
realclean: clean
rm -f expread.tab.c TAGS
rm -f dep.c opcode.h param.h pinsn.c config.status
rm -f Makefile
xgdb.o : defs.h param.h symtab.h frame.h
/* Make copying.c from COPYING */
copying.c : COPYING copying.awk
awk -f copying.awk < COPYING > copying.c
expread.tab.c : expread.y
@echo 'Expect 4 shift/reduce conflict.'
${YACC} expread.y
mv y.tab.c expread.tab.c
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
readline/libreadline.a : force_update
cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}" "CC=${CC}" libreadline.a
force_update :
/* Only useful if you are using the gnu malloc routines. */
malloc.o : malloc.c
${CC} -c ${MALLOC_FLAGS} malloc.c
/* dep.o depends on config.status in case someone reconfigures gdb out
from under an already compiled gdb. */
dep.o : dep.c config.status defs.h param.h frame.h inferior.h obstack.h \
a.out.encap.h
/* pinsn.o depends on config.status in case someone reconfigures gdb out
from under an already compiled gdb. */
pinsn.o : pinsn.c config.status defs.h param.h symtab.h obstack.h symseg.h \
frame.h opcode.h
/* The rest of this is a standard dependencies list (hand edited output of
cpp -M). It does not include dependencies of .o files on .c files. */
/* All files which depend on config.status also depend on param.h in case
someone reconfigures gdb out from under an already compiled gdb. */
blockframe.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
breakpoint.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
coffread.o : defs.h param.h config.status
command.o : command.h defs.h
core.o : defs.h param.h config.status a.out.encap.h
dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h a.out.encap.h \
stab.gnu.h
environ.o : environ.h
eval.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
expprint.o : defs.h symtab.h obstack.h symseg.h param.h config.status expression.h
findvar.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h value.h
infcmd.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
environ.h value.h
inflow.o : defs.h param.h config.status frame.h inferior.h
infrun.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
wait.h
kdb-start.o : defs.h param.h config.status
main.o : defs.h command.h param.h config.status
malloc.o : getpagesize.h
obstack.o : obstack.h
printcmd.o : defs.h param.h config.status frame.h symtab.h obstack.h symseg.h value.h \
expression.h
regex.o : regex.h
remote.o : defs.h param.h config.status frame.h inferior.h wait.h
source.o : defs.h symtab.h obstack.h symseg.h param.h config.status
stack.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
standalone.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h \
inferior.h wait.h
symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
symtab.o : defs.h symtab.h obstack.h symseg.h param.h config.status obstack.h
utils.o : defs.h param.h config.status
valarith.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
valops.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h frame.h \
inferior.h
valprint.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
values.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
robotussin.h : getpagesize.h
symtab.h : obstack.h symseg.h
a.out.encap.h : a.out.gnu.h

114
gdb/Projects Normal file
View File

@ -0,0 +1,114 @@
Suggested projects for aspiring or current GDB hackers
======================================================
(You should probably chat with kingdon@ai.mit.edu to make sure that
no one else is doing the project you chose).
Add watchpoints (break if a memory location changes). This would
usually have to involve constant single stepping, but occasionally
there is operating system support which gdb should be able to cleanly
use (e.g. on the 80386, there are 4 debug registers. By ptracing an
address into them, you can get a trap on writes or on reads and
writes).
Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
Suggestions:
1) Make each test in wait_for_inferior a seperate subroutine
call.
2) Combine wait_for_inferior and normal_stop to clean up
communication via global variables.
3) See if you can find some way to clean up the global
variables that are used; possibly group them by data flow
and information content?
Work out some kind of way to allow running the inferior to be done as
a sub-execution of, eg. breakpoint command lists. Currently running
the inferior interupts any command list execution. This would require
some rewriting of wait_for_inferior & friends, and hence should
probably be done in concert with the above.
Add function arguments to gdb user defined functions.
Add convenience variables that refer to exec file, symbol file,
selected frame source file, selected frame function, selected frame
line number, etc.
Add a "suspend" subcommand of the "continue" command to suspend gdb
while continuing execution of the subprocess. Useful when you are
debugging servers and you want to dodge out and initiate a connection
to a server running under gdb.
Make "handle" understand symbolic signal names.
Work out and implement a reasonably general mechanism for multi-threaded
processies. There are parts of one implemented in convex-dep.c, if
you want an example.
A standalone version of gdb on the i386 exists. Anyone who wants to
do some serious working cleaning it up and making it a general
standalone gdb should contact pace@wheaties.ai.mit.edu.
Add stab information to allow reasonable debugging of inline functions
(possibly they should show up on a stack backtrace? With a note
indicating that they weren't "real"?).
Implement support for specifying arbitrary locations of stack frames
(in practice, this usually requires specification of both the top and
bottom of the stack frame (fp and sp), since you *must* retrieve the
pc that was saved in the innermost frame).
Modify the naked "until" command to step until past the current source
line, rather than past the current pc value. This is tricky simply
because the low level routines have no way of specifying a multi-line
step range, and there is no way of saying "don't print stuff when we
stop" from above (otherwise could just call step many times).
Modify the handling of symbols grouped through BINCL/EINCL stabs to
allocate a partial symtab for each BINCL/EINCL grouping. This will
seriously decrease the size of inter-psymtab dependencies and hence
lessen the amount that needs to be read in when a new source file is
accessed.
Work out some method of saving breakpoints across the reloading of an
executable. Probably this should be by saving the commands by which
the breakpoints were set and re-executing them (as text locations may
change).
Do an "x/i $pc" after each stepi or nexti.
Modify all of the disassemblers to use printf_filtered to get correct
more filtering.
Modify gdb to work correctly with Pascal.
Rewrite macros that handle frame chaining and frameless functions.
They should be able to tell the difference between start, main, and a
frameless function called from main.
Work out what information would need to be included in an executable
by the compiler to allow gdb to debug functions which do not have a
frame pointer. Modify gdb and gcc to do this.
When `attached' to a program (via either OS support or remote
debugging), gdb should arrange to catch signals which the terminal
might send, as it is unlikely that the program will be able to notice
them. SIGINT and SIGTSTP are obvious examples.
Enhance the gdb manual with extra examples where needed.
Arrange for list_command not to use decode_line_1 and thus not require
symbols to be read in simply to read a source file.
Problem in xgdb; the readline library needs the terminal in CBREAK
mode for command line editing, but this makes it difficult to dispatch
on button presses. Possible solution: use a define to replace getc in
readline.c with a routine that does button dispatches. You should
probably see XGDB-README before you fiddle with XGDB. Also, someone
is implementing a new xgdb; it may not be worth while fiddling with
the old one.
# Local Variables:
# mode: text
# End:

View File

@ -1,367 +0,0 @@
head 1.4;
access ;
symbols ;
locks ; strict;
comment @# @;
1.4
date 89.03.27.21.28.33; author gnu; state Exp;
branches ;
next 1.3;
1.3
date 89.03.27.18.33.31; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.03.13.19.02.58; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.03.15.53; author gnu; state Exp;
branches ;
next ;
desc
@@
1.4
log
@More general support for ALLOCA and other local library routines;
other minor cleanup.
@
text
@# On HPUX, you need to add -Ihp-include to CFLAGS.
# The headers in the directory hp-include override system headers
# and tell GDB to use BSD executable file format.
# You must also define REGEX & REGEX1 below and ALLOCA & ALLOCA1 (get
# alloca.c from the emacs distribution) to the CLIBS.
# If you compile GDB with GCC on HPUX, you must make sure that the "nm" used
# in "munch" is GNU's nm. This is because gcc uses a different .o
# file format than the native HPUX compiler.
# On USG (System V) machines, you must make sure to setup REGEX &
# REGEX1 to point at regex.o and use the USG version of CLIBS.
# If your system has a broken alloca() -- most do -- then get
# alloca.c from the GNU Emacs distribution and set ALLOCA & ALLOCA1.
# Also, if you compile gdb with a compiler which uses the coff
# encapsulation feature (this is a function of the compiler used, NOT
# of the m-?.h file selected by config.gdb), you must make sure that
# the GNU nm is the one that is used by munch.
# On Sunos 4.0 machines, make sure to compile *without* shared
# libraries if you want to run gdb on itself. Make sure to compile
# any program on which you want to run gdb without shared libraries.
# If you are compiling with GCC, make sure that either 1) You use the
# -traditional flag, or 2) You have the fixed include files where GCC
# can reach them. Otherwise the ioctl calls in inflow.c will be
# incorrectly compiled. The "fixincludes" script in the gcc
# distribution will probably fix your include files up.
CC=cc
SHELL=/bin/sh
# Set this up with gcc if you have gnu ld and the loader will print out
# line numbers for undefinded refs.
CC-LD=${CC}
# -I. for "#include <obstack.h>". Possibly regex.h also.
#CFLAGS = -g -pg -I. -O
CFLAGS = -I. -g
#LDFLAGS = -pg -g
LDFLAGS = -g
# define this to be "obstack.o" if you don't have the obstack library installed
# you must at the same time define OBSTACK1 as "obstack.o"
# so that the dependencies work right. Similarly with REGEX and "regex.o".
# You must define REGEX and REGEX1 on USG machines.
# If your system is missing alloca(), or, more likely, it's there but it
# doesn't work, define ALLOCA and ALLOCA1.
OBSTACK = obstack.o
OBSTACK1 = obstack.o
REGEX = regex.o
REGEX1 = regex.o
ALLOCA = alloca.o
ALLOCA1 = alloca.o
ADD_FILES = $(OBSTACK) $(REGEX) $(ALLOCA) $(GNU_MALLOC)
ADD_DEPS = $(OBSTACK1) $(REGEX1) $(ALLOCA1) $(GNU_MALLOC)
#
# define this to be "malloc.o" if you want to use the gnu malloc routine
# (useful for debugging memory allocation problems in gdb). Otherwise, leave
# it blank.
GNU_MALLOC =
#GNU_MALLOC = malloc.o
# Flags to be used in compiling malloc.o
# Specify range checking for storage allocation.
MALLOC_FLAGS =
#MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal -DMSTATS
# for BSD
CLIBS = $(ADD_FILES)
# for USG
#CLIBS= $(ADD_FILES) -lPW
SFILES = blockframe.c breakpoint.c coffread.c command.c core.c dbxread.c \
environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
kdb-start.c main.c printcmd.c \
remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
xgdb.c
DEPFILES = convex-dep.c umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
sparc-dep.c hp9k320-dep.c news-dep.c i386-dep.c
PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
ns32k-pinsn.c
HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
inferior.h symseg.h symtab.h value.h wait.h \
a.out.encap.h a.out.gnu.h stab.gnu.h
OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
ns32k-opcode.h
MFILES = m-hp9k320.h m-i386.h m-i386gas.h m-isi.h m-merlin.h m-news.h \
m-npl.h m-pn.h m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h
POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c
TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
OTHERS = Makefile createtags munch config.gdb ChangeLog README TAGS \
gdb.texinfo .gdbinit COPYING expread.tab.c stab.def hp-include
TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
${POSSLIBS}
TARFILES = ${TAGFILES} ${OTHERS}
OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
values.o eval.o valops.o valarith.o valprint.o printcmd.o \
symtab.o symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
command.o utils.o expread.o expprint.o pinsn.o environ.o version.o
TSOBS = core.o inflow.o dep.o
NTSOBS = standalone.o
TSSTART = /lib/crt0.o
NTSSTART = kdb-start.o
gdb : $(OBS) $(TSOBS) $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(TSOBS) > init.c
${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) $(CLIBS)
xgdb : $(OBS) $(TSOBS) xgdb.o $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(TSOBS) xgdb.o > init.c
$(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
-lXaw -lXt -lX11 $(CLIBS)
kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS)
-rm -f init.c
./munch $(OBS) $(NTSOBS) > init.c
$(CC-LD) $(LDFLAGS) -c init.c $(CLIBS)
ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o -lc $(CLIBS)
# If it can figure out the appropriate order, createtags will make sure
# that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
# in the tags list. It will attempt to do the same for dbxread.c and
# coffread.c. This makes using M-. on machine dependent routines much
# easier.
#
TAGS: ${TAGFILES}
createtags ${TAGFILES}
tags: TAGS
gdb.tar: ${TARFILES}
rm -f gdb.tar
mkdir dist-gdb
cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
tar chf gdb.tar dist-gdb
rm -rf dist-gdb
gdb.tar.Z: gdb.tar
compress gdb.tar
clean:
-rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX}
-rm -f init.c init.o
-rm -f gdb
realclean: clean
-rm -f expread.tab.c tags TAGS
xgdb.o : xgdb.c defs.h param.h symtab.h frame.h
$(CC) -c $(CFLAGS) xgdb.c -o $@@
expread.tab.c : expread.y
@@echo 'Expect 101 shift/reduce conflicts and 1 reduce/reduce conflict.'
yacc expread.y
mv y.tab.c expread.tab.c
expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
$(CC) -c ${CFLAGS} expread.tab.c
mv expread.tab.o expread.o
#
# Only useful if you are using the gnu malloc routines.
#
malloc.o : malloc.c
${CC} -c ${MALLOC_FLAGS} malloc.c
#
# dep.o depends on ALL the dep files since we don't know which one
# is really being used.
#
dep.o : ${DEPFILES} defs.h param.h frame.h inferior.h obstack.h \
a.out.encap.h
# pinsn.o depends on ALL the opcode printers
# since we don't know which one is really being used.
pinsn.o : ${PINSNS} defs.h param.h symtab.h obstack.h symseg.h frame.h \
${OPCODES}
#
# The rest of this is a standard dependencies list (hand edited output of
# cpp -M). It does not include dependencies of .o files on .c files.
#
blockframe.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
breakpoint.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
coffread.o : defs.h param.h
command.o : command.h defs.h
core.o : defs.h param.h a.out.encap.h
dbxread.o : param.h defs.h symtab.h obstack.h symseg.h a.out.encap.h \
stab.gnu.h
environ.o : environ.h
eval.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h
expprint.o : defs.h symtab.h obstack.h symseg.h param.h expression.h
findvar.o : defs.h param.h symtab.h obstack.h symseg.h frame.h value.h
infcmd.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \
environ.h value.h
inflow.o : defs.h param.h frame.h inferior.h
infrun.o : defs.h param.h symtab.h obstack.h symseg.h frame.h inferior.h \
wait.h
kdb-start.o : defs.h param.h
main.o : defs.h command.h param.h
malloc.o : getpagesize.h
obstack.o : obstack.h
printcmd.o : defs.h param.h frame.h symtab.h obstack.h symseg.h value.h \
expression.h
regex.o : regex.h
remote.o : defs.h param.h frame.h inferior.h wait.h
source.o : defs.h symtab.h obstack.h symseg.h param.h
stack.o : defs.h param.h symtab.h obstack.h symseg.h frame.h
standalone.o : defs.h param.h symtab.h obstack.h symseg.h frame.h \
inferior.h wait.h
symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
symtab.o : defs.h symtab.h obstack.h symseg.h param.h obstack.h
utils.o : defs.h param.h
valarith.o : defs.h param.h symtab.h obstack.h symseg.h value.h expression.h
valops.o : defs.h param.h symtab.h obstack.h symseg.h value.h frame.h \
inferior.h
valprint.o : defs.h param.h symtab.h obstack.h symseg.h value.h
values.o : defs.h param.h symtab.h obstack.h symseg.h value.h
robotussin.h : getpagesize.h
symtab.h : obstack.h symseg.h
a.out.encap.h : a.out.gnu.h
@
1.3
log
@A/UX changes. Use cc, use local regex.o, use local alloca.o
@
text
@d4 2
a5 2
# You must also define REGEX & REGEX1 below and add alloca.o (from
# the emacs distribution) to the CLIBS.
d12 2
d26 2
a27 1
# incorrectly compiled.
d46 2
d52 4
d70 1
a70 1
#CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC)
d72 1
a72 1
CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) alloca.o
d122 1
a122 1
gdb : $(OBS) $(TSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC}
d127 1
a127 1
xgdb : $(OBS) $(TSOBS) xgdb.o $(OBSTACK1) $(REGEX1) ${GNU_MALLOC}
d133 1
a133 1
kdb : $(NTSSTART) $(OBS) $(NTSOBS) $(OBSTACK1) $(REGEX1) ${GNU_MALLOC}
d161 1
a161 1
-rm -f init.c
d165 1
a165 1
-rm -f expread.tab.c
@
1.2
log
@All rm's to rm -f's.
@
text
@d26 1
a26 1
CC=gcc
d45 2
a46 2
REGEX =
REGEX1 =
d61 1
a61 1
CLIBS = $(OBSTACK) $(REGEX) $(GNU_MALLOC)
d63 1
a63 1
#CLIBS= $(OBSTACK) $(REGEX) $(GNU_MALLOC) -lPW
@
1.1
log
@Initial revision
@
text
@d26 1
a26 1
CC=/bin/cc
d114 1
a114 1
-rm init.c
d119 1
a119 1
-rm init.c
d125 1
a125 1
-rm init.c
d151 3
a153 3
-rm ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX}
-rm init.c
-rm gdb
d156 1
a156 1
-rm expread.tab.c
@

View File

@ -1,606 +0,0 @@
head 1.3;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.3
date 89.03.16.21.09.52; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.02.09.23.21.53; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.15.15.16; author gnu; state Exp;
branches ;
next ;
desc
@@
1.3
log
@Don't stop the stack trace until the "next frame pointer" is zero.
@
text
@/* Get info from stack frames;
convert between frames, blocks, functions and pc values.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
/* Address of end of first object file.
This file is assumed to be a startup file
and frames with pc's inside it
are treated as nonexistent. */
CORE_ADDR first_object_file_end;
/* Address of innermost stack frame (contents of FP register) */
static FRAME current_frame;
struct block *block_for_pc ();
CORE_ADDR get_pc_function_start ();
/*
* Cache for frame addresses already read by gdb. Valid only while
* inferior is stopped. Control variables for the frame cache should
* be local to this module.
*/
struct obstack frame_cache_obstack;
/* Return the innermost (currently executing) stack frame. */
FRAME
get_current_frame ()
{
/* We assume its address is kept in a general register;
param.h says which register. */
return current_frame;
}
void
set_current_frame (frame)
FRAME frame;
{
current_frame = frame;
}
FRAME
create_new_frame (addr, pc)
FRAME_ADDR addr;
CORE_ADDR pc;
{
struct frame_info *fci; /* Same type as FRAME */
fci = (struct frame_info *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_info));
/* Arbitrary frame */
fci->next = (struct frame_info *) 0;
fci->prev = (struct frame_info *) 0;
fci->frame = addr;
fci->next_frame = 0; /* Since arbitrary */
fci->pc = pc;
#ifdef INIT_EXTRA_FRAME_INFO
INIT_EXTRA_FRAME_INFO (fci);
#endif
return fci;
}
/* Return the frame that called FRAME.
If FRAME is the original frame (it has no caller), return 0. */
FRAME
get_prev_frame (frame)
FRAME frame;
{
/* We're allowed to know that FRAME and "struct frame_info *" are
the same */
return get_prev_frame_info (frame);
}
/*
* Flush the entire frame cache.
*/
void
flush_cached_frames ()
{
/* Since we can't really be sure what the first object allocated was */
obstack_free (&frame_cache_obstack, 0);
obstack_init (&frame_cache_obstack);
current_frame = (struct frame_info *) 0; /* Invalidate cache */
}
/* Return a structure containing various interesting information
about a specified stack frame. */
/* How do I justify including this function? Well, the FRAME
identifier format has gone through several changes recently, and
it's not completely inconceivable that it could happen again. If
it does, have this routine around will help */
struct frame_info *
get_frame_info (frame)
FRAME frame;
{
return frame;
}
/* Return a structure containing various interesting information
about the frame that called NEXT_FRAME. */
struct frame_info *
get_prev_frame_info (next_frame)
FRAME next_frame;
{
FRAME_ADDR address;
struct frame_info *prev;
int fromleaf = 0;
/* If we are within "start" right now, don't go any higher. */
/* This truncates stack traces of things at sigtramp() though,
because sigtramp() doesn't have a normal return PC, it has
garbage or a small value (seen: 3) in the return PC slot.
It's VITAL to see where the signal occurred, so punt this. */
#if 0
if (next_frame && next_frame->pc < first_object_file_end)
return 0;
#endif
/* If the requested entry is in the cache, return it.
Otherwise, figure out what the address should be for the entry
we're about to add to the cache. */
if (!next_frame)
{
if (!current_frame)
error ("No frame is currently selected.");
return current_frame;
}
else
{
/* If we have the prev one, return it */
if (next_frame->prev)
return next_frame->prev;
/* There is a questionable, but probably always correct
assumption being made here. The assumption is that if
functions on a specific machine has a FUNCTION_START_OFFSET,
then this is used by the function call instruction for some
purpose. If the function call instruction has this much hair
in it, it probably also sets up the frame pointer
automatically (ie. we'll never have what I am calling a
"leaf node", one which shares a frame pointer with it's
calling function). This is true on a vax. The only other
way to find this out would be to setup a seperate macro
"FUNCTION_HAS_FRAME_POINTER", which would often be equivalent
to SKIP_PROLOGUE modifying a pc value. */
#if FUNCTION_START_OFFSET == 0
if (!(next_frame->next))
{
/* Innermost */
CORE_ADDR func_start, after_prologue;
func_start = (get_pc_function_start (next_frame->pc) +
FUNCTION_START_OFFSET);
after_prologue = func_start;
SKIP_PROLOGUE (after_prologue);
if (after_prologue == func_start)
{
fromleaf = 1;
address = next_frame->frame;
}
}
#endif
if (!fromleaf)
{
/* Two macros defined in param.h specify the machine-dependent
actions to be performed here. */
/* First, get the frame's chain-pointer.
If that is zero, the frame is the outermost frame. */
address = FRAME_CHAIN (next_frame);
if (!FRAME_CHAIN_VALID (address, next_frame))
return 0;
/* If frame has a caller, combine the chain pointer and
the frame's own address to get the address of the caller. */
address = FRAME_CHAIN_COMBINE (address, next_frame);
}
}
prev = (struct frame_info *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_info));
if (next_frame)
next_frame->prev = prev;
prev->next = next_frame;
prev->prev = (struct frame_info *) 0;
prev->frame = address;
prev->next_frame = prev->next ? prev->next->frame : 0;
#ifdef INIT_EXTRA_FRAME_INFO
INIT_EXTRA_FRAME_INFO(prev);
#endif
/* This entry is in the frame queue now, which is good since
FRAME_SAVED_PC may use that queue to figure out it's value
(see m-sparc.h). We want the pc saved in the inferior frame. */
prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
return prev;
}
CORE_ADDR
get_frame_pc (frame)
FRAME frame;
{
struct frame_info *fi;
fi = get_frame_info (frame);
return fi->pc;
}
/* Find the addresses in which registers are saved in FRAME. */
void
get_frame_saved_regs (frame_info_addr, saved_regs_addr)
struct frame_info *frame_info_addr;
struct frame_saved_regs *saved_regs_addr;
{
#if 1
FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
#else
{
register int regnum;
register int regmask;
register CORE_ADDR next_addr;
register CORE_ADDR pc;
int nextinsn;
bzero (&*saved_regs_addr, sizeof *saved_regs_addr);
if ((frame_info_addr)->pc >= ((frame_info_addr)->frame
- CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4)
&& (frame_info_addr)->pc <= (frame_info_addr)->frame)
{
next_addr = (frame_info_addr)->frame;
pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4;
}
else
{
pc = get_pc_function_start ((frame_info_addr)->pc);
/* Verify we have a link a6 instruction next;
if not we lose. If we win, find the address above the saved
regs using the amount of storage from the link instruction. */
if (044016 == read_memory_integer (pc, 2))
{
next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4);
pc += 4;
}
else if (047126 == read_memory_integer (pc, 2))
{
next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2);
pc+=2;
}
else goto lose;
/* If have an addal #-n, sp next, adjust next_addr. */
if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
{
next_addr += read_memory_integer (pc += 2, 4);
pc += 4;
}
}
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
regmask = read_memory_integer (pc + 2, 2);
/* But before that can come an fmovem. Check for it. */
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf227 == nextinsn
&& (regmask & 0xff00) == 0xe000)
{
pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
for (regnum = FP0_REGNUM + 7;
regnum >= FP0_REGNUM;
regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr -= 12);
regmask = read_memory_integer (pc + 2, 2);
}
if (0044327 == read_memory_integer (pc, 2))
{
pc += 4; /* Regmask's low bit is for register 0, the first written */
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4;
}
else if (0044347 == read_memory_integer (pc, 2))
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr -= 4); }
else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
(*saved_regs_addr).regs[regnum] = (next_addr -= 4); }
/* fmovemx to index of sp may follow. */
regmask = read_memory_integer (pc + 2, 2);
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf236 == nextinsn
&& (regmask & 0xff00) == 0xf000)
{
pc += 10; /* Regmask's low bit is for register fp0, the first written */
for (regnum = FP0_REGNUM + 7;
regnum >= FP0_REGNUM;
regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12;
regmask = read_memory_integer (pc + 2, 2);
}
/* clrw -(sp); movw ccr,-(sp) may follow. */
if (0x426742e7 == read_memory_integer (pc, 4))
(*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4);
lose: ;
(*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8;
(*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame;
(*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4;
}
#endif
}
/* Return the innermost lexical block in execution
in a specified stack frame. The frame address is assumed valid. */
struct block *
get_frame_block (frame)
FRAME frame;
{
struct frame_info *fi;
fi = get_frame_info (frame);
return block_for_pc (fi->pc);
}
struct block *
get_current_block ()
{
return block_for_pc (read_pc ());
}
CORE_ADDR
get_pc_function_start (pc)
CORE_ADDR pc;
{
register struct block *bl = block_for_pc (pc);
register struct symbol *symbol;
if (bl == 0 || (symbol = block_function (bl)) == 0)
{
register int misc_index = find_pc_misc_function (pc);
if (misc_index >= 0)
return misc_function_vector[misc_index].address;
return 0;
}
bl = SYMBOL_BLOCK_VALUE (symbol);
return BLOCK_START (bl);
}
/* Return the symbol for the function executing in frame FRAME. */
struct symbol *
get_frame_function (frame)
FRAME frame;
{
register struct block *bl = get_frame_block (frame);
if (bl == 0)
return 0;
return block_function (bl);
}
/* Return the innermost lexical block containing the specified pc value,
or 0 if there is none. */
extern struct symtab *psymtab_to_symtab ();
struct block *
block_for_pc (pc)
register CORE_ADDR pc;
{
register struct block *b;
register int bot, top, half;
register struct symtab *s;
register struct partial_symtab *ps;
struct blockvector *bl;
/* First search all symtabs for one whose file contains our pc */
for (s = symtab_list; s; s = s->next)
{
bl = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bl, 0);
if (BLOCK_START (b) <= pc
&& BLOCK_END (b) > pc)
break;
}
if (s == 0)
for (ps = partial_symtab_list; ps; ps = ps->next)
{
if (ps->textlow <= pc
&& ps->texthigh > pc)
{
s = psymtab_to_symtab (ps);
bl = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bl, 0);
break;
}
}
if (s == 0)
return 0;
/* Then search that symtab for the smallest block that wins. */
/* Use binary search to find the last block that starts before PC. */
bot = 0;
top = BLOCKVECTOR_NBLOCKS (bl);
while (top - bot > 1)
{
half = (top - bot + 1) >> 1;
b = BLOCKVECTOR_BLOCK (bl, bot + half);
if (BLOCK_START (b) <= pc)
bot += half;
else
top = bot + half;
}
/* Now search backward for a block that ends after PC. */
while (bot >= 0)
{
b = BLOCKVECTOR_BLOCK (bl, bot);
if (BLOCK_END (b) > pc)
return b;
bot--;
}
return 0;
}
/* Return the function containing pc value PC.
Returns 0 if function is not known. */
struct symbol *
find_pc_function (pc)
CORE_ADDR pc;
{
register struct block *b = block_for_pc (pc);
if (b == 0)
return 0;
return block_function (b);
}
/* Find the misc function whose address is the largest
while being less than PC. Return its index in misc_function_vector.
Returns -1 if PC is not in suitable range. */
int
find_pc_misc_function (pc)
register CORE_ADDR pc;
{
register int lo = 0;
register int hi = misc_function_count-1;
register int new;
register int distance;
/* Note that the last thing in the vector is always _etext. */
/* Above statement is not *always* true - fix for case where there are */
/* no misc functions at all (ie no symbol table has been read). */
if (hi < 0) return -1; /* no misc functions recorded */
/* trivial reject range test */
if (pc < misc_function_vector[0].address ||
pc > misc_function_vector[hi].address)
return -1;
do {
new = (lo + hi) >> 1;
distance = misc_function_vector[new].address - pc;
if (distance == 0)
return new; /* an exact match */
else if (distance > 0)
hi = new;
else
lo = new;
} while (hi-lo != 1);
/* if here, we had no exact match, so return the lower choice */
return lo;
}
/* Return the innermost stack frame executing inside of the specified block,
or zero if there is no such frame. */
FRAME
block_innermost_frame (block)
struct block *block;
{
struct frame_info *fi;
register FRAME frame;
register CORE_ADDR start = BLOCK_START (block);
register CORE_ADDR end = BLOCK_END (block);
frame = 0;
while (1)
{
frame = get_prev_frame (frame);
if (frame == 0)
return 0;
fi = get_frame_info (frame);
if (fi->pc >= start && fi->pc < end)
return frame;
}
}
void
_initialize_blockframe ()
{
obstack_init (&frame_cache_obstack);
}
@
1.2
log
@Avoid fatal error for simple user error
@
text
@d142 5
d149 1
@
1.1
log
@Initial revision
@
text
@d152 1
a152 1
fatal ("get_prev_frame_info: Called before cache primed");
@

File diff suppressed because it is too large Load Diff

View File

@ -1,229 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @@;
1.2
date 89.03.27.18.38.55; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.13.19.14.24; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Add A/UX option (config.gdb aux).
@
text
@#!/bin/sh
#
# Shell script to create proper links to machine-dependent files in
# preparation for compiling gdb.
#
# Usage: config.gdb machine [operating-system]
#
# If config.gdb succeeds, it leaves its status in config.status.
# If config.gdb fails after disturbing the status quo,
# config.status is removed.
#
progname=$0
case $# in
1)
machine=$1
os="none"
;;
2)
machine=$1
os=$2
;;
*)
echo "Usage: $progname machine [operating-system]"
echo "Available machine types:"
echo m-*.h | sed 's/m-//g' | sed 's/\.h//g'
if [ -r config.status ]
then
cat config.status
fi
exit 1
;;
esac
paramfile=m-${machine}.h
pinsnfile=${machine}-pinsn.c
opcodefile=${machine}-opcode.h
if [ -r ${machine}-dep.c ]
then
depfile=${machine}-dep.c
else
depfile=default-dep.c
fi
#
# Special cases.
# If a file is not needed, set the filename to 'skip' and it will be
# ignored.
#
case $machine in
aux)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
vax)
pinsnfile=vax-pinsn.c
opcodefile=vax-opcode.h
;;
hp9k320)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
isi)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
i386)
echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile"
opcodefile=skip
;;
i386gas)
echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile"
echo "Use of the coff encapsulation features also requires the GNU binutils utilities"
echo "to be ahead of their System V counterparts in your path."
pinsnfile=i386-pinsn.c
depfile=i386-dep.c
opcodefile=skip
;;
merlin)
pinsnfile=ns32k-pinsn.c
opcodefile=ns32k-opcode.h
;;
news)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
npl)
pinsnfile=gld-pinsn.c
;;
pn)
pinsnfile=gld-pinsn.c
;;
sun2)
case $os in
os4|sunos4)
paramfile=m-sun2os4.h
;;
os2|sunos2)
paramfile=m-sun2os2.h
esac
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun2os2)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun2os4)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun3)
case $os in
os4|sunos4)
paramfile=m-sun3os4.h
esac
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun3os4)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
depfile=sun3-dep.c
;;
sun4os4)
pinsnfile=sparc-pinsn.c
opcodefile=sparc-opcode.h
depfile=sparc-dep.c
;;
umax)
pinsnfile=ns32k-pinsn.c
opcodefile=ns32k-opcode.h
;;
sparc|sun4)
case $os in
os4|sunos4)
paramfile=m-sun4os4.h
esac
pinsnfile=sparc-pinsn.c
opcodefile=sparc-opcode.h
depfile=sparc-dep.c
paramfile=m-sparc.h
;;
test)
paramfile=one
pinsnfile=three
opcodefile=four
;;
*)
echo "Unknown machine type: \`$machine'"
echo "Available types:"
echo m-*.h | sed 's/m-//g' | sed 's/\.h//g'
exit 1
esac
files="$paramfile $pinsnfile $opcodefile $depfile"
links="param.h pinsn.c opcode.h dep.c"
while [ -n "$files" ]
do
# set file to car of files, files to cdr of files
set $files; file=$1; shift; files=$*
set $links; link=$1; shift; links=$*
if [ "$file" != skip ]
then
if [ ! -r $file ]
then
echo "$progname: cannot create a link \`$link',"
echo "since the file \`$file' does not exist."
exit 1
fi
rm -f $link config.status
# Make a symlink if possible, otherwise try a hard link
ln -s $file $link 2>/dev/null || ln $file $link
if [ ! -r $link ]
then
echo "$progname: unable to link \`$link' to \`$file'."
exit 1
fi
echo "Linked \`$link' to \`$file'."
fi
done
echo "Links are now set up for use with a $machine." \
| tee config.status
exit 0
@
1.1
log
@Initial revision
@
text
@d53 4
@

View File

@ -1,651 +0,0 @@
head 1.4;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.4
date 89.03.27.18.39.18; author gnu; state Exp;
branches ;
next 1.3;
1.3
date 89.02.10.01.39.45; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.02.09.23.22.33; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.22.49.56; author gnu; state Exp;
branches ;
next ;
desc
@@
1.4
log
@Unisoft Assholes changes for user.ps. Avoid sys/fcntl.h.
@
text
@/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "gdbcore.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
#endif
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
#else
#include <a.out.h>
#endif
#ifndef N_MAGIC
#ifdef COFF_FORMAT
#define N_MAGIC(exec) ((exec).magic)
#else
#define N_MAGIC(exec) ((exec).a_magic)
#endif
#endif
#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/file.h>
#include <sys/stat.h>
#ifdef UNISOFT_ASSHOLES
#define PMMU
#define NEW_PMMU
#include <sys/seg.h> /* Required for user.ps */
#include <sys/time.h> /* '' */
#include <sys/mmu.h> /* '' */
#include <sys/reg.h>
#define mc68881 /* Required to get float in user.ps */
#endif
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else
#include <sys/user.h>
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
#ifndef N_DATADDR
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
#ifndef COFF_FORMAT
#define AOUTHDR struct exec
#endif
extern char *sys_siglist[];
extern core_file_command (), exec_file_command ();
/* Hook for `exec_file_command' command to call. */
void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
char *corefile;
char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
int corechan;
int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
CORE_ADDR data_start;
CORE_ADDR data_end;
CORE_ADDR stack_start;
CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
CORE_ADDR text_start;
CORE_ADDR text_end;
CORE_ADDR exec_data_start;
CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
int text_offset;
/* Address in executable file of start of data area data. */
int exec_data_offset;
/* Address in core file of start of data area data. */
int data_offset;
/* Address in core file of start of stack area data. */
int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
FILHDR file_hdr;
SCNHDR text_hdr;
SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
AOUTHDR core_aouthdr;
/* a.out header of exec file. */
AOUTHDR exec_aouthdr;
void validate_files ();
unsigned int register_addr ();
/* Call this to specify the hook for exec_file_command to call back.
This is called from the x-window display code. */
void
specify_exec_file_hook (hook)
void (*hook) ();
{
exec_file_display_hook = hook;
}
/* The exec file must be closed before running an inferior.
If it is needed again after the inferior dies, it must
be reopened. */
void
close_exec_file ()
{
if (execchan >= 0)
close (execchan);
execchan = -1;
}
void
reopen_exec_file ()
{
if (execchan < 0 && execfile != 0)
{
char *filename = concat (execfile, "", "");
exec_file_command (filename, 0);
free (filename);
}
}
/* If we have both a core file and an exec file,
print a warning if they don't go together.
This should really check that the core file came
from that exec file, but I don't know how to do it. */
void
validate_files ()
{
if (execfile != 0 && corefile != 0)
{
struct stat st_core;
fstat (corechan, &st_core);
if (N_MAGIC (core_aouthdr) != 0
&& bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
printf ("Warning: core file does not match specified executable file.\n");
else if (exec_mtime > st_core.st_mtime)
printf ("Warning: exec file is newer than core file.\n");
}
}
/* Return the name of the executable file as a string.
ERR nonzero means get error if there is none specified;
otherwise return 0 in that case. */
char *
get_exec_file (err)
int err;
{
if (err && execfile == 0)
error ("No executable file specified.\n\
Use the \"exec-file\" and \"symbol-file\" commands.");
return execfile;
}
int
have_core_file_p ()
{
return corefile != 0;
}
static void
files_info ()
{
char *symfile;
extern char *get_sym_file ();
if (execfile)
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
if (corefile)
printf ("Core dump file \"%s\".\n", corefile);
else
printf ("No core dump file\n");
if (have_inferior_p ())
printf ("Using the running image of the program, rather than these files.\n");
symfile = get_sym_file ();
if (symfile != 0)
printf ("Symbols from \"%s\".\n", symfile);
if (! have_inferior_p ())
{
if (execfile)
{
printf ("Text segment in executable from 0x%x to 0x%x.\n",
text_start, text_end);
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
if (corefile)
printf("(But since we have a core file, we're using...)\n");
}
if (corefile)
{
printf ("Data segment in core file from 0x%x to 0x%x.\n",
data_start, data_end);
printf ("Stack segment in core file from 0x%x to 0x%x.\n",
stack_start, stack_end);
}
}
}
/* Read "memory data" from core file and/or executable file.
Returns zero if successful, 1 if xfer_core_file failed, errno value if
ptrace failed. */
int
read_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
return read_inferior_memory (memaddr, myaddr, len);
else
return xfer_core_file (memaddr, myaddr, len);
}
/* Write LEN bytes of data starting at address MYADDR
into debugged program memory at address MEMADDR.
Returns zero if successful, or an errno value if ptrace failed. */
int
write_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
return write_inferior_memory (memaddr, myaddr, len);
else
error ("Can write memory only when program being debugged is running.");
}
/* Read from the program's memory (except for inferior processes).
This function is misnamed, since it only reads, never writes; and
since it will use the core file and/or executable file as necessary.
It should be extended to write as well as read, FIXME, for patching files.
Return 0 if address could be read, 1 if not. */
int
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
register int val;
int xferchan;
char **xferfile;
int fileptr;
int returnval = 0;
while (len > 0)
{
xferfile = 0;
xferchan = 0;
/* Determine which file the next bunch of addresses reside in,
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
If desired address is nonexistent, leave them zero.
i is set to the number of bytes that can be handled
along with the next address.
We put the most likely tests first for efficiency. */
/* Note that if there is no core file
data_start and data_end are equal. */
if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
xferfile = &corefile;
xferchan = corechan;
}
/* Note that if there is no core file
stack_start and stack_end are equal. */
else if (memaddr >= stack_start && memaddr < stack_end)
{
i = min (len, stack_end - memaddr);
fileptr = memaddr - stack_start + stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
else if (corechan < 0
&& memaddr >= exec_data_start && memaddr < exec_data_end)
{
i = min (len, exec_data_end - memaddr);
fileptr = memaddr - exec_data_start + exec_data_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr >= text_start && memaddr < text_end)
{
i = min (len, text_end - memaddr);
fileptr = memaddr - text_start + text_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end
&& memaddr < (corechan >= 0? data_start : exec_data_start))
{
i = min (len, data_start - memaddr);
}
else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
&& memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
}
else
{
/* Address did not classify into one of the known ranges.
This could be because data_start != exec_data_start
or data_end similarly. */
abort();
}
/* Now we know which file to use.
Set up its pointer and transfer the data. */
if (xferfile)
{
if (*xferfile == 0)
if (xferfile == &execfile)
error ("No program file to examine.");
else
error ("No core dump file or running program to examine.");
val = lseek (xferchan, fileptr, 0);
if (val < 0)
perror_with_name (*xferfile);
val = myread (xferchan, myaddr, i);
if (val < 0)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing.
(FIXME we never write.) */
else
{
bzero (myaddr, i);
returnval = 1;
}
memaddr += i;
myaddr += i;
len -= i;
}
return returnval;
}
/* My replacement for the read system call.
Used like `read' but keeps going if `read' returns too soon. */
int
myread (desc, addr, len)
int desc;
char *addr;
int len;
{
register int val;
int orglen = len;
while (len > 0)
{
val = read (desc, addr, len);
if (val < 0)
return val;
if (val == 0)
return orglen - len;
len -= val;
addr += val;
}
return orglen;
}
#ifdef REGISTER_U_ADDR
/* Return the address in the core dump or inferior of register REGNO.
BLOCKEND is the address of the end of the user structure. */
unsigned int
register_addr (regno, blockend)
int regno;
int blockend;
{
int addr;
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
REGISTER_U_ADDR (addr, blockend, regno);
return addr;
}
#endif /* REGISTER_U_ADDR */
void
_initialize_core()
{
corechan = -1;
execchan = -1;
corefile = 0;
execfile = 0;
exec_file_display_hook = 0;
text_start = 0;
text_end = 0;
data_start = 0;
data_end = 0;
exec_data_start = 0;
exec_data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
add_com ("core-file", class_files, core_file_command,
"Use FILE as core dump for examining memory and registers.\n\
No arg means have no core file.");
add_com ("exec-file", class_files, exec_file_command,
"Use FILE as program for getting contents of pure memory.\n\
If FILE cannot be found as specified, your execution directory path\n\
is searched for a command of that name.\n\
No arg means have no executable file.");
add_info ("files", files_info, "Names of files being debugged.");
}
@
1.3
log
@Fix up "info files" some more, to give more information.
Rearrange the tests in xfer_core_file to avoid dependencies
between data_start and exec_data_start, and for efficiency
and add an abort() to test correctness. (If you take out
never mind...)
@
text
@d27 1
a27 1
#include <sys/fcntl.h>
d50 10
@
1.2
log
@Create gdbcore.h for externally visible variables;
spiff up the "info files" output to make it easier to read and more
informative.
@
text
@d250 4
d257 4
a260 7
printf ("Data segment in core file from 0x%x to 0x%x.\nStack segment in core file from 0x%x to 0x%x.\n",
data_start, data_end, stack_start, stack_end);
}
else if (execfile)
{
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
d297 3
a299 1
/* Return 0 if address could be read, 1 if not. */
d301 4
d327 1
d329 1
d331 3
a333 1
along with the next address. */
a334 17
if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end && memaddr < data_start)
{
i = min (len, data_start - memaddr);
}
else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
&& memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
}
d337 1
a337 1
else if (memaddr >= data_start && memaddr < data_end)
d368 25
d411 2
a412 1
read zeros if reading, or do nothing if writing. */
@
1.1
log
@Initial revision
@
text
@d2 1
a2 1
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
d23 1
d35 1
d43 1
d231 4
a234 1
if (corefile == 0)
a235 2
else
printf ("Core dump file \"%s\".\n", corefile);
d242 1
a242 1
printf ("Symbols loaded from \"%s\".\n", symfile);
d248 1
a248 1
printf ("Text segment from 0x%x to 0x%x.\n",
d253 1
a253 1
printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
d256 1
a256 1
else
@

File diff suppressed because it is too large Load Diff

View File

@ -1,584 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.04.26.01.06.46; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.04.25.15.38.48; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@use XXX_BIG_ENDIAN macros rather than runtime tests.
@
text
@/* Find a variable's value in memory, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "value.h"
CORE_ADDR read_register ();
/* Return the address in which frame FRAME's value of register REGNUM
has been saved in memory. Or return zero if it has not been saved.
If REGNUM specifies the SP, the value we return is actually
the SP value, not an address where it was saved. */
CORE_ADDR
find_saved_register (frame, regnum)
FRAME frame;
int regnum;
{
struct frame_info *fi;
struct frame_saved_regs saved_regs;
register FRAME frame1 = 0;
register CORE_ADDR addr = 0;
#ifdef HAVE_REGISTER_WINDOWS
/* We assume that a register in a register window will only be saved
in one place (since the name changes and dissapears as you go
towards inner frames), so we only call get_frame_saved_regs on
the current frame. This is directly in contradiction to the
usage below, which assumes that registers used in a frame must be
saved in a lower (more interior) frame. This change is a result
of working on a register window machine; get_frame_saved_regs
always returns the registers saved within a frame, within the
context (register namespace) of that frame. */
if (REGISTER_IN_WINDOW_P(regnum))
{
fi = get_frame_info (frame);
get_frame_saved_regs (fi, &saved_regs);
return (saved_regs.regs[regnum] ?
saved_regs.regs[regnum] : 0);
}
#endif /* HAVE_REGISTER_WINDOWS */
/* Note that this next routine assumes that registers used in
frame x will be saved only in the frame that x calls and
frames interior to it. This is not true on the sparc, but the
above macro takes care of it, so we should be all right. */
while (1)
{
QUIT;
frame1 = get_prev_frame (frame1);
if (frame1 == 0 || frame1 == frame)
break;
fi = get_frame_info (frame1);
get_frame_saved_regs (fi, &saved_regs);
if (saved_regs.regs[regnum])
addr = saved_regs.regs[regnum];
}
return addr;
}
/* Copy the bytes of register REGNUM, relative to the current stack frame,
into our memory at MYADDR.
The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). */
void
read_relative_register_raw_bytes (regnum, myaddr)
int regnum;
char *myaddr;
{
register CORE_ADDR addr;
if (regnum == FP_REGNUM)
{
bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
return;
}
addr = find_saved_register (selected_frame, regnum);
if (addr)
{
if (regnum == SP_REGNUM)
{
CORE_ADDR buffer = addr;
bcopy (&buffer, myaddr, sizeof (CORE_ADDR));
}
else
read_memory (addr, myaddr, REGISTER_RAW_SIZE (regnum));
return;
}
read_register_bytes (REGISTER_BYTE (regnum),
myaddr, REGISTER_RAW_SIZE (regnum));
}
/* Return a `value' with the contents of register REGNUM
in its virtual format, with the type specified by
REGISTER_VIRTUAL_TYPE. */
value
value_of_register (regnum)
int regnum;
{
register CORE_ADDR addr;
register value val;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
if (! (have_inferior_p () || have_core_file_p ()))
error ("Can't get value of register without inferior or core file");
addr = find_saved_register (selected_frame, regnum);
if (addr)
{
if (regnum == SP_REGNUM)
return value_from_long (builtin_type_int, (LONGEST) addr);
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
}
else
read_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
REGISTER_RAW_SIZE (regnum));
REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
bcopy (virtual_buffer, VALUE_CONTENTS (val), REGISTER_VIRTUAL_SIZE (regnum));
VALUE_LVAL (val) = addr ? lval_memory : lval_register;
VALUE_ADDRESS (val) = addr ? addr : REGISTER_BYTE (regnum);
VALUE_REGNO (val) = regnum;
return val;
}
/* Low level examining and depositing of registers.
Note that you must call `fetch_registers' once
before examining or depositing any registers. */
char registers[REGISTER_BYTES];
/* Copy LEN bytes of consecutive data from registers
starting with the REGBYTE'th byte of register data
into memory at MYADDR. */
void
read_register_bytes (regbyte, myaddr, len)
int regbyte;
char *myaddr;
int len;
{
bcopy (&registers[regbyte], myaddr, len);
}
/* Copy LEN bytes of consecutive data from memory at MYADDR
into registers starting with the REGBYTE'th byte of register data. */
void
write_register_bytes (regbyte, myaddr, len)
int regbyte;
char *myaddr;
int len;
{
bcopy (myaddr, &registers[regbyte], len);
if (have_inferior_p ())
store_inferior_registers (-1);
}
/* Return the contents of register REGNO,
regarding it as an integer. */
CORE_ADDR
read_register (regno)
int regno;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
return *(int *) &registers[REGISTER_BYTE (regno)];
}
/* Store VALUE in the register number REGNO, regarded as an integer. */
void
write_register (regno, val)
int regno, val;
{
/* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
#if defined(sun4)
/* This is a no-op on a Sun 4. */
if (regno == 0)
return;
#endif
*(int *) &registers[REGISTER_BYTE (regno)] = val;
if (have_inferior_p ())
store_inferior_registers (regno);
}
/* Record that register REGNO contains VAL.
This is used when the value is obtained from the inferior or core dump,
so there is no need to store the value there. */
void
supply_register (regno, val)
int regno;
char *val;
{
bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
}
/* Given a struct symbol for a variable,
and a stack frame address, read the value of the variable
and return a (pointer to a) struct value containing the value. */
value
read_var_value (var, frame)
register struct symbol *var;
FRAME frame;
{
register value v;
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
register CORE_ADDR addr = 0;
int val = SYMBOL_VALUE (var);
register int len;
v = allocate_value (type);
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
len = TYPE_LENGTH (type);
if (frame == 0) frame = selected_frame;
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
case LOC_LABEL:
bcopy (&val, VALUE_CONTENTS (v), len);
VALUE_LVAL (v) = not_lval;
return v;
case LOC_CONST_BYTES:
bcopy (val, VALUE_CONTENTS (v), len);
VALUE_LVAL (v) = not_lval;
return v;
case LOC_STATIC:
addr = val;
break;
case LOC_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
break;
case LOC_TYPEDEF:
error ("Cannot look up value of a typedef");
case LOC_BLOCK:
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
return v;
case LOC_REGISTER:
case LOC_REGPARM:
v = value_from_register (type, val, frame);
return v;
}
read_memory (addr, VALUE_CONTENTS (v), len);
VALUE_ADDRESS (v) = addr;
return v;
}
/* Return a value of type TYPE, stored in register REGNUM, in frame
FRAME. */
value
value_from_register (type, regnum, frame)
struct type *type;
int regnum;
FRAME frame;
{
char raw_buffer [MAX_REGISTER_RAW_SIZE];
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
CORE_ADDR addr;
value v = allocate_value (type);
int len = TYPE_LENGTH (type);
char *value_bytes = 0;
int value_bytes_copied = 0;
int num_storage_locs;
VALUE_REGNO (v) = regnum;
num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 :
1);
if (num_storage_locs > 1)
{
/* Value spread across multiple storage locations. */
int local_regnum;
int mem_stor = 0, reg_stor = 0;
int mem_tracking = 1;
CORE_ADDR last_addr = 0;
value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
/* Copy all of the data out, whereever it may be. */
for (local_regnum = regnum;
value_bytes_copied < len;
(value_bytes_copied += REGISTER_RAW_SIZE (local_regnum),
++local_regnum))
{
int register_index = local_regnum - regnum;
addr = find_saved_register (frame, local_regnum);
if (addr == 0)
{
read_register_bytes (REGISTER_BYTE (local_regnum),
value_bytes + value_bytes_copied,
REGISTER_RAW_SIZE (local_regnum));
reg_stor++;
}
else
{
read_memory (addr, value_bytes + value_bytes_copied,
REGISTER_RAW_SIZE (local_regnum));
mem_stor++;
mem_tracking =
(mem_tracking
&& (regnum == local_regnum
|| addr == last_addr));
}
last_addr = addr;
}
if ((reg_stor && mem_stor)
|| (mem_stor && !mem_tracking))
/* Mixed storage; all of the hassle we just went through was
for some good purpose. */
{
VALUE_LVAL (v) = lval_reg_frame_relative;
VALUE_FRAME (v) = FRAME_FP (frame);
VALUE_FRAME_REGNUM (v) = regnum;
}
else if (mem_stor)
{
VALUE_LVAL (v) = lval_memory;
VALUE_ADDRESS (v) = find_saved_register (frame, regnum);
}
else if (reg_stor)
{
VALUE_LVAL (v) = lval_register;
VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
}
else
fatal ("value_from_register: Value not stored anywhere!");
/* Any structure stored in more than one register will always be
an inegral number of registers. Otherwise, you'd need to do
some fiddling with the last register copied here for little
endian machines. */
/* Copy into the contents section of the value. */
bcopy (value_bytes, VALUE_CONTENTS (v), len);
return v;
}
/* Data is completely contained within a single register. Locate the
register's contents in a real register or in core;
read the data in raw format. */
addr = find_saved_register (frame, regnum);
if (addr == 0)
{
/* Value is really in a register. */
VALUE_LVAL (v) = lval_register;
VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
read_register_bytes (REGISTER_BYTE (regnum),
raw_buffer, REGISTER_RAW_SIZE (regnum));
}
else
{
/* Value was in a register that has been saved in memory. */
read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
VALUE_LVAL (v) = lval_memory;
VALUE_ADDRESS (v) = addr;
}
/* Convert the raw contents to virtual contents.
(Just copy them if the formats are the same.) */
REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
if (REGISTER_CONVERTIBLE (regnum))
{
/* When the raw and virtual formats differ, the virtual format
corresponds to a specific data type. If we want that type,
copy the data into the value.
Otherwise, do a type-conversion. */
if (type != REGISTER_VIRTUAL_TYPE (regnum))
{
/* eg a variable of type `float' in a 68881 register
with raw type `extended' and virtual type `double'.
Fetch it as a `double' and then convert to `float'. */
v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
v = value_cast (type, v);
}
else
bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
}
else
{
/* Raw and virtual formats are the same for this register. */
#ifdef BYTES_BIG_ENDIAN
if (len < REGISTER_RAW_SIZE (regnum))
{
/* Big-endian, and we want less than full size. */
VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
}
#endif
bcopy (virtual_buffer + VALUE_OFFSET (v),
VALUE_CONTENTS (v), len);
}
return v;
}
/* Given a struct symbol for a variable,
and a stack frame address,
return a (pointer to a) struct value containing the variable's address. */
value
locate_var_value (var, frame)
register struct symbol *var;
FRAME frame;
{
register CORE_ADDR addr = 0;
int val = SYMBOL_VALUE (var);
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
if (frame == 0) frame = selected_frame;
switch (SYMBOL_CLASS (var))
{
case LOC_CONST:
case LOC_CONST_BYTES:
error ("Address requested for identifier \"%s\" which is a constant.",
SYMBOL_NAME (var));
case LOC_REGISTER:
case LOC_REGPARM:
addr = find_saved_register (frame, val);
if (addr != 0)
{
int len = TYPE_LENGTH (type);
#ifdef BYTES_BIG_ENDIAN
if (len < REGISTER_RAW_SIZE (val))
/* Big-endian, and we want less than full size. */
addr += REGISTER_RAW_SIZE (val) - len;
#endif
break;
}
error ("Address requested for identifier \"%s\" which is in a register.",
SYMBOL_NAME (var));
case LOC_STATIC:
case LOC_LABEL:
addr = val;
break;
case LOC_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
break;
case LOC_TYPEDEF:
error ("Address requested for identifier \"%s\" which is a typedef.",
SYMBOL_NAME (var));
case LOC_BLOCK:
addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
break;
}
return value_cast (lookup_pointer_type (type),
value_from_long (builtin_type_long, (LONGEST) addr));
}
@
1.1
log
@Initial revision
@
text
@d448 2
a449 5
union { int i; char c; } test;
/* If we want less than the full size, we need to
test for a big-endian or little-endian machine. */
test.i = 1;
if (test.c != 1 && len < REGISTER_RAW_SIZE (regnum))
d454 2
a455 1
a490 1
union { int i; char c; } test;
d492 2
a493 4
/* If var is less than the full size of register, we need to
test for a big-endian or little-endian machine. */
test.i = 1;
if (test.c != 1 && len < REGISTER_RAW_SIZE (val))
d496 1
@

File diff suppressed because it is too large Load Diff

View File

@ -1,105 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.02.09.23.23.12; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.22.43.14; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Create gdbcore.h with external variables that relate to core files.
@
text
@/* Machine independent variables that describe the core file under GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/* File names of core file and executable file. */
extern char *corefile;
extern char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
extern int corechan;
extern int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
extern int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
extern CORE_ADDR data_start;
extern CORE_ADDR data_end;
extern CORE_ADDR stack_start;
extern CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
extern CORE_ADDR text_start;
extern CORE_ADDR text_end;
extern CORE_ADDR exec_data_start;
extern CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
extern int text_offset;
/* Address in executable file of start of data area data. */
extern int exec_data_offset;
/* Address in core file of start of data area data. */
extern int data_offset;
/* Address in core file of start of stack area data. */
extern int stack_offset;
@
1.1
log
@Initial revision
@
text
@d1 68
@

View File

@ -1,636 +0,0 @@
head 1.3;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.3
date 89.03.27.20.12.35; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.02.09.23.23.40; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.22.28.04; author gnu; state Exp;
branches ;
next ;
desc
@@
1.3
log
@General portability changes. Make various local terminal control
parameter processing #ifdef the particular IOCTL used to get them.
This handles various Sys V/Berkeley merges. Also avoid vfork
and <sys/fcntl.h>.
@
text
@/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#ifdef HAVE_TERMIO
#include <termio.h>
#undef TIOCGETP
#define TIOCGETP TCGETA
#undef TIOCSETN
#define TIOCSETN TCSETA
#undef TIOCSETP
#define TIOCSETP TCSETAF
#define TERMINAL struct termio
#else
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sgtty.h>
#define TERMINAL struct sgttyb
#endif
#ifdef SET_STACK_LIMIT_HUGE
#include <sys/time.h>
#include <sys/resource.h>
extern int original_stack_limit;
#endif /* SET_STACK_LIMIT_HUGE */
extern int errno;
/* Nonzero if we are debugging an attached outside process
rather than an inferior. */
int attach_flag;
/* Record terminal status separately for debugger and inferior. */
static TERMINAL sg_inferior;
static TERMINAL sg_ours;
static int tflags_inferior;
static int tflags_ours;
#ifdef TIOCGETC
static struct tchars tc_inferior;
static struct tchars tc_ours;
#endif
#ifdef TIOCGLTC
static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
#endif /* TIOCGLTC */
#ifdef TIOCLGET
static int lmode_inferior;
static int lmode_ours;
#endif
#ifdef TIOCGPGRP
static int pgrp_inferior;
static int pgrp_ours;
#else
static int (*sigint_ours) ();
static int (*sigquit_ours) ();
#endif /* TIOCGPGRP */
/* Copy of inferior_io_terminal when inferior was last started. */
static char *inferior_thisrun_terminal;
static void terminal_ours_1 ();
/* Nonzero if our terminal settings are in effect.
Zero if the inferior's settings are in effect. */
static int terminal_is_ours;
/* Initialize the terminal settings we record for the inferior,
before we actually run the inferior. */
void
terminal_init_inferior ()
{
if (remote_debugging)
return;
sg_inferior = sg_ours;
tflags_inferior = tflags_ours;
#ifdef TIOCGETC
tc_inferior = tc_ours;
#endif
#ifdef TIOCGLTC
ltc_inferior = ltc_ours;
#endif
#ifdef TIOCLGET
lmode_inferior = lmode_ours;
#endif
#ifdef TIOCGPGRP
pgrp_inferior = inferior_pid;
#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}
/* Put the inferior's terminal settings into effect.
This is preparation for starting or resuming the inferior. */
void
terminal_inferior ()
{
if (remote_debugging)
return;
if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
ioctl (0, TIOCSETN, &sg_inferior);
#ifdef TIOCGETC
ioctl (0, TIOCSETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_inferior);
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCSPGRP, &pgrp_inferior);
#else
sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
#endif /* TIOCGPGRP */
}
terminal_is_ours = 0;
}
/* Put some of our terminal settings into effect,
enough to get proper results from our output,
but do not change into or out of RAW mode
so that no input is discarded.
After doing this, either terminal_ours or terminal_inferior
should be called to get back to a normal state of affairs. */
void
terminal_ours_for_output ()
{
if (remote_debugging)
return;
terminal_ours_1 (1);
}
/* Put our terminal settings into effect.
First record the inferior's terminal settings
so they can be restored properly later. */
void
terminal_ours ()
{
if (remote_debugging)
return;
terminal_ours_1 (0);
}
static void
terminal_ours_1 (output_only)
int output_only;
{
#ifdef TIOCGPGRP
/* Ignore this signal since it will happen when we try to set the pgrp. */
int (*osigttou) ();
#endif /* TIOCGPGRP */
if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
{
terminal_is_ours = 1;
#ifdef TIOCGPGRP
osigttou = signal (SIGTTOU, SIG_IGN);
ioctl (0, TIOCGPGRP, &pgrp_inferior);
ioctl (0, TIOCSPGRP, &pgrp_ours);
signal (SIGTTOU, osigttou);
#else
signal (SIGINT, sigint_ours);
signal (SIGQUIT, sigquit_ours);
#endif /* TIOCGPGRP */
tflags_inferior = fcntl (0, F_GETFL, 0);
ioctl (0, TIOCGETP, &sg_inferior);
#ifdef TIOCGETC
ioctl (0, TIOCGETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_inferior);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_inferior);
#endif
}
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
if (output_only && !(sg_inferior.c_lflag & ICANON))
sg_ours.c_lflag &= ~ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
if (output_only)
sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
#endif /* not HAVE_TERMIO */
fcntl (0, F_SETFL, tflags_ours);
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
#ifdef TIOCGETC
ioctl (0, TIOCSETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLSET, &lmode_ours);
#endif
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
#else /* not HAVE_TERMIO */
sg_ours.sg_flags &= ~RAW & ~CBREAK;
#endif /* not HAVE_TERMIO */
}
static void
term_status_command ()
{
register int i;
if (remote_debugging)
{
printf ("No terminal status when remote debugging.\n");
return;
}
printf ("Inferior's terminal status (currently saved by GDB):\n");
#ifdef HAVE_TERMIO
printf ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
printf ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
printf ("c_cc: ");
for (i = 0; (i < NCC); i += 1)
printf ("0x%x ", sg_inferior.c_cc[i]);
printf ("\n");
#else /* not HAVE_TERMIO */
printf ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
#endif /* not HAVE_TERMIO */
#ifdef TIOCGETC
printf ("tchars: ");
for (i = 0; i < sizeof (struct tchars); i++)
printf ("0x%x ", ((char *)&tc_inferior)[i]);
printf ("\n");
#endif
#ifdef TIOCGLTC
printf ("ltchars: ");
for (i = 0; i < sizeof (struct ltchars); i++)
printf ("0x%x ", ((char *)&ltc_inferior)[i]);
printf ("\n");
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
printf ("lmode: %x\n", lmode_inferior);
#endif
}
static void
new_tty (ttyname)
char *ttyname;
{
register int tty;
register int fd;
#ifdef TIOCNOTTY
/* Disconnect the child process from our controlling terminal. */
tty = open("/dev/tty", O_RDWR);
if (tty > 0)
{
ioctl(tty, TIOCNOTTY, 0);
close(tty);
}
#endif
/* Now open the specified new terminal. */
tty = open(ttyname, O_RDWR);
if (tty == -1)
_exit(1);
dup2(tty, 0);
dup2(tty, 1);
dup2(tty, 2);
close(tty);
}
/* Start an inferior process and returns its pid.
ALLARGS is a string containing shell command to run the program.
ENV is the environment vector to pass. */
#ifndef SHELL_FILE
#define SHELL_FILE "/bin/sh"
#endif
int
create_inferior (allargs, env)
char *allargs;
char **env;
{
int pid;
char *shell_command;
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
/* If desired, concat something onto the front of ALLARGS.
SHELL_COMMAND is the result. */
#ifdef SHELL_COMMAND_CONCAT
shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
strcpy (shell_command, SHELL_COMMAND_CONCAT);
strcat (shell_command, allargs);
#else
shell_command = allargs;
#endif
/* exec is said to fail if the executable is open. */
close_exec_file ();
pid = fork ();
if (pid < 0)
perror_with_name ("fork");
if (pid == 0)
{
#ifdef TIOCGPGRP
/* Run inferior in a separate process group. */
setpgrp (getpid (), getpid ());
#endif /* TIOCGPGRP */
#ifdef SET_STACK_LIMIT_HUGE
/* Reset the stack limit back to what it was. */
{
struct rlimit rlim;
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = original_stack_limit;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif /* SET_STACK_LIMIT_HUGE */
inferior_thisrun_terminal = inferior_io_terminal;
if (inferior_io_terminal != 0)
new_tty (inferior_io_terminal);
/* Not needed on Sun, at least, and loses there
because it clobbers the superior. */
/*??? signal (SIGQUIT, SIG_DFL);
signal (SIGINT, SIG_DFL); */
call_ptrace (0);
execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);
fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
fflush (stderr);
_exit (0177);
}
return pid;
}
/* Kill the inferior process. Make us have no inferior. */
static void
kill_command ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
error ("The program is not being run.");
if (!query ("Kill the inferior process? "))
error ("Not confirmed.");
kill_inferior ();
}
void
inferior_died ()
{
inferior_pid = 0;
attach_flag = 0;
mark_breakpoints_out ();
select_frame ( (FRAME) 0, -1);
reopen_exec_file ();
if (have_core_file_p ())
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
}
static void
try_writing_regs_command ()
{
register int i;
register int value;
extern int errno;
if (inferior_pid == 0)
error ("There is no inferior process now.");
for (i = 0; ; i += 2)
{
QUIT;
errno = 0;
value = call_ptrace (3, inferior_pid, i, 0);
call_ptrace (6, inferior_pid, i, value);
if (errno == 0)
{
printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
i, value, value);
}
else if ((i & 0377) == 0)
printf (" Failed at 0x%x.\n", i);
}
}
void
_initialize_inflow ()
{
add_com ("term-status", class_obscure, term_status_command,
"Print info on inferior's saved terminal status.");
add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
"Try writing all locations in inferior's system block.\n\
Report which ones can be written.");
add_com ("kill", class_run, kill_command,
"Kill execution of program being debugged.");
inferior_pid = 0;
ioctl (0, TIOCGETP, &sg_ours);
fcntl (0, F_GETFL, tflags_ours);
#ifdef TIOCGETC
ioctl (0, TIOCGETC, &tc_ours);
#endif
#ifdef TIOCGLTC
ioctl (0, TIOCGLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
ioctl (0, TIOCLGET, &lmode_ours);
#endif
#ifdef TIOCGPGRP
ioctl (0, TIOCGPGRP, &pgrp_ours);
#endif /* TIOCGPGRP */
terminal_is_ours = 1;
}
@
1.2
log
@When the inferior process dies, deselect the current frame so that
the "where" ("backtrace") command will not think there's a stack.
@
text
@d27 1
a27 1
#include <sys/fcntl.h>
a34 6
/* May be unnecessary since many parts of inflow.c
have migrated to *-infdep.c */
#ifdef USG
#include <sys/user.h>
#endif
d73 1
a73 1
#ifdef TIOCGLTC
d76 3
d81 3
d86 1
a86 1
#endif /* TIOCGLTC */
d117 4
a121 1
tc_inferior = tc_ours;
d123 3
d127 1
a127 1
#endif /* TIOCGLTC */
d150 3
a153 1
ioctl (0, TIOCSETC, &tc_inferior);
d155 2
d158 1
a158 1
#endif /* TIOCGLTC */
d228 3
a231 1
ioctl (0, TIOCGETC, &tc_inferior);
d233 2
d236 1
a236 1
#endif /* TIOCGLTC */
d253 3
a256 1
ioctl (0, TIOCSETC, &tc_ours);
d258 2
d261 1
a261 1
#endif /* TIOCGLTC */
d297 6
a302 3
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, lmode_inferior,
sg_inferior.sg_flags, pgrp_inferior);
d307 3
d314 2
d317 3
a319 1
#endif /* not HAVE_TERMIO */
d383 1
a383 1
pid = vfork ();
d385 1
a385 1
perror_with_name ("vfork");
d497 3
a500 1
ioctl (0, TIOCGETC, &tc_ours);
d502 2
d505 1
a505 1
#endif /* TIOCGLTC */
@
1.1
log
@Initial revision
@
text
@d418 1
@

File diff suppressed because it is too large Load Diff

View File

@ -1,591 +0,0 @@
head 1.4;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.4
date 89.04.26.00.51.42; author gnu; state Exp;
branches ;
next 1.3;
1.3
date 89.03.27.20.16.05; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.03.26.20.13.28; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.13.19.16.52; author gnu; state Exp;
branches ;
next ;
desc
@@
1.4
log
@(1) Defined the big-endianness of the target machine.
(2) Define float to be IEEE compatible.
(3) Define invalid floats to be NaNs.
@
text
@/* Parameters for execution on A/UX, for GDB, the GNU debugger.
Copyright (C) 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef aux
#define aux
#endif
/* It's a USG system */
#define USG
/* Assembler instructions in USG "SGS" (sw generation system) format */
#define USG_SGS_ASM
/* Debugger information will be in COFF format. */
#define COFF_FORMAT
#define COFF_NO_LONG_FILE_NAMES
/* Terminal interface via termio */
#define HAVE_TERMIO
/* Unisoft fucked up the include files */
#define UNISOFT_ASSHOLES
/* Big or Little-Endian target machine
BITS: defined if bit #0 is the high-order bit of a byte.
BYTES:defined if byte#0 is the high-order byte of an int.
WORDS:defined if word#0 is the high-order word of a double. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Floating point is IEEE compatible */
#define IEEE_FLOAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
}
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space. */
#define STACK_END_ADDR 0x20000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
/* A/UX uses "trap &1" */
#define BREAKPOINT {0x4e, 0x41}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
/* Return 1 if P points to an invalid floating point value. */
/* FIXME, it's not clear what "invalid" means here. I take it to mean
"something that coredumps gdb if gdb tries to manipulate it" */
#define INVALID_FLOAT(p, len) is_nan(p, len)
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 29
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"ps", "pc", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr" }
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 14 /* Contains address of executing stack frame */
#define SP_REGNUM 15 /* Contains address of top of stack */
#define PS_REGNUM 16 /* Contains processor status */
#define PC_REGNUM 17 /* Contains program counter */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
/* This is a piece of magic that is given a register number REGNO
and as BLOCKEND the address in the system of the end of the user structure
and stores in ADDR the address in the kernel or core dump
of that register. */
#define REGISTER_U_ADDR(addr, blockend, regno) { \
struct user u; \
if (regno <= SP_REGNUM) \
addr = blockend + regno * 4; \
else if (regno == PS_REGNUM) \
addr = blockend + RPS * 4; /* From reg.h */ \
else if (regno == PC_REGNUM) \
addr = blockend + PC * 4; /* From reg.h */ \
else if (regno < FPC_REGNUM) \
addr = (char *) u.u_fpdreg [regno-FP0_REGNUM] - (char *)&u; \
else \
addr = (char *)&u.u_fpsysreg[regno-FPC_REGNUM] - (char *)&u; \
}
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4+8*12+8+20)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) \
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
: (N) * 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 12 bytes. */
/* Note that the unsigned cast here forces the result of the
subtractiion to very high positive values if N < FP0_REGNUM */
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
/* Number of bytes of storage in the program's representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 8-byte doubles. */
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_from_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
convert_to_68881 ((FROM), (TO)); \
else \
bcopy ((FROM), (TO), 4); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_register (9, (ADDR)); }
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the 68k, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the C compiler delays popping them. */
#define FRAME_NUM_ARGS(val,fi) (val = -1)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
register int insn = 0177777 & read_memory_integer (pc, 2); \
val = 0; \
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
val = read_memory_integer (pc + 2, 2); \
else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
|| (insn & 0170777) == 0050117) /* addqw */ \
{ val = (insn >> 9) & 7; if (val == 0) val = 8; } \
else if (insn == 0157774) /* addal #WW, sp */ \
val = read_memory_integer (pc + 2, 4); \
val >>= 2; }
#endif
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 8
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register int regmask; \
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
int nextinsn; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
&& (frame_info)->pc <= (frame_info)->frame) \
{ next_addr = (frame_info)->frame; \
pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
else \
{ pc = get_pc_function_start ((frame_info)->pc); \
/* Verify we have a link a6 instruction next; \
if not we lose. If we win, find the address above the saved \
regs using the amount of storage from the link instruction. */\
if (044016 == read_memory_integer (pc, 2)) \
next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
else if (047126 == read_memory_integer (pc, 2)) \
next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
else goto lose; \
/* If have an addal #-n, sp next, adjust next_addr. */ \
if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
} \
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
regmask = read_memory_integer (pc + 2, 2); \
/* But before that can come an fmovem. Check for it. */ \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf227 == nextinsn \
&& (regmask & 0xff00) == 0xe000) \
{ pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 12); \
regmask = read_memory_integer (pc + 2, 2); } \
if (0044327 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 0, the first written */ \
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
else if (0044347 == read_memory_integer (pc, 2)) \
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
/* fmovemx to index of sp may follow. */ \
regmask = read_memory_integer (pc + 2, 2); \
nextinsn = 0xffff & read_memory_integer (pc, 2); \
if (0xf236 == nextinsn \
&& (regmask & 0xff00) == 0xf000) \
{ pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
regmask = read_memory_integer (pc + 2, 2); } \
/* clrw -(sp); movw ccr,-(sp) may follow. */ \
if (0x426742e7 == read_memory_integer (pc, 4)) \
(frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
lose: ; \
(frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
(frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
}
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM),\
read_pc ())); }
/* This sequence of words is the instructions
fmovem 0xff,-(sp)
moveml 0xfffc,-(sp)
clrw -(sp)
movew ccr,-(sp)
/..* The arguments are pushed at this point by GDB;
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @@#32323232
addl #69696969,sp
trap #15
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the
registers is done by PUSH_DUMMY_FRAME. If this were real code,
the arguments for the function called by the jsr would be pushed
between the moveml and the jsr, and we could allow it to execute through.
But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY_LENGTH 28
#define CALL_DUMMY_START_OFFSET 12
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 20) = nargs * 4; \
*(int *)((char *) dummyname + 14) = fun; }
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
0, 0, 0, 0, 0, 0, 0, 0, \
SIGILL }
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movel #end, sp"); \
asm ("movel #0,a6"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("movel a6,sp@@-");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("movl sp@@,a6");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("clrw -(sp)"); \
asm ("pea sp@@(10)"); \
asm ("movem #0xfffe,sp@@-"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("subil #8,sp@@(28)"); \
asm ("movem sp@@,#0xffff"); \
asm ("rte"); }
@
1.3
log
@Fix DECR_PC_AFTER_BREAK; A/UX reports breaks at the breakpoint addr,
not there+2.
@
text
@d41 11
d100 2
d103 1
a103 1
#define INVALID_FLOAT(p, len) 1 /* FIXME! Just a first guess; not checked */
@
1.2
log
@Mostly works!
@
text
@d82 1
a82 1
#define DECR_PC_AFTER_BREAK 2
@
1.1
log
@Initial revision
@
text
@d1 504
@

View File

@ -1,747 +0,0 @@
head 1.3;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.3
date 89.04.26.00.52.29; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.03.16.21.10.29; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.14.15.28.32; author gnu; state Exp;
branches ;
next ;
desc
@@
1.3
log
@(1) Define big-endianness of SPARC.
(2) Define IEEE compatible float.
@
text
@/* Parameters for execution on a Sun 4, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@@mcc.com)
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef sun4
#define sun4
#endif
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
#define NAMES_HAVE_UNDERSCORE
/* Debugger information will be in DBX format. */
#define READ_DBX_FORMAT
/* Big or Little-Endian target machine
BITS: defined if bit #0 is the high-order bit of a byte.
BYTES:defined if byte#0 is the high-order byte of an int.
WORDS:defined if word#0 is the high-order word of a double. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Floating point is IEEE compatible. */
#define IEEE_FLOAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ pc = skip_prologue (pc); }
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
/* On the Sun 4 under SunOS, the compile will leave a fake insn which
encodes the structure size being returned. If we detect such
a fake insn, step past it. */
#define PC_ADJUST(pc) ((read_memory_integer (pc + 8, 4) & 0xfffffe00) == 0 ? \
pc+12 : pc+8)
#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
/* Address of end of stack space. */
#define STACK_END_ADDR 0xf8000000
/* Stack grows downward. */
#define INNER_THAN <
/* Stack has strict alignment. */
#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. */
/* For SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0".
Note: this does not work for functions returning structures under SunOS. */
#define ABOUT_TO_RETURN(pc) \
((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
/* Largest integer type */
#define LONGEST long
/* Name of the builtin type for the LONGEST type above. */
#define BUILTIN_TYPE_LONGEST builtin_type_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 72
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
"o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
"i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \
\
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
\
"y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FP_REGNUM 30 /* Contains address of executing stack frame */
#define RP_REGNUM 15 /* Contains return address value, *before* \
any windows get switched. */
#define SP_REGNUM 14 /* Contains address of top of stack, \
which is also the bottom of the frame. */
#define Y_REGNUM 64 /* Temp register for multiplication, etc. */
#define PS_REGNUM 65 /* Contains processor status */
#define PC_REGNUM 68 /* Contains program counter */
#define NPC_REGNUM 69 /* Contains next PC */
#define FP0_REGNUM 32 /* Floating point register 0 */
#define FPS_REGNUM 70 /* Floating point status register */
#define CPS_REGNUM 71 /* Coprocessor status register */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (32*4+32*4+8*4)
/* Index within `registers' of the first byte of the space for
register N. */
/* ?? */
#define REGISTER_BYTE(N) ((N)*4)
/* The SPARC processor has register windows. */
#define HAVE_REGISTER_WINDOWS
/* Is this register part of the register window system? A yes answer
implies that 1) The name of this register will not be the same in
other frames, and 2) This register is automatically "saved" (out
registers shifting into ins counts) upon subroutine calls and thus
there is no need to search more than one stack frame for it. */
#define REGISTER_IN_WINDOW_P(regnum) \
((regnum) >= 8 && (regnum) < 32)
/* Number of bytes of storage in the actual machine representation
for register N. */
/* On the SPARC, all regs are 4 bytes. */
#define REGISTER_RAW_SIZE(N) (4)
/* Number of bytes of storage in the program's representation
for register N. */
/* On the SPARC, all regs are 4 bytes. */
#define REGISTER_VIRTUAL_SIZE(N) (4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 8
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) (0)
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ bcopy ((FROM), (TO), 4); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ bcopy ((FROM), (TO), 4); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : \
builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_memory ((SP)+(16*4), &(ADDR), 4); }
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
/* On sparc, values are returned in register %o0. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (REGISTER_BYTE (8), VALBUF, TYPE_LENGTH (TYPE))
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4))
/* Enable use of alternate code to read and write registers. */
#define NEW_SUN_PTRACE
/* Enable use of alternate code for Sun's format of core dump file. */
#define NEW_SUN_CORE
/* Do implement the attach and detach commands. */
#define ATTACH_DETACH
/* It is safe to look for symsegs on a Sun, because Sun's ld
does not screw up with random garbage at end of file. */
#define READ_GDB_SYMSEGS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
#include <machine/reg.h>
#define GET_RWINDOW_REG(FRAME, REG) \
(read_memory_integer (&((struct rwindow *)FRAME)->REG, 4))
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
and produces the nominal address of the caller frame.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the Sun 4, the frame-chain's nominal address
is held in the frame pointer register.
On the Sun4, the frame (in %fp) is %sp for the previous frame.
From the previous frame's %sp, we can find the previous frame's
%fp: it is in the save area just above the previous frame's %sp.
If we are setting up an arbitrary frame, we'll need to know where
it ends. Hence the following. This part of the frame cache
structure should be checked before it is assumed that this frame's
bottom is in the stack pointer.
If there isn't a frame below this one, the bottom of this frame is
in the stack pointer.
If there is a frame below this one, and the frame pointers are
identical, it's a leaf frame and the bottoms are the same also.
Otherwise the bottom of this frame is the top of the next frame. */
#define EXTRA_FRAME_INFO FRAME_ADDR bottom;
#define INIT_EXTRA_FRAME_INFO(fci) \
(fci)->bottom = \
((fci)->next ? \
((fci)->frame == (fci)->next_frame ? \
(fci)->next->bottom : (fci)->next->frame) : \
read_register (SP_REGNUM));
#define FRAME_CHAIN(thisframe) \
GET_RWINDOW_REG ((thisframe)->frame, rw_in[6])
/* Avoid checking FRAME_SAVED_PC since that screws us due to
improperly set up saved PC on a signal trampoline call */
#if 0
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#else
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0)
#endif
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* Where is the PC for a specific frame */
#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
/* If the argument is on the stack, it will be here. */
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame)
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the C compiler delays popping them. */
#define FRAME_NUM_ARGS(val,fi) (val = -1)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 68
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame.
Note that on register window machines, we are currently making the
assumption that window registers are being saved somewhere in the
frame in which they are being used. If they are stored in an
inferior frame, find_saved_register will break.
On the Sun 4, the only time all registers are saved is when
a dummy frame is involved. Otherwise, the only saved registers
are the LOCAL and IN registers which are saved as a result
of the "save/restore" opcodes. This condition is determined
by address rather than by value. */
#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \
{ register int regnum; \
register CORE_ADDR pc; \
FRAME_ADDR frame = read_register (FP_REGNUM); \
FRAME fid = FRAME_INFO_ID (fi); \
if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \
bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
if ((fi)->pc >= frame - CALL_DUMMY_LENGTH - 0x140 \
&& (fi)->pc <= frame) \
{ \
for (regnum = 1; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum] = \
frame + regnum * 4 - 0xa0; \
for (regnum = 24; regnum < 32; regnum++) \
(frame_saved_regs).regs[regnum] = \
frame + (regnum - 24) * 4 - 0xc0; \
for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++) \
(frame_saved_regs).regs[regnum] = \
frame + (regnum - FP0_REGNUM) * 4 - 0x80; \
for (regnum = 64; regnum < NUM_REGS; regnum++) \
(frame_saved_regs).regs[regnum] = \
frame + (regnum - 64) * 4 - 0xe0; \
frame = (fi)->bottom ? \
(fi)->bottom : read_register (SP_REGNUM); \
} \
else \
{ \
frame = (fi)->bottom ? \
(fi)->bottom : read_register (SP_REGNUM); \
for (regnum = 16; regnum < 32; regnum++) \
(frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \
} \
if ((fi)->next) \
{ \
/* Pull off either the next frame pointer or \
the stack pointer */ \
FRAME_ADDR next_next_frame = \
((fi)->next->bottom ? \
(fi)->next->bottom : \
read_register (SP_REGNUM)); \
for (regnum = 8; regnum < 16; regnum++) \
(frame_saved_regs).regs[regnum] = next_next_frame + regnum * 4; \
} \
/* Otherwise, whatever we would get from ptrace(GETREGS) */ \
/* is accurate */ \
for (regnum = 30; regnum < 32; regnum++) \
(frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \
(frame_saved_regs).regs[SP_REGNUM] = frame; \
(frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \
}
/* Things needed for making the inferior call functions. */
/*
* First of all, let me give my opinion of what the DUMMY_FRAME
* actually looks like.
*
* | |
* | |
* + - - - - - - - - - - - - - - - - +<-- fp (level 0)
* | |
* | |
* | |
* | |
* | Frame of innermost program |
* | function |
* | |
* | |
* | |
* | |
* | |
* |---------------------------------|<-- sp (level 0), fp (c)
* | |
* DUMMY | fp0-31 |
* | |
* | ------ |<-- fp - 0x80
* FRAME | g0-7 |<-- fp - 0xa0
* | i0-7 |<-- fp - 0xc0
* | other |<-- fp - 0xe0
* | ? |
* | ? |
* |---------------------------------|<-- sp' = fp - 0x140
* | |
* xcution start | |
* sp' + 0x94 -->| CALL_DUMMY (x code) |
* | |
* | |
* |---------------------------------|<-- sp'' = fp - 0x200
* | align sp to 8 byte boundary |
* | ==> args to fn <== |
* Room for | |
* i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44|
* |---------------------------------|<-- final sp (variable)
* | |
* | Where function called will |
* | build frame. |
* | |
* | |
*
* I understand everything in this picture except what the space
* between fp - 0xe0 and fp - 0x140 is used for. Oh, and I don't
* understand why there's a large chunk of CALL_DUMMY that never gets
* executed (its function is superceeded by PUSH_DUMMY_FRAME; they
* are designed to do the same thing).
*
* PUSH_DUMMY_FRAME saves the registers above sp' and pushes the
* register file stack down one.
*
* call_function then writes CALL_DUMMY, pushes the args onto the
* stack, and adjusts the stack pointer.
*
* run_stack_dummy then starts execution (in the middle of
* CALL_DUMMY, as directed by call_function).
*/
/* Push an empty stack frame, to record the current PC, etc. */
/* Note: to be perfectly correct, we have to restore the
IN registers (which were the OUT registers of the calling frame). */
/* Note that the write's are of registers in the context of the newly
pushed frame. Thus the the fp*'s, the g*'s, the i*'s, and
the others, of the new frame, are being saved.
The locals are new; they don't need to be saved. The i's and l's of
the last frame were saved by the do_save_insn in the register
file (ie. on the stack, since a context switch happended imm after) */
/* We note that the return pointer register does not *need* to have
the pc saved into it (return from this frame will be accomplished
by a POP_FRAME), however, just in case it might be needed, we will
leave it. However, we will write the original value of RP into the
location on the stack for saving i7 (what rp turns into upon call);
this way we don't loose the value with our function call. */
/* Note that the pc saved must be 8 less than the actual pc, since
both POP_FRAME and the normal return sequence on the sparc return
to 8 more than the value of RP_REGNUM */
#define PUSH_DUMMY_FRAME \
{ extern char registers[]; \
register int regnum; \
CORE_ADDR fp = read_register (FP_REGNUM); \
CORE_ADDR pc = read_register (PC_REGNUM) - 8; \
CORE_ADDR rp = read_register (RP_REGNUM); \
void do_save_insn (); \
supply_register (RP_REGNUM, &pc); \
do_save_insn (0x140); \
fp = read_register (FP_REGNUM); \
write_memory (fp - 0x80, &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\
write_memory (fp - 0xa0, &registers[REGISTER_BYTE (0)], 8 * 4); \
write_memory (fp - 0xc0, &registers[REGISTER_BYTE (24)], 7 * 4); \
write_memory (fp - 0xa4, &rp, 4); \
write_memory (fp - 0xe0, &registers[REGISTER_BYTE (64)], 8 * 4); \
}
/* Discard from the stack the innermost frame,
restoring all saved registers.
Note that the values stored in fsr by get_frame_saved_regs are *in
the context of the inferior frame*. What this means is that the i
regs of fsr must be restored into the o regs of the frame popped
into. We don't care about the output regs of the inferior frame.
This is true for dummy frames. Is it true for normal frames? It
really does appear so. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register CORE_ADDR pc; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[REGISTER_BYTES]; \
void do_restore_insn (); \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
pc = read_memory_integer (fsr.regs[PC_REGNUM], 4); \
do_restore_insn (PC_ADJUST (pc)); \
if (fsr.regs[FP0_REGNUM]) \
{ \
read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); \
write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4); \
} \
if (fsr.regs[1]) \
{ \
read_memory (fsr.regs[1], raw_buffer, 7 * 4); \
write_register_bytes (REGISTER_BYTE (1), raw_buffer, 7 * 4); \
} \
if (fsr.regs[24]) \
{ \
read_memory (fsr.regs[24], raw_buffer, 8 * 4); \
write_register_bytes (REGISTER_BYTE (8), raw_buffer, 8 * 4); \
} \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
if (fsr.regs[Y_REGNUM]) \
write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4)); \
if (fsr.regs[NPC_REGNUM]) \
write_register (NPC_REGNUM, read_memory_integer (fsr.regs[NPC_REGNUM], 4)); \
flush_cached_frames (); \
set_current_frame ( create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
/* This sequence of words is the instructions
save %sp,-0x140,%sp
std %f30,[%fp-0x08]
std %f28,[%fp-0x10]
std %f26,[%fp-0x18]
std %f24,[%fp-0x20]
std %f22,[%fp-0x28]
std %f20,[%fp-0x30]
std %f18,[%fp-0x38]
std %f16,[%fp-0x40]
std %f14,[%fp-0x48]
std %f12,[%fp-0x50]
std %f10,[%fp-0x58]
std %f8,[%fp-0x60]
std %f6,[%fp-0x68]
std %f4,[%fp-0x70]
std %f2,[%fp-0x78]
std %f0,[%fp-0x80]
std %g6,[%fp-0x88]
std %g4,[%fp-0x90]
std %g2,[%fp-0x98]
std %g0,[%fp-0xa0]
std %i6,[%fp-0xa8]
std %i4,[%fp-0xb0]
std %i2,[%fp-0xb8]
std %i0,[%fp-0xc0]
nop ! stcsr [%fp-0xc4]
nop ! stfsr [%fp-0xc8]
nop ! wr %npc,[%fp-0xcc]
nop ! wr %pc,[%fp-0xd0]
rd %tbr,%o0
st %o0,[%fp-0xd4]
rd %wim,%o1
st %o0,[%fp-0xd8]
rd %psr,%o0
st %o0,[%fp-0xdc]
rd %y,%o0
st %o0,[%fp-0xe0]
/..* The arguments are pushed at this point by GDB;
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following ld instruction. *../
ld [%sp+0x58],%o5
ld [%sp+0x54],%o4
ld [%sp+0x50],%o3
ld [%sp+0x4c],%o2
ld [%sp+0x48],%o1
call 0x00000000
ld [%sp+0x44],%o0
nop
ta 1
nop
note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes.
note that the `call' insn is a relative, not an absolute call.
note that the `nop' at the end is needed to keep the trap from
clobbering things (if NPC pointed to garbage instead).
We actually start executing at the `sethi', since the pushing of the
registers (as arguments) is done by PUSH_DUMMY_FRAME. If this were
real code, the arguments for the function called by the CALL would be
pushed between the list of ST insns and the CALL, and we could allow
it to execute through. But the arguments have to be pushed by GDB
after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST
insns to be performed again, lest the registers saved be taken for
arguments. */
#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8, \
0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8, \
0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8, \
0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88, \
0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68, \
0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48, \
0xf03fbf40, 0x01000000, 0x01000000, 0x01000000, \
0x01000000, 0x91580000, 0xd027bf50, 0x93500000, \
0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000, \
0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050, \
0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044, \
0x01000000, 0x91d02001, 0x01000000, 0x01000000}
#define CALL_DUMMY_LENGTH 192
#define CALL_DUMMY_START_OFFSET 148
#define CALL_DUMMY_STACK_ADJUST 68
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ \
*(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \
if (TYPE_CODE (type) == TYPE_CODE_STRUCT \
|| TYPE_CODE (type) == TYPE_CODE_UNION) \
*(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \
}
/* Sparc has no reliable single step ptrace call */
#define NO_SINGLE_STEP 1
/* It does have a wait structure, and it might help things out . . . */
#define HAVE_WAIT_STRUCT
/* Handle a feature in the sun4 compiler ("call .stret4" at the end of
functions returning structures). */
#define SUN4_COMPILER_FEATURE
/* We need two arguments (in general) to the "info frame" command.
Note that the definition of this macro implies that there exists a
function "setup_arbitrary_frame" in mach-dep.c */
#define FRAME_SPECIFICATION_DYADIC
/* KDB stuff flushed for now. */
@
1.2
log
@Don't stop the stack trace until the "next frame pointer" is zero.
@
text
@d39 11
@
1.1
log
@Initial revision
@
text
@d66 1
a66 1
#define STACK_END_ADDR 0xff000000
d307 3
d312 4
@

View File

@ -1,824 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.03.27.20.19.34; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.20.19.29.33; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Change HPUX_ASM to USG_SGS_ASM since it's really the Sys V
"Software Generation System" that we are fighting here.
@
text
@/* Print m68k instructions for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "opcode.h"
/* 68k instructions are never longer than this many bytes. */
#define MAXLEN 22
/* Number of elements in the opcode table. */
#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
extern char *reg_names[];
char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
"fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
static unsigned char *print_insn_arg ();
static unsigned char *print_indexed ();
static void print_base ();
static int fetch_arg ();
#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
#define NEXTWORD(p) \
(p += 2, ((((char *)p)[-2]) << 8) + p[-1])
#define NEXTLONG(p) \
(p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
#define NEXTSINGLE(p) \
(p += 4, *((float *)(p - 4)))
#define NEXTDOUBLE(p) \
(p += 8, *((double *)(p - 8)))
#define NEXTEXTEND(p) \
(p += 12, 0.0) /* Need a function to convert from extended to double
precision... */
#define NEXTPACKED(p) \
(p += 12, 0.0) /* Need a function to convert from packed to double
precision. Actually, it's easier to print a
packed number than a double anyway, so maybe
there should be a special case to handle this... */
/* Print the m68k instruction at address MEMADDR in debugged memory,
on STREAM. Returns length of the instruction, in bytes. */
int
print_insn (memaddr, stream)
CORE_ADDR memaddr;
FILE *stream;
{
unsigned char buffer[MAXLEN];
register int i;
register unsigned char *p;
register char *d;
register int bestmask;
int best;
read_memory (memaddr, buffer, MAXLEN);
bestmask = 0;
best = -1;
for (i = 0; i < NOPCODES; i++)
{
register unsigned int opcode = m68k_opcodes[i].opcode;
register unsigned int match = m68k_opcodes[i].match;
if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
&& ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
&& ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
&& ((0xff & buffer[3] & match) == (0xff & opcode)))
{
/* Don't use for printout the variants of divul and divsl
that have the same register number in two places.
The more general variants will match instead. */
for (d = m68k_opcodes[i].args; *d; d += 2)
if (d[1] == 'D')
break;
/* Don't use for printout the variants of most floating
point coprocessor instructions which use the same
register number in two places, as above. */
if (*d == 0)
for (d = m68k_opcodes[i].args; *d; d += 2)
if (d[1] == 't')
break;
if (*d == 0 && match > bestmask)
{
best = i;
bestmask = match;
}
}
}
/* Handle undefined instructions. */
if (best < 0)
{
fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]);
return 2;
}
fprintf (stream, "%s", m68k_opcodes[best].name);
/* Point at first word of argument data,
and at descriptor for first argument. */
p = buffer + 2;
/* Why do this this way? -MelloN */
for (d = m68k_opcodes[best].args; *d; d += 2)
{
if (d[0] == '#')
{
if (d[1] == 'l' && p - buffer < 6)
p = buffer + 6;
else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
p = buffer + 4;
}
if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
p = buffer + 4;
if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
p = buffer + 6;
}
d = m68k_opcodes[best].args;
if (*d)
fputc (' ', stream);
while (*d)
{
p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
d += 2;
if (*d && *(d - 2) != 'I' && *d != 'k')
fprintf (stream, ",");
}
return p - buffer;
}
static unsigned char *
print_insn_arg (d, buffer, p, addr, stream)
char *d;
unsigned char *buffer;
register unsigned char *p;
CORE_ADDR addr; /* PC for this arg to be relative to */
FILE *stream;
{
register int val;
register int place = d[1];
int regno;
register char *regname;
register unsigned char *p1;
register double flval;
int flt_p;
switch (*d)
{
case 'C':
fprintf (stream, "ccr");
break;
case 'S':
fprintf (stream, "sr");
break;
case 'U':
fprintf (stream, "usp");
break;
case 'J':
{
static struct { char *name; int value; } names[]
= {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
{"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
{"msp", 0x803}, {"isp", 0x804}};
val = fetch_arg (buffer, place, 12);
for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
if (names[regno].value == val)
{
fprintf (stream, names[regno].name);
break;
}
if (regno < 0)
fprintf (stream, "%d", val);
}
break;
case 'Q':
val = fetch_arg (buffer, place, 3);
if (val == 0) val = 8;
fprintf (stream, "#%d", val);
break;
case 'M':
val = fetch_arg (buffer, place, 8);
if (val & 0x80)
val = val - 0x100;
fprintf (stream, "#%d", val);
break;
case 'T':
val = fetch_arg (buffer, place, 4);
fprintf (stream, "#%d", val);
break;
case 'D':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
break;
case 'A':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]);
break;
case 'R':
fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
break;
case 'F':
fprintf (stream, "fp%d", fetch_arg (buffer, place, 3));
break;
case 'O':
val = fetch_arg (buffer, place, 6);
if (val & 0x20)
fprintf (stream, "%s", reg_names [val & 7]);
else
fprintf (stream, "%d", val);
break;
case '+':
fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]);
break;
case '-':
fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]);
break;
case 'k':
if (place == 'k')
fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
else if (place == 'C')
{
val = fetch_arg (buffer, place, 7);
if ( val > 63 ) /* This is a signed constant. */
val -= 128;
fprintf (stream, "{#%d}", val);
}
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
break;
case '#':
p1 = buffer + 2;
if (place == 's')
val = fetch_arg (buffer, place, 4);
else if (place == 'C')
val = fetch_arg (buffer, place, 7);
else if (place == '8')
val = fetch_arg (buffer, place, 3);
else if (place == '3')
val = fetch_arg (buffer, place, 8);
else if (place == 'b')
val = NEXTBYTE (p1);
else if (place == 'w')
val = NEXTWORD (p1);
else if (place == 'l')
val = NEXTLONG (p1);
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
fprintf (stream, "#%d", val);
break;
case '^':
if (place == 's')
val = fetch_arg (buffer, place, 4);
else if (place == 'C')
val = fetch_arg (buffer, place, 7);
else if (place == '8')
val = fetch_arg (buffer, place, 3);
else if (place == 'b')
val = NEXTBYTE (p);
else if (place == 'w')
val = NEXTWORD (p);
else if (place == 'l')
val = NEXTLONG (p);
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
fprintf (stream, "#%d", val);
break;
case 'B':
if (place == 'b')
val = NEXTBYTE (p);
else if (place == 'w')
val = NEXTWORD (p);
else if (place == 'l')
val = NEXTLONG (p);
else if (place == 'g')
{
val = ((char *)buffer)[1];
if (val == 0)
val = NEXTWORD (p);
else if (val == -1)
val = NEXTLONG (p);
}
else if (place == 'c')
{
if (buffer[1] & 0x40) /* If bit six is one, long offset */
val = NEXTLONG (p);
else
val = NEXTWORD (p);
}
else
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
print_address (addr + val, stream);
break;
case 'd':
val = NEXTWORD (p);
fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]);
break;
case 's':
fprintf (stream, "%s", fpcr_names[fetch_arg (buffer, place, 3)]);
break;
case 'I':
val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
if (val != 1) /* Unusual coprocessor ID? */
fprintf (stream, "(cpid=%d) ", val);
if (place == 'i')
p += 2; /* Skip coprocessor extended operands */
break;
case '*':
case '~':
case '%':
case ';':
case '@@':
case '!':
case '$':
case '?':
case '/':
case '&':
if (place == 'd')
{
val = fetch_arg (buffer, 'x', 6);
val = ((val & 7) << 3) + ((val >> 3) & 7);
}
else
val = fetch_arg (buffer, 's', 6);
/* Get register number assuming address register. */
regno = (val & 7) + 8;
regname = reg_names[regno];
switch (val >> 3)
{
case 0:
fprintf (stream, "%s", reg_names[val]);
break;
case 1:
fprintf (stream, "%s", regname);
break;
case 2:
fprintf (stream, "(%s)", regname);
break;
case 3:
fprintf (stream, "(%s)+", regname);
break;
case 4:
fprintf (stream, "-(%s)", regname);
break;
case 5:
val = NEXTWORD (p);
fprintf (stream, "%d(%s)", val, regname);
break;
case 6:
p = print_indexed (regno, p, addr, stream);
break;
case 7:
switch (val & 7)
{
case 0:
val = NEXTWORD (p);
fprintf (stream, "@@#");
print_address (val, stream);
break;
case 1:
val = NEXTLONG (p);
fprintf (stream, "@@#");
print_address (val, stream);
break;
case 2:
val = NEXTWORD (p);
print_address (addr + val, stream);
break;
case 3:
p = print_indexed (-1, p, addr, stream);
break;
case 4:
flt_p = 1; /* Assume it's a float... */
switch( place )
{
case 'b':
val = NEXTBYTE (p);
flt_p = 0;
break;
case 'w':
val = NEXTWORD (p);
flt_p = 0;
break;
case 'l':
val = NEXTLONG (p);
flt_p = 0;
break;
case 'f':
flval = NEXTSINGLE(p);
break;
case 'F':
flval = NEXTDOUBLE(p);
break;
case 'x':
flval = NEXTEXTEND(p);
break;
case 'p':
flval = NEXTPACKED(p);
break;
default:
error ("Invalid arg format in opcode table: \"%c%c\".",
*d, place);
}
if ( flt_p ) /* Print a float? */
fprintf (stream, "#%g", flval);
else
fprintf (stream, "#%d", val);
break;
default:
fprintf (stream, "<invalid address mode 0%o>", val);
}
}
break;
default:
error ("Invalid arg format in opcode table: \"%c\".", *d);
}
return (unsigned char *) p;
}
/* Fetch BITS bits from a position in the instruction specified by CODE.
CODE is a "place to put an argument", or 'x' for a destination
that is a general address (mode and register).
BUFFER contains the instruction. */
static int
fetch_arg (buffer, code, bits)
unsigned char *buffer;
char code;
int bits;
{
register int val;
switch (code)
{
case 's':
val = buffer[1];
break;
case 'd': /* Destination, for register or quick. */
val = (buffer[0] << 8) + buffer[1];
val >>= 9;
break;
case 'x': /* Destination, for general arg */
val = (buffer[0] << 8) + buffer[1];
val >>= 6;
break;
case 'k':
val = (buffer[3] >> 4);
break;
case 'C':
val = buffer[3];
break;
case '1':
val = (buffer[2] << 8) + buffer[3];
val >>= 12;
break;
case '2':
val = (buffer[2] << 8) + buffer[3];
val >>= 6;
break;
case '3':
case 'j':
val = (buffer[2] << 8) + buffer[3];
break;
case '4':
val = (buffer[4] << 8) + buffer[5];
val >>= 12;
break;
case '5':
val = (buffer[4] << 8) + buffer[5];
val >>= 6;
break;
case '6':
val = (buffer[4] << 8) + buffer[5];
break;
case '7':
val = (buffer[2] << 8) + buffer[3];
val >>= 7;
break;
case '8':
val = (buffer[2] << 8) + buffer[3];
val >>= 10;
break;
default:
abort ();
}
switch (bits)
{
case 3:
return val & 7;
case 4:
return val & 017;
case 5:
return val & 037;
case 6:
return val & 077;
case 7:
return val & 0177;
case 8:
return val & 0377;
case 12:
return val & 07777;
default:
abort ();
}
}
/* Print an indexed argument. The base register is BASEREG (-1 for pc).
P points to extension word, in buffer.
ADDR is the nominal core address of that extension word. */
static unsigned char *
print_indexed (basereg, p, addr, stream)
int basereg;
unsigned char *p;
FILE *stream;
CORE_ADDR addr;
{
register int word;
static char *scales[] = {"", "*2", "*4", "*8"};
register int base_disp;
register int outer_disp;
char buf[40];
word = NEXTWORD (p);
/* Generate the text for the index register.
Where this will be output is not yet determined. */
sprintf (buf, "[%s.%c%s]",
reg_names[(word >> 12) & 0xf],
(word & 0x800) ? 'l' : 'w',
scales[(word >> 9) & 3]);
/* Handle the 68000 style of indexing. */
if ((word & 0x100) == 0)
{
print_base (basereg,
((word & 0x80) ? word | 0xff00 : word & 0xff)
+ ((basereg == -1) ? addr : 0),
stream);
fprintf (stream, "%s", buf);
return p;
}
/* Handle the generalized kind. */
/* First, compute the displacement to add to the base register. */
if (word & 0200)
basereg = -2;
if (word & 0100)
buf[0] = 0;
base_disp = 0;
switch ((word >> 4) & 3)
{
case 2:
base_disp = NEXTWORD (p);
break;
case 3:
base_disp = NEXTLONG (p);
}
if (basereg == -1)
base_disp += addr;
/* Handle single-level case (not indirect) */
if ((word & 7) == 0)
{
print_base (basereg, base_disp, stream);
fprintf (stream, "%s", buf);
return p;
}
/* Two level. Compute displacement to add after indirection. */
outer_disp = 0;
switch (word & 3)
{
case 2:
outer_disp = NEXTWORD (p);
break;
case 3:
outer_disp = NEXTLONG (p);
}
fprintf (stream, "%d(", outer_disp);
print_base (basereg, base_disp, stream);
/* If postindexed, print the closeparen before the index. */
if (word & 4)
fprintf (stream, ")%s", buf);
/* If preindexed, print the closeparen after the index. */
else
fprintf (stream, "%s)", buf);
return p;
}
/* Print a base register REGNO and displacement DISP, on STREAM.
REGNO = -1 for pc, -2 for none (suppressed). */
static void
print_base (regno, disp, stream)
int regno;
int disp;
FILE *stream;
{
if (regno == -2)
fprintf (stream, "%d", disp);
else if (regno == -1)
fprintf (stream, "0x%x", disp);
else
fprintf (stream, "%d(%s)", disp, reg_names[regno]);
}
/* This is not part of insn printing, but it is machine-specific,
so this is a convenient place to put it.
Convert a 68881 extended float to a double.
FROM is the address of the extended float.
Store the double in *TO. */
convert_from_68881 (from, to)
char *from;
double *to;
{
#ifdef USG_SGS_ASM
asm ("mov.l 8(%a6),%a0");
asm ("mov.l 12(%a6),%a1");
asm ("fmove.x (%a0),%fp0");
asm ("fmove.d %fp0,(%a1)");
#else /* not USG_SGS_ASM */
#if 0
asm ("movl a6@@(8),a0");
asm ("movl a6@@(12),a1");
asm ("fmovex a0@@,fp0");
asm ("fmoved fp0,a1@@");
#else
/* Hand-assemble those insns since some assemblers lose
and some have different syntax. */
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2104800");
asm (".long 0xf2117400");
#endif
#endif /* not USG_SGS_ASM */
}
/* The converse: convert the double *FROM to an extended float
and store where TO points. */
convert_to_68881 (from, to)
double *from;
char *to;
{
#ifdef USG_SGS_ASM
asm ("mov.l 8(%a6),%a0");
asm ("mov.l 12(%a6),%a1");
asm ("fmove.d (%a0),%fp0");
asm ("fmove.x %fp0,(%a1)");
#else /* not USG_SGS_ASM */
#if 0
asm ("movl a6@@(8),a0");
asm ("movl a6@@(12),a1");
asm ("fmoved a0@@,fp0");
asm ("fmovex fp0,a1@@");
#else
/* Hand-assemble those insns since some assemblers lose. */
asm (".word 020156");
asm (".word 8");
asm (".word 021156");
asm (".word 12");
asm (".long 0xf2105400");
asm (".long 0xf2116800");
#endif
#endif /* not USG_SGS_ASM */
}
@
1.1
log
@Initial revision
@
text
@d717 1
a717 1
#ifdef HPUX_ASM
d722 1
a722 1
#else /* not HPUX_ASM */
d738 1
a738 1
#endif /* not HPUX_ASM */
d748 1
a748 1
#ifdef HPUX_ASM
d753 1
a753 1
#else /* not HPUX_ASM */
d768 1
a768 1
#endif /* not HPUX_ASM */
@

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
head 1.3;
access ;
symbols ;
locks ; strict;
comment @# @;
1.3
date 89.03.27.21.15.45; author gnu; state Exp;
branches ;
next 1.2;
1.2
date 89.03.27.20.18.28; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.20.18.58.17; author gnu; state Exp;
branches ;
next ;
desc
@@
1.3
log
@Fix up "munch" so it generates a name that doesn't match its own
"grep" conventions. Change main so that it calls the new name,
and also doesn't use the conventions for functions that should NOT
be called by init.c.
@
text
@#! /bin/sh
# create an initialization procedure from a list of .o files
# Look in object files, find symbols including the string _initialize_,
# and call each one as a function.
echo '/* Do not modify this file. It is created automatically by "munch". */'
echo 'void init_all_files () {'
nm $* | egrep '_initialize_' | \
sed -e 's/^.*\(initialize_[a-zA-Z_0-9]*\).*$/ _\1 ();/' | \
sort -u
echo '}'
@
1.2
log
@Generic change: make it not care much about the output format of "nm".
Now as long as _initialize_foo is not touching any other
symbol or alphanumeric, we'll find it and use it.
@
text
@d8 1
a8 1
echo 'void initialize_all_files () {'
@
1.1
log
@Initial revision
@
text
@d4 2
d10 3
a12 1
nm -p $* | egrep 'T *__?initialize_' | sed -e 's/^.*T *_*\(.*\)/ _\1 ();/'
@

File diff suppressed because it is too large Load Diff

View File

@ -1,662 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.03.27.20.21.22; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.20.18.45.46; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Avoid <sys/fcntl.h>.
@
text
@/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/* Remote communication protocol.
All values are encoded in ascii hex digits.
Request Packet
read registers g
reply XX....X Each byte of register data
is described by two hex digits.
Registers are in the internal order
for GDB, and the bytes in a register
are in the same order the machine uses.
or ENN for an error.
write regs GXX..XX Each byte of register data
is described by two hex digits.
reply OK for success
ENN for an error
read mem mAA..AA,LLLL AA..AA is address, LLLL is length.
reply XX..XX XX..XX is mem contents
or ENN NN is errno
write mem MAA..AA,LLLL:XX..XX
AA..AA is address,
LLLL is number of bytes,
XX..XX is data
reply OK for success
ENN for an error
cont cAA..AA AA..AA is address to resume
If AA..AA is omitted,
resume at same address.
step sAA..AA AA..AA is address to resume
If AA..AA is omitted,
resume at same address.
There is no immediate reply to step or cont.
The reply comes when the machine stops.
It is SAA AA is the "signal number"
kill req k
*/
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#include "wait.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
#endif
#include <stdio.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#ifdef HAVE_TERMIO
#include <termio.h>
#undef TIOCGETP
#define TIOCGETP TCGETA
#undef TIOCSETN
#define TIOCSETN TCSETA
#undef TIOCSETP
#define TIOCSETP TCSETAF
#define TERMINAL struct termio
#else
#include <sgtty.h>
#define TERMINAL struct sgttyb
#endif
int kiodebug;
int icache;
/* Descriptor for I/O to remote machine. */
int remote_desc;
#define PBUFSIZ 400
static void remote_send ();
static void putpkt ();
static void getpkt ();
static void dcache_flush ();
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
void
remote_open (name, from_tty)
char *name;
int from_tty;
{
TERMINAL sg;
remote_debugging = 0;
dcache_init ();
remote_desc = open (name, O_RDWR);
if (remote_desc < 0)
perror_with_name (name);
ioctl (remote_desc, TIOCGETP, &sg);
#ifdef HAVE_TERMIO
sg.c_lflag &= ~ICANON;
#else
sg.sg_flags = RAW;
#endif
ioctl (remote_desc, TIOCSETP, &sg);
if (from_tty)
printf ("Remote debugging using %s\n", name);
remote_debugging = 1;
}
/* Convert hex digit A to a number. */
static int
fromhex (a)
int a;
{
if (a >= '0' && a <= '9')
return a - '0';
else if (a >= 'a' && a <= 'f')
return a - 'a' + 10;
else
error ("Reply contains invalid hex digit");
}
/* Convert number NIB to a hex digit. */
static int
tohex (nib)
int nib;
{
if (nib < 10)
return '0'+nib;
else
return 'a'+nib-10;
}
/* Tell the remote machine to resume. */
int
remote_resume (step, signal)
int step, signal;
{
char buf[PBUFSIZ];
dcache_flush ();
strcpy (buf, step ? "s": "c");
putpkt (buf);
}
/* Wait until the remote machine stops, then return,
storing status in STATUS just as `wait' would. */
int
remote_wait (status)
WAITTYPE *status;
{
char buf[PBUFSIZ];
WSETEXIT ((*status), 0);
getpkt (buf);
if (buf[0] == 'E')
error ("Remote failure reply: %s", buf);
if (buf[0] != 'S')
error ("Invalid remote reply: %s", buf);
WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
}
/* Read the remote registers into the block REGS. */
void
remote_fetch_registers (regs)
char *regs;
{
char buf[PBUFSIZ];
int i;
char *p;
sprintf (buf, "g");
remote_send (buf);
/* Reply describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf;
for (i = 0; i < REGISTER_BYTES; i++)
{
if (p[0] == 0 || p[1] == 0)
error ("Remote reply is too short: %s", buf);
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
}
/* Store the remote registers from the contents of the block REGS. */
void
remote_store_registers (regs)
char *regs;
{
char buf[PBUFSIZ];
int i;
char *p;
buf[0] = 'G';
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf + 1;
for (i = 0; i < REGISTER_BYTES; i++)
{
*p++ = tohex ((regs[i] >> 4) & 0xf);
*p++ = tohex (regs[i] & 0xf);
}
remote_send (buf);
}
/* Read a word from remote address ADDR and return it.
This goes through the data cache. */
int
remote_fetch_word (addr)
CORE_ADDR addr;
{
if (icache)
{
extern CORE_ADDR text_start, text_end;
if (addr >= text_start && addr < text_end)
{
int buffer;
xfer_core_file (addr, &buffer, sizeof (int));
return buffer;
}
}
return dcache_fetch (addr);
}
/* Write a word WORD into remote address ADDR.
This goes through the data cache. */
void
remote_store_word (addr, word)
CORE_ADDR addr;
int word;
{
dcache_poke (addr, word);
}
/* Write memory data directly to the remote machine.
This does not inform the data cache; the data cache uses this.
MEMADDR is the address in the remote memory space.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
remote_write_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
char buf[PBUFSIZ];
int i;
char *p;
if (len > PBUFSIZ / 2 - 20)
abort ();
sprintf (buf, "M%x,%x:", memaddr, len);
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf + strlen (buf);
for (i = 0; i < len; i++)
{
*p++ = tohex ((myaddr[i] >> 4) & 0xf);
*p++ = tohex (myaddr[i] & 0xf);
}
remote_send (buf);
}
/* Read memory data directly from the remote machine.
This does not use the data cache; the data cache uses this.
MEMADDR is the address in the remote memory space.
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
remote_read_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
char buf[PBUFSIZ];
int i;
char *p;
if (len > PBUFSIZ / 2 - 1)
abort ();
sprintf (buf, "m%x,%x", memaddr, len);
remote_send (buf);
/* Reply describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf;
for (i = 0; i < len; i++)
{
if (p[0] == 0 || p[1] == 0)
error ("Remote reply is too short: %s", buf);
myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
}
/*
A debug packet whose contents are <data>
is encapsulated for transmission in the form:
$ <data> # CSUM1 CSUM2
<data> must be ASCII alphanumeric and cannot include characters
'$' or '#'
CSUM1 and CSUM2 are ascii hex representation of an 8-bit
checksum of <data>, the most significant nibble is sent first.
the hex digits 0-9,a-f are used.
Receiver responds with:
+ - if CSUM is correct and ready for next packet
- - if CSUM is incorrect
*/
/* Send the command in BUF to the remote machine,
and read the reply into BUF.
Report an error if we get an error reply. */
static void
remote_send (buf)
char *buf;
{
int i;
putpkt (buf);
getpkt (buf);
if (buf[0] == 'E')
error ("Remote failure reply: %s", buf);
}
/* Send a packet to the remote machine, with error checking.
The data of the packet is in BUF. */
static void
putpkt (buf)
char *buf;
{
int i;
char csum = 0;
char buf2[500];
char buf3[1];
int cnt = strlen (buf);
char *p;
if (kiodebug)
fprintf (stderr, "Sending packet: %s\n", buf);
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
p = buf2;
*p++ = '$';
for (i = 0; i < cnt; i++)
{
csum += buf[i];
*p++ = buf[i];
}
*p++ = '#';
*p++ = tohex ((csum >> 4) & 0xf);
*p++ = tohex (csum & 0xf);
/* Send it over and over until we get a positive ack. */
do {
write (remote_desc, buf2, p - buf2);
read (remote_desc, buf3, 1);
} while (buf3[0] != '+');
}
static int
readchar ()
{
char buf[1];
while (read (remote_desc, buf, 1) != 1) ;
return buf[0] & 0x7f;
}
/* Read a packet from the remote machine, with error checking,
and store it in BUF. */
static void
getpkt (buf)
char *buf;
{
char *bp;
unsigned char csum;
unsigned int c, c1, c2;
extern kiodebug;
while (1)
{
/* Force csum to be zero here because of possible error retry. */
csum = 0;
while ((c = readchar()) != '$');
bp = buf;
while (1)
{
c = readchar ();
if (c == '#')
break;
*bp++ = c;
csum += c;
}
*bp = 0;
c1 = fromhex (readchar ());
c2 = fromhex (readchar ());
if (csum == (c1 << 4) + c2)
break;
printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
write (remote_desc, "-", 1);
}
write (remote_desc, "+", 1);
if (kiodebug)
fprintf (stderr,"Packet received :%s\n", buf);
}
/* The data cache records all the data read from the remote machine
since the last time it stopped.
Each cache block holds 16 bytes of data
starting at a multiple-of-16 address. */
#define DCACHE_SIZE 64 /* Number of cache blocks */
struct dcache_block {
struct dcache_block *next, *last;
unsigned int addr; /* Address for which data is recorded. */
int data[4];
};
struct dcache_block dcache_free, dcache_valid;
/* Free all the data cache blocks, thus discarding all cached data. */
static void
dcache_flush ()
{
register struct dcache_block *db;
while ((db = dcache_valid.next) != &dcache_valid)
{
remque (db);
insque (db, &dcache_free);
}
}
/*
* If addr is present in the dcache, return the address of the block
* containing it.
*/
struct dcache_block *
dcache_hit (addr)
{
register struct dcache_block *db;
if (addr & 3)
abort ();
/* Search all cache blocks for one that is at this address. */
db = dcache_valid.next;
while (db != &dcache_valid)
{
if ((addr & 0xfffffff0) == db->addr)
return db;
db = db->next;
}
return NULL;
}
/* Return the int data at address ADDR in dcache block DC. */
int
dcache_value (db, addr)
struct dcache_block *db;
unsigned int addr;
{
if (addr & 3)
abort ();
return (db->data[(addr>>2)&3]);
}
/* Get a free cache block, put it on the valid list,
and return its address. The caller should store into the block
the address and data that it describes. */
struct dcache_block *
dcache_alloc ()
{
register struct dcache_block *db;
if ((db = dcache_free.next) == &dcache_free)
/* If we can't get one from the free list, take last valid */
db = dcache_valid.last;
remque (db);
insque (db, &dcache_valid);
return (db);
}
/* Return the contents of the word at address ADDR in the remote machine,
using the data cache. */
int
dcache_fetch (addr)
CORE_ADDR addr;
{
register struct dcache_block *db;
db = dcache_hit (addr);
if (db == 0)
{
db = dcache_alloc ();
remote_read_bytes (addr & ~0xf, db->data, 16);
db->addr = addr & ~0xf;
}
return (dcache_value (db, addr));
}
/* Write the word at ADDR both in the data cache and in the remote machine. */
dcache_poke (addr, data)
CORE_ADDR addr;
int data;
{
register struct dcache_block *db;
/* First make sure the word is IN the cache. DB is its cache block. */
db = dcache_hit (addr);
if (db == 0)
{
db = dcache_alloc ();
remote_read_bytes (addr & ~0xf, db->data, 16);
db->addr = addr & ~0xf;
}
/* Modify the word in the cache. */
db->data[(addr>>2)&3] = data;
/* Send the changed word. */
remote_write_bytes (addr, &data, 4);
}
/* Initialize the data cache. */
dcache_init ()
{
register i;
register struct dcache_block *db;
db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) *
DCACHE_SIZE);
dcache_free.next = dcache_free.last = &dcache_free;
dcache_valid.next = dcache_valid.last = &dcache_valid;
for (i=0;i<DCACHE_SIZE;i++,db++)
insque (db, &dcache_free);
}
@
1.1
log
@Initial revision
@
text
@d74 1
a74 1
#include <sys/fcntl.h>
@

View File

@ -1,990 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.03.27.20.21.45; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.20.18.45.48; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Avoid <sys/fcntl.h>.
@
text
@/* List lines of source files for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "symtab.h"
#include "param.h"
#ifdef USG
#include <sys/types.h>
#include <fcntl.h>
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
/* Path of directories to search for source files.
Same format as the PATH environment variable's value. */
static char *source_path;
/* Symtab of default file for listing lines of. */
struct symtab *current_source_symtab;
/* Default next line to list. */
int current_source_line;
/* Line number of last line printed. Default for various commands.
current_source_line is usually, but not always, the same as this. */
static int last_line_listed;
/* First line number listed by last listing command. */
static int first_line_listed;
struct symtab *psymtab_to_symtab ();
/* Set the source file default for the "list" command,
specifying a symtab. */
void
select_source_symtab (s)
register struct symtab *s;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
struct partial_symtab *ps, *cs_pst;
/* Make the default place to list be the function `main'
if one exists. */
if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0))
{
sals = decode_line_spec ("main", 1);
sal = sals.sals[0];
free (sals.sals);
current_source_symtab = sal.symtab;
current_source_line = sal.line - 9;
return;
}
/* If there is no `main', use the last symtab in the list,
which is actually the first found in the file's symbol table.
But ignore .h files. */
if (s)
{
do
{
char *name = s->filename;
int len = strlen (name);
if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
current_source_symtab = s;
s = s->next;
}
while (s);
current_source_line = 1;
}
else
{
ps = partial_symtab_list;
while (ps)
{
char *name = ps->filename;
int len = strlen (name);
if (! (len > 2 && !strcmp (&name[len - 2], ".h")))
cs_pst = ps;
ps = ps->next;
}
if (cs_pst)
current_source_symtab = psymtab_to_symtab (cs_pst);
else
current_source_symtab = 0;
current_source_line = 1;
}
}
static void
directories_info ()
{
printf ("Source directories searched: %s\n", source_path);
}
void
init_source_path ()
{
register struct symtab *s;
source_path = savestring (current_directory, strlen (current_directory));
/* Forget what we learned about line positions in source files;
must check again now since files may be found in
a different directory now. */
for (s = symtab_list; s; s = s->next)
if (s->line_charpos != 0)
{
free (s->line_charpos);
s->line_charpos = 0;
}
}
void
directory_command (dirname, from_tty)
char *dirname;
int from_tty;
{
char *old = source_path;
if (dirname == 0)
{
if (query ("Reinitialize source path to %s? ", current_directory))
{
init_source_path ();
free (old);
}
}
else
{
struct stat st;
register int len = strlen (dirname);
register char *tem;
extern char *index ();
if (index (dirname, ':'))
error ("Please add one directory at a time to the source path.");
if (dirname[len - 1] == '/')
/* Sigh. "foo/" => "foo" */
dirname[--len] == '\0';
while (dirname[len - 1] == '.')
{
if (len == 1)
{
/* "." => getwd () */
dirname = current_directory;
goto append;
}
else if (dirname[len - 2] == '/')
{
if (len == 2)
{
/* "/." => "/" */
dirname[--len] = '\0';
goto append;
}
else
{
/* "...foo/." => "...foo" */
dirname[len -= 2] = '\0';
continue;
}
}
break;
}
if (dirname[0] != '/')
dirname = concat (current_directory, "/", dirname);
else
dirname = savestring (dirname, len);
make_cleanup (free, dirname);
if (stat (dirname, &st) < 0)
perror_with_name (dirname);
if ((st.st_mode & S_IFMT) != S_IFDIR)
error ("%s is not a directory.", dirname);
append:
len = strlen (dirname);
tem = source_path;
while (1)
{
if (!strncmp (tem, dirname, len)
&& (tem[len] == '\0' || tem[len] == ':'))
{
printf ("\"%s\" is already in the source path.\n",
dirname);
break;
}
tem = index (tem, ':');
if (tem)
tem++;
else
{
source_path = concat (old, ":", dirname);
free (old);
break;
}
}
if (from_tty)
directories_info ();
}
}
/* Open a file named STRING, searching path PATH (dir names sep by colons)
using mode MODE and protection bits PROT in the calls to open.
If TRY_CWD_FIRST, try to open ./STRING before searching PATH.
(ie pretend the first element of PATH is ".")
If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
the actual file opened (this string will always start with a "/"
If a file is found, return the descriptor.
Otherwise, return -1, with errno set for the last name we tried to open. */
/* >>>> This should only allow files of certain types,
>>>> eg executable, non-directory */
int
openp (path, try_cwd_first, string, mode, prot, filename_opened)
char *path;
int try_cwd_first;
char *string;
int mode;
int prot;
char **filename_opened;
{
register int fd;
register char *filename;
register char *p, *p1;
register int len;
/* ./foo => foo */
while (string[0] == '.' && string[1] == '/')
string += 2;
if (try_cwd_first || string[0] == '/')
{
filename = string;
fd = open (filename, mode, prot);
if (fd >= 0 || string[0] == '/')
goto done;
}
filename = (char *) alloca (strlen (path) + strlen (string) + 2);
fd = -1;
for (p = path; p; p = p1 ? p1 + 1 : 0)
{
p1 = (char *) index (p, ':');
if (p1)
len = p1 - p;
else
len = strlen (p);
strncpy (filename, p, len);
filename[len] = 0;
strcat (filename, "/");
strcat (filename, string);
fd = open (filename, mode, prot);
if (fd >= 0) break;
}
done:
if (filename_opened)
if (fd < 0)
*filename_opened = (char *) 0;
else if (filename[0] == '/')
*filename_opened = savestring (filename, strlen (filename));
else
{
*filename_opened = concat (current_directory, "/", filename);
}
return fd;
}
/* Create and initialize the table S->line_charpos that records
the positions of the lines in the source file, which is assumed
to be open on descriptor DESC.
All set S->nlines to the number of such lines. */
static void
find_source_lines (s, desc)
struct symtab *s;
int desc;
{
struct stat st;
register char *data, *p, *end;
int nlines = 0;
int lines_allocated = 1000;
int *line_charpos = (int *) xmalloc (lines_allocated * sizeof (int));
extern int exec_mtime;
fstat (desc, &st);
if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime)
printf ("Source file is more recent than executable.\n");
data = (char *) alloca (st.st_size);
myread (desc, data, st.st_size);
end = data + st.st_size;
p = data;
line_charpos[0] = 0;
nlines = 1;
while (p != end)
{
if (*p++ == '\n'
/* A newline at the end does not start a new line. */
&& p != end)
{
if (nlines == lines_allocated)
{
lines_allocated *= 2;
line_charpos = (int *) xrealloc (line_charpos,
sizeof (int) * lines_allocated);
}
line_charpos[nlines++] = p - data;
}
}
s->nlines = nlines;
s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int));
}
/* Return the character position of a line LINE in symtab S.
Return 0 if anything is invalid. */
int
source_line_charpos (s, line)
struct symtab *s;
int line;
{
if (!s) return 0;
if (!s->line_charpos || line <= 0) return 0;
if (line > s->nlines)
line = s->nlines;
return s->line_charpos[line - 1];
}
/* Return the line number of character position POS in symtab S. */
int
source_charpos_line (s, chr)
register struct symtab *s;
register int chr;
{
register int line = 0;
register int *lnp;
if (s == 0 || s->line_charpos == 0) return 0;
lnp = s->line_charpos;
/* Files are usually short, so sequential search is Ok */
while (line < s->nlines && *lnp <= chr)
{
line++;
lnp++;
}
if (line >= s->nlines)
line = s->nlines;
return line;
}
/* Get full pathname and line number positions for a symtab.
Return nonzero if line numbers may have changed.
Set *FULLNAME to actual name of the file as found by `openp',
or to 0 if the file is not found. */
int
get_filename_and_charpos (s, line, fullname)
struct symtab *s;
int line;
char **fullname;
{
register int desc, linenums_changed = 0;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
if (desc < 0)
{
if (fullname)
*fullname = NULL;
return 0;
}
if (fullname)
*fullname = s->fullname;
if (s->line_charpos == 0) linenums_changed = 1;
if (linenums_changed) find_source_lines (s, desc);
close (desc);
return linenums_changed;
}
/* Print text describing the full name of the source file S
and the line number LINE and its corresponding character position.
The text starts with two Ctrl-z so that the Emacs-GDB interface
can easily find it.
MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
Return 1 if successful, 0 if could not find the file. */
int
identify_source_line (s, line, mid_statement)
struct symtab *s;
int line;
int mid_statement;
{
if (s->line_charpos == 0)
get_filename_and_charpos (s, line, 0);
if (s->fullname == 0)
return 0;
printf ("\032\032%s:%d:%d:%s\n", s->fullname,
line, s->line_charpos[line - 1],
mid_statement ? "middle" : "beg");
current_source_line = line;
first_line_listed = line;
last_line_listed = line;
current_source_symtab = s;
return 1;
}
/* Print source lines from the file of symtab S,
starting with line number LINE and stopping before line number STOPLINE. */
void
print_source_lines (s, line, stopline, noerror)
struct symtab *s;
int line, stopline;
int noerror;
{
register int c;
register int desc;
register FILE *stream;
int nlines = stopline - line;
desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
if (desc < 0)
{
extern int errno;
if (! noerror)
perror_with_name (s->filename);
print_sys_errmsg (s->filename, errno);
return;
}
if (s->line_charpos == 0)
find_source_lines (s, desc);
if (line < 1 || line > s->nlines)
{
close (desc);
error ("Line number out of range; %s has %d lines.",
s->filename, s->nlines);
}
if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (s->filename);
}
current_source_symtab = s;
current_source_line = line;
first_line_listed = line;
stream = fdopen (desc, "r");
clearerr (stream);
while (nlines-- > 0)
{
c = fgetc (stream);
if (c == EOF) break;
last_line_listed = current_source_line;
printf ("%d\t", current_source_line++);
do
{
if (c < 040 && c != '\t' && c != '\n')
{
fputc ('^', stdout);
fputc (c + 0100, stdout);
}
else if (c == 0177)
printf ("^?");
else
fputc (c, stdout);
} while (c != '\n' && (c = fgetc (stream)) >= 0);
}
fclose (stream);
}
/*
C++
Print a list of files and line numbers which a user may choose from
in order to list a function which was specified ambiguously
(as with `list classname::overloadedfuncname', for example).
The vector in SALS provides the filenames and line numbers.
*/
static void
ambiguous_line_spec (sals)
struct symtabs_and_lines *sals;
{
int i;
for (i = 0; i < sals->nelts; ++i)
printf("file: \"%s\", line number: %d\n",
sals->sals[i].symtab->filename, sals->sals[i].line);
}
static void
list_command (arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals, sals_end;
struct symtab_and_line sal, sal_end;
struct symbol *sym;
char *arg1;
int no_end = 1;
int dummy_end = 0;
int dummy_beg = 0;
int linenum_beg = 0;
char *p;
if (symtab_list == 0 && partial_symtab_list == 0)
error ("Listing source lines requires symbols.");
/* Pull in a current source symtab if necessary */
if (current_source_symtab == 0 &&
(arg == 0 || arg[0] == '+' || arg[0] == '-'))
select_source_symtab (symtab_list);
/* "l" or "l +" lists next ten lines. */
if (arg == 0 || !strcmp (arg, "+"))
{
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
print_source_lines (current_source_symtab, current_source_line,
current_source_line + 10, 0);
return;
}
/* "l -" lists previous ten lines, the ones before the ten just listed. */
if (!strcmp (arg, "-"))
{
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
print_source_lines (current_source_symtab,
max (first_line_listed - 10, 1),
first_line_listed, 0);
return;
}
/* Now if there is only one argument, decode it in SAL
and set NO_END.
If there are two arguments, decode them in SAL and SAL_END
and clear NO_END; however, if one of the arguments is blank,
set DUMMY_BEG or DUMMY_END to record that fact. */
arg1 = arg;
if (*arg1 == ',')
dummy_beg = 1;
else
{
sals = decode_line_1 (&arg1, 0, 0, 0);
if (! sals.nelts) return; /* C++ */
if (sals.nelts > 1)
{
ambiguous_line_spec (&sals);
free (sals.sals);
return;
}
sal = sals.sals[0];
free (sals.sals);
}
/* Record whether the BEG arg is all digits. */
for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
linenum_beg = (p == arg1);
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
if (*arg1 == ',')
{
no_end = 0;
arg1++;
while (*arg1 == ' ' || *arg1 == '\t')
arg1++;
if (*arg1 == 0)
dummy_end = 1;
else
{
if (dummy_beg)
sals_end = decode_line_1 (&arg1, 0, 0, 0);
else
sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line);
if (sals_end.nelts == 0)
return;
if (sals_end.nelts > 1)
{
ambiguous_line_spec (&sals_end);
free (sals_end.sals);
return;
}
sal_end = sals_end.sals[0];
free (sals_end.sals);
}
}
if (*arg1)
error ("Junk at end of line specification.");
if (!no_end && !dummy_beg && !dummy_end
&& sal.symtab != sal_end.symtab)
error ("Specified start and end are in different files.");
if (dummy_beg && dummy_end)
error ("Two empty args do not say what lines to list.");
/* if line was specified by address,
first print exactly which line, and which file.
In this case, sal.symtab == 0 means address is outside
of all known source files, not that user failed to give a filename. */
if (*arg == '*')
{
if (sal.symtab == 0)
error ("No source file for address 0x%x.", sal.pc);
sym = find_pc_function (sal.pc);
if (sym)
printf ("0x%x is in %s (%s, line %d).\n",
sal.pc, SYMBOL_NAME (sym), sal.symtab->filename, sal.line);
else
printf ("0x%x is in %s, line %d.\n",
sal.pc, sal.symtab->filename, sal.line);
}
/* If line was not specified by just a line number,
and it does not imply a symtab, it must be an undebuggable symbol
which means no source code. */
if (! linenum_beg && sal.symtab == 0)
error ("No line number known for %s.", arg);
/* If this command is repeated with RET,
turn it into the no-arg variant. */
if (from_tty)
*arg = 0;
if (dummy_beg && sal_end.symtab == 0)
error ("No default source file yet. Do \"help list\".");
if (dummy_beg)
print_source_lines (sal_end.symtab, max (sal_end.line - 9, 1),
sal_end.line + 1, 0);
else if (sal.symtab == 0)
error ("No default source file yet. Do \"help list\".");
else if (no_end)
print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0);
else
print_source_lines (sal.symtab, sal.line,
dummy_end ? sal.line + 10 : sal_end.line + 1,
0);
}
/* Print info on range of pc's in a specified line. */
static void
line_info (arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
int start_pc, end_pc;
int i;
if (arg == 0)
{
sal.symtab = current_source_symtab;
sal.line = last_line_listed;
sals.nelts = 1;
sals.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
sals.sals[0] = sal;
}
else
{
sals = decode_line_spec_1 (arg, 0);
/* If this command is repeated with RET,
turn it into the no-arg variant. */
if (from_tty)
*arg = 0;
}
/* C++ More than one line may have been specified, as when the user
specifies an overloaded function name. Print info on them all. */
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
if (sal.symtab == 0)
error ("No source file specified.");
if (sal.line > 0
&& find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
{
if (start_pc == end_pc)
printf ("Line %d of \"%s\" is at pc 0x%x but contains no code.\n",
sal.line, sal.symtab->filename, start_pc);
else
printf ("Line %d of \"%s\" starts at pc 0x%x and ends at 0x%x.\n",
sal.line, sal.symtab->filename, start_pc, end_pc);
/* x/i should display this line's code. */
set_next_address (start_pc);
/* Repeating "info line" should do the following line. */
last_line_listed = sal.line + 1;
}
else
printf ("Line number %d is out of range for \"%s\".\n",
sal.line, sal.symtab->filename);
}
}
/* Commands to search the source file for a regexp. */
static void
forward_search_command (regex, from_tty)
char *regex;
{
register int c;
register int desc;
register FILE *stream;
int line = last_line_listed + 1;
char *msg;
msg = (char *) re_comp (regex);
if (msg)
error (msg);
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
/* Search from last_line_listed+1 in current_source_symtab */
desc = openp (source_path, 0, current_source_symtab->filename,
O_RDONLY, 0, &current_source_symtab->fullname);
if (desc < 0)
perror_with_name (current_source_symtab->filename);
if (current_source_symtab->line_charpos == 0)
find_source_lines (current_source_symtab, desc);
if (line < 1 || line > current_source_symtab->nlines)
{
close (desc);
error ("Expression not found");
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (current_source_symtab->filename);
}
stream = fdopen (desc, "r");
clearerr (stream);
while (1) {
char buf[4096]; /* Should be reasonable??? */
register char *p = buf;
c = fgetc (stream);
if (c == EOF)
break;
do {
*p++ = c;
} while (c != '\n' && (c = fgetc (stream)) >= 0);
/* we now have a source line in buf, null terminate and match */
*p = 0;
if (re_exec (buf) > 0)
{
/* Match! */
fclose (stream);
print_source_lines (current_source_symtab,
line, line+1, 0);
current_source_line = max (line - 5, 1);
return;
}
line++;
}
printf ("Expression not found\n");
fclose (stream);
}
static void
reverse_search_command (regex, from_tty)
char *regex;
{
register int c;
register int desc;
register FILE *stream;
int line = last_line_listed - 1;
char *msg;
msg = (char *) re_comp (regex);
if (msg)
error (msg);
if (current_source_symtab == 0)
error ("No default source file yet. Do \"help list\".");
/* Search from last_line_listed-1 in current_source_symtab */
desc = openp (source_path, 0, current_source_symtab->filename,
O_RDONLY, 0, &current_source_symtab->fullname);
if (desc < 0)
perror_with_name (current_source_symtab->filename);
if (current_source_symtab->line_charpos == 0)
find_source_lines (current_source_symtab, desc);
if (line < 1 || line > current_source_symtab->nlines)
{
close (desc);
error ("Expression not found");
}
if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
close (desc);
perror_with_name (current_source_symtab->filename);
}
stream = fdopen (desc, "r");
clearerr (stream);
while (1)
{
char buf[4096]; /* Should be reasonable??? */
register char *p = buf;
c = fgetc (stream);
if (c == EOF)
break;
do {
*p++ = c;
} while (c != '\n' && (c = fgetc (stream)) >= 0);
/* We now have a source line in buf; null terminate and match. */
*p = 0;
if (re_exec (buf) > 0)
{
/* Match! */
fclose (stream);
print_source_lines (current_source_symtab,
line, line+1, 0);
current_source_line = max (line - 5, 1);
return;
}
line--;
if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
{
fclose (stream);
perror_with_name (current_source_symtab->filename);
}
}
printf ("Expression not found\n");
fclose (stream);
return;
}
void
_initialize_source ()
{
current_source_symtab = 0;
init_source_path ();
add_com ("directory", class_files, directory_command,
"Add directory DIR to end of search path for source files.\n\
With no argument, reset the search path to just the working directory\n\
and forget cached info on line positions in source files.");
add_info ("directories", directories_info,
"Current search path for finding source files.");
add_info ("line", line_info,
"Core addresses of the code for a source line.\n\
Line can be specified as\n\
LINENUM, to list around that line in current file,\n\
FILE:LINENUM, to list around that line in that file,\n\
FUNCTION, to list around beginning of that function,\n\
FILE:FUNCTION, to distinguish among like-named static functions.\n\
Default is to describe the last source line that was listed.\n\n\
This sets the default address for \"x\" to the line's first instruction\n\
so that \"x/i\" suffices to start examining the machine code.\n\
The address is also stored as the value of \"$_\".");
add_com ("forward-search", class_files, forward_search_command,
"Search for regular expression (see regex(3)) from last line listed.");
add_com_alias ("search", "forward-search", class_files, 0);
add_com ("reverse-search", class_files, reverse_search_command,
"Search backward for regular expression (see regex(3)) from last line listed.");
add_com ("list", class_files, list_command,
"List specified function or line.\n\
With no argument, lists ten more lines after or around previous listing.\n\
\"list -\" lists the ten lines before a previous ten-line listing.\n\
One argument specifies a line, and ten lines are listed around that line.\n\
Two arguments with comma between specify starting and ending lines to list.\n\
Lines can be specified in these ways:\n\
LINENUM, to list around that line in current file,\n\
FILE:LINENUM, to list around that line in that file,\n\
FUNCTION, to list around beginning of that function,\n\
FILE:FUNCTION, to distinguish among like-named static functions.\n\
*ADDRESS, to list around the line containing that address.\n\
With two args if one is empty it stands for ten lines away from the other arg.");
}
@
1.1
log
@Initial revision
@
text
@d27 1
a27 1
#include <sys/fcntl.h>
@

File diff suppressed because it is too large Load Diff

View File

@ -1,882 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.02.09.23.53.05; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.02.09.15.03.51; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Avoid coredumps if stack commands are used when there is no stack.
@
text
@/* Print and select stack frames for GDB, the GNU debugger.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
#include "gdbcore.h"
/* Thie "selected" stack frame is used by default for local and arg access.
May be zero, for no selected frame. */
FRAME selected_frame;
/* Level of the selected frame:
0 for innermost, 1 for its caller, ...
or -1 for frame specified by address with no defined level. */
int selected_frame_level;
/* Error message when selected_frame is zero when it's needed */
char no_sel_frame[] = "There is no current stack frame.";
/* Nonzero means print the full filename and linenumber
when a frame is printed, and do so in a format programs can parse. */
int frame_file_full_name = 0;
static void select_calling_frame ();
void print_frame_info ();
/* Print a stack frame briefly. FRAME should be the frame address
and LEVEL should be its level in the stack (or -1 for level not defined).
This prints the level, the function executing, the arguments,
and the file name and line number.
If the pc is not at the beginning of the source line,
the actual pc is printed at the beginning.
If SOURCE is 1, print the source line as well.
If SOURCE is -1, print ONLY the source line. */
/* FIXME, the argument "frame" is always "selected_frame". This is why
we can say "No selected frame" if it == 0. Probably shouldn't be an
argument anymore... */
static void
print_stack_frame (frame, level, source)
FRAME frame;
int level;
int source;
{
struct frame_info *fi;
if (frame == 0)
error (no_sel_frame);
fi = get_frame_info (frame);
print_frame_info (fi, level, source, 1);
}
void
print_frame_info (fi, level, source, args)
struct frame_info *fi;
register int level;
int source;
int args;
{
struct symtab_and_line sal;
struct symbol *func;
register char *funname = 0;
int numargs;
sal = find_pc_line (fi->pc, fi->next_frame);
func = find_pc_function (fi->pc);
if (func)
funname = SYMBOL_NAME (func);
else
{
register int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0)
funname = misc_function_vector[misc_index].name;
}
if (source >= 0 || !sal.symtab)
{
if (level >= 0)
printf ("#%-2d ", level);
if (fi->pc != sal.pc || !sal.symtab)
printf ("0x%x in ", fi->pc);
printf ("%s (", funname ? funname : "??");
if (args)
{
FRAME_NUM_ARGS (numargs, fi);
print_frame_args (func, fi, numargs, stdout);
}
printf (")");
if (sal.symtab)
printf (" (%s line %d)", sal.symtab->filename, sal.line);
printf ("\n");
}
if (source != 0 && sal.symtab)
{
int done = 0;
int mid_statement = source < 0 && fi->pc != sal.pc;
if (frame_file_full_name)
done = identify_source_line (sal.symtab, sal.line, mid_statement);
if (!done)
{
if (mid_statement)
printf ("0x%x\t", fi->pc);
print_source_lines (sal.symtab, sal.line, sal.line + 1, 1);
}
current_source_line = max (sal.line - 5, 1);
}
if (source != 0)
set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
fflush (stdout);
}
/* Call here to print info on selected frame, after a trap. */
void
print_sel_frame (just_source)
int just_source;
{
print_stack_frame (selected_frame, -1, just_source ? -1 : 1);
}
/* Print info on the selected frame, including level number
but not source. */
void
print_selected_frame ()
{
print_stack_frame (selected_frame, selected_frame_level, 0);
}
void flush_cached_frames (); /* FIXME, never called! */
#ifdef FRAME_SPECIFICATION_DYADIC
extern FRAME setup_arbitrary_frame ();
#endif
/*
* Read a frame specification in whatever the appropriate format is.
*/
static FRAME
parse_frame_specification (frame_exp)
char *frame_exp;
{
int numargs = 0;
int arg1, arg2;
if (frame_exp)
{
char *addr_string, *p;
struct cleanup *tmp_cleanup;
struct frame_info *fci;
while (*frame_exp == ' ') frame_exp++;
for (p = frame_exp; *p && *p != ' '; p++)
;
if (*frame_exp)
{
numargs = 1;
addr_string = savestring(frame_exp, p - frame_exp);
{
tmp_cleanup = make_cleanup (free, addr_string);
arg1 = parse_and_eval_address (addr_string);
do_cleanups (tmp_cleanup);
}
while (*p == ' ') p++;
if (*p)
{
numargs = 2;
arg2 = parse_and_eval_address (p);
}
}
}
switch (numargs)
{
case 0:
if (selected_frame == 0)
error (no_sel_frame);
return selected_frame;
/* NOTREACHED */
case 1:
{
int level = arg1;
FRAME fid = find_relative_frame (get_current_frame (), &level);
FRAME tfid;
if (level == 0)
/* find_relative_frame was successful */
return fid;
/* If (s)he specifies the frame with an address, he deserves what
(s)he gets. Still, give the highest one that matches. */
for (fid = get_current_frame ();
fid && FRAME_FP (fid) != arg1;
fid = get_prev_frame (fid))
;
if (fid)
while ((tfid = get_prev_frame (fid)) &&
(FRAME_FP (tfid) == arg1))
fid = tfid;
#ifdef FRAME_SPECIFICATION_DYADIC
if (!fid)
error ("Incorrect number of args in frame specification");
return fid;
#else
return create_new_frame (arg1, 0);
#endif
}
/* NOTREACHED */
case 2:
/* Must be addresses */
#ifndef FRAME_SPECIFICATION_DYADIC
error ("Incorrect number of args in frame specification");
#else
return setup_arbitrary_frame (arg1, arg2);
#endif
/* NOTREACHED */
}
fatal ("Internal: Error in parsing in parse_frame_specification");
/* NOTREACHED */
}
/* Print verbosely the selected frame or the frame at address ADDR.
This means absolutely all information in the frame is printed. */
static void
frame_info (addr_exp)
char *addr_exp;
{
FRAME frame;
struct frame_info *fi;
struct frame_saved_regs fsr;
struct symtab_and_line sal;
struct symbol *func;
FRAME calling_frame;
int i, count;
char *funname = 0;
int numargs;
frame = parse_frame_specification (addr_exp);
fi = get_frame_info (frame);
get_frame_saved_regs (fi, &fsr);
sal = find_pc_line (fi->pc, fi->next_frame);
func = get_frame_function (frame);
if (func)
funname = SYMBOL_NAME (func);
else
{
register int misc_index = find_pc_misc_function (fi->pc);
if (misc_index >= 0)
funname = misc_function_vector[misc_index].name;
}
calling_frame = get_prev_frame (frame);
if (!addr_exp && selected_frame_level >= 0)
printf ("Stack level %d, frame at 0x%x:\n pc = 0x%x",
selected_frame_level, FRAME_FP(frame), fi->pc);
else
printf ("Stack frame at 0x%x:\n pc = 0x%x",
FRAME_FP(frame), fi->pc);
if (funname)
printf (" in %s", funname);
if (sal.symtab)
printf (" (%s line %d)", sal.symtab->filename, sal.line);
printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame));
if (calling_frame)
printf (" called by frame at 0x%x", FRAME_FP (calling_frame));
if (fi->next_frame && calling_frame)
printf (",");
if (fi->next_frame)
printf (" caller of frame at 0x%x", fi->next_frame);
if (fi->next_frame || calling_frame)
printf ("\n");
printf (" Arglist at 0x%x,", FRAME_ARGS_ADDRESS (fi));
FRAME_NUM_ARGS (i, fi);
if (i < 0)
printf (" args: ");
else if (i == 0)
printf (" no args.");
else if (i == 1)
printf (" 1 arg: ");
else
printf (" %d args: ", i);
FRAME_NUM_ARGS (numargs, fi);
print_frame_args (func, fi, numargs, stdout);
printf ("\n");
count = 0;
for (i = 0; i < NUM_REGS; i++)
if (fsr.regs[i])
{
if (count % 4 != 0)
printf (", ");
else
{
if (count == 0)
printf (" Saved registers:");
printf ("\n ");
}
printf ("%s at 0x%x", reg_names[i], fsr.regs[i]);
count++;
}
if (count)
printf ("\n");
}
#if 0
/* Set a limit on the number of frames printed by default in a
backtrace. */
static int backtrace_limit;
static void
set_backtrace_limit_command (count_exp, from_tty)
char *count_exp;
int from_tty;
{
int count = parse_and_eval_address (count_exp);
if (count < 0)
error ("Negative argument not meaningful as backtrace limit.");
backtrace_limit = count;
}
static void
backtrace_limit_info (arg, from_tty)
char *arg;
int from_tty;
{
if (arg)
error ("\"Info backtrace-limit\" takes no arguments.");
printf ("Backtrace limit: %d.\n", backtrace_limit);
}
#endif
/* Print briefly all stack frames or just the innermost COUNT frames. */
static void
backtrace_command (count_exp)
char *count_exp;
{
struct frame_info *fi;
register int count;
register FRAME frame;
register int i;
register FRAME trailing;
register int trailing_level;
if (have_inferior_p () == 0 && corefile == 0)
error ("There is no running program or core file.");
/* The following code must do two things. First, it must
set the variable TRAILING to the frame from which we should start
printing. Second, it must set the variable count to the number
of frames which we should print, or -1 if all of them. */
trailing = get_current_frame ();
trailing_level = 0;
if (count_exp)
{
count = parse_and_eval_address (count_exp);
if (count < 0)
{
FRAME current;
count = -count;
current = trailing;
while (current && count--)
current = get_prev_frame (current);
/* Will stop when CURRENT reaches the top of the stack. TRAILING
will be COUNT below it. */
while (current)
{
trailing = get_prev_frame (trailing);
current = get_prev_frame (current);
trailing_level++;
}
count = -1;
}
}
else
#if 0
count = backtrace_limit;
#else
count = -1;
#endif
for (i = 0, frame = trailing;
frame && count--;
i++, frame = get_prev_frame (frame))
{
QUIT;
fi = get_frame_info (frame);
print_frame_info (fi, trailing_level + i, 0, 1);
}
/* If we've stopped before the end, mention that. */
if (frame)
printf ("(More stack frames follow...)\n");
}
/* Print the local variables of a block B active in FRAME. */
static void
print_block_frame_locals (b, frame, stream)
struct block *b;
register FRAME frame;
register FILE *stream;
{
int nsyms;
register int i;
register struct symbol *sym;
nsyms = BLOCK_NSYMS (b);
for (i = 0; i < nsyms; i++)
{
sym = BLOCK_SYM (b, i);
if (SYMBOL_CLASS (sym) == LOC_LOCAL
|| SYMBOL_CLASS (sym) == LOC_REGISTER
|| SYMBOL_CLASS (sym) == LOC_STATIC)
{
fprintf (stream, "%s = ", SYMBOL_NAME (sym));
print_variable_value (sym, frame, stream);
fprintf (stream, "\n");
fflush (stream);
}
}
}
/* Print on STREAM all the local variables in frame FRAME,
including all the blocks active in that frame
at its current pc.
Returns 1 if the job was done,
or 0 if nothing was printed because we have no info
on the function running in FRAME. */
static int
print_frame_local_vars (frame, stream)
register FRAME frame;
register FILE *stream;
{
register struct block *block;
block = get_frame_block (frame);
if (block == 0)
return 0;
while (block != 0)
{
print_block_frame_locals (block, frame, stream);
/* After handling the function's top-level block, stop.
Don't continue to its superblock, the block of
per-file symbols. */
if (BLOCK_FUNCTION (block))
break;
block = BLOCK_SUPERBLOCK (block);
}
return 1;
}
static void
locals_info ()
{
if (selected_frame == 0)
error(no_sel_frame);
print_frame_local_vars (selected_frame, stdout);
}
static int
print_frame_arg_vars (frame, stream)
register FRAME frame;
register FILE *stream;
{
struct symbol *func;
register struct block *b;
int nsyms;
register int i;
register struct symbol *sym;
func = get_frame_function (frame);
if (func == 0)
return 0;
b = SYMBOL_BLOCK_VALUE (func);
nsyms = BLOCK_NSYMS (b);
for (i = 0; i < nsyms; i++)
{
sym = BLOCK_SYM (b, i);
if (SYMBOL_CLASS (sym) == LOC_ARG || SYMBOL_CLASS (sym) == LOC_REGPARM)
{
fprintf (stream, "%s = ", SYMBOL_NAME (sym));
print_variable_value (sym, frame, stream);
fprintf (stream, "\n");
fflush (stream);
}
}
return 1;
}
static void
args_info ()
{
if (selected_frame == 0)
error(no_sel_frame);
print_frame_arg_vars (selected_frame, stdout);
}
/* Select frame FRAME, and note that its stack level is LEVEL.
LEVEL may be -1 if an actual level number is not known. */
void
select_frame (frame, level)
FRAME frame;
int level;
{
selected_frame = frame;
selected_frame_level = level;
}
/* Store the selected frame and its level into *FRAMEP and *LEVELP. */
void
record_selected_frame (frameaddrp, levelp)
FRAME_ADDR *frameaddrp;
int *levelp;
{
*frameaddrp = FRAME_FP (selected_frame);
*levelp = selected_frame_level;
}
/* Return the symbol-block in which the selected frame is executing.
Can return zero under various legitimate circumstances. */
struct block *
get_selected_block ()
{
if (!have_inferior_p () && !have_core_file_p ())
return 0;
if (!selected_frame)
return get_current_block ();
return get_frame_block (selected_frame);
}
/* Find a frame a certain number of levels away from FRAME.
LEVEL_OFFSET_PTR points to an int containing the number of levels.
Positive means go to earlier frames (up); negative, the reverse.
The int that contains the number of levels is counted toward
zero as the frames for those levels are found.
If the top or bottom frame is reached, that frame is returned,
but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
how much farther the original request asked to go. */
FRAME
find_relative_frame (frame, level_offset_ptr)
register FRAME frame;
register int* level_offset_ptr;
{
register FRAME prev;
register FRAME frame1, frame2;
if (frame == 0)
error (no_sel_frame);
/* Going up is simple: just do get_prev_frame enough times
or until initial frame is reached. */
while (*level_offset_ptr > 0)
{
prev = get_prev_frame (frame);
if (prev == 0)
break;
(*level_offset_ptr)--;
frame = prev;
}
/* Going down could be done by iterating get_frame_info to
find the next frame, but that would be quadratic
since get_frame_info must scan all the way from the current frame.
The following algorithm is linear. */
if (*level_offset_ptr < 0)
{
/* First put frame1 at innermost frame
and frame2 N levels up from there. */
frame1 = get_current_frame ();
frame2 = frame1;
while (*level_offset_ptr < 0 && frame2 != frame)
{
frame2 = get_prev_frame (frame2);
(*level_offset_ptr) ++;
}
/* Then slide frame1 and frame2 up in synchrony
and when frame2 reaches our starting point
frame1 must be N levels down from there. */
while (frame2 != frame)
{
frame1 = get_prev_frame (frame1);
frame2 = get_prev_frame (frame2);
}
return frame1;
}
return frame;
}
/* The "frame" command. With no arg, print selected frame briefly.
With arg LEVEL_EXP, select the frame at level LEVEL if it is a
valid level. Otherwise, treat level_exp as an address expression
and print it. See parse_frame_specification for more info on proper
frame expressions. */
static void
frame_command (level_exp, from_tty)
char *level_exp;
int from_tty;
{
register FRAME frame, frame1;
unsigned int level = 0;
frame = parse_frame_specification (level_exp);
for (frame1 = get_prev_frame (0);
frame1 && frame1 != frame;
frame1 = get_prev_frame (frame1))
level++;
if (!frame1)
level = 0;
select_frame (frame, level);
if (!from_tty)
return;
print_stack_frame (selected_frame, selected_frame_level, 1);
}
/* Select the frame up one or COUNT stack levels
from the previously selected frame, and print it briefly. */
static void
up_command (count_exp)
char *count_exp;
{
register FRAME frame;
int count = 1, count1;
if (count_exp)
count = parse_and_eval_address (count_exp);
count1 = count;
frame = find_relative_frame (selected_frame, &count1);
if (count1 != 0 && count_exp == 0)
error ("Initial frame selected; you cannot go up.");
select_frame (frame, selected_frame_level + count - count1);
print_stack_frame (selected_frame, selected_frame_level, 1);
}
/* Select the frame down one or COUNT stack levels
from the previously selected frame, and print it briefly. */
static void
down_command (count_exp)
char *count_exp;
{
register FRAME frame;
int count = -1, count1;
if (count_exp)
count = - parse_and_eval_address (count_exp);
count1 = count;
frame = find_relative_frame (selected_frame, &count1);
if (count1 != 0 && count_exp == 0)
error ("Bottom (i.e., innermost) frame selected; you cannot go down.");
select_frame (frame, selected_frame_level + count - count1);
print_stack_frame (selected_frame, selected_frame_level, 1);
}
static void
return_command (retval_exp, from_tty)
char *retval_exp;
int from_tty;
{
struct symbol *thisfun = get_frame_function (selected_frame);
/* If interactive, require confirmation. */
if (from_tty)
{
if (thisfun != 0)
{
if (!query ("Make %s return now? ", SYMBOL_NAME (thisfun)))
error ("Not confirmed.");
}
else
if (!query ("Make selected stack frame return now? "))
error ("Not confirmed.");
}
/* Do the real work. Pop until the specified frame is current. */
while (selected_frame != get_current_frame ())
POP_FRAME;
/* Then pop that frame. */
POP_FRAME;
/* Compute the return value (if any) and store in the place
for return values. */
if (retval_exp)
set_return_value (parse_and_eval (retval_exp));
/* If interactive, print the frame that is now current. */
if (from_tty)
frame_command ("0", 1);
}
extern struct cmd_list_element *setlist;
void
_initialize_stack ()
{
#if 0
backtrace_limit = 30;
#endif
add_com ("return", class_stack, return_command,
"Make selected stack frame return to its caller.\n\
Control remains in the debugger, but when you continue\n\
execution will resume in the frame above the one now selected.\n\
If an argument is given, it is an expression for the value to return.");
add_com ("up", class_stack, up_command,
"Select and print stack frame that called this one.\n\
An argument says how many frames up to go.");
add_com ("down", class_stack, down_command,
"Select and print stack frame called by this one.\n\
An argument says how many frames down to go.");
add_com_alias ("do", "down", class_stack, 1);
add_com ("frame", class_stack, frame_command,
"Select and print a stack frame.\n\
With no argument, print the selected stack frame. (See also \"info frame\").\n\
An argument specifies the frame to select.\n\
It can be a stack frame number or the address of the frame.\n\
With argument, nothing is printed if input is coming from\n\
a command file or a user-defined command.");
add_com_alias ("f", "frame", class_stack, 1);
add_com ("backtrace", class_stack, backtrace_command,
"Print backtrace of all stack frames, or innermost COUNT frames.\n\
With a negative argument, print outermost -COUNT frames.");
add_com_alias ("bt", "backtrace", class_stack, 0);
add_com_alias ("where", "backtrace", class_alias, 0);
add_info ("stack", backtrace_command,
"Backtrace of the stack, or innermost COUNT frames.");
add_info_alias ("s", "stack", 1);
add_info ("frame", frame_info,
"All about selected stack frame, or frame at ADDR.");
add_info_alias ("f", "frame", 1);
add_info ("locals", locals_info,
"Local variables of current stack frame.");
add_info ("args", args_info,
"Argument variables of current stack frame.");
#if 0
add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command,
"Specify maximum number of frames for \"backtrace\" to print by default.",
&setlist);
add_info ("backtrace-limit", backtrace_limit_info,
"The maximum number of frames for \"backtrace\" to print by default.");
#endif
}
@
1.1
log
@Initial revision
@
text
@d2 1
a2 1
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
d27 2
d42 3
d64 4
d76 2
d162 1
a162 1
void flush_cached_frames ();
d212 2
d392 3
d489 3
a491 1
register struct block *block = get_frame_block (frame);
d510 2
d520 1
a520 1
struct symbol *func = get_frame_function (frame);
d526 1
d551 2
d610 2
@

View File

@ -1,726 +0,0 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
1.2
date 89.03.27.20.22.34; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.23.14.27.48; author gnu; state Exp;
branches ;
next ;
desc
@@
1.2
log
@Portability changes. If USG, we need to re-enable the SIGINT
signal handler when it is called. Also, build the sys_siglist
table at runtime, based on the actual values of the signal
#define's. Too many USG systems added Berkeley signal names
as various numbers.
@
text
@/* General utility routines for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include <stdio.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include "defs.h"
#include "param.h"
#ifdef HAVE_TERMIO
#include <termio.h>
#endif
void error ();
void fatal ();
/* Chain of cleanup actions established with make_cleanup,
to be executed if an error happens. */
static struct cleanup *cleanup_chain;
/* Nonzero means a quit has been requested. */
int quit_flag;
/* Nonzero means quit immediately if Control-C is typed now,
rather than waiting until QUIT is executed. */
int immediate_quit;
/* Add a new cleanup to the cleanup_chain,
and return the previous chain pointer
to be passed later to do_cleanups or discard_cleanups.
Args are FUNCTION to clean up with, and ARG to pass to it. */
struct cleanup *
make_cleanup (function, arg)
void (*function) ();
int arg;
{
register struct cleanup *new
= (struct cleanup *) xmalloc (sizeof (struct cleanup));
register struct cleanup *old_chain = cleanup_chain;
new->next = cleanup_chain;
new->function = function;
new->arg = arg;
cleanup_chain = new;
return old_chain;
}
/* Discard cleanups and do the actions they describe
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
do_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
(*ptr->function) (ptr->arg);
cleanup_chain = ptr->next;
free (ptr);
}
}
/* Discard cleanups, not doing the actions they describe,
until we get back to the point OLD_CHAIN in the cleanup_chain. */
void
discard_cleanups (old_chain)
register struct cleanup *old_chain;
{
register struct cleanup *ptr;
while ((ptr = cleanup_chain) != old_chain)
{
cleanup_chain = ptr->next;
free (ptr);
}
}
/* Set the cleanup_chain to 0, and return the old cleanup chain. */
struct cleanup *
save_cleanups ()
{
struct cleanup *old_chain = cleanup_chain;
cleanup_chain = 0;
return old_chain;
}
/* Restore the cleanup chain from a previously saved chain. */
void
restore_cleanups (chain)
struct cleanup *chain;
{
cleanup_chain = chain;
}
/* This function is useful for cleanups.
Do
foo = xmalloc (...);
old_chain = make_cleanup (free_current_contents, &foo);
to arrange to free the object thus allocated. */
void
free_current_contents (location)
char **location;
{
free (*location);
}
/* Generally useful subroutines used throughout the program. */
/* Like malloc but get error if no storage available. */
char *
xmalloc (size)
long size;
{
register char *val = (char *) malloc (size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Like realloc but get error if no storage available. */
char *
xrealloc (ptr, size)
char *ptr;
long size;
{
register char *val = (char *) realloc (ptr, size);
if (!val)
fatal ("virtual memory exhausted.", 0);
return val;
}
/* Print the system error message for errno, and also mention STRING
as the file name for which the error was encountered.
Then return to command level. */
void
perror_with_name (string)
char *string;
{
extern int sys_nerr;
extern char *sys_errlist[];
extern int errno;
char *err;
char *combined;
if (errno < sys_nerr)
err = sys_errlist[errno];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
error ("%s.", combined);
}
/* Print the system error message for ERRCODE, and also mention STRING
as the file name for which the error was encountered. */
void
print_sys_errmsg (string, errcode)
char *string;
int errcode;
{
extern int sys_nerr;
extern char *sys_errlist[];
char *err;
char *combined;
if (errcode < sys_nerr)
err = sys_errlist[errcode];
else
err = "unknown error";
combined = (char *) alloca (strlen (err) + strlen (string) + 3);
strcpy (combined, string);
strcat (combined, ": ");
strcat (combined, err);
printf ("%s.\n", combined);
}
void
quit ()
{
fflush (stdout);
#ifdef HAVE_TERMIO
ioctl (fileno (stdout), TCFLSH, 1);
#else /* not HAVE_TERMIO */
ioctl (fileno (stdout), TIOCFLUSH, 0);
#endif /* not HAVE_TERMIO */
#ifdef TIOCGPGRP
error ("Quit");
#else
error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
#endif /* TIOCGPGRP */
}
/* Control C comes here */
void
request_quit ()
{
quit_flag = 1;
#ifdef USG
/* Restore the signal handler */
signal(SIGINT, request_quit);
#endif
if (immediate_quit)
quit ();
}
/* Print an error message and return to command level.
STRING is the error message, used as a fprintf string,
and ARG is passed as an argument to it. */
void
error (string, arg1, arg2, arg3)
char *string;
int arg1, arg2, arg3;
{
fflush (stdout);
fprintf (stderr, string, arg1, arg2, arg3);
fprintf (stderr, "\n");
return_to_top_level ();
}
/* Print an error message and exit reporting failure.
This is for a error that we cannot continue from.
STRING and ARG are passed to fprintf. */
void
fatal (string, arg)
char *string;
int arg;
{
fprintf (stderr, "gdb: ");
fprintf (stderr, string, arg);
fprintf (stderr, "\n");
exit (1);
}
/* Make a copy of the string at PTR with SIZE characters
(and add a null character at the end in the copy).
Uses malloc to get the space. Returns the address of the copy. */
char *
savestring (ptr, size)
char *ptr;
int size;
{
register char *p = (char *) xmalloc (size + 1);
bcopy (ptr, p, size);
p[size] = 0;
return p;
}
char *
concat (s1, s2, s3)
char *s1, *s2, *s3;
{
register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
register char *val = (char *) xmalloc (len);
strcpy (val, s1);
strcat (val, s2);
strcat (val, s3);
return val;
}
void
print_spaces (n, file)
register int n;
register FILE *file;
{
while (n-- > 0)
fputc (' ', file);
}
/* Ask user a y-or-n question and return 1 iff answer is yes.
Takes three args which are given to printf to print the question.
The first, a control string, should end in "? ".
It should not say how to answer, because we do that. */
int
query (ctlstr, arg1, arg2)
char *ctlstr;
{
register int answer;
/* Automatically answer "yes" if input is not from a terminal. */
if (!input_from_terminal_p ())
return 1;
while (1)
{
printf (ctlstr, arg1, arg2);
printf ("(y or n) ");
fflush (stdout);
answer = fgetc (stdin);
clearerr (stdin); /* in case of C-d */
if (answer != '\n')
while (fgetc (stdin) != '\n') clearerr (stdin);
if (answer >= 'a')
answer -= 040;
if (answer == 'Y')
return 1;
if (answer == 'N')
return 0;
printf ("Please answer y or n.\n");
}
}
/* Parse a C escape sequence. STRING_PTR points to a variable
containing a pointer to the string to parse. That pointer
is updated past the characters we use. The value of the
escape sequence is returned.
A negative value means the sequence \ newline was seen,
which is supposed to be equivalent to nothing at all.
If \ is followed by a null character, we return a negative
value and leave the string pointer pointing at the null character.
If \ is followed by 000, we return 0 and leave the string pointer
after the zeros. A value of 0 does not mean end of string. */
int
parse_escape (string_ptr)
char **string_ptr;
{
register int c = *(*string_ptr)++;
switch (c)
{
case 'a':
return '\a';
case 'b':
return '\b';
case 'e':
return 033;
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case '\n':
return -2;
case 0:
(*string_ptr)--;
return 0;
case '^':
c = *(*string_ptr)++;
if (c == '\\')
c = parse_escape (string_ptr);
if (c == '?')
return 0177;
return (c & 0200) | (c & 037);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
register int i = c - '0';
register int count = 0;
while (++count < 3)
{
if ((c = *(*string_ptr)++) >= '0' && c <= '7')
{
i *= 8;
i += c - '0';
}
else
{
(*string_ptr)--;
break;
}
}
return i;
}
default:
return c;
}
}
/* Print the character CH on STREAM as part of the contents
of a literal string whose delimiter is QUOTER. */
void
printchar (ch, stream, quoter)
unsigned char ch;
FILE *stream;
int quoter;
{
register int c = ch;
if (c < 040 || c >= 0177)
{
if (c == '\n')
fprintf (stream, "\\n");
else if (c == '\b')
fprintf (stream, "\\b");
else if (c == '\t')
fprintf (stream, "\\t");
else if (c == '\f')
fprintf (stream, "\\f");
else if (c == '\r')
fprintf (stream, "\\r");
else if (c == 033)
fprintf (stream, "\\e");
else if (c == '\a')
fprintf (stream, "\\a");
else
fprintf (stream, "\\%03o", c);
}
else
{
if (c == '\\' || c == quoter)
fputc ('\\', stream);
fputc (c, stream);
}
}
#ifdef USG
bcopy (from, to, count)
char *from, *to;
{
memcpy (to, from, count);
}
bcmp (from, to, count)
{
return (memcmp (to, from, count));
}
bzero (to, count)
char *to;
{
while (count--)
*to++ = 0;
}
getwd (buf)
char *buf;
{
getcwd (buf, MAXPATHLEN);
}
char *
index (s, c)
char *s;
{
char *strchr ();
return strchr (s, c);
}
char *
rindex (s, c)
char *s;
{
char *strrchr ();
return strrchr (s, c);
}
/* Queue routines */
struct queue {
struct queue *forw;
struct queue *back;
};
insque (item, after)
struct queue *item;
struct queue *after;
{
item->forw = after->forw;
after->forw->back = item;
item->back = after;
after->forw = item;
}
remque (item)
struct queue *item;
{
item->forw->back = item->back;
item->back->forw = item->forw;
}
/*
* There is too much variation in Sys V signal numbers and names, so
* we must initialize them at runtime. If C provided a way to initialize
* an array based on subscript and value, this would not be necessary.
*/
static char undoc[] = "(undocumented)";
char *sys_siglist[NSIG];
_initialize_utils()
{
int i;
for (i = 0; i < NSIG; i++)
sys_siglist[i] = undoc;
#ifdef SIGHUP
sys_siglist[SIGHUP ] = "SIGHUP";
#endif
#ifdef SIGINT
sys_siglist[SIGINT ] = "SIGINT";
#endif
#ifdef SIGQUIT
sys_siglist[SIGQUIT ] = "SIGQUIT";
#endif
#ifdef SIGILL
sys_siglist[SIGILL ] = "SIGILL";
#endif
#ifdef SIGTRAP
sys_siglist[SIGTRAP ] = "SIGTRAP";
#endif
#ifdef SIGIOT
sys_siglist[SIGIOT ] = "SIGIOT";
#endif
#ifdef SIGEMT
sys_siglist[SIGEMT ] = "SIGEMT";
#endif
#ifdef SIGFPE
sys_siglist[SIGFPE ] = "SIGFPE";
#endif
#ifdef SIGKILL
sys_siglist[SIGKILL ] = "SIGKILL";
#endif
#ifdef SIGBUS
sys_siglist[SIGBUS ] = "SIGBUS";
#endif
#ifdef SIGSEGV
sys_siglist[SIGSEGV ] = "SIGSEGV";
#endif
#ifdef SIGSYS
sys_siglist[SIGSYS ] = "SIGSYS";
#endif
#ifdef SIGPIPE
sys_siglist[SIGPIPE ] = "SIGPIPE";
#endif
#ifdef SIGALRM
sys_siglist[SIGALRM ] = "SIGALRM";
#endif
#ifdef SIGTERM
sys_siglist[SIGTERM ] = "SIGTERM";
#endif
#ifdef SIGUSR1
sys_siglist[SIGUSR1 ] = "SIGUSR1";
#endif
#ifdef SIGUSR2
sys_siglist[SIGUSR2 ] = "SIGUSR2";
#endif
#ifdef SIGCLD
sys_siglist[SIGCLD ] = "SIGCLD";
#endif
#ifdef SIGCHLD
sys_siglist[SIGCHLD ] = "SIGCHLD";
#endif
#ifdef SIGPWR
sys_siglist[SIGPWR ] = "SIGPWR";
#endif
#ifdef SIGTSTP
sys_siglist[SIGTSTP ] = "SIGTSTP";
#endif
#ifdef SIGTTIN
sys_siglist[SIGTTIN ] = "SIGTTIN";
#endif
#ifdef SIGTTOU
sys_siglist[SIGTTOU ] = "SIGTTOU";
#endif
#ifdef SIGSTOP
sys_siglist[SIGSTOP ] = "SIGSTOP";
#endif
#ifdef SIGXCPU
sys_siglist[SIGXCPU ] = "SIGXCPU";
#endif
#ifdef SIGXFSZ
sys_siglist[SIGXFSZ ] = "SIGXFSZ";
#endif
#ifdef SIGVTALRM
sys_siglist[SIGVTALRM ] = "SIGVTALRM";
#endif
#ifdef SIGPROF
sys_siglist[SIGPROF ] = "SIGPROF";
#endif
#ifdef SIGWINCH
sys_siglist[SIGWINCH ] = "SIGWINCH";
#endif
#ifdef SIGCONT
sys_siglist[SIGCONT ] = "SIGCONT";
#endif
#ifdef SIGURG
sys_siglist[SIGURG ] = "SIGURG";
#endif
#ifdef SIGIO
sys_siglist[SIGIO ] = "SIGIO";
#endif
#ifdef SIGWIND
sys_siglist[SIGWIND ] = "SIGWIND";
#endif
#ifdef SIGPHONE
sys_siglist[SIGPHONE ] = "SIGPHONE";
#endif
#ifdef SIGPOLL
sys_siglist[SIGPOLL ] = "SIGPOLL";
#endif
}
#endif /* USG */
@
1.1
log
@Initial revision
@
text
@d223 1
d237 6
a506 26
char *sys_siglist[32] = {
"SIG0",
"SIGHUP",
"SIGINT",
"SIGQUIT",
"SIGILL",
"SIGTRAP",
"SIGIOT",
"SIGEMT",
"SIGFPE",
"SIGKILL",
"SIGBUS",
"SIGSEGV",
"SIGSYS",
"SIGPIPE",
"SIGALRM",
"SIGTERM",
"SIGUSR1",
"SIGUSR2",
"SIGCLD",
"SIGPWR",
"SIGWIND",
"SIGPHONE",
"SIGPOLL",
};
d530 124
@

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,127 @@
This is GDB, a source-level debugger intended for GNU,
presently running under un*x.
This is GDB, the GNU source-level debugger, presently running under un*x.
Before compiling GDB, you must set up links to five files according to
the kind of machine you are running on. To do this, type `config.gdb
machine', where machine is something like `vax' or `sun2'. This
creates links named `param.h', `opcode.h', `pinsn.c', and `infdep.c'.
Before compiling GDB, you must tell GDB what kind of machine you are
running on. To do this, type `config.gdb machine', where machine is
something like `vax' or `sun2'. For a list of valid machine types,
type `config.gdb'.
Normally config.gdb edits the makefile as necessary. If you have to
edit the makefile on a standard machine listed in config.gdb this
should be considered a bug and reported as such.
Once these files are set up, just `make' will do everything,
producing an executable `gdb' in this directory.
If you want a new (current to this release) version of the manual, you
will have to use the gdb.texinfo file provided with this distribution.
The gdb.texinfo file requires the texinfo-format-buffer command from
emacs 18.55 or later.
About languages other than C...
C++ support has been integrated into gdb. GDB should work with Pascal
and FORTRAN programs, but I am not aware of anyone who is working on
getting it to use the syntax of any language other than C or C++.
About -gg format...
Currently GDB version 3.x does *not* support GCC's -gg format. This
is because it is (in theory) has fast enough startup on dbx debugging
format object files that -gg format is unnecessary (and hence
undesirable, since it wastes space and processing power in gcc). I
would like to hear people's opinions on the amount of time currently
spent in startup; is it fast enough?
About remote debugging...
The two files remote-multi.shar and remote-sa.m68k.shar contain two
examples of a remote stub to be used with remote.c. The the -multi
file is a general stub that can probably be running on various
different flavors of unix to allow debugging over a serial line from
one machine to another. The remote-sa.m68k.shar is designed to run
standalone on a 68k type cpu and communicate properley with the
remote.c stub over a serial line.
About reporting bugs...
The correct address for reporting bugs found with gdb is
"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
About xgdb...
xgdb.c was provided to us by the user community; it is not an integral
part of the gdb distribution. The problem of providing visual
debugging support on top of gdb is peripheral to the GNU project and
(at least right now) we can't afford to put time into it. So while we
will be happy to incorporate user fixes to xgdb.c, we do not guarantee
that it will work and we will not fix bugs reported in it. Someone is
working on writing a new XGDB, so improving (e.g. by fixing it so that
it will work, if it doesn't currently) the current one is not worth it.
For those intersted in auto display of source and the availability of
an editor while debugging I suggest trying gdb-mode in gnu-emacs.
Comments on this mode are welcome.
About the machine-dependent files...
m-<machine>.h
m-<machine>.h (param.h is a link to this file).
This file contains macro definitions that express information
about the machine's registers, stack frame format and instructions.
<machine>-opcode.h, <machine>-pinsn.c
<machine>-opcode.h (opcode.h is a link to this file).
<machine>-pinsn.c (pinsn.c is a link to this file).
These files contain the information necessary to print instructions
for your cpu type.
<machine>-dep.c
<machine>-dep.c (dep.c is a link to this file).
Those routines which provide a low level interface to ptrace and which
tend to be machine-dependent. (The machine-independent routines are in
`infrun.c' and `inflow.c')
About writing code for GDB...
We appreciate having users contribute code that is of general use, but
for it to be included in future GDB releases it must be cleanly
written. We do not want to include changes that will needlessly make future
maintainance difficult. It is not much harder to do things right, and
in the long term it is worth it to the GNU project, and probably to
you individually as well.
Please code according to the GNU coding standards. If you do not have
a copy, you can request one by sending mail to gnu@prep.ai.mit.edu.
Please try to avoid making machine-specific changes to
machine-independent files (i.e. all files except "param.h" and
"dep.c". "pinsn.c" and "opcode.h" are processor-specific but not
operating system-dependent). If this is unavoidable, put a hook in
the machine-independent file which calls a (possibly)
machine-dependent macro (for example, the IGNORE_SYMBOL macro can be
used for any symbols which need to be ignored on a specific machine.
Calling IGNORE_SYMBOL in dbxread.c is a lot cleaner than a maze of
#if defined's). The machine-independent code should do whatever "most"
machines want if the macro is not defined in param.h. Using #if defined
can sometimes be OK (e.g. SET_STACK_LIMIT_HUGE) but should usually be
conditionalized on a specific feature of an operating system (set in
param.h) rather than something like #if defined(vax) or #if defined(SYSV).
It is better to replace entire routines which may be system-specific,
rather than put in a whole bunch of hooks which are probably not going
to be helpful for any purpose other than your changes. For example,
if you want to modify dbxread.c to deal with DBX debugging symbols
which are in COFF files rather than a.out files, do something
along the lines of a macro GET_NEXT_SYMBOL, which could have
different definitions for COFF and a.out, rather than trying to put
the necessary changes throughout all the code in dbxread.c that
currently assumes a.out format.
Please avoid duplicating code. For example, if something needs to be
changed in read_inferior_memory, it is very painful because there is a
copy in every dep.c file. The correct way to do this is to put the
standard ptrace interfaces in a separate file ptrace.c, which is used
by all systems which have ptrace. ptrace.c would deal with variations
between systems the same way any system-independent file would (hooks,
#if defined, etc.).
About debugging gdb with itself...
You probably want to do a "make TAGS" after you configure your
@ -41,27 +138,3 @@ The "info" command, when executed without a subcommand in a gdb being
debugged by gdb, will pop you back up to the top level gdb. See
.gdbinit for more details.
About languages other than C...
C++ support has been integrated into gdb; it works, but somewhat
buggily. Pascal support has not yet been integrated in gdb; the work
is being done.
About reporting bugs...
The correct address for reporting bugs found with gdb is
"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
About xgdb...
xgdb.c was provided to us by the user community; it is not an integral
part of the gdb distribution. The problem of providing visual
debugging support on top of gdb is peripheral to the GNU project and
(at least right now) we can't afford to put time into it. So while we
will be happy to incorporate user fixes to xgdb.c, we do not guarantee
that it will work and we will not fix bugs reported in it.
For those intersted in auto display of source and the availability of
an editor while debugging I suggest trying gdb-mode in gnu-emacs.
Comments on this mode are welcome.

2089
gdb/TAGS Normal file

File diff suppressed because it is too large Load Diff

57
gdb/XGDB-README Normal file
View File

@ -0,0 +1,57 @@
XGDB is an attempt at a graphical interface from GDB to X windows.
Its source code is in xgdb.c. The decision of whether to include this
file is made at *link time*; compile-time conditionals for xgdb are not
allowed. See the Makefile.
The current version does run with X11R2 but does not completely work.
For one thing it encounters an apparent bug in the predefined widget
used to display source files. This bug (which I have reported) causes
parts of the source-code display to appear blank.
But XGDB has bugs also. I suspect that xgdb_display_source passes the
wrong line-number arguments to that widget and it may work in an
overcomplicated manner. Also, at a deeper level, it does not handle
X-events while either the inferior or a command is running. This
certainly means that the window won't refresh at such times. It's
possible that events also fail to be handled at other times, such as
after a button has been clicked, and if so this would account for some
of the failure to display the source text fully.
I think that someone who really understands the X toolkit ought to write
something which will handle events asynchronously.
The user interface currently implemented is not very convenient to
use. For example, it is necessary to move the mouse back and forth
often between the XGDB window and the window where XGDB's text I/O is
done. XGDB should arrange to receive keyboard input via the XGDB
window so the mouse can be left there all the time. These chars may
need to be echoed explicitly and stuffed into the keyboard buffer so
they intermix properly with those typed in the text I/O window.
Is it worth while to have several buttons that simply use the
selection as keyboard input with a few extra characters before and
after? Perhaps it would be better to have just one button (or a mouse
click) to use the selection as text input, since this would work in
any GDB command. You would first type the command yourself, then use
the selection as input, then type RET yourself. If this is done with
a mouse click, and if keyboard input is allowed through the XGDB
window, then all this can be done with no extra mouse motion.
There needs to be a command to find out the line number of the
selected line (or it should be displayed all the time); otherwise how
do you use the "jump" command, or go to the editor and find that line
easily? Alternatively there should be buttons for these two things.
Some of the buttons' meanings aren't evident. For example, how does
"Brk in" differ from "Brk at"? What is "print *"? I intuitively
expected to click on a button and then select what it should apply to,
and I was surprised to find that one must do it in the other order.
There should be a "Help" button which displays a screen which explains
all the features of the graphical interface, and perhaps an "Info"
button which runs the info program to display the on-line GDB manual.
I would suggest that someone look at other graphical debuggers
(including Sun's dbxtool) and consider how to change the interface to
be easier to use in practice.
-- RMS

View File

@ -1,7 +1,22 @@
/* Another try at encapsulating bsd object files in coff.
Copyright (C) 1988, 1989, Free Software Foundation, Inc.
Written by Pace Willisson 12/9/88
This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* another try at encapsulating bsd object files in coff
* by Pace Willisson 12/9/88
*
* This time, we will only use the coff headers to tell the kernel
* how to exec the file. Therefore, the only fields that need to
* be filled in are the scnptr and vaddr for the text and data
@ -65,8 +80,11 @@ struct coffheader
#ifdef i386
#define COFF_MAGIC 0514 /* I386MAGIC */
#endif
#ifdef m68k
#define COFF_MAGIC 0520 /* MC68MAGIC */
#endif
#if defined(i386)
#ifdef COFF_MAGIC
short __header_offset_temp;
#define HEADER_OFFSET(f) \
(__header_offset_temp = 0, \
@ -104,8 +122,8 @@ short __header_offset_temp;
#define N_TXTADDR(x) \
((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
sizeof (struct coffheader) + sizeof (struct exec) : 0)
#define SEGMENT_SIZE 0x400000
#define N_DATADDR(x) \
((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
(SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \

View File

@ -58,6 +58,10 @@ enum machine_type {
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#define _N_BADMAG(x) \
(N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC)
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
#define N_TXTOFF(x) \
@ -82,9 +86,16 @@ enum machine_type {
#ifdef vax
#define SEGMENT_SIZE page_size
#endif
#ifdef sony
#define SEGMENT_SIZE 0x2000
#endif /* Sony. */
#ifdef is68k
#define SEGMENT_SIZE 0x20000
#endif
#if defined(m68k) && defined(PORTAR)
#define PAGE_SIZE 0x400
#define SEGMENT_SIZE PAGE_SIZE
#endif
#ifndef N_DATADDR
#define N_DATADDR(x) \
@ -101,10 +112,10 @@ struct nlist {
struct nlist *n_next;
long n_strx;
} n_un;
char n_type;
unsigned char n_type;
char n_other;
short n_desc;
unsigned n_value;
unsigned long n_value;
};
#define N_UNDF 0

Binary file not shown.

View File

@ -1,59 +1,22 @@
head 1.4;
access ;
symbols ;
locks ; strict;
comment @ * @;
/* Low level interface to ptrace, for GDB when running under m68k SVR2 Unix
on Altos 3068. Report bugs to Jyrki Kuoppala <jkp@cs.hut.fi>
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
1.4
date 89.03.27.20.08.50; author gnu; state Exp;
branches ;
next 1.3;
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
1.3
date 89.03.27.20.07.47; author gnu; state Exp;
branches ;
next 1.2;
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
1.2
date 89.03.27.18.49.06; author gnu; state Exp;
branches ;
next 1.1;
1.1
date 89.03.20.19.47.11; author gnu; state Exp;
branches ;
next ;
desc
@@
1.4
log
@Restore A/UX-specific changes.
@
text
@/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1988 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -64,25 +27,19 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/types.h>
#endif
#ifdef UNISOFT_ASSHOLES
#define PMMU
#define NEW_PMMU
#define mc68881 /* Needed to get float in user.h!!! */
#include <sys/seg.h> /* For user.h */
#include <sys/mmu.h>
#include <sys/time.h>
/* Things Unisoft defined differently from every other Unix system */
#define NBPG PAGESIZE
#define UPAGES USIZE
#define KERNEL_U_ADDR UDOT
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef USG
#include <sys/page.h>
#ifdef ALTOS
#include <sys/net.h>
#include <errno.h>
#endif
#endif
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
@ -93,7 +50,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
#endif
#include <sys/user.h> /* After a.out.h */
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include <sys/stat.h>
@ -101,28 +58,12 @@ extern int errno;
/* This function simply calls ptrace with the given arguments.
It exists so that all calls to ptrace are isolated in this
machine-dependent file.
If you are having trouble debugging ptrace calls, turn on DEBUG
and every call to ptrace, in this module or elsewhere, will be
logged to stderr. */
machine-dependent file. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
#ifdef DEBUG
int result;
fprintf(stderr, "ptrace(%x,,%x, %x) = ", request, arg3, arg4);
result=ptrace (request, pid, arg3, arg4);
fprintf(stderr, "%x\n", result);
return result;
#define ptrace call_ptrace
#else
return ptrace (request, pid, arg3, arg4);
#endif
}
kill_inferior ()
@ -177,7 +118,7 @@ fetch_inferior_registers ()
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
unsigned int offset = (char *) &u.u_state - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
for (regno = 0; regno < NUM_REGS; regno++)
@ -203,20 +144,14 @@ store_inferior_registers (regno)
char buf[80];
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
unsigned int offset = (char *) &u.u_state - (char *) &u;
offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
errno = 0;
#ifdef UNISOFT_ASSHOLES
/* You can't write the PC with ptrace 6, only with ptrace 11! */
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
@ -227,12 +162,7 @@ store_inferior_registers (regno)
{
regaddr = register_addr (regno, offset);
errno = 0;
#ifdef UNISOFT_ASSHOLES
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
@ -341,11 +271,6 @@ write_inferior_memory (memaddr, myaddr, len)
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
@ -362,8 +287,10 @@ write_inferior_memory (memaddr, myaddr, len)
#endif
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -467,6 +394,9 @@ core_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
@ -476,26 +406,32 @@ core_file_command (filename, from_tty)
{
struct user u;
int reg_offset;
unsigned int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
data_start = exec_data_start;
#define NBPG NBPP
#define UPAGES USIZE
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here; Unisoft
seems to put the offset in the upage of the regs. Sigh. */
reg_offset = (int) u.u_ar0;
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_state;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
bcopy (&u.u_exdata, &core_aouthdr, sizeof (AOUTHDR));
printf ("Core file is from \"%s\".\n", u.u_comm);
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
@ -511,12 +447,17 @@ core_file_command (filename, from_tty)
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0)
perror_with_name (reg_names[regno]);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (reg_names[regno])
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, reg_names[regno]);
perror_with_name (buffer);
}
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (reg_names[regno]);
supply_register (regno, buf);
}
}
@ -563,6 +504,9 @@ exec_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
@ -636,96 +580,4 @@ exec_file_command (filename, from_tty)
if (exec_file_display_hook)
(*exec_file_display_hook) (filename);
}
@
1.3
log
@Remove A/UX-specific changes for shipping to FSF.
@
text
@d30 13
d176 7
a182 1
ptrace (6, inferior_pid, regaddr, read_register (regno));
d193 6
a198 1
ptrace (6, inferior_pid, regaddr, read_register (regno));
@
1.2
log
@A/UX and USG changes, and a little better error reporting.
@
text
@a29 13
#ifdef UNISOFT_ASSHOLES
#define PMMU
#define NEW_PMMU
#define mc68881 /* Needed to get float in user.h!!! */
#include <sys/seg.h> /* For user.h */
#include <sys/mmu.h>
#include <sys/time.h>
/* Things Unisoft defined differently from every other Unix system */
#define NBPG PAGESIZE
#define UPAGES USIZE
#define KERNEL_U_ADDR UDOT
#endif
d163 1
a163 7
#ifdef UNISOFT_ASSHOLES
/* You can't write the PC with ptrace 6, only with ptrace 11! */
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
d174 1
a174 6
#ifdef UNISOFT_ASSHOLES
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
@
1.1
log
@Initial revision
@
text
@d30 13
a46 1
#include <sys/user.h>
d58 2
d67 5
a71 1
machine-dependent file. */
d76 11
d88 1
d176 7
a182 1
ptrace (6, inferior_pid, regaddr, read_register (regno));
d193 6
a198 1
ptrace (6, inferior_pid, regaddr, read_register (regno));
d201 1
a201 1
sprintf (buf, "writing register number %d", regno);
d446 3
a448 1
perror_with_name (filename);
d455 6
a460 1
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
d478 1
a478 1
perror_with_name (filename);
d482 1
a482 1
perror_with_name (filename);
@

View File

@ -1,35 +1,48 @@
/* Get info from stack frames;
convert between frames, blocks, functions and pc values.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
#include "symtab.h"
#include "frame.h"
/* Address of end of first object file.
#include <obstack.h>
/* Start and end of object file containing the entry point.
STARTUP_FILE_END is the first address of the next file.
This file is assumed to be a startup file
and frames with pc's inside it
are treated as nonexistent. */
are treated as nonexistent.
CORE_ADDR first_object_file_end;
Setting these variables is necessary so that backtraces do not fly off
the bottom of the stack. */
CORE_ADDR startup_file_start;
CORE_ADDR startup_file_end;
/* Is ADDR outside the startup file? */
int
outside_startup_file (addr)
CORE_ADDR addr;
{
return !(addr >= startup_file_start && addr < startup_file_end);
}
/* Address of innermost stack frame (contents of FP register) */
@ -100,6 +113,18 @@ get_prev_frame (frame)
return get_prev_frame_info (frame);
}
/* Return the frame that FRAME calls (0 if FRAME is the innermost
frame). */
FRAME
get_next_frame (frame)
FRAME frame;
{
/* We're allowed to know that FRAME and "struct frame_info *" are
the same */
return frame->next;
}
/*
* Flush the entire frame cache.
*/
@ -109,7 +134,7 @@ flush_cached_frames ()
/* Since we can't really be sure what the first object allocated was */
obstack_free (&frame_cache_obstack, 0);
obstack_init (&frame_cache_obstack);
current_frame = (struct frame_info *) 0; /* Invalidate cache */
}
@ -127,6 +152,33 @@ get_frame_info (frame)
return frame;
}
/* If a machine allows frameless functions, it should define a macro
FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct
frame_info for the frame, and FRAMELESS should be set to nonzero
if it represents a frameless function invocation. */
/* Many machines which allow frameless functions can detect them using
this macro. Such machines should define FRAMELESS_FUNCTION_INVOCATION
to just call this macro. */
#define FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS) \
{ \
CORE_ADDR func_start, after_prologue; \
func_start = (get_pc_function_start ((FI)->pc) + \
FUNCTION_START_OFFSET); \
if (func_start) \
{ \
after_prologue = func_start; \
SKIP_PROLOGUE (after_prologue); \
(FRAMELESS) = (after_prologue == func_start); \
} \
else \
/* If we can't find the start of the function, we don't really */ \
/* know whether the function is frameless, but we should be */ \
/* able to get a reasonable (i.e. best we can do under the */ \
/* circumstances) backtrace by saying that it isn't. */ \
(FRAMELESS) = 0; \
}
/* Return a structure containing various interesting information
about the frame that called NEXT_FRAME. */
@ -138,16 +190,6 @@ get_prev_frame_info (next_frame)
struct frame_info *prev;
int fromleaf = 0;
/* If we are within "start" right now, don't go any higher. */
/* This truncates stack traces of things at sigtramp() though,
because sigtramp() doesn't have a normal return PC, it has
garbage or a small value (seen: 3) in the return PC slot.
It's VITAL to see where the signal occurred, so punt this. */
#if 0
if (next_frame && next_frame->pc < first_object_file_end)
return 0;
#endif
/* If the requested entry is in the cache, return it.
Otherwise, figure out what the address should be for the entry
we're about to add to the cache. */
@ -155,61 +197,58 @@ get_prev_frame_info (next_frame)
if (!next_frame)
{
if (!current_frame)
error ("No frame is currently selected.");
{
if (!have_inferior_p () && !have_core_file_p ())
fatal ("get_prev_frame_info: Called before cache primed. \"Shouldn't happen.\"");
else
error ("No inferior or core file.");
}
return current_frame;
}
else
/* If we have the prev one, return it */
if (next_frame->prev)
return next_frame->prev;
/* On some machines it is possible to call a function without
setting up a stack frame for it. On these machines, we
define this macro to take two args; a frameinfo pointer
identifying a frame and a variable to set or clear if it is
or isn't leafless. */
#ifdef FRAMELESS_FUNCTION_INVOCATION
/* Still don't want to worry about this except on the innermost
frame. This macro will set FROMLEAF if NEXT_FRAME is a
frameless function invocation. */
if (!(next_frame->next))
{
/* If we have the prev one, return it */
if (next_frame->prev)
return next_frame->prev;
/* There is a questionable, but probably always correct
assumption being made here. The assumption is that if
functions on a specific machine has a FUNCTION_START_OFFSET,
then this is used by the function call instruction for some
purpose. If the function call instruction has this much hair
in it, it probably also sets up the frame pointer
automatically (ie. we'll never have what I am calling a
"leaf node", one which shares a frame pointer with it's
calling function). This is true on a vax. The only other
way to find this out would be to setup a seperate macro
"FUNCTION_HAS_FRAME_POINTER", which would often be equivalent
to SKIP_PROLOGUE modifying a pc value. */
#if FUNCTION_START_OFFSET == 0
if (!(next_frame->next))
{
/* Innermost */
CORE_ADDR func_start, after_prologue;
func_start = (get_pc_function_start (next_frame->pc) +
FUNCTION_START_OFFSET);
after_prologue = func_start;
SKIP_PROLOGUE (after_prologue);
if (after_prologue == func_start)
{
fromleaf = 1;
address = next_frame->frame;
}
}
FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
if (fromleaf)
address = next_frame->frame;
}
#endif
if (!fromleaf)
{
/* Two macros defined in param.h specify the machine-dependent
actions to be performed here. */
/* First, get the frame's chain-pointer.
If that is zero, the frame is the outermost frame. */
address = FRAME_CHAIN (next_frame);
if (!FRAME_CHAIN_VALID (address, next_frame))
return 0;
if (!fromleaf)
{
/* Two macros defined in param.h specify the machine-dependent
actions to be performed here.
First, get the frame's chain-pointer.
If that is zero, the frame is the outermost frame or a leaf
called by the outermost frame. This means that if start
calls main without a frame, we'll return 0 (which is fine
anyway).
/* If frame has a caller, combine the chain pointer and
the frame's own address to get the address of the caller. */
address = FRAME_CHAIN_COMBINE (address, next_frame);
}
Nope; there's a problem. This also returns when the current
routine is a leaf of main. This is unacceptable. We move
this to after the ffi test; I'd rather have backtraces from
start go curfluy than have an abort called from main not show
main. */
address = FRAME_CHAIN (next_frame);
if (!FRAME_CHAIN_VALID (address, next_frame))
return 0;
/* If this frame is a leaf, this will be superceeded by the
code below. */
address = FRAME_CHAIN_COMBINE (address, next_frame);
}
prev = (struct frame_info *)
@ -252,102 +291,7 @@ get_frame_saved_regs (frame_info_addr, saved_regs_addr)
struct frame_info *frame_info_addr;
struct frame_saved_regs *saved_regs_addr;
{
#if 1
FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
#else
{
register int regnum;
register int regmask;
register CORE_ADDR next_addr;
register CORE_ADDR pc;
int nextinsn;
bzero (&*saved_regs_addr, sizeof *saved_regs_addr);
if ((frame_info_addr)->pc >= ((frame_info_addr)->frame
- CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4)
&& (frame_info_addr)->pc <= (frame_info_addr)->frame)
{
next_addr = (frame_info_addr)->frame;
pc = (frame_info_addr)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4;
}
else
{
pc = get_pc_function_start ((frame_info_addr)->pc);
/* Verify we have a link a6 instruction next;
if not we lose. If we win, find the address above the saved
regs using the amount of storage from the link instruction. */
if (044016 == read_memory_integer (pc, 2))
{
next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 4);
pc += 4;
}
else if (047126 == read_memory_integer (pc, 2))
{
next_addr = (frame_info_addr)->frame + read_memory_integer (pc += 2, 2);
pc+=2;
}
else goto lose;
/* If have an addal #-n, sp next, adjust next_addr. */
if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
{
next_addr += read_memory_integer (pc += 2, 4);
pc += 4;
}
}
/* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
regmask = read_memory_integer (pc + 2, 2);
/* But before that can come an fmovem. Check for it. */
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf227 == nextinsn
&& (regmask & 0xff00) == 0xe000)
{
pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
for (regnum = FP0_REGNUM + 7;
regnum >= FP0_REGNUM;
regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr -= 12);
regmask = read_memory_integer (pc + 2, 2);
}
if (0044327 == read_memory_integer (pc, 2))
{
pc += 4; /* Regmask's low bit is for register 0, the first written */
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr += 4) - 4;
}
else if (0044347 == read_memory_integer (pc, 2))
{ pc += 4; /* Regmask's low bit is for register 15, the first pushed */
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr -= 4); }
else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
(*saved_regs_addr).regs[regnum] = (next_addr -= 4); }
/* fmovemx to index of sp may follow. */
regmask = read_memory_integer (pc + 2, 2);
nextinsn = 0xffff & read_memory_integer (pc, 2);
if (0xf236 == nextinsn
&& (regmask & 0xff00) == 0xf000)
{
pc += 10; /* Regmask's low bit is for register fp0, the first written */
for (regnum = FP0_REGNUM + 7;
regnum >= FP0_REGNUM;
regnum--, regmask >>= 1)
if (regmask & 1)
(*saved_regs_addr).regs[regnum] = (next_addr += 12) - 12;
regmask = read_memory_integer (pc + 2, 2);
}
/* clrw -(sp); movw ccr,-(sp) may follow. */
if (0x426742e7 == read_memory_integer (pc, 4))
(*saved_regs_addr).regs[PS_REGNUM] = (next_addr -= 4);
lose: ;
(*saved_regs_addr).regs[SP_REGNUM] = (frame_info_addr)->frame + 8;
(*saved_regs_addr).regs[FP_REGNUM] = (frame_info_addr)->frame;
(*saved_regs_addr).regs[PC_REGNUM] = (frame_info_addr)->frame + 4;
}
#endif
}
/* Return the innermost lexical block in execution
@ -430,6 +374,8 @@ block_for_pc (pc)
if (ps->textlow <= pc
&& ps->texthigh > pc)
{
if (ps->readin)
fatal ("Internal error: pc found in readin psymtab and not in any symtab.");
s = psymtab_to_symtab (ps);
bl = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bl, 0);
@ -482,6 +428,91 @@ find_pc_function (pc)
return block_function (b);
}
/* Finds the "function" (text symbol) that is smaller than PC
but greatest of all of the potential text symbols. Sets
*NAME and/or *ADDRESS conditionally if that pointer is non-zero.
Returns 0 if it couldn't find anything, 1 if it did. */
int
find_pc_partial_function (pc, name, address)
CORE_ADDR pc;
char **name;
CORE_ADDR *address;
{
struct partial_symtab *pst = find_pc_psymtab (pc);
struct symbol *f;
int miscfunc;
struct partial_symbol *psb;
if (pst)
{
if (pst->readin)
{
/* The information we want has already been read in.
We can go to the already readin symbols and we'll get
the best possible answer. */
f = find_pc_function (pc);
if (!f)
{
/* No availible symbol. */
if (name != 0)
*name = 0;
if (address != 0)
*address = 0;
return 0;
}
if (name)
*name = SYMBOL_NAME (f);
if (address)
*address = SYMBOL_VALUE (f);
}
/* Get the information from a combination of the pst
(static symbols), and the misc function vector (extern
symbols). */
miscfunc = find_pc_misc_function (pc);
psb = find_pc_psymbol (pst, pc);
if (!psb && miscfunc == -1)
{
if (address != 0)
*address = 0;
if (name != 0)
*name = 0;
return 0;
}
if (!psb
|| (miscfunc != -1
&& SYMBOL_VALUE(psb) < misc_function_vector[miscfunc].address))
{
if (address)
*address = misc_function_vector[miscfunc].address;
if (name)
*name = misc_function_vector[miscfunc].name;
}
else
{
if (address)
*address = SYMBOL_VALUE (psb);
if (name)
*name = SYMBOL_NAME (psb);
}
}
else
/* Must be in the misc function stuff. */
{
miscfunc = find_pc_misc_function (pc);
if (miscfunc == -1)
return 0;
if (address)
*address = misc_function_vector[miscfunc].address;
if (name)
*name = misc_function_vector[miscfunc].name;
}
return 1;
}
/* Find the misc function whose address is the largest
while being less than PC. Return its index in misc_function_vector.
Returns -1 if PC is not in suitable range. */
@ -496,6 +527,8 @@ find_pc_misc_function (pc)
register int distance;
/* Note that the last thing in the vector is always _etext. */
/* Actually, "end", now that non-functions
go on the misc_function_vector. */
/* Above statement is not *always* true - fix for case where there are */
/* no misc functions at all (ie no symbol table has been read). */
@ -506,6 +539,11 @@ find_pc_misc_function (pc)
pc > misc_function_vector[hi].address)
return -1;
/* Note that the following search will not return hi if
pc == misc_function_vector[hi].address. If "end" points to the
first unused location, this is correct and the above test
simply needs to be changed to
"pc >= misc_function_vector[hi].address". */
do {
new = (lo + hi) >> 1;
distance = misc_function_vector[new].address - pc;

View File

@ -1,22 +1,21 @@
/* Everything about breakpoints, for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -107,6 +106,9 @@ struct command_line *breakpoint_commands;
static void delete_breakpoint ();
void clear_momentary_breakpoints ();
void breakpoint_auto_delete ();
/* Flag indicating extra verbosity for xgdb. */
extern int xgdb_verbose;
/* condition N EXP -- set break condition of breakpoint N to EXP. */
@ -125,6 +127,9 @@ condition_command (arg, from_tty)
p = arg;
while (*p >= '0' && *p <= '9') p++;
if (p == arg)
/* There is no number here. (e.g. "cond a == b"). */
error_no_arg ("breakpoint number");
bnum = atoi (arg);
ALL_BREAKPOINTS (b)
@ -376,6 +381,9 @@ breakpoint_stop_status (pc, frame_address)
int value_zero;
if (b->cond)
{
/* Need to select the frame, with all that implies
so that the conditions will have the right context. */
select_frame (get_current_frame (), 0);
value_zero
= catch_errors (breakpoint_cond_eval, b->cond,
"Error occurred in testing breakpoint condition.");
@ -420,12 +428,12 @@ breakpoint_1 (bnum)
register struct breakpoint *b;
register struct command_line *l;
register struct symbol *sym;
CORE_ADDR last_addr = -1;
CORE_ADDR last_addr = (CORE_ADDR)-1;
ALL_BREAKPOINTS (b)
if (bnum == -1 || bnum == b->number)
{
printf ("#%-3d %c 0x%08x ", b->number,
printf_filtered ("#%-3d %c 0x%08x ", b->number,
"nyod"[(int) b->enable],
b->address);
last_addr = b->address;
@ -433,32 +441,48 @@ breakpoint_1 (bnum)
{
sym = find_pc_function (b->address);
if (sym)
printf (" in %s (%s line %d)", SYMBOL_NAME (sym),
b->symtab->filename, b->line_number);
printf_filtered (" in %s (%s line %d)", SYMBOL_NAME (sym),
b->symtab->filename, b->line_number);
else
printf ("%s line %d", b->symtab->filename, b->line_number);
printf_filtered ("%s line %d", b->symtab->filename, b->line_number);
}
printf ("\n");
else
{
char *name;
int addr;
if (find_pc_partial_function (b->address, &name, &addr))
{
if (b->address - addr)
printf_filtered ("<%s+%d>", name, b->address - addr);
else
printf_filtered ("<%s>", name);
}
}
printf_filtered ("\n");
if (b->ignore_count)
printf ("\tignore next %d hits\n", b->ignore_count);
printf_filtered ("\tignore next %d hits\n", b->ignore_count);
if (b->frame)
printf ("\tstop only in stack frame at 0x%x\n", b->frame);
printf_filtered ("\tstop only in stack frame at 0x%x\n", b->frame);
if (b->cond)
{
printf ("\tbreak only if ");
printf_filtered ("\tbreak only if ");
print_expression (b->cond, stdout);
printf ("\n");
printf_filtered ("\n");
}
if (l = b->commands)
while (l)
{
printf ("\t%s\n", l->line);
printf_filtered ("\t%s\n", l->line);
l = l->next;
}
}
if (last_addr != -1)
/* Compare against (CORE_ADDR)-1 in case some compiler decides
that a comparison of an unsigned with -1 is always false. */
if (last_addr != (CORE_ADDR)-1)
set_next_address (last_addr);
}
@ -471,9 +495,9 @@ breakpoints_info (bnum_exp)
if (bnum_exp)
bnum = parse_and_eval_address (bnum_exp);
else if (breakpoint_chain == 0)
printf ("No breakpoints.\n");
printf_filtered ("No breakpoints.\n");
else
printf ("Breakpoints:\n\
printf_filtered ("Breakpoints:\n\
Num Enb Address Where\n");
breakpoint_1 (bnum);
@ -686,7 +710,13 @@ break_command_1 (arg, tempflag, from_tty)
error ("No default breakpoint address now.");
}
else
if (default_breakpoint_valid)
/* Force almost all breakpoints to be in terms of the
current_source_symtab (which is decode_line_1's default). This
should produce the results we want almost all of the time while
leaving default_breakpoint_* alone. */
if (default_breakpoint_valid
&& (!current_source_symtab
|| (arg && (*arg == '+' || *arg == '-'))))
sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
default_breakpoint_line);
else
@ -770,14 +800,15 @@ tbreak_command (arg, from_tty)
* because it uses the mechanisms of breakpoints.
*/
void
until_break_command(arg, from_tty)
until_break_command (arg, from_tty)
char *arg;
int from_tty;
{
struct symtabs_and_lines sals;
struct symtab_and_line sal;
FRAME frame = get_current_frame ();
FRAME prev_frame = get_prev_frame (frame);
FRAME prev_frame = get_prev_frame (selected_frame);
clear_proceed_status ();
/* Set a breakpoint where the user wants it and at return from
this function */
@ -803,7 +834,7 @@ until_break_command(arg, from_tty)
if (sal.pc == 0)
error ("No line %d in file \"%s\".", sal.line, sal.symtab->filename);
set_momentary_breakpoint (sal, 0);
set_momentary_breakpoint (sal, selected_frame);
/* Keep within the current frame */
@ -940,6 +971,10 @@ delete_breakpoint (bpt)
free_command_lines (&bpt->commands);
if (bpt->cond)
free (bpt->cond);
if (xgdb_verbose && bpt->number >=0)
printf ("breakpoint #%d deleted\n", bpt->number);
free (bpt);
}
@ -954,7 +989,9 @@ delete_command (arg, from_tty)
if (arg == 0)
{
if (!from_tty || query ("Delete all breakpoints? "))
/* Ask user only if there are some breakpoints to delete. */
if (!from_tty
|| breakpoint_chain && query ("Delete all breakpoints? "))
{
/* No arg; clear all breakpoints. */
while (breakpoint_chain)
@ -1077,6 +1114,9 @@ enable_breakpoint (bpt)
{
bpt->enable = enabled;
if (xgdb_verbose && bpt->number >= 0)
printf ("breakpoint #%d enabled\n", bpt->number);
check_duplicates (bpt->address);
}
@ -1084,7 +1124,12 @@ static void
enable_command (args)
char *args;
{
map_breakpoint_numbers (args, enable_breakpoint);
struct breakpoint *bpt;
if (args == 0)
ALL_BREAKPOINTS (bpt)
enable_breakpoint (bpt);
else
map_breakpoint_numbers (args, enable_breakpoint);
}
static void
@ -1093,6 +1138,9 @@ disable_breakpoint (bpt)
{
bpt->enable = disabled;
if (xgdb_verbose && bpt->number >= 0)
printf ("breakpoint #%d disabled\n", bpt->number);
check_duplicates (bpt->address);
}
@ -1263,12 +1311,13 @@ This command may be abbreviated \"disable\".",
Arguments are breakpoint numbers with spaces in between.\n\
To delete all breakpoints, give no argument.\n\
\n\
The \"display\" subcommand applies to auto-displays instead of breakpoints.",
Also a prefix command for deletion of other GDB objects.\n\
The \"unset\" command is also an alias for \"delete\".",
&deletelist, "delete ", 1, &cmdlist);
add_com_alias ("d", "delete", class_breakpoint, 1);
add_com_alias ("unset", "delete", class_breakpoint, 1);
add_com_alias ("unset", "delete", class_alias, 1);
add_abbrev_cmd ("breakpoints", class_breakpoint, delete_command,
add_cmd ("breakpoints", class_alias, delete_command,
"Delete some breakpoints or auto-display expressions.\n\
Arguments are breakpoint numbers with spaces in between.\n\
To delete all breakpoints, give no argument.\n\

View File

@ -4,22 +4,21 @@
Revised 11/27/87 ddj@cs.brown.edu
Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -37,9 +36,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/param.h>
#include <sys/file.h>
/* Avoid problems with A/UX predefine */
#undef aux
static void add_symbol_to_list ();
static void read_coff_symtab ();
static void patch_opaque_types ();
@ -58,6 +54,7 @@ static char *getsymname ();
static int init_lineno ();
static void enter_linenos ();
extern int fclose ();
extern void free_all_symtabs ();
extern void free_all_psymtabs ();
@ -73,6 +70,9 @@ static char *last_source_file;
static CORE_ADDR cur_src_start_addr;
static CORE_ADDR cur_src_end_addr;
/* Core address of the end of the first object file. */
static CORE_ADDR first_object_file_end;
/* End of the text segment of the executable file,
as found in the symbol _etext. */
@ -84,10 +84,11 @@ static CORE_ADDR end_of_text_addr;
static FILE *nlist_stream_global;
static int nlist_nsyms_global;
/* The file and text section headers of the symbol file */
/* The file, a.out and text section headers of the symbol file */
static FILHDR file_hdr;
static SCNHDR text_hdr;
static AOUTHDR aout_hdr;
/* The index in the symbol table of the last coff symbol that was processed. */
@ -172,7 +173,8 @@ struct pending_block
struct pending_block *pending_blocks;
extern CORE_ADDR first_object_file_end; /* From blockframe.c */
extern CORE_ADDR startup_file_start; /* From blockframe.c */
extern CORE_ADDR startup_file_end; /* From blockframe.c */
/* File name symbols were loaded from. */
@ -423,6 +425,13 @@ complete_symtab (name, start_addr, size)
last_source_file = savestring (name, strlen (name));
cur_src_start_addr = start_addr;
cur_src_end_addr = start_addr + size;
if (aout_hdr.entry < cur_src_end_addr
&& aout_hdr.entry >= cur_src_start_addr)
{
startup_file_start = cur_src_start_addr;
startup_file_end = cur_src_end_addr;
}
}
/* Finish the symbol definitions for one main source file,
@ -541,6 +550,7 @@ record_misc_function (name, address)
}
misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name));
misc_bunch->contents[misc_bunch_index].address = address;
misc_bunch->contents[misc_bunch_index].type = mf_unknown;
misc_bunch_index++;
misc_count++;
}
@ -691,6 +701,9 @@ symbol_file_command (name)
return;
}
name = tilde_expand (name);
make_cleanup (free, name);
if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name))
error ("Not confirmed.");
@ -714,6 +727,23 @@ symbol_file_command (name)
if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0)
error ("File \"%s\" not in executable format.", name);
/* If an a.out header is present, read it in. If not (e.g. a .o file)
deal with its absence. */
if (file_hdr.f_opthdr == 0
|| read_aout_hdr (desc, &aout_hdr, file_hdr.f_opthdr) < 0)
{
/* We will not actually be able to run code, since backtraces would
fly off the bottom of the stack (there is no way to reliably
detect bottom of stack), but that's fine since the kernel won't
run something without an a.out header anyway. Passive examination
of .o files is one place this might make sense. */
/* ~0 will not be in any file. */
aout_hdr.entry = ~0;
/* set the startup file to be an empty range. */
startup_file_start = 0;
startup_file_end = 0;
}
if (num_symbols == 0)
{
free_all_symtabs ();
@ -844,7 +874,7 @@ read_coff_symtab (desc, nsyms)
int fcn_start_addr;
long fcn_line_ptr;
struct cleanup *old_chain;
int fclose();
newfd = dup (desc);
if (newfd == -1)
@ -973,7 +1003,11 @@ read_coff_symtab (desc, nsyms)
case C_FCN:
if (strcmp (cs->c_name, ".bf") == 0)
{
#if 0
/* Don't do this; we want all functions to be on the
mfl now. */
unrecord_misc_function ();
#endif
within_function = 1;
@ -1079,6 +1113,9 @@ read_file_hdr (chan, file_hdr)
switch (file_hdr->f_magic)
{
#ifdef MC68MAGIC
case MC68MAGIC:
#endif
#ifdef NS32GMAGIC
case NS32GMAGIC:
case NS32SMAGIC:
@ -1086,15 +1123,17 @@ read_file_hdr (chan, file_hdr)
#ifdef I386MAGIC
case I386MAGIC:
#endif
#ifdef CLIPPERMAGIC
case CLIPPERMAGIC:
#endif
return file_hdr->f_nsyms;
default:
#ifdef BADMAG
if (BADMAG(file_hdr))
return -1;
return -1;
else
return file_hdr->f_nsyms;
return file_hdr->f_nsyms;
#else
return -1;
#endif
@ -1289,18 +1328,20 @@ enter_linenos (file_offset, first_line, last_line)
register int last_line;
{
register char *rawptr = &linetab[file_offset - linetab_offset];
register struct lineno *lptr;
struct lineno lptr;
/* skip first line entry for each function */
rawptr += LINESZ;
/* line numbers start at one for the first line of the function */
first_line--;
for (lptr = (struct lineno *)rawptr;
lptr->l_lnno && lptr->l_lnno <= last_line;
rawptr += LINESZ, lptr = (struct lineno *)rawptr)
/* Bcopy since occaisionally rawptr isn't pointing at long
boundaries. */
for (bcopy (rawptr, &lptr, LINESZ);
lptr.l_lnno && lptr.l_lnno <= last_line;
rawptr += LINESZ, bcopy (rawptr, &lptr, LINESZ))
{
record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr);
record_line (first_line + lptr.l_lnno, lptr.l_addr.l_paddr);
}
}
@ -1478,7 +1519,6 @@ process_coff_symbol (cs, aux)
break;
case C_REG:
case C_REGPARM:
SYMBOL_CLASS (sym) = LOC_REGISTER;
add_symbol_to_list (sym, &local_symbols);
break;
@ -1489,6 +1529,7 @@ process_coff_symbol (cs, aux)
case C_ARG:
SYMBOL_CLASS (sym) = LOC_ARG;
add_symbol_to_list (sym, &local_symbols);
#ifndef clipper
/* If PCC says a parameter is a short or a char,
it is really an int. */
if (SYMBOL_TYPE (sym) == builtin_type_char
@ -1497,8 +1538,24 @@ process_coff_symbol (cs, aux)
else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
|| SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
#endif
break;
case C_REGPARM:
SYMBOL_CLASS (sym) = LOC_REGPARM;
add_symbol_to_list (sym, &local_symbols);
#ifndef clipper
/* If PCC says a parameter is a short or a char,
it is really an int. */
if (SYMBOL_TYPE (sym) == builtin_type_char
|| SYMBOL_TYPE (sym) == builtin_type_short)
SYMBOL_TYPE (sym) = builtin_type_int;
else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char
|| SYMBOL_TYPE (sym) == builtin_type_unsigned_short)
SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
#endif
break;
case C_TPDEF:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
@ -1935,13 +1992,14 @@ psymtab_to_symtab ()
}
/* These will stay zero all the time */
struct partial_symbol *global_psymbols, *static_psymbols;
struct psymbol_allocation_list global_psymbols, static_psymbols;
_initialize_coff ()
{
symfile = 0;
static_psymbols = global_psymbols = (struct partial_symbol *) 0;
bzero (&global_psymbols, sizeof (global_psymbols));
bzero (&static_psymbols, sizeof (static_psymbols));
add_com ("symbol-file", class_files, symbol_file_command,
"Load symbol table (in coff format) from executable file FILE.");

View File

@ -1,115 +1,24 @@
/* Library for reading command lines and decoding commands.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
NO WARRANTY
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1986 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file or
any portion of it, and copy and distribute such modifications under
the terms of Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse of
software.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "command.h"
#include "defs.h"
#include <stdio.h>
#ifdef sparc
#include <alloca.h>
#endif
#include <ctype.h>
extern char *xmalloc ();
@ -189,7 +98,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
register struct cmd_list_element *c;
copied_name = (char *) alloca (strlen (oldname) + 1);
strcpy (copied_name, oldname);
old = lookup_cmd (&copied_name, *list, 0, 1);
old = lookup_cmd (&copied_name, *list, 0, 1, 1);
if (old == 0)
{
@ -303,7 +212,7 @@ help_cmd (command, stream)
return;
}
c = lookup_cmd (&command, cmdlist, "", 0);
c = lookup_cmd (&command, cmdlist, "", 0, 0);
if (c == 0)
return;
@ -320,10 +229,12 @@ help_cmd (command, stream)
and then set class to he number of this class
so that the commands in the class will be listed. */
fprintf (stream, "%s\n", c->doc);
fputs_filtered (c->doc, stream);
fputs_filtered ("\n", stream);
if (c->prefixlist == 0 && c->function != 0)
return;
fputc ('\n', stream);
fprintf_filtered (stream, "\n");
/* If this is a prefix command, print it's subcommands */
if (c->prefixlist)
@ -372,18 +283,18 @@ help_list (list, cmdtype, class, stream)
}
if (class == -2)
fprintf (stream, "List of classes of %scommands:\n\n", cmdtype2);
fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
else
fprintf (stream, "List of %scommands:\n\n", cmdtype2);
fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
help_cmd_list (list, class, cmdtype, (class >= 0), stream);
if (class == -2)
fprintf (stream, "\n\
fprintf_filtered (stream, "\n\
Type \"help%s\" followed by a class name for a list of commands in that class.",
cmdtype1);
fprintf (stream, "\n\
fprintf_filtered (stream, "\n\
Type \"help%s\" followed by %scommand name for full documentation.\n\
Command name abbreviations are allowed if unambiguous.\n",
cmdtype1, cmdtype2);
@ -416,6 +327,14 @@ help_cmd_list (list, class, prefix, recurse, stream)
{
register struct cmd_list_element *c;
register char *p;
static char *line_buffer = 0;
static int line_size;
if (!line_buffer)
{
line_size = 80;
line_buffer = (char *) xmalloc (line_size);
}
for (c = list; c; c = c->next)
{
@ -424,12 +343,20 @@ help_cmd_list (list, class, prefix, recurse, stream)
|| (class == -2 && c->function == 0)
|| (class == c->class && c->function != 0)))
{
fprintf (stream, "%s%s -- ", prefix, c->name);
fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
/* Print just the first line */
p = c->doc;
while (*p && *p != '\n') p++;
fwrite (c->doc, 1, p - c->doc, stream);
fputc('\n', stream);
if (p - c->doc > line_size - 1)
{
line_size = p - c->doc + 1;
free (line_buffer);
line_buffer = (char *) xmalloc (line_size);
}
strncpy (line_buffer, c->doc, p - c->doc);
line_buffer[p - c->doc] = '\0';
fputs_filtered (line_buffer, stream);
fputs_filtered ("\n", stream);
}
if (recurse
&& c->prefixlist != 0
@ -438,6 +365,260 @@ help_cmd_list (list, class, prefix, recurse, stream)
}
}
/* This routine takes a line of TEXT and a CLIST in which to
start the lookup. When it returns it will have incremented the text
pointer past the section of text it matched, set *RESULT_LIST to
the list in which the last word was matched, and will return the
cmd list element which the text matches. It will return 0 if no
match at all was possible. It will return -1 if ambigous matches are
possible; in this case *RESULT_LIST will be set to the list in which
there are ambiguous choices (and text will be set to the ambiguous
text string).
It does no error reporting whatsoever; control will always return
to the superior routine.
In the case of an ambiguous return (-1), *RESULT_LIST will be set to
point at the prefix_command (ie. the best match) *or* (special
case) will be 0 if no prefix command was ever found. For example,
in the case of "info a", "info" matches without ambiguity, but "a"
could be "args" or "address", so *RESULT_LIST is set to
the cmd_list_element for "info". So in this case
result list should not be interpeted as a pointer to the beginning
of a list; it simply points to a specific command.
This routine does *not* modify the text pointed to by TEXT.
If INGNORE_HELP_CLASSES is nonzero, ignore any command list
elements which are actually help classes rather than commands (i.e.
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
char **text;
struct cmd_list_element *clist, **result_list;
int ignore_help_classes;
{
char *p, *command;
int len, tmp, nfound;
struct cmd_list_element *found, *c;
while (**text == ' ' || **text == '\t')
(*text)++;
/* Treating underscores as part of command words is important
so that "set args_foo()" doesn't get interpreted as
"set args _foo()". */
for (p = *text;
*p && (isalnum(*p) || *p == '-' || *p == '_');
p++)
;
/* If nothing but whitespace, return 0. */
if (p == *text)
return 0;
len = p - *text;
/* *text and p now bracket the first command word to lookup (and
it's length is len). We copy this into a local temporary,
converting to lower case as we go. */
command = (char *) alloca (len + 1);
for (tmp = 0; tmp < len; tmp++)
{
char x = (*text)[tmp];
command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
}
command[len] = '\0';
/* Look it up. */
found = 0;
nfound = 0;
for (c = clist; c; c = c->next)
if (!strncmp (command, c->name, len)
&& (!ignore_help_classes || c->function))
{
found = c;
nfound++;
if (c->name[len] == '\0')
{
nfound = 1;
break;
}
}
/* If nothing matches, we have a simple failure. */
if (nfound == 0)
return 0;
if (nfound > 1)
{
*result_list = 0; /* Will be modified in calling routine
if we know what the prefix command is.
*/
return (struct cmd_list_element *) -1; /* Ambiguous. */
}
/* We've matched something on this list. Move text pointer forward. */
*text = p;
if (found->prefixlist)
{
c = lookup_cmd_1 (text, *found->prefixlist, result_list,
ignore_help_classes);
if (!c)
{
/* Didn't find anything; this is as far as we got. */
*result_list = clist;
return found;
}
else if (c == (struct cmd_list_element *) -1)
{
/* We've gotten this far properley, but the next step
is ambiguous. We need to set the result list to the best
we've found (if an inferior hasn't already set it). */
if (!*result_list)
/* This used to say *result_list = *found->prefixlist
If that was correct, need to modify the documentation
at the top of this function to clarify what is supposed
to be going on. */
*result_list = found;
return c;
}
else
{
/* We matched! */
return c;
}
}
else
{
*result_list = clist;
return found;
}
}
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
If it is found, return the struct cmd_list_element for that command
and update *LINE to point after the command name, at the first argument.
If not found, call error if ALLOW_UNKNOWN is zero
otherwise (or if error returns) return zero.
Call error if specified command is ambiguous,
unless ALLOW_UNKNOWN is negative.
CMDTYPE precedes the word "command" in the error message.
If INGNORE_HELP_CLASSES is nonzero, ignore any command list
elements which are actually help classes rather than commands (i.e.
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
char **line;
struct cmd_list_element *list;
char *cmdtype;
int allow_unknown;
int ignore_help_classes;
{
struct cmd_list_element *last_list = 0;
struct cmd_list_element *c =
lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
char *ptr = (*line) + strlen (*line) - 1;
/* Clear off trailing whitespace. */
while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
ptr--;
*(ptr + 1) = '\0';
if (!c)
{
if (!allow_unknown)
{
if (!*line)
error ("Lack of needed %scommand", cmdtype);
else
{
char *p = *line, *q;
while (isalnum(*p) || *p == '-')
p++;
q = (char *) alloca (p - *line + 1);
strncpy (q, *line, p - *line);
q[p-*line] = '\0';
error ("Undefined %scommand: \"%s\".", cmdtype, q);
}
}
else
return 0;
}
else if (c == (struct cmd_list_element *) -1)
{
/* Ambigous. Local values should be off prefixlist or called
values. */
int local_allow_unknown = (last_list ? last_list->allow_unknown :
allow_unknown);
char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
struct cmd_list_element *local_list =
(last_list ? *(last_list->prefixlist) : list);
if (local_allow_unknown < 0)
{
if (last_list)
return last_list; /* Found something. */
else
return 0; /* Found nothing. */
}
else
{
/* Report as error. */
int amb_len;
char ambbuf[100];
for (amb_len = 0;
((*line)[amb_len] && (*line)[amb_len] != ' '
&& (*line)[amb_len] != '\t');
amb_len++)
;
ambbuf[0] = 0;
for (c = local_list; c; c = c->next)
if (!strncmp (*line, c->name, amb_len))
{
if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
{
if (strlen (ambbuf))
strcat (ambbuf, ", ");
strcat (ambbuf, c->name);
}
else
{
strcat (ambbuf, "..");
break;
}
}
error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
*line, ambbuf);
}
}
else
{
/* We've got something. It may still not be what the caller
wants (if this command *needs* a subcommand). */
while (**line == ' ' || **line == '\t')
(*line)++;
if (c->prefixlist && **line && !c->allow_unknown)
error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
/* Seems to be what he wants. Return it. */
return c;
}
}
#if 0
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
If it is found, return the struct cmd_list_element for that command
@ -477,12 +658,10 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
/* Find end of command name. */
p = *line;
if (*p == '!')
p++;
else while (*p == '-'
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9'))
while (*p == '-'
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9'))
p++;
/* Look up the command name.
@ -576,6 +755,61 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
return found;
}
#endif
/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
/* Return a vector of char pointers which point to the different
possible completions in LIST of TEXT. */
char **
complete_on_cmdlist (list, text)
struct cmd_list_element *list;
char *text;
{
struct cmd_list_element *ptr;
char **matchlist;
int sizeof_matchlist;
int matches;
int textlen = strlen (text);
sizeof_matchlist = 10;
matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
matches = 0;
for (ptr = list; ptr; ptr = ptr->next)
if (!strncmp (ptr->name, text, textlen)
&& !ptr->abbrev_flag
&& (ptr->function
|| ptr->prefixlist))
{
if (matches == sizeof_matchlist)
{
sizeof_matchlist *= 2;
matchlist = (char **) xrealloc (matchlist,
(sizeof_matchlist
* sizeof (char *)));
}
matchlist[matches] = (char *)
xmalloc (strlen (ptr->name) + 1);
strcpy (matchlist[matches++], ptr->name);
}
if (matches == 0)
{
free (matchlist);
matchlist = 0;
}
else
{
matchlist = (char **) xrealloc (matchlist, ((matches + 1)
* sizeof (char *)));
matchlist[matches] = (char *) 0;
}
return matchlist;
}
static void
shell_escape (arg, from_tty)
@ -619,6 +853,4 @@ _initialize_command ()
add_com ("shell", class_support, shell_escape,
"Execute the rest of the line as a shell command. \n\
With no arguments, run an inferior shell.");
add_com_alias ("!", "shell", class_support, 1);
}

View File

@ -1,107 +1,19 @@
/* Header file for command-reading library command.c.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
NO WARRANTY
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1986 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file or
any portion of it, and copy and distribute such modifications under
the terms of Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse of
software.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This structure records one command'd definition. */
@ -148,7 +60,9 @@ struct cmd_list_element
char allow_unknown;
/* Nonzero says this is an abbreviation, and should not
be mentioned in lists of commands. */
be mentioned in lists of commands.
This allows "br<tab>" to complete to "break", which it
otherwise wouldn't. */
char abbrev_flag;
};
@ -157,6 +71,7 @@ struct cmd_list_element
extern struct cmd_list_element *add_cmd ();
extern struct cmd_list_element *add_alias_cmd ();
extern struct cmd_list_element *add_prefix_cmd ();
extern struct cmd_list_element *lookup_cmd ();
extern struct cmd_list_element *lookup_cmd (), *lookup_cmd_1 ();
extern char **complete_on_cmdlist ();
extern void delete_cmd ();
extern void help_cmd ();

View File

@ -1,7 +1,7 @@
#!/bin/sh
#
# Shell script to create proper links to machine-dependent files in
# Shell script to do machine-dependent things in
# preparation for compiling gdb.
#
# Usage: config.gdb machine [operating-system]
@ -10,13 +10,17 @@
# If config.gdb fails after disturbing the status quo,
# config.status is removed.
#
# Note: if making something gives errors like "unable to make target
# 1-dep.c", this means that the compiler has put in a builtin define
# and there is a "-U" missing from makedefine in this file.
#
progname=$0
case $# in
1)
machine=$1
os="none"
os=""
;;
2)
machine=$1
@ -34,49 +38,149 @@ case $# in
;;
esac
paramfile=m-${machine}.h
pinsnfile=${machine}-pinsn.c
opcodefile=${machine}-opcode.h
if [ -r ${machine}-dep.c ]
# cannonicalize the machine name.
case $machine in
news)
case $os in
os3|newsos3)
$machine=newsos3
$os=""
;;
esac
;;
sun2)
case $os in
os4|sunos4)
$machine=sun2os4
$os=""
;;
os2|sunos2)
$machine=sun2os2
$os=""
;;
esac
;;
sun3)
case $os in
os4|sunos4)
$machine=sun3os4
$os=""
;;
os3|sunos3)
$machine=sun3os3
$os=""
;;
esac
;;
sparc|sun4)
case $os in
os4|sunos4)
$machine=sun4os4
$os=""
;;
esac
;;
esac
paramfile=m-${machine}${os}.h
pinsnfile=${machine}${os}-pinsn.c
opcodefile=${machine}${os}-opcode.h
# Set up a define for purposes of editing the makefile.
makedefine=
if [ -r ${machine}${os}-dep.c ]
then
depfile=${machine}-dep.c
depfile=${machine}${os}-dep.c
else
depfile=default-dep.c
fi
#
# Special cases.
# If a file is not needed, set the filename to 'skip' and it will be
# ignored.
# If a file is not needed, set the file name to something.
# It must be linked to something, or else make will try to make it.
# /dev/null will not work because on systems without symbolic links,
# it will complain that /dev/null is on a different file system.
#
case $machine in
aux)
altos)
makedefine="-DM_REGEX=regex.o -DM_SYSV -DM_BSD_NM"
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
altosgas)
echo "Use of the coff encapsulation features require the GNU binutils utilities"
echo "To be ahead of their System V counterparts in your path."
makedefine="-DM_REGEX=regex.o -DM_SYSV -DM_BSD_NM"
pinsnfile=m68k-pinsn.c
depfile=altos-dep.c
opcodefile=m68k-opcode.h
;;
vax)
echo
echo "/bin/cc has been known to fail on readline.c on VAXen running BSD4.3"
echo "If this occurs, use gcc "
echo " (but see comments in Makefile.dist about compiling with gcc)."
echo
pinsnfile=vax-pinsn.c
opcodefile=vax-opcode.h
;;
hp9k320)
# The headers in the directory hp-include override system headers
# and tell GDB to use BSD executable file format (hence -Ihp-include)
makedefine="-DM_SYSV -DM_BSD_NM -DM_REGEX=regex.o
-DM_ALLOCA=alloca.o -DM_CFLAGS=-Ihp-include"
# The following is true because gcc uses a different .o file format
# than the native HPUX compiler
echo
echo "If you compile GDB with GCC on HPUX, you must make sure"
echo "that the \`nm' used in \`munch' is GNU nm"
echo
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
hp300bsd)
# Not sure what makefile editing (if any) is necessary for this machine.
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
isi)
# ISI running bsd4.2
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
i386)
echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile"
opcodefile=skip
makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o"
# The following is a lie, but a necessary one. See comment at beginning
# of this file about unneeded files.
opcodefile=m-i386.h
;;
i386gas)
echo "Note: i386 users need to modify \`CLIBS' & \`REGEX*' in the Makefile"
echo "Use of the coff encapsulation features also requires the GNU binutils utilities"
makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o"
echo
echo "Use of the coff encapsulation features requires the GNU binary utilities"
echo "to be ahead of their System V counterparts in your path."
echo
pinsnfile=i386-pinsn.c
depfile=i386-dep.c
opcodefile=skip
# The following is a lie, but a necessary one. See comment at beginning
# of this file about unneeded files.
opcodefile=m-i386.h
;;
i386-sysv3.2)
makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o"
pinsnfile=i386-pinsn.c
depfile=i386-dep.c
opcodefile=/dev/null
;;
i386gas-sysv3.2)
makedefine="-DM_CLIBS=-lPW -DM_SYSV -DM_REGEX=regex.o"
echo
echo "Use of the coff encapsulation features requires the GNU binary utilities"
echo "to be ahead of their System V counterparts in your path."
echo
pinsnfile=i386-pinsn.c
depfile=i386-dep.c
opcodefile=/dev/null
;;
merlin)
pinsnfile=ns32k-pinsn.c
@ -86,6 +190,11 @@ news)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
newsos3)
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
depfile=news-dep.c
;;
npl)
pinsnfile=gld-pinsn.c
;;
@ -93,55 +202,77 @@ pn)
pinsnfile=gld-pinsn.c
;;
sun2)
case $os in
os4|sunos4)
paramfile=m-sun2os4.h
;;
os2|sunos2)
paramfile=m-sun2os2.h
esac
depfile=sun3-dep.c
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun2os2)
sun2os2|sun2-os2)
depfile=default-dep.c
paramfile=m-sun2.h
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun2os4)
sun2os4|sun2-os4)
# Compile GDB without shared libraries so that it can be run on itself.
makedefine=-DM_CFLAGS=-Bstatic
echo
echo "Make sure to compile any program on which you want to run gdb"
echo " without shared libraries (cc -Bstatic)"
echo
paramfile=m-sun2os4.h
depfile=sun3-dep.c
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun3)
case $os in
os4|sunos4)
paramfile=m-sun3os4.h
esac
sun3os3)
paramfile=m-sun3.h
depfile=sun3-dep.c
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
;;
sun3os4)
sun3os4|sun3-os4)
# Compile GDB without shared libraries so that it can be run on itself.
makedefine=-DM_CFLAGS=-Bstatic
echo
echo "Make sure to compile any program on which you want to run gdb"
echo " without shared libraries (cc -Bstatic)"
echo
paramfile=m-sun3os4.h
pinsnfile=m68k-pinsn.c
opcodefile=m68k-opcode.h
depfile=sun3-dep.c
;;
sun4os4)
sun4os4|sun4-os4)
# Compile GDB without shared libraries so that it can be run on itself.
# Undefine sparc to avoid changing sparc-dep.c to 1-dep.c
makedefine="-DM_CFLAGS=-Bstatic -Usparc"
echo
echo "Make sure to compile any program on which you want to run gdb"
echo " without shared libraries (cc -Bstatic)"
echo
paramfile=m-sun4os4.h
pinsnfile=sparc-pinsn.c
opcodefile=sparc-opcode.h
depfile=sparc-dep.c
;;
symmetry)
pinsnfile=i386-pinsn.c
# Need *some* opcode file to keep make from trying to make opcode.h
opcodefile=/dev/null
;;
umax)
pinsnfile=ns32k-pinsn.c
opcodefile=ns32k-opcode.h
;;
sparc|sun4)
case $os in
os4|sunos4)
paramfile=m-sun4os4.h
esac
sparc|sun4|sun4os3|sun4-os3)
paramfile=m-sparc.h
# Undefine sparc to avoid changing sparc-dep.c to 1-dep.c
makedefine=-Usparc
pinsnfile=sparc-pinsn.c
opcodefile=sparc-opcode.h
depfile=sparc-dep.c
paramfile=m-sparc.h
;;
convex)
;;
test)
paramfile=one
@ -153,11 +284,13 @@ test)
echo "Available types:"
echo m-*.h | sed 's/m-//g' | sed 's/\.h//g'
exit 1
;;
esac
files="$paramfile $pinsnfile $opcodefile $depfile"
links="param.h pinsn.c opcode.h dep.c"
rm -f config.status
while [ -n "$files" ]
do
# set file to car of files, files to cdr of files
@ -173,7 +306,8 @@ do
exit 1
fi
rm -f $link config.status
echo "Linking \`$link' to \`$file'."
rm -f $link
# Make a symlink if possible, otherwise try a hard link
ln -s $file $link 2>/dev/null || ln $file $link
@ -182,11 +316,16 @@ do
echo "$progname: unable to link \`$link' to \`$file'."
exit 1
fi
echo "Linked \`$link' to \`$file'."
fi
done
echo "Links are now set up for use with a $machine." \
# edit the makefile
echo "Editing Makefile"
cp Makefile.dist tmp.c
cc -E >Makefile tmp.c $makedefine -DM_MAKEDEFINE="$makedefine"
rm -f tmp.c
echo "GDB is now set up for use with a $machine." \
| tee config.status
exit 0

View File

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

File diff suppressed because it is too large Load Diff

1674
gdb/convex-opcode.h Normal file

File diff suppressed because it is too large Load Diff

314
gdb/convex-pinsn.c Normal file
View File

@ -0,0 +1,314 @@
/* Print Convex instructions for GDB, the GNU debugger.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "defs.h"
#include "param.h"
#include "symtab.h"
/* reg (fmt_field, inst_field) --
the {first,second,third} operand of instruction as fmt_field = [ijk]
gets the value of the field from the [ijk] position of the instruction */
#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b]
/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */
#define lit(i) op[fmt->i]
/* aj[j] -- name for A register j */
#define aj ((char (*)[3])(op[A]))
union inst {
struct {
unsigned : 7;
unsigned i : 3;
unsigned j : 3;
unsigned k : 3;
unsigned : 16;
unsigned : 32;
} f0;
struct {
unsigned : 8;
unsigned indir : 1;
unsigned len : 1;
unsigned j : 3;
unsigned k : 3;
unsigned : 16;
unsigned : 32;
} f1;
unsigned char byte[8];
unsigned short half[4];
char signed_byte[8];
short signed_half[4];
};
struct opform {
int mask; /* opcode mask */
int shift; /* opcode align */
struct formstr *formstr[3]; /* ST, E0, E1 */
};
struct formstr {
unsigned lop:8, rop:5; /* opcode */
unsigned fmt:5; /* inst format */
unsigned i:5, j:5, k:2; /* operand formats */
};
#include "convex-opcode.h"
unsigned char formdecode [] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
struct opform opdecode[] = {
0x7e00, 9, format0, e0_format0, e1_format0,
0x3f00, 8, format1, e0_format1, e1_format1,
0x1fc0, 6, format2, e0_format2, e1_format2,
0x0fc0, 6, format3, e0_format3, e1_format3,
0x0700, 8, format4, e0_format4, e1_format4,
0x03c0, 6, format5, e0_format5, e1_format5,
0x01f8, 3, format6, e0_format6, e1_format6,
0x00f8, 3, format7, e0_format7, e1_format7,
0x0000, 0, formatx, formatx, formatx,
0x0f80, 7, formatx, formatx, formatx,
0x0f80, 7, formatx, formatx, formatx,
};
/* Print the 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;
{
union inst inst;
struct formstr *fmt;
register int format, op1, pfx;
int l;
read_memory (memaddr, &inst, sizeof inst);
/* Remove and note prefix, if present */
pfx = inst.half[0];
if ((pfx & 0xfff0) == 0x7ef0)
{
pfx = ((pfx >> 3) & 1) + 1;
*(long long *) &inst = *(long long *) &inst.half[1];
}
else pfx = 0;
/* Split opcode into format.op1 and look up in appropriate table */
format = formdecode[inst.byte[0]];
op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift;
if (format == 9)
{
if (pfx)
fmt = formatx;
else if (inst.f1.j == 0)
fmt = &format1a[op1];
else if (inst.f1.j == 1)
fmt = &format1b[op1];
else
fmt = formatx;
}
else
fmt = &opdecode[format].formstr[pfx][op1];
/* Print it */
if (fmt->fmt == xxx)
{
/* noninstruction */
fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]);
return 2;
}
if (pfx)
pfx = 2;
fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop],
&" "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]);
switch (fmt->fmt)
{
case rrr: /* three register */
fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k));
return pfx + 2;
case rr: /* two register */
fprintf (stream, "%s,%s", reg(i,j), reg(j,k));
return pfx + 2;
case rxr: /* two register, reversed i and j fields */
fprintf (stream, "%s,%s", reg(i,k), reg(j,j));
return pfx + 2;
case r: /* one register */
fprintf (stream, "%s", reg(i,k));
return pfx + 2;
case nops: /* no operands */
return pfx + 2;
case nr: /* short immediate, one register */
fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k));
return pfx + 2;
case pcrel: /* pc relative */
print_address (memaddr + 2 * inst.signed_byte[1], stream);
return pfx + 2;
case lr: /* literal, one register */
fprintf (stream, "%s,%s", lit(i), reg(j,k));
return pfx + 2;
case rxl: /* one register, literal */
fprintf (stream, "%s,%s", reg(i,k), lit(j));
return pfx + 2;
case rlr: /* register, literal, register */
fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k));
return pfx + 2;
case rrl: /* register, register, literal */
fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k));
return pfx + 2;
case iml: /* immediate, literal */
if (inst.f1.len)
{
fprintf (stream, "#%#x,%s",
(inst.signed_half[1] << 16) + inst.half[2], lit(i));
return pfx + 6;
}
else
{
fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i));
return pfx + 4;
}
case imr: /* immediate, register */
if (inst.f1.len)
{
fprintf (stream, "#%#x,%s",
(inst.signed_half[1] << 16) + inst.half[2], reg(i,k));
return pfx + 6;
}
else
{
fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k));
return pfx + 4;
}
case a1r: /* memory, register */
l = print_effa (inst, stream);
fprintf (stream, ",%s", reg(i,k));
return pfx + l;
case a1l: /* memory, literal */
l = print_effa (inst, stream);
fprintf (stream, ",%s", lit(i));
return pfx + l;
case a2r: /* register, memory */
fprintf (stream, "%s,", reg(i,k));
return pfx + print_effa (inst, stream);
case a2l: /* literal, memory */
fprintf (stream, "%s,", lit(i));
return pfx + print_effa (inst, stream);
case a3: /* memory */
return pfx + print_effa (inst, stream);
case a4: /* system call */
l = 29; goto a4a5;
case a5: /* trap */
l = 27;
a4a5:
if (inst.f1.len)
{
unsigned int m = (inst.signed_half[1] << 16) + inst.half[2];
fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
return pfx + 6;
}
else
{
unsigned int m = inst.signed_half[1];
fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
return pfx + 4;
}
}
}
/* print effective address @nnn(aj), return instruction length */
int print_effa (inst, stream)
union inst inst;
FILE *stream;
{
int n, l;
if (inst.f1.len)
{
n = (inst.signed_half[1] << 16) + inst.half[2];
l = 6;
}
else
{
n = inst.signed_half[1];
l = 4;
}
if (inst.f1.indir)
printf ("@");
if (!inst.f1.j)
{
print_address (n, stream);
return l;
}
fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)",
n, aj[inst.f1.j]);
return l;
}

53
gdb/copying.awk Normal file
View File

@ -0,0 +1,53 @@
BEGIN {
FS="\"";
print "/* Do not modify this file; it is created automatically";
print " by copying.awk. */";
print "extern int immediate_quit;";
print "static void";
print "copying_info ()";
print "{";
print " immediate_quit++;";
}
NR == 1,/^[ ]*NO WARRANTY[ ]*$/ {
if (! ($0 ~ /^[ ]*NO WARRANTY[ ]*$/))
{
printf " printf_filtered (\"";
for (i = 1; i < NF; i++)
printf "%s\\\"", $i;
printf "%s\\n\");\n", $NF;
}
}
/^[ ]*NO WARRANTY[ ]*$/ {
print " immediate_quit--;";
print "}";
print "";
print "static void";
print "warranty_info ()";
print "{";
print " immediate_quit++;";
}
/^[ ]*NO WARRANTY[ ]*$/, /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/{
if (! ($0 ~ /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/))
{
printf " printf_filtered (\"";
for (i = 1; i < NF; i++)
printf "%s\\\"", $i;
printf "%s\\n\");\n", $NF;
}
}
END {
print " immediate_quit--;";
print "}";
print "";
print "void"
print "_initialize_copying ()";
print "{";
print " add_info (\"copying\", copying_info,";
print " \"Conditions for redistributing copies of GDB.\");";
print " add_info (\"warranty\", warranty_info,";
print " \"Various kinds of warranty you do not have.\");";
print "}";
}

215
gdb/copying.c Normal file
View File

@ -0,0 +1,215 @@
/* Do not modify this file; it is created automatically
by copying.awk. */
extern int immediate_quit;
static void
copying_info ()
{
immediate_quit++;
printf_filtered ("\n");
printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
printf_filtered (" Version 1, February 1989\n");
printf_filtered ("\n");
printf_filtered (" Copyright (C) 1989 Free Software Foundation, Inc.\n");
printf_filtered (" 675 Mass Ave, Cambridge, MA 02139, USA\n");
printf_filtered (" Everyone is permitted to copy and distribute verbatim copies\n");
printf_filtered (" of this license document, but changing it is not allowed.\n");
printf_filtered ("\n");
printf_filtered (" Preamble\n");
printf_filtered ("\n");
printf_filtered (" The license agreements of most software companies try to keep users\n");
printf_filtered ("at the mercy of those companies. By contrast, our General Public\n");
printf_filtered ("License is intended to guarantee your freedom to share and change free\n");
printf_filtered ("software--to make sure the software is free for all its users. The\n");
printf_filtered ("General Public License applies to the Free Software Foundation's\n");
printf_filtered ("software and to any other program whose authors commit to using it.\n");
printf_filtered ("You can use it for your programs, too.\n");
printf_filtered ("\n");
printf_filtered (" When we speak of free software, we are referring to freedom, not\n");
printf_filtered ("price. Specifically, the General Public License is designed to make\n");
printf_filtered ("sure that you have the freedom to give away or sell copies of free\n");
printf_filtered ("software, that you receive source code or can get it if you want it,\n");
printf_filtered ("that you can change the software or use pieces of it in new free\n");
printf_filtered ("programs; and that you know you can do these things.\n");
printf_filtered ("\n");
printf_filtered (" To protect your rights, we need to make restrictions that forbid\n");
printf_filtered ("anyone to deny you these rights or to ask you to surrender the rights.\n");
printf_filtered ("These restrictions translate to certain responsibilities for you if you\n");
printf_filtered ("distribute copies of the software, or if you modify it.\n");
printf_filtered ("\n");
printf_filtered (" For example, if you distribute copies of a such a program, whether\n");
printf_filtered ("gratis or for a fee, you must give the recipients all the rights that\n");
printf_filtered ("you have. You must make sure that they, too, receive or can get the\n");
printf_filtered ("source code. And you must tell them their rights.\n");
printf_filtered ("\n");
printf_filtered (" We protect your rights with two steps: (1) copyright the software, and\n");
printf_filtered ("(2) offer you this license which gives you legal permission to copy,\n");
printf_filtered ("distribute and/or modify the software.\n");
printf_filtered ("\n");
printf_filtered (" Also, for each author's protection and ours, we want to make certain\n");
printf_filtered ("that everyone understands that there is no warranty for this free\n");
printf_filtered ("software. If the software is modified by someone else and passed on, we\n");
printf_filtered ("want its recipients to know that what they have is not the original, so\n");
printf_filtered ("that any problems introduced by others will not reflect on the original\n");
printf_filtered ("authors' reputations.\n");
printf_filtered ("\n");
printf_filtered (" The precise terms and conditions for copying, distribution and\n");
printf_filtered ("modification follow.\n");
printf_filtered (" \n");
printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
printf_filtered (" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
printf_filtered ("\n");
printf_filtered (" 0. This License Agreement applies to any program or other work which\n");
printf_filtered ("contains a notice placed by the copyright holder saying it may be\n");
printf_filtered ("distributed under the terms of this General Public License. The\n");
printf_filtered ("\"Program\", below, refers to any such program or work, and a \"work based\n");
printf_filtered ("on the Program\" means either the Program or any work containing the\n");
printf_filtered ("Program or a portion of it, either verbatim or with modifications. Each\n");
printf_filtered ("licensee is addressed as \"you\".\n");
printf_filtered ("\n");
printf_filtered (" 1. You may copy and distribute verbatim copies of the Program's source\n");
printf_filtered ("code as you receive it, in any medium, provided that you conspicuously and\n");
printf_filtered ("appropriately publish on each copy an appropriate copyright notice and\n");
printf_filtered ("disclaimer of warranty; keep intact all the notices that refer to this\n");
printf_filtered ("General Public License and to the absence of any warranty; and give any\n");
printf_filtered ("other recipients of the Program a copy of this General Public License\n");
printf_filtered ("along with the Program. You may charge a fee for the physical act of\n");
printf_filtered ("transferring a copy.\n");
printf_filtered ("\n");
printf_filtered (" 2. You may modify your copy or copies of the Program or any portion of\n");
printf_filtered ("it, and copy and distribute such modifications under the terms of Paragraph\n");
printf_filtered ("1 above, provided that you also do the following:\n");
printf_filtered ("\n");
printf_filtered (" a) cause the modified files to carry prominent notices stating that\n");
printf_filtered (" you changed the files and the date of any change; and\n");
printf_filtered ("\n");
printf_filtered (" b) cause the whole of any work that you distribute or publish, that\n");
printf_filtered (" in whole or in part contains the Program or any part thereof, either\n");
printf_filtered (" with or without modifications, to be licensed at no charge to all\n");
printf_filtered (" third parties under the terms of this General Public License (except\n");
printf_filtered (" that you may choose to grant warranty protection to some or all\n");
printf_filtered (" third parties, at your option).\n");
printf_filtered ("\n");
printf_filtered (" c) If the modified program normally reads commands interactively when\n");
printf_filtered (" run, you must cause it, when started running for such interactive use\n");
printf_filtered (" in the simplest and most usual way, to print or display an\n");
printf_filtered (" announcement including an appropriate copyright notice and a notice\n");
printf_filtered (" that there is no warranty (or else, saying that you provide a\n");
printf_filtered (" warranty) and that users may redistribute the program under these\n");
printf_filtered (" conditions, and telling the user how to view a copy of this General\n");
printf_filtered (" Public License.\n");
printf_filtered ("\n");
printf_filtered (" d) You may charge a fee for the physical act of transferring a\n");
printf_filtered (" copy, and you may at your option offer warranty protection in\n");
printf_filtered (" exchange for a fee.\n");
printf_filtered ("\n");
printf_filtered ("Mere aggregation of another independent work with the Program (or its\n");
printf_filtered ("derivative) on a volume of a storage or distribution medium does not bring\n");
printf_filtered ("the other work under the scope of these terms.\n");
printf_filtered (" \n");
printf_filtered (" 3. You may copy and distribute the Program (or a portion or derivative of\n");
printf_filtered ("it, under Paragraph 2) in object code or executable form under the terms of\n");
printf_filtered ("Paragraphs 1 and 2 above provided that you also do one of the following:\n");
printf_filtered ("\n");
printf_filtered (" a) accompany it with the complete corresponding machine-readable\n");
printf_filtered (" source code, which must be distributed under the terms of\n");
printf_filtered (" Paragraphs 1 and 2 above; or,\n");
printf_filtered ("\n");
printf_filtered (" b) accompany it with a written offer, valid for at least three\n");
printf_filtered (" years, to give any third party free (except for a nominal charge\n");
printf_filtered (" for the cost of distribution) a complete machine-readable copy of the\n");
printf_filtered (" corresponding source code, to be distributed under the terms of\n");
printf_filtered (" Paragraphs 1 and 2 above; or,\n");
printf_filtered ("\n");
printf_filtered (" c) accompany it with the information you received as to where the\n");
printf_filtered (" corresponding source code may be obtained. (This alternative is\n");
printf_filtered (" allowed only for noncommercial distribution and only if you\n");
printf_filtered (" received the program in object code or executable form alone.)\n");
printf_filtered ("\n");
printf_filtered ("Source code for a work means the preferred form of the work for making\n");
printf_filtered ("modifications to it. For an executable file, complete source code means\n");
printf_filtered ("all the source code for all modules it contains; but, as a special\n");
printf_filtered ("exception, it need not include source code for modules which are standard\n");
printf_filtered ("libraries that accompany the operating system on which the executable\n");
printf_filtered ("file runs, or for standard header files or definitions files that\n");
printf_filtered ("accompany that operating system.\n");
printf_filtered ("\n");
printf_filtered (" 4. You may not copy, modify, sublicense, distribute or transfer the\n");
printf_filtered ("Program except as expressly provided under this General Public License.\n");
printf_filtered ("Any attempt otherwise to copy, modify, sublicense, distribute or transfer\n");
printf_filtered ("the Program is void, and will automatically terminate your rights to use\n");
printf_filtered ("the Program under this License. However, parties who have received\n");
printf_filtered ("copies, or rights to use copies, from you under this General Public\n");
printf_filtered ("License will not have their licenses terminated so long as such parties\n");
printf_filtered ("remain in full compliance.\n");
printf_filtered ("\n");
printf_filtered (" 5. By copying, distributing or modifying the Program (or any work based\n");
printf_filtered ("on the Program) you indicate your acceptance of this license to do so,\n");
printf_filtered ("and all its terms and conditions.\n");
printf_filtered ("\n");
printf_filtered (" 6. Each time you redistribute the Program (or any work based on the\n");
printf_filtered ("Program), the recipient automatically receives a license from the original\n");
printf_filtered ("licensor to copy, distribute or modify the Program subject to these\n");
printf_filtered ("terms and conditions. You may not impose any further restrictions on the\n");
printf_filtered ("recipients' exercise of the rights granted herein.\n");
printf_filtered (" \n");
printf_filtered (" 7. The Free Software Foundation may publish revised and/or new versions\n");
printf_filtered ("of the General Public License from time to time. Such new versions will\n");
printf_filtered ("be similar in spirit to the present version, but may differ in detail to\n");
printf_filtered ("address new problems or concerns.\n");
printf_filtered ("\n");
printf_filtered ("Each version is given a distinguishing version number. If the Program\n");
printf_filtered ("specifies a version number of the license which applies to it and \"any\n");
printf_filtered ("later version\", you have the option of following the terms and conditions\n");
printf_filtered ("either of that version or of any later version published by the Free\n");
printf_filtered ("Software Foundation. If the Program does not specify a version number of\n");
printf_filtered ("the license, you may choose any version ever published by the Free Software\n");
printf_filtered ("Foundation.\n");
printf_filtered ("\n");
printf_filtered (" 8. If you wish to incorporate parts of the Program into other free\n");
printf_filtered ("programs whose distribution conditions are different, write to the author\n");
printf_filtered ("to ask for permission. For software which is copyrighted by the Free\n");
printf_filtered ("Software Foundation, write to the Free Software Foundation; we sometimes\n");
printf_filtered ("make exceptions for this. Our decision will be guided by the two goals\n");
printf_filtered ("of preserving the free status of all derivatives of our free software and\n");
printf_filtered ("of promoting the sharing and reuse of software generally.\n");
printf_filtered ("\n");
immediate_quit--;
}
static void
warranty_info ()
{
immediate_quit++;
printf_filtered (" NO WARRANTY\n");
printf_filtered ("\n");
printf_filtered (" 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
printf_filtered ("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n");
printf_filtered ("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
printf_filtered ("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
printf_filtered ("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
printf_filtered ("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n");
printf_filtered ("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n");
printf_filtered ("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
printf_filtered ("REPAIR OR CORRECTION.\n");
printf_filtered ("\n");
printf_filtered (" 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
printf_filtered ("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
printf_filtered ("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
printf_filtered ("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
printf_filtered ("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
printf_filtered ("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
printf_filtered ("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
printf_filtered ("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
printf_filtered ("POSSIBILITY OF SUCH DAMAGES.\n");
printf_filtered ("\n");
immediate_quit--;
}
void
_initialize_copying ()
{
add_info ("copying", copying_info,
"Conditions for redistributing copies of GDB.");
add_info ("warranty", warranty_info,
"Various kinds of warranty you do not have.");
}

View File

@ -1,26 +1,26 @@
/* Work with core dump and executable files, for GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
#include "gdbcore.h"
#include "frame.h" /* required by inferior.h */
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
@ -32,7 +32,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#else
#include <a.out.h>
#endif
#ifndef N_MAGIC
#ifdef COFF_FORMAT
#define N_MAGIC(exec) ((exec).magic)
@ -40,7 +39,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define N_MAGIC(exec) ((exec).a_magic)
#endif
#endif
#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
@ -48,16 +46,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/file.h>
#include <sys/stat.h>
#ifdef UNISOFT_ASSHOLES
#define PMMU
#define NEW_PMMU
#include <sys/seg.h> /* Required for user.ps */
#include <sys/time.h> /* '' */
#include <sys/mmu.h> /* '' */
#include <sys/reg.h>
#define mc68881 /* Required to get float in user.ps */
#endif
#ifdef UMAX_CORE
#include <sys/ptrace.h>
#else
@ -73,8 +61,10 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#endif /* no N_DATADDR */
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -238,18 +228,22 @@ files_info ()
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
if (corefile)
printf ("Core dump file \"%s\".\n", corefile);
else
if (corefile == 0)
printf ("No core dump file\n");
else
printf ("Core dump file \"%s\".\n", corefile);
if (have_inferior_p ())
printf ("Using the running image of the program, rather than these files.\n");
symfile = get_sym_file ();
if (symfile != 0)
printf ("Symbols from \"%s\".\n", symfile);
printf ("Symbols from \"%s\".\n", symfile);
#ifdef FILES_INFO_HOOK
if (FILES_INFO_HOOK ())
return;
#endif
if (! have_inferior_p ())
{
@ -260,11 +254,11 @@ files_info ()
printf ("Data segment in executable from 0x%x to 0x%x.\n",
exec_data_start, exec_data_end);
if (corefile)
printf("(But since we have a core file, we're using...)\n");
printf ("(But since we have a core file, we're using...)\n");
}
if (corefile)
{
printf ("Data segment in core file from 0x%x to 0x%x.\n",
printf ("Data segment in core file from 0x%x to 0x%x.\n",
data_start, data_end);
printf ("Stack segment in core file from 0x%x to 0x%x.\n",
stack_start, stack_end);
@ -282,8 +276,16 @@ read_memory (memaddr, myaddr, len)
char *myaddr;
int len;
{
if (len == 0)
return 0;
if (have_inferior_p ())
return read_inferior_memory (memaddr, myaddr, len);
{
if (remote_debugging)
return remote_read_inferior_memory (memaddr, myaddr, len);
else
return read_inferior_memory (memaddr, myaddr, len);
}
else
return xfer_core_file (memaddr, myaddr, len);
}
@ -299,11 +301,17 @@ write_memory (memaddr, myaddr, len)
int len;
{
if (have_inferior_p ())
return write_inferior_memory (memaddr, myaddr, len);
{
if (remote_debugging)
return remote_write_inferior_memory (memaddr, myaddr, len);
else
return write_inferior_memory (memaddr, myaddr, len);
}
else
error ("Can write memory only when program being debugged is running.");
}
#ifndef XFER_CORE_FILE
/* Read from the program's memory (except for inferior processes).
This function is misnamed, since it only reads, never writes; and
since it will use the core file and/or executable file as necessary.
@ -384,21 +392,29 @@ xfer_core_file (memaddr, myaddr, len)
{
i = min (len, data_start - memaddr);
}
else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
&& memaddr < stack_start)
else if (corechan >= 0
&& memaddr >= data_end && memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (corechan < 0 && memaddr >= exec_data_end)
{
/* Since there is nothing at higher addresses than data
(without a core file or an inferior, there is no
stack, set i to do the rest of the operation now. */
i = len;
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
/* Since there is nothing at higher addresses than
the stack, set i to do the rest of the operation now. */
i = len;
}
else
{
/* Address did not classify into one of the known ranges.
This could be because data_start != exec_data_start
or data_end similarly. */
abort();
This shouldn't happen; we catch the endpoints. */
fatal ("Internal: Bad case logic in xfer_core_file.");
}
/* Now we know which file to use.
@ -419,7 +435,7 @@ xfer_core_file (memaddr, myaddr, len)
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing.
(FIXME we never write.) */
Actually, we never right. */
else
{
bzero (myaddr, i);
@ -432,6 +448,7 @@ xfer_core_file (memaddr, myaddr, len)
}
return returnval;
}
#endif /* XFER_CORE_FILE */
/* My replacement for the read system call.
Used like `read' but keeps going if `read' returns too soon. */

View File

@ -5,14 +5,13 @@
# we setup the TAGS entries to point to the actual source directory.
#
filelist=""
if test -h main.c ; then
if test "`find main.c -type l -print `" != "" ; then
prefix=`ls -l main.c | awk '{print $11}' | sed 's;main.c$;;'`
echo path 1
else
prefix=""
fi
for i in $@ ; do
filelist="$prefix$i $filelist"
filelist="$filelist $prefix$i"
done
#
# Here we simply make sure that the actual machine dependent files being used

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,21 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1988 Free Software Foundation, Inc.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -27,25 +26,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/types.h>
#endif
#ifdef UNISOFT_ASSHOLES
#define PMMU
#define NEW_PMMU
#define mc68881 /* Needed to get float in user.h!!! */
#include <sys/seg.h> /* For user.h */
#include <sys/mmu.h>
#include <sys/time.h>
/* Things Unisoft defined differently from every other Unix system */
#define NBPG PAGESIZE
#define UPAGES USIZE
#define KERNEL_U_ADDR UDOT
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
/* #include <fcntl.h> Can we live without this? */
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
@ -56,7 +42,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
#endif
#include <sys/user.h> /* After a.out.h */
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include <sys/stat.h>
@ -64,28 +50,12 @@ extern int errno;
/* This function simply calls ptrace with the given arguments.
It exists so that all calls to ptrace are isolated in this
machine-dependent file.
If you are having trouble debugging ptrace calls, turn on DEBUG
and every call to ptrace, in this module or elsewhere, will be
logged to stderr. */
machine-dependent file. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
#ifdef DEBUG
int result;
fprintf(stderr, "ptrace(%x,,%x, %x) = ", request, arg3, arg4);
result=ptrace (request, pid, arg3, arg4);
fprintf(stderr, "%x\n", result);
return result;
#define ptrace call_ptrace
#else
return ptrace (request, pid, arg3, arg4);
#endif
}
kill_inferior ()
@ -173,13 +143,7 @@ store_inferior_registers (regno)
{
regaddr = register_addr (regno, offset);
errno = 0;
#ifdef UNISOFT_ASSHOLES
/* You can't write the PC with ptrace 6, only with ptrace 11! */
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
@ -190,12 +154,7 @@ store_inferior_registers (regno)
{
regaddr = register_addr (regno, offset);
errno = 0;
#ifdef UNISOFT_ASSHOLES
if (regno == PC_REGNUM)
ptrace(11, inferior_pid, 16, read_register(regno));
else
#endif
ptrace (6, inferior_pid, regaddr, read_register (regno));
ptrace (6, inferior_pid, regaddr, read_register (regno));
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
@ -229,8 +188,16 @@ read_inferior_memory (memaddr, myaddr, len)
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
#if 0
This is now done by read_memory, because when this function did it,
reading a byte or short int hardware port read whole longs, causing
serious side effects
such as bus errors and unexpected hardware operation. This would
also be a problem with ptrace if the inferior process could read
or write hardware registers, but that's not usually the case.
if (remote_debugging)
buffer[i] = remote_fetch_word (addr);
#endif
else
buffer[i] = ptrace (1, inferior_pid, addr, 0);
if (errno)
@ -304,11 +271,6 @@ write_inferior_memory (memaddr, myaddr, len)
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
@ -325,8 +287,10 @@ write_inferior_memory (memaddr, myaddr, len)
#endif
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -430,6 +394,9 @@ core_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
@ -439,12 +406,12 @@ core_file_command (filename, from_tty)
{
struct user u;
int reg_offset;
unsigned int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
data_start = exec_data_start;
@ -453,8 +420,8 @@ core_file_command (filename, from_tty)
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here; Unisoft
seems to put the offset in the upage of the regs. Sigh. */
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_ar0;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
@ -474,12 +441,17 @@ core_file_command (filename, from_tty)
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0)
perror_with_name (reg_names[regno]);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (reg_names[regno])
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, reg_names[regno]);
perror_with_name (buffer);
}
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (reg_names[regno]);
supply_register (regno, buf);
}
}
@ -526,6 +498,9 @@ exec_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)

View File

@ -1,22 +1,21 @@
/* Basic definitions for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define CORE_ADDR unsigned int
@ -26,16 +25,29 @@ 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[];
/* Various possibilities for alloca. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#ifdef sparc
#include <alloca.h>
#else
extern char *alloca ();
#endif
#endif
extern int quit_flag;
extern int immediate_quit;
#define QUIT { if (quit_flag) quit (); }
/* Notes on classes: class_alias is for alias commands which are not
abbreviations of the original command. */
enum command_class
{
no_class = -1, class_run = 0, class_vars, class_stack,
@ -66,6 +78,12 @@ extern struct cleanup *make_cleanup ();
extern struct cleanup *save_cleanups ();
extern void restore_cleanups ();
extern void free_current_contents ();
extern void reinitialize_more_filter ();
extern void fputs_filtered ();
extern void fprintf_filtered ();
extern void printf_filtered ();
extern void print_spaces_filtered ();
extern char *tilde_expand ();
/* Structure for saved commands lines
(for breakpoints, defined commands, etc). */
@ -82,7 +100,3 @@ struct command_line *read_command_lines ();
char *current_directory;
#ifdef sparc
#include <alloca.h>
#endif

View File

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

View File

@ -1,104 +1,19 @@
/* environ.c -- library for manipulating environments for GNU.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
NO WARRANTY
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
CORRECTION.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
GENERAL PUBLIC LICENSE TO COPY
1. You may copy and distribute verbatim copies of this source file
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy a valid copyright notice "Copyright
(C) 1986 Free Software Foundation, Inc."; and include following the
copyright notice a verbatim copy of the above disclaimer of warranty
and of this License. You may charge a distribution fee for the
physical act of transferring a copy.
2. You may modify your copy or copies of this source file or
any portion of it, and copy and distribute such modifications under
the terms of Paragraph 1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating
that you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish,
that in whole or in part contains or is a derivative of this
program or any part thereof, to be licensed at no charge to all
third parties on terms identical to those contained in this
License Agreement (except that you may choose to grant more extensive
warranty protection to some or all third parties, at your option).
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty
protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other program under the scope of these terms.
3. You may copy and distribute this program (or a portion or derivative
of it, under Paragraph 2) in object code or executable form under the terms
of Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal
shipping charge) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
For an executable file, complete source code means all the source code for
all modules it contains; but, as a special exception, it need not include
source code for modules which are standard libraries that accompany the
operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer this program
except as expressly provided under this License Agreement. Any attempt
otherwise to copy, sublicense, distribute or transfer this program is void and
your rights to use the program under this License agreement shall be
automatically terminated. However, parties who have received computer
software programs from you with this License Agreement will not have
their licenses terminated so long as such parties remain in full compliance.
5. If you wish to incorporate parts of this program into other free
programs whose distribution conditions are different, write to the Free
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
worked out a simple rule that can be stated here, but we will often permit
this. We will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse of
software.
In other words, feel free to share this program, but don't try to
stop anyone else from sharing it. */
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))

View File

@ -1,3 +1,19 @@
/* Header for environment manipulation library.
Copyright (C) 1989, Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* We manipulate environments represented as these structures. */

View File

@ -1,22 +1,21 @@
/* Evaluate expressions for GDB.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -106,8 +105,14 @@ enum noside
{ EVAL_NORMAL,
EVAL_SKIP, /* Only effect is to increment pos. */
EVAL_AVOID_SIDE_EFFECTS, /* Don't modify any variables or
call any functions. Correct type
is returned. */
call any functions. The value
returned will have the correct
type, and will have an
approximately correct lvalue
type (inaccuracy: anything that is
listed as being in a register in
the function in which it was
declared will be lval_register). */
};
value
@ -150,7 +155,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
{
case OP_SCOPE:
tem = strlen (&exp->elts[pc + 2].string);
(*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
(*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);
@ -168,7 +174,28 @@ evaluate_subexp (expect_type, exp, pos, noside)
(*pos) += 2;
if (noside == EVAL_SKIP)
goto nosideret;
return value_of_variable (exp->elts[pc + 1].symbol);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct symbol * sym = exp->elts[pc + 1].symbol;
enum lval_type lv;
switch (SYMBOL_CLASS (sym))
{
case LOC_CONST:
case LOC_LABEL:
case LOC_CONST_BYTES:
lv = not_lval;
case LOC_REGISTER:
case LOC_REGPARM:
lv = lval_register;
default:
lv = lval_memory;
}
return value_zero (SYMBOL_TYPE (sym), lv);
}
else
return value_of_variable (exp->elts[pc + 1].symbol);
case OP_LAST:
(*pos) += 2;
@ -184,7 +211,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
case OP_STRING:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
(*pos) += 2 + ((tem + sizeof (union exp_element))
/ sizeof (union exp_element));
if (noside == EVAL_SKIP)
goto nosideret;
return value_string (&exp->elts[pc + 1].string, tem);
@ -319,11 +347,20 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
{
int static_memfuncp;
argvec[1] = arg2;
argvec[0] =
value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
&static_memfuncp,
op == STRUCTOP_STRUCT
? "structure" : "structure pointer");
if (static_memfuncp)
{
argvec[1] = argvec[0];
nargs--;
argvec++;
}
}
else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
{
@ -354,12 +391,18 @@ evaluate_subexp (expect_type, exp, pos, noside)
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
(*pos) += 2 + ((tem + sizeof (union exp_element))
/ sizeof (union exp_element));
arg1 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
&exp->elts[pc + 1].string),
lval_memory);
else
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
"structure");
case STRUCTOP_PTR:
tem = strlen (&exp->elts[pc + 1].string);
@ -367,8 +410,14 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg1 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure pointer");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE
(VALUE_TYPE (arg1)),
&exp->elts[pc + 1].string),
lval_memory);
else
return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
"structure pointer");
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
@ -376,9 +425,16 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
/* Now, convert these values to an address. */
if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
|| ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
!= TYPE_CODE_MEMBER)
&& (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
!= TYPE_CODE_METHOD)))
error ("non-pointer-to-member value used in pointer-to-member construct");
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)));
VALUE_TYPE (arg3) =
lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
return value_ind (arg3);
case STRUCTOP_MPTR:
@ -387,9 +443,14 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
/* Now, convert these values to an address. */
if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
|| (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER
&& TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD))
error ("non-pointer-to-member value used in pointer-to-member construct");
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)));
VALUE_TYPE (arg3) =
lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
return value_ind (arg3);
case BINOP_ASSIGN:
@ -453,6 +514,10 @@ evaluate_subexp (expect_type, exp, pos, noside)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, 0);
else
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& op == BINOP_DIV)
return value_zero (VALUE_TYPE (arg1), not_lval);
else
return value_binop (arg1, arg2, op);
@ -461,10 +526,14 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
VALUE_LVAL (arg1));
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, 0);
else
return value_subscript (arg1, arg2, op);
return value_subscript (arg1, arg2);
case BINOP_AND:
arg1 = evaluate_subexp (0, exp, pos, noside);
@ -613,7 +682,13 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg2 = evaluate_subexp (0, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_repeat (arg1, (int) value_as_long (arg2));
if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT)
error ("Non-integral right operand for \"@\" operator.");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_repeat_value (VALUE_TYPE (arg1),
(int) value_as_long (arg2));
else
return value_repeat (arg1, (int) value_as_long (arg2));
case BINOP_COMMA:
evaluate_subexp (0, exp, pos, noside);
@ -624,7 +699,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
if (unop_user_defined_p (op, arg1))
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
else
return value_neg (arg1);
@ -633,7 +708,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
if (unop_user_defined_p (op, arg1))
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
else
return value_lognot (arg1);
@ -642,7 +717,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_SKIP)
goto nosideret;
if (unop_user_defined_p (op, arg1))
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
else
return value_from_long (builtin_type_int,
(LONGEST) value_zerop (arg1));
@ -653,6 +728,21 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
|| TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF
/* In C you can dereference an array to get the 1st elt. */
|| TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY
)
return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
lval_memory);
else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
/* GDB allows dereferencing an int. */
return value_zero (BUILTIN_TYPE_LONGEST, lval_memory);
else
error ("Attempt to take contents of a non-pointer value.");
}
return value_ind (arg1);
case UNOP_ADDR:
@ -707,8 +797,11 @@ evaluate_subexp (expect_type, exp, pos, noside)
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
return value_at (exp->elts[pc + 1].type,
(CORE_ADDR) value_as_long (arg1));
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (exp->elts[pc + 1].type, lval_memory);
else
return value_at (exp->elts[pc + 1].type,
(CORE_ADDR) value_as_long (arg1));
case UNOP_PREINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
@ -716,7 +809,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
return arg1;
else if (unop_user_defined_p (op, arg1))
{
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
}
else
{
@ -731,7 +824,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
return arg1;
else if (unop_user_defined_p (op, arg1))
{
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
}
else
{
@ -746,7 +839,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
return arg1;
else if (unop_user_defined_p (op, arg1))
{
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
}
else
{
@ -762,7 +855,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
return arg1;
else if (unop_user_defined_p (op, arg1))
{
return value_x_unop (arg1, op, 0);
return value_x_unop (arg1, op);
}
else
{
@ -816,9 +909,35 @@ evaluate_subexp_for_address (exp, pos, noside)
case OP_VAR_VALUE:
(*pos) += 3;
return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type =
lookup_pointer_type (SYMBOL_TYPE (exp->elts[pc + 1].symbol));
enum address_class sym_class =
SYMBOL_CLASS (exp->elts[pc + 1].symbol);
if (sym_class == LOC_CONST
|| sym_class == LOC_CONST_BYTES
|| sym_class == LOC_REGISTER
|| sym_class == LOC_REGPARM)
error ("Attempt to take address of register or constant.");
return
value_zero (type, not_lval);
}
else
return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
default:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
value x = evaluate_subexp (0, exp, pos, noside);
if (VALUE_LVAL (x) == lval_memory)
return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)),
not_lval);
else
error ("Attempt to take address of non-lval");
}
return value_addr (evaluate_subexp (0, exp, pos, noside));
}
}

View File

@ -1,27 +1,27 @@
/* Print in infix form a struct expression.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "symtab.h"
#include "param.h"
#include "expression.h"
#include "value.h"
#include <stdio.h>
@ -138,14 +138,14 @@ print_subexp (exp, pos, stream, prec)
(*pos) += 3;
value_print (value_from_long (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst),
stream, 0);
stream, 0, Val_no_prettyprint);
return;
case OP_DOUBLE:
(*pos) += 3;
value_print (value_from_double (exp->elts[pc + 1].type,
exp->elts[pc + 2].doubleconst),
stream, 0);
stream, 0, Val_no_prettyprint);
return;
case OP_VAR_VALUE:
@ -155,7 +155,7 @@ print_subexp (exp, pos, stream, prec)
case OP_LAST:
(*pos) += 2;
fprintf (stream, "$%d", exp->elts[pc + 1].longconst);
fprintf (stream, "$%d", (int) exp->elts[pc + 1].longconst);
return;
case OP_REGISTER:
@ -276,6 +276,11 @@ print_subexp (exp, pos, stream, prec)
break;
}
case OP_THIS:
++(*pos);
fprintf (stream, "this");
return;
default:
for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
if (op_print_tab[tem].opcode == opcode)

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,21 @@
/* Parse C expressions for GDB.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
@ -35,6 +34,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include "expression.h"
#include <stdio.h>
#include <a.out.h>
static struct expression *expout;
static int expout_size;
@ -43,6 +43,12 @@ static int expout_ptr;
static int yylex ();
static void yyerror ();
static void write_exp_elt ();
static void write_exp_elt_opcode ();
static void write_exp_elt_sym ();
static void write_exp_elt_longcst ();
static void write_exp_elt_dblcst ();
static void write_exp_elt_type ();
static void write_exp_elt_intern ();
static void write_exp_string ();
static void start_arglist ();
static int end_arglist ();
@ -83,6 +89,19 @@ struct stoken
char *ptr;
int length;
};
/* For parsing of complicated types.
An array should be preceded in the list by the size of the array. */
enum type_pieces
{tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
static enum type_pieces *type_stack;
static int type_stack_depth, type_stack_size;
static void push_type ();
static enum type_pieces pop_type ();
/* Allow debugging of parsing. */
#define YYDEBUG 1
%}
/* Although the yacc "value" of an expression is not used,
@ -91,7 +110,8 @@ struct stoken
%union
{
long lval;
LONGEST lval;
unsigned LONGEST ulval;
double dval;
struct symbol *sym;
struct type *tval;
@ -110,7 +130,13 @@ struct stoken
%type <tvec> nonempty_typelist
%type <bval> block
/* Fancy type parsing. */
%type <voidval> func_mod direct_abs_decl abs_decl
%type <tval> ptype
%type <lval> array_mod
%token <lval> INT CHAR
%token <ulval> UINT
%token <dval> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
@ -122,11 +148,15 @@ struct stoken
Contexts where this distinction is not important can use the
nonterminal "name", which matches either NAME or TYPENAME. */
%token <sval> NAME TYPENAME STRING
%type <sval> name
%token <sval> NAME TYPENAME BLOCKNAME STRING
%type <sval> name name_not_typename typename
%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
%token SIGNED LONG SHORT INT_KEYWORD
%token <lval> LAST REGNAME
%token <ivar> VARIABLE
@ -139,6 +169,7 @@ struct stoken
%left ','
%left ABOVE_COMMA
%right '=' ASSIGN_MODIFY
%right '?'
%left OR
%left AND
%left '|'
@ -147,11 +178,11 @@ struct stoken
%left EQUAL NOTEQUAL
%left '<' '>' LEQ GEQ
%left LSH RSH
%left '@'
%left '+' '-'
%left '*' '/' '%'
%left '@'
%right UNARY INCREMENT DECREMENT
%right ARROW '.' '['
%right ARROW '.' '[' '('
%left COLONCOLON
%%
@ -232,9 +263,9 @@ exp : exp '('
/* This is to save the value of arglist_len
being accumulated by an outer function call. */
{ start_arglist (); }
arglist ')'
arglist ')' %prec ARROW
{ write_exp_elt_opcode (OP_FUNCALL);
write_exp_elt_longcst (end_arglist ());
write_exp_elt_longcst ((LONGEST) end_arglist ());
write_exp_elt_opcode (OP_FUNCALL); }
;
@ -343,7 +374,7 @@ exp : exp OR exp
{ write_exp_elt_opcode (BINOP_OR); }
;
exp : exp '?' exp ':' exp
exp : exp '?' exp ':' exp %prec '?'
{ write_exp_elt_opcode (TERNOP_COND); }
;
@ -359,15 +390,30 @@ exp : exp ASSIGN_MODIFY exp
exp : INT
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_long);
write_exp_elt_longcst ($1);
if ($1 == (int) $1 || $1 == (unsigned int) $1)
write_exp_elt_type (builtin_type_int);
else
write_exp_elt_type (BUILTIN_TYPE_LONGEST);
write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LONG); }
;
exp : UINT
{
write_exp_elt_opcode (OP_LONG);
if ($1 == (unsigned int) $1)
write_exp_elt_type (builtin_type_unsigned_int);
else
write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LONG);
}
;
exp : CHAR
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_char);
write_exp_elt_longcst ($1);
write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LONG); }
;
@ -383,13 +429,13 @@ exp : variable
exp : LAST
{ write_exp_elt_opcode (OP_LAST);
write_exp_elt_longcst ($1);
write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_LAST); }
;
exp : REGNAME
{ write_exp_elt_opcode (OP_REGISTER);
write_exp_elt_longcst ($1);
write_exp_elt_longcst ((LONGEST) $1);
write_exp_elt_opcode (OP_REGISTER); }
;
@ -399,10 +445,10 @@ exp : VARIABLE
write_exp_elt_opcode (OP_INTERNALVAR); }
;
exp : SIZEOF '(' type ')'
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst ((long) TYPE_LENGTH ($3));
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
;
@ -420,7 +466,7 @@ exp : THIS
/* end of C++. */
block : name
block : BLOCKNAME
{
struct symtab *tem = lookup_symtab (copy_name ($1));
struct symbol *sym;
@ -494,12 +540,21 @@ variable: typebase COLONCOLON name
if (i < misc_function_count)
{
enum misc_function_type mft =
(enum misc_function_type)
misc_function_vector[i].type;
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
if (mft == mf_data || mft == mf_bss)
write_exp_elt_type (builtin_type_int);
else if (mft == mf_text)
write_exp_elt_type (lookup_function_type (builtin_type_int));
else
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else
@ -511,7 +566,7 @@ variable: typebase COLONCOLON name
}
;
variable: NAME
variable: name_not_typename
{ struct symbol *sym;
int is_a_field_of_this;
@ -560,12 +615,21 @@ variable: NAME
if (i < misc_function_count)
{
enum misc_function_type mft =
(enum misc_function_type)
misc_function_vector[i].type;
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
write_exp_elt_longcst (misc_function_vector[i].address);
write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_type (builtin_type_char);
if (mft == mf_data || mft == mf_bss)
write_exp_elt_type (builtin_type_int);
else if (mft == mf_text)
write_exp_elt_type (lookup_function_type (builtin_type_int));
else
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else if (symtab_list == 0
@ -578,19 +642,90 @@ variable: NAME
}
;
type : typebase
| type '*'
{ $$ = lookup_pointer_type ($1); }
| type '&'
{ $$ = lookup_reference_type ($1); }
ptype : typebase
| typebase abs_decl
{
/* This is where the interesting stuff happens. */
int done = 0;
int array_size;
struct type *follow_type = $1;
while (!done)
switch (pop_type ())
{
case tp_end:
done = 1;
break;
case tp_pointer:
follow_type = lookup_pointer_type (follow_type);
break;
case tp_reference:
follow_type = lookup_reference_type (follow_type);
break;
case tp_array:
array_size = (int) pop_type ();
if (array_size != -1)
follow_type = create_array_type (follow_type,
array_size);
else
follow_type = lookup_pointer_type (follow_type);
break;
case tp_function:
follow_type = lookup_function_type (follow_type);
break;
}
$$ = follow_type;
}
;
abs_decl: '*'
{ push_type (tp_pointer); $$ = 0; }
| '*' abs_decl
{ push_type (tp_pointer); $$ = $2; }
| direct_abs_decl
;
direct_abs_decl: '(' abs_decl ')'
{ $$ = $2; }
| direct_abs_decl array_mod
{
push_type ((enum type_pieces) $2);
push_type (tp_array);
}
| array_mod
{
push_type ((enum type_pieces) $1);
push_type (tp_array);
$$ = 0;
}
| direct_abs_decl func_mod
{ push_type (tp_function); }
| func_mod
{ push_type (tp_function); }
;
array_mod: '[' ']'
{ $$ = -1; }
| '[' INT ']'
{ $$ = $2; }
;
func_mod: '(' ')'
{ $$ = 0; }
;
type : ptype
| 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)); }
{ $$ = lookup_member_type
(lookup_function_type ($1), $3); }
| type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
{ $$ = lookup_member_type (lookup_function_type ($1));
{ $$ = lookup_member_type
(lookup_function_type ($1), $3);
free ($8); }
;
@ -598,6 +733,20 @@ typebase
: TYPENAME
{ $$ = lookup_typename (copy_name ($1),
expression_context_block, 0); }
| INT_KEYWORD
{ $$ = builtin_type_int; }
| LONG
{ $$ = builtin_type_long; }
| SHORT
{ $$ = builtin_type_short; }
| LONG INT_KEYWORD
{ $$ = builtin_type_long; }
| UNSIGNED LONG INT_KEYWORD
{ $$ = builtin_type_unsigned_long; }
| SHORT INT_KEYWORD
{ $$ = builtin_type_short; }
| UNSIGNED SHORT INT_KEYWORD
{ $$ = builtin_type_unsigned_short; }
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
@ -607,8 +756,33 @@ typebase
| ENUM name
{ $$ = lookup_enum (copy_name ($2),
expression_context_block); }
| UNSIGNED name
| UNSIGNED typename
{ $$ = lookup_unsigned_typename (copy_name ($2)); }
| UNSIGNED
{ $$ = builtin_type_unsigned_int; }
| SIGNED typename
{ $$ = lookup_typename (copy_name ($2),
expression_context_block, 0); }
| SIGNED
{ $$ = builtin_type_int; }
;
typename: TYPENAME
| INT_KEYWORD
{
$$.ptr = "int";
$$.length = 3;
}
| LONG
{
$$.ptr = "long";
$$.length = 4;
}
| SHORT
{
$$.ptr = "short";
$$.length = 5;
}
;
nonempty_typelist
@ -625,8 +799,14 @@ nonempty_typelist
;
name : NAME
| BLOCKNAME
| TYPENAME
;
name_not_typename : NAME
| BLOCKNAME
;
%%
/* Begin counting arguments for a function call,
@ -782,7 +962,7 @@ write_exp_string (str)
}
bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
write_exp_elt_longcst (len);
write_exp_elt_longcst ((LONGEST) len);
}
/* During parsing of a C expression, the pointer to the next character
@ -820,11 +1000,12 @@ parse_number (olen)
int olen;
{
register char *p = lexptr;
register long n = 0;
register LONGEST n = 0;
register int c;
register int base = 10;
register int len = olen;
char *err_copy;
int unsigned_p = 0;
extern double atof ();
@ -850,7 +1031,7 @@ parse_number (olen)
{
c = *p++;
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
if (c != 'l')
if (c != 'l' && c != 'u')
n *= base;
if (c >= '0' && c <= '9')
n += c - '0';
@ -860,6 +1041,16 @@ parse_number (olen)
n += c - 'a' + 10;
else if (len == 0 && c == 'l')
;
else if (len == 0 && c == 'u')
unsigned_p = 1;
else if (base == 10 && len != 0 && (c == 'e' || c == 'E'))
{
/* Scientific notation, where we are unlucky enough not
to have a '.' in the string. */
yylval.dval = atof (lexptr);
lexptr += olen;
return FLOAT;
}
else
{
err_copy = (char *) alloca (olen + 1);
@ -871,8 +1062,16 @@ parse_number (olen)
}
lexptr = p;
yylval.lval = n;
return INT;
if (unsigned_p)
{
yylval.ulval = n;
return UINT;
}
else
{
yylval.lval = n;
return INT;
}
}
struct token
@ -1006,6 +1205,11 @@ yylex ()
lexptr++;
return c;
case '.':
/* Might be a floating point number. */
if (lexptr[1] >= '0' && lexptr[1] <= '9')
break; /* Falls into number code. */
case '+':
case '-':
case '*':
@ -1021,7 +1225,6 @@ yylex ()
case '>':
case '[':
case ']':
case '.':
case '?':
case ':':
case '=':
@ -1047,29 +1250,47 @@ yylex ()
lexptr += namelen + 1;
return STRING;
}
if (c >= '0' && c <= '9')
/* Is it a number? */
/* Note: We have already dealt with the case of the token '.'.
See case '.' above. */
if ((c >= '0' && c <= '9') || c == '.')
{
/* It's a number */
for (namelen = 0;
c = tokstart[namelen],
(c == '_' || c == '$' || c == '.' || (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
namelen++)
;
return parse_number (namelen);
/* It's a number. */
int got_dot = 0, got_e = 0;
register char *p = tokstart;
int hex = c == '0' && (p[1] == 'x' || p[1] == 'X');
if (hex)
p += 2;
for (;; ++p)
{
if (!hex && !got_e && (*p == 'e' || *p == 'E'))
got_dot = got_e = 1;
else if (!hex && !got_dot && *p == '.')
got_dot = 1;
else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
&& (*p == '-' || *p == '+'))
/* This is the sign of the exponent, not the end of the
number. */
continue;
else if (*p < '0' || *p > '9'
&& (!hex || ((*p < 'a' || *p > 'f')
&& (*p < 'A' || *p > 'F'))))
break;
}
return parse_number (p - tokstart);
}
if (!(c == '_' || c == '$'
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
error ("Invalid token in expression.");
/* It is a name. See how long it is. */
for (namelen = 0;
c = tokstart[namelen],
/* It's a name. See how long it is. */
namelen = 0;
for (c = tokstart[namelen];
(c == '_' || c == '$' || (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
namelen++)
c = tokstart[++namelen])
;
/* The token "if" terminates the expression and is NOT
@ -1134,36 +1355,45 @@ yylex ()
return REGNAME;
}
}
if (namelen == 6 && !strncmp (tokstart, "struct", 6))
{
return STRUCT;
}
if (namelen == 5)
/* Catch specific keywords. Should be done with a data structure. */
switch (namelen)
{
case 8:
if (!strncmp (tokstart, "unsigned", 8))
return UNSIGNED;
break;
case 6:
if (!strncmp (tokstart, "struct", 6))
return STRUCT;
if (!strncmp (tokstart, "signed", 6))
return SIGNED;
if (!strncmp (tokstart, "sizeof", 6))
return SIZEOF;
break;
case 5:
if (!strncmp (tokstart, "union", 5))
{
return UNION;
}
}
if (namelen == 4)
{
return UNION;
if (!strncmp (tokstart, "short", 5))
return SHORT;
break;
case 4:
if (!strncmp (tokstart, "enum", 4))
{
return ENUM;
}
return ENUM;
if (!strncmp (tokstart, "long", 4))
return LONG;
if (!strncmp (tokstart, "this", 4)
&& lookup_symbol ("$this", expression_context_block,
VAR_NAMESPACE, 0))
return THIS;
break;
case 3:
if (!strncmp (tokstart, "int", 3))
return INT_KEYWORD;
break;
default:
break;
}
if (namelen == 6 && !strncmp (tokstart, "sizeof", 6))
{
return SIZEOF;
}
if (namelen == 8 && !strncmp (tokstart, "unsigned", 6))
{
return UNSIGNED;
}
yylval.sval.ptr = tokstart;
yylval.sval.length = namelen;
@ -1175,12 +1405,25 @@ yylex ()
return VARIABLE;
}
/* Use token-type TYPENAME for symbols that happen to be defined
/* Use token-type BLOCKNAME for symbols that happen to be defined as
functions or symtabs. If this is not so, then ...
Use token-type TYPENAME for symbols that happen to be defined
currently as names of types; NAME for other symbols.
The caller is not constrained to care about the distinction. */
if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
return TYPENAME;
return NAME;
{
char *tmp = copy_name (yylval.sval);
struct symbol *sym;
if (lookup_partial_symtab (tmp))
return BLOCKNAME;
sym = lookup_symbol (tmp, expression_context_block,
VAR_NAMESPACE, 0);
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
return BLOCKNAME;
if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
return TYPENAME;
return NAME;
}
}
static void
@ -1443,6 +1686,7 @@ parse_c_1 (stringptr, block, comma)
lexptr = *stringptr;
paren_depth = 0;
type_stack_depth = 0;
comma_terminates = comma;
@ -1487,3 +1731,33 @@ parse_c_expression (string)
error ("Junk after end of expression.");
return exp;
}
static void
push_type (tp)
enum type_pieces tp;
{
if (type_stack_depth == type_stack_size)
{
type_stack_size *= 2;
type_stack = (enum type_pieces *)
xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
}
type_stack[type_stack_depth++] = tp;
}
static enum type_pieces
pop_type ()
{
if (type_stack_depth)
return type_stack[--type_stack_depth];
return tp_end;
}
void
_initialize_expread ()
{
type_stack_size = 80;
type_stack_depth = 0;
type_stack = (enum type_pieces *)
xmalloc (type_stack_size * sizeof (enum type_pieces));
}

View File

@ -1,22 +1,21 @@
/* Definitions for expressions stored in reversed prefix form, for GDB.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Definitions for saved C expressions. */

View File

@ -1,22 +1,21 @@
/* Find a variable's value in memory, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -44,7 +43,7 @@ find_saved_register (frame, regnum)
#ifdef HAVE_REGISTER_WINDOWS
/* We assume that a register in a register window will only be saved
in one place (since the name changes and dissapears as you go
in one place (since the name changes and disappears as you go
towards inner frames), so we only call get_frame_saved_regs on
the current frame. This is directly in contradiction to the
usage below, which assumes that registers used in a frame must be
@ -53,9 +52,25 @@ find_saved_register (frame, regnum)
always returns the registers saved within a frame, within the
context (register namespace) of that frame. */
/* However, note that we don't want this to return anything if
nothing is saved (if there's a frame inside of this one). Also,
callers to this routine asking for the stack pointer want the
stack pointer saved for *this* frame; this is returned from the
next frame. */
if (REGISTER_IN_WINDOW_P(regnum))
{
fi = get_frame_info (frame);
frame1 = get_next_frame (frame);
if (!frame1) return 0; /* Registers of this frame are
active. */
/* Get the SP from the next frame in; it will be this
current frame. */
if (regnum != SP_REGNUM)
frame1 = frame;
fi = get_frame_info (frame1);
get_frame_saved_regs (fi, &saved_regs);
return (saved_regs.regs[regnum] ?
saved_regs.regs[regnum] : 0);
@ -228,7 +243,7 @@ supply_register (regno, val)
}
/* Given a struct symbol for a variable,
and a stack frame address, read the value of the variable
and a stack frame id, read the value of the variable
and return a (pointer to a) struct value containing the value. */
value
@ -272,7 +287,13 @@ read_var_value (var, frame)
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_REF_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
addr = read_memory_integer (addr, sizeof (CORE_ADDR));
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
@ -444,15 +465,15 @@ value_from_register (type, regnum, frame)
else
{
/* Raw and virtual formats are the same for this register. */
#ifdef BYTES_BIG_ENDIAN
if (len < REGISTER_RAW_SIZE (regnum))
{
/* Big-endian, and we want less than full size. */
/* Big-endian, and we want less than full size. */
VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
}
#endif
bcopy (virtual_buffer + VALUE_OFFSET (v),
VALUE_CONTENTS (v), len);
}
@ -461,7 +482,7 @@ value_from_register (type, regnum, frame)
}
/* Given a struct symbol for a variable,
and a stack frame address,
and a stack frame id,
return a (pointer to a) struct value containing the variable's address. */
value
@ -473,6 +494,7 @@ locate_var_value (var, frame)
int val = SYMBOL_VALUE (var);
struct frame_info *fi;
struct type *type = SYMBOL_TYPE (var);
struct type *result_type;
if (frame == 0) frame = selected_frame;
@ -509,6 +531,12 @@ locate_var_value (var, frame)
addr = val + FRAME_ARGS_ADDRESS (fi);
break;
case LOC_REF_ARG:
fi = get_frame_info (frame);
addr = val + FRAME_ARGS_ADDRESS (fi);
addr = read_memory_integer (addr, sizeof (CORE_ADDR));
break;
case LOC_LOCAL:
fi = get_frame_info (frame);
addr = val + FRAME_LOCALS_ADDRESS (fi);
@ -523,7 +551,12 @@ locate_var_value (var, frame)
break;
}
return value_cast (lookup_pointer_type (type),
/* Address of an array is of the type of address of it's elements. */
result_type =
lookup_pointer_type (TYPE_CODE (type) == TYPE_CODE_ARRAY ?
TYPE_TARGET_TYPE (type) : type);
return value_cast (result_type,
value_from_long (builtin_type_long, (LONGEST) addr));
}

View File

@ -1,22 +1,21 @@
/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Note that frame.h requires param.h! */
@ -101,6 +100,7 @@ extern void get_frame_saved_regs ();
extern FRAME get_prev_frame ();
extern FRAME get_current_frame ();
extern FRAME get_next_frame ();
extern struct block *get_frame_block ();
extern struct block *get_current_block ();

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +0,0 @@
/* Machine independent variables that describe the core file under GDB.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
/* File names of core file and executable file. */
extern char *corefile;
extern char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
extern int corechan;
extern int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
extern int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
extern CORE_ADDR data_start;
extern CORE_ADDR data_end;
extern CORE_ADDR stack_start;
extern CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
extern CORE_ADDR text_start;
extern CORE_ADDR text_end;
extern CORE_ADDR exec_data_start;
extern CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
extern int text_offset;
/* Address in executable file of start of data area data. */
extern int exec_data_offset;
/* Address in core file of start of data area data. */
extern int data_offset;
/* Address in core file of start of stack area data. */
extern int stack_offset;

View File

@ -1,22 +1,21 @@
/* Print GOULD RISC instructions for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <a.out.h>

View File

@ -1,22 +1,21 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -258,6 +257,7 @@ write_inferior_memory (memaddr, myaddr, len)
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* This should probably be deleted. */
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
@ -279,8 +279,10 @@ write_inferior_memory (memaddr, myaddr, len)
#endif
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -384,6 +386,9 @@ core_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
@ -472,6 +477,9 @@ exec_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)

View File

@ -1,132 +1,79 @@
/* Special version of <a.out.h> for use under hp-ux.
Copyright (C) 1988 Free Software Foundation, Inc. */
Copyright (C) 1988 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this file; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The `exec' structure and overall layout must be close to HP's when
we are running on an HP system, otherwise we will not be able to
execute the resulting file. */
/* Allow this file to be included twice. */
#ifndef EXEC_PAGESIZE
#ifndef __GNU_EXEC_MACROS__
struct exec
{
unsigned short a_machtype; /* machine type */
unsigned short a_magic; /* magic number */
unsigned long a_spare1;
unsigned long a_spare2;
unsigned long a_text; /* size of text segment */
unsigned long a_data; /* size of data segment */
unsigned long a_bss; /* size of bss segment */
unsigned long a_trsize; /* text relocation size */
unsigned long a_drsize; /* data relocation size */
unsigned long a_spare3; /* HP = pascal interface size */
unsigned long a_spare4; /* HP = symbol table size */
unsigned long a_spare5; /* HP = debug name table size */
unsigned long a_entry; /* entry point */
unsigned long a_spare6; /* HP = source line table size */
unsigned long a_spare7; /* HP = value table size */
unsigned long a_syms; /* symbol table size */
unsigned long a_spare8;
};
{
unsigned short a_machtype; /* machine type */
unsigned short a_magic; /* magic number */
unsigned long a_spare1;
unsigned long a_spare2;
unsigned long a_text; /* length of text, in bytes */
unsigned long a_data; /* length of data, in bytes */
unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
unsigned long a_trsize; /* length of relocation info for text, in bytes */
unsigned long a_drsize; /* length of relocation info for data, in bytes */
unsigned long a_spare3; /* HP = pascal interface size */
unsigned long a_spare4; /* HP = symbol table size */
unsigned long a_spare5; /* HP = debug name table size */
unsigned long a_entry; /* start address */
unsigned long a_spare6; /* HP = source line table size */
unsigned long a_spare7; /* HP = value table size */
unsigned long a_syms; /* length of symbol table data in file, in bytes */
unsigned long a_spare8;
};
#define OMAGIC 0x107
#define NMAGIC 0x108
#define ZMAGIC 0x10B
/* Tell a.out.gnu.h not to define `struct exec'. */
#define __STRUCT_EXEC_OVERRIDE__
#define N_BADTYPE(x) \
((((x) . a_magic) != OMAGIC) \
&& (((x) . a_magic) != NMAGIC) \
&& (((x) . a_magic) != ZMAGIC))
#include "../a.out.gnu.h"
#undef N_MAGIC
#undef N_MACHTYPE
#undef N_FLAGS
#undef N_SET_INFO
#undef N_SET_MAGIC
#undef N_SET_MACHTYPE
#undef N_SET_FLAGS
#define N_MAGIC(exec) ((exec) . a_magic)
#define N_MACHTYPE(exec) ((exec) . a_machtype)
#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
#undef N_BADMAG
#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
#define _N_BADMACH(x) \
(((N_MACHTYPE (x)) != HP9000S200_ID) && \
((N_MACHTYPE (x)) != HP98x6_ID))
#define HP98x6_ID 0x20A
#define HP9000S200_ID 0x20C
#define N_BADMACH(x) \
((((x) . a_machtype) != HP9000S200_ID) \
&& (((x) . a_machtype) != HP98x6_ID))
#undef _N_HDROFF
#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
#define N_BADMAG(x) ((N_BADTYPE (x)) || (N_BADMACH (x)))
#define SEGMENT_SIZE 0x1000
#define EXEC_PAGESIZE 0x1000
#define EXEC_ALIGN(offset) \
(((offset) + (EXEC_PAGESIZE - 1)) & (~ (EXEC_PAGESIZE - 1)))
#define N_TXTOFF(x) \
((((x) . a_magic) == ZMAGIC) \
? (EXEC_ALIGN (sizeof (struct exec))) \
: (sizeof (struct exec)))
#define N_DATOFF(x) \
((((x) . a_magic) == ZMAGIC) \
? ((EXEC_ALIGN (sizeof (struct exec))) \
+ (EXEC_ALIGN ((x) . a_text))) \
: ((sizeof (struct exec)) + ((x) . a_text)))
#define N_TROFF(x) \
((((x) . a_magic) == ZMAGIC) \
? ((EXEC_ALIGN (sizeof (struct exec))) \
+ (EXEC_ALIGN ((x) . a_text)) \
+ (EXEC_ALIGN ((x) . a_data))) \
: ((sizeof (struct exec)) + ((x) . a_text) + ((x) . a_data)))
#define N_SYMOFF(x) ((N_TROFF (x)) + ((x) . a_trsize) + ((x) . a_drsize))
#define N_STROFF(x) ((N_SYMOFF (x)) + ((x) . a_syms))
/* Macros which take exec structures as arguments and tell where the
various pieces will be loaded. */
#define N_TXTADDR(x) 0
#define N_DATADDR(x) \
((((x) . a_magic) == OMAGIC) \
? ((x) . a_text) \
: (EXEC_ALIGN ((x) . a_text)))
#define N_BSSADDR(x) ((N_DATADDR (x)) + ((x) . a_data))
struct relocation_info
{
long r_address; /* address which is relocated */
unsigned int
r_symbolnum : 24, /* local symbol ordinal */
r_pcrel : 1, /* was relocated pc relative already */
r_length : 2, /* 0=byte, 1=word, 2=long */
r_extern : 1, /* does not include value of sym referenced */
: 4; /* nothing, yet */
};
struct nlist
{
union
{
char *n_name; /* for use when in-core */
long n_strx; /* index into file string table */
} n_un;
unsigned char n_type; /* type flag (N_TEXT,..) */
char n_other; /* unused */
short n_desc; /* see <stab.h> */
unsigned long n_value; /* value of symbol (or sdb offset) */
};
/* Simple values for n_type. */
#define N_UNDF 0x00 /* undefined */
#define N_ABS 0x02 /* absolute */
#define N_TEXT 0x04 /* text */
#define N_DATA 0x06 /* data */
#define N_BSS 0x08 /* bss */
#define N_COMM 0x12 /* common (internal to ld) */
#define N_FN 0x1F /* file name symbol */
#define N_EXT 0x01 /* external bit, or'ed in */
#define N_TYPE 0x1E /* mask for all the type bits */
/* dbx entries have some of the N_STAB bits set.
These are given in <stab.h> */
#define N_STAB 0xE0 /* if any of these bits set, a dbx symbol */
/* Format for namelist values. */
#define N_FORMAT "%08x"
#endif /* EXEC_PAGESIZE */
#endif /* __GNU_EXEC_MACROS__ */

115
gdb/hp-include/stab.def Normal file
View File

@ -0,0 +1,115 @@
/* Table of DBX symbol codes for the GNU system.
Copyright (C) 1988 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Global variable. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_GSYM, 0x20, "GSYM")
/* Function name for BSD Fortran. Only the name is significant.
To find the address, look in the corresponding external symbol. */
__define_stab (N_FNAME, 0x22, "FNAME")
/* Function name or text-segment variable for C. Value is its address.
Desc is supposedly starting line number, but GCC doesn't set it
and DBX seems not to miss it. */
__define_stab (N_FUN, 0x24, "FUN")
/* Data-segment variable with internal linkage. Value is its address. */
__define_stab (N_STSYM, 0x26, "STSYM")
/* BSS-segment variable with internal linkage. Value is its address. */
__define_stab (N_LCSYM, 0x28, "LCSYM")
/* Name of main routine. Only the name is significant.
This is not used in C. */
__define_stab (N_MAIN, 0x2a, "MAIN")
/* Register variable. Value is number of register. */
__define_stab (N_RSYM, 0x40, "RSYM")
/* Structure or union element. Value is offset in the structure. */
__define_stab (N_SSYM, 0x60, "SSYM")
/* Parameter variable. Value is offset from argument pointer.
(On most machines the argument pointer is the same as the frame pointer. */
__define_stab (N_PSYM, 0xa0, "PSYM")
/* Automatic variable in the stack. Value is offset from frame pointer.
Also used for type descriptions. */
__define_stab (N_LSYM, 0x80, "LSYM")
/* Alternate entry point. Value is its address. */
__define_stab (N_ENTRY, 0xa4, "ENTRY")
/* Name of main source file.
Value is starting text address of the compilation. */
__define_stab (N_SO, 0x64, "SO")
/* Name of sub-source file.
Value is starting text address of the compilation. */
__define_stab (N_SOL, 0x84, "SOL")
/* Line number in text segment. Desc is the line number;
value is corresponding address. */
__define_stab (N_SLINE, 0x44, "SLINE")
/* Similar, for data segment. */
__define_stab (N_DSLINE, 0x46, "DSLINE")
/* Similar, for bss segment. */
__define_stab (N_BSLINE, 0x48, "BSLINE")
/* Beginning of an include file. Only Sun uses this.
In an object file, only the name is significant.
The Sun linker puts data into some of the other fields. */
__define_stab (N_BINCL, 0x82, "BINCL")
/* End of an include file. No name.
These two act as brackets around the file's output.
In an object file, there is no significant data in this entry.
The Sun linker puts data into some of the fields. */
__define_stab (N_EINCL, 0xa2, "EINCL")
/* Place holder for deleted include file.
This appears only in output from the Sun linker. */
__define_stab (N_EXCL, 0xc2, "EXCL")
/* Beginning of lexical block.
The desc is the nesting level in lexical blocks.
The value is the address of the start of the text for the block.
The variables declared inside the block *precede* the N_LBRAC symbol. */
__define_stab (N_LBRAC, 0xc0, "LBRAC")
/* End of a lexical block. Desc matches the N_LBRAC's desc.
The value is the address of the end of the text for the block. */
__define_stab (N_RBRAC, 0xe0, "RBRAC")
/* Begin named common block. Only the name is significant. */
__define_stab (N_BCOMM, 0xe2, "BCOMM")
/* Begin named common block. Only the name is significant
(and it should match the N_BCOMM). */
__define_stab (N_ECOMM, 0xe4, "ECOMM")
/* End common (local name): value is address.
I'm not sure how this is used. */
__define_stab (N_ECOML, 0xe8, "ECOML")
/* Second symbol entry containing a length-value for the preceding entry.
The value is the length. */
__define_stab (N_LENG, 0xfe, "LENG")
/* Global symbol in Pascal.
Supposedly the value is its line number; I'm skeptical. */
__define_stab (N_PC, 0x30, "PC")
/* Modula-2 compilation unit. Can someone say what info it contains? */
__define_stab (N_M2C, 0x42, "M2C")
/* Modula-2 scope information. Can someone say what info it contains? */
__define_stab (N_SCOPE, 0xc4, "SCOPE")

View File

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

View File

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

556
gdb/hp300bsd-dep.c Normal file
View File

@ -0,0 +1,556 @@
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef COFF_ENCAPSULATE
#include "a.out.encap.h"
#else
#include <a.out.h>
#endif
#ifndef N_SET_MAGIC
#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
#endif
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
extern int errno;
/* This function simply calls ptrace with the given arguments.
It exists so that all calls to ptrace are isolated in this
machine-dependent file. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
kill_inferior ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (PT_KILL, inferior_pid, 0, 0);
wait (0);
inferior_died ();
}
/* This is used when GDB is exiting. It gives less chance of error.*/
kill_inferior_fast ()
{
if (remote_debugging)
return;
if (inferior_pid == 0)
return;
ptrace (PT_KILL, inferior_pid, 0, 0);
wait (0);
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
{
errno = 0;
if (remote_debugging)
remote_resume (step, signal);
else
{
ptrace (step ? PT_STEP : PT_CONTINUE, inferior_pid, 1, signal);
if (errno)
perror_with_name ("ptrace");
}
}
void
fetch_inferior_registers ()
{
register int regno;
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
{
*(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, regaddr, 0);
regaddr += sizeof (int);
}
supply_register (regno, buf);
}
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
store_inferior_registers (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
extern char registers[];
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WRITE_U, inferior_pid, regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i]);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
else for (regno = 0; regno < NUM_REGS; regno++)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WRITE_U, inferior_pid, regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i]);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
}
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR.
On failure (cannot read from inferior, usually because address is out
of bounds) returns the value of errno. */
int
read_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
extern int errno;
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
if (remote_debugging)
buffer[i] = remote_fetch_word (addr);
else
buffer[i] = ptrace (PT_READ_I, inferior_pid, addr, 0);
if (errno)
return errno;
}
/* Copy appropriate bytes out of the buffer. */
bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
return 0;
}
/* Copy LEN bytes of data from debugger memory at MYADDR
to inferior's memory at MEMADDR.
On failure (cannot write the inferior)
returns the value of errno. */
int
write_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
/* Round starting address down to longword boundary. */
register CORE_ADDR addr = memaddr & - sizeof (int);
/* Round ending address up; get number of longwords that makes. */
register int count
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
/* Allocate buffer of that many longwords. */
register int *buffer = (int *) alloca (count * sizeof (int));
extern int errno;
/* Fill start and end extra bytes of buffer with existing memory data. */
if (remote_debugging)
buffer[0] = remote_fetch_word (addr);
else
buffer[0] = ptrace (PT_READ_I, inferior_pid, addr, 0);
if (count > 1)
{
if (remote_debugging)
buffer[count - 1]
= remote_fetch_word (addr + (count - 1) * sizeof (int));
else
buffer[count - 1]
= ptrace (PT_READ_I, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
}
/* Copy data to be written over corresponding part of buffer */
bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
/* Write the entire buffer. */
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
if (remote_debugging)
remote_store_word (addr, buffer[i]);
else
ptrace (PT_WRITE_I, inferior_pid, addr, buffer[i]);
if (errno)
return errno;
}
return 0;
}
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
#endif /* no N_TXTADDR */
#ifndef N_DATADDR
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
/* Make COFF and non-COFF names for things a little more compatible
to reduce conditionals later. */
#ifdef COFF_FORMAT
#define a_magic magic
#endif
#ifndef COFF_FORMAT
#define AOUTHDR struct exec
#endif
extern char *sys_siglist[];
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
extern char *corefile;
extern char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
extern int corechan;
extern int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
extern int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
extern CORE_ADDR data_start;
extern CORE_ADDR data_end;
extern CORE_ADDR stack_start;
extern CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
extern CORE_ADDR text_start;
extern CORE_ADDR text_end;
extern CORE_ADDR exec_data_start;
extern CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
extern int text_offset;
/* Address in executable file of start of data area data. */
extern int exec_data_offset;
/* Address in core file of start of data area data. */
extern int data_offset;
/* Address in core file of start of stack area data. */
extern int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
extern FILHDR file_hdr;
extern SCNHDR text_hdr;
extern SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
extern AOUTHDR core_aouthdr;
/* a.out header of exec file. */
extern AOUTHDR exec_aouthdr;
extern void validate_files ();
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name (filename);
data_start = exec_data_start;
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < NUM_REGS; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0)
perror_with_name (filename);
val = myread (corechan, buf, sizeof buf);
if (val < 0)
perror_with_name (filename);
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename);
}
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf ("No core file now.\n");
}
exec_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
/* Eliminate all traces of old exec file.
Mark text segment as empty. */
if (execfile)
free (execfile);
execfile = 0;
data_start = 0;
data_end -= exec_data_start;
text_start = 0;
text_end = 0;
exec_data_start = 0;
exec_data_end = 0;
if (execchan >= 0)
close (execchan);
execchan = -1;
/* Now open and digest the file the user requested, if any. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
perror_with_name (filename);
#ifdef COFF_FORMAT
{
int aout_hdrsize;
int num_sections;
if (read_file_hdr (execchan, &file_hdr) < 0)
error ("\"%s\": not in executable format.", execfile);
aout_hdrsize = file_hdr.f_opthdr;
num_sections = file_hdr.f_nscns;
if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
error ("\"%s\": can't read optional aouthdr", execfile);
if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections) < 0)
error ("\"%s\": can't read text section header", execfile);
if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 0)
error ("\"%s\": can't read data section header", execfile);
text_start = exec_aouthdr.text_start;
text_end = text_start + exec_aouthdr.tsize;
text_offset = text_hdr.s_scnptr;
exec_data_start = exec_aouthdr.data_start;
exec_data_end = exec_data_start + exec_aouthdr.dsize;
exec_data_offset = data_hdr.s_scnptr;
data_start = exec_data_start;
data_end += exec_data_start;
exec_mtime = file_hdr.f_timdat;
}
#else /* not COFF_FORMAT */
{
struct stat st_exec;
#ifdef HEADER_SEEK_FD
HEADER_SEEK_FD (execchan);
#endif
val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
if (val < 0)
perror_with_name (filename);
text_start = N_TXTADDR (exec_aouthdr);
exec_data_start = N_DATADDR (exec_aouthdr);
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
text_end = text_start + exec_aouthdr.a_text;
exec_data_end = exec_data_start + exec_aouthdr.a_data;
data_start = exec_data_start;
data_end += exec_data_start;
fstat (execchan, &st_exec);
exec_mtime = st_exec.st_mtime;
}
#endif /* not COFF_FORMAT */
validate_files ();
}
else if (from_tty)
printf ("No exec file now.\n");
/* Tell display code (if any) about the changed file name. */
if (exec_file_display_hook)
(*exec_file_display_hook) (filename);
}

View File

@ -1,22 +1,21 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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!
*/
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -46,8 +45,8 @@ extern int errno;
It exists so that all calls to ptrace are isolated in this
machine-dependent file. */
int
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
call_ptrace (request, pid, arg3, arg4)
int request, pid, arg3, arg4;
{
return ptrace (request, pid, arg3, arg4);
}
@ -80,9 +79,9 @@ kill_inferior_fast ()
If SIGNAL is nonzero, give it that signal. */
void
resume (step, signal)
int step;
int signal;
resume (step, signal)
int step;
int signal;
{
errno = 0;
if (remote_debugging)
@ -101,16 +100,16 @@ resume (step, signal)
- KERNEL_U_ADDR)
static void
fetch_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
fetch_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
{
#ifndef HPUX_VERSION_5
if (regno == PS_REGNUM)
{
union { int i; short s[2]; } ps_val;
int regval;
ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
regval = ps_val.s[0];
supply_register (regno, &regval);
@ -120,7 +119,7 @@ fetch_inferior_register (regno, regaddr)
{
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);
@ -132,10 +131,10 @@ fetch_inferior_register (regno, regaddr)
}
static void
store_inferior_register_1 (regno, regaddr, value)
int regno;
unsigned int regaddr;
int value;
store_inferior_register_1 (regno, regaddr, value)
int regno;
unsigned int regaddr;
int value;
{
errno = 0;
ptrace (PT_WUAREA, inferior_pid, regaddr, value);
@ -145,7 +144,7 @@ store_inferior_register_1 (regno, regaddr, value)
if (errno != 0)
{
char string_buf[64];
sprintf (string_buf, "writing register number %d", regno);
perror_with_name (string_buf);
}
@ -154,15 +153,15 @@ store_inferior_register_1 (regno, regaddr, value)
}
static void
store_inferior_register (regno, regaddr)
register int regno;
register unsigned int regaddr;
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);
@ -173,7 +172,7 @@ store_inferior_register (regno, regaddr)
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
@ -186,17 +185,23 @@ store_inferior_register (regno, regaddr)
}
void
fetch_inferior_registers ()
fetch_inferior_registers ()
{
struct user u;
register int regno;
register unsigned int ar0_offset;
ar0_offset = (INFERIOR_AR0 (u));
for (regno = 0; (regno < FP0_REGNUM); regno++)
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
extern char registers[];
if (remote_debugging)
remote_fetch_registers (registers);
else
{
ar0_offset = (INFERIOR_AR0 (u));
for (regno = 0; (regno < FP0_REGNUM); regno++)
fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
}
}
/* Store our register values back into the inferior.
@ -208,24 +213,30 @@ store_inferior_registers (regno)
{
struct user u;
register unsigned int ar0_offset;
extern char registers[];
if (regno >= FP0_REGNUM)
if (remote_debugging)
remote_store_registers (registers);
else
{
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
return;
if (regno >= FP0_REGNUM)
{
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
return;
}
ar0_offset = (INFERIOR_AR0 (u));
if (regno >= 0)
{
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
return;
}
for (regno = 0; (regno < FP0_REGNUM); regno++)
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
}
ar0_offset = (INFERIOR_AR0 (u));
if (regno >= 0)
{
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
return;
}
for (regno = 0; (regno < FP0_REGNUM); regno++)
store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
for (; (regno < NUM_REGS); regno++)
store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
return;
}
@ -336,6 +347,7 @@ write_inferior_memory (memaddr, myaddr, len)
/* Work with core dump and executable files, for GDB.
This code would be in core.c if it weren't machine-dependent. */
/* This should probably be deleted. */
/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
#ifdef AOUTHDR
#define COFF_FORMAT
@ -363,8 +375,10 @@ write_inferior_memory (memaddr, myaddr, len)
#endif
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -468,6 +482,9 @@ core_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
@ -571,6 +588,9 @@ exec_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)

View File

@ -1,22 +1,21 @@
/* Low level interface to ptrace, for GDB when running on the Intel 386.
Copyright (C) 1988 Free Software Foundation, Inc.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -283,8 +282,10 @@ write_inferior_memory (memaddr, myaddr, len)
to reduce conditionals later. */
#ifndef COFF_FORMAT
#ifndef AOUTHDR
#define AOUTHDR struct exec
#endif
#endif
extern char *sys_siglist[];
@ -388,6 +389,9 @@ core_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the inferior with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
@ -478,6 +482,9 @@ exec_file_command (filename, from_tty)
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
@ -1129,7 +1136,11 @@ print_387_status (status, ep)
if (ep->r3)
printf ("warning: reserved3 is 0x%x\n", ep->r3);
}
#ifndef U_FPSTATE
#define U_FPSTATE(u) u.u_fpstate
#endif
i386_float_info ()
{
struct user u; /* just for address computations */
@ -1171,7 +1182,7 @@ i386_float_info ()
return;
}
uaddr = (char *)&u.u_fpstate - (char *)&u;
uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
if (have_inferior_p ())
{
int *ip;

View File

@ -1,22 +1,21 @@
/* Print i386 instructions for GDB, the GNU debugger.
Copyright (C) 1988 Free Software Foundation, Inc.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)

View File

@ -1,22 +1,21 @@
/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"
@ -126,8 +125,9 @@ set_args_command (args)
}
void
tty_command (file)
tty_command (file, from_tty)
char *file;
int from_tty;
{
if (file == 0)
error_no_arg ("terminal name for running target process");
@ -160,13 +160,13 @@ Start it from the beginning? "))
kill_inferior ();
}
exec_file = (char *) get_exec_file (1);
if (remote_debugging)
{
free (allargs);
if (from_tty)
{
printf ("Starting program: %s%s\n",
exec_file, inferior_args);
printf ("Starting program: %s\n", exec_file);
fflush (stdout);
}
}
@ -175,7 +175,6 @@ Start it from the beginning? "))
if (args)
set_args_command (args);
exec_file = (char *) get_exec_file (1);
if (from_tty)
{
printf ("Starting program: %s%s\n",
@ -566,7 +565,7 @@ finish_command (arg, from_tty)
value_type));
printf ("Value returned is $%d = ", record_latest_value (val));
value_print (val, stdout, 0);
value_print (val, stdout, 0, Val_no_prettyprint);
putchar ('\n');
}
}
@ -674,11 +673,18 @@ set_environment_command (arg)
}
static void
unset_environment_command (var)
unset_environment_command (var, from_tty)
char *var;
int from_tty;
{
if (var == 0)
error_no_arg ("environment variable");
/* If there is no argument, delete all environment variables.
Ask for confirmation if reading from the terminal. */
if (!from_tty || query ("Delete all environment variables? "))
{
free_environ (inferior_environ);
inferior_environ = make_environ ();
}
unset_in_environ (inferior_environ, var);
}
@ -694,25 +700,48 @@ read_memory_integer (memaddr, len)
short sbuf;
int ibuf;
long lbuf;
int result_err;
extern int sys_nerr;
extern char *sys_errlist[];
if (len == sizeof (char))
{
read_memory (memaddr, &cbuf, len);
result_err = read_memory (memaddr, &cbuf, len);
if (result_err)
error ("Error reading memory address 0x%x: %s (%d).",
memaddr, (result_err < sys_nerr ?
sys_errlist[result_err] :
"uknown error"), result_err);
return cbuf;
}
if (len == sizeof (short))
{
read_memory (memaddr, &sbuf, len);
result_err = read_memory (memaddr, &sbuf, len);
if (result_err)
error ("Error reading memory address 0x%x: %s (%d).",
memaddr, (result_err < sys_nerr ?
sys_errlist[result_err] :
"uknown error"), result_err);
return sbuf;
}
if (len == sizeof (int))
{
read_memory (memaddr, &ibuf, len);
result_err = read_memory (memaddr, &ibuf, len);
if (result_err)
error ("Error reading memory address 0x%x: %s (%d).",
memaddr, (result_err < sys_nerr ?
sys_errlist[result_err] :
"uknown error"), result_err);
return ibuf;
}
if (len == sizeof (lbuf))
{
read_memory (memaddr, &lbuf, len);
result_err = read_memory (memaddr, &lbuf, len);
if (result_err)
error ("Error reading memory address 0x%x: %s (%d).",
memaddr, (result_err < sys_nerr ?
sys_errlist[result_err] :
"uknown error"), result_err);
return lbuf;
}
error ("Cannot handle integers of %d bytes.", len);
@ -763,7 +792,8 @@ registers_info (addr_exp)
}
}
else
printf ("Reg\tContents\n\n");
printf_filtered (
"Register Contents (relative to selected stack frame)\n\n");
for (i = 0; i < NUM_REGS; i++)
{
@ -774,34 +804,26 @@ registers_info (addr_exp)
if (addr_exp != 0 && i != regnum)
continue;
/* On machines with lots of registers, pause every 16 lines
so user can read the output. */
if (addr_exp == 0 && i > 0 && i % 16 == 0)
{
printf ("--Type Return to print more--");
fflush (stdout);
gdb_read_line (0, 0);
}
/* Get the data in raw format, then convert also to virtual format. */
read_relative_register_raw_bytes (i, raw_buffer);
REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
printf ("%s\t", reg_names[i]);
fputs_filtered (reg_names[i], stdout);
print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
/* If virtual format is floating, print it that way. */
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
&& ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
stdout, 0, 1);
stdout, 0, 1, 0, Val_pretty_default);
/* 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))
{
register int j;
printf ("0x");
printf_filtered ("0x");
for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
printf ("%02x", virtual_buffer[j]);
printf_filtered ("%02x", virtual_buffer[j]);
}
/* Else print as integer in hex and in decimal. */
else
@ -810,9 +832,9 @@ registers_info (addr_exp)
bcopy (virtual_buffer, &val, sizeof (long));
if (val == 0)
printf ("0");
printf_filtered ("0");
else
printf ("0x%08x %d", val, val);
printf_filtered ("0x%08x %d", val, val);
}
/* If register has different raw and virtual formats,
@ -822,18 +844,20 @@ registers_info (addr_exp)
{
register int j;
printf (" (raw 0x");
printf_filtered (" (raw 0x");
for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
printf ("%02x", raw_buffer[j]);
printf (")");
printf_filtered ("%02x", raw_buffer[j]);
printf_filtered (")");
}
printf ("\n");
printf_filtered ("\n");
}
printf ("Contents are relative to selected stack frame.\n");
}
#ifdef ATTACH_DETACH
#define PROCESS_ATTACH_ALLOWED 1
#else
#define PROCESS_ATTACH_ALLOWED 0
#endif
/*
* TODO:
* Should save/restore the tty state since it might be that the
@ -841,6 +865,7 @@ registers_info (addr_exp)
* the tty in some state other than what we want. If it's running
* on another terminal or without a terminal, then saving and
* restoring the tty state is a harmless no-op.
* This only needs to be done if we are attaching to a process.
*/
/*
@ -862,14 +887,18 @@ attach_command (args, from_tty)
dont_repeat();
if (!args)
error_no_arg ("process-id to attach");
error_no_arg ("process-id or device file to attach");
while (*args == ' ' || *args == '\t') args++;
if (args[0] == '/')
remote = 1;
else
#ifndef ATTACH_DETACH
error ("Can't attach to a process on this machine.");
#else
pid = atoi (args);
#endif
if (inferior_pid)
{
@ -891,13 +920,17 @@ attach_command (args, from_tty)
fflush (stdout);
}
#ifdef ATTACH_DETACH
if (remote)
{
#endif
remote_open (args, from_tty);
start_remote ();
#ifdef ATTACH_DETACH
}
else
attach_program (pid);
#endif
}
/*
@ -918,24 +951,36 @@ detach_command (args, from_tty)
{
int signal = 0;
if (!inferior_pid)
error ("Not currently tracing a program\n");
if (from_tty)
#ifdef ATTACH_DETACH
if (inferior_pid)
{
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);
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);
}
if (args)
signal = atoi (args);
detach (signal);
inferior_pid = 0;
}
if (args)
signal = atoi (args);
else
#endif
{
if (!remote_debugging)
error ("Not currently attached to subsidiary or remote process.");
detach (signal);
inferior_pid = 0;
if (args)
error ("Argument given to \"detach\" when remotely debugging.");
remote_close (from_tty);
}
}
#endif /* ATTACH_DETACH */
/* ARGUSUED */
static void
@ -983,15 +1028,25 @@ This does not affect the program until the next \"run\" command.",
#ifdef ATTACH_DETACH
add_com ("attach", class_run, attach_command,
"Attach to a process that was started up outside of GDB.\n\
To do this, you must have permission to send the process a signal.\n\
And it must have the same effective uid as the debugger.\n\n\
This command may take as argument a process id or a device file.\n\
For a process id, you must have permission to send the process a signal,\n\
and it must have the same effective uid as the debugger.\n\
For a device file, the file must be a connection to a remote debug server.\n\n\
Before using \"attach\", you must use the \"exec-file\" command\n\
to specify the program running in the process,\n\
and the \"symbol-file\" command to load its symbol table.");
#else
add_com ("attach", class_run, attach_command,
"Attach to a process that was started up outside of GDB.\n\
This commands takes as an argument the name of a device file.\n\
This file must be a connection to a remote debug server.\n\n\
Before using \"attach\", you must use the \"exec-file\" command\n\
to specify the program running in the process,\n\
and the \"symbol-file\" command to load its symbol table.");
#endif
add_com ("detach", class_run, detach_command,
"Detach the process previously attached.\n\
The process is no longer traced and continues its execution.");
#endif /* ATTACH_DETACH */
add_com ("signal", class_run, signal_command,
"Continue program giving it signal number SIGNUMBER.");
@ -1043,9 +1098,9 @@ then the same breakpoint won't break until the Nth time it is reached.");
"Start debugged program. You may specify arguments to give it.\n\
Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\
Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
With no arguments, uses arguments last specified (with \"run\" or \"set-args\".\n\
With no arguments, uses arguments last specified (with \"run\" or \"set args\".\n\
To cancel previous arguments and run with no arguments,\n\
use \"set-args\" without arguments.");
use \"set args\" without arguments.");
add_com_alias ("r", "run", class_run, 1);
add_info ("registers", registers_info,

View File

@ -1,23 +1,22 @@
/* Variables that describe the inferior process running under GDB:
Where it is, why it stopped, and how to step it.
Copyright (C) 1986 Free Software Foundation, Inc.
Copyright (C) 1986, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Structure in which to save the status of the inferior. Save
@ -62,9 +61,12 @@ extern char *inferior_io_terminal;
extern int inferior_pid;
/* Nonzero if debugging a remote machine via a serial link or ethernet. */
extern int remote_debugging;
/* Routines for use in remote debugging. Documented in remote.c. */
int remote_read_inferior_memory ();
int remote_write_inferior_memory ();
/* Last signal that the inferior received (why it stopped). */
extern int stop_signal;
@ -127,5 +129,4 @@ extern char stop_registers[REGISTER_BYTES];
extern int pc_changed;
long read_memory_integer ();

View File

@ -1,22 +1,22 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#include "defs.h"
#include "param.h"
#include "frame.h"
@ -70,7 +70,7 @@ static TERMINAL sg_ours;
static int tflags_inferior;
static int tflags_ours;
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
static struct tchars tc_inferior;
static struct tchars tc_ours;
#endif
@ -78,7 +78,7 @@ static struct tchars tc_ours;
#ifdef TIOCGLTC
static struct ltchars ltc_inferior;
static struct ltchars ltc_ours;
#endif /* TIOCGLTC */
#endif
#ifdef TIOCLGET
static int lmode_inferior;
@ -114,7 +114,7 @@ terminal_init_inferior ()
sg_inferior = sg_ours;
tflags_inferior = tflags_ours;
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
tc_inferior = tc_ours;
#endif
@ -147,7 +147,8 @@ terminal_inferior ()
fcntl (0, F_SETFL, tflags_inferior);
fcntl (0, F_SETFL, tflags_inferior);
ioctl (0, TIOCSETN, &sg_inferior);
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCSETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
@ -211,7 +212,7 @@ terminal_ours_1 (output_only)
terminal_is_ours = 1;
#ifdef TIOCGPGRP
osigttou = signal (SIGTTOU, SIG_IGN);
osigttou = (int (*) ()) signal (SIGTTOU, SIG_IGN);
ioctl (0, TIOCGPGRP, &pgrp_inferior);
ioctl (0, TIOCSPGRP, &pgrp_ours);
@ -225,7 +226,7 @@ terminal_ours_1 (output_only)
tflags_inferior = fcntl (0, F_GETFL, 0);
ioctl (0, TIOCGETP, &sg_inferior);
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCGETC, &tc_inferior);
#endif
#ifdef TIOCGLTC
@ -250,7 +251,7 @@ terminal_ours_1 (output_only)
fcntl (0, F_SETFL, tflags_ours);
ioctl (0, TIOCSETN, &sg_ours);
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCSETC, &tc_ours);
#endif
#ifdef TIOCGLTC
@ -260,7 +261,6 @@ terminal_ours_1 (output_only)
ioctl (0, TIOCLSET, &lmode_ours);
#endif
#ifdef HAVE_TERMIO
sg_ours.c_lflag |= ICANON;
#else /* not HAVE_TERMIO */
@ -275,47 +275,47 @@ term_status_command ()
if (remote_debugging)
{
printf ("No terminal status when remote debugging.\n");
printf_filtered ("No terminal status when remote debugging.\n");
return;
}
printf ("Inferior's terminal status (currently saved by GDB):\n");
printf_filtered ("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",
printf_filtered ("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",
printf_filtered ("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: ");
printf_filtered ("c_cc: ");
for (i = 0; (i < NCC); i += 1)
printf ("0x%x ", sg_inferior.c_cc[i]);
printf ("\n");
printf_filtered ("0x%x ", sg_inferior.c_cc[i]);
printf_filtered ("\n");
#else /* not HAVE_TERMIO */
printf ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
#endif /* not HAVE_TERMIO */
#ifdef TIOCGETC
printf ("tchars: ");
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
printf_filtered ("tchars: ");
for (i = 0; i < sizeof (struct tchars); i++)
printf ("0x%x ", ((char *)&tc_inferior)[i]);
printf ("\n");
printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]);
printf_filtered ("\n");
#endif
#ifdef TIOCGLTC
printf ("ltchars: ");
printf_filtered ("ltchars: ");
for (i = 0; i < sizeof (struct ltchars); i++)
printf ("0x%x ", ((char *)&ltc_inferior)[i]);
printf ("\n");
printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
printf_filtered ("\n");
ioctl (0, TIOCSLTC, &ltc_ours);
#endif
#ifdef TIOCLGET
printf ("lmode: %x\n", lmode_inferior);
printf_filtered ("lmode: %x\n", lmode_inferior);
#endif
}
@ -342,10 +342,15 @@ new_tty (ttyname)
if (tty == -1)
_exit(1);
dup2(tty, 0);
dup2(tty, 1);
dup2(tty, 2);
close(tty);
/* Avoid use of dup2; doesn't exist on all systems. */
if (tty != 0)
{ close (0); dup (tty); }
if (tty != 1)
{ close (1); dup (tty); }
if (tty != 2)
{ close (2); dup (tty); }
if (tty > 2)
close(tty);
}
/* Start an inferior process and returns its pid.
@ -380,9 +385,14 @@ create_inferior (allargs, env)
/* exec is said to fail if the executable is open. */
close_exec_file ();
#if defined(USG) && !defined(HAVE_VFORK)
pid = fork ();
#else
pid = vfork ();
#endif
if (pid < 0)
perror_with_name ("fork");
perror_with_name ("vfork");
if (pid == 0)
{
@ -407,6 +417,10 @@ create_inferior (allargs, env)
if (inferior_io_terminal != 0)
new_tty (inferior_io_terminal);
/* It seems that changing the signal handlers for the inferior after
a vfork also changes them for the superior. See comments in
initialize_signals for how we get the right signal handlers
for the inferior. */
/* Not needed on Sun, at least, and loses there
because it clobbers the superior. */
/*??? signal (SIGQUIT, SIG_DFL);
@ -420,6 +434,10 @@ create_inferior (allargs, env)
fflush (stderr);
_exit (0177);
}
#ifdef CREATE_INFERIOR_HOOK
CREATE_INFERIOR_HOOK (pid);
#endif
return pid;
}
@ -443,11 +461,13 @@ inferior_died ()
inferior_pid = 0;
attach_flag = 0;
mark_breakpoints_out ();
select_frame ( (FRAME) 0, -1);
select_frame ((FRAME) 0, -1);
reopen_exec_file ();
if (have_core_file_p ())
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
else
set_current_frame (0);
}
static void
@ -494,7 +514,7 @@ Report which ones can be written.");
ioctl (0, TIOCGETP, &sg_ours);
fcntl (0, F_GETFL, tflags_ours);
#ifdef TIOCGETC
#if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
ioctl (0, TIOCGETC, &tc_ours);
#endif
#ifdef TIOCGLTC

View File

@ -1,22 +1,21 @@
/* Start and stop the inferior process, for GDB.
Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Notes on the algorithm used in wait_for_inferior to determine if we
just did a subroutine call when stepping. We have the following
@ -134,12 +133,8 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/file.h>
#endif
/* The idiots at Apple only define X_OK if POSIX is defined. Fuck 'em. */
#ifndef X_OK
#define X_OK 1 /* Execute permission for access() */
#endif
#ifdef UMAX_PTRACE
#include <aouthdr.h>
#include <sys/param.h>
#include <sys/ptrace.h>
#endif /* UMAX_PTRACE */
@ -436,6 +431,7 @@ attach_program (pid)
clear_proceed_status ();
stop_after_attach = 1;
/*proceed (-1, 0, -2);*/
terminal_inferior ();
wait_for_inferior ();
normal_stop ();
}
@ -458,23 +454,26 @@ wait_for_inferior ()
int random_signal;
CORE_ADDR stop_sp, prev_sp;
CORE_ADDR prev_func_start, stop_func_start;
char *prev_func_name, *stop_func_name;
CORE_ADDR prologue_pc;
int stop_step_resume_break;
CORE_ADDR step_resume_break_sp;
int newmisc;
int newfun_pc;
struct symbol *newfun;
struct symtab_and_line sal;
int prev_pc;
extern CORE_ADDR text_end;
int remove_breakpoints_on_following_step = 0;
prev_pc = read_pc ();
prev_func_start = get_pc_function_start (prev_pc) + FUNCTION_START_OFFSET;
(void) find_pc_partial_function (prev_pc, &prev_func_name,
&prev_func_start);
prev_func_start += FUNCTION_START_OFFSET;
prev_sp = read_register (SP_REGNUM);
while (1)
{
/* Clean up saved state that will become invalid */
/* Clean up saved state that will become invalid. */
pc_changed = 0;
flush_cached_frames ();
@ -487,7 +486,7 @@ wait_for_inferior ()
continue;
}
/* See if the process still exists; clean up if it doesn't. */
/* See if the process still exists; clean up if it doesn't. */
if (WIFEXITED (w))
{
terminal_ours_for_output ();
@ -498,8 +497,8 @@ wait_for_inferior ()
fflush (stdout);
inferior_died ();
#ifdef NO_SINGLE_STEP
one_stepped = 0; /* Clear single_step state since proc gone */
#endif /* NO_SINGLE_STEP */
one_stepped = 0;
#endif
stop_print_frame = 0;
break;
}
@ -517,42 +516,29 @@ wait_for_inferior ()
printf ("The inferior process no longer exists.\n");
fflush (stdout);
#ifdef NO_SINGLE_STEP
one_stepped = 0; /* Clear single_step state since proc gone */
#endif /* NO_SINGLE_STEP */
one_stepped = 0;
#endif
break;
}
#ifdef NO_SINGLE_STEP
if (one_stepped)
single_step (0); /* This actually cleans up the ss */
#endif /* NO_SINGLE_STEP */
fetch_inferior_registers ();
stop_pc = read_pc ();
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
#ifdef CONVEX_PTRACE
/* pop frame stored by user-mode trap, if present */
if (stop_pc == BREAK_TRAP_ADDR)
{
POP_FRAME;
stop_pc = read_pc () - 2;
write_register (PC_REGNUM, stop_pc);
#ifdef NPC_REGNUM
write_register (NPC_REGNUM, stop_pc + 4);
#endif
pc_changed = 0;
}
else if (stop_pc > STACK_END_ADDR)
{
POP_FRAME;
stop_pc = read_pc ();
}
#endif /* CONVEX_PTRACE */
stop_frame_address = FRAME_FP (get_current_frame ());
stop_sp = read_register (SP_REGNUM);
stop_func_start =
get_pc_function_start (stop_pc) + FUNCTION_START_OFFSET;
stop_func_start = 0;
/* Don't care about return value; stop_func_start will be 0
if it doesn't work. */
(void) find_pc_partial_function (stop_pc, &stop_func_name,
&stop_func_start);
stop_func_start += FUNCTION_START_OFFSET;
another_trap = 0;
stop_breakpoint = 0;
stop_step = 0;
@ -562,30 +548,28 @@ wait_for_inferior ()
random_signal = 0;
stopped_by_random_signal = 0;
breakpoints_failed = 0;
/* Look at the cause of the stop, and decide what to do.
The alternatives are:
1) break; to really stop and return to the debugger,
2) drop through to start up again
(set another_trap to 1 to single step once)
(set another_trap to 1 to single step once)
3) set random_signal to 1, and the decision between 1 and 2
will be made according to the signal handling tables. */
will be made according to the signal handling tables. */
stop_signal = WSTOPSIG (w);
/* First, distinguish signals caused by the debugger from signals
that have to do with the program's own actions.
Note that breakpoint insns may cause SIGTRAP or SIGILL
or SIGEMT, depending on the operating system version.
Here we detect when a SIGILL or SIGEMT is really a breakpoint
and change it to SIGTRAP. */
if (stop_signal == SIGTRAP
#ifndef CONVEX_PTRACE
|| (breakpoints_inserted &&
(stop_signal == SIGILL
|| stop_signal == SIGEMT))
#endif /* not CONVEX_PTRACE */
|| stop_after_attach)
{
if (stop_signal == SIGTRAP && stop_after_trap)
@ -614,43 +598,44 @@ wait_for_inferior ()
&& step_range_end && !step_resume_break_address))
#endif /* DECR_PC_AFTER_BREAK not zero */
{
/* For condition exprs. */
select_frame (get_current_frame (), 0);
stop_breakpoint =
breakpoint_stop_status (stop_pc, stop_frame_address);
/* Following in case break condition called a
function. */
stop_print_frame = 1;
if (stop_breakpoint && DECR_PC_AFTER_BREAK)
/* See if we stopped at the special breakpoint for
stepping over a subroutine call. */
if (stop_pc - DECR_PC_AFTER_BREAK
== step_resume_break_address)
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
#ifdef NPC_REGNUM
write_register (NPC_REGNUM, stop_pc + 4);
#endif
pc_changed = 0;
stop_step_resume_break = 1;
if (DECR_PC_AFTER_BREAK)
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
pc_changed = 0;
}
}
}
/* See if we stopped at the special breakpoint for
stepping over a subroutine call. */
if (stop_pc - DECR_PC_AFTER_BREAK
== step_resume_break_address)
{
stop_step_resume_break = 1;
if (DECR_PC_AFTER_BREAK)
else
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
pc_changed = 0;
stop_breakpoint =
breakpoint_stop_status (stop_pc, stop_frame_address);
/* Following in case break condition called a
function. */
stop_print_frame = 1;
if (stop_breakpoint && DECR_PC_AFTER_BREAK)
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_register (PC_REGNUM, stop_pc);
#ifdef NPC_REGNUM
write_register (NPC_REGNUM, stop_pc + 4);
#endif
pc_changed = 0;
}
}
}
}
if (stop_signal == SIGTRAP)
random_signal
= !(stop_breakpoint || trap_expected
|| stop_step_resume_break
#ifndef CONVEX_PTRACE
#ifndef CANNOT_EXECUTE_STACK
|| (stop_sp INNER_THAN stop_pc
&& stop_pc INNER_THAN stop_frame_address)
#else
@ -662,11 +647,11 @@ wait_for_inferior ()
random_signal
= !(stop_breakpoint
|| stop_step_resume_break
#ifdef news800
#ifdef sony_news
|| (stop_sp INNER_THAN stop_pc
&& stop_pc INNER_THAN stop_frame_address)
#endif
);
if (!random_signal)
stop_signal = SIGTRAP;
@ -674,18 +659,18 @@ wait_for_inferior ()
}
else
random_signal = 1;
/* For the program's own signals, act according to
the signal handling tables. */
if (random_signal
&& !(running_in_shell && stop_signal == SIGSEGV))
{
/* Signal not for debugging purposes. */
int printed = 0;
stopped_by_random_signal = 1;
if (stop_signal >= NSIG
|| signal_print[stop_signal])
{
@ -694,8 +679,8 @@ wait_for_inferior ()
printf ("\nProgram received signal %d, %s\n",
stop_signal,
stop_signal < NSIG
? sys_siglist[stop_signal]
: "(undocumented)");
? sys_siglist[stop_signal]
: "(undocumented)");
fflush (stdout);
}
if (stop_signal >= NSIG
@ -706,9 +691,9 @@ wait_for_inferior ()
else if (printed)
terminal_inferior ();
}
/* Handle cases caused by hitting a breakpoint. */
if (!random_signal
&& (stop_breakpoint || stop_step_resume_break))
{
@ -743,20 +728,14 @@ wait_for_inferior ()
the stack pointer doesn't have to change if it
the bp was set in a routine without a frame (pc can
be stored in some other window).
The removal of the sp test is to allow calls to
alloca. Nasty things were happening. Oh, well,
gdb can only handle one level deep of lack of
frame pointer. */
if (stop_step_resume_break
&& (step_frame_address == 0
|| (stop_frame_address == step_frame_address
#if 0
#ifndef HAVE_REGISTER_WINDOWS
&& step_resume_break_sp INNER_THAN stop_sp
#endif
#endif
)))
|| (stop_frame_address == step_frame_address)))
{
remove_step_breakpoint ();
step_resume_break_address = 0;
@ -770,32 +749,31 @@ wait_for_inferior ()
breakpoints_inserted = 0;
another_trap = 1;
}
/* We come here if we hit a breakpoint but should not
stop for it. Possibly we also were stepping
and should stop for that. So fall through and
test for stepping. But, if not stepping,
do not stop. */
}
/* If this is the breakpoint at the end of a stack dummy,
just stop silently. */
#ifndef CONVEX_PTRACE
#ifndef CANNOT_EXECUTE_STACK
if (stop_sp INNER_THAN stop_pc
&& stop_pc INNER_THAN stop_frame_address)
#else
/* "stack" dummy must be in text segment for Convex Unix */
if (stop_pc == text_end - 2)
if (stop_pc == text_end - 2)
#endif
{
stop_print_frame = 0;
stop_stack_dummy = 1;
#ifdef HP9K320
trap_expected_after_continue = 1;
{
stop_print_frame = 0;
stop_stack_dummy = 1;
#ifdef HP_OS_BUG
trap_expected_after_continue = 1;
#endif
break;
}
break;
}
if (step_resume_break_address)
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
@ -812,7 +790,7 @@ wait_for_inferior ()
just changed, we've stepped outside */
&& !(stop_pc == step_range_start
&& stop_frame_address
&& (stop_sp != prev_sp
&& (stop_sp INNER_THAN prev_sp
|| stop_frame_address != step_frame_address)))
{
/* Don't step through the return from a function
@ -823,7 +801,7 @@ wait_for_inferior ()
break;
}
}
/* We stepped out of the stepping range. See if that was due
to a subroutine call that we should proceed to the end of. */
else if (!random_signal && step_range_end)
@ -834,16 +812,35 @@ wait_for_inferior ()
SKIP_PROLOGUE (prologue_pc);
}
/* ==> See comments at top of file on this algorithm. <==*/
/* Did we just take a signal? */
if (stop_func_name && !strcmp ("_sigtramp", stop_func_name)
&& (!prev_func_name || strcmp ("_sigtramp", prev_func_name)))
{
/* We've just taken a signal; go until we are back to
the point where we took it and one more. */
step_resume_break_address = prev_pc;
step_resume_break_duplicate =
breakpoint_here_p (step_resume_break_address);
step_resume_break_sp = stop_sp;
if (breakpoints_inserted)
insert_step_breakpoint ();
/* Make sure that the stepping range gets us past
that instruction. */
if (step_range_end == 1)
step_range_end = (step_range_start = prev_pc) + 1;
remove_breakpoints_on_following_step = 1;
}
if (stop_pc == stop_func_start
/* ==> See comments at top of file on this algorithm. <==*/
else if (stop_pc == stop_func_start
&& (stop_func_start != prev_func_start
|| prologue_pc != stop_func_start
|| stop_sp != prev_sp))
{
newfun = find_pc_function (stop_pc);
/* It's a subroutine call */
if (step_over_calls > 0 || (step_over_calls && newfun == 0))
if (step_over_calls > 0
|| (step_over_calls && find_pc_function (stop_pc) == 0))
{
/* A subroutine call has happened. */
/* Set a special breakpoint after the return */
@ -867,7 +864,7 @@ wait_for_inferior ()
/* If the prologue ends in the middle of a source line,
continue to the end of that source line.
Otherwise, just go to end of prologue. */
#ifdef convex
#ifdef PROLOGUE_FIRSTLINE_OVERLAP
/* no, don't either. It skips any code that's
legitimately on the first line. */
#else
@ -925,6 +922,7 @@ wait_for_inferior ()
original pc would not have
been at the start of a
function. */
prev_func_name = stop_func_name;
prev_sp = stop_sp;
/* If we did not do break;, it means we should keep
@ -947,6 +945,15 @@ wait_for_inferior ()
{
resume (0, SIGSEGV);
}
else if (trap_expected && stop_signal != SIGTRAP)
{
/* We took a signal which we are supposed to pass through to
the inferior and we haven't yet gotten our trap. Simply
continue. */
resume ((step_range_end && !step_resume_break_address)
|| trap_expected,
stop_signal);
}
else
{
/* Here, we are not awaiting another exec to get
@ -954,7 +961,16 @@ wait_for_inferior ()
Insert breakpoints now, unless we are trying
to one-proceed past a breakpoint. */
running_in_shell = 0;
if (!breakpoints_inserted && !another_trap)
/* If we've just finished a special step resume and we don't
want to hit a breakpoint, pull em out. */
if (!step_resume_break_address &&
remove_breakpoints_on_following_step)
{
remove_breakpoints_on_following_step = 0;
remove_breakpoints ();
breakpoints_inserted = 0;
}
else if (!breakpoints_inserted && !another_trap)
{
insert_step_breakpoint ();
breakpoints_failed = insert_breakpoints ();
@ -985,10 +1001,6 @@ wait_for_inferior ()
BREAKPOINTS_FAILED nonzero means stop was due to error
attempting to insert breakpoints. */
/* FIXME, normal_stop is ALWAYS called immediately after wait_for_inferior.
They should probably be merged into a single function, since that
would avoid numerous tests (e.g. of inferior_pid). */
static void
normal_stop ()
{
@ -1029,7 +1041,7 @@ Further execution is probably impossible.\n");
delete that auto-display to avoid an infinite recursion. */
if (stopped_by_random_signal)
delete_current_display ();
disable_current_display ();
if (step_multi && stop_step)
return;
@ -1052,10 +1064,10 @@ This is so that \"sh\" will process wildcards and I/O redirection.\n\
This time, \"sh\" crashed.\n\
\n\
One known bug in \"sh\" bites when the environment takes up a lot of space.\n\
Try \"info env\" to see the environment; then use \"unset-env\" to kill\n\
Try \"info env\" to see the environment; then use \"delete env\" to kill\n\
some variables whose values are large; then do \"run\" again.\n\
\n\
If that works, you might want to put those \"unset-env\" commands\n\
If that works, you might want to put those \"delete 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. */
@ -1211,37 +1223,34 @@ signals_info (signum_exp)
char *signum_exp;
{
register int i;
printf ("Number\tStop\tPrint\tPass to program\tDescription\n");
printf_filtered ("Number\tStop\tPrint\tPass to program\tDescription\n");
if (signum_exp)
{
i = parse_and_eval_address (signum_exp);
printf ("%d\t", i);
printf ("%s\t", signal_stop[i] ? "Yes" : "No");
printf ("%s\t", signal_print[i] ? "Yes" : "No");
printf ("%s\t\t", signal_program[i] ? "Yes" : "No");
printf ("%s\n", sys_siglist[i]);
if (i >= NSIG || i < 0)
error ("Signal number out of bounds.");
printf_filtered ("%d\t", i);
printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
printf_filtered ("%s\n", sys_siglist[i]);
return;
}
printf ("\n");
printf_filtered ("\n");
for (i = 0; i < NSIG; i++)
{
QUIT;
if (i > 0 && i % 16 == 0)
{
printf ("[Type Return to see more]");
fflush (stdout);
gdb_read_line (0, 0);
}
printf ("%d\t", i);
printf ("%s\t", signal_stop[i] ? "Yes" : "No");
printf ("%s\t", signal_print[i] ? "Yes" : "No");
printf ("%s\t\t", signal_program[i] ? "Yes" : "No");
printf ("%s\n", sys_siglist[i]);
printf_filtered ("%d\t", i);
printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
printf_filtered ("%s\n", sys_siglist[i]);
}
printf ("\nUse the \"handle\" command to change these tables.\n");
printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
}
/* Save all of the information associated with the inferior<==>gdb

View File

@ -1,3 +1,22 @@
/* Main loop for the standalone kernel debugger.
Copyright (C) 1989, Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "param.h"

View File

@ -1,85 +1,93 @@
head 1.2;
access ;
symbols ;
locks ; strict;
comment @ * @;
/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
Copyright (C) 1987,1989 Free Software Foundation, Inc.
This file is part of GDB.
1.2
date 89.03.27.20.17.11; author gnu; state Exp;
branches ;
next 1.1;
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
1.1
date 89.03.20.19.29.58; author gnu; state Exp;
branches ;
next ;
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
desc
@@
/* The altos support would make a good base for a port to other USGR2 systems
(like the 3b1 and the Convergent miniframe). */
/* This is only needed in one file, but it's cleaner to put it here than
putting in more #ifdef's. */
#include <sys/page.h>
#include <sys/net.h>
1.2
log
@Change "HPUX_ASM" define to "USG_SGS_ASM", since it's really the USG
Software Generation System assembler that we're fighting here.
.,
@
text
@/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef HP9K320
#define HP9K320
#ifndef ALTOS
#define ALTOS
#endif
/* Set flag to indicate whether HP's assembler is in use. */
#ifdef __GNU__
#ifdef __HPUX_ASM__
#define USG_SGS_ASM
#endif
#else
#define USG_SGS_ASM
#endif
/* Define this for versions of hp-ux older than 6.0 */
/* #define HPUX_VERSION_5 */
/* define USG if you are using sys5 /usr/include's */
#define USG
#define HAVE_TERMIO
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Get rid of any system-imposed stack limit if possible. */
/* #define SET_STACK_LIMIT_HUGE */
/*#define SET_STACK_LIMIT_HUGE*/
#define HAVE_TERMIO
#define CBREAK XTABS /* It takes all kinds... */
/*
* #define FLOATING_POINT if you have 68881
* This hasn't been tested
*/
/*#define FLOATING_POINT*/
/*#undef FLOATING_POINT*/
#ifndef __GNUC__
#undef USE_GAS
#define ALTOS_AS
#else
#define USE_GAS
#endif
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN (1024)
#endif
/* Motorola assembly format */
#if !defined(USE_GAS) && !defined(ALTOS)
#define MOTOROLA
#endif
/* Get sys/wait.h ie. from a Sun and edit it a little (mc68000 to m68k) */
#define HAVE_WAIT_STRUCT
/* 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
#undef NAMES_HAVE_UNDERSCORE
/* Debugger information will be in DBX format. */
/* Exec files and symbol tables are in COFF format */
#define READ_DBX_FORMAT
#define COFF_FORMAT
#define COFF_NO_LONG_FILE_NAMES
#define vfork fork
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -91,14 +99,20 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
else if (op == 0060000) \
pc += 4; /* Skip bra #word */ \
else if (op == 00600377) \
pc += 6; /* skip bra #long */ \
else if ((op & 0177400) == 0060000) \
pc += 2; /* skip bra #char */ \
}
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
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. */
@ -106,17 +120,14 @@ anyone else from sharing it farther. Help stamp out software hoarding!
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. */
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
#define KERNEL_U_ADDR 0x1fbf000
/* Address of end of stack space. */
#define STACK_END_ADDR 0xFFF00000
/*#define STACK_END_ADDR (0xffffff)*/
#define STACK_END_ADDR (0x1000000)
/* Stack grows downward. */
@ -124,13 +135,14 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Sequence of bytes for breakpoint instruction. */
#define BREAKPOINT {0x4e, 0x41}
#define BREAKPOINT {0x4e, 0x4e}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
but not always.
On the Altos, the kernel resets the pc to the trap instr */
#define DECR_PC_AFTER_BREAK 2
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. */
@ -138,7 +150,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
#define INVALID_FLOAT(p, len) (*((int *) (p)) == -1) /* Just a first guess; not checked */
/* Largest integer type */
#define LONGEST long
@ -152,17 +164,30 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Number of machine registers */
#define NUM_REGS 29
#ifdef FLOATING_POINT
#define NUM_REGS 31
#else
#define NUM_REGS 18
#endif
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#ifdef FLOATING_POINT
#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" }
"fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" \
}
#else
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"ps", "pc", \
}
#endif
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
@ -180,7 +205,7 @@ read_memory_integer (read_register (SP_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)
#define REGISTER_BYTES (16*4+8*12+8+20)
/* Index within `registers' of the first byte of the space for
register N. */
@ -193,6 +218,8 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Number of bytes of storage in the actual machine representation
for register N. On the 68000, all regs are 4 bytes
except the floating point regs which are 12 bytes. */
/* Note that the unsigned cast here forces the result of the
subtractiion to very high positive values if N < FP0_REGNUM */
#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
@ -202,6 +229,15 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ if (regno <= SP_REGNUM) \
addr = blockend + regno * 4; \
else if (regno == PS_REGNUM) \
addr = blockend + regno * 4 + 4; \
else if (regno == PC_REGNUM) \
addr = blockend + regno * 4 + 2; \
}
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
@ -277,11 +313,6 @@ read_memory_integer (read_register (SP_REGNUM), 4)
? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
: (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
- ((char *) (& u)))
/* It is safe to look for symsegs on a Sun, because Sun's ld
does not screw up with random garbage at end of file. */
#define READ_GDB_SYMSEGS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@ -296,18 +327,27 @@ read_memory_integer (read_register (SP_REGNUM), 4)
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the Sun, the frame's nominal address
/* In the case of the Altos, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -317,13 +357,20 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Set VAL to the number of args passed to frame described by FI.
Can set VAL to -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the C compiler delays popping them. */
#define FRAME_NUM_ARGS(val,fi) (val = -1)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
/* We can't tell how many args there are
now that the (gnu) C compiler delays popping them.
Perhaps we could tell if we use the Altos cc, but I'm not sure
COFF_FORMAT is the right conditional */
#ifdef COFF_FORMAT
#define FRAME_NUM_ARGS(val, fi) (val = -1)
#if 0
#define FRAME_NUM_ARGS(val, fi) \
{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
{ register 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 */ \
@ -392,7 +439,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
if (regmask & 1) \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \
{ regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
(frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
/* fmovemx to index of sp may follow. */ \
@ -414,6 +461,147 @@ read_memory_integer (read_register (SP_REGNUM), 4)
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
}
#if 0
{ 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; \
}
#endif
#if 0
#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; \
}
#endif
#else
#define FRAME_NUM_ARGS(val, fi) (val = -1)
#endif
/* Things needed for making the inferior call functions. */
/* Push an empty stack frame, to record the current PC, etc. */
@ -437,30 +625,30 @@ read_memory_integer (read_register (SP_REGNUM), 4)
restoring all saved registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
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]) \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM),\
read_pc ()));}
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
/* This sequence of words is the instructions
fmovem 0xff,-(sp)
@ -471,7 +659,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
no code is needed in the dummy for this.
The CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @@#32323232
jsr @#32323232
addl #69696969,sp
bpt
nop
@ -484,7 +672,7 @@ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71}
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4e4e71}
#define CALL_DUMMY_LENGTH 28
@ -513,95 +701,101 @@ taken for the arguments. */
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. */
#ifdef MOTOROLA
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("move.l $ end, sp"); \
asm ("clr.l fp"); }
#else
#ifdef ALTOS_AS
#define INIT_STACK(beg, end) \
{ asm ("global end"); \
asm ("mov.l &end,%sp"); \
asm ("clr.l %fp"); }
#else
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movel $ end, sp"); \
asm ("clrl fp"); }
#endif
#endif
/* Push the frame pointer register on the stack. */
#ifdef MOTOROLA
#define PUSH_FRAME_PTR \
asm ("move.l fp, -(sp)");
#else
#ifdef ALTOS_AS
#define PUSH_FRAME_PTR \
asm ("mov.l %fp, -(%sp)");
#else
#define PUSH_FRAME_PTR \
asm ("movel fp, -(sp)");
#endif
#endif
/* Copy the top-of-stack to the frame pointer register. */
#ifdef MOTOROLA
#define POP_FRAME_PTR \
asm ("move.l (sp), fp");
#else
#ifdef ALTOS_AS
#define POP_FRAME_PTR \
asm ("mov.l (%sp), %fp");
#else
#define POP_FRAME_PTR \
asm ("movl (sp), fp");
#endif
#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
#ifdef ALTOS_AS
#define PUSH_REGISTERS \
{ asm ("clr.w -(%sp)"); \
asm ("pea (10,%sp)"); \
asm ("movm.l &0xfffe,-(%sp)"); }
#else
#define PUSH_REGISTERS \
{ asm ("clrw -(sp)"); \
asm ("pea 10(sp)"); \
asm ("movem $ 0xfffe,-(sp)"); }
#endif
#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
#ifdef ALTOS_AS
#define POP_REGISTERS \
{ asm ("sub.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
#endif
#else /* HPUX_ASM */
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm ("global end"); \
asm ("mov.l &end,%sp"); \
asm ("clr.l %a6"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("mov.l %fp,-(%sp)");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("mov.l (%sp),%fp");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("clr.w -(%sp)"); \
asm ("pea 10(%sp)"); \
asm ("movm.l &0xfffe,-(%sp)"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("subi.l &8,28(%sp)"); \
asm ("mov.m (%sp),&0xffff"); \
asm ("rte"); }
#endif /* HPUX_ASM */
@
1.1
log
@Initial revision
@
text
@d28 1
a28 1
#define HPUX_ASM
d31 1
a31 1
#define HPUX_ASM
@

603
gdb/m-convex.h Normal file
View File

@ -0,0 +1,603 @@
/* Definitions to make GDB run on Convex Unix (4bsd)
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Describe the endian nature of this machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Include certain files for dbxread.c */
#include <convex/filehdr.h>
#include <convex/opthdr.h>
#include <convex/scnhdr.h>
#include <nlist.h>
#define LONG_LONG
#define ATTACH_DETACH
#define HAVE_WAIT_STRUCT
#define NO_SIGINTERRUPT
/* 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
/* There is come problem with the debugging symbols generated by the
compiler such that the debugging symbol for the first line of a
function overlap with the function prologue. */
#define PROLOGUE_FIRSTLINE_OVERLAP
/* When convex pcc says CHAR or SHORT, it provides the correct address. */
#define BELIEVE_PCC_PROMOTION 1
/* Symbol types to ignore. */
#define IGNORE_SYMBOL(TYPE) \
(((TYPE) & ~N_EXT) == N_TBSS || ((TYPE) & ~N_EXT) == N_TDATA)
/* Use SIGCONT rather than SIGTSTP because convex Unix occasionally
turkeys SIGTSTP. I think. */
#define STOP_SIGNAL SIGCONT
/* Convex ld sometimes omits _etext.
Get text segment end from a.out header in this case. */
extern unsigned text_end;
#define END_OF_TEXT_DEFAULT text_end
/* Use csh to do argument expansion so we get ~ and such. */
/* Doesn't work. */
/* #define SHELL_FILE "/bin/csh" */
/* 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.
Convex prolog is:
[sub.w #-,sp] in one of 3 possible sizes
[mov psw,- fc/vc main program prolog
and #-,- (skip it because the "mov psw" saves the
mov -,psw] T bit, so continue gets a surprise trap)
[and #-,sp] fc/vc O2 main program prolog
[ld.- -(ap),-] pcc/gcc register arg loads
*/
#define SKIP_PROLOGUE(pc) \
{ int op, ix; \
op = read_memory_integer (pc, 2); \
if ((op & 0xffc7) == 0x5ac0) pc += 2; \
else if (op == 0x1580) pc += 4; \
else if (op == 0x15c0) pc += 6; \
if ((read_memory_integer (pc, 2) & 0xfff8) == 0x7c40 \
&& (read_memory_integer (pc + 2, 2) & 0xfff8) == 0x1240 \
&& (read_memory_integer (pc + 8, 2) & 0xfff8) == 0x7c48) \
pc += 10; \
if (read_memory_integer (pc, 2) == 0x1240) pc += 6; \
for (;;) { \
op = read_memory_integer (pc, 2); \
ix = (op >> 3) & 7; \
if (ix != 6) break; \
if ((op & 0xfcc0) == 0x3000) pc += 4; \
else if ((op & 0xfcc0) == 0x3040) pc += 6; \
else if ((op & 0xfcc0) == 0x2800) pc += 4; \
else if ((op & 0xfcc0) == 0x2840) pc += 6; \
else break;}}
/* Immediately after a function call, return the saved pc.
(ignore frame and return *$sp so we can handle both calls and callq) */
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space.
This is ((USRSTACK + 0xfff) & -0x1000)) from <convex/vmparam.h> but
that expression depends on the kernel version; instead, fetch a
page-zero pointer and get it from that. This will be invalid if
they ever change the way bkpt signals are delivered. */
#define STACK_END_ADDR (0xfffff000 & *(unsigned *) 0x80000050)
/* User-mode traps push an extended rtn block,
then fault with one of the following PCs */
#define is_trace_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000040)) <= 4)
#define is_arith_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000044)) <= 4)
#define is_break_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000050)) <= 4)
/* We need to manipulate trap bits in the psw */
#define PSW_TRAP_FLAGS 0x69670000
#define PSW_T_BIT 0x08000000
#define PSW_S_BIT 0x01000000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. (bkpt) */
#define BREAKPOINT {0x7d,0x50}
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT but not always.
(The break PC needs to be decremented by 2, but we do it when the
break frame is recognized and popped. That way gdb can tell breaks
from trace traps with certainty.) */
#define DECR_PC_AFTER_BREAK 0
/* Nonzero if instruction at PC is a return instruction. (rtn or rtnq) */
#define ABOUT_TO_RETURN(pc) \
((read_memory_integer (pc, 2) & 0xffe0) == 0x7c80)
/* Return 1 if P points to an invalid floating point value. */
#define INVALID_FLOAT(p,len) 0
/* Largest integer type */
#define LONGEST long long
/* Name of the builtin type for the LONGEST type above. */
#undef BUILTIN_TYPE_LONGEST
#define BUILTIN_TYPE_LONGEST builtin_type_long_long
/* Say how long (ordinary) registers are. */
#define REGISTER_TYPE long long
/* Number of machine registers */
#define NUM_REGS 26
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES {"pc","psw","fp","ap","a5","a4","a3","a2","a1","sp",\
"s7","s6","s5","s4","s3","s2","s1","s0",\
"S7","S6","S5","S4","S3","S2","S1","S0"}
/* 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 S0_REGNUM 25 /* the real S regs */
#define S7_REGNUM 18
#define s0_REGNUM 17 /* low-order halves of S regs */
#define s7_REGNUM 10
#define SP_REGNUM 9 /* A regs */
#define A1_REGNUM 8
#define A5_REGNUM 4
#define AP_REGNUM 3
#define FP_REGNUM 2 /* Contains address of executing stack frame */
#define PS_REGNUM 1 /* Contains processor status */
#define PC_REGNUM 0 /* Contains program counter */
/* convert dbx stab register number (from `r' declaration) to a gdb REGNUM */
#define STAB_REG_TO_REGNUM(value) \
((value) < 8 ? S0_REGNUM - (value) : SP_REGNUM - ((value) - 8))
/* Vector register numbers, not handled as ordinary regs.
They are treated as convenience variables whose values are read
from the inferior when needed. */
#define V0_REGNUM 0
#define V7_REGNUM 7
#define VM_REGNUM 8
#define VS_REGNUM 9
#define VL_REGNUM 10
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (4*10 + 8*8)
/* Index within `registers' of the first byte of the space for
register N.
NB: must match structure of struct syscall_context for correct operation */
#define REGISTER_BYTE(N) ((N) < s7_REGNUM ? 4*(N) : \
(N) < S7_REGNUM ? 44 + 8 * ((N)-s7_REGNUM) : \
40 + 8 * ((N)-S7_REGNUM))
/* Number of bytes of storage in the actual machine representation
for register N. */
#define REGISTER_RAW_SIZE(N) ((N) < S7_REGNUM ? 4 : 8)
/* Number of bytes of storage in the program's representation
for register N. */
#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
/* 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_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_RAW_SIZE (REGNUM));
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
((N) < S7_REGNUM ? builtin_type_int : builtin_type_long_long)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_register (A1_REGNUM, (ADDR)); }
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (&((char *) REGBUF) [REGISTER_BYTE (S0_REGNUM) + \
8 - TYPE_LENGTH (TYPE)],\
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 (S0_REGNUM), VALBUF, 8)
/* 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 *) & ((char *) REGBUF) [REGISTER_BYTE (s0_REGNUM)])
/* Compensate for lack of `vprintf' function. */
#ifndef HAVE_VPRINTF
#define vprintf(format, ap) _doprnt (format, ap, stdout)
#endif /* not HAVE_VPRINTF */
/* Define trapped internal variable hooks to read and write
vector and communication registers. */
#define IS_TRAPPED_INTERNALVAR is_trapped_internalvar
#define VALUE_OF_TRAPPED_INTERNALVAR value_of_trapped_internalvar
#define SET_TRAPPED_INTERNALVAR set_trapped_internalvar
extern struct value *value_of_trapped_internalvar ();
/* Hooks to read data from soff exec and core files,
and to describe the files. */
#define XFER_CORE_FILE
#define FILES_INFO_HOOK print_maps
/* Hook to call after creating inferior process. */
#define CREATE_INFERIOR_HOOK create_inferior_hook
/* Hook to call to print a typeless integer value, normally printed in decimal.
For convex, use hex instead if the number looks like an address. */
#define PRINT_TYPELESS_INTEGER decout
/* Specify that variables for a particular lexical context are listed
after the beginning LBRAC instead of before in the executables list
of symbols. */
#define VARIABLES_INSIDE_BLOCK
/* Pcc occaisionally puts an SO where there should be an SOL. */
#define PCC_SOL_BROKEN
/* Cannot execute with pc on the stack. */
#define CANNOT_EXECUTE_STACK
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame_info with a frame's nominal address in fi->frame,
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. */
/* (caller fp is saved at 8(fp)) */
#define FRAME_CHAIN(fi) (read_memory_integer ((fi)->frame + 8, 4))
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0.
On convex, check at the return address for `callq' -- if so, frameless,
otherwise, not. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
{ \
extern CORE_ADDR text_start, text_end; \
CORE_ADDR call_addr = SAVED_PC_AFTER_CALL (FI); \
(FRAMELESS) = (call_addr >= text_start && call_addr < text_end \
&& read_memory_integer (call_addr - 6, 1) == 0x22); \
}
#define FRAME_SAVED_PC(fi) (read_memory_integer ((fi)->frame, 4))
#define FRAME_ARGS_ADDRESS(fi) (read_memory_integer ((fi)->frame + 12, 4))
#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) \
{ numargs = read_memory_integer (FRAME_ARGS_ADDRESS (fi) - 4, 4); \
if (numargs < 0 || numargs >= 256) numargs = -1;}
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* 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. */
/* Normal (short) frames save only PC, FP, (callee's) AP. To reasonably
handle gcc and pcc register variables, scan the code following the
call for the instructions the compiler inserts to reload register
variables from stack slots and record the stack slots as the saved
locations of those registers. This will occasionally identify some
random load as a saved register; this is harmless. vc does not
declare its register allocation actions in the stabs. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */\
(read_memory_integer ((frame_info)->frame + 4, 4) >> 25) & 3; \
register CORE_ADDR frame_fp = \
read_memory_integer ((frame_info)->frame + 8, 4); \
register CORE_ADDR next_addr; \
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 0; \
(frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \
(frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 8; \
(frame_saved_regs).regs[AP_REGNUM] = frame_fp + 12; \
next_addr = (frame_info)->frame + 12; \
if (frame_length < 3) \
for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
(frame_saved_regs).regs[regnum] = (next_addr += 4); \
if (frame_length < 2) \
(frame_saved_regs).regs[SP_REGNUM] = (next_addr += 4); \
next_addr -= 4; \
if (frame_length < 3) \
for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) \
(frame_saved_regs).regs[regnum] = (next_addr += 8); \
if (frame_length < 2) \
(frame_saved_regs).regs[S0_REGNUM] = (next_addr += 8); \
else \
(frame_saved_regs).regs[SP_REGNUM] = next_addr + 8; \
if (frame_length == 3) { \
CORE_ADDR pc = read_memory_integer ((frame_info)->frame, 4); \
int op, ix, disp; \
op = read_memory_integer (pc, 2); \
if ((op & 0xffc7) == 0x1480) pc += 4; /* add.w #-,sp */ \
else if ((op & 0xffc7) == 0x58c0) pc += 2; /* add.w #-,sp */ \
op = read_memory_integer (pc, 2); \
if ((op & 0xffc7) == 0x2a06) pc += 4; /* ld.w -,ap */ \
for (;;) { \
op = read_memory_integer (pc, 2); \
ix = (op >> 3) & 7; \
if ((op & 0xfcc0) == 0x2800) { /* ld.- -,ak */ \
regnum = SP_REGNUM - (op & 7); \
disp = read_memory_integer (pc + 2, 2); \
pc += 4;} \
else if ((op & 0xfcc0) == 0x2840) { /* ld.- -,ak */ \
regnum = SP_REGNUM - (op & 7); \
disp = read_memory_integer (pc + 2, 4); \
pc += 6;} \
if ((op & 0xfcc0) == 0x3000) { /* ld.- -,sk */ \
regnum = S0_REGNUM - (op & 7); \
disp = read_memory_integer (pc + 2, 2); \
pc += 4;} \
else if ((op & 0xfcc0) == 0x3040) { /* ld.- -,sk */ \
regnum = S0_REGNUM - (op & 7); \
disp = read_memory_integer (pc + 2, 4); \
pc += 6;} \
else if ((op & 0xff00) == 0x7100) { /* br crossjump */ \
pc += 2 * (char) op; \
continue;} \
else if (op == 0x0140) { /* jmp crossjump */ \
pc = read_memory_integer (pc + 2, 4); \
continue;} \
else break; \
if ((frame_saved_regs).regs[regnum]) \
break; \
if (ix == 7) disp += frame_fp; \
else if (ix == 6) disp += read_memory_integer (frame_fp + 12, 4); \
else if (ix != 0) break; \
(frame_saved_regs).regs[regnum] = \
disp - 8 + (1 << ((op >> 8) & 3)); \
if (regnum >= S7_REGNUM) \
(frame_saved_regs).regs[regnum - S0_REGNUM + s0_REGNUM] = \
disp - 4 + (1 << ((op >> 8) & 3)); \
} \
} \
}
/* 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 buf[8]; \
long word; \
for (regnum = S0_REGNUM; regnum >= S7_REGNUM; --regnum) { \
read_register_bytes (REGISTER_BYTE (regnum), buf, 8); \
sp = push_bytes (sp, buf, 8);} \
for (regnum = SP_REGNUM; regnum >= FP_REGNUM; --regnum) { \
word = read_register (regnum); \
sp = push_bytes (sp, &word, 4);} \
word = (read_register (PS_REGNUM) &~ (3<<25)) | (1<<25); \
sp = push_bytes (sp, &word, 4); \
word = read_register (PC_REGNUM); \
sp = push_bytes (sp, &word, 4); \
write_register (SP_REGNUM, sp); \
write_register (FP_REGNUM, sp); \
write_register (AP_REGNUM, sp);}
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME do {\
register CORE_ADDR fp = read_register (FP_REGNUM); \
register int regnum; \
register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */ \
(read_memory_integer (fp + 4, 4) >> 25) & 3; \
char buf[8]; \
write_register (PC_REGNUM, read_memory_integer (fp, 4)); \
write_register (PS_REGNUM, read_memory_integer (fp += 4, 4)); \
write_register (FP_REGNUM, read_memory_integer (fp += 4, 4)); \
write_register (AP_REGNUM, read_memory_integer (fp += 4, 4)); \
if (frame_length < 3) \
for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
write_register (regnum, read_memory_integer (fp += 4, 4)); \
if (frame_length < 2) \
write_register (SP_REGNUM, read_memory_integer (fp += 4, 4)); \
fp -= 4; \
if (frame_length < 3) \
for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) { \
read_memory (fp += 8, buf, 8); \
write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
if (frame_length < 2) { \
read_memory (fp += 8, buf, 8); \
write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
else write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); \
} while (0)
/* This sequence of words is the instructions
mov sp,ap
pshea 69696969
calls 32323232
bkpt
Note this is 16 bytes. */
#define CALL_DUMMY {0x50860d4069696969LL,0x2140323232327d50LL}
#define CALL_DUMMY_START_OFFSET 0
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
{ *(int *)((char *) dummyname + 4) = nargs; \
*(int *)((char *) dummyname + 10) = fun; }
/* Defs to read soff symbol tables, see dbxread.c */
#define NUMBER_OF_SYMBOLS ((long) opthdr.o_nsyms)
#define STRING_TABLE_OFFSET ((long) filehdr.h_strptr)
#define SYMBOL_TABLE_OFFSET ((long) opthdr.o_symptr)
#define STRING_TABLE_SIZE ((long) filehdr.h_strsiz)
#define SIZE_OF_TEXT_SEGMENT ((long) txthdr.s_size)
#define ENTRY_POINT ((long) opthdr.o_entry)
#define READ_STRING_TABLE_SIZE(BUFFER) \
(BUFFER = STRING_TABLE_SIZE)
#define DECLARE_FILE_HEADERS \
FILEHDR filehdr; \
OPTHDR opthdr; \
SCNHDR txthdr
#define READ_FILE_HEADERS(DESC,NAME) \
{ \
int n; \
val = myread (DESC, &filehdr, sizeof filehdr); \
if (val < 0) \
perror_with_name (NAME); \
if (! IS_SOFF_MAGIC (filehdr.h_magic)) \
error ("%s: not an executable file.", NAME); \
lseek (DESC, 0L, 0); \
if (myread (DESC, &filehdr, sizeof filehdr) < 0) \
perror_with_name (NAME); \
if (myread (DESC, &opthdr, filehdr.h_opthdr) <= 0) \
perror_with_name (NAME); \
for (n = 0; n < filehdr.h_nscns; n++) \
{ \
if (myread (DESC, &txthdr, sizeof txthdr) < 0) \
perror_with_name (NAME); \
if ((txthdr.s_flags & S_TYPMASK) == S_TEXT) \
break; \
} \
}
/* Interface definitions for kernel debugger KDB. */
/* (no kdb) */

View File

@ -1,53 +1,53 @@
/* Parameters for execution on A/UX, for GDB, the GNU debugger.
Copyright (C) 1989 Free Software Foundation, Inc.
/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
#ifndef aux
#define aux
#endif
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* It's a USG system */
#define USG
/* Assembler instructions in USG "SGS" (sw generation system) format */
#define USG_SGS_ASM
/* Debugger information will be in COFF format. */
#define COFF_FORMAT
#define COFF_NO_LONG_FILE_NAMES
/* Terminal interface via termio */
#define HAVE_TERMIO
/* Unisoft fucked up the include files */
#define UNISOFT_ASSHOLES
/* Big or Little-Endian target machine
BITS: defined if bit #0 is the high-order bit of a byte.
BYTES:defined if byte#0 is the high-order byte of an int.
WORDS:defined if word#0 is the high-order word of a double. */
/* Describe the endian nature of this machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Floating point is IEEE compatible */
#define IEEE_FLOAT
/*
* 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. */
@ -73,34 +73,36 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define SAVED_PC_AFTER_CALL(frame) \
read_memory_integer (read_register (SP_REGNUM), 4)
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR 0x00917000
/* Address of end of stack space. */
#define STACK_END_ADDR 0x20000000
#define STACK_END_ADDR 0xfff00000
/* Stack grows downward. */
#define INNER_THAN <
/* Sequence of bytes for breakpoint instruction. */
/* A/UX uses "trap &1" */
#define BREAKPOINT {0x4e, 0x41}
#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 0
#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. */
/* FIXME, it's not clear what "invalid" means here. I take it to mean
"something that coredumps gdb if gdb tries to manipulate it" */
#define INVALID_FLOAT(p, len) is_nan(p, len)
#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
/* Largest integer type */
#define LONGEST long
@ -121,7 +123,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
"ps", "pc", \
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
"fpcontrol", "fpstatus", "fpiaddr" }
@ -139,31 +141,11 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define PC_REGNUM 17 /* Contains program counter */
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
#define FPS_REGNUM 27 /* 68881 status register */
/* This is a piece of magic that is given a register number REGNO
and as BLOCKEND the address in the system of the end of the user structure
and stores in ADDR the address in the kernel or core dump
of that register. */
#define REGISTER_U_ADDR(addr, blockend, regno) { \
struct user u; \
if (regno <= SP_REGNUM) \
addr = blockend + regno * 4; \
else if (regno == PS_REGNUM) \
addr = blockend + RPS * 4; /* From reg.h */ \
else if (regno == PC_REGNUM) \
addr = blockend + PC * 4; /* From reg.h */ \
else if (regno < FPC_REGNUM) \
addr = (char *) u.u_fpdreg [regno-FP0_REGNUM] - (char *)&u; \
else \
addr = (char *)&u.u_fpsysreg[regno-FPC_REGNUM] - (char *)&u; \
}
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4+8*12+8+20)
#define REGISTER_BYTES (16*4+8*12+8+12)
/* Index within `registers' of the first byte of the space for
register N. */
@ -249,6 +231,34 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Compensate for lack of `vprintf' function. */
#ifndef HAVE_VPRINTF
#define vprintf(format, ap) _doprnt (format, ap, stdout)
#endif /* not HAVE_VPRINTF */
/* 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; \
}
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@ -263,18 +273,27 @@ read_memory_integer (read_register (SP_REGNUM), 4)
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
/* In the case of the 68k, the frame's nominal address
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -321,7 +340,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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) \
&& (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 \
@ -408,7 +427,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
@ -440,7 +459,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp
trap #15
trap #2
nop
Note this is 28 bytes.
We actually start executing at the jsr, since the pushing of the
@ -451,7 +470,7 @@ But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
and we cannot allow the moveml to push the registers again lest they be
taken for the arguments. */
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e424e71}
#define CALL_DUMMY_LENGTH 28

View File

@ -1,34 +1,41 @@
/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
#ifndef HP9K320
#define HP9K320
#endif
/* Define this to indicate problems with traps after continuing. */
#define HP_OS_BUG
/* Set flag to indicate whether HP's assembler is in use. */
#ifdef __GNU__
#ifdef __GNUC__
#ifdef __HPUX_ASM__
#define USG_SGS_ASM
#define HPUX_ASM
#endif
#else
#define USG_SGS_ASM
#define HPUX_ASM
#endif
/* Define this for versions of hp-ux older than 6.0 */
@ -40,8 +47,10 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define HAVE_TERMIO
/* Get rid of any system-imposed stack limit if possible. */
/* The hp9k320.h doesn't seem to have this feature. */
/* #define SET_STACK_LIMIT_HUGE */
/* So we'll just have to avoid big alloca's. */
#define BROKEN_LARGE_ALLOCA
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
@ -248,11 +257,6 @@ read_memory_integer (read_register (SP_REGNUM), 4)
? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
: (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
- ((char *) (& u)))
/* It is safe to look for symsegs on a Sun, because Sun's ld
does not screw up with random garbage at end of file. */
#define READ_GDB_SYMSEGS
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@ -270,15 +274,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) : \
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)

28
gdb/m-i386-sysv3.2.h Normal file
View File

@ -0,0 +1,28 @@
/* Macro defintions for i386, running System V 3.2.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "m-i386.h"
/* Apparently there is inconsistency among various System V's about what
the name of this field is. */
#define U_FPSTATE(u) u.u_fps.u_fpstate
/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
is not. This makes problems for inflow.c. */
#define TIOCGETC_BROKEN

View File

@ -1,27 +1,32 @@
/* Macro defintions for i386.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
/* #define BITS_BIG_ENDIAN */
/* #define BYTES_BIG_ENDIAN */
/* #define WORDS_BIG_ENDIAN */
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*/
/*
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#ifndef i386
#define i386
@ -255,15 +260,24 @@ anyone else from sharing it farther. Help stamp out software hoarding!
it means the given frame is the outermost one and has no caller.
In that case, FRAME_CHAIN_COMBINE is not used. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)

28
gdb/m-i386gas-sysv3.2.h Normal file
View File

@ -0,0 +1,28 @@
/* Macro defintions for i386, running System V 3.2.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "m-i386gas.h"
/* Apparently there is inconsistency among various System V's about what
the name of this field is. */
#define U_FPSTATE(u) u.u_fps.u_fpstate
/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
is not. This makes problems for inflow.c. */
#define TIOCGETC_BROKEN

View File

@ -1,3 +1,22 @@
/* Macro definitions for i386 using the GNU object file format.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
@ -5,25 +24,6 @@
* i386gnu: COFF_ENCAPSULATE
*/
/*
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
#define COFF_ENCAPSULATE

View File

@ -1,66 +1,35 @@
/*
Date: Thu, 2 Apr 87 00:02:42 EST
From: crl@maxwell.physics.purdue.edu (Charles R. LaBrec)
Message-Id: <8704020502.AA01744@maxwell.physics.purdue.edu>
To: bug-gdb@prep.ai.mit.edu
Subject: gdb for ISI Optimum V
/* Definitions to make GDB run on an ISI Optimum V (3.05) under 4.3bsd.
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
Here is an m-isi-ov.h file for gdb version 2.1. It supports the 68881
registers, and tracks down the function prologue (since the ISI cc
puts it at the end of the function and branches to it if not
optimizing). Also included are diffs to core.c, findvar.c, and
inflow.c, since the original code assumed that registers are an int in
the user struct, which isn't the case for 68020's with 68881's (and
not using the NEW_SUN_PTRACE). I have not fixed the bugs associated
with the other direction (writing registers back to the user struct).
I have also included a diff that turns m68k-pinsn.c into isi-pinsn.c,
which is needed since the 3.05 release of as does not understand
floating point ops, and it compiles incorrectly under "cc -20"
This file is part of GDB.
I have used gdb for a while now, and it seems to work relatively well,
but I do not guarantee that it is perfect. The more that use it, the
faster the bugs will get shaken out. One bug I know of is not in gdb,
but in the assembler. It seems to screw up the .stabs of variables.
For externs, this is not important since gdb uses the global symbol
value, but for statics, this makes gdb unable to find them. I am
currently trying to track it down.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
As an aside, I notice that only global functions are used as symbols
to print as relative addresses, i.e. "<function + offset>", and not
static functions, which end up printing as large offsets from the last
global one. Would there be a problem if static functions were also
recorded as misc functions in read_dbx_symtab?
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Charles LaBrec
crl @ maxwell.physics.purdue.edu
Definitions to make GDB run on a ISI Optimum V (3.05) under 4.2bsd.
Copyright (C) 1987 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing.
Refer to the GDB General Public License for full details.
Everyone is granted permission to copy, modify and redistribute GDB,
but only under the conditions described in the GDB General Public
License. A copy of this license is supposed to have been given to you
along with GDB so you can know your rights and responsibilities. It
should be in a file named COPYING. Among other things, the copyright
notice and this notice must be preserved on all copies.
In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This has not been tested on ISI's running BSD 4.2, but it will probably
work. */
/* Identify this machine */
#ifndef ISI68K
#define ISI68K
#endif
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
@ -104,11 +73,13 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR 0x10800000
/*#define KERNEL_U_ADDR 0x10800000*/
#define KERNEL_U_ADDR 0
/* Address of end of stack space. */
#define STACK_END_ADDR 0x10000000
/*#define STACK_END_ADDR 0x10000000*/
#define STACK_END_ADDR 0xfffe000
/* Stack grows downward. */
@ -130,7 +101,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always.
but not always.
On the ISI, the kernel resets the pc to the trap instr */
#define DECR_PC_AFTER_BREAK 0
@ -154,7 +125,6 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define REGISTER_TYPE long
/* Number of machine registers */
#define NUM_REGS 29
/* Initializer for an array of names of registers.
@ -181,23 +151,15 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
#ifdef BSD43_ISI40D
#define BLOCKFUDGE 0x400000
#else
#define BLOCKFUDGE 0
#endif
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ blockend -= BLOCKFUDGE; \
if (regno < 2) addr = blockend - 0x18 + regno * 4; \
else if (regno < 8) addr = blockend - 0x54 + regno * 4; \
else if (regno < 10) addr = blockend - 0x30 + regno * 4;\
else if (regno < 15) addr = blockend - 0x5c + regno * 4;\
else if (regno < 16) addr = blockend - 0x1c; \
else if (regno < 18) addr = blockend - 0x44 + regno * 4;\
else if (regno < 26) addr = (int) ((struct user *)0)->u_68881_regs \
+ (regno - 18) * 12; \
else if (regno < 29) addr = (int) ((struct user *)0)->u_68881_regs \
+ 8 * 12 + (regno - 26) * 4; \
/* expects blockend to be u.u_ar0 */
extern int rloc[]; /* Defined in isi-dep.c */
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ blockend &= UPAGES*NBPG - 1; \
if (regno < 18) addr = (int)blockend + rloc[regno]*4; \
else if (regno < 26) addr = (int) &((struct user *)0)->u_68881_regs \
+ (regno - 18) * 12; \
else if (regno < 29) addr = (int) &((struct user *)0)->u_68881_regs \
+ 8 * 12 + (regno - 26) * 4; \
}
/* Total amount of space needed to store our copies of the machine's
@ -302,15 +264,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the ISI, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && outside_startup_file (FRAME_SAVED_PC (thisframe)))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -411,8 +382,10 @@ retry: \
(frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
}
/* Compensate for lack of `vprintf' function. */
#define vprintf(format, ap) _doprnt (format, ap, stdout)
/* Compensate for lack of `vprintf' function. */
#ifndef HAVE_VPRINTF
#define vprintf(format, ap) _doprnt (format, ap, stdout)
#endif
/* Things needed for making the inferior call functions. */
@ -468,7 +441,7 @@ retry: \
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 CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp

View File

@ -1,27 +1,31 @@
/* Definitions to make GDB run on a merlin under utek 2.1
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef ns16000
#define ns16000
#endif
/* Define the bit, byte, and word ordering of the machine. */
/* #define BITS_BIG_ENDIAN */
/* #define BYTES_BIG_ENDIAN */
/* #define WORDS_BIG_ENDIAN */
# include <machine/reg.h>
/* Define this if the C compiler puts an underscore at the front
@ -265,10 +269,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* In the case of the Merlin, the frame's nominal address is the FP value,
and at that address is saved previous FP value as a 4-byte word. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
@ -337,8 +344,10 @@ anyone else from sharing it farther. Help stamp out software hoarding!
(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)
/* Compensate for lack of `vprintf' function. */
#ifndef HAVE_VPRINTF
#define vprintf(format, ap) _doprnt (format, ap, stdout)
#endif /* not HAVE_VPRINTF */
/* Things needed for making the inferior call functions. */
@ -374,7 +383,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM),\
read_pc ()));
read_pc ())); \
}
/* This sequence of words is the instructions

View File

@ -1,42 +1,63 @@
/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
Probably ths parameters is match as news800, news700 and news900.
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* See following cpu type determination macro to get the machine type.
Here is an m-news.h file for gdb. It supports the 68881 registers.
by hikichi@srava.sra.junet
* Support Sun assembly format instead of Motorola one.
* Ptrace for handling floating register has a bug(before NEWS OS version 2.2),
* After NEWS OS version 3.2, some of ptrace's bug is fixed.
But we cannot change the floating register(see adb(1) in OS 3.2) yet.
Here is an m-news800.h file for gdb version 2.6. It supports the 68881
registers.
(hikichi@srava.sra.junet or hikichi%srava.sra.junet%kddlabs@uunet.uu.net
and now hikichi@wheaties.ai.mit.edu)
* Now(9/2 '87) NEWS's printf has a bug.
* And support Sun assembly format instead of Motorola one.
* Probably not well support floating registers from core file rarely that
I do not know detail.
* Ptrace for handling floating register has a bug(7/3 '87), but not fixed
yet. We cannot write floating register.
Copyright (C) 1987 Free Software Foundation, Inc.
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
#ifndef sony_news
#define sony_news
#endif
/* determine the cpu type from machine type. */
#if defined(news1500)||defined(news1700)||defined(news1800)||defined(news1900)
# ifndef mc68020
# define mc68020
# endif /* not def mc68020 */
# ifndef mc68030
# define mc68030
# endif /* not def mc68030 */
#else /* 1000 Series */
# if defined(news700)||defined(news800)||defined(news900)
# ifndef mc68020
# define mc68020
# endif
# else /* 800 Series */
/* unkown model ? */
# endif /* 800 Series */
#endif /* 1000 Series */
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Use GNU assembler instead of standard assembler */
#define USE_GAS
@ -45,6 +66,15 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define MOTOROLA
#endif
/* Doesn't have siginterrupt. */
#define NO_SIGINTERRUPT
#define HAVE_WAIT_STRUCT
/* 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. */
@ -53,6 +83,10 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* Symbols on this machine are in DBX format. */
#define READ_DBX_FORMAT
/* We can't use "isatty" or "fileno" on this machine. This isn't good,
but it will have to do. */
#define ISATTY(FP) ((FP) == stdin || (FP) == stdout)
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -85,7 +119,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* Address of end of stack space. */
#define STACK_END_ADDR (0x80000000 - ctob(UPAGES + 1))
#define STACK_END_ADDR (0x80000000 - (UPAGES+CLSIZE)*NBPG)
/* Stack grows downward. */
@ -147,6 +181,8 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define FP0_REGNUM 18 /* Floating point register 0 */
#define FPC_REGNUM 26 /* 68881 control register */
/* before NEWSOS version 2.2 or more. If you have a new OS,
redefine this macro in 'see m-newsos3.h'. */
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ if (regno <= FP_REGNUM) \
addr = blockend + 4 + regno * 4; \
@ -155,7 +191,7 @@ read_memory_integer (read_register (SP_REGNUM), 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; \
addr = blockend + 4 + 4 * 14 + 4 * 4 + (regno - FP0_REGNUM) * 12; \
else \
addr = blockend + 4 + 4 * 16 + (regno - FPC_REGNUM) * 4; \
}
@ -231,14 +267,30 @@ read_memory_integer (read_register (SP_REGNUM), 4)
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
/* when it return the floating value, use the FP0 in NEWS. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
{ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
{ \
REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, \
&REGBUF[REGISTER_BYTE (FP0_REGNUM)], VALBUF); \
} \
else \
bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); }
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
/* when it return the floating value, use the FP0 in NEWS. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
{ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
{ \
char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
REGISTER_CONVERT_TO_RAW (FP0_REGNUM, VALBUF, raw_buf); \
write_register_bytes (FP0_REGNUM, \
raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \
} \
else \
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,
@ -246,8 +298,10 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
/* Compensate for lack of `vprintf' function. */
#define vprintf(format, ap) _doprnt (format, ap, stdout)
/* Compensate for lack of `vprintf' function. */
#ifndef HAVE_VPRINTF
#define vprintf(format, ap) _doprnt (format, ap, stdout)
#endif /* not HAVE_VPRINTF */
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
@ -265,15 +319,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the NEWS, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -311,8 +374,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
register int regmask; \
register CORE_ADDR next_addr; \
register CORE_ADDR pc; \
register int insn; \
register int offset; \
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) \
@ -320,53 +382,54 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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; \
/* 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. */\
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 (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) */ \
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; \
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); \
} else if (insn == 0044347) /* moveml mask, -(sp) */ \
{ pc += 2; \
/* Regmask's low bit is for register 15, the first pushed */ \
(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 (read_memory_integer (pc, 2) == 041147 \
&& read_memory_integer (pc+2, 2) == 042347) \
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; \
@ -375,52 +438,11 @@ retry: \
}
/* Things needed for making the inferior call functions. */
/* On NEWS os 2.x ptrace cannot modify fp and floating registers. */
#define PTRACE_BUG
/* Push an empty stack frame, to record the current PC, etc. */
#if 0 /* now these define is not used */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
#else /* now ptrace has a bug to write floating register */
/* now ptrace has a bug to write floating register in old OS */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
@ -454,10 +476,10 @@ retry: \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
#endif
/* This sequence of words is the instructions
fmove.m #<f0-f7>,-(sp)
movem.l 0xfffc,-(sp)
movem.l 0xfffc,-(sp) ;; no save a6(fp) and a7(sp)
clr.w -(sp)
move.w ccr,-(sp)
/..* The arguments are pushed at this point by GDB;

117
gdb/m-newsos3.h Normal file
View File

@ -0,0 +1,117 @@
/* Parameters for execution on a Sony/NEWS with News-OS version 3,
for GDB, the GNU debugger.
Copyright (C) 1989 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define NEWSOS3
#include "m-news.h"
#undef STACK_END_ADDR
/* <machine/vmparam.h> USRSTACK */
#define STACK_END_ADDR (0x80000000 - UPAGES*NBPG)
/* Have siginterupt on NEWS OS 3.x. */
#undef NO_SIGINTERRUPT
#undef USE_PCB
/* now old ptrace bug has fixed almost. Remain constrain is;
When some process do not touch the floating register,
ptrace cannot change the floating register containts.
*/
#undef PTRACE_BUG
#undef PUSH_DUMMY_FRAME
#undef POP_FRAME
/* now ptrace has a bug to write floating register in NEWS OS version 2.x */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
char raw_buffer[12]; \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
write_register (FP_REGNUM, sp); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
{ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
sp = push_bytes (sp, raw_buffer, 12); } \
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
sp = push_word (sp, read_register (regnum)); \
sp = push_word (sp, read_register (PS_REGNUM)); \
write_register (SP_REGNUM, sp); }
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
/* NewsOS 3 apparently dies on large alloca's -- roland@ai.mit.edu. */
#define BROKEN_LARGE_ALLOCA
/* Make this macro from peep of core file. */
#undef REGISTER_U_ADDR
#ifdef USE_PCB
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ blockend += 4; /* why? */ \
if (regno <= FP_REGNUM) \
addr = blockend + regno * 4; \
else if (regno == SP_REGNUM) \
addr = blockend - 4 - 4 * 4; \
else if (regno <= PS_REGNUM) \
addr = blockend - 4 + (regno - PS_REGNUM) * 4; \
else if (regno < FPC_REGNUM) \
addr = blockend + (14 + 1 + 3) * 4 + (regno - FP0_REGNUM) * 12; \
else \
addr = blockend + 15 * 4 + (regno - FPC_REGNUM) * 4; \
}
#else
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ blockend += 4; /* why? */ \
if (regno <= FP_REGNUM) \
addr = blockend + regno * 4; \
else if (regno == SP_REGNUM) \
addr = blockend -4 - 4 * 4; \
else if (regno <= PS_REGNUM) \
addr = blockend - 4 + (regno - PS_REGNUM) * 4; \
else if (regno < FPC_REGNUM) \
addr = blockend + (14 + 1 + 3) * 4 + (regno - FP0_REGNUM) * 12; \
else \
addr = blockend + 15 * 4 + (regno - FPC_REGNUM) * 4; \
}
#endif

View File

@ -1,25 +1,34 @@
/* Parameters for execution on a Gould NP1, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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! */
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* This code appears in libraries on Gould machines. Ignore it. */
#define IGNORE_SYMBOL(type) (type == N_ENTRY)
/* We don't want the extra gnu symbols on the machine;
they will interfere with the shared segment symbols. */
#define NO_GNU_STABS
/* Macro for text-offset and data info (in NPL a.out format). */
#define TEXTINFO \
text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); \
@ -67,7 +76,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* Define COFF and other symbolic names needed on NP1 */
#define NS32GMAGIC GNP1MAGIC
#define NS32SMAGIC GPNMAGIC
#ifndef HAVE_VPRINTF
#define vprintf printf
#endif /* not HAVE_VPRINTF */
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE

View File

@ -1,25 +1,34 @@
/* Parameters for execution on a Gould PN, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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! */
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* This code appears in libraries on Gould machines. Ignore it. */
#define IGNORE_SYMBOL(type) (type == N_ENTRY)
/* We don't want the extra gnu symbols on the machine;
they will interfere with the shared segment symbols. */
#define NO_GNU_STABS
/* Macro for text-offset and data info (in PN a.out format). */
#define TEXTINFO \
text_offset = N_TXTOFF (exec_coffhdr); \
@ -67,7 +76,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! */
/* Define COFF and other symbolic names needed on NP1 */
#define NS32GMAGIC GDPMAGIC
#define NS32SMAGIC PN_MAGIC
#ifndef HAVE_VPRINTF
#define vprintf printf
#endif /* not HAVE_VPRINTF */
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE

View File

@ -1,28 +1,34 @@
/* Parameters for execution on a Sun 4, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@mcc.com)
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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!
*/
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef sun4
#define sun4
#endif
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Floating point is IEEE compatible. */
#define IEEE_FLOAT
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE
@ -36,16 +42,16 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define READ_DBX_FORMAT
/* Big or Little-Endian target machine
BITS: defined if bit #0 is the high-order bit of a byte.
BYTES:defined if byte#0 is the high-order byte of an int.
WORDS:defined if word#0 is the high-order word of a double. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* If Pcc says that a parameter is a short, it's a short. This is
because the parameter does get passed in in a register as an int,
but pcc puts it onto the stack frame as a short (not nailing
whatever else might be there. I'm not sure that I consider this
swift. Sigh.)
/* Floating point is IEEE compatible. */
#define IEEE_FLOAT
No, don't do this. The problem here is that pcc says that the
argument is in the upper half of the word reserved on the stack,
but puts it in the lower half. */
/* #define BELIEVE_PCC_PROMOTION 1 */
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -73,10 +79,9 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
/* Address of end of stack space. */
#define STACK_END_ADDR 0xf8000000
/* Stack grows downward. */
#include <sys/types.h>
#include <machine/vmparam.h>
#define STACK_END_ADDR USRSTACK
#define INNER_THAN <
@ -261,11 +266,6 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#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). */
@ -315,20 +315,19 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define FRAME_CHAIN(thisframe) \
GET_RWINDOW_REG ((thisframe)->frame, rw_in[6])
/* Avoid checking FRAME_SAVED_PC since that screws us due to
improperly set up saved PC on a signal trampoline call */
#if 0
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
#else
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0)
#endif
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
/* Where is the PC for a specific frame */
#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
@ -375,8 +374,12 @@ anyone else from sharing it farther. Help stamp out software hoarding!
FRAME fid = FRAME_INFO_ID (fi); \
if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \
bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
/* Old test. \
if ((fi)->pc >= frame - CALL_DUMMY_LENGTH - 0x140 \
&& (fi)->pc <= frame) \
&& (fi)->pc <= frame) */ \
if ((fi)->pc >= ((fi)->bottom ? (fi)->bottom : \
read_register (SP_REGNUM)) \
&& (fi)->pc <= FRAME_FP(fi)) \
{ \
for (regnum = 1; regnum < 8; regnum++) \
(frame_saved_regs).regs[regnum] = \
@ -415,7 +418,7 @@ anyone else from sharing it farther. Help stamp out software hoarding!
/* is accurate */ \
for (regnum = 30; regnum < 32; regnum++) \
(frame_saved_regs).regs[regnum] = frame + (regnum-16) * 4; \
(frame_saved_regs).regs[SP_REGNUM] = frame; \
(frame_saved_regs).regs[SP_REGNUM] = FRAME_FP (fi); \
(frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \
}

View File

@ -1,27 +1,31 @@
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef sun2
#define sun2
#endif
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Define this if the C compiler puts an underscore at the front
of external names before giving them to the linker. */
@ -229,15 +233,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -368,7 +381,7 @@ read_memory_integer (read_register (SP_REGNUM), 4)
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 CALL_DUMMY_START_OFFSET gives the position of
the following jsr instruction. *../
jsr @#32323232
addl #69696969,sp

View File

@ -1,2 +1,21 @@
/* Macro definitions for a sun 2 running os 4.
Copyright (C) 1989, Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "m-sun2.h"
#define SUNOS4

View File

@ -1,27 +1,31 @@
/* Parameters for execution on a Sun, for GDB, the GNU debugger.
Copyright (C) 1986, 1987 Free Software Foundation, Inc.
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
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.
This file is part of GDB.
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.
GDB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
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!
*/
GDB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef sun3
#define sun3
#endif
/* Define the bit, byte, and word ordering of the machine. */
#define BITS_BIG_ENDIAN
#define BYTES_BIG_ENDIAN
#define WORDS_BIG_ENDIAN
/* Get rid of any system-imposed stack limit if possible. */
#define SET_STACK_LIMIT_HUGE
@ -45,9 +49,9 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define SKIP_PROLOGUE(pc) \
{ register int op = read_memory_integer (pc, 2); \
if (op == 0047126) \
if (op == 0047126) \
pc += 4; /* Skip link #word */ \
else if (op == 0044016) \
else if (op == 0044016) \
pc += 6; /* Skip link #long */ \
}
@ -78,8 +82,10 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#define DECR_PC_AFTER_BREAK 2
/* Nonzero if instruction at PC is a return instruction. */
/* Allow any of the return instructions, including a trapv and a return
from interupt. */
#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75)
#define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 2) & ~0x3) == 0x4e74)
/* Return 1 if P points to an invalid floating point value. */
@ -223,10 +229,6 @@ read_memory_integer (read_register (SP_REGNUM), 4)
#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). */
@ -244,15 +246,24 @@ read_memory_integer (read_register (SP_REGNUM), 4)
/* In the case of the Sun, the frame's nominal address
is the address of a 4-byte word containing the calling frame's address. */
#define FRAME_CHAIN(thisframe) (read_memory_integer ((thisframe)->frame, 4))
#define FRAME_CHAIN(thisframe) \
(outside_startup_file ((thisframe)->pc) ? \
read_memory_integer ((thisframe)->frame, 4) :\
0)
#define FRAME_CHAIN_VALID(chain, thisframe) \
(chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
(chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
@ -382,29 +393,29 @@ read_memory_integer (read_register (SP_REGNUM), 4)
restoring all saved registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char raw_buffer[12]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], raw_buffer, 12); \
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
if (fsr.regs[regnum]) \
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]) \
if (fsr.regs[PS_REGNUM]) \
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM),\
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM), \
read_pc ())); }
/* This sequence of words is the instructions

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