gdb-3.3
This commit is contained in:
parent
e91b87a368
commit
4187119d59
@ -1,3 +1,5 @@
|
||||
echo Setting up the environment for debugging gdb.\n
|
||||
|
||||
b fatal
|
||||
|
||||
b info_command
|
||||
|
315
gdb/COPYING
315
gdb/COPYING
@ -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!
|
||||
|
2805
gdb/ChangeLog
2805
gdb/ChangeLog
File diff suppressed because it is too large
Load Diff
163
gdb/Convex.notes
Normal file
163
gdb/Convex.notes
Normal 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}.
|
240
gdb/Makefile
240
gdb/Makefile
@ -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
351
gdb/Makefile.dist
Normal 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
114
gdb/Projects
Normal 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:
|
@ -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
|
||||
@
|
@ -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");
|
||||
@
|
2047
gdb/RCS/coffread.c,v
2047
gdb/RCS/coffread.c,v
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
@
|
651
gdb/RCS/core.c,v
651
gdb/RCS/core.c,v
@ -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
|
||||
@
|
4610
gdb/RCS/dbxread.c,v
4610
gdb/RCS/dbxread.c,v
File diff suppressed because it is too large
Load Diff
@ -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 (®isters[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, ®isters[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 *) ®isters[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 *) ®isters[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, ®isters[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
@ -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
|
||||
@
|
@ -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, <c_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, <c_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, <c_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 *)<c_inferior)[i]);
|
||||
printf ("\n");
|
||||
ioctl (0, TIOCSLTC, <c_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, <c_ours);
|
||||
#endif
|
||||
#ifdef TIOCLGET
|
||||
ioctl (0, TIOCLGET, &lmode_ours);
|
||||
#endif
|
||||
|
||||
#ifdef TIOCGPGRP
|
||||
ioctl (0, TIOCGPGRP, &pgrp_ours);
|
||||
#endif /* TIOCGPGRP */
|
||||
|
||||
terminal_is_ours = 1;
|
||||
}
|
||||
|
||||
@
|
||||
|
||||
|
||||
1.2
|
||||
log
|
||||
@When the inferior process dies, deselect the current frame so that
|
||||
the "where" ("backtrace") command will not think there's a stack.
|
||||
@
|
||||
text
|
||||
@d27 1
|
||||
a27 1
|
||||
#include <sys/fcntl.h>
|
||||
a34 6
|
||||
/* May be unnecessary since many parts of inflow.c
|
||||
have migrated to *-infdep.c */
|
||||
#ifdef USG
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
|
||||
d73 1
|
||||
a73 1
|
||||
#ifdef TIOCGLTC
|
||||
d76 3
|
||||
d81 3
|
||||
d86 1
|
||||
a86 1
|
||||
#endif /* TIOCGLTC */
|
||||
d117 4
|
||||
a121 1
|
||||
tc_inferior = tc_ours;
|
||||
d123 3
|
||||
d127 1
|
||||
a127 1
|
||||
#endif /* TIOCGLTC */
|
||||
d150 3
|
||||
a153 1
|
||||
ioctl (0, TIOCSETC, &tc_inferior);
|
||||
d155 2
|
||||
d158 1
|
||||
a158 1
|
||||
#endif /* TIOCGLTC */
|
||||
d228 3
|
||||
a231 1
|
||||
ioctl (0, TIOCGETC, &tc_inferior);
|
||||
d233 2
|
||||
d236 1
|
||||
a236 1
|
||||
#endif /* TIOCGLTC */
|
||||
d253 3
|
||||
a256 1
|
||||
ioctl (0, TIOCSETC, &tc_ours);
|
||||
d258 2
|
||||
d261 1
|
||||
a261 1
|
||||
#endif /* TIOCGLTC */
|
||||
d297 6
|
||||
a302 3
|
||||
printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
|
||||
tflags_inferior, lmode_inferior,
|
||||
sg_inferior.sg_flags, pgrp_inferior);
|
||||
d307 3
|
||||
d314 2
|
||||
d317 3
|
||||
a319 1
|
||||
#endif /* not HAVE_TERMIO */
|
||||
d383 1
|
||||
a383 1
|
||||
pid = vfork ();
|
||||
d385 1
|
||||
a385 1
|
||||
perror_with_name ("vfork");
|
||||
d497 3
|
||||
a500 1
|
||||
ioctl (0, TIOCGETC, &tc_ours);
|
||||
d502 2
|
||||
d505 1
|
||||
a505 1
|
||||
#endif /* TIOCGLTC */
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d418 1
|
||||
@
|
1855
gdb/RCS/infrun.c,v
1855
gdb/RCS/infrun.c,v
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
@
|
@ -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, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4);\
|
||||
write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \
|
||||
write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 7 * 4); \
|
||||
write_memory (fp - 0xa4, &rp, 4); \
|
||||
write_memory (fp - 0xe0, ®isters[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
|
||||
@
|
@ -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 */
|
||||
@
|
1348
gdb/RCS/main.c,v
1348
gdb/RCS/main.c,v
File diff suppressed because it is too large
Load Diff
@ -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 ();/'
|
||||
@
|
1707
gdb/RCS/printcmd.c,v
1707
gdb/RCS/printcmd.c,v
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
@
|
@ -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, ¤t_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, ¤t_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
@ -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
|
||||
@
|
@ -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
|
||||
@
|
1117
gdb/RCS/valprint.c,v
1117
gdb/RCS/valprint.c,v
File diff suppressed because it is too large
Load Diff
1047
gdb/RCS/values.c,v
1047
gdb/RCS/values.c,v
File diff suppressed because it is too large
Load Diff
141
gdb/README
141
gdb/README
@ -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.
|
||||
|
||||
|
57
gdb/XGDB-README
Normal file
57
gdb/XGDB-README
Normal 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
|
@ -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))) : \
|
||||
|
@ -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
|
||||
|
BIN
gdb/alloca.o
BIN
gdb/alloca.o
Binary file not shown.
@ -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);
|
||||
@
|
382
gdb/blockframe.c
382
gdb/blockframe.c
@ -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;
|
||||
|
127
gdb/breakpoint.c
127
gdb/breakpoint.c
@ -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\
|
||||
|
120
gdb/coffread.c
120
gdb/coffread.c
@ -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.");
|
||||
|
478
gdb/command.c
478
gdb/command.c
@ -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);
|
||||
}
|
||||
|
119
gdb/command.h
119
gdb/command.h
@ -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 ();
|
||||
|
219
gdb/config.gdb
219
gdb/config.gdb
@ -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
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Links are now set up for use with a sun4.
|
2083
gdb/convex-dep.c
2083
gdb/convex-dep.c
File diff suppressed because it is too large
Load Diff
1674
gdb/convex-opcode.h
Normal file
1674
gdb/convex-opcode.h
Normal file
File diff suppressed because it is too large
Load Diff
314
gdb/convex-pinsn.c
Normal file
314
gdb/convex-pinsn.c
Normal 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
53
gdb/copying.awk
Normal 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
215
gdb/copying.c
Normal 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.");
|
||||
}
|
103
gdb/core.c
103
gdb/core.c
@ -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. */
|
||||
|
@ -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
|
||||
|
1996
gdb/dbxread.c
1996
gdb/dbxread.c
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
54
gdb/defs.h
54
gdb/defs.h
@ -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
|
||||
|
||||
|
109
gdb/environ.c
109
gdb/environ.c
@ -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))
|
||||
|
@ -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. */
|
||||
|
||||
|
197
gdb/eval.c
197
gdb/eval.c
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
2422
gdb/expread.tab.c
2422
gdb/expread.tab.c
File diff suppressed because it is too large
Load Diff
454
gdb/expread.y
454
gdb/expread.y
@ -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));
|
||||
}
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
30
gdb/frame.h
30
gdb/frame.h
@ -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 ();
|
||||
|
1745
gdb/gdb.texinfo
1745
gdb/gdb.texinfo
File diff suppressed because it is too large
Load Diff
@ -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;
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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
115
gdb/hp-include/stab.def
Normal 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")
|
@ -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_ */
|
||||
|
@ -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
556
gdb/hp300bsd-dep.c
Normal 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 *) ®isters[REGISTER_BYTE (regno) + i]);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d(%d)", regno, i);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
regaddr += sizeof(int);
|
||||
}
|
||||
}
|
||||
else for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
regaddr = register_addr (regno, offset);
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PT_WRITE_U, inferior_pid, regaddr,
|
||||
*(int *) ®isters[REGISTER_BYTE (regno) + i]);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d(%d)", regno, i);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
regaddr += sizeof(int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
@ -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, ®val);
|
||||
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
193
gdb/infcmd.c
193
gdb/infcmd.c
@ -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,
|
||||
|
@ -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 ();
|
||||
|
114
gdb/inflow.c
114
gdb/inflow.c
@ -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 *)<c_inferior)[i]);
|
||||
printf ("\n");
|
||||
printf_filtered ("0x%x ", ((char *)<c_inferior)[i]);
|
||||
printf_filtered ("\n");
|
||||
ioctl (0, TIOCSLTC, <c_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
|
||||
|
309
gdb/infrun.c
309
gdb/infrun.c
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
603
gdb/m-convex.h
Normal 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) */
|
@ -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
|
||||
|
@ -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
28
gdb/m-i386-sysv3.2.h
Normal 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
|
56
gdb/m-i386.h
56
gdb/m-i386.h
@ -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
28
gdb/m-i386gas-sysv3.2.h
Normal 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
|
@ -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
|
||||
|
||||
|
129
gdb/m-isi.h
129
gdb/m-isi.h
@ -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
|
||||
|
@ -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
|
||||
|
264
gdb/m-news.h
264
gdb/m-news.h
@ -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, \
|
||||
®BUF[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
117
gdb/m-newsos3.h
Normal 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
|
39
gdb/m-npl.h
39
gdb/m-npl.h
@ -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
|
||||
|
39
gdb/m-pn.h
39
gdb/m-pn.h
@ -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
|
||||
|
@ -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; \
|
||||
}
|
||||
|
||||
|
49
gdb/m-sun2.h
49
gdb/m-sun2.h
@ -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
|
||||
|
@ -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
|
||||
|
99
gdb/m-sun3.h
99
gdb/m-sun3.h
@ -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
Loading…
x
Reference in New Issue
Block a user