forked from Imagelibrary/binutils-gdb
Compare commits
1 Commits
gdb-7.8-br
...
binutils-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b7529f26d |
143
gdb/CONTRIBUTE
143
gdb/CONTRIBUTE
@@ -1,143 +0,0 @@
|
||||
|
||||
Contributing to GDB
|
||||
|
||||
GDB is a collaborative project and one which wants to encourage new
|
||||
development. You may wish to fix GDB bugs, improve testing, port GDB
|
||||
to a new platform, update documentation, add new GDB features, and the
|
||||
like. To help with this, there is a lot of documentation
|
||||
available.. In addition to the user guide and internals manual
|
||||
included in the GDB distribution, the GDB web pages also contain much
|
||||
information.
|
||||
|
||||
You may also want to submit your change so that can be considered for
|
||||
conclusion in a future version of GDB (see below). Regardless, we
|
||||
encourage you to distribute the change yourself.
|
||||
|
||||
If you don't feel up to hacking GDB, there are still plenty of ways to
|
||||
help! You can answer questions on the mailing lists, write
|
||||
documentation, find bugs, create a GDB related website (contribute to
|
||||
the official GDB web site), or create a GDB related software
|
||||
package. We welcome all of the above and feel free to ask on the GDB
|
||||
mailing lists if you are looking for feedback or for people to review
|
||||
a work in progress.
|
||||
|
||||
Ref: http://www.gnu.org/software/gdb/
|
||||
|
||||
Finally, there are certain legal requirements and style issues which
|
||||
all contributors need to be aware of.
|
||||
|
||||
o Coding Standards
|
||||
|
||||
All contributions must conform to the GNU Coding Standard.
|
||||
Submissions which do not conform to the standards will be
|
||||
returned with a request to reformat the changes.
|
||||
|
||||
GDB has certain additional coding requirements. Those
|
||||
requirements are explained in the GDB internals documentation
|
||||
in the gdb/doc directory.
|
||||
|
||||
Ref: http://www.gnu.org/prep/standards_toc.html
|
||||
|
||||
|
||||
o Copyright Assignment
|
||||
|
||||
Before we can accept code contributions from you, we need a
|
||||
copyright assignment form filled out and filed with the FSF.
|
||||
|
||||
See some documentation by the FSF for details and contact us
|
||||
(either via the GDB mailing list or the GDB maintainer that is
|
||||
taking care of your contributions) to obtain the relevant
|
||||
forms.
|
||||
|
||||
Small changes can be accepted without a copyright assignment form on file.
|
||||
|
||||
Ref: http://www.gnu.org/prep/maintain.html#SEC6
|
||||
|
||||
|
||||
o Submitting Patches
|
||||
|
||||
Every patch must have several pieces of information before we
|
||||
can properly evaluate it.
|
||||
|
||||
A description of the bug and how your patch fixes this
|
||||
bug. A reference to a testsuite failure is very helpful. For
|
||||
new features a description of the feature and your
|
||||
implementation.
|
||||
|
||||
A ChangeLog entry as plaintext (separate from the patch); see
|
||||
the various ChangeLog files for format and content. Note that,
|
||||
unlike some other projects, we do require ChangeLogs also for
|
||||
documentation (i.e., .texi files).
|
||||
|
||||
The patch itself. If you are accessing the CVS repository use
|
||||
"cvs update; cvs diff -cp"; else, use "diff -cp OLD NEW" or
|
||||
"diff -up OLD NEW". If your version of diff does not support
|
||||
these options, then get the latest version of GNU diff.
|
||||
|
||||
We accept patches as plain text (preferred for the compilers
|
||||
themselves), MIME attachments (preferred for the web pages),
|
||||
or as uuencoded gzipped text.
|
||||
|
||||
When you have all these pieces, bundle them up in a mail
|
||||
message and send it to gdb-patches@sources.redhat.com. All
|
||||
patches and related discussion should be sent to the
|
||||
gdb-patches mailinglist. For further information on the GDB
|
||||
CVS repository, see the Anonymous read-only CVS access and
|
||||
Read-write CVS access page.
|
||||
|
||||
--
|
||||
|
||||
Supplemental information for GDB:
|
||||
|
||||
o Please try to run the relevant testsuite before and after
|
||||
committing a patch
|
||||
|
||||
If the contributor doesn't do it then the maintainer will. A
|
||||
contributor might include before/after test results in their
|
||||
contribution.
|
||||
|
||||
|
||||
o For bug fixes, please try to include a way of
|
||||
demonstrating that the patch actually fixes something.
|
||||
|
||||
The best way of doing this is to ensure that the
|
||||
testsuite contains one or more test cases that
|
||||
fail without the fix but pass with the fix.
|
||||
|
||||
People are encouraged to submit patches that extend
|
||||
the testsuite.
|
||||
|
||||
|
||||
o Please read your patch before submitting it.
|
||||
|
||||
A patch containing several unrelated changes or
|
||||
arbitrary reformats will be returned with a request
|
||||
to re-formatting / split it.
|
||||
|
||||
|
||||
o If ``gdb/configure.in'' is modified then you don't
|
||||
need to include patches to the regenerated file
|
||||
``configure''.
|
||||
|
||||
The maintainer will re-generate those files
|
||||
using autoconf (2.13 as of 2000-02-29).
|
||||
|
||||
|
||||
o If ``gdb/gdbarch.sh'' is modified, you don't
|
||||
need to include patches to the generated files
|
||||
``gdbarch.h'' and ``gdbarch.c''.
|
||||
|
||||
See ``gdb/configure.in'' above.
|
||||
|
||||
|
||||
o When submitting a patch that fixes a bug
|
||||
in GDB's bug database a brief reference
|
||||
to the bug can be included in the ChangeLog
|
||||
vis
|
||||
|
||||
* CONTRIBUTE: Mention PR convention.
|
||||
Fix PR gdb/4705.
|
||||
|
||||
The text ``PR gdb/4705'' should also be included
|
||||
in the CVS commit message. That causes the
|
||||
patch to automatically be archived with the PR.
|
||||
340
gdb/COPYING
340
gdb/COPYING
@@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU 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. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), 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 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 show them these terms so they know their
|
||||
rights.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License 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 derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
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 License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary 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
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 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 Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing 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 for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
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.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. 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.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this 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
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. 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.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. 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.
|
||||
|
||||
12. 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
|
||||
|
||||
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 the public, 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy 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 is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
8830
gdb/ChangeLog
8830
gdb/ChangeLog
File diff suppressed because it is too large
Load Diff
3155
gdb/ChangeLog-1990
3155
gdb/ChangeLog-1990
File diff suppressed because it is too large
Load Diff
5175
gdb/ChangeLog-1991
5175
gdb/ChangeLog-1991
File diff suppressed because it is too large
Load Diff
6285
gdb/ChangeLog-1992
6285
gdb/ChangeLog-1992
File diff suppressed because it is too large
Load Diff
7597
gdb/ChangeLog-1993
7597
gdb/ChangeLog-1993
File diff suppressed because it is too large
Load Diff
5705
gdb/ChangeLog-1994
5705
gdb/ChangeLog-1994
File diff suppressed because it is too large
Load Diff
4915
gdb/ChangeLog-1995
4915
gdb/ChangeLog-1995
File diff suppressed because it is too large
Load Diff
5116
gdb/ChangeLog-1996
5116
gdb/ChangeLog-1996
File diff suppressed because it is too large
Load Diff
2909
gdb/ChangeLog-1997
2909
gdb/ChangeLog-1997
File diff suppressed because it is too large
Load Diff
7220
gdb/ChangeLog-1998
7220
gdb/ChangeLog-1998
File diff suppressed because it is too large
Load Diff
9296
gdb/ChangeLog-1999
9296
gdb/ChangeLog-1999
File diff suppressed because it is too large
Load Diff
8204
gdb/ChangeLog-2000
8204
gdb/ChangeLog-2000
File diff suppressed because it is too large
Load Diff
9895
gdb/ChangeLog-2001
9895
gdb/ChangeLog-2001
File diff suppressed because it is too large
Load Diff
4838
gdb/ChangeLog-3.x
4838
gdb/ChangeLog-3.x
File diff suppressed because it is too large
Load Diff
471
gdb/MAINTAINERS
471
gdb/MAINTAINERS
@@ -1,471 +0,0 @@
|
||||
GDB Maintainers
|
||||
|
||||
|
||||
Blanket Write Privs
|
||||
(alphabetic)
|
||||
|
||||
Jim Blandy jimb@redhat.com
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
Andrew Cagney ac131313@redhat.com
|
||||
J.T. Conklin jtc@redback.com
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Stan Shebs shebs@apple.com
|
||||
Michael Snyder msnyder@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Eli Zaretskii eliz@gnu.org
|
||||
|
||||
|
||||
Various Maintainers
|
||||
|
||||
Note individuals who maintain parts of the debugger need approval to
|
||||
check in changes outside of the immediate domain that they maintain.
|
||||
|
||||
If there is no maintainer for a given domain then the responsibility
|
||||
falls to the head maintainer.
|
||||
|
||||
If there are several maintainers for a given domain then
|
||||
responsibility falls to the first maintainer. The first maintainer is
|
||||
free to devolve that responsibility among the other maintainers.
|
||||
|
||||
|
||||
The Obvious Fix Rule
|
||||
|
||||
All maintainers listed in this file are allowed to check in obvious
|
||||
fixes.
|
||||
|
||||
An "obvious fix" means that there is no possibility that anyone will
|
||||
disagree with the change.
|
||||
|
||||
A good mental test is "will the person who hates my work the most be
|
||||
able to find fault with the change" - if so, then it's not obvious and
|
||||
needs to be posted first. :-)
|
||||
|
||||
Something like changing or bypassing an interface is _not_ an obvious
|
||||
fix, since such a change without discussion will result in
|
||||
instantaneous and loud complaints.
|
||||
|
||||
|
||||
Target/Architecture:
|
||||
|
||||
Generic ISA (Instruction Set Architecture) issues, API variants, CPU
|
||||
variants. *-tdep.c. The Target/Architecture maintainer works with the
|
||||
host maintainer when resolving build issues. The Target/Architecture
|
||||
maintainer works with the native maintainer when resolving API issues.
|
||||
|
||||
a29k Deleted.
|
||||
|
||||
alpha --target=alpha-dec-osf4.0a -Werror
|
||||
Maintenance only
|
||||
|
||||
arc --target=arc-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
arm --target=arm-elf ,
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
Scott Bambrough scottb@netwinder.org
|
||||
Richard Earnshaw rearnsha@arm.com
|
||||
Not multi-arch
|
||||
|
||||
avr --target=avr ,-Werror
|
||||
Theodore A. Roth troth@verinet.com
|
||||
|
||||
cris --target=cris-elf ,-Werror
|
||||
Orjan Friberg orjanf@axis.com
|
||||
|
||||
d10v --target=d10v-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
d30v --target=d30v-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
djgpp --target=i586-pc-msdosdjgpp ,-Werror
|
||||
(See native and host)
|
||||
|
||||
fr30 --target=fr30-elf -Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
h8300 --target=h8300hms -Werror
|
||||
Maintenance only
|
||||
Not multi-arch, work in progress
|
||||
|
||||
h8500 --target=h8500hms -Werror
|
||||
Maintenance only
|
||||
Not multi-arch, work in progress
|
||||
|
||||
i386 --target=i386-elf,i386-aout ,-Werror
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
|
||||
i960 --target=i960-coff ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
ia64 --target=ia64-linux ,-Werror
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
m32r (--target=m32r-elf broken)
|
||||
Michael Snyder msnyder@redhat.com
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
m68hc11 --target=m68hc11-elf ,-Werror ,
|
||||
Stephane Carrez stcarrez@nerim.fr
|
||||
|
||||
m68k --target=m68k-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
m88k --target=m88k ,-Werror
|
||||
Known problem in 5.1
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
mcore --target=mcore-elf,mcore-pe ,-Werror
|
||||
Maintenance only
|
||||
|
||||
mips --target=mips-elf,mips64-elf ,-Werror
|
||||
Andrew Cagney cagney@redhat.com
|
||||
|
||||
mn10200 --target=mn10200-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
mn10300 --target=mn10300-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
ns32k --target=ns32k-netbsd ,-Werror
|
||||
Maintenance only
|
||||
|
||||
pa (--target=hppa1.1-hp-proelf broken)
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
powerpc --target=powerpc-eabi ,-Werror
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
rs6000 --target=rs6000-ibm-aix4.1 ,-Werror
|
||||
(see rs6000 native and ppc target)
|
||||
|
||||
s390 --target=s390-linux ,-Werror
|
||||
(contact DJ Barrow djbarrow@de.ibm.com)
|
||||
|
||||
sh --target=sh-elf ,-Werror
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
|
||||
sparc --target=sparc-elf,sparc64-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
tic80 Deleted.
|
||||
|
||||
v850 --target=v850-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
vax --target=vax-dec-vms5.5 ,-Werror
|
||||
Maintenance only
|
||||
|
||||
w65 Deleted.
|
||||
|
||||
x86-64 --target=x86_64-linux-gnu ,-Werror
|
||||
Maintenance only
|
||||
|
||||
xstormy16 --target=xstormy16-elf ,-Werror
|
||||
Corinna Vinschen vinschen@redhat.com
|
||||
|
||||
z8k --target=z8k-coff ,-Werror
|
||||
Known problem in 5.1
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
All developers recognized by this file can make arbitrary changes to
|
||||
OBSOLETE targets.
|
||||
|
||||
All maintainers can test and thence approve non-trivial changes to
|
||||
``maintenance only'' targets submitted by recognized developers.
|
||||
|
||||
All recognized developers can make mechanical changes (by virtue of
|
||||
the obvious fix rule) to ``maintenance only'' targets. The change
|
||||
shall be sanity checked by compiling with one of the listed targets.
|
||||
|
||||
The Bourne shell script:
|
||||
|
||||
cat MAINTAINERS | tr -s '[\t]' '[ ]' | sed -n '
|
||||
/^[ ]*[-a-z0-9\.]*[ ]*[(]*--target=.*/ !d
|
||||
s/^.*--target=//
|
||||
s/).*$//
|
||||
h
|
||||
:loop
|
||||
g
|
||||
/^[^ ]*,/ !b end
|
||||
s/,[^ ]*//
|
||||
p
|
||||
g
|
||||
s/^[^,]*,//
|
||||
h
|
||||
b loop
|
||||
:end
|
||||
p
|
||||
'
|
||||
|
||||
can be used to generate a list of buildable targets. The list
|
||||
containing values for the configure options --target=,
|
||||
--enable-gdb-build-warnings= and optionally
|
||||
--enable-sim-build-warnings vis:
|
||||
|
||||
arc-elf ,-Werror
|
||||
...
|
||||
m68hc11-elf ,-Werror ,
|
||||
...
|
||||
hppa1.1-hp-proelf broken
|
||||
...
|
||||
|
||||
While the ``broken'' targets are included in the listing, the are not
|
||||
expected to build.
|
||||
|
||||
|
||||
Host/Native:
|
||||
|
||||
The Native maintainer is responsible for target specific native
|
||||
support - typically shared libraries and quirks to procfs/ptrace/...
|
||||
The Native maintainer works with the Arch and Core maintainers when
|
||||
resolving more generic problems.
|
||||
|
||||
The host maintainer ensures that gdb (including mmalloc) can be built
|
||||
as a cross debugger on their platform.
|
||||
|
||||
AIX Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
djgpp native Eli Zaretskii eliz@gnu.org
|
||||
DJ Delorie dj@redhat.com
|
||||
MS Windows (NT, CE, '00, 9x, Me) host & native
|
||||
Chris Faylor cgf@redhat.com
|
||||
GNU/Linux/x86 native & host
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
Jim Blandy jimb@redhat.com
|
||||
GNU/Linux PPC native Kevin Buettner kevinb@redhat.com
|
||||
GNU/Linux MIPS native & host
|
||||
Daniel Jacobowitz dan@debian.org
|
||||
GNU/Linux m68k Andreas Schwab schwab@suse.de
|
||||
FreeBSD native & host Mark Kettenis kettenis@gnu.org
|
||||
David O'Brien obrien@freebsd.org
|
||||
hurd native Mark Kettenis kettenis@gnu.org
|
||||
NetBSD native & host Jason Thorpe thorpej@wasabisystems.com
|
||||
SCO/Unixware Robert Lipe rjl@sco.com
|
||||
GNU/Linux ARM native Scott Bambrough scottb@netwinder.org
|
||||
Solaris/x86 native & host (devolved)
|
||||
Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Solaris/SPARC native & host (devolved)
|
||||
Michael Snyder msnyder@redhat.com
|
||||
|
||||
|
||||
|
||||
Core: Generic components used by all of GDB
|
||||
|
||||
generic arch support Andrew Cagney cagney@redhat.com
|
||||
Any host/target maintainer can add to
|
||||
gdbarch.{c,h,sh}. Send tricky ones to cagney.
|
||||
target vector Andrew Cagney cagney@redhat.com
|
||||
main (main.c, top.c) Elena Zannoni ezannoni@redhat.com
|
||||
event loop Elena Zannoni ezannoni@redhat.com
|
||||
|
||||
generic symtabs Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
dwarf readers Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
elf reader Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
stabs reader Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
coff reader Philippe De Muyter phdm@macqel.be
|
||||
xcoff reader Any maintainer can modify this; please send tricky
|
||||
ones to Kevin Buettner <kevinb@redhat.com>
|
||||
linespec Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
HP/UX readers Any [past] maintainer can modify this.
|
||||
Please send tricky ones to the symtabs maintainers.
|
||||
|
||||
tracing bytecode stuff Jim Blandy jimb@redhat.com
|
||||
tracing Michael Snyder msnyder@redhat.com
|
||||
threads Michael Snyder msnyder@redhat.com
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
breakpoints Michael Snyder msnyder@redhat.com
|
||||
Jim Blandy jimb@redhat.com
|
||||
language support (Blanket Write Privs Maintainers)
|
||||
C++ Daniel Jacobowitz dan@debian.org
|
||||
Java support (devolved)
|
||||
Per Bothner per@bothner.com
|
||||
Anthony Green green@redhat.com
|
||||
Pascal support Pierre Muller muller@sources.redhat.com
|
||||
Scheme support Jim Blandy jimb@redhat.com
|
||||
|
||||
shared libs (devolved) Jim Blandy jimb@redhat.com
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
xcoffsolib Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
|
||||
remote.c Andrew Cagney cagney@redhat.com
|
||||
include/remote-sim.h, remote-sim.c
|
||||
Andrew Cagney cagney@redhat.com
|
||||
sds protocol Fernando Nasser fnasser@redhat.com
|
||||
rdi/adp protocol Fernando Nasser fnasser@redhat.com
|
||||
documentation Eli Zaretskii eliz@gnu.org
|
||||
testsuite Fernando Nasser fnasser@redhat.com
|
||||
config Mark Salter msalter@redhat.com
|
||||
lib Mark Salter msalter@redhat.com
|
||||
gdbtk (gdb.gdbtk) Keith Seitz keiths@redhat.com
|
||||
c++ (gdb.c++) Michael Chastain mec@shout.net
|
||||
mi tests (gdb.mi) Elena Zannoni ezannoni@redhat.com
|
||||
Andrew Cagney cagney@redhat.com
|
||||
stabs (gdb.stabs) Elena Zannoni ezannoni@redhat.com
|
||||
threads (gdb.threads) Michael Snyder msnyder@redhat.com
|
||||
trace (gdb.trace) Michael Snyder msnyder@redhat.com
|
||||
hp tests (gdb.hp) (vacant)
|
||||
Java tests (gdb.java) Anthony Green green@redhat.com
|
||||
Kernel Object Display Fernando Nasser fnasser@redhat.com
|
||||
|
||||
|
||||
UI: External (user) interfaces.
|
||||
|
||||
command interpreter Fernando Nasser fnasser@redhat.com
|
||||
gdbtk (c & tcl) Jim Ingham jingham@apple.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
Keith Seitz keiths@redhat.com
|
||||
libgui (w/foundry, sn) Jim Ingham jingham@apple.com
|
||||
Keith Seitz keiths@redhat.com
|
||||
mi (gdb/mi) Andrew Cagney cagney@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
tui (vacant)
|
||||
Technical Contact Point wdb@cup.hp.com
|
||||
|
||||
|
||||
Misc:
|
||||
|
||||
gdb/gdbserver Daniel Jacobowitz dan@debian.org
|
||||
|
||||
Web pages. Jim Kingdon jkingdon@engr.sgi.com ++
|
||||
(anyone can edit; kingdon is just lead maintainer)
|
||||
|
||||
Makefile.in, configure* ALL
|
||||
|
||||
mmalloc/ ALL Host maintainers
|
||||
|
||||
NEWS ALL
|
||||
|
||||
sim/ See sim/MAINTAINERS
|
||||
|
||||
readline/ Master version: ftp://ftp.cwru.edu/pub/bash/
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Host maintainers (host dependant parts)
|
||||
(but get your changes into the master version)
|
||||
|
||||
tcl/ tk/ itcl/ Ian Roxborough irox@redhat.com
|
||||
|
||||
Write After Approval
|
||||
(alphabetic)
|
||||
|
||||
To get recommended for the Write After Approval list you need a valid
|
||||
FSF assignment and have submitted one good patch.
|
||||
|
||||
David Anderson davea@sgi.com
|
||||
Scott Bambrough scottb@netwinder.org
|
||||
Jim Blandy jimb@redhat.com
|
||||
Philip Blundell philb@gnu.org
|
||||
Per Bothner per@bothner.com
|
||||
Joel Brobecker brobecker@act-europe.fr
|
||||
Dave Brolley brolley@redhat.com
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
Andrew Cagney ac131313@redhat.com
|
||||
Stephane Carrez stcarrez@nerim.fr
|
||||
Michael Chastain mec@shout.net
|
||||
Eric Christopher echristo@redhat.com
|
||||
Nick Clifton nickc@redhat.com
|
||||
Philippe De Muyter phdm@macqel.be
|
||||
Chris G. Demetriou cgd@broadcom.com
|
||||
Klee Dienes kdienes@apple.com
|
||||
DJ Delorie dj@redhat.com
|
||||
Richard Earnshaw rearnsha@arm.com
|
||||
Frank Ch. Eigler fche@redhat.com
|
||||
Ben Elliston bje@redhat.com
|
||||
Anthony Green green@redhat.com
|
||||
Matthew Green mrg@eterna.com.au
|
||||
Chris Faylor cgf@redhat.com
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Orjan Friberg orjanf@axis.com
|
||||
Ben Harris bjh21@netbsd.org
|
||||
Richard Henderson rth@redhat.com
|
||||
Aldy Hernandez aldyh@redhat.com
|
||||
Paul Hilfinger hilfinger@gnat.com
|
||||
Matt Hiller hiller@redhat.com
|
||||
Kazu Hirata kazu@hxi.com
|
||||
Jeff Holcomb jeffh@redhat.com
|
||||
Don Howard dhoward@redhat.com
|
||||
Martin Hunt hunt@redhat.com
|
||||
Jim Ingham jingham@apple.com
|
||||
Daniel Jacobowitz dan@debian.org
|
||||
Andreas Jaeger aj@suse.de
|
||||
Geoff Keating geoffk@redhat.com
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
Jim Kingdon jkingdon@engr.sgi.com ++
|
||||
Jeff Law law@redhat.com
|
||||
Jonathan Larmour jlarmour@redhat.co.uk
|
||||
Robert Lipe rjl@sco.com
|
||||
H.J. Lu hjl@lucon.org
|
||||
Michal Ludvig mludvig@suse.cz
|
||||
Glen McCready gkm@redhat.com
|
||||
Greg McGary greg@mcgary.org
|
||||
Jason Merrill jason@redhat.com
|
||||
David S. Miller davem@redhat.com
|
||||
Jason Molenda jmolenda@apple.com
|
||||
Pierre Muller muller@sources.redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
David O'Brien obrien@freebsd.org
|
||||
Alexandre Oliva aoliva@redhat.com
|
||||
Tom Rix trix@redhat.com
|
||||
Theodore A. Roth troth@verinet.com
|
||||
Ian Roxborough irox@redhat.com
|
||||
Grace Sainsbury graces@redhat.com
|
||||
Mark Salter msalter@redhat.com
|
||||
Peter Schauer Peter.Schauer@regent
|
||||
Andreas Schwab schwab@suse.de
|
||||
Keith Seitz keiths@redhat.com
|
||||
Jiri Smid smid@suse.cz
|
||||
David Smith dsmith@redhat.com
|
||||
Stephen P. Smith ischis2@home.com
|
||||
Jackie Smith Cashion jsmith@redhat.com
|
||||
Stan Shebs shebs@apple.com
|
||||
Michael Snyder msnyder@redhat.com
|
||||
Petr Sorfa petrs@caldera.com
|
||||
Gary Thomas gthomas@redhat.com
|
||||
Jason Thorpe thorpej@wasabisystems.com
|
||||
Tom Tromey tromey@redhat.com
|
||||
Corinna Vinschen vinschen@redhat.com
|
||||
Keith Walker keith.walker@arm.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Eli Zaretskii eliz@gnu.org
|
||||
|
||||
|
||||
|
||||
Past Maintainers
|
||||
|
||||
Jimmy Guo (gdb.hp, tui) guo at cup dot hp dot com
|
||||
Jeff Law (hppa) law at cygnus dot com
|
||||
Daniel Berlin (C++ support) dan at cgsoftware dot com
|
||||
Nick Duffek (powerpc, SCO, Sol/x86) nick at duffek dot com
|
||||
David Taylor (d10v, sparc, utils, defs,
|
||||
expression evaluator, language support) taylor at candd dot org
|
||||
J.T. Conklin (dcache, NetBSD, remote) jtc at redback dot com
|
||||
Frank Ch. Eigler (sim) fche at redhat dot com
|
||||
|
||||
|
||||
|
||||
Folks that have been caught up in a paper trail:
|
||||
|
||||
Jim Kingdon jkingdon@engr.sgi.com
|
||||
|
||||
--
|
||||
|
||||
(*) Indicates folks that don't have a Kerberos/SSH account in the GDB
|
||||
group.
|
||||
2462
gdb/Makefile.in
2462
gdb/Makefile.in
File diff suppressed because it is too large
Load Diff
32
gdb/PROBLEMS
32
gdb/PROBLEMS
@@ -1,32 +0,0 @@
|
||||
|
||||
Known problems in GDB 5.2
|
||||
|
||||
See also: http://www.gnu.org/software/gdb/bugs/
|
||||
|
||||
|
||||
hppa2.0-hp-hpux10.20
|
||||
--------------------
|
||||
|
||||
gdb/487: The top level make files used to build GDB are not compatible
|
||||
with HP/UX make. As a workaround, use GNU make.
|
||||
|
||||
gdb/486: The HP/UX C compiler defaults to K&R mode but GDB only builds
|
||||
with an ISO C compiler. The top level configuration incorrectly sets
|
||||
CC to `cc' instead of `cc -Ae'. As a workaround, the correct compiler
|
||||
can be specified as part of the configuration vis:
|
||||
|
||||
$ 'CC=cc -Ae' ./configure
|
||||
|
||||
|
||||
s390*-*-*
|
||||
---------
|
||||
|
||||
gdb/513: GDB does not build on s390 GNU/Linux. The problem should be
|
||||
fixed in more recent sources.
|
||||
|
||||
|
||||
i386-*-freebsd4.4*
|
||||
------------------
|
||||
|
||||
gdb/455: GDB doesn't build on a FreeBSD 4.4-STABLE system. The
|
||||
problem is still being investigated.
|
||||
578
gdb/README
578
gdb/README
@@ -1,578 +0,0 @@
|
||||
README for gdb-5.2 release
|
||||
Updated 17 April, 2002 by Andrew Cagney
|
||||
|
||||
This is GDB, the GNU source-level debugger.
|
||||
|
||||
A summary of new features is in the file `gdb/NEWS'.
|
||||
|
||||
Check the GDB home page at http://www.gnu.org/software/gdb/ for up to
|
||||
date release information, mailing list links and archives, etc.
|
||||
|
||||
The file `gdb/PROBLEMS' contains information on problems identified
|
||||
late in the release cycle. GDB's bug tracking data base at
|
||||
http://www.gnu.org/software/gdb/bugs/ contains a more complete list of
|
||||
bugs.
|
||||
|
||||
|
||||
Unpacking and Installation -- quick overview
|
||||
==========================
|
||||
|
||||
In this release, the GDB debugger sources, the generic GNU include
|
||||
files, the BFD ("binary file description") library, the readline
|
||||
library, and other libraries all have directories of their own
|
||||
underneath the gdb-5.2 directory. The idea is that a variety of GNU
|
||||
tools can share a common copy of these things. Be aware of variation
|
||||
over time--for example don't try to build gdb with a copy of bfd from
|
||||
a release other than the gdb release (such as a binutils release),
|
||||
especially if the releases are more than a few weeks apart.
|
||||
Configuration scripts and makefiles exist to cruise up and down this
|
||||
directory tree and automatically build all the pieces in the right
|
||||
order.
|
||||
|
||||
When you unpack the gdb-5.2.tar.gz file, you'll find a directory
|
||||
called `gdb-5.2', which contains:
|
||||
|
||||
COPYING config.sub intl missing opcodes
|
||||
COPYING.LIB configure libiberty mkinstalldirs readline
|
||||
Makefile.in configure.in libtool.m4 mmalloc sim
|
||||
README djunpack.bat ltcf-c.sh move-if-change symlink-tree
|
||||
bfd etc ltcf-cxx.sh mpw-README texinfo
|
||||
config gdb ltcf-gcj.sh mpw-build.in utils
|
||||
config-ml.in gettext.m4 ltconfig mpw-config.in ylwrap
|
||||
config.guess include ltmain.sh mpw-configure
|
||||
config.if install-sh md5.sum mpw-install
|
||||
|
||||
You can build GDB right in the source directory:
|
||||
|
||||
cd gdb-5.2
|
||||
./configure
|
||||
make
|
||||
cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
|
||||
|
||||
However, we recommend that an empty directory be used instead.
|
||||
This way you do not clutter your source tree with binary files
|
||||
and will be able to create different builds with different
|
||||
configuration options.
|
||||
|
||||
You can build GDB in any empty build directory:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
<full path to your sources>/gdb-5.2/configure
|
||||
make
|
||||
cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
|
||||
|
||||
(Building GDB with DJGPP tools for MS-DOS/MS-Windows is slightly
|
||||
different; see the file gdb-5.2/gdb/config/djgpp/README for details.)
|
||||
|
||||
This will configure and build all the libraries as well as GDB. If
|
||||
`configure' can't determine your system type, specify one as its
|
||||
argument, e.g., `./configure sun4' or `./configure decstation'.
|
||||
|
||||
If you get compiler errors during this stage, see the `Reporting
|
||||
Bugs' section below; there are a few known problems.
|
||||
|
||||
GDB requires an ISO C (ANSI C) compiler. If you do not have an ISO
|
||||
C compiler for your system, you may be able to download and install
|
||||
the GNU CC compiler. It is available via anonymous FTP from the
|
||||
directory `ftp://ftp.gnu.org/pub/gnu/gcc'.
|
||||
|
||||
GDB can be used as a cross-debugger, running on a machine of one
|
||||
type while debugging a program running on a machine of another type.
|
||||
See below.
|
||||
|
||||
|
||||
More Documentation
|
||||
******************
|
||||
|
||||
All the documentation for GDB comes as part of the machine-readable
|
||||
distribution. The documentation is written in Texinfo format, which
|
||||
is a documentation system that uses a single source file to produce
|
||||
both on-line information and a printed manual. You can use one of the
|
||||
Info formatting commands to create the on-line version of the
|
||||
documentation and TeX (or `texi2roff') to typeset the printed version.
|
||||
|
||||
GDB includes an already formatted copy of the on-line Info version
|
||||
of this manual in the `gdb/doc' subdirectory. The main Info file is
|
||||
`gdb-5.2/gdb/doc/gdb.info', and it refers to subordinate files
|
||||
matching `gdb.info*' in the same directory. If necessary, you can
|
||||
print out these files, or read them with any editor; but they are
|
||||
easier to read using the `info' subsystem in GNU Emacs or the
|
||||
standalone `info' program, available as part of the GNU Texinfo
|
||||
distribution.
|
||||
|
||||
If you want to format these Info files yourself, you need one of the
|
||||
Info formatting programs, such as `texinfo-format-buffer' or
|
||||
`makeinfo'.
|
||||
|
||||
If you have `makeinfo' installed, and are in the top level GDB
|
||||
source directory (`gdb-5.2', in the case of version 5.2), you can make
|
||||
the Info file by typing:
|
||||
|
||||
cd gdb/doc
|
||||
make info
|
||||
|
||||
If you want to typeset and print copies of this manual, you need
|
||||
TeX, a program to print its DVI output files, and `texinfo.tex', the
|
||||
Texinfo definitions file. This file is included in the GDB
|
||||
distribution, in the directory `gdb-5.2/texinfo'.
|
||||
|
||||
TeX is a typesetting program; it does not print files directly, but
|
||||
produces output files called DVI files. To print a typeset document,
|
||||
you need a program to print DVI files. If your system has TeX
|
||||
installed, chances are it has such a program. The precise command to
|
||||
use depends on your system; `lpr -d' is common; another (for PostScript
|
||||
devices) is `dvips'. The DVI print command may require a file name
|
||||
without any extension or a `.dvi' extension.
|
||||
|
||||
TeX also requires a macro definitions file called `texinfo.tex'.
|
||||
This file tells TeX how to typeset a document written in Texinfo
|
||||
format. On its own, TeX cannot read, much less typeset a Texinfo file.
|
||||
`texinfo.tex' is distributed with GDB and is located in the
|
||||
`gdb-5.2/texinfo' directory.
|
||||
|
||||
If you have TeX and a DVI printer program installed, you can typeset
|
||||
and print this manual. First switch to the the `gdb' subdirectory of
|
||||
the main source directory (for example, to `gdb-5.2/gdb') and then type:
|
||||
|
||||
make doc/gdb.dvi
|
||||
|
||||
If you prefer to have the manual in PDF format, type this from the
|
||||
`gdb/doc' subdirectory of the main source directory:
|
||||
|
||||
make gdb.pdf
|
||||
|
||||
For this to work, you will need the PDFTeX package to be installed.
|
||||
|
||||
|
||||
Installing GDB
|
||||
**************
|
||||
|
||||
GDB comes with a `configure' script that automates the process of
|
||||
preparing GDB for installation; you can then use `make' to build the
|
||||
`gdb' program.
|
||||
|
||||
The GDB distribution includes all the source code you need for GDB in
|
||||
a single directory, whose name is usually composed by appending the
|
||||
version number to `gdb'.
|
||||
|
||||
For example, the GDB version 5.2 distribution is in the `gdb-5.2'
|
||||
directory. That directory contains:
|
||||
|
||||
`gdb-5.2/{COPYING,COPYING.LIB}'
|
||||
Standard GNU license files. Please read them.
|
||||
|
||||
`gdb-5.2/bfd'
|
||||
source for the Binary File Descriptor library
|
||||
|
||||
`gdb-5.2/config*'
|
||||
script for configuring GDB, along with other support files
|
||||
|
||||
`gdb-5.2/gdb'
|
||||
the source specific to GDB itself
|
||||
|
||||
`gdb-5.2/include'
|
||||
GNU include files
|
||||
|
||||
`gdb-5.2/libiberty'
|
||||
source for the `-liberty' free software library
|
||||
|
||||
`gdb-5.2/mmalloc'
|
||||
source for the GNU memory-mapped malloc package
|
||||
|
||||
`gdb-5.2/opcodes'
|
||||
source for the library of opcode tables and disassemblers
|
||||
|
||||
`gdb-5.2/readline'
|
||||
source for the GNU command-line interface
|
||||
NOTE: The readline library is compiled for use by GDB, but will
|
||||
not be installed on your system when "make install" is issued.
|
||||
|
||||
`gdb-5.2/sim'
|
||||
source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc)
|
||||
|
||||
`gdb-5.2/intl'
|
||||
source for the GNU gettext library, for internationalization.
|
||||
This is slightly modified from the standalone gettext
|
||||
distribution you can get from GNU.
|
||||
|
||||
`gdb-5.2/texinfo'
|
||||
The `texinfo.tex' file, which you need in order to make a printed
|
||||
manual using TeX.
|
||||
|
||||
`gdb-5.2/etc'
|
||||
Coding standards, useful files for editing GDB, and other
|
||||
miscellanea.
|
||||
|
||||
`gdb-5.2/utils'
|
||||
A grab bag of random utilities.
|
||||
|
||||
Note: the following instructions are for building GDB on Unix or
|
||||
Unix-like systems. Instructions for building with DJGPP for
|
||||
MS-DOS/MS-Windows are in the file gdb/config/djgpp/README.
|
||||
|
||||
The simplest way to configure and build GDB is to run `configure'
|
||||
from the `gdb-VERSION-NUMBER' source directory, which in this example
|
||||
is the `gdb-5.2' directory.
|
||||
|
||||
First switch to the `gdb-VERSION-NUMBER' source directory if you are
|
||||
not already in it; then run `configure'.
|
||||
|
||||
For example:
|
||||
|
||||
cd gdb-5.2
|
||||
./configure
|
||||
make
|
||||
|
||||
Running `configure' followed by `make' builds the `bfd',
|
||||
`readline', `mmalloc', and `libiberty' libraries, then `gdb' itself.
|
||||
The configured source files, and the binaries, are left in the
|
||||
corresponding source directories.
|
||||
|
||||
`configure' is a Bourne-shell (`/bin/sh') script; if your system
|
||||
does not recognize this automatically when you run a different shell,
|
||||
you may need to run `sh' on it explicitly:
|
||||
|
||||
sh configure
|
||||
|
||||
If you run `configure' from a directory that contains source
|
||||
directories for multiple libraries or programs, such as the `gdb-5.2'
|
||||
source directory for version 5.2, `configure' creates configuration
|
||||
files for every directory level underneath (unless you tell it not to,
|
||||
with the `--norecursion' option).
|
||||
|
||||
You can run the `configure' script from any of the subordinate
|
||||
directories in the GDB distribution, if you only want to configure that
|
||||
subdirectory; but be sure to specify a path to it.
|
||||
|
||||
For example, with version 5.2, type the following to configure only
|
||||
the `bfd' subdirectory:
|
||||
|
||||
cd gdb-5.2/bfd
|
||||
../configure
|
||||
|
||||
You can install `gdb' anywhere; it has no hardwired paths. However,
|
||||
you should make sure that the shell on your path (named by the `SHELL'
|
||||
environment variable) is publicly readable. Remember that GDB uses the
|
||||
shell to start your program--some systems refuse to let GDB debug child
|
||||
processes whose programs are not readable.
|
||||
|
||||
|
||||
Compiling GDB in another directory
|
||||
==================================
|
||||
|
||||
If you want to run GDB versions for several host or target machines,
|
||||
you need a different `gdb' compiled for each combination of host and
|
||||
target. `configure' is designed to make this easy by allowing you to
|
||||
generate each configuration in a separate subdirectory, rather than in
|
||||
the source directory. If your `make' program handles the `VPATH'
|
||||
feature correctly (GNU `make' and SunOS 'make' are two that should),
|
||||
running `make' in each of these directories builds the `gdb' program
|
||||
specified there.
|
||||
|
||||
To build `gdb' in a separate directory, run `configure' with the
|
||||
`--srcdir' option to specify where to find the source. (You also need
|
||||
to specify a path to find `configure' itself from your working
|
||||
directory. If the path to `configure' would be the same as the
|
||||
argument to `--srcdir', you can leave out the `--srcdir' option; it
|
||||
will be assumed.)
|
||||
|
||||
For example, with version 5.2, you can build GDB in a separate
|
||||
directory for a Sun 4 like this:
|
||||
|
||||
cd gdb-5.2
|
||||
mkdir ../gdb-sun4
|
||||
cd ../gdb-sun4
|
||||
../gdb-5.2/configure
|
||||
make
|
||||
|
||||
When `configure' builds a configuration using a remote source
|
||||
directory, it creates a tree for the binaries with the same structure
|
||||
(and using the same names) as the tree under the source directory. In
|
||||
the example, you'd find the Sun 4 library `libiberty.a' in the
|
||||
directory `gdb-sun4/libiberty', and GDB itself in `gdb-sun4/gdb'.
|
||||
|
||||
One popular reason to build several GDB configurations in separate
|
||||
directories is to configure GDB for cross-compiling (where GDB runs on
|
||||
one machine--the host--while debugging programs that run on another
|
||||
machine--the target). You specify a cross-debugging target by giving
|
||||
the `--target=TARGET' option to `configure'.
|
||||
|
||||
When you run `make' to build a program or library, you must run it
|
||||
in a configured directory--whatever directory you were in when you
|
||||
called `configure' (or one of its subdirectories).
|
||||
|
||||
The `Makefile' that `configure' generates in each source directory
|
||||
also runs recursively. If you type `make' in a source directory such
|
||||
as `gdb-5.2' (or in a separate configured directory configured with
|
||||
`--srcdir=PATH/gdb-5.2'), you will build all the required libraries,
|
||||
and then build GDB.
|
||||
|
||||
When you have multiple hosts or targets configured in separate
|
||||
directories, you can run `make' on them in parallel (for example, if
|
||||
they are NFS-mounted on each of the hosts); they will not interfere
|
||||
with each other.
|
||||
|
||||
|
||||
Specifying names for hosts and targets
|
||||
======================================
|
||||
|
||||
The specifications used for hosts and targets in the `configure'
|
||||
script are based on a three-part naming scheme, but some short
|
||||
predefined aliases are also supported. The full naming scheme encodes
|
||||
three pieces of information in the following pattern:
|
||||
|
||||
ARCHITECTURE-VENDOR-OS
|
||||
|
||||
For example, you can use the alias `sun4' as a HOST argument or in a
|
||||
`--target=TARGET' option. The equivalent full name is
|
||||
`sparc-sun-sunos4'.
|
||||
|
||||
The `configure' script accompanying GDB does not provide any query
|
||||
facility to list all supported host and target names or aliases.
|
||||
`configure' calls the Bourne shell script `config.sub' to map
|
||||
abbreviations to full names; you can read the script, if you wish, or
|
||||
you can use it to test your guesses on abbreviations--for example:
|
||||
|
||||
% sh config.sub sun4
|
||||
sparc-sun-sunos4.1.1
|
||||
% sh config.sub sun3
|
||||
m68k-sun-sunos4.1.1
|
||||
% sh config.sub decstation
|
||||
mips-dec-ultrix4.2
|
||||
% sh config.sub hp300bsd
|
||||
m68k-hp-bsd
|
||||
% sh config.sub i386v
|
||||
i386-pc-sysv
|
||||
% sh config.sub i786v
|
||||
Invalid configuration `i786v': machine `i786v' not recognized
|
||||
|
||||
`config.sub' is also distributed in the GDB source directory
|
||||
(`gdb-5.2', for version 5.2).
|
||||
|
||||
|
||||
`configure' options
|
||||
===================
|
||||
|
||||
Here is a summary of the `configure' options and arguments that are
|
||||
most often useful for building GDB. `configure' also has several other
|
||||
options not listed here. *note : (configure.info)What Configure Does,
|
||||
for a full explanation of `configure'.
|
||||
|
||||
configure [--help]
|
||||
[--prefix=DIR]
|
||||
[--srcdir=PATH]
|
||||
[--norecursion] [--rm]
|
||||
[--enable-build-warnings]
|
||||
[--target=TARGET]
|
||||
[--host=HOST]
|
||||
[HOST]
|
||||
|
||||
You may introduce options with a single `-' rather than `--' if you
|
||||
prefer; but you may abbreviate option names if you use `--'.
|
||||
|
||||
`--help'
|
||||
Display a quick summary of how to invoke `configure'.
|
||||
|
||||
`-prefix=DIR'
|
||||
Configure the source to install programs and files under directory
|
||||
`DIR'.
|
||||
|
||||
`--srcdir=PATH'
|
||||
*Warning: using this option requires GNU `make', or another `make'
|
||||
that compatibly implements the `VPATH' feature.*
|
||||
Use this option to make configurations in directories separate
|
||||
from the GDB source directories. Among other things, you can use
|
||||
this to build (or maintain) several configurations simultaneously,
|
||||
in separate directories. `configure' writes configuration
|
||||
specific files in the current directory, but arranges for them to
|
||||
use the source in the directory PATH. `configure' will create
|
||||
directories under the working directory in parallel to the source
|
||||
directories below PATH.
|
||||
|
||||
`--norecursion'
|
||||
Configure only the directory level where `configure' is executed;
|
||||
do not propagate configuration to subdirectories.
|
||||
|
||||
`--rm'
|
||||
Remove the configuration that the other arguments specify.
|
||||
|
||||
`--enable-build-warnings'
|
||||
When building the GDB sources, ask the compiler to warn about any
|
||||
code which looks even vaguely suspicious. You should only using
|
||||
this feature if you're compiling with GNU CC. It passes the
|
||||
following flags:
|
||||
-Wimplicit
|
||||
-Wreturn-type
|
||||
-Wcomment
|
||||
-Wtrigraphs
|
||||
-Wformat
|
||||
-Wparentheses
|
||||
-Wpointer-arith
|
||||
|
||||
`--target=TARGET'
|
||||
Configure GDB for cross-debugging programs running on the specified
|
||||
TARGET. Without this option, GDB is configured to debug programs
|
||||
that run on the same machine (HOST) as GDB itself.
|
||||
|
||||
There is no convenient way to generate a list of all available
|
||||
targets.
|
||||
|
||||
`--host=HOST'
|
||||
Configure GDB to run on the specified HOST.
|
||||
|
||||
There is no convenient way to generate a list of all available
|
||||
hosts.
|
||||
|
||||
`HOST ...'
|
||||
Same as `--host=HOST'. If you omit this, GDB will guess; it's
|
||||
quite accurate.
|
||||
|
||||
`configure' accepts other options, for compatibility with configuring
|
||||
other GNU tools recursively; but these are the only options that affect
|
||||
GDB or its supporting libraries.
|
||||
|
||||
|
||||
Remote debugging
|
||||
=================
|
||||
|
||||
The files m68k-stub.c, i386-stub.c, and sparc-stub.c are examples
|
||||
of remote stubs to be used with remote.c. They are designed to run
|
||||
standalone on an m68k, i386, or SPARC cpu and communicate properly
|
||||
with the remote.c stub over a serial line.
|
||||
|
||||
The directory gdb/gdbserver/ contains `gdbserver', a program that
|
||||
allows remote debugging for Unix applications. gdbserver is only
|
||||
supported for some native configurations, including Sun 3, Sun 4, and
|
||||
Linux.
|
||||
|
||||
There are a number of remote interfaces for talking to existing ROM
|
||||
monitors and other hardware:
|
||||
|
||||
remote-adapt.c AMD 29000 "Adapt"
|
||||
remote-array.c Array Tech RAID controller
|
||||
remote-bug.c Motorola BUG monitor
|
||||
remote-e7000.c Hitachi E7000 ICE
|
||||
remote-eb.c AMD 29000 "EBMON"
|
||||
remote-es.c Ericsson 1800 monitor
|
||||
remote-est.c EST emulator
|
||||
remote-hms.c Hitachi Micro Systems H8/300 monitor
|
||||
remote-mips.c MIPS remote debugging protocol
|
||||
remote-mm.c AMD 29000 "minimon"
|
||||
remote-nindy.c Intel 960 "Nindy"
|
||||
remote-nrom.c NetROM ROM emulator
|
||||
remote-os9k.c PC running OS/9000
|
||||
remote-rdi.c ARM with Angel monitor
|
||||
remote-rdp.c ARM with Demon monitor
|
||||
remote-sds.c PowerPC SDS monitor
|
||||
remote-sim.c Generalized simulator protocol
|
||||
remote-st.c Tandem ST-2000 monitor
|
||||
remote-udi.c AMD 29000 using the AMD "Universal Debug Interface"
|
||||
remote-vx.c VxWorks realtime kernel
|
||||
|
||||
Remote-vx.c and the vx-share subdirectory contain a remote
|
||||
interface for the VxWorks realtime kernel, which communicates over TCP
|
||||
using the Sun RPC library. This would be a useful starting point for
|
||||
other remote- via-ethernet back ends.
|
||||
|
||||
Remote-udi.c and the 29k-share subdirectory contain a remote
|
||||
interface for AMD 29000 programs, which uses the AMD "Universal Debug
|
||||
Interface". This allows GDB to talk to software simulators,
|
||||
emulators, and/or bare hardware boards, via network or serial
|
||||
interfaces. Note that GDB only provides an interface that speaks UDI,
|
||||
not a complete solution. You will need something on the other end
|
||||
that also speaks UDI.
|
||||
|
||||
|
||||
Reporting Bugs in GDB
|
||||
=====================
|
||||
|
||||
There are several ways of reporting bugs in GDB. The prefered
|
||||
method is to use the World Wide Web:
|
||||
|
||||
http://www.gnu.org/software/gdb/bugs/
|
||||
|
||||
As an alternative, the bug report can be submitted, via e-mail, to the
|
||||
address "bug-gdb@gnu.org".
|
||||
|
||||
When submitting a bug, please include the GDB version number (e.g.,
|
||||
gdb-5.2), and how you configured it (e.g., "sun4" or "mach386 host,
|
||||
i586-intel-synopsys target"). Since GDB now supports so many
|
||||
different configurations, it is important that you be precise about
|
||||
this. If at all possible, you should include the actual banner that
|
||||
GDB prints when it starts up, or failing that, the actual configure
|
||||
command that you used when configuring GDB.
|
||||
|
||||
For more information on how/whether to report bugs, see the
|
||||
Reporting Bugs chapter of the GDB manual (gdb/doc/gdb.texinfo).
|
||||
|
||||
|
||||
Graphical interface to GDB -- X Windows, MS Windows
|
||||
==========================
|
||||
|
||||
Several graphical interfaces to GDB are available. You should
|
||||
check:
|
||||
|
||||
http://www.gnu.org/software/gdb/gui/
|
||||
|
||||
for an up-to-date list.
|
||||
|
||||
Emacs users will very likely enjoy the Grand Unified Debugger mode;
|
||||
try typing `M-x gdb RET'.
|
||||
|
||||
|
||||
Writing Code for GDB
|
||||
=====================
|
||||
|
||||
There is a lot of information about writing code for GDB in the
|
||||
internals manual, distributed with GDB in gdb/doc/gdbint.texinfo. You
|
||||
can read it by hand, print it by using TeX and texinfo, or process it
|
||||
into an `info' file for use with Emacs' info mode or the standalone
|
||||
`info' program.
|
||||
|
||||
If you are pondering writing anything but a short patch, especially
|
||||
take note of the information about copyrights in the node Submitting
|
||||
Patches. It can take quite a while to get all the paperwork done, so
|
||||
we encourage you to start that process as soon as you decide you are
|
||||
planning to work on something, or at least well ahead of when you
|
||||
think you will be ready to submit the patches.
|
||||
|
||||
|
||||
GDB Testsuite
|
||||
=============
|
||||
|
||||
Included with the GDB distribution is a DejaGNU based testsuite
|
||||
that can either be used to test your newly built GDB, or for
|
||||
regression testing a GDB with local modifications.
|
||||
|
||||
Running the testsuite requires the prior installation of DejaGNU,
|
||||
which is generally available via ftp. The directory
|
||||
ftp://sources.redhat.com/pub/dejagnu/ will contain a recent snapshot.
|
||||
Once DejaGNU is installed, you can run the tests in one of the
|
||||
following ways:
|
||||
|
||||
(1) cd gdb-5.2
|
||||
make check-gdb
|
||||
|
||||
or
|
||||
|
||||
(2) cd gdb-5.2/gdb
|
||||
make check
|
||||
|
||||
or
|
||||
|
||||
(3) cd gdb-5.2/gdb/testsuite
|
||||
make site.exp (builds the site specific file)
|
||||
runtest -tool gdb GDB=../gdb (or GDB=<somepath> as appropriate)
|
||||
|
||||
The last method gives you slightly more control in case of problems
|
||||
with building one or more test executables or if you are using the
|
||||
testsuite `standalone', without it being part of the GDB source tree.
|
||||
|
||||
See the DejaGNU documentation for further details.
|
||||
|
||||
|
||||
(this is for editing this file with GNU emacs)
|
||||
Local Variables:
|
||||
mode: text
|
||||
End:
|
||||
347
gdb/TODO
347
gdb/TODO
@@ -1,347 +0,0 @@
|
||||
If you find inaccuracies in this list, please send mail to
|
||||
gdb-patches@sources.redhat.com. If you would like to work on any
|
||||
of these, you should consider sending mail to the same address, to
|
||||
find out whether anyone else is working on it.
|
||||
|
||||
|
||||
GDB 5.1 - Fixes
|
||||
===============
|
||||
|
||||
Below is a list of problems identified during the GDB 5.0 release
|
||||
cycle. People hope to have these problems fixed in 5.1.
|
||||
|
||||
--
|
||||
|
||||
Wow, three bug reports for the same problem in one day! We should
|
||||
probably make fixing this a real priority :-).
|
||||
|
||||
Anyway, thanks for reporting.
|
||||
|
||||
The following patch will fix the problems with setting breakpoints in
|
||||
dynamically loaded objects:
|
||||
|
||||
http://sources.redhat.com/ml/gdb-patches/2000-05/msg00230.html
|
||||
|
||||
This patch isn't checked in yet (ping Michael/JimB), but I hope this
|
||||
will be in the next GDB release.
|
||||
|
||||
There should really be a test in the testsuite for this problem, since
|
||||
it keeps coming up :-(. Any volunteers?
|
||||
|
||||
Mark
|
||||
|
||||
--
|
||||
|
||||
GDB 5.1 - New features
|
||||
======================
|
||||
|
||||
The following new features should be included in 5.1.
|
||||
|
||||
--
|
||||
|
||||
GDB 5.1 - Cleanups
|
||||
==================
|
||||
|
||||
The following code cleanups will hopefully be applied to GDB 5.1.
|
||||
|
||||
--
|
||||
|
||||
GDB 5.1 - Known Problems
|
||||
========================
|
||||
|
||||
--
|
||||
|
||||
z8k
|
||||
|
||||
The z8k has suffered bit rot and is known to not build. The problem
|
||||
was occuring in the opcodes directory.
|
||||
|
||||
--
|
||||
|
||||
The BFD directory requires bug-fixed AUTOMAKE et.al.
|
||||
|
||||
AUTOMAKE 1.4 incorrectly set the TEXINPUTS environment variable. It
|
||||
contained the full path to texinfo.tex when it should have only
|
||||
contained the directory. The bug has been fixed in the current
|
||||
AUTOMAKE sources. Automake snapshots can be found in:
|
||||
ftp://sources.redhat.com/pub/gdb/infrastructure
|
||||
and ftp://sources.redhat.com/pub/binutils
|
||||
|
||||
--
|
||||
|
||||
Solaris 8 x86 CURSES_H problem
|
||||
http://sources.redhat.com/ml/gdb/2000-07/msg00038.html
|
||||
|
||||
The original problem was worked around with:
|
||||
|
||||
2000-06-06 Michael Snyder <msnyder@cygnus.com>
|
||||
|
||||
* configure.in: Enable autoconf to find curses.h on Solaris 2.8.
|
||||
* configure: Regenerate.
|
||||
|
||||
When building both GDB and SID using the same source tree the problem
|
||||
will still occure. sid/component/configure.in mis-configures
|
||||
<curses.h> and leaves wrong information in the config cache.
|
||||
|
||||
--
|
||||
|
||||
GDB 5.2 - Fixes
|
||||
===============
|
||||
|
||||
--
|
||||
|
||||
GDB 5.2 - New features
|
||||
======================
|
||||
|
||||
--
|
||||
|
||||
GCC 3.0 ABI support (but hopefully sooner...).
|
||||
|
||||
--
|
||||
|
||||
Objective C/C++ support (but hopefully sooner...).
|
||||
|
||||
--
|
||||
|
||||
Import of readline 4.2
|
||||
|
||||
--
|
||||
|
||||
GDB 5.2 - Cleanups
|
||||
==================
|
||||
|
||||
The following cleanups have been identified as part of GDB 5.2.
|
||||
|
||||
--
|
||||
|
||||
Remove old code that does not use ui_out functions and all the related
|
||||
"ifdef"s. This also allows the elimination of -DUI_OUT from
|
||||
Makefile.in and configure.in.
|
||||
|
||||
--
|
||||
|
||||
Compiler warnings.
|
||||
|
||||
Eliminate warnings for all targets on at least one host for one of the
|
||||
-W flags. Flags up for debate include: -Wswitch -Wcomment -trigraphs
|
||||
-Wtrigraphs -Wunused-function -Wunused-label -Wunused-variable
|
||||
-Wunused-value -Wchar-subscripts -Wtraditional -Wshadow -Wcast-qual
|
||||
-Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes
|
||||
-Wmissing-prototypes -Wmissing-declarations -Wredundant-decls
|
||||
-Woverloaded-virtual -Winline
|
||||
|
||||
--
|
||||
|
||||
Deprecate, if not delete, the following:
|
||||
|
||||
register[]
|
||||
register_valid[]
|
||||
REGISTER_BYTE()
|
||||
Replaced by, on the target side
|
||||
supply_register()
|
||||
and on core-gdb side:
|
||||
{read,write}_register_gen()
|
||||
Remote.c will need to use something
|
||||
other than REGISTER_BYTE() and
|
||||
REGISTER_RAW_SIZE() when unpacking
|
||||
[gG] packets.
|
||||
|
||||
STORE_PSEUDO_REGISTER
|
||||
FETCH_PSEUDO_REGISTER
|
||||
Now handed by the methods
|
||||
gdbarch_{read,write}_register()
|
||||
which sits between core GDB and
|
||||
the register cache.
|
||||
|
||||
REGISTER_CONVERTIBLE
|
||||
REGISTER_CONVERT_TO_RAW
|
||||
REGISTER_CONVERT_TO_VIRTUAL
|
||||
I think these three are redundant.
|
||||
gdbarch_register_{read,write} can
|
||||
do any conversion it likes.
|
||||
|
||||
REGISTER_VIRTUAL_SIZE
|
||||
MAX_REGISTER_VIRTUAL_SIZE
|
||||
REGISTER_VIRTUAL_TYPE
|
||||
I think these can be replaced by
|
||||
the pair:
|
||||
FRAME_REGISTER_TYPE(frame, regnum)
|
||||
REGISTER_TYPE(regnum)
|
||||
|
||||
DO_REGISTERS_INFO
|
||||
Replace with
|
||||
FRAME_REGISTER_INFO (frame, ...)
|
||||
|
||||
REGISTER_SIM_REGNO()
|
||||
If nothing else rename this so that
|
||||
how it relates to rawreg and the
|
||||
regnum is clear.
|
||||
|
||||
REGISTER_BYTES
|
||||
The size of the cache can be computed
|
||||
on the fly.
|
||||
|
||||
IS_TRAPPED_INTERNALVAR
|
||||
The pseudo registers should eventually make
|
||||
this redundant.
|
||||
|
||||
--
|
||||
|
||||
Obsolete the targets:
|
||||
|
||||
arm*-wince-pe
|
||||
mips*-*-pe
|
||||
sh*-*-pe
|
||||
|
||||
--
|
||||
|
||||
Obsolete the protocols:
|
||||
|
||||
RDB?
|
||||
|
||||
``As of version 5.3, WindRiver has removed the RDB server (RDB
|
||||
protocol support is built into gdb).'' -- Till.
|
||||
|
||||
--
|
||||
|
||||
Restructure gdb directory tree so that it avoids any 8.3 and 14
|
||||
filename problems.
|
||||
|
||||
--
|
||||
|
||||
Convert GDB build process to AUTOMAKE.
|
||||
|
||||
See also sub-directory configure below.
|
||||
|
||||
The current convention is (kind of) to use $(<header>_h) in all
|
||||
dependency lists. It isn't done in a consistent way.
|
||||
|
||||
--
|
||||
|
||||
GDB 5.2 - Known Problems
|
||||
========================
|
||||
|
||||
--
|
||||
|
||||
Code Cleanups: General
|
||||
======================
|
||||
|
||||
The following are more general cleanups and fixes. They are not tied
|
||||
to any specific release.
|
||||
|
||||
|
||||
New Features and Fixes
|
||||
======================
|
||||
|
||||
These are harder than cleanups but easier than work involving
|
||||
fundamental architectural change.
|
||||
|
||||
--
|
||||
|
||||
Language Support
|
||||
================
|
||||
|
||||
New languages come onto the scene all the time.
|
||||
|
||||
--
|
||||
|
||||
Re: Various C++ things
|
||||
|
||||
RTTI for g++ should be using the typeinfo functions rather than the
|
||||
vtables. The typeinfo functions are always at offset 4 from the
|
||||
beginning of the vtable, and are always right. The vtables will have
|
||||
weird names like E::VB sometimes. The typeinfo function will always
|
||||
be "E type_info function", or somesuch.
|
||||
|
||||
value_virtual_fn_field needs to be fixed so there are no failures for
|
||||
virtual functions for C++ using g++.
|
||||
|
||||
Testsuite cases are the major priority right now for C++ support,
|
||||
since i have to make a lot of changes that could potentially break
|
||||
each other.
|
||||
|
||||
--
|
||||
|
||||
|
||||
Symbol Support
|
||||
==============
|
||||
|
||||
--
|
||||
|
||||
Investiagate ways of reducing memory.
|
||||
|
||||
--
|
||||
|
||||
Investigate ways of improving load time.
|
||||
|
||||
--
|
||||
|
||||
Testsuite Support
|
||||
=================
|
||||
|
||||
There are never to many testcases.
|
||||
|
||||
--
|
||||
|
||||
Better thread testsuite.
|
||||
|
||||
--
|
||||
|
||||
Better C++ testsuite.
|
||||
|
||||
--
|
||||
|
||||
Architectural Changes: General
|
||||
==============================
|
||||
|
||||
These are harder than simple cleanups / fixes and, consequently
|
||||
involve more work. Typically an Architectural Change will be broken
|
||||
down into a more digestible set of cleanups and fixes.
|
||||
|
||||
--
|
||||
|
||||
Architectural Change: Multi-arch et al.
|
||||
=======================================
|
||||
|
||||
The long term objective is to remove all assumptions that there is a
|
||||
single target with a single address space with a single instruction
|
||||
set architecture and single application binary interface.
|
||||
|
||||
This is an ongoing effort. The first milestone is to enable
|
||||
``multi-arch'' where by all architectural decisions are made at
|
||||
runtime.
|
||||
|
||||
It should be noted that ``gdbarch'' is really ``gdbabi'' and
|
||||
``gdbisa''. Once things are multi-arched breaking that down correctly
|
||||
will become much easier.
|
||||
|
||||
--
|
||||
|
||||
Architectural Change: MI, LIBGDB and scripting languages
|
||||
========================================================
|
||||
|
||||
See also architectural changes related to the event loop. LIBGDB
|
||||
can't be finished until there is a generic event loop being used by
|
||||
all targets.
|
||||
|
||||
The long term objective is it to be possible to integrate GDB into
|
||||
scripting languages.
|
||||
|
||||
--
|
||||
|
||||
Architectural Change: Async
|
||||
===========================
|
||||
|
||||
While GDB uses an event loop when prompting the user for input. That
|
||||
event loop is not exploited by targets when they allow the target
|
||||
program to continue. Typically targets still block in (target_wait())
|
||||
until the program again halts.
|
||||
|
||||
The closest a target comes to supporting full asynchronous mode are
|
||||
the remote targets ``async'' and ``extended-async''.
|
||||
|
||||
--
|
||||
|
||||
# Local Variables:
|
||||
# mode: text
|
||||
# End:
|
||||
122
gdb/a68v-nat.c
122
gdb/a68v-nat.c
@@ -1,122 +0,0 @@
|
||||
/* Host-dependent code for Apollo-68ks for GDB, the GNU debugger.
|
||||
Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#ifndef _ISP__M68K
|
||||
#define _ISP__M68K 1
|
||||
#endif
|
||||
|
||||
#include <ptrace.h>
|
||||
|
||||
extern int errno;
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int ignored)
|
||||
{
|
||||
struct ptrace_$data_regs_m68k inferior_registers;
|
||||
struct ptrace_$floating_regs_m68k inferior_fp_registers;
|
||||
struct ptrace_$control_regs_m68k inferior_control_registers;
|
||||
|
||||
ptrace_$init_control (&inferior_control_registers);
|
||||
inferior_fp_registers.size = sizeof (inferior_fp_registers);
|
||||
|
||||
registers_fetched ();
|
||||
|
||||
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers,
|
||||
ptrace_$data_set,
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers,
|
||||
ptrace_$data_set);
|
||||
|
||||
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k);
|
||||
|
||||
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k);
|
||||
|
||||
bcopy (&inferior_registers, registers, 16 * 4);
|
||||
bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof inferior_fp_registers.regs);
|
||||
*(int *) ®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_control_registers.sr;
|
||||
*(int *) ®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_control_registers.pc;
|
||||
}
|
||||
|
||||
/* 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). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
struct ptrace_$data_regs_m68k inferior_registers;
|
||||
struct ptrace_$floating_regs_m68k inferior_fp_registers;
|
||||
struct ptrace_$control_regs_m68k inferior_control_registers;
|
||||
|
||||
ptrace_$init_control (&inferior_control_registers);
|
||||
inferior_fp_registers.size = sizeof (inferior_fp_registers);
|
||||
|
||||
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k);
|
||||
|
||||
ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k);
|
||||
|
||||
bcopy (registers, &inferior_registers, sizeof (inferior_registers));
|
||||
|
||||
bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], inferior_fp_registers.regs,
|
||||
sizeof inferior_fp_registers.regs);
|
||||
|
||||
inferior_control_registers.sr = *(int *) ®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
inferior_control_registers.pc = *(int *) ®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
|
||||
ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers,
|
||||
ptrace_$data_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers,
|
||||
ptrace_$data_set_m68k);
|
||||
|
||||
ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers,
|
||||
ptrace_$floating_set_m68k);
|
||||
|
||||
ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k,
|
||||
(PTRACE_ARG3_TYPE) & inferior_control_registers,
|
||||
ptrace_$control_set_m68k);
|
||||
}
|
||||
178
gdb/abug-rom.c
178
gdb/abug-rom.c
@@ -1,178 +0,0 @@
|
||||
/* Remote debugging interface for ABug Rom monitor for GDB, the GNU debugger.
|
||||
Copyright 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Rob Savoye of Cygnus Support
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
||||
static void abug_open (char *args, int from_tty);
|
||||
|
||||
static void
|
||||
abug_supply_register (char *regname, int regnamelen, char *val, int vallen)
|
||||
{
|
||||
int regno;
|
||||
|
||||
if (regnamelen != 2)
|
||||
return;
|
||||
|
||||
switch (regname[0])
|
||||
{
|
||||
case 'S':
|
||||
if (regname[1] != 'R')
|
||||
return;
|
||||
regno = PS_REGNUM;
|
||||
break;
|
||||
case 'P':
|
||||
if (regname[1] != 'C')
|
||||
return;
|
||||
regno = PC_REGNUM;
|
||||
break;
|
||||
case 'D':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + D0_REGNUM;
|
||||
break;
|
||||
case 'A':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + A0_REGNUM;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_supply_register (regno, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This array of registers needs to match the indexes used by GDB. The
|
||||
* whole reason this exists is because the various ROM monitors use
|
||||
* different names than GDB does, and don't support all the
|
||||
* registers either. So, typing "info reg sp" becomes an "A7".
|
||||
*/
|
||||
|
||||
static const char *
|
||||
abug_regname (int index)
|
||||
{
|
||||
static char *regnames[] =
|
||||
{
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
|
||||
"PC",
|
||||
};
|
||||
|
||||
if ((index >= (sizeof (regnames) / sizeof (regnames[0])))
|
||||
|| (index < 0) || (index >= NUM_REGS))
|
||||
return NULL;
|
||||
else
|
||||
return regnames[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Define the monitor command strings. Since these are passed directly
|
||||
* through to a printf style function, we need can include formatting
|
||||
* strings. We also need a CR or LF on the end.
|
||||
*/
|
||||
|
||||
static struct target_ops abug_ops;
|
||||
|
||||
static char *abug_inits[] =
|
||||
{"\r", NULL};
|
||||
|
||||
static struct monitor_ops abug_cmds;
|
||||
|
||||
static void
|
||||
init_abug_cmds (void)
|
||||
{
|
||||
abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
|
||||
abug_cmds.init = abug_inits; /* Init strings */
|
||||
abug_cmds.cont = "g\r"; /* continue command */
|
||||
abug_cmds.step = "t\r"; /* single step */
|
||||
abug_cmds.stop = NULL; /* interrupt command */
|
||||
abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
|
||||
abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
|
||||
abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
|
||||
abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
|
||||
abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
|
||||
abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
|
||||
abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
|
||||
abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
|
||||
abug_cmds.setmem.term = NULL; /* setreg.term */
|
||||
abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
|
||||
abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
|
||||
abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
|
||||
abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
|
||||
abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
|
||||
abug_cmds.getmem.term = NULL; /* getmem.term */
|
||||
abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
|
||||
abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
|
||||
abug_cmds.setreg.term = "? "; /* setreg.term */
|
||||
abug_cmds.setreg.term_cmd = ".\r"; /* setreg.term_cmd */
|
||||
abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
|
||||
abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
|
||||
abug_cmds.getreg.term = "? "; /* getreg.term */
|
||||
abug_cmds.getreg.term_cmd = ".\r"; /* getreg.term_cmd */
|
||||
abug_cmds.dump_registers = "rd\r"; /* dump_registers */
|
||||
abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
|
||||
abug_cmds.supply_register = abug_supply_register; /* supply_register */
|
||||
abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
abug_cmds.load = "lo 0\r"; /* download command */
|
||||
abug_cmds.loadresp = "\n"; /* load response */
|
||||
abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
|
||||
abug_cmds.line_term = "\r"; /* end-of-line terminator */
|
||||
abug_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
abug_cmds.target = &abug_ops; /* target operations */
|
||||
abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
abug_cmds.regnames = NULL; /* registers names */
|
||||
abug_cmds.regname = abug_regname;
|
||||
abug_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
};
|
||||
|
||||
static void
|
||||
abug_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &abug_cmds, from_tty);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_abug_rom (void)
|
||||
{
|
||||
init_abug_cmds ();
|
||||
init_monitor_ops (&abug_ops);
|
||||
|
||||
abug_ops.to_shortname = "abug";
|
||||
abug_ops.to_longname = "ABug monitor";
|
||||
abug_ops.to_doc = "Debug via the ABug monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
abug_ops.to_open = abug_open;
|
||||
|
||||
add_target (&abug_ops);
|
||||
}
|
||||
178
gdb/acconfig.h
178
gdb/acconfig.h
@@ -1,178 +0,0 @@
|
||||
/* Define if compiling on Solaris 7. */
|
||||
#undef _MSE_INT_H
|
||||
|
||||
/* Define if your struct reg has r_fs. */
|
||||
#undef HAVE_STRUCT_REG_R_FS
|
||||
|
||||
/* Define if your struct reg has r_gs. */
|
||||
#undef HAVE_STRUCT_REG_R_GS
|
||||
|
||||
/* Define if pstatus_t type is available */
|
||||
#undef HAVE_PSTATUS_T
|
||||
|
||||
/* Define if prrun_t type is available */
|
||||
#undef HAVE_PRRUN_T
|
||||
|
||||
/* Define if fpregset_t type is available. */
|
||||
#undef HAVE_FPREGSET_T
|
||||
|
||||
/* Define if gregset_t type is available. */
|
||||
#undef HAVE_GREGSET_T
|
||||
|
||||
/* Define if <sys/procfs.h> has prgregset_t. */
|
||||
#undef HAVE_PRGREGSET_T
|
||||
|
||||
/* Define if <sys/procfs.h> has prfpregset_t. */
|
||||
#undef HAVE_PRFPREGSET_T
|
||||
|
||||
/* Define if <sys/procfs.h> has lwpid_t. */
|
||||
#undef HAVE_LWPID_T
|
||||
|
||||
/* Define if <sys/procfs.h> has psaddr_t. */
|
||||
#undef HAVE_PSADDR_T
|
||||
|
||||
/* Define if <sys/procfs.h> has prgregset32_t. */
|
||||
#undef HAVE_PRGREGSET32_T
|
||||
|
||||
/* Define if <sys/procfs.h> has prfpregset32_t. */
|
||||
#undef HAVE_PRFPREGSET32_T
|
||||
|
||||
/* Define if <sys/procfs.h> has prsysent_t */
|
||||
#undef HAVE_PRSYSENT_T
|
||||
|
||||
/* Define if <sys/procfs.h> has pr_sigset_t */
|
||||
#undef HAVE_PR_SIGSET_T
|
||||
|
||||
/* Define if <sys/procfs.h> has pr_sigaction64_t */
|
||||
#undef HAVE_PR_SIGACTION64_T
|
||||
|
||||
/* Define if <sys/procfs.h> has pr_siginfo64_t */
|
||||
#undef HAVE_PR_SIGINFO64_T
|
||||
|
||||
/* Define if <link.h> exists and defines struct link_map which has
|
||||
members with an ``l_'' prefix. (For Solaris, SVR4, and
|
||||
SVR4-like systems.) */
|
||||
#undef HAVE_STRUCT_LINK_MAP_WITH_L_MEMBERS
|
||||
|
||||
/* Define if <link.h> exists and defines struct link_map which has
|
||||
members with an ``lm_'' prefix. (For SunOS.) */
|
||||
#undef HAVE_STRUCT_LINK_MAP_WITH_LM_MEMBERS
|
||||
|
||||
/* Define if <link.h> exists and defines a struct so_map which has
|
||||
members with an ``som_'' prefix. (Found on older *BSD systems.) */
|
||||
#undef HAVE_STRUCT_SO_MAP_WITH_SOM_MEMBERS
|
||||
|
||||
/* Define if <sys/link.h> has struct link_map32 */
|
||||
#undef HAVE_STRUCT_LINK_MAP32
|
||||
|
||||
/* Define if <sys/link.h> has link_map32 (solaris sparc-64 target) */
|
||||
#undef _SYSCALL32
|
||||
|
||||
/* Define if the prfpregset_t type is broken. */
|
||||
#undef PRFPREGSET_T_BROKEN
|
||||
|
||||
/* Define if you want to use new multi-fd /proc interface
|
||||
(replaces HAVE_MULTIPLE_PROC_FDS as well as other macros). */
|
||||
#undef NEW_PROC_API
|
||||
|
||||
/* Define if ioctl argument PIOCSET is available. */
|
||||
#undef HAVE_PROCFS_PIOCSET
|
||||
|
||||
/* Define if the `long long' type works. */
|
||||
#undef CC_HAS_LONG_LONG
|
||||
|
||||
/* Define if the "ll" format works to print long long ints. */
|
||||
#undef PRINTF_HAS_LONG_LONG
|
||||
|
||||
/* Define if the "%Lg" format works to print long doubles. */
|
||||
#undef PRINTF_HAS_LONG_DOUBLE
|
||||
|
||||
/* Define if the "%Lg" format works to scan long doubles. */
|
||||
#undef SCANF_HAS_LONG_DOUBLE
|
||||
|
||||
/* Define if using Solaris thread debugging. */
|
||||
#undef HAVE_THREAD_DB_LIB
|
||||
|
||||
/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
|
||||
#undef START_INFERIOR_TRAPS_EXPECTED
|
||||
#undef sys_quotactl
|
||||
|
||||
/* Define if you have HPUX threads */
|
||||
#undef HAVE_HPUX_THREAD_SUPPORT
|
||||
|
||||
/* Define if you want to use the memory mapped malloc package (mmalloc). */
|
||||
#undef USE_MMALLOC
|
||||
|
||||
/* Define if the runtime uses a routine from mmalloc before gdb has a chance
|
||||
to initialize mmalloc, and we want to force checking to be used anyway.
|
||||
This may cause spurious memory corruption messages if the runtime tries
|
||||
to explicitly deallocate that memory when gdb calls exit. */
|
||||
#undef MMCHECK_FORCE
|
||||
|
||||
/* Define to 1 if NLS is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
|
||||
#undef HAVE_CATGETS
|
||||
|
||||
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define as 1 if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||
#undef HAVE_LC_MESSAGES
|
||||
|
||||
/* Define if you want to use the full-screen terminal user interface. */
|
||||
#undef TUI
|
||||
|
||||
/* Define if <proc_service.h> on solaris uses int instead of
|
||||
size_t, and assorted other type changes. */
|
||||
#undef PROC_SERVICE_IS_OLD
|
||||
|
||||
/* If you want to specify a default CPU variant, define this to be its
|
||||
name, as a C string. */
|
||||
#undef TARGET_CPU_DEFAULT
|
||||
|
||||
/* Define if the simulator is being linked in. */
|
||||
#undef WITH_SIM
|
||||
|
||||
/* Set to true if the save_state_t structure is present */
|
||||
#undef HAVE_STRUCT_SAVE_STATE_T
|
||||
|
||||
/* Set to true if the save_state_t structure has the ss_wide member */
|
||||
#undef HAVE_STRUCT_MEMBER_SS_WIDE
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PTRACE_GETREGS request. */
|
||||
#undef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PTRACE_GETFPXREGS request. */
|
||||
#undef HAVE_PTRACE_GETFPXREGS
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PT_GETDBREGS request. */
|
||||
#undef HAVE_PT_GETDBREGS
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PT_GETXMMREGS request. */
|
||||
#undef HAVE_PT_GETXMMREGS
|
||||
|
||||
/* Define if gnu-regex.c included with GDB should be used. */
|
||||
#undef USE_INCLUDED_REGEX
|
||||
|
||||
/* BFD's default architecture. */
|
||||
#undef DEFAULT_BFD_ARCH
|
||||
|
||||
/* BFD's default target vector. */
|
||||
#undef DEFAULT_BFD_VEC
|
||||
|
||||
/* Multi-arch enabled. */
|
||||
#undef GDB_MULTI_ARCH
|
||||
|
||||
/* hostfile */
|
||||
#undef GDB_XM_FILE
|
||||
|
||||
/* targetfile */
|
||||
#undef GDB_TM_FILE
|
||||
|
||||
/* nativefile */
|
||||
#undef GDB_NM_FILE
|
||||
978
gdb/acinclude.m4
978
gdb/acinclude.m4
@@ -1,978 +0,0 @@
|
||||
dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
|
||||
dnl major rewriting for Tcl 7.5 by Don Libes <libes@nist.gov>
|
||||
|
||||
dnl gdb/configure.in uses BFD_NEED_DECLARATION, so get its definition.
|
||||
sinclude(../bfd/acinclude.m4)
|
||||
|
||||
dnl This gets the standard macros, like the TCL, TK, etc ones.
|
||||
sinclude(../config/acinclude.m4)
|
||||
|
||||
dnl CYGNUS LOCAL: This gets the right posix flag for gcc
|
||||
AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
|
||||
[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
|
||||
AC_MSG_CHECKING([if running LynxOS])
|
||||
AC_CACHE_VAL(ac_cv_os_lynx,
|
||||
[AC_EGREP_CPP(yes,
|
||||
[/*
|
||||
* The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
|
||||
*/
|
||||
#if defined(__Lynx__) || defined(Lynx)
|
||||
yes
|
||||
#endif
|
||||
], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
|
||||
#
|
||||
if test "$ac_cv_os_lynx" = "yes" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(LYNX)
|
||||
AC_MSG_CHECKING([whether -mposix or -X is available])
|
||||
AC_CACHE_VAL(ac_cv_c_posix_flag,
|
||||
[AC_TRY_COMPILE(,[
|
||||
/*
|
||||
* This flag varies depending on how old the compiler is.
|
||||
* -X is for the old "cc" and "gcc" (based on 1.42).
|
||||
* -mposix is for the new gcc (at least 2.5.8).
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__ >= 2
|
||||
choke me
|
||||
#endif
|
||||
], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
|
||||
CC="$CC $ac_cv_c_posix_flag"
|
||||
AC_MSG_RESULT($ac_cv_c_posix_flag)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
])
|
||||
|
||||
#
|
||||
# Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This
|
||||
# makes configure think it's cross compiling. If --target wasn't used, then
|
||||
# we can't configure, so something is wrong. We don't use the cache
|
||||
# here cause if somebody fixes their compiler install, we want this to work.
|
||||
AC_DEFUN(CY_AC_C_WORKS,
|
||||
[# If we cannot compile and link a trivial program, we can't expect anything to work
|
||||
AC_MSG_CHECKING(whether the compiler ($CC) actually works)
|
||||
AC_TRY_COMPILE(, [/* don't need anything here */],
|
||||
c_compiles=yes, c_compiles=no)
|
||||
|
||||
AC_TRY_LINK(, [/* don't need anything here */],
|
||||
c_links=yes, c_links=no)
|
||||
|
||||
if test x"${c_compiles}" = x"no" ; then
|
||||
AC_MSG_ERROR(the native compiler is broken and won't compile.)
|
||||
fi
|
||||
|
||||
if test x"${c_links}" = x"no" ; then
|
||||
AC_MSG_ERROR(the native compiler is broken and won't link.)
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
])
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TCLH, [
|
||||
#
|
||||
# Ok, lets find the tcl source trees so we can use the headers
|
||||
# Warning: transition of version 9 to 10 will break this algorithm
|
||||
# because 10 sorts before 9. We also look for just tcl. We have to
|
||||
# be careful that we don't match stuff like tclX by accident.
|
||||
# the alternative search directory is involked by --with-tclinclude
|
||||
#
|
||||
|
||||
no_tcl=true
|
||||
AC_MSG_CHECKING(for Tcl private headers. dir=${configdir})
|
||||
AC_ARG_WITH(tclinclude, [ --with-tclinclude=DIR Directory where tcl private headers are], with_tclinclude=${withval})
|
||||
AC_CACHE_VAL(ac_cv_c_tclh,[
|
||||
# first check to see if --with-tclinclude was specified
|
||||
if test x"${with_tclinclude}" != x ; then
|
||||
if test -f ${with_tclinclude}/tclInt.h ; then
|
||||
ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
|
||||
elif test -f ${with_tclinclude}/generic/tclInt.h ; then
|
||||
ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
|
||||
fi
|
||||
fi
|
||||
|
||||
# next check if it came with Tcl configuration file
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
if test -f $ac_cv_c_tclconfig/../generic/tclInt.h ; then
|
||||
ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/..; pwd)`
|
||||
fi
|
||||
fi
|
||||
|
||||
# next check in private source directory
|
||||
#
|
||||
# since ls returns lowest version numbers first, reverse its output
|
||||
if test x"${ac_cv_c_tclh}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tcl \
|
||||
`ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` \
|
||||
${srcdir}/../../tcl \
|
||||
`ls -dr ${srcdir}/../../tcl[[7-9]]* 2>/dev/null` \
|
||||
${srcdir}/../../../tcl \
|
||||
`ls -dr ${srcdir}/../../../tcl[[7-9]]* 2>/dev/null ` ; do
|
||||
if test -f $i/generic/tclInt.h ; then
|
||||
ac_cv_c_tclh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# finally check in a few common install locations
|
||||
#
|
||||
# since ls returns lowest version numbers first, reverse its output
|
||||
if test x"${ac_cv_c_tclh}" = x ; then
|
||||
for i in \
|
||||
`ls -dr /usr/local/src/tcl[[7-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/local/lib/tcl[[7-9]]* 2>/dev/null` \
|
||||
/usr/local/src/tcl \
|
||||
/usr/local/lib/tcl \
|
||||
${prefix}/include ; do
|
||||
if test -f $i/generic/tclInt.h ; then
|
||||
ac_cv_c_tclh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# see if one is installed
|
||||
if test x"${ac_cv_c_tclh}" = x ; then
|
||||
AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tclh}" = x ; then
|
||||
TCLHDIR="# no Tcl private headers found"
|
||||
AC_MSG_ERROR([Can't find Tcl private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_tclh}" != x ; then
|
||||
no_tcl=""
|
||||
if test x"${ac_cv_c_tclh}" = x"installed" ; then
|
||||
AC_MSG_RESULT([is installed])
|
||||
TCLHDIR=""
|
||||
else
|
||||
AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
|
||||
# this hack is cause the TCLHDIR won't print if there is a "-I" in it.
|
||||
TCLHDIR="-I${ac_cv_c_tclh}"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(TCLHDIR)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
|
||||
#
|
||||
# Ok, lets find the tcl configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-tclconfig
|
||||
#
|
||||
|
||||
if test x"${no_tcl}" = x ; then
|
||||
# we reset no_tcl in case something fails here
|
||||
no_tcl=true
|
||||
AC_ARG_WITH(tclconfig, [ --with-tclconfig=DIR Directory containing tcl configuration (tclConfig.sh)],
|
||||
with_tclconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tcl configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tclconfig,[
|
||||
|
||||
# First check to see if --with-tclconfig was specified.
|
||||
if test x"${with_tclconfig}" != x ; then
|
||||
if test -f "${with_tclconfig}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tcl installation
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
../tcl \
|
||||
`ls -dr ../tcl[[7-9]]* 2>/dev/null` \
|
||||
../../tcl \
|
||||
`ls -dr ../../tcl[[7-9]]* 2>/dev/null` \
|
||||
../../../tcl \
|
||||
`ls -dr ../../../tcl[[7-9]]* 2>/dev/null` ; do
|
||||
if test -f "$i/${configdir}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tcl \
|
||||
`ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` ; do
|
||||
if test -f "$i/${configdir}/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tclconfig}" = x ; then
|
||||
TCLCONFIG="# no Tcl configs found"
|
||||
AC_MSG_WARN(Can't find Tcl configuration definitions)
|
||||
else
|
||||
no_tcl=
|
||||
TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
|
||||
AC_MSG_RESULT(found $TCLCONFIG)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_TCLCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_TCLCONFIG, [
|
||||
. $TCLCONFIG
|
||||
|
||||
AC_SUBST(TCL_VERSION)
|
||||
AC_SUBST(TCL_MAJOR_VERSION)
|
||||
AC_SUBST(TCL_MINOR_VERSION)
|
||||
AC_SUBST(TCL_CC)
|
||||
AC_SUBST(TCL_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TCL_LIB_FILE)
|
||||
|
||||
dnl don't export, not used outside of configure
|
||||
dnl AC_SUBST(TCL_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TCL_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TCL_EXEC_PREFIX)
|
||||
|
||||
AC_SUBST(TCL_SHLIB_CFLAGS)
|
||||
AC_SUBST(TCL_SHLIB_LD)
|
||||
dnl don't export, not used outside of configure
|
||||
AC_SUBST(TCL_SHLIB_LD_LIBS)
|
||||
AC_SUBST(TCL_SHLIB_SUFFIX)
|
||||
dnl not used, don't export to save symbols
|
||||
AC_SUBST(TCL_DL_LIBS)
|
||||
AC_SUBST(TCL_LD_FLAGS)
|
||||
dnl don't export, not used outside of configure
|
||||
AC_SUBST(TCL_LD_SEARCH_FLAGS)
|
||||
AC_SUBST(TCL_COMPAT_OBJS)
|
||||
AC_SUBST(TCL_RANLIB)
|
||||
AC_SUBST(TCL_BUILD_LIB_SPEC)
|
||||
AC_SUBST(TCL_LIB_SPEC)
|
||||
AC_SUBST(TCL_LIB_VERSIONS_OK)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TCL_SHARED_LIB_SUFFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
|
||||
])
|
||||
|
||||
# Warning: Tk definitions are very similar to Tcl definitions but
|
||||
# are not precisely the same. There are a couple of differences,
|
||||
# so don't do changes to Tcl thinking you can cut and paste it do
|
||||
# the Tk differences and later simply substitute "Tk" for "Tcl".
|
||||
# Known differences:
|
||||
# - Acceptable Tcl major version #s is 7-9 while Tk is 4-9
|
||||
# - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
|
||||
# - Computing major/minor versions is different because Tk depends on
|
||||
# headers to Tcl, Tk, and X.
|
||||
# - Symbols in tkConfig.sh are different than tclConfig.sh
|
||||
# - Acceptable for Tk to be missing but not Tcl.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TKH, [
|
||||
#
|
||||
# Ok, lets find the tk source trees so we can use the headers
|
||||
# If the directory (presumably symlink) named "tk" exists, use that one
|
||||
# in preference to any others. Same logic is used when choosing library
|
||||
# and again with Tcl. The search order is the best place to look first, then in
|
||||
# decreasing significance. The loop breaks if the trigger file is found.
|
||||
# Note the gross little conversion here of srcdir by cd'ing to the found
|
||||
# directory. This converts the path from a relative to an absolute, so
|
||||
# recursive cache variables for the path will work right. We check all
|
||||
# the possible paths in one loop rather than many seperate loops to speed
|
||||
# things up.
|
||||
# the alternative search directory is involked by --with-tkinclude
|
||||
#
|
||||
no_tk=true
|
||||
AC_MSG_CHECKING(for Tk private headers)
|
||||
AC_ARG_WITH(tkinclude, [ --with-tkinclude=DIR Directory where tk private headers are], with_tkinclude=${withval})
|
||||
AC_CACHE_VAL(ac_cv_c_tkh,[
|
||||
# first check to see if --with-tkinclude was specified
|
||||
if test x"${with_tkinclude}" != x ; then
|
||||
if test -f ${with_tkinclude}/tk.h ; then
|
||||
ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
|
||||
elif test -f ${with_tkinclude}/generic/tk.h ; then
|
||||
ac_cv_c_tkh=`(cd ${with_tkinclude}/generic; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
|
||||
fi
|
||||
fi
|
||||
|
||||
# next check if it came with Tk configuration file
|
||||
if test x"${ac_cv_c_tkconfig}" = x ; then
|
||||
if test -f $ac_cv_c_tkconfig/../generic/tk.h ; then
|
||||
ac_cv_c_tkh=`(cd $ac_cv_c_tkconfig/..; pwd)`
|
||||
fi
|
||||
fi
|
||||
|
||||
# next check in private source directory
|
||||
#
|
||||
# since ls returns lowest version numbers first, reverse its output
|
||||
if test x"${ac_cv_c_tkh}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tk \
|
||||
`ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` \
|
||||
${srcdir}/../../tk \
|
||||
`ls -dr ${srcdir}/../../tk[[4-9]]* 2>/dev/null` \
|
||||
${srcdir}/../../../tk \
|
||||
`ls -dr ${srcdir}/../../../tk[[4-9]]* 2>/dev/null ` ; do
|
||||
if test -f $i/generic/tk.h ; then
|
||||
ac_cv_c_tkh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# finally check in a few common install locations
|
||||
#
|
||||
# since ls returns lowest version numbers first, reverse its output
|
||||
if test x"${ac_cv_c_tkh}" = x ; then
|
||||
for i in \
|
||||
`ls -dr /usr/local/src/tk[[4-9]]* 2>/dev/null` \
|
||||
`ls -dr /usr/local/lib/tk[[4-9]]* 2>/dev/null` \
|
||||
/usr/local/src/tk \
|
||||
/usr/local/lib/tk \
|
||||
${prefix}/include ; do
|
||||
if test -f $i/generic/tk.h ; then
|
||||
ac_cv_c_tkh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# see if one is installed
|
||||
if test x"${ac_cv_c_tkh}" = x ; then
|
||||
AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed, ac_cv_c_tkh="")
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tkh}" != x ; then
|
||||
no_tk=""
|
||||
if test x"${ac_cv_c_tkh}" = x"installed" ; then
|
||||
AC_MSG_RESULT([is installed])
|
||||
TKHDIR=""
|
||||
else
|
||||
AC_MSG_RESULT([found in ${ac_cv_c_tkh}])
|
||||
# this hack is cause the TKHDIR won't print if there is a "-I" in it.
|
||||
TKHDIR="-I${ac_cv_c_tkh}"
|
||||
fi
|
||||
else
|
||||
TKHDIR="# no Tk directory found"
|
||||
AC_MSG_WARN([Can't find Tk private headers])
|
||||
no_tk=true
|
||||
fi
|
||||
|
||||
AC_SUBST(TKHDIR)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TKCONFIG, [
|
||||
#
|
||||
# Ok, lets find the tk configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-tkconfig
|
||||
#
|
||||
|
||||
if test x"${no_tk}" = x ; then
|
||||
# we reset no_tk in case something fails here
|
||||
no_tk=true
|
||||
AC_ARG_WITH(tkconfig, [ --with-tkconfig=DIR Directory containing tk configuration (tkConfig.sh)],
|
||||
with_tkconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tk configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tkconfig,[
|
||||
|
||||
# First check to see if --with-tkconfig was specified.
|
||||
if test x"${with_tkconfig}" != x ; then
|
||||
if test -f "${with_tkconfig}/tkConfig.sh" ; then
|
||||
ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tk library
|
||||
if test x"${ac_cv_c_tkconfig}" = x ; then
|
||||
for i in \
|
||||
../tk \
|
||||
`ls -dr ../tk[[4-9]]* 2>/dev/null` \
|
||||
../../tk \
|
||||
`ls -dr ../../tk[[4-9]]* 2>/dev/null` \
|
||||
../../../tk \
|
||||
`ls -dr ../../../tk[[4-9]]* 2>/dev/null` ; do
|
||||
if test -f "$i/${configdir}/tkConfig.sh" ; then
|
||||
ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tkconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
if test -f "$i/tkConfig.sh" ; then
|
||||
ac_cv_c_tkconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_tkconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tk \
|
||||
`ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` ; do
|
||||
if test -f "$i/${configdir}/tkConfig.sh" ; then
|
||||
ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tkconfig}" = x ; then
|
||||
TKCONFIG="# no Tk configs found"
|
||||
AC_MSG_WARN(Can't find Tk configuration definitions)
|
||||
else
|
||||
no_tk=
|
||||
TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
|
||||
AC_MSG_RESULT(found $TKCONFIG)
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_TKCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_TKCONFIG, [
|
||||
if test -f "$TKCONFIG" ; then
|
||||
. $TKCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(TK_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(TK_MAJOR_VERSION)
|
||||
dnl AC_SUBST(TK_MINOR_VERSION)
|
||||
AC_SUBST(TK_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TK_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(TK_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TK_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TK_EXEC_PREFIX)
|
||||
|
||||
AC_SUBST(TK_BUILD_INCLUDES)
|
||||
AC_SUBST(TK_XINCLUDES)
|
||||
AC_SUBST(TK_XLIBSW)
|
||||
AC_SUBST(TK_BUILD_LIB_SPEC)
|
||||
AC_SUBST(TK_LIB_SPEC)
|
||||
])
|
||||
|
||||
# check for Itcl headers.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_ITCLCONFIG, [
|
||||
#
|
||||
# Ok, lets find the itcl configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-itclconfig
|
||||
#
|
||||
|
||||
if test x"${no_itcl}" = x ; then
|
||||
# we reset no_itcl in case something fails here
|
||||
no_itcl=true
|
||||
AC_ARG_WITH(itclconfig, [ --with-itclconfig Directory containing itcl configuration (itclConfig.sh)],
|
||||
with_itclconfig=${withval})
|
||||
AC_MSG_CHECKING([for Itcl configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_itclconfig,[
|
||||
|
||||
# First check to see if --with-itclconfig was specified.
|
||||
if test x"${with_itclconfig}" != x ; then
|
||||
if test -f "${with_itclconfig}/itclConfig.sh" ; then
|
||||
ac_cv_c_itclconfig=`(cd ${with_itclconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_itclconfig} directory doesn't contain itclConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Itcl library
|
||||
if test x"${ac_cv_c_itclconfig}" = x ; then
|
||||
for i in \
|
||||
../itcl/itcl \
|
||||
`ls -dr ../itcl[[4-9]]*/itcl 2>/dev/null` \
|
||||
../../itcl \
|
||||
`ls -dr ../../itcl[[4-9]]*/itcl 2>/dev/null` \
|
||||
../../../itcl \
|
||||
`ls -dr ../../../itcl[[4-9]]*/itcl 2>/dev/null` ; do
|
||||
if test -f "$i/itclConfig.sh" ; then
|
||||
ac_cv_c_itclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_itclconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
if test -f "$i/itclConfig.sh" ; then
|
||||
ac_cv_c_itclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_itclconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../itcl/itcl \
|
||||
`ls -dr ${srcdir}/../itcl[[4-9]]*/itcl 2>/dev/null` ; do
|
||||
if test -f "$i/itclConfig.sh" ; then
|
||||
ac_cv_c_itclconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_itclconfig}" = x ; then
|
||||
ITCLCONFIG="# no Itcl configs found"
|
||||
AC_MSG_WARN(Can't find Itcl configuration definitions)
|
||||
else
|
||||
no_itcl=
|
||||
ITCLCONFIG=${ac_cv_c_itclconfig}/itclConfig.sh
|
||||
AC_MSG_RESULT(found $ITCLCONFIG)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_ITCLCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_ITCLCONFIG, [
|
||||
if test -f "$ITCLCONFIG" ; then
|
||||
. $ITCLCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(ITCL_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(ITCL_MAJOR_VERSION)
|
||||
dnl AC_SUBST(ITCL_MINOR_VERSION)
|
||||
AC_SUBST(ITCL_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITCL_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(ITCL_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITCL_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITCL_EXEC_PREFIX)
|
||||
|
||||
AC_SUBST(ITCL_BUILD_INCLUDES)
|
||||
AC_SUBST(ITCL_BUILD_LIB_SPEC)
|
||||
AC_SUBST(ITCL_LIB_SPEC)
|
||||
])
|
||||
|
||||
# check for Itcl headers.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_ITCLH, [
|
||||
AC_MSG_CHECKING(for Itcl private headers. srcdir=${srcdir})
|
||||
if test x"${ac_cv_c_itclh}" = x ; then
|
||||
for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itcl; do
|
||||
if test -f $i/generic/itcl.h ; then
|
||||
ac_cv_c_itclh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test x"${ac_cv_c_itclh}" = x ; then
|
||||
ITCLHDIR="# no Itcl private headers found"
|
||||
AC_MSG_ERROR([Can't find Itcl private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_itclh}" != x ; then
|
||||
ITCLHDIR="-I${ac_cv_c_itclh}"
|
||||
fi
|
||||
# should always be here
|
||||
# ITCLLIB="../itcl/itcl/unix/libitcl.a"
|
||||
AC_SUBST(ITCLHDIR)
|
||||
#AC_SUBST(ITCLLIB)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_ITKCONFIG, [
|
||||
#
|
||||
# Ok, lets find the itk configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-itkconfig
|
||||
#
|
||||
|
||||
if test x"${no_itk}" = x ; then
|
||||
# we reset no_itk in case something fails here
|
||||
no_itk=true
|
||||
AC_ARG_WITH(itkconfig, [ --with-itkconfig Directory containing itk configuration (itkConfig.sh)],
|
||||
with_itkconfig=${withval})
|
||||
AC_MSG_CHECKING([for Itk configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_itkconfig,[
|
||||
|
||||
# First check to see if --with-itkconfig was specified.
|
||||
if test x"${with_itkconfig}" != x ; then
|
||||
if test -f "${with_itkconfig}/itkConfig.sh" ; then
|
||||
ac_cv_c_itkconfig=`(cd ${with_itkconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_itkconfig} directory doesn't contain itkConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Itk library
|
||||
if test x"${ac_cv_c_itkconfig}" = x ; then
|
||||
for i in \
|
||||
../itcl/itk \
|
||||
`ls -dr ../itcl[[4-9]]*/itk 2>/dev/null` \
|
||||
../../itk \
|
||||
`ls -dr ../../itcl[[4-9]]*/itk 2>/dev/null` \
|
||||
../../../itk \
|
||||
`ls -dr ../../../itcl[[4-9]]*/itk 2>/dev/null` ; do
|
||||
if test -f "$i/itkConfig.sh" ; then
|
||||
ac_cv_c_itkconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_itkconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
if test -f "$i/itkConfig.sh" ; then
|
||||
ac_cv_c_itkconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
if test x"${ac_cv_c_itkconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../itcl/itk \
|
||||
`ls -dr ${srcdir}/../itcl[[4-9]]*/itk 2>/dev/null` ; do
|
||||
if test -f "$i/itkConfig.sh" ; then
|
||||
ac_cv_c_itkconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_itkconfig}" = x ; then
|
||||
ITKCONFIG="# no Itk configs found"
|
||||
AC_MSG_WARN(Can't find Itk configuration definitions)
|
||||
else
|
||||
no_itk=
|
||||
ITKCONFIG=${ac_cv_c_itkconfig}/itkConfig.sh
|
||||
AC_MSG_RESULT(found $ITKCONFIG)
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_ITKCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_ITKCONFIG, [
|
||||
if test -f "$ITKCONFIG" ; then
|
||||
. $ITKCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(ITK_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(ITK_MAJOR_VERSION)
|
||||
dnl AC_SUBST(ITK_MINOR_VERSION)
|
||||
AC_SUBST(ITK_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITK_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(ITK_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITK_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(ITK_EXEC_PREFIX)
|
||||
|
||||
AC_SUBST(ITK_BUILD_INCLUDES)
|
||||
AC_SUBST(ITK_BUILD_LIB_SPEC)
|
||||
AC_SUBST(ITK_LIB_SPEC)
|
||||
])
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_ITKH, [
|
||||
AC_MSG_CHECKING(for Itk private headers. srcdir=${srcdir})
|
||||
if test x"${ac_cv_c_itkh}" = x ; then
|
||||
for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itk; do
|
||||
if test -f $i/generic/itk.h ; then
|
||||
ac_cv_c_itkh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test x"${ac_cv_c_itkh}" = x ; then
|
||||
ITKHDIR="# no Itk private headers found"
|
||||
AC_MSG_ERROR([Can't find Itk private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_itkh}" != x ; then
|
||||
ITKHDIR="-I${ac_cv_c_itkh}"
|
||||
fi
|
||||
# should always be here
|
||||
# ITKLIB="../itcl/itk/unix/libitk.a"
|
||||
AC_SUBST(ITKHDIR)
|
||||
#AC_SUBST(ITKLIB)
|
||||
])
|
||||
|
||||
# check for Tix headers.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXH, [
|
||||
AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
|
||||
if test -f $i/generic/tix.h ; then
|
||||
ac_cv_c_tixh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
TIXHDIR="# no Tix private headers found"
|
||||
AC_MSG_ERROR([Can't find Tix private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" != x ; then
|
||||
TIXHDIR="-I${ac_cv_c_tixh}"
|
||||
fi
|
||||
AC_SUBST(TIXHDIR)
|
||||
])
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
|
||||
#
|
||||
# Ok, lets find the tix configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-itkconfig
|
||||
#
|
||||
|
||||
if test x"${no_tix}" = x ; then
|
||||
# we reset no_tix in case something fails here
|
||||
no_tix=true
|
||||
AC_ARG_WITH(tixconfig, [ --with-tixconfig Directory containing tix configuration (tixConfig.sh)],
|
||||
with_tixconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tix configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tixconfig,[
|
||||
|
||||
# First check to see if --with-tixconfig was specified.
|
||||
if test x"${with_tixconfig}" != x ; then
|
||||
if test -f "${with_tixconfig}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tix library
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
../tix \
|
||||
`ls -dr ../tix 2>/dev/null` \
|
||||
../../tix \
|
||||
`ls -dr ../../tix 2>/dev/null` \
|
||||
../../../tix \
|
||||
`ls -dr ../../../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
echo "**** Looking at $i"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
echo "**** Other private locations"
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tix \
|
||||
`ls -dr ${srcdir}/../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/${configdir}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
TIXCONFIG="# no Tix configs found"
|
||||
AC_MSG_WARN(Can't find Tix configuration definitions)
|
||||
else
|
||||
no_tix=
|
||||
TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
|
||||
AC_MSG_RESULT(found $TIXCONFIG)
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_TIXCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
|
||||
if test -f "$TIXCONFIG" ; then
|
||||
. $TIXCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(TIX_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_MAJOR_VERSION)
|
||||
dnl AC_SUBST(TIX_MINOR_VERSION)
|
||||
dnl AC_SUBST(TIX_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl dnl AC_SUBST(TIX_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(TIX_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_EXEC_PREFIX)
|
||||
|
||||
dnl AC_SUBST(TIX_BUILD_INCLUDES)
|
||||
AC_SUBST(TIX_BUILD_LIB_SPEC)
|
||||
dnl AC_SUBST(TIX_LIB_SPEC)
|
||||
])
|
||||
|
||||
dnl sinclude(../gettext.m4) already included by bfd/acinclude.m4
|
||||
dnl The lines below arrange for aclocal not to bring gettext.m4's
|
||||
dnl CY_GNU_GETTEXT into aclocal.m4.
|
||||
ifelse(yes,no,[
|
||||
AC_DEFUN([CY_GNU_GETTEXT],)
|
||||
])
|
||||
|
||||
## ----------------------------------------- ##
|
||||
## ANSIfy the C compiler whenever possible. ##
|
||||
## From Franc,ois Pinard ##
|
||||
## ----------------------------------------- ##
|
||||
|
||||
# Copyright 1996, 1997, 1999, 2000, 2001 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 2, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
# serial 1
|
||||
|
||||
# @defmac AC_PROG_CC_STDC
|
||||
# @maindex PROG_CC_STDC
|
||||
# @ovindex CC
|
||||
# If the C compiler in not in ANSI C mode by default, try to add an option
|
||||
# to output variable @code{CC} to make it so. This macro tries various
|
||||
# options that select ANSI C on some system or another. It considers the
|
||||
# compiler to be in ANSI C mode if it handles function prototypes correctly.
|
||||
#
|
||||
# If you use this macro, you should check after calling it whether the C
|
||||
# compiler has been set to accept ANSI C; if not, the shell variable
|
||||
# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
|
||||
# code in ANSI C, you can make an un-ANSIfied copy of it by using the
|
||||
# program @code{ansi2knr}, which comes with Ghostscript.
|
||||
# @end defmac
|
||||
|
||||
AC_DEFUN([AM_PROG_CC_STDC],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_BEFORE([$0], [AC_C_INLINE])
|
||||
AC_BEFORE([$0], [AC_C_CONST])
|
||||
dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
|
||||
dnl a magic option to avoid problems with ANSI preprocessor commands
|
||||
dnl like #elif.
|
||||
dnl FIXME: can't do this because then AC_AIX won't work due to a
|
||||
dnl circular dependency.
|
||||
dnl AC_BEFORE([$0], [AC_PROG_CPP])
|
||||
AC_MSG_CHECKING([for ${CC-cc} option to accept ANSI C])
|
||||
AC_CACHE_VAL(am_cv_prog_cc_stdc,
|
||||
[am_cv_prog_cc_stdc=no
|
||||
ac_save_CC="$CC"
|
||||
# Don't try gcc -ansi; that turns off useful extensions and
|
||||
# breaks some systems' header files.
|
||||
# AIX -qlanglvl=ansi
|
||||
# Ultrix and OSF/1 -std1
|
||||
# HP-UX 10.20 and later -Ae
|
||||
# HP-UX older versions -Aa -D_HPUX_SOURCE
|
||||
# SVR4 -Xc -D__EXTENSIONS__
|
||||
for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
|
||||
do
|
||||
CC="$ac_save_CC $ac_arg"
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
static char *e (p, i)
|
||||
char **p;
|
||||
int i;
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
static char *f (char * (*g) (char **, int), char **p, ...)
|
||||
{
|
||||
char *s;
|
||||
va_list v;
|
||||
va_start (v,p);
|
||||
s = g (p, va_arg (v,int));
|
||||
va_end (v);
|
||||
return s;
|
||||
}
|
||||
int test (int i, double x);
|
||||
struct s1 {int (*f) (int a);};
|
||||
struct s2 {int (*f) (double a);};
|
||||
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
|
||||
int argc;
|
||||
char **argv;
|
||||
], [
|
||||
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
|
||||
],
|
||||
[am_cv_prog_cc_stdc="$ac_arg"; break])
|
||||
done
|
||||
CC="$ac_save_CC"
|
||||
])
|
||||
if test -z "$am_cv_prog_cc_stdc"; then
|
||||
AC_MSG_RESULT([none needed])
|
||||
else
|
||||
AC_MSG_RESULT([$am_cv_prog_cc_stdc])
|
||||
fi
|
||||
case "x$am_cv_prog_cc_stdc" in
|
||||
x|xno) ;;
|
||||
*) CC="$CC $am_cv_prog_cc_stdc" ;;
|
||||
esac
|
||||
])
|
||||
1020
gdb/aclocal.m4
vendored
1020
gdb/aclocal.m4
vendored
File diff suppressed because it is too large
Load Diff
964
gdb/ada-exp.y
964
gdb/ada-exp.y
@@ -1,964 +0,0 @@
|
||||
/* YACC parser for Ada expressions, for GDB.
|
||||
Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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. */
|
||||
|
||||
/* Parse an Ada expression from text in a string,
|
||||
and return the result as a struct expression pointer.
|
||||
That structure contains arithmetic operations in reverse polish,
|
||||
with constants represented by operations that are followed by special data.
|
||||
See expression.h for the details of the format.
|
||||
What is important here is that it can be built up sequentially
|
||||
during the process of parsing; the lower levels of the tree always
|
||||
come first in the result.
|
||||
|
||||
malloc's and realloc's in this file are transformed to
|
||||
xmalloc and xrealloc respectively by the same sed command in the
|
||||
makefile that remaps any other malloc/realloc inserted by the parser
|
||||
generator. Doing this with #defines and trying to control the interaction
|
||||
with include files (<malloc.h> and <stdlib.h> for example) just became
|
||||
too messy, particularly when such includes can be inserted at random
|
||||
times by the parser generator. */
|
||||
|
||||
%{
|
||||
|
||||
#include "defs.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "ada-lang.h"
|
||||
#include "bfd.h" /* Required by objfiles.h. */
|
||||
#include "symfile.h" /* Required by objfiles.h. */
|
||||
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
|
||||
#include "frame.h"
|
||||
|
||||
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
|
||||
as well as gratuitiously global symbol names, so we can have multiple
|
||||
yacc generated parsers in gdb. These are only the variables
|
||||
produced by yacc. If other parser generators (bison, byacc, etc) produce
|
||||
additional global names that conflict at link time, then those parser
|
||||
generators need to be fixed instead of adding those names to this list. */
|
||||
|
||||
/* NOTE: This is clumsy, especially since BISON and FLEX provide --prefix
|
||||
options. I presume we are maintaining it to accommodate systems
|
||||
without BISON? (PNH) */
|
||||
|
||||
#define yymaxdepth ada_maxdepth
|
||||
#define yyparse _ada_parse /* ada_parse calls this after initialization */
|
||||
#define yylex ada_lex
|
||||
#define yyerror ada_error
|
||||
#define yylval ada_lval
|
||||
#define yychar ada_char
|
||||
#define yydebug ada_debug
|
||||
#define yypact ada_pact
|
||||
#define yyr1 ada_r1
|
||||
#define yyr2 ada_r2
|
||||
#define yydef ada_def
|
||||
#define yychk ada_chk
|
||||
#define yypgo ada_pgo
|
||||
#define yyact ada_act
|
||||
#define yyexca ada_exca
|
||||
#define yyerrflag ada_errflag
|
||||
#define yynerrs ada_nerrs
|
||||
#define yyps ada_ps
|
||||
#define yypv ada_pv
|
||||
#define yys ada_s
|
||||
#define yy_yys ada_yys
|
||||
#define yystate ada_state
|
||||
#define yytmp ada_tmp
|
||||
#define yyv ada_v
|
||||
#define yy_yyv ada_yyv
|
||||
#define yyval ada_val
|
||||
#define yylloc ada_lloc
|
||||
#define yyreds ada_reds /* With YYDEBUG defined */
|
||||
#define yytoks ada_toks /* With YYDEBUG defined */
|
||||
|
||||
#ifndef YYDEBUG
|
||||
#define YYDEBUG 1 /* Default to yydebug support */
|
||||
#endif
|
||||
|
||||
#define YYFPRINTF parser_fprintf
|
||||
|
||||
struct name_info {
|
||||
struct symbol* sym;
|
||||
struct minimal_symbol* msym;
|
||||
struct block* block;
|
||||
struct stoken stoken;
|
||||
};
|
||||
|
||||
/* If expression is in the context of TYPE'(...), then TYPE, else
|
||||
* NULL. */
|
||||
static struct type* type_qualifier;
|
||||
|
||||
int yyparse (void);
|
||||
|
||||
static int yylex (void);
|
||||
|
||||
void yyerror (char *);
|
||||
|
||||
static struct stoken string_to_operator (struct stoken);
|
||||
|
||||
static void write_attribute_call0 (enum ada_attribute);
|
||||
|
||||
static void write_attribute_call1 (enum ada_attribute, LONGEST);
|
||||
|
||||
static void write_attribute_calln (enum ada_attribute, int);
|
||||
|
||||
static void write_object_renaming (struct block*, struct symbol*);
|
||||
|
||||
static void write_var_from_name (struct block*, struct name_info);
|
||||
|
||||
static LONGEST
|
||||
convert_char_literal (struct type*, LONGEST);
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
LONGEST lval;
|
||||
struct {
|
||||
LONGEST val;
|
||||
struct type *type;
|
||||
} typed_val;
|
||||
struct {
|
||||
DOUBLEST dval;
|
||||
struct type *type;
|
||||
} typed_val_float;
|
||||
struct type *tval;
|
||||
struct stoken sval;
|
||||
struct name_info ssym;
|
||||
int voidval;
|
||||
struct block *bval;
|
||||
struct internalvar *ivar;
|
||||
|
||||
}
|
||||
|
||||
%type <voidval> exp exp1 simple_exp start variable
|
||||
%type <tval> type
|
||||
|
||||
%token <typed_val> INT NULL_PTR CHARLIT
|
||||
%token <typed_val_float> FLOAT
|
||||
%token <tval> TYPENAME
|
||||
%token <bval> BLOCKNAME
|
||||
|
||||
/* Both NAME and TYPENAME tokens represent symbols in the input,
|
||||
and both convey their data as strings.
|
||||
But a TYPENAME is a string that happens to be defined as a typedef
|
||||
or builtin type name (such as int or char)
|
||||
and a NAME is any other symbol.
|
||||
Contexts where this distinction is not important can use the
|
||||
nonterminal "name", which matches either NAME or TYPENAME. */
|
||||
|
||||
%token <sval> STRING
|
||||
%token <ssym> NAME DOT_ID OBJECT_RENAMING
|
||||
%type <bval> block
|
||||
%type <lval> arglist tick_arglist
|
||||
|
||||
%type <tval> save_qualifier
|
||||
|
||||
%token DOT_ALL
|
||||
|
||||
/* Special type cases, put in to allow the parser to distinguish different
|
||||
legal basetypes. */
|
||||
%token <lval> LAST REGNAME
|
||||
|
||||
%token <ivar> INTERNAL_VARIABLE
|
||||
|
||||
%nonassoc ASSIGN
|
||||
%left _AND_ OR XOR THEN ELSE
|
||||
%left '=' NOTEQUAL '<' '>' LEQ GEQ IN DOTDOT
|
||||
%left '@'
|
||||
%left '+' '-' '&'
|
||||
%left UNARY
|
||||
%left '*' '/' MOD REM
|
||||
%right STARSTAR ABS NOT
|
||||
/* The following are right-associative only so that reductions at this
|
||||
precedence have lower precedence than '.' and '('. The syntax still
|
||||
forces a.b.c, e.g., to be LEFT-associated. */
|
||||
%right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
|
||||
%right TICK_MAX TICK_MIN TICK_MODULUS
|
||||
%right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
|
||||
%right '.' '(' '[' DOT_ID DOT_ALL
|
||||
|
||||
%token ARROW NEW
|
||||
|
||||
|
||||
%%
|
||||
|
||||
start : exp1
|
||||
| type { write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
/* Expressions, including the sequencing operator. */
|
||||
exp1 : exp
|
||||
| exp1 ';' exp
|
||||
{ write_exp_elt_opcode (BINOP_COMMA); }
|
||||
;
|
||||
|
||||
/* Expressions, not including the sequencing operator. */
|
||||
simple_exp : simple_exp DOT_ALL
|
||||
{ write_exp_elt_opcode (UNOP_IND); }
|
||||
;
|
||||
|
||||
simple_exp : simple_exp DOT_ID
|
||||
{ write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
write_exp_string ($2.stoken);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : simple_exp '(' arglist ')'
|
||||
{
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
write_exp_elt_longcst ($3);
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : type '(' exp ')'
|
||||
{
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : type '\'' save_qualifier { type_qualifier = $1; } '(' exp ')'
|
||||
{
|
||||
/* write_exp_elt_opcode (UNOP_QUAL); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
write_exp_elt_type ($1);
|
||||
/* write_exp_elt_opcode (UNOP_QUAL); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
type_qualifier = $3;
|
||||
}
|
||||
;
|
||||
|
||||
save_qualifier : { $$ = type_qualifier; }
|
||||
|
||||
simple_exp :
|
||||
simple_exp '(' exp DOTDOT exp ')'
|
||||
{ write_exp_elt_opcode (TERNOP_SLICE); }
|
||||
;
|
||||
|
||||
simple_exp : '(' exp1 ')' { }
|
||||
;
|
||||
|
||||
simple_exp : variable
|
||||
;
|
||||
|
||||
simple_exp: REGNAME /* GDB extension */
|
||||
{ write_exp_elt_opcode (OP_REGISTER);
|
||||
write_exp_elt_longcst ((LONGEST) $1);
|
||||
write_exp_elt_opcode (OP_REGISTER);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp: INTERNAL_VARIABLE /* GDB extension */
|
||||
{ write_exp_elt_opcode (OP_INTERNALVAR);
|
||||
write_exp_elt_intern ($1);
|
||||
write_exp_elt_opcode (OP_INTERNALVAR);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
exp : simple_exp
|
||||
;
|
||||
|
||||
simple_exp: LAST
|
||||
{ write_exp_elt_opcode (OP_LAST);
|
||||
write_exp_elt_longcst ((LONGEST) $1);
|
||||
write_exp_elt_opcode (OP_LAST);
|
||||
}
|
||||
;
|
||||
|
||||
exp : exp ASSIGN exp /* Extension for convenience */
|
||||
{ write_exp_elt_opcode (BINOP_ASSIGN); }
|
||||
;
|
||||
|
||||
exp : '-' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_NEG); }
|
||||
;
|
||||
|
||||
exp : '+' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_PLUS); }
|
||||
;
|
||||
|
||||
exp : NOT exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
|
||||
;
|
||||
|
||||
exp : ABS exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_ABS); }
|
||||
;
|
||||
|
||||
arglist : { $$ = 0; }
|
||||
;
|
||||
|
||||
arglist : exp
|
||||
{ $$ = 1; }
|
||||
| any_name ARROW exp
|
||||
{ $$ = 1; }
|
||||
| arglist ',' exp
|
||||
{ $$ = $1 + 1; }
|
||||
| arglist ',' any_name ARROW exp
|
||||
{ $$ = $1 + 1; }
|
||||
;
|
||||
|
||||
exp : '{' type '}' exp %prec '.'
|
||||
/* GDB extension */
|
||||
{ write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
write_exp_elt_type ($2);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
;
|
||||
|
||||
/* Binary operators in order of decreasing precedence. */
|
||||
|
||||
exp : exp STARSTAR exp
|
||||
{ write_exp_elt_opcode (BINOP_EXP); }
|
||||
;
|
||||
|
||||
exp : exp '*' exp
|
||||
{ write_exp_elt_opcode (BINOP_MUL); }
|
||||
;
|
||||
|
||||
exp : exp '/' exp
|
||||
{ write_exp_elt_opcode (BINOP_DIV); }
|
||||
;
|
||||
|
||||
exp : exp REM exp /* May need to be fixed to give correct Ada REM */
|
||||
{ write_exp_elt_opcode (BINOP_REM); }
|
||||
;
|
||||
|
||||
exp : exp MOD exp
|
||||
{ write_exp_elt_opcode (BINOP_MOD); }
|
||||
;
|
||||
|
||||
exp : exp '@' exp /* GDB extension */
|
||||
{ write_exp_elt_opcode (BINOP_REPEAT); }
|
||||
;
|
||||
|
||||
exp : exp '+' exp
|
||||
{ write_exp_elt_opcode (BINOP_ADD); }
|
||||
;
|
||||
|
||||
exp : exp '&' exp
|
||||
{ write_exp_elt_opcode (BINOP_CONCAT); }
|
||||
;
|
||||
|
||||
exp : exp '-' exp
|
||||
{ write_exp_elt_opcode (BINOP_SUB); }
|
||||
;
|
||||
|
||||
exp : exp '=' exp
|
||||
{ write_exp_elt_opcode (BINOP_EQUAL); }
|
||||
;
|
||||
|
||||
exp : exp NOTEQUAL exp
|
||||
{ write_exp_elt_opcode (BINOP_NOTEQUAL); }
|
||||
;
|
||||
|
||||
exp : exp LEQ exp
|
||||
{ write_exp_elt_opcode (BINOP_LEQ); }
|
||||
;
|
||||
|
||||
exp : exp IN exp DOTDOT exp
|
||||
{ /*write_exp_elt_opcode (TERNOP_MBR); */ }
|
||||
/* FIXME: TERNOP_MBR should be defined in
|
||||
expression.h */
|
||||
| exp IN exp TICK_RANGE tick_arglist
|
||||
{ /*write_exp_elt_opcode (BINOP_MBR); */
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) $5);
|
||||
/*write_exp_elt_opcode (BINOP_MBR); */
|
||||
}
|
||||
| exp IN TYPENAME %prec TICK_ACCESS
|
||||
{ /*write_exp_elt_opcode (UNOP_MBR); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
write_exp_elt_type ($3);
|
||||
/* write_exp_elt_opcode (UNOP_MBR); */
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
}
|
||||
| exp NOT IN exp DOTDOT exp
|
||||
{ /*write_exp_elt_opcode (TERNOP_MBR); */
|
||||
/* FIXME: TERNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
| exp NOT IN exp TICK_RANGE tick_arglist
|
||||
{ /* write_exp_elt_opcode (BINOP_MBR); */
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) $6);
|
||||
/*write_exp_elt_opcode (BINOP_MBR);*/
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
| exp NOT IN TYPENAME %prec TICK_ACCESS
|
||||
{ /*write_exp_elt_opcode (UNOP_MBR);*/
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_type ($4);
|
||||
/* write_exp_elt_opcode (UNOP_MBR);*/
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
;
|
||||
|
||||
exp : exp GEQ exp
|
||||
{ write_exp_elt_opcode (BINOP_GEQ); }
|
||||
;
|
||||
|
||||
exp : exp '<' exp
|
||||
{ write_exp_elt_opcode (BINOP_LESS); }
|
||||
;
|
||||
|
||||
exp : exp '>' exp
|
||||
{ write_exp_elt_opcode (BINOP_GTR); }
|
||||
;
|
||||
|
||||
exp : exp _AND_ exp /* Fix for Ada elementwise AND. */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_AND); }
|
||||
;
|
||||
|
||||
exp : exp _AND_ THEN exp %prec _AND_
|
||||
{ write_exp_elt_opcode (BINOP_LOGICAL_AND); }
|
||||
;
|
||||
|
||||
exp : exp OR exp /* Fix for Ada elementwise OR */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_IOR); }
|
||||
;
|
||||
|
||||
exp : exp OR ELSE exp
|
||||
{ write_exp_elt_opcode (BINOP_LOGICAL_OR); }
|
||||
;
|
||||
|
||||
exp : exp XOR exp /* Fix for Ada elementwise XOR */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_XOR); }
|
||||
;
|
||||
|
||||
simple_exp : simple_exp TICK_ACCESS
|
||||
{ write_exp_elt_opcode (UNOP_ADDR); }
|
||||
| simple_exp TICK_ADDRESS
|
||||
{ write_exp_elt_opcode (UNOP_ADDR);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
write_exp_elt_type (builtin_type_ada_system_address);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
}
|
||||
| simple_exp TICK_FIRST tick_arglist
|
||||
{ write_attribute_call1 (ATR_FIRST, $3); }
|
||||
| simple_exp TICK_LAST tick_arglist
|
||||
{ write_attribute_call1 (ATR_LAST, $3); }
|
||||
| simple_exp TICK_LENGTH tick_arglist
|
||||
{ write_attribute_call1 (ATR_LENGTH, $3); }
|
||||
| simple_exp TICK_SIZE
|
||||
{ write_attribute_call0 (ATR_SIZE); }
|
||||
| simple_exp TICK_TAG
|
||||
{ write_attribute_call0 (ATR_TAG); }
|
||||
| opt_type_prefix TICK_MIN '(' exp ',' exp ')'
|
||||
{ write_attribute_calln (ATR_MIN, 2); }
|
||||
| opt_type_prefix TICK_MAX '(' exp ',' exp ')'
|
||||
{ write_attribute_calln (ATR_MAX, 2); }
|
||||
| opt_type_prefix TICK_POS '(' exp ')'
|
||||
{ write_attribute_calln (ATR_POS, 1); }
|
||||
| type_prefix TICK_FIRST tick_arglist
|
||||
{ write_attribute_call1 (ATR_FIRST, $3); }
|
||||
| type_prefix TICK_LAST tick_arglist
|
||||
{ write_attribute_call1 (ATR_LAST, $3); }
|
||||
| type_prefix TICK_LENGTH tick_arglist
|
||||
{ write_attribute_call1 (ATR_LENGTH, $3); }
|
||||
| type_prefix TICK_VAL '(' exp ')'
|
||||
{ write_attribute_calln (ATR_VAL, 1); }
|
||||
| type_prefix TICK_MODULUS
|
||||
{ write_attribute_call0 (ATR_MODULUS); }
|
||||
;
|
||||
|
||||
tick_arglist : %prec '('
|
||||
{ $$ = 1; }
|
||||
| '(' INT ')'
|
||||
{ $$ = $2.val; }
|
||||
;
|
||||
|
||||
type_prefix :
|
||||
TYPENAME
|
||||
{ write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
opt_type_prefix :
|
||||
type_prefix
|
||||
| /* EMPTY */
|
||||
{ write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type (builtin_type_void);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
|
||||
exp : INT
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type ($1.type);
|
||||
write_exp_elt_longcst ((LONGEST)($1.val));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
;
|
||||
|
||||
exp : CHARLIT
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
if (type_qualifier == NULL)
|
||||
write_exp_elt_type ($1.type);
|
||||
else
|
||||
write_exp_elt_type (type_qualifier);
|
||||
write_exp_elt_longcst
|
||||
(convert_char_literal (type_qualifier, $1.val));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
|
||||
|
||||
exp : FLOAT
|
||||
{ write_exp_elt_opcode (OP_DOUBLE);
|
||||
write_exp_elt_type ($1.type);
|
||||
write_exp_elt_dblcst ($1.dval);
|
||||
write_exp_elt_opcode (OP_DOUBLE);
|
||||
}
|
||||
;
|
||||
|
||||
exp : NULL_PTR
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst ((LONGEST)(0));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
|
||||
exp : STRING
|
||||
{ /* Ada strings are converted into array constants
|
||||
a lower bound of 1. Thus, the array upper bound
|
||||
is the string length. */
|
||||
char *sp = $1.ptr; int count;
|
||||
if ($1.length == 0)
|
||||
{ /* One dummy character for the type */
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_char);
|
||||
write_exp_elt_longcst ((LONGEST)(0));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
for (count = $1.length; count > 0; count -= 1)
|
||||
{
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_char);
|
||||
write_exp_elt_longcst ((LONGEST)(*sp));
|
||||
sp += 1;
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
write_exp_elt_opcode (OP_ARRAY);
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_longcst ((LONGEST) ($1.length));
|
||||
write_exp_elt_opcode (OP_ARRAY);
|
||||
}
|
||||
;
|
||||
|
||||
exp : NEW TYPENAME
|
||||
{ error ("NEW not implemented."); }
|
||||
;
|
||||
|
||||
variable: NAME { write_var_from_name (NULL, $1); }
|
||||
| block NAME /* GDB extension */
|
||||
{ write_var_from_name ($1, $2); }
|
||||
| OBJECT_RENAMING { write_object_renaming (NULL, $1.sym); }
|
||||
| block OBJECT_RENAMING
|
||||
{ write_object_renaming ($1, $2.sym); }
|
||||
;
|
||||
|
||||
any_name : NAME { }
|
||||
| TYPENAME { }
|
||||
| OBJECT_RENAMING { }
|
||||
;
|
||||
|
||||
block : BLOCKNAME /* GDB extension */
|
||||
{ $$ = $1; }
|
||||
| block BLOCKNAME /* GDB extension */
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
type : TYPENAME { $$ = $1; }
|
||||
| block TYPENAME { $$ = $2; }
|
||||
| TYPENAME TICK_ACCESS
|
||||
{ $$ = lookup_pointer_type ($1); }
|
||||
| block TYPENAME TICK_ACCESS
|
||||
{ $$ = lookup_pointer_type ($2); }
|
||||
;
|
||||
|
||||
/* Some extensions borrowed from C, for the benefit of those who find they
|
||||
can't get used to Ada notation in GDB. */
|
||||
|
||||
exp : '*' exp %prec '.'
|
||||
{ write_exp_elt_opcode (UNOP_IND); }
|
||||
| '&' exp %prec '.'
|
||||
{ write_exp_elt_opcode (UNOP_ADDR); }
|
||||
| exp '[' exp ']'
|
||||
{ write_exp_elt_opcode (BINOP_SUBSCRIPT); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* yylex defined in ada-lex.c: Reads one token, getting characters */
|
||||
/* through lexptr. */
|
||||
|
||||
/* Remap normal flex interface names (yylex) as well as gratuitiously */
|
||||
/* global symbol names, so we can have multiple flex-generated parsers */
|
||||
/* in gdb. */
|
||||
|
||||
/* (See note above on previous definitions for YACC.) */
|
||||
|
||||
#define yy_create_buffer ada_yy_create_buffer
|
||||
#define yy_delete_buffer ada_yy_delete_buffer
|
||||
#define yy_init_buffer ada_yy_init_buffer
|
||||
#define yy_load_buffer_state ada_yy_load_buffer_state
|
||||
#define yy_switch_to_buffer ada_yy_switch_to_buffer
|
||||
#define yyrestart ada_yyrestart
|
||||
#define yytext ada_yytext
|
||||
#define yywrap ada_yywrap
|
||||
|
||||
/* The following kludge was found necessary to prevent conflicts between */
|
||||
/* defs.h and non-standard stdlib.h files. */
|
||||
#define qsort __qsort__dummy
|
||||
#include "ada-lex.c"
|
||||
|
||||
int
|
||||
ada_parse ()
|
||||
{
|
||||
lexer_init (yyin); /* (Re-)initialize lexer. */
|
||||
left_block_context = NULL;
|
||||
type_qualifier = NULL;
|
||||
|
||||
return _ada_parse ();
|
||||
}
|
||||
|
||||
void
|
||||
yyerror (msg)
|
||||
char *msg;
|
||||
{
|
||||
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
|
||||
}
|
||||
|
||||
/* The operator name corresponding to operator symbol STRING (adds
|
||||
quotes and maps to lower-case). Destroys the previous contents of
|
||||
the array pointed to by STRING.ptr. Error if STRING does not match
|
||||
a valid Ada operator. Assumes that STRING.ptr points to a
|
||||
null-terminated string and that, if STRING is a valid operator
|
||||
symbol, the array pointed to by STRING.ptr contains at least
|
||||
STRING.length+3 characters. */
|
||||
|
||||
static struct stoken
|
||||
string_to_operator (string)
|
||||
struct stoken string;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
|
||||
{
|
||||
if (string.length == strlen (ada_opname_table[i].demangled)-2
|
||||
&& strncasecmp (string.ptr, ada_opname_table[i].demangled+1,
|
||||
string.length) == 0)
|
||||
{
|
||||
strncpy (string.ptr, ada_opname_table[i].demangled,
|
||||
string.length+2);
|
||||
string.length += 2;
|
||||
return string;
|
||||
}
|
||||
}
|
||||
error ("Invalid operator symbol `%s'", string.ptr);
|
||||
}
|
||||
|
||||
/* Emit expression to access an instance of SYM, in block BLOCK (if
|
||||
* non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
|
||||
static void
|
||||
write_var_from_sym (orig_left_context, block, sym)
|
||||
struct block* orig_left_context;
|
||||
struct block* block;
|
||||
struct symbol* sym;
|
||||
{
|
||||
if (orig_left_context == NULL && symbol_read_needs_frame (sym))
|
||||
{
|
||||
if (innermost_block == 0 ||
|
||||
contained_in (block, innermost_block))
|
||||
innermost_block = block;
|
||||
}
|
||||
|
||||
write_exp_elt_opcode (OP_VAR_VALUE);
|
||||
/* We want to use the selected frame, not another more inner frame
|
||||
which happens to be in the same block */
|
||||
write_exp_elt_block (NULL);
|
||||
write_exp_elt_sym (sym);
|
||||
write_exp_elt_opcode (OP_VAR_VALUE);
|
||||
}
|
||||
|
||||
/* Emit expression to access an instance of NAME. */
|
||||
static void
|
||||
write_var_from_name (orig_left_context, name)
|
||||
struct block* orig_left_context;
|
||||
struct name_info name;
|
||||
{
|
||||
if (name.msym != NULL)
|
||||
{
|
||||
write_exp_msymbol (name.msym,
|
||||
lookup_function_type (builtin_type_int),
|
||||
builtin_type_int);
|
||||
}
|
||||
else if (name.sym == NULL)
|
||||
{
|
||||
/* Multiple matches: record name and starting block for later
|
||||
resolution by ada_resolve. */
|
||||
/* write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
|
||||
/* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */
|
||||
write_exp_elt_block (name.block);
|
||||
/* write_exp_elt_name (name.stoken.ptr); */
|
||||
/* FIXME: write_exp_elt_name should be defined in defs.h, located in parse.c */
|
||||
/* write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
|
||||
/* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */
|
||||
}
|
||||
else
|
||||
write_var_from_sym (orig_left_context, name.block, name.sym);
|
||||
}
|
||||
|
||||
/* Write a call on parameterless attribute ATR. */
|
||||
|
||||
static void
|
||||
write_attribute_call0 (atr)
|
||||
enum ada_attribute atr;
|
||||
{
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE); */
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) 0);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE); */
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Write a call on an attribute ATR with one constant integer
|
||||
* parameter. */
|
||||
|
||||
static void
|
||||
write_attribute_call1 (atr, arg)
|
||||
enum ada_attribute atr;
|
||||
LONGEST arg;
|
||||
{
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst (arg);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Write a call on an attribute ATR with N parameters, whose code must have
|
||||
* been generated previously. */
|
||||
|
||||
static void
|
||||
write_attribute_calln (atr, n)
|
||||
enum ada_attribute atr;
|
||||
int n;
|
||||
{
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) n);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Emit expression corresponding to the renamed object designated by
|
||||
* the type RENAMING, which must be the referent of an object renaming
|
||||
* type, in the context of ORIG_LEFT_CONTEXT (?). */
|
||||
static void
|
||||
write_object_renaming (orig_left_context, renaming)
|
||||
struct block* orig_left_context;
|
||||
struct symbol* renaming;
|
||||
{
|
||||
const char* qualification = SYMBOL_NAME (renaming);
|
||||
const char* simple_tail;
|
||||
const char* expr = TYPE_FIELD_NAME (SYMBOL_TYPE (renaming), 0);
|
||||
const char* suffix;
|
||||
char* name;
|
||||
struct symbol* sym;
|
||||
enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
|
||||
|
||||
/* if orig_left_context is null, then use the currently selected
|
||||
block, otherwise we might fail our symbol lookup below */
|
||||
if (orig_left_context == NULL)
|
||||
orig_left_context = get_selected_block (NULL);
|
||||
|
||||
for (simple_tail = qualification + strlen (qualification);
|
||||
simple_tail != qualification; simple_tail -= 1)
|
||||
{
|
||||
if (*simple_tail == '.')
|
||||
{
|
||||
simple_tail += 1;
|
||||
break;
|
||||
}
|
||||
else if (STREQN (simple_tail, "__", 2))
|
||||
{
|
||||
simple_tail += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
suffix = strstr (expr, "___XE");
|
||||
if (suffix == NULL)
|
||||
goto BadEncoding;
|
||||
|
||||
name = (char*) malloc (suffix - expr + 1);
|
||||
/* add_name_string_cleanup (name); */
|
||||
/* FIXME: add_name_string_cleanup should be defined in
|
||||
parser-defs.h, implemented in parse.c */
|
||||
strncpy (name, expr, suffix-expr);
|
||||
name[suffix-expr] = '\000';
|
||||
sym = lookup_symbol (name, orig_left_context, VAR_NAMESPACE, 0, NULL);
|
||||
/* if (sym == NULL)
|
||||
error ("Could not find renamed variable: %s", ada_demangle (name));
|
||||
*/
|
||||
/* FIXME: ada_demangle should be defined in defs.h, implemented in ada-lang.c */
|
||||
write_var_from_sym (orig_left_context, block_found, sym);
|
||||
|
||||
suffix += 5;
|
||||
slice_state = SIMPLE_INDEX;
|
||||
while (*suffix == 'X')
|
||||
{
|
||||
suffix += 1;
|
||||
|
||||
switch (*suffix) {
|
||||
case 'L':
|
||||
slice_state = LOWER_BOUND;
|
||||
case 'S':
|
||||
suffix += 1;
|
||||
if (isdigit (*suffix))
|
||||
{
|
||||
char* next;
|
||||
long val = strtol (suffix, &next, 10);
|
||||
if (next == suffix)
|
||||
goto BadEncoding;
|
||||
suffix = next;
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_int);
|
||||
write_exp_elt_longcst ((LONGEST) val);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* end;
|
||||
char* index_name;
|
||||
int index_len;
|
||||
struct symbol* index_sym;
|
||||
|
||||
end = strchr (suffix, 'X');
|
||||
if (end == NULL)
|
||||
end = suffix + strlen (suffix);
|
||||
|
||||
index_len = simple_tail - qualification + 2 + (suffix - end) + 1;
|
||||
index_name = (char*) malloc (index_len);
|
||||
memset (index_name, '\000', index_len);
|
||||
/* add_name_string_cleanup (index_name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in
|
||||
parser-defs.h, implemented in parse.c */
|
||||
strncpy (index_name, qualification, simple_tail - qualification);
|
||||
index_name[simple_tail - qualification] = '\000';
|
||||
strncat (index_name, suffix, suffix-end);
|
||||
suffix = end;
|
||||
|
||||
index_sym =
|
||||
lookup_symbol (index_name, NULL, VAR_NAMESPACE, 0, NULL);
|
||||
if (index_sym == NULL)
|
||||
error ("Could not find %s", index_name);
|
||||
write_var_from_sym (NULL, block_found, sym);
|
||||
}
|
||||
if (slice_state == SIMPLE_INDEX)
|
||||
{
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
}
|
||||
else if (slice_state == LOWER_BOUND)
|
||||
slice_state = UPPER_BOUND;
|
||||
else if (slice_state == UPPER_BOUND)
|
||||
{
|
||||
write_exp_elt_opcode (TERNOP_SLICE);
|
||||
slice_state = SIMPLE_INDEX;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
{
|
||||
struct stoken field_name;
|
||||
const char* end;
|
||||
suffix += 1;
|
||||
|
||||
if (slice_state != SIMPLE_INDEX)
|
||||
goto BadEncoding;
|
||||
end = strchr (suffix, 'X');
|
||||
if (end == NULL)
|
||||
end = suffix + strlen (suffix);
|
||||
field_name.length = end - suffix;
|
||||
field_name.ptr = (char*) malloc (end - suffix + 1);
|
||||
strncpy (field_name.ptr, suffix, end - suffix);
|
||||
field_name.ptr[end - suffix] = '\000';
|
||||
suffix = end;
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
write_exp_string (field_name);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto BadEncoding;
|
||||
}
|
||||
}
|
||||
if (slice_state == SIMPLE_INDEX)
|
||||
return;
|
||||
|
||||
BadEncoding:
|
||||
error ("Internal error in encoding of renaming declaration: %s",
|
||||
SYMBOL_NAME (renaming));
|
||||
}
|
||||
|
||||
/* Convert the character literal whose ASCII value would be VAL to the
|
||||
appropriate value of type TYPE, if there is a translation.
|
||||
Otherwise return VAL. Hence, in an enumeration type ('A', 'B'),
|
||||
the literal 'A' (VAL == 65), returns 0. */
|
||||
static LONGEST
|
||||
convert_char_literal (struct type* type, LONGEST val)
|
||||
{
|
||||
char name[7];
|
||||
int f;
|
||||
|
||||
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
|
||||
return val;
|
||||
sprintf (name, "QU%02x", (int) val);
|
||||
for (f = 0; f < TYPE_NFIELDS (type); f += 1)
|
||||
{
|
||||
if (STREQ (name, TYPE_FIELD_NAME (type, f)))
|
||||
return TYPE_FIELD_BITPOS (type, f);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
8625
gdb/ada-lang.c
8625
gdb/ada-lang.c
File diff suppressed because it is too large
Load Diff
365
gdb/ada-lang.h
365
gdb/ada-lang.h
@@ -1,365 +0,0 @@
|
||||
/* Ada language support definitions for GDB, the GNU debugger.
|
||||
Copyright 1992, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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. */
|
||||
|
||||
#if !defined (ADA_LANG_H)
|
||||
#define ADA_LANG_H 1
|
||||
|
||||
#include "value.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
/* A macro to reorder the bytes of an address depending on the endiannes
|
||||
of the target */
|
||||
#define EXTRACT_ADDRESS(x) ((void *) extract_address (&(x), sizeof (x)))
|
||||
/* A macro to reorder the bytes of an int depending on the endiannes
|
||||
of the target */
|
||||
#define EXTRACT_INT(x) ((int) extract_signed_integer (&(x), sizeof (x)))
|
||||
|
||||
/* Chain of cleanups for arguments of OP_UNRESOLVED_VALUE names. Created in
|
||||
yyparse and freed in ada_resolve. */
|
||||
extern struct cleanup* unresolved_names;
|
||||
|
||||
/* Corresponding mangled/demangled names and opcodes for Ada user-definable
|
||||
operators. */
|
||||
struct ada_opname_map {
|
||||
const char* mangled;
|
||||
const char* demangled;
|
||||
enum exp_opcode op;
|
||||
};
|
||||
|
||||
/* Table of Ada operators in mangled and demangled forms. */
|
||||
/* Defined in ada-lang.c */
|
||||
extern const struct ada_opname_map ada_opname_table[];
|
||||
|
||||
/* The maximum number of tasks known to the Ada runtime */
|
||||
extern const int MAX_NUMBER_OF_KNOWN_TASKS;
|
||||
|
||||
/* Identifiers for Ada attributes that need special processing. Be sure
|
||||
to update the table attribute_names in ada-lang.c whenever you change this.
|
||||
*/
|
||||
|
||||
enum ada_attribute {
|
||||
/* Invalid attribute for error checking. */
|
||||
ATR_INVALID,
|
||||
|
||||
ATR_FIRST,
|
||||
ATR_LAST,
|
||||
ATR_LENGTH,
|
||||
ATR_IMAGE,
|
||||
ATR_IMG,
|
||||
ATR_MAX,
|
||||
ATR_MIN,
|
||||
ATR_MODULUS,
|
||||
ATR_POS,
|
||||
ATR_SIZE,
|
||||
ATR_TAG,
|
||||
ATR_VAL,
|
||||
|
||||
/* Dummy last attribute. */
|
||||
ATR_END
|
||||
};
|
||||
|
||||
enum task_states {
|
||||
Unactivated,
|
||||
Runnable,
|
||||
Terminated,
|
||||
Activator_Sleep,
|
||||
Acceptor_Sleep,
|
||||
Entry_Caller_Sleep,
|
||||
Async_Select_Sleep,
|
||||
Delay_Sleep,
|
||||
Master_Completion_Sleep,
|
||||
Master_Phase_2_Sleep
|
||||
};
|
||||
|
||||
extern char *ada_task_states[];
|
||||
|
||||
typedef struct {
|
||||
char *P_ARRAY;
|
||||
int *P_BOUNDS;
|
||||
} fat_string;
|
||||
|
||||
typedef struct entry_call {
|
||||
void *self;
|
||||
} *entry_call_link;
|
||||
|
||||
struct task_fields
|
||||
{
|
||||
int entry_num;
|
||||
#if (defined (VXWORKS_TARGET) || !defined (i386)) \
|
||||
&& !(defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
int pad1;
|
||||
#endif
|
||||
char state;
|
||||
#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
char pad_8bits;
|
||||
#endif
|
||||
void *parent;
|
||||
int priority;
|
||||
int current_priority;
|
||||
fat_string image;
|
||||
entry_call_link call;
|
||||
#if (defined (sun) && defined (__SVR4)) && !defined (VXWORKS_TARGET)
|
||||
int pad2;
|
||||
unsigned thread;
|
||||
unsigned lwp;
|
||||
#else
|
||||
void *thread;
|
||||
void *lwp;
|
||||
#endif
|
||||
}
|
||||
#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
__attribute__ ((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct task_entry
|
||||
{
|
||||
void *task_id;
|
||||
int task_num;
|
||||
int known_tasks_index;
|
||||
struct task_entry *next_task;
|
||||
void *thread;
|
||||
void *lwp;
|
||||
int stack_per;
|
||||
};
|
||||
|
||||
extern struct type* builtin_type_ada_int;
|
||||
extern struct type* builtin_type_ada_short;
|
||||
extern struct type* builtin_type_ada_long;
|
||||
extern struct type* builtin_type_ada_long_long;
|
||||
extern struct type* builtin_type_ada_char;
|
||||
extern struct type* builtin_type_ada_float;
|
||||
extern struct type* builtin_type_ada_double;
|
||||
extern struct type* builtin_type_ada_long_double;
|
||||
extern struct type* builtin_type_ada_natural;
|
||||
extern struct type* builtin_type_ada_positive;
|
||||
extern struct type* builtin_type_ada_system_address;
|
||||
|
||||
/* Assuming V points to an array of S objects, make sure that it contains at
|
||||
least M objects, updating V and S as necessary. */
|
||||
|
||||
#define GROW_VECT(v, s, m) \
|
||||
if ((s) < (m)) grow_vect ((void**) &(v), &(s), (m), sizeof(*(v)));
|
||||
|
||||
extern void grow_vect (void**, size_t*, size_t, int);
|
||||
|
||||
extern int ada_parse (void); /* Defined in ada-exp.y */
|
||||
|
||||
extern void ada_error (char *); /* Defined in ada-exp.y */
|
||||
|
||||
/* Defined in ada-typeprint.c */
|
||||
extern void ada_print_type (struct type*, char*, struct ui_file*, int, int);
|
||||
|
||||
extern int ada_val_print (struct type*, char*, int, CORE_ADDR,
|
||||
struct ui_file*, int, int, int, enum val_prettyprint);
|
||||
|
||||
extern int ada_value_print (struct value*, struct ui_file*, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
/* Defined in ada-lang.c */
|
||||
|
||||
extern struct value* value_from_contents_and_address (struct type*, char*, CORE_ADDR);
|
||||
|
||||
extern void ada_emit_char (int, struct ui_file *, int, int);
|
||||
|
||||
extern void ada_printchar (int, struct ui_file*);
|
||||
|
||||
extern void ada_printstr (struct ui_file*, char *, unsigned int, int, int);
|
||||
|
||||
extern void ada_convert_actuals (struct value*, int, struct value**, CORE_ADDR*);
|
||||
|
||||
extern struct value* ada_value_subscript (struct value*, int, struct value**);
|
||||
|
||||
extern struct type* ada_array_element_type (struct type*, int);
|
||||
|
||||
extern int ada_array_arity (struct type*);
|
||||
|
||||
struct type* ada_type_of_array (struct value*, int);
|
||||
|
||||
extern struct value* ada_coerce_to_simple_array (struct value*);
|
||||
|
||||
extern struct value* ada_coerce_to_simple_array_ptr (struct value*);
|
||||
|
||||
extern int ada_is_simple_array (struct type*);
|
||||
|
||||
extern int ada_is_array_descriptor (struct type*);
|
||||
|
||||
extern int ada_is_bogus_array_descriptor (struct type*);
|
||||
|
||||
extern struct type* ada_index_type (struct type*, int);
|
||||
|
||||
extern struct value* ada_array_bound (struct value*, int, int);
|
||||
|
||||
extern int ada_lookup_symbol_list (const char*, struct block*, namespace_enum,
|
||||
struct symbol***, struct block***);
|
||||
|
||||
extern char* ada_fold_name (const char*);
|
||||
|
||||
extern struct symbol* ada_lookup_symbol (const char*, struct block*, namespace_enum);
|
||||
|
||||
extern struct minimal_symbol* ada_lookup_minimal_symbol (const char*);
|
||||
|
||||
extern void ada_resolve (struct expression**, struct type*);
|
||||
|
||||
extern int ada_resolve_function (struct symbol**, struct block**, int,
|
||||
struct value**, int, const char*, struct type*);
|
||||
|
||||
extern void ada_fill_in_ada_prototype (struct symbol*);
|
||||
|
||||
extern int user_select_syms (struct symbol**, struct block**, int, int);
|
||||
|
||||
extern int get_selections (int*, int, int, int, char*);
|
||||
|
||||
extern char* ada_start_decode_line_1 (char*);
|
||||
|
||||
extern struct symtabs_and_lines ada_finish_decode_line_1 (char**, struct symtab*, int, char***);
|
||||
|
||||
extern int ada_scan_number (const char*, int, LONGEST*, int*);
|
||||
|
||||
extern struct type* ada_parent_type (struct type*);
|
||||
|
||||
extern int ada_is_ignored_field (struct type*, int);
|
||||
|
||||
extern int ada_is_packed_array_type (struct type*);
|
||||
|
||||
extern struct value* ada_value_primitive_packed_val (struct value*, char*, long, int,
|
||||
int, struct type*);
|
||||
|
||||
extern struct type* ada_coerce_to_simple_array_type (struct type*);
|
||||
|
||||
extern int ada_is_character_type (struct type*);
|
||||
|
||||
extern int ada_is_string_type (struct type*);
|
||||
|
||||
extern int ada_is_tagged_type (struct type*);
|
||||
|
||||
extern struct type* ada_tag_type (struct value*);
|
||||
|
||||
extern struct value* ada_value_tag (struct value*);
|
||||
|
||||
extern int ada_is_parent_field (struct type*, int);
|
||||
|
||||
extern int ada_is_wrapper_field (struct type*, int);
|
||||
|
||||
extern int ada_is_variant_part (struct type*, int);
|
||||
|
||||
extern struct type* ada_variant_discrim_type (struct type*, struct type*);
|
||||
|
||||
extern int ada_is_others_clause (struct type*, int);
|
||||
|
||||
extern int ada_in_variant (LONGEST, struct type*, int);
|
||||
|
||||
extern char* ada_variant_discrim_name (struct type*);
|
||||
|
||||
extern struct type* ada_lookup_struct_elt_type (struct type*, char*, int, int*);
|
||||
|
||||
extern struct value* ada_value_struct_elt (struct value*, char*, char*);
|
||||
|
||||
extern struct value* ada_search_struct_field (char*, struct value*, int, struct type*);
|
||||
|
||||
extern int ada_is_aligner_type (struct type*);
|
||||
|
||||
extern struct type* ada_aligned_type (struct type*);
|
||||
|
||||
extern char* ada_aligned_value_addr (struct type*, char*);
|
||||
|
||||
extern const char* ada_attribute_name (int);
|
||||
|
||||
extern int ada_is_fixed_point_type (struct type*);
|
||||
|
||||
extern DOUBLEST ada_delta (struct type*);
|
||||
|
||||
extern DOUBLEST ada_fixed_to_float (struct type *, LONGEST);
|
||||
|
||||
extern LONGEST ada_float_to_fixed (struct type*, DOUBLEST);
|
||||
|
||||
extern int ada_is_vax_floating_type (struct type*);
|
||||
|
||||
extern int ada_vax_float_type_suffix (struct type*);
|
||||
|
||||
extern struct value* ada_vax_float_print_function (struct type*);
|
||||
|
||||
extern struct type* ada_system_address_type (void);
|
||||
|
||||
extern int ada_which_variant_applies (struct type*, struct type*, char*);
|
||||
|
||||
extern struct value* ada_to_fixed_value (struct type*, char*, CORE_ADDR, struct value*);
|
||||
|
||||
extern struct type* ada_to_fixed_type (struct type*, char*, CORE_ADDR, struct value*);
|
||||
|
||||
extern int ada_name_prefix_len (const char*);
|
||||
|
||||
extern char* ada_type_name (struct type*);
|
||||
|
||||
extern struct type* ada_find_parallel_type (struct type*, const char *suffix);
|
||||
|
||||
extern LONGEST get_int_var_value (char*, char*, int* );
|
||||
|
||||
extern struct type* ada_find_any_type (const char *name);
|
||||
|
||||
extern int ada_prefer_type (struct type*, struct type*);
|
||||
|
||||
extern struct type* ada_get_base_type (struct type*);
|
||||
|
||||
extern struct type* ada_completed_type (struct type*);
|
||||
|
||||
extern char* ada_mangle (const char*);
|
||||
|
||||
extern const char* ada_enum_name (const char*);
|
||||
|
||||
extern int ada_is_modular_type (struct type*);
|
||||
|
||||
extern LONGEST ada_modulus (struct type*);
|
||||
|
||||
extern struct value* ada_value_ind (struct value*);
|
||||
|
||||
extern void ada_print_scalar (struct type*, LONGEST, struct ui_file*);
|
||||
|
||||
extern int ada_is_range_type_name (const char*);
|
||||
|
||||
extern const char* ada_renaming_type (struct type*);
|
||||
|
||||
extern int ada_is_object_renaming (struct symbol*);
|
||||
|
||||
extern const char* ada_simple_renamed_entity (struct symbol*);
|
||||
|
||||
extern char* ada_breakpoint_rewrite (char*, int*);
|
||||
|
||||
/* Tasking-related: ada-tasks.c */
|
||||
|
||||
extern int valid_task_id (int);
|
||||
|
||||
extern int get_current_task (void);
|
||||
|
||||
extern void init_task_list (void);
|
||||
|
||||
extern void* get_self_id (void);
|
||||
|
||||
extern int get_current_task (void);
|
||||
|
||||
extern int get_entry_number (void*);
|
||||
|
||||
extern void ada_report_exception_break (struct breakpoint *);
|
||||
|
||||
extern int ada_maybe_exception_partial_symbol (struct partial_symbol* sym);
|
||||
|
||||
extern int ada_is_exception_sym (struct symbol* sym);
|
||||
|
||||
|
||||
#endif
|
||||
928
gdb/ada-lex.l
928
gdb/ada-lex.l
@@ -1,928 +0,0 @@
|
||||
/* FLEX lexer for Ada expressions, for GDB.
|
||||
Copyright (C) 1994, 1997, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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. */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/* The converted version of this file is to be included in ada-exp.y, */
|
||||
/* the Ada parser for gdb. The function yylex obtains characters from */
|
||||
/* the global pointer lexptr. It returns a syntactic category for */
|
||||
/* each successive token and places a semantic value into yylval */
|
||||
/* (ada-lval), defined by the parser. */
|
||||
|
||||
/* Run flex with (at least) the -i option (case-insensitive), and the -I */
|
||||
/* option (interactive---no unnecessary lookahead). */
|
||||
|
||||
DIG [0-9]
|
||||
NUM10 ({DIG}({DIG}|_)*)
|
||||
HEXDIG [0-9a-f]
|
||||
NUM16 ({HEXDIG}({HEXDIG}|_)*)
|
||||
OCTDIG [0-7]
|
||||
LETTER [a-z_]
|
||||
ID ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
|
||||
WHITE [ \t\n]
|
||||
TICK ("'"{WHITE}*)
|
||||
GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
|
||||
OPER ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
|
||||
|
||||
EXP (e[+-]{NUM10})
|
||||
POSEXP (e"+"?{NUM10})
|
||||
|
||||
%{
|
||||
#define NUMERAL_WIDTH 256
|
||||
#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
|
||||
|
||||
/* Temporary staging for numeric literals. */
|
||||
static char numbuf[NUMERAL_WIDTH];
|
||||
static void canonicalizeNumeral (char* s1, const char*);
|
||||
static int processInt (const char*, const char*, const char*);
|
||||
static int processReal (const char*);
|
||||
static int processId (const char*, int);
|
||||
static int processAttribute (const char*);
|
||||
static int find_dot_all (const char*);
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL static int yylex ( void )
|
||||
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
|
||||
if ( *lexptr == '\000' ) \
|
||||
(RESULT) = YY_NULL; \
|
||||
else \
|
||||
{ \
|
||||
*(BUF) = *lexptr; \
|
||||
(RESULT) = 1; \
|
||||
lexptr += 1; \
|
||||
}
|
||||
|
||||
static char *tempbuf = NULL;
|
||||
static int tempbufsize = 0;
|
||||
static int tempbuf_len;
|
||||
static struct block* left_block_context;
|
||||
|
||||
static void resize_tempbuf (unsigned int);
|
||||
|
||||
static void block_lookup (char*, char*);
|
||||
|
||||
static int name_lookup (char*, char*, int*);
|
||||
|
||||
static int find_dot_all (const char*);
|
||||
|
||||
%}
|
||||
|
||||
%s IN_STRING BEFORE_QUAL_QUOTE
|
||||
|
||||
%%
|
||||
|
||||
{WHITE} { }
|
||||
|
||||
"--".* { yyterminate(); }
|
||||
|
||||
{NUM10}{POSEXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1);
|
||||
}
|
||||
|
||||
{NUM10} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (NULL, numbuf, NULL);
|
||||
}
|
||||
|
||||
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (numbuf,
|
||||
strchr (numbuf, '#') + 1,
|
||||
strrchr(numbuf, '#') + 1);
|
||||
}
|
||||
|
||||
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (numbuf, strchr (numbuf, '#') + 1, NULL);
|
||||
}
|
||||
|
||||
"0x"{HEXDIG}+ {
|
||||
canonicalizeNumeral (numbuf, yytext+2);
|
||||
return processInt ("16#", numbuf, NULL);
|
||||
}
|
||||
|
||||
|
||||
{NUM10}"."{NUM10}{EXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processReal (numbuf);
|
||||
}
|
||||
|
||||
{NUM10}"."{NUM10} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processReal (numbuf);
|
||||
}
|
||||
|
||||
{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
|
||||
error ("Based real literals not implemented yet.");
|
||||
}
|
||||
|
||||
{NUM10}"#"{NUM16}"."{NUM16}"#" {
|
||||
error ("Based real literals not implemented yet.");
|
||||
}
|
||||
|
||||
<INITIAL>"'"({GRAPHIC}|\")"'" {
|
||||
yylval.typed_val.type = builtin_type_ada_char;
|
||||
yylval.typed_val.val = yytext[1];
|
||||
return CHARLIT;
|
||||
}
|
||||
|
||||
<INITIAL>"'[\""{HEXDIG}{2}"\"]'" {
|
||||
int v;
|
||||
yylval.typed_val.type = builtin_type_ada_char;
|
||||
sscanf (yytext+3, "%2x", &v);
|
||||
yylval.typed_val.val = v;
|
||||
return CHARLIT;
|
||||
}
|
||||
|
||||
\"{OPER}\"/{WHITE}*"(" { return processId (yytext, yyleng); }
|
||||
|
||||
<INITIAL>\" {
|
||||
tempbuf_len = 0;
|
||||
BEGIN IN_STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*\" {
|
||||
resize_tempbuf (yyleng+tempbuf_len);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-1);
|
||||
tempbuf_len += yyleng-1;
|
||||
yylval.sval.ptr = tempbuf;
|
||||
yylval.sval.length = tempbuf_len;
|
||||
BEGIN INITIAL;
|
||||
return STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-5+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
sscanf(yytext+yyleng-4, "%2x", &n);
|
||||
tempbuf[yyleng-6+tempbuf_len] = (char) n;
|
||||
tempbuf_len += yyleng-5;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\"\"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-4+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
tempbuf[yyleng-5+tempbuf_len] = '"';
|
||||
tempbuf_len += yyleng-4;
|
||||
}
|
||||
|
||||
if {
|
||||
while (*lexptr != 'i' && *lexptr != 'I')
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ADA KEYWORDS */
|
||||
|
||||
abs { return ABS; }
|
||||
and { return _AND_; }
|
||||
else { return ELSE; }
|
||||
in { return IN; }
|
||||
mod { return MOD; }
|
||||
new { return NEW; }
|
||||
not { return NOT; }
|
||||
null { return NULL_PTR; }
|
||||
or { return OR; }
|
||||
rem { return REM; }
|
||||
then { return THEN; }
|
||||
xor { return XOR; }
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
||||
{TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); }
|
||||
|
||||
/* PUNCTUATION */
|
||||
|
||||
"=>" { return ARROW; }
|
||||
".." { return DOTDOT; }
|
||||
"**" { return STARSTAR; }
|
||||
":=" { return ASSIGN; }
|
||||
"/=" { return NOTEQUAL; }
|
||||
"<=" { return LEQ; }
|
||||
">=" { return GEQ; }
|
||||
|
||||
<BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
|
||||
|
||||
[-&*+./:<>=|;\[\]] { return yytext[0]; }
|
||||
|
||||
"," { if (paren_depth == 0 && comma_terminates)
|
||||
{
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return ',';
|
||||
}
|
||||
|
||||
"(" { paren_depth += 1; return '('; }
|
||||
")" { if (paren_depth == 0)
|
||||
{
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
paren_depth -= 1;
|
||||
return ')';
|
||||
}
|
||||
}
|
||||
|
||||
"."{WHITE}*all { return DOT_ALL; }
|
||||
|
||||
"."{WHITE}*{ID} {
|
||||
processId (yytext+1, yyleng-1);
|
||||
return DOT_ID;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
|
||||
int all_posn = find_dot_all (yytext);
|
||||
int token_type, segments, k;
|
||||
int quote_follows;
|
||||
|
||||
if (all_posn == -1 && yytext[yyleng-1] == '\'')
|
||||
{
|
||||
quote_follows = 1;
|
||||
do {
|
||||
yyless (yyleng-1);
|
||||
} while (yytext[yyleng-1] == ' ');
|
||||
}
|
||||
else
|
||||
quote_follows = 0;
|
||||
|
||||
if (all_posn >= 0)
|
||||
yyless (all_posn);
|
||||
processId(yytext, yyleng);
|
||||
segments = name_lookup (ada_mangle (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr, &token_type);
|
||||
left_block_context = NULL;
|
||||
for (k = yyleng; segments > 0 && k > 0; k -= 1)
|
||||
{
|
||||
if (yytext[k-1] == '.')
|
||||
segments -= 1;
|
||||
quote_follows = 0;
|
||||
}
|
||||
if (k <= 0)
|
||||
error ("confused by name %s", yytext);
|
||||
yyless (k);
|
||||
if (quote_follows)
|
||||
BEGIN BEFORE_QUAL_QUOTE;
|
||||
return token_type;
|
||||
}
|
||||
|
||||
/* GDB EXPRESSION CONSTRUCTS */
|
||||
|
||||
|
||||
"'"[^']+"'"{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (ada_mangle (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
}
|
||||
|
||||
[{}@] { return yytext[0]; }
|
||||
|
||||
"$$" { yylval.lval = -1; return LAST; }
|
||||
"$$"{DIG}+ { yylval.lval = -atoi(yytext+2); return LAST; }
|
||||
"$" { yylval.lval = 0; return LAST; }
|
||||
"$"{DIG}+ { yylval.lval = atoi(yytext+1); return LAST; }
|
||||
|
||||
|
||||
/* REGISTERS AND GDB CONVENIENCE VARIABLES */
|
||||
|
||||
"$"({LETTER}|{DIG}|"$")+ {
|
||||
int c;
|
||||
for (c = 0; c < NUM_REGS; c++)
|
||||
if (REGISTER_NAME (c) &&
|
||||
strcmp (yytext + 1, REGISTER_NAME (c)) == 0)
|
||||
{
|
||||
yylval.lval = c;
|
||||
return REGNAME;
|
||||
}
|
||||
yylval.sval.ptr = yytext;
|
||||
yylval.sval.length = yyleng;
|
||||
yylval.ivar =
|
||||
lookup_internalvar (copy_name (yylval.sval) + 1);
|
||||
return INTERNAL_VARIABLE;
|
||||
}
|
||||
|
||||
/* CATCH-ALL ERROR CASE */
|
||||
|
||||
. { error ("Invalid character '%s' in expression.", yytext); }
|
||||
%%
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Initialize the lexer for processing new expression */
|
||||
void
|
||||
lexer_init (FILE* inp)
|
||||
{
|
||||
BEGIN INITIAL;
|
||||
yyrestart (inp);
|
||||
}
|
||||
|
||||
|
||||
/* Make sure that tempbuf points at an array at least N characters long. */
|
||||
|
||||
static void
|
||||
resize_tempbuf (n)
|
||||
unsigned int n;
|
||||
{
|
||||
if (tempbufsize < n)
|
||||
{
|
||||
tempbufsize = (n+63) & ~63;
|
||||
tempbuf = (char*) xrealloc (tempbuf, tempbufsize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
|
||||
|
||||
static void
|
||||
canonicalizeNumeral (s1,s2)
|
||||
char* s1;
|
||||
const char* s2;
|
||||
{
|
||||
for (; *s2 != '\000'; s2 += 1)
|
||||
{
|
||||
if (*s2 != '_')
|
||||
{
|
||||
*s1 = tolower(*s2);
|
||||
s1 += 1;
|
||||
}
|
||||
}
|
||||
s1[0] = '\000';
|
||||
}
|
||||
|
||||
#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
|
||||
|
||||
/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
|
||||
where 2 <= BASE <= 16. */
|
||||
|
||||
static int
|
||||
is_digit_in_base (digit, base)
|
||||
unsigned char digit;
|
||||
int base;
|
||||
{
|
||||
if (!isxdigit (digit))
|
||||
return 0;
|
||||
if (base <= 10)
|
||||
return (isdigit (digit) && digit < base + '0');
|
||||
else
|
||||
return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
|
||||
}
|
||||
|
||||
static int
|
||||
digit_to_int (c)
|
||||
unsigned char c;
|
||||
{
|
||||
if (isdigit (c))
|
||||
return c - '0';
|
||||
else
|
||||
return tolower (c) - 'a' + 10;
|
||||
}
|
||||
|
||||
/* As for strtoul, but for ULONGEST results. */
|
||||
ULONGEST
|
||||
strtoulst (num, trailer, base)
|
||||
const char *num;
|
||||
const char **trailer;
|
||||
int base;
|
||||
{
|
||||
unsigned int high_part;
|
||||
ULONGEST result;
|
||||
int i;
|
||||
unsigned char lim;
|
||||
|
||||
if (base < 2 || base > 16)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
lim = base - 1 + '0';
|
||||
|
||||
result = high_part = 0;
|
||||
for (i = 0; is_digit_in_base (num[i], base); i += 1)
|
||||
{
|
||||
result = result*base + digit_to_int (num[i]);
|
||||
high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN);
|
||||
result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
|
||||
if (high_part > 0xff)
|
||||
{
|
||||
errno = ERANGE;
|
||||
result = high_part = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trailer != NULL)
|
||||
*trailer = &num[i];
|
||||
|
||||
return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Interprets the prefix of NUM that consists of digits of the given BASE
|
||||
as an integer of that BASE, with the string EXP as an exponent.
|
||||
Puts value in yylval, and returns INT, if the string is valid. Causes
|
||||
an error if the number is improperly formated. BASE, if NULL, defaults
|
||||
to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */
|
||||
|
||||
static int
|
||||
processInt (base0, num0, exp0)
|
||||
const char* num0;
|
||||
const char* base0;
|
||||
const char* exp0;
|
||||
{
|
||||
ULONGEST result;
|
||||
long exp;
|
||||
int base;
|
||||
|
||||
char* trailer;
|
||||
|
||||
if (base0 == NULL)
|
||||
base = 10;
|
||||
else
|
||||
{
|
||||
base = strtol (base0, (char**) NULL, 10);
|
||||
if (base < 2 || base > 16)
|
||||
error ("Invalid base: %d.", base);
|
||||
}
|
||||
|
||||
if (exp0 == NULL)
|
||||
exp = 0;
|
||||
else
|
||||
exp = strtol(exp0, (char**) NULL, 10);
|
||||
|
||||
errno = 0;
|
||||
result = strtoulst (num0, &trailer, base);
|
||||
if (errno == ERANGE)
|
||||
error ("Integer literal out of range");
|
||||
if (isxdigit(*trailer))
|
||||
error ("Invalid digit `%c' in based literal", *trailer);
|
||||
|
||||
while (exp > 0)
|
||||
{
|
||||
if (result > (ULONG_MAX / base))
|
||||
error ("Integer literal out of range");
|
||||
result *= base;
|
||||
exp -= 1;
|
||||
}
|
||||
|
||||
if ((result >> (TARGET_INT_BIT-1)) == 0)
|
||||
yylval.typed_val.type = builtin_type_ada_int;
|
||||
else if ((result >> (TARGET_LONG_BIT-1)) == 0)
|
||||
yylval.typed_val.type = builtin_type_ada_long;
|
||||
else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0)
|
||||
{
|
||||
/* We have a number representable as an unsigned integer quantity.
|
||||
For consistency with the C treatment, we will treat it as an
|
||||
anonymous modular (unsigned) quantity. Alas, the types are such
|
||||
that we need to store .val as a signed quantity. Sorry
|
||||
for the mess, but C doesn't officially guarantee that a simple
|
||||
assignment does the trick (no, it doesn't; read the reference manual).
|
||||
*/
|
||||
yylval.typed_val.type = builtin_type_unsigned_long;
|
||||
if (result & LONGEST_SIGN)
|
||||
yylval.typed_val.val =
|
||||
(LONGEST) (result & ~LONGEST_SIGN)
|
||||
- (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
|
||||
else
|
||||
yylval.typed_val.val = (LONGEST) result;
|
||||
return INT;
|
||||
}
|
||||
else
|
||||
yylval.typed_val.type = builtin_type_ada_long_long;
|
||||
|
||||
yylval.typed_val.val = (LONGEST) result;
|
||||
return INT;
|
||||
}
|
||||
|
||||
static int
|
||||
processReal (num0)
|
||||
const char* num0;
|
||||
{
|
||||
if (sizeof (DOUBLEST) <= sizeof (float))
|
||||
sscanf (num0, "%g", &yylval.typed_val_float.dval);
|
||||
else if (sizeof (DOUBLEST) <= sizeof (double))
|
||||
sscanf (num0, "%lg", &yylval.typed_val_float.dval);
|
||||
else
|
||||
{
|
||||
#ifdef PRINTF_HAS_LONG_DOUBLE
|
||||
sscanf (num0, "%Lg", &yylval.typed_val_float.dval);
|
||||
#else
|
||||
/* Scan it into a double, then convert and assign it to the
|
||||
long double. This at least wins with values representable
|
||||
in the range of doubles. */
|
||||
double temp;
|
||||
sscanf (num0, "%lg", &temp);
|
||||
yylval.typed_val_float.dval = temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
yylval.typed_val_float.type = builtin_type_ada_float;
|
||||
if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT)
|
||||
yylval.typed_val_float.type = builtin_type_ada_double;
|
||||
if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)
|
||||
yylval.typed_val_float.type = builtin_type_ada_long_double;
|
||||
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
static int
|
||||
processId (name0, len)
|
||||
const char *name0;
|
||||
int len;
|
||||
{
|
||||
char* name = xmalloc (len + 11);
|
||||
int i0, i;
|
||||
|
||||
/* add_name_string_cleanup (name); */
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
while (len > 0 && isspace (name0[len-1]))
|
||||
len -= 1;
|
||||
i = i0 = 0;
|
||||
while (i0 < len)
|
||||
{
|
||||
if (isalnum (name0[i0]))
|
||||
{
|
||||
name[i] = tolower (name0[i0]);
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
else switch (name0[i0])
|
||||
{
|
||||
default:
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
break;
|
||||
case ' ': case '\t':
|
||||
i0 += 1;
|
||||
break;
|
||||
case '\'':
|
||||
i0 += 1;
|
||||
while (i0 < len && name0[i0] != '\'')
|
||||
{
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
i0 += 1;
|
||||
break;
|
||||
case '<':
|
||||
i0 += 1;
|
||||
while (i0 < len && name0[i0] != '>')
|
||||
{
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
i0 += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
name[i] = '\000';
|
||||
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = i;
|
||||
return NAME;
|
||||
}
|
||||
|
||||
static void
|
||||
block_lookup (name, err_name)
|
||||
char* name;
|
||||
char* err_name;
|
||||
{
|
||||
struct symbol** syms;
|
||||
struct block** blocks;
|
||||
int nsyms;
|
||||
struct symtab *symtab;
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_NAMESPACE, &syms, &blocks);
|
||||
if (left_block_context == NULL &&
|
||||
(nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK))
|
||||
symtab = lookup_symtab (name);
|
||||
else
|
||||
symtab = NULL;
|
||||
|
||||
if (symtab != NULL)
|
||||
left_block_context = yylval.bval =
|
||||
BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
else if (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK)
|
||||
{
|
||||
if (left_block_context == NULL)
|
||||
error ("No file or function \"%s\".", err_name);
|
||||
else
|
||||
error ("No function \"%s\" in specified context.", err_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0]);
|
||||
if (nsyms > 1)
|
||||
warning ("Function name \"%s\" ambiguous here", err_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up NAME0 (assumed to be mangled) as a name in VAR_NAMESPACE,
|
||||
setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is
|
||||
found. Try first the entire name, then the name without the last
|
||||
segment (i.e., after the last .id), etc., and return the number of
|
||||
segments that had to be removed to get a match. Calls error if no
|
||||
matches are found, using ERR_NAME in any error message. When
|
||||
exactly one symbol match is found, it is placed in yylval. */
|
||||
|
||||
static int
|
||||
name_lookup (name0, err_name, token_type)
|
||||
char* name0;
|
||||
char* err_name;
|
||||
int* token_type;
|
||||
{
|
||||
struct symbol** syms;
|
||||
struct block** blocks;
|
||||
struct type* type;
|
||||
int len0 = strlen (name0);
|
||||
char* name = savestring (name0, len0);
|
||||
int nsyms;
|
||||
int segments;
|
||||
|
||||
/* add_name_string_cleanup (name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = strlen (name);
|
||||
for (segments = 0; ; segments += 1)
|
||||
{
|
||||
struct type* preferred_type;
|
||||
int i, preferred_index;
|
||||
|
||||
if (left_block_context == NULL)
|
||||
nsyms = ada_lookup_symbol_list (name, expression_context_block,
|
||||
VAR_NAMESPACE, &syms, &blocks);
|
||||
else
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_NAMESPACE, &syms, &blocks);
|
||||
|
||||
/* Check for a type definition. */
|
||||
|
||||
/* Look for a symbol that doesn't denote void. This is (I think) a */
|
||||
/* temporary kludge to get around problems in GNAT output. */
|
||||
preferred_index = -1; preferred_type = NULL;
|
||||
for (i = 0; i < nsyms; i += 1)
|
||||
switch (SYMBOL_CLASS (syms[i]))
|
||||
{
|
||||
case LOC_TYPEDEF:
|
||||
if (ada_prefer_type (SYMBOL_TYPE (syms[i]), preferred_type))
|
||||
{
|
||||
preferred_index = i;
|
||||
preferred_type = SYMBOL_TYPE (syms[i]);
|
||||
}
|
||||
break;
|
||||
case LOC_REGISTER:
|
||||
case LOC_ARG:
|
||||
case LOC_REF_ARG:
|
||||
case LOC_REGPARM:
|
||||
case LOC_REGPARM_ADDR:
|
||||
case LOC_LOCAL:
|
||||
case LOC_LOCAL_ARG:
|
||||
case LOC_BASEREG:
|
||||
case LOC_BASEREG_ARG:
|
||||
goto NotType;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (preferred_type != NULL)
|
||||
{
|
||||
/* if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID)
|
||||
error ("`%s' matches only void type name(s)",
|
||||
ada_demangle (name));
|
||||
*/
|
||||
/* FIXME: ada_demangle should be defined in defs.h, and is located in ada-lang.c */
|
||||
/* else*/ if (ada_is_object_renaming (syms[preferred_index]))
|
||||
{
|
||||
yylval.ssym.sym = syms[preferred_index];
|
||||
*token_type = OBJECT_RENAMING;
|
||||
return segments;
|
||||
}
|
||||
else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index]))
|
||||
!= NULL)
|
||||
{
|
||||
int result;
|
||||
const char* renaming =
|
||||
ada_simple_renamed_entity (syms[preferred_index]);
|
||||
char* new_name = xmalloc (strlen (renaming) + len0
|
||||
- yylval.ssym.stoken.length + 1);
|
||||
/* add_name_string_cleanup (new_name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
strcpy (new_name, renaming);
|
||||
strcat (new_name, name0 + yylval.ssym.stoken.length);
|
||||
result = name_lookup (new_name, err_name, token_type);
|
||||
if (result > segments)
|
||||
error ("Confused by renamed symbol.");
|
||||
return result;
|
||||
}
|
||||
else if (segments == 0)
|
||||
{
|
||||
yylval.tval = preferred_type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (segments == 0)
|
||||
{
|
||||
type = lookup_primitive_typename (name);
|
||||
if (type == NULL && STREQ ("system__address", name))
|
||||
type = builtin_type_ada_system_address;
|
||||
if (type != NULL)
|
||||
{
|
||||
yylval.tval = type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NotType:
|
||||
if (nsyms == 1)
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = syms[0];
|
||||
yylval.ssym.msym = NULL;
|
||||
yylval.ssym.block = blocks[0];
|
||||
return segments;
|
||||
}
|
||||
else if (nsyms == 0) {
|
||||
int i;
|
||||
yylval.ssym.msym = ada_lookup_minimal_symbol (name);
|
||||
if (yylval.ssym.msym != NULL)
|
||||
{
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.block = NULL;
|
||||
*token_type = NAME;
|
||||
return segments;
|
||||
}
|
||||
|
||||
for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1)
|
||||
{
|
||||
if (name[i] == '.')
|
||||
{
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
else if (name[i] == '_' && name[i-1] == '_')
|
||||
{
|
||||
i -= 1;
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i <= 0)
|
||||
{
|
||||
if (!have_full_symbols () && !have_partial_symbols ()
|
||||
&& left_block_context == NULL)
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
if (left_block_context == NULL)
|
||||
error ("No definition of \"%s\" in current context.",
|
||||
err_name);
|
||||
else
|
||||
error ("No definition of \"%s\" in specified context.",
|
||||
err_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.msym = NULL;
|
||||
if (left_block_context == NULL)
|
||||
yylval.ssym.block = expression_context_block;
|
||||
else
|
||||
yylval.ssym.block = left_block_context;
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the position within STR of the '.' in a
|
||||
'.{WHITE}*all' component of a dotted name, or -1 if there is none. */
|
||||
static int
|
||||
find_dot_all (str)
|
||||
const char* str;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; str[i] != '\000'; i += 1)
|
||||
{
|
||||
if (str[i] == '.')
|
||||
{
|
||||
int i0 = i;
|
||||
do
|
||||
i += 1;
|
||||
while (isspace (str[i]));
|
||||
if (strcmp (str+i, "all") == 0
|
||||
&& ! isalnum (str[i+3]) && str[i+3] != '_')
|
||||
return i0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
|
||||
case. */
|
||||
|
||||
static int
|
||||
subseqMatch (subseq, str)
|
||||
const char* subseq;
|
||||
const char* str;
|
||||
{
|
||||
if (subseq[0] == '\0')
|
||||
return 1;
|
||||
else if (str[0] == '\0')
|
||||
return 0;
|
||||
else if (tolower (subseq[0]) == tolower (str[0]))
|
||||
return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
|
||||
else
|
||||
return subseqMatch (subseq, str+1);
|
||||
}
|
||||
|
||||
|
||||
static struct { const char* name; int code; }
|
||||
attributes[] = {
|
||||
{ "address", TICK_ADDRESS },
|
||||
{ "unchecked_access", TICK_ACCESS },
|
||||
{ "unrestricted_access", TICK_ACCESS },
|
||||
{ "access", TICK_ACCESS },
|
||||
{ "first", TICK_FIRST },
|
||||
{ "last", TICK_LAST },
|
||||
{ "length", TICK_LENGTH },
|
||||
{ "max", TICK_MAX },
|
||||
{ "min", TICK_MIN },
|
||||
{ "modulus", TICK_MODULUS },
|
||||
{ "pos", TICK_POS },
|
||||
{ "range", TICK_RANGE },
|
||||
{ "size", TICK_SIZE },
|
||||
{ "tag", TICK_TAG },
|
||||
{ "val", TICK_VAL },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
/* Return the syntactic code corresponding to the attribute name or
|
||||
abbreviation STR. */
|
||||
|
||||
static int
|
||||
processAttribute (str)
|
||||
const char* str;
|
||||
{
|
||||
int i, k;
|
||||
|
||||
for (i = 0; attributes[i].code != -1; i += 1)
|
||||
if (strcasecmp (str, attributes[i].name) == 0)
|
||||
return attributes[i].code;
|
||||
|
||||
for (i = 0, k = -1; attributes[i].code != -1; i += 1)
|
||||
if (subseqMatch (str, attributes[i].name))
|
||||
{
|
||||
if (k == -1)
|
||||
k = i;
|
||||
else
|
||||
error ("ambiguous attribute name: `%s'", str);
|
||||
}
|
||||
if (k == -1)
|
||||
error ("unrecognized attribute: `%s'", str);
|
||||
|
||||
return attributes[k].code;
|
||||
}
|
||||
|
||||
int
|
||||
yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
806
gdb/ada-tasks.c
806
gdb/ada-tasks.c
@@ -1,806 +0,0 @@
|
||||
/* file ada-tasks.c: Ada tasking control for GDB
|
||||
Copyright 1997 Free Software Foundation, Inc.
|
||||
Contributed by Ada Core Technologies, Inc
|
||||
.
|
||||
This file is part of GDB.
|
||||
|
||||
[$Id$]
|
||||
Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com>
|
||||
|
||||
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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "defs.h"
|
||||
#include "command.h"
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "inferior.h"
|
||||
#include "symtab.h"
|
||||
#include "target.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
#include "gregset.h"
|
||||
#endif
|
||||
|
||||
#include "ada-lang.h"
|
||||
|
||||
/* FIXME: move all this conditional compilation in description
|
||||
files or in configure.in */
|
||||
|
||||
#if defined (VXWORKS_TARGET)
|
||||
#define THREAD_TO_PID(tid,lwpid) (tid)
|
||||
|
||||
#elif defined (linux)
|
||||
#define THREAD_TO_PID(tid,lwpid) (0)
|
||||
|
||||
#elif (defined (sun) && defined (__SVR4))
|
||||
#define THREAD_TO_PID thread_to_pid
|
||||
|
||||
#elif defined (sgi) || defined (__WIN32__) || defined (hpux)
|
||||
#define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
|
||||
|
||||
#else
|
||||
#define THREAD_TO_PID(tid,lwpid) (0)
|
||||
#endif
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
#define THREAD_FETCH_REGISTERS dec_thread_fetch_registers
|
||||
#define GET_CURRENT_THREAD dec_thread_get_current_thread
|
||||
extern int dec_thread_get_registers (gdb_gregset_t *, gdb_fpregset_t *);
|
||||
#endif
|
||||
|
||||
#if defined (_AIX)
|
||||
#define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
|
||||
#define GET_CURRENT_THREAD aix_thread_get_current_thread
|
||||
#endif
|
||||
|
||||
#if defined(VXWORKS_TARGET)
|
||||
#define GET_CURRENT_THREAD() ((void*)inferior_pid)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
|
||||
#elif defined (sun) && defined (__SVR4)
|
||||
#define GET_CURRENT_THREAD solaris_thread_get_current_thread
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
extern void *GET_CURRENT_THREAD();
|
||||
|
||||
#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
|
||||
extern void *GET_CURRENT_THREAD();
|
||||
|
||||
#elif defined (__WIN32__) || defined (hpux)
|
||||
#define GET_CURRENT_THREAD() (inferior_pid)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
|
||||
#else
|
||||
#define GET_CURRENT_THREAD() (NULL)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
#endif
|
||||
|
||||
#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
|
||||
|
||||
#define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
|
||||
/* external declarations */
|
||||
|
||||
extern struct value* find_function_in_inferior (char *);
|
||||
|
||||
/* Global visible variables */
|
||||
|
||||
struct task_entry *task_list = NULL;
|
||||
int ada__tasks_check_symbol_table = 1;
|
||||
void *pthread_kern_addr = NULL;
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
gdb_gregset_t gregset_saved;
|
||||
gdb_fpregset_t fpregset_saved;
|
||||
#endif
|
||||
|
||||
/* The maximum number of tasks known to the Ada runtime */
|
||||
const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
|
||||
|
||||
/* the current task */
|
||||
int current_task = -1, current_task_id = -1, current_task_index;
|
||||
void *current_thread, *current_lwp;
|
||||
|
||||
char *ada_task_states[] =
|
||||
{
|
||||
"Unactivated",
|
||||
"Runnable",
|
||||
"Terminated",
|
||||
"Child Activation Wait",
|
||||
"Accept Statement",
|
||||
"Waiting on entry call",
|
||||
"Async Select Wait",
|
||||
"Delay Sleep",
|
||||
"Child Termination Wait",
|
||||
"Wait Child in Term Alt",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Asynchronous Hold"
|
||||
};
|
||||
|
||||
/* Global internal types */
|
||||
|
||||
static char *ada_long_task_states[] =
|
||||
{
|
||||
"Unactivated",
|
||||
"Runnable",
|
||||
"Terminated",
|
||||
"Waiting for child activation",
|
||||
"Blocked in accept statement",
|
||||
"Waiting on entry call",
|
||||
"Asynchronous Selective Wait",
|
||||
"Delay Sleep",
|
||||
"Waiting for children termination",
|
||||
"Waiting for children in terminate alternative",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Asynchronous Hold"
|
||||
};
|
||||
|
||||
/* Global internal variables */
|
||||
|
||||
static int highest_task_num = 0;
|
||||
int thread_support = 0; /* 1 if the thread library in use is supported */
|
||||
static int gdbtk_task_initialization = 0;
|
||||
|
||||
static int add_task_entry (p_task_id, index)
|
||||
void *p_task_id;
|
||||
int index;
|
||||
{
|
||||
struct task_entry *new_task_entry = NULL;
|
||||
struct task_entry *pt;
|
||||
|
||||
highest_task_num++;
|
||||
new_task_entry = xmalloc (sizeof (struct task_entry));
|
||||
new_task_entry->task_num = highest_task_num;
|
||||
new_task_entry->task_id = p_task_id;
|
||||
new_task_entry->known_tasks_index = index;
|
||||
new_task_entry->next_task = NULL;
|
||||
pt = task_list;
|
||||
if (pt)
|
||||
{
|
||||
while (pt->next_task)
|
||||
pt = pt->next_task;
|
||||
pt->next_task = new_task_entry;
|
||||
pt->stack_per = 0;
|
||||
}
|
||||
else task_list = new_task_entry;
|
||||
return new_task_entry->task_num;
|
||||
}
|
||||
|
||||
int
|
||||
get_entry_number (p_task_id)
|
||||
void *p_task_id;
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt != NULL)
|
||||
{
|
||||
if (pt->task_id == p_task_id)
|
||||
return pt->task_num;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct task_entry *get_thread_entry_vptr (thread)
|
||||
void *thread;
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt != NULL)
|
||||
{
|
||||
if (pt->thread == thread)
|
||||
return pt;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct task_entry *get_entry_vptr (p_task_num)
|
||||
int p_task_num;
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
if (pt->task_num == p_task_num)
|
||||
return pt;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_task_list ()
|
||||
{
|
||||
struct task_entry *pt, *old_pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
old_pt = pt;
|
||||
pt = pt->next_task;
|
||||
xfree (old_pt);
|
||||
};
|
||||
task_list = NULL;
|
||||
highest_task_num = 0;
|
||||
}
|
||||
|
||||
int valid_task_id (task)
|
||||
int task;
|
||||
{
|
||||
return get_entry_vptr (task) != NULL;
|
||||
}
|
||||
|
||||
void *get_self_id ()
|
||||
{
|
||||
struct value* val;
|
||||
void *self_id;
|
||||
int result;
|
||||
struct task_entry *ent;
|
||||
extern int do_not_insert_breakpoints;
|
||||
|
||||
#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
|
||||
if (thread_support)
|
||||
#endif
|
||||
{
|
||||
ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
|
||||
return ent ? ent->task_id : 0;
|
||||
}
|
||||
|
||||
/* FIXME: calling a function in the inferior with a multithreaded application
|
||||
is not reliable, so return NULL if there is no safe way to get the current
|
||||
task */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_current_task ()
|
||||
{
|
||||
int result;
|
||||
|
||||
/* FIXME: language_ada should be defined in defs.h */
|
||||
/* if (current_language->la_language != language_ada) return -1; */
|
||||
|
||||
result = get_entry_number (get_self_id ());
|
||||
|
||||
/* return -1 if not found */
|
||||
return result == 0 ? -1 : result;
|
||||
}
|
||||
|
||||
/* Print detailed information about specified task */
|
||||
|
||||
static void
|
||||
info_task (arg, from_tty)
|
||||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
void *temp_task;
|
||||
struct task_entry *pt, *pt2;
|
||||
void *self_id, *caller;
|
||||
struct task_fields atcb, atcb2;
|
||||
struct entry_call call;
|
||||
int bounds [2];
|
||||
char image [256];
|
||||
int num;
|
||||
|
||||
/* FIXME: language_ada should be defined in defs.h */
|
||||
/* if (current_language->la_language != language_ada)
|
||||
{
|
||||
printf_filtered ("The current language does not support tasks.\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
pt = get_entry_vptr (atoi (arg));
|
||||
if (pt == NULL)
|
||||
{
|
||||
printf_filtered ("Task %s not found.\n", arg);
|
||||
return;
|
||||
}
|
||||
|
||||
temp_task = pt->task_id;
|
||||
|
||||
/* read the atcb in the inferior */
|
||||
READ_MEMORY ((CORE_ADDR) temp_task, atcb);
|
||||
|
||||
/* print the Ada task id */
|
||||
printf_filtered ("Ada Task: %p\n", temp_task);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb.image.P_ARRAY != NULL) {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
|
||||
bounds [1] = EXTRACT_INT (bounds [1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
|
||||
(char*) &image, bounds [1]);
|
||||
printf_filtered ("Name: %.*s\n", bounds [1], image);
|
||||
}
|
||||
else printf_filtered ("<no name>\n");
|
||||
|
||||
/* print the thread id */
|
||||
|
||||
if ((long) pt->thread < 65536)
|
||||
printf_filtered ("Thread: %ld\n", (long int) pt->thread);
|
||||
else
|
||||
printf_filtered ("Thread: %p\n", pt->thread);
|
||||
|
||||
if ((long) pt->lwp != 0)
|
||||
{
|
||||
if ((long) pt->lwp < 65536)
|
||||
printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
|
||||
else
|
||||
printf_filtered ("LWP: %p\n", pt->lwp);
|
||||
}
|
||||
|
||||
/* print the parent gdb task id */
|
||||
num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
|
||||
if (num != 0)
|
||||
{
|
||||
printf_filtered ("Parent: %d", num);
|
||||
pt2 = get_entry_vptr (num);
|
||||
READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb2.image.P_ARRAY != NULL) {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
|
||||
bounds);
|
||||
bounds [1] = EXTRACT_INT (bounds [1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
|
||||
(char*) &image, bounds [1]);
|
||||
printf_filtered (" (%.*s)\n", bounds [1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("No parent\n");
|
||||
|
||||
/* print the base priority of the task */
|
||||
printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
|
||||
|
||||
/* print the current state of the task */
|
||||
|
||||
/* check if this task is accepting a rendezvous */
|
||||
if (atcb.call == NULL)
|
||||
caller = NULL;
|
||||
else {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
|
||||
caller = EXTRACT_ADDRESS (call.self);
|
||||
}
|
||||
|
||||
if (caller != NULL)
|
||||
{
|
||||
num = get_entry_number (caller);
|
||||
printf_filtered ("Accepting rendezvous with %d", num);
|
||||
|
||||
if (num != 0)
|
||||
{
|
||||
pt2 = get_entry_vptr (num);
|
||||
READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb2.image.P_ARRAY != NULL) {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
|
||||
bounds);
|
||||
bounds [1] = EXTRACT_INT (bounds [1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
|
||||
(char*) &image, bounds [1]);
|
||||
printf_filtered (" (%.*s)\n", bounds [1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("State: %s\n", ada_long_task_states [atcb.state]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* A useful function that shows the alignment of all the fields in the
|
||||
tasks_fields structure
|
||||
*/
|
||||
|
||||
print_align ()
|
||||
{
|
||||
struct task_fields tf;
|
||||
void *tf_base = &(tf);
|
||||
void *tf_state = &(tf.state);
|
||||
void *tf_entry_num = &(tf.entry_num);
|
||||
void *tf_parent = &(tf.parent);
|
||||
void *tf_priority = &(tf.priority);
|
||||
void *tf_current_priority = &(tf.current_priority);
|
||||
void *tf_image = &(tf.image);
|
||||
void *tf_call = &(tf.call);
|
||||
void *tf_thread = &(tf.thread);
|
||||
void *tf_lwp = &(tf.lwp);
|
||||
printf_filtered ("\n");
|
||||
printf_filtered ("(tf_base = 0x%x)\n", tf_base);
|
||||
printf_filtered ("task_fields.entry_num at %3d (0x%x)\n", tf_entry_num - tf_base, tf_entry_num);
|
||||
printf_filtered ("task_fields.state at %3d (0x%x)\n", tf_state - tf_base, tf_state);
|
||||
printf_filtered ("task_fields.parent at %3d (0x%x)\n", tf_parent - tf_base, tf_parent);
|
||||
printf_filtered ("task_fields.priority at %3d (0x%x)\n", tf_priority - tf_base, tf_priority);
|
||||
printf_filtered ("task_fields.current_priority at %3d (0x%x)\n", tf_current_priority - tf_base, tf_current_priority);
|
||||
printf_filtered ("task_fields.image at %3d (0x%x)\n", tf_image - tf_base, tf_image);
|
||||
printf_filtered ("task_fields.call at %3d (0x%x)\n", tf_call - tf_base, tf_call);
|
||||
printf_filtered ("task_fields.thread at %3d (0x%x)\n", tf_thread - tf_base, tf_thread);
|
||||
printf_filtered ("task_fields.lwp at %3d (0x%x)\n", tf_lwp - tf_base, tf_lwp);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print information about currently known tasks */
|
||||
|
||||
static void
|
||||
info_tasks (arg, from_tty)
|
||||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
struct value* val;
|
||||
int i, task_number, state;
|
||||
void *temp_task, *temp_tasks [MAX_NUMBER_OF_KNOWN_TASKS];
|
||||
struct task_entry *pt;
|
||||
void *self_id, *caller, *thread_id=NULL;
|
||||
struct task_fields atcb;
|
||||
struct entry_call call;
|
||||
int bounds [2];
|
||||
char image [256];
|
||||
int size;
|
||||
char car;
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
pthreadTeb_t thr;
|
||||
gdb_gregset_t regs;
|
||||
#endif
|
||||
|
||||
static struct symbol *sym;
|
||||
static struct minimal_symbol *msym;
|
||||
static void *known_tasks_addr = NULL;
|
||||
|
||||
int init_only = gdbtk_task_initialization;
|
||||
gdbtk_task_initialization = 0;
|
||||
|
||||
task_number = 0;
|
||||
|
||||
if (PIDGET(inferior_ptid) == 0)
|
||||
{
|
||||
printf_filtered ("The program is not being run under gdb. ");
|
||||
printf_filtered ("Use 'run' or 'attach' first.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ada__tasks_check_symbol_table)
|
||||
{
|
||||
thread_support = 0;
|
||||
#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
|
||||
defined (_AIX)
|
||||
thread_support = 1;
|
||||
#endif
|
||||
|
||||
msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
|
||||
if (msym != NULL)
|
||||
known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
|
||||
else
|
||||
#ifndef VXWORKS_TARGET
|
||||
return;
|
||||
#else
|
||||
{
|
||||
if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ada__tasks_check_symbol_table = 0;
|
||||
}
|
||||
|
||||
if (known_tasks_addr == NULL)
|
||||
return;
|
||||
|
||||
#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
|
||||
if (thread_support)
|
||||
#endif
|
||||
thread_id = GET_CURRENT_THREAD ();
|
||||
|
||||
/* then we get a list of tasks created */
|
||||
|
||||
init_task_list ();
|
||||
|
||||
READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
|
||||
|
||||
for (i=0; i<MAX_NUMBER_OF_KNOWN_TASKS; i++)
|
||||
{
|
||||
temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
|
||||
|
||||
if (temp_task != NULL)
|
||||
{
|
||||
task_number = get_entry_number (temp_task);
|
||||
if (task_number == 0)
|
||||
task_number = add_task_entry (temp_task, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return without printing anything if this function was called in
|
||||
order to init GDBTK tasking. */
|
||||
|
||||
if (init_only) return;
|
||||
|
||||
/* print the header */
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
printf_filtered
|
||||
(" ID TID P-ID Pri Stack %% State Name\n");
|
||||
#else
|
||||
printf_filtered (" ID TID P-ID Pri State Name\n");
|
||||
#endif
|
||||
|
||||
/* Now that we have a list of task id's, we can print them */
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
temp_task = pt->task_id;
|
||||
|
||||
/* read the atcb in the inferior */
|
||||
READ_MEMORY ((CORE_ADDR) temp_task, atcb);
|
||||
|
||||
/* store the thread id for future use */
|
||||
pt->thread = EXTRACT_ADDRESS (atcb.thread);
|
||||
|
||||
#if defined (linux)
|
||||
pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
|
||||
#else
|
||||
pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
|
||||
#endif
|
||||
|
||||
/* print a star if this task is the current one */
|
||||
if (thread_id)
|
||||
#if defined (__WIN32__) || defined (SGI) || defined (hpux)
|
||||
printf_filtered (pt->lwp == thread_id ? "*" : " ");
|
||||
#else
|
||||
printf_filtered (pt->thread == thread_id ? "*" : " ");
|
||||
#endif
|
||||
|
||||
/* print the gdb task id */
|
||||
printf_filtered ("%3d", pt->task_num);
|
||||
|
||||
/* print the Ada task id */
|
||||
#ifndef VXWORKS_TARGET
|
||||
printf_filtered (" %9lx", (long) temp_task);
|
||||
#else
|
||||
#ifdef TARGET_64
|
||||
printf_filtered (" %#9lx", (unsigned long)pt->thread & 0x3ffffffffff);
|
||||
#else
|
||||
printf_filtered (" %#9lx", (long)pt->thread);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* print the parent gdb task id */
|
||||
printf_filtered
|
||||
(" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
|
||||
|
||||
/* print the base priority of the task */
|
||||
printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
if (pt->task_num == 1 || atcb.state == Terminated)
|
||||
{
|
||||
printf_filtered (" Unknown");
|
||||
goto next;
|
||||
}
|
||||
|
||||
read_memory ((CORE_ADDR)atcb.thread, &thr, sizeof (thr));
|
||||
current_thread = atcb.thread;
|
||||
regs.regs [SP_REGNUM] = 0;
|
||||
if (dec_thread_get_registers (®s, NULL) == 0) {
|
||||
pt->stack_per = (100 * ((long)thr.__stack_base -
|
||||
regs.regs [SP_REGNUM])) / thr.__stack_size;
|
||||
/* if the thread is terminated but still there, the
|
||||
stack_base/size values are erroneous. Try to patch it */
|
||||
if (pt->stack_per < 0 || pt->stack_per > 100) pt->stack_per = 0;
|
||||
}
|
||||
|
||||
/* print information about stack space used in the thread */
|
||||
if (thr.__stack_size < 1024*1024)
|
||||
{
|
||||
size = thr.__stack_size / 1024;
|
||||
car = 'K';
|
||||
}
|
||||
else if (thr.__stack_size < 1024*1024*1024)
|
||||
{
|
||||
size = thr.__stack_size / 1024 / 1024;
|
||||
car = 'M';
|
||||
}
|
||||
else /* Who knows... */
|
||||
{
|
||||
size = thr.__stack_size / 1024 / 1024 / 1024;
|
||||
car = 'G';
|
||||
}
|
||||
printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
|
||||
next:
|
||||
#endif
|
||||
|
||||
/* print the current state of the task */
|
||||
|
||||
/* check if this task is accepting a rendezvous */
|
||||
if (atcb.call == NULL)
|
||||
caller = NULL;
|
||||
else {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
|
||||
caller = EXTRACT_ADDRESS (call.self);
|
||||
}
|
||||
|
||||
if (caller != NULL)
|
||||
printf_filtered (" Accepting RV with %-4d", get_entry_number (caller));
|
||||
else
|
||||
{
|
||||
state = atcb.state;
|
||||
#if defined (__WIN32__) || defined (SGI) || defined (hpux)
|
||||
if (state == Runnable && (thread_id && pt->lwp == thread_id))
|
||||
#else
|
||||
if (state == Runnable && (thread_id && pt->thread == thread_id))
|
||||
#endif
|
||||
/* Replace "Runnable" by "Running" if this is the current task */
|
||||
printf_filtered (" %-22s", "Running");
|
||||
else
|
||||
printf_filtered (" %-22s", ada_task_states [state]);
|
||||
}
|
||||
|
||||
/* finally, print the name of the task */
|
||||
if (atcb.image.P_ARRAY != NULL) {
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
|
||||
bounds [1] = EXTRACT_INT (bounds [1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
|
||||
(char*)&image, bounds [1]);
|
||||
printf_filtered (" %.*s\n", bounds [1], image);
|
||||
}
|
||||
else printf_filtered (" <no name>\n");
|
||||
|
||||
pt = pt->next_task;
|
||||
}
|
||||
}
|
||||
|
||||
/* Task list initialization for GDB-Tk. We basically use info_tasks()
|
||||
to initialize our variables, but abort that function before we
|
||||
actually print anything. */
|
||||
|
||||
int
|
||||
gdbtk_tcl_tasks_initialize ()
|
||||
{
|
||||
gdbtk_task_initialization = 1;
|
||||
info_tasks ("", gdb_stdout);
|
||||
|
||||
return (task_list != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
info_tasks_command (arg, from_tty)
|
||||
char *arg;
|
||||
int from_tty;
|
||||
{
|
||||
if (arg == NULL || *arg == '\000')
|
||||
info_tasks (arg, from_tty);
|
||||
else
|
||||
info_task (arg, from_tty);
|
||||
}
|
||||
|
||||
/* Switch from one thread to another. */
|
||||
|
||||
static void
|
||||
switch_to_thread (ptid_t ptid)
|
||||
|
||||
{
|
||||
if (ptid_equal (ptid, inferior_ptid))
|
||||
return;
|
||||
|
||||
inferior_ptid = ptid;
|
||||
flush_cached_frames ();
|
||||
registers_changed ();
|
||||
stop_pc = read_pc ();
|
||||
select_frame (get_current_frame ());
|
||||
}
|
||||
|
||||
/* Switch to a specified task. */
|
||||
|
||||
static int task_switch (tid, lwpid)
|
||||
void *tid, *lwpid;
|
||||
{
|
||||
int res = 0, pid;
|
||||
|
||||
if (thread_support)
|
||||
{
|
||||
flush_cached_frames ();
|
||||
|
||||
if (current_task != current_task_id)
|
||||
{
|
||||
res = THREAD_FETCH_REGISTERS ();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
supply_gregset (&gregset_saved);
|
||||
supply_fpregset (&fpregset_saved);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res == 0) stop_pc = read_pc();
|
||||
select_frame (get_current_frame ());
|
||||
return res;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void task_command (tidstr, from_tty)
|
||||
char *tidstr;
|
||||
int from_tty;
|
||||
{
|
||||
int num;
|
||||
struct task_entry *e;
|
||||
|
||||
if (!tidstr)
|
||||
error ("Please specify a task ID. Use the \"info tasks\" command to\n"
|
||||
"see the IDs of currently known tasks.");
|
||||
|
||||
num = atoi (tidstr);
|
||||
e = get_entry_vptr (num);
|
||||
|
||||
if (e == NULL)
|
||||
error ("Task ID %d not known. Use the \"info tasks\" command to\n"
|
||||
"see the IDs of currently known tasks.", num);
|
||||
|
||||
if (current_task_id == -1)
|
||||
{
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
fill_gregset (&gregset_saved, -1);
|
||||
fill_fpregset (&fpregset_saved, -1);
|
||||
#endif
|
||||
current_task_id = get_current_task ();
|
||||
}
|
||||
|
||||
current_task = num;
|
||||
current_task_index = e->known_tasks_index;
|
||||
current_thread = e->thread;
|
||||
current_lwp = e->lwp;
|
||||
if (task_switch (e->thread, e->lwp) == 0)
|
||||
{
|
||||
/* FIXME: find_printable_frame should be defined in frame.h, and
|
||||
implemented in ada-lang.c */
|
||||
/* find_printable_frame (selected_frame, frame_relative_level (selected_frame));*/
|
||||
printf_filtered ("[Switching to task %d]\n", num);
|
||||
print_stack_frame (selected_frame, frame_relative_level (selected_frame), 1);
|
||||
}
|
||||
else
|
||||
printf_filtered ("Unable to switch to task %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_tasks ()
|
||||
{
|
||||
static struct cmd_list_element *task_cmd_list = NULL;
|
||||
extern struct cmd_list_element *cmdlist;
|
||||
|
||||
add_info (
|
||||
"tasks", info_tasks_command,
|
||||
"Without argument: list all known Ada tasks, with status information.\n"
|
||||
"info tasks n: print detailed information of task n.\n");
|
||||
|
||||
add_prefix_cmd ("task", class_run, task_command,
|
||||
"Use this command to switch between tasks.\n\
|
||||
The new task ID must be currently known.", &task_cmd_list, "task ", 1,
|
||||
&cmdlist);
|
||||
}
|
||||
@@ -1,896 +0,0 @@
|
||||
/* Support for printing Ada types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "bfd.h" /* Binary File Description */
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "language.h"
|
||||
#include "demangle.h"
|
||||
#include "c-lang.h"
|
||||
#include "typeprint.h"
|
||||
#include "ada-lang.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int print_record_field_types (struct type *, struct type *,
|
||||
struct ui_file *, int, int);
|
||||
|
||||
static void print_array_type (struct type*, struct ui_file*, int, int);
|
||||
|
||||
static void print_choices (struct type*, int, struct ui_file*, struct type*);
|
||||
|
||||
static void print_range (struct type*, struct ui_file*);
|
||||
|
||||
static void print_range_bound (struct type*, char*, int*, struct ui_file*);
|
||||
|
||||
static void
|
||||
print_dynamic_range_bound (struct type*, const char*, int,
|
||||
const char*, struct ui_file*);
|
||||
|
||||
static void print_range_type_named (char*, struct ui_file*);
|
||||
|
||||
|
||||
|
||||
static char* name_buffer;
|
||||
static int name_buffer_len;
|
||||
|
||||
/* The (demangled) Ada name of TYPE. This value persists until the
|
||||
next call. */
|
||||
|
||||
static char*
|
||||
demangled_type_name (type)
|
||||
struct type *type;
|
||||
{
|
||||
if (ada_type_name (type) == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
char* raw_name = ada_type_name (type);
|
||||
char *s, *q;
|
||||
|
||||
if (name_buffer == NULL || name_buffer_len <= strlen (raw_name))
|
||||
{
|
||||
name_buffer_len = 16 + 2 * strlen (raw_name);
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_len);
|
||||
}
|
||||
strcpy (name_buffer, raw_name);
|
||||
|
||||
s = (char*) strstr (name_buffer, "___");
|
||||
if (s != NULL)
|
||||
*s = '\0';
|
||||
|
||||
s = name_buffer + strlen (name_buffer) - 1;
|
||||
while (s > name_buffer && (s[0] != '_' || s[-1] != '_'))
|
||||
s -= 1;
|
||||
|
||||
if (s == name_buffer)
|
||||
return name_buffer;
|
||||
|
||||
if (! islower (s[1]))
|
||||
return NULL;
|
||||
|
||||
for (s = q = name_buffer; *s != '\0'; q += 1)
|
||||
{
|
||||
if (s[0] == '_' && s[1] == '_')
|
||||
{
|
||||
*q = '.'; s += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*q = *s; s += 1;
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
return name_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print a description of a type in the format of a
|
||||
typedef for the current language.
|
||||
NEW is the new name for a type TYPE. */
|
||||
|
||||
void
|
||||
ada_typedef_print (type, new, stream)
|
||||
struct type *type;
|
||||
struct symbol *new;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
fprintf_filtered (stream, "type %.*s is ",
|
||||
ada_name_prefix_len (SYMBOL_SOURCE_NAME(new)),
|
||||
SYMBOL_SOURCE_NAME(new));
|
||||
type_print (type, "", stream, 1);
|
||||
}
|
||||
|
||||
/* Print range type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_range (type, stream)
|
||||
struct type* type;
|
||||
struct ui_file* stream;
|
||||
{
|
||||
struct type* target_type;
|
||||
target_type = TYPE_TARGET_TYPE (type);
|
||||
if (target_type == NULL)
|
||||
target_type = type;
|
||||
|
||||
switch (TYPE_CODE (target_type))
|
||||
{
|
||||
case TYPE_CODE_RANGE:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_BOOL:
|
||||
case TYPE_CODE_CHAR:
|
||||
case TYPE_CODE_ENUM:
|
||||
break;
|
||||
default:
|
||||
target_type = builtin_type_ada_int;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TYPE_NFIELDS (type) < 2)
|
||||
{
|
||||
/* A range needs at least 2 bounds to be printed. If there are less
|
||||
than 2, just print the type name instead of the range itself.
|
||||
This check handles cases such as characters, for example.
|
||||
|
||||
Note that if the name is not defined, then we don't print anything.
|
||||
*/
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (TYPE_NAME (type)),
|
||||
TYPE_NAME (type));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We extract the range type bounds respectively from the first element
|
||||
and the last element of the type->fields array */
|
||||
const LONGEST lower_bound = (LONGEST) TYPE_LOW_BOUND (type);
|
||||
const LONGEST upper_bound =
|
||||
(LONGEST) TYPE_FIELD_BITPOS (type, TYPE_NFIELDS (type) -1);
|
||||
|
||||
ada_print_scalar (target_type, lower_bound, stream);
|
||||
fprintf_filtered (stream, " .. ");
|
||||
ada_print_scalar (target_type, upper_bound, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the number or discriminant bound at BOUNDS+*N on STREAM, and
|
||||
set *N past the bound and its delimiter, if any. */
|
||||
|
||||
static void
|
||||
print_range_bound (type, bounds, n, stream)
|
||||
struct type* type;
|
||||
char* bounds;
|
||||
int* n;
|
||||
struct ui_file* stream;
|
||||
{
|
||||
LONGEST B;
|
||||
if (ada_scan_number (bounds, *n, &B, n))
|
||||
{
|
||||
ada_print_scalar (type, B, stream);
|
||||
if (bounds[*n] == '_')
|
||||
*n += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bound_len;
|
||||
char* bound = bounds + *n;
|
||||
char* pend;
|
||||
|
||||
pend = strstr (bound, "__");
|
||||
if (pend == NULL)
|
||||
*n += bound_len = strlen (bound);
|
||||
else
|
||||
{
|
||||
bound_len = pend - bound;
|
||||
*n += bound_len + 2;
|
||||
}
|
||||
fprintf_filtered (stream, "%.*s", bound_len, bound);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming NAME[0 .. NAME_LEN-1] is the name of a range type, print
|
||||
the value (if found) of the bound indicated by SUFFIX ("___L" or
|
||||
"___U") according to the ___XD conventions. */
|
||||
|
||||
static void
|
||||
print_dynamic_range_bound (type, name, name_len, suffix, stream)
|
||||
struct type* type;
|
||||
const char* name;
|
||||
int name_len;
|
||||
const char* suffix;
|
||||
struct ui_file* stream;
|
||||
{
|
||||
static char *name_buf = NULL;
|
||||
static size_t name_buf_len = 0;
|
||||
LONGEST B;
|
||||
int OK;
|
||||
|
||||
GROW_VECT (name_buf, name_buf_len, name_len + strlen (suffix) + 1);
|
||||
strncpy (name_buf, name, name_len);
|
||||
strcpy (name_buf + name_len, suffix);
|
||||
|
||||
B = get_int_var_value (name_buf, 0, &OK);
|
||||
if (OK)
|
||||
ada_print_scalar (type, B, stream);
|
||||
else
|
||||
fprintf_filtered (stream, "?");
|
||||
}
|
||||
|
||||
/* Print the range type named NAME. */
|
||||
|
||||
static void
|
||||
print_range_type_named (name, stream)
|
||||
char* name;
|
||||
struct ui_file* stream;
|
||||
{
|
||||
struct type *raw_type = ada_find_any_type (name);
|
||||
struct type *base_type;
|
||||
LONGEST low, high;
|
||||
char* subtype_info;
|
||||
|
||||
if (raw_type == NULL)
|
||||
base_type = builtin_type_int;
|
||||
else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
|
||||
base_type = TYPE_TARGET_TYPE (raw_type);
|
||||
else
|
||||
base_type = raw_type;
|
||||
|
||||
subtype_info = strstr (name, "___XD");
|
||||
if (subtype_info == NULL && raw_type == NULL)
|
||||
fprintf_filtered (stream, "? .. ?");
|
||||
else if (subtype_info == NULL)
|
||||
print_range (raw_type, stream);
|
||||
else
|
||||
{
|
||||
int prefix_len = subtype_info - name;
|
||||
char *bounds_str;
|
||||
int n;
|
||||
|
||||
subtype_info += 5;
|
||||
bounds_str = strchr (subtype_info, '_');
|
||||
n = 1;
|
||||
|
||||
if (*subtype_info == 'L')
|
||||
{
|
||||
print_range_bound (raw_type, bounds_str, &n, stream);
|
||||
subtype_info += 1;
|
||||
}
|
||||
else
|
||||
print_dynamic_range_bound (raw_type, name, prefix_len, "___L", stream);
|
||||
|
||||
fprintf_filtered (stream, " .. ");
|
||||
|
||||
if (*subtype_info == 'U')
|
||||
print_range_bound (raw_type, bounds_str, &n, stream);
|
||||
else
|
||||
print_dynamic_range_bound (raw_type, name, prefix_len, "___U", stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print enumerated type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_enum_type (type, stream)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
int len = TYPE_NFIELDS (type);
|
||||
int i, lastval;
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
wrap_here (" ");
|
||||
|
||||
lastval = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (i) fprintf_filtered (stream, ", ");
|
||||
wrap_here (" ");
|
||||
fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
|
||||
if (lastval != TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
fprintf_filtered (stream, " => %d", TYPE_FIELD_BITPOS (type, i));
|
||||
lastval = TYPE_FIELD_BITPOS (type, i);
|
||||
}
|
||||
lastval += 1;
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
/* Print representation of Ada fixed-point type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_fixed_point_type (type, stream)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
DOUBLEST delta = ada_delta (type);
|
||||
DOUBLEST small = ada_fixed_to_float (type, 1.0);
|
||||
|
||||
if (delta < 0.0)
|
||||
fprintf_filtered (stream, "delta ??");
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "delta %g", (double) delta);
|
||||
if (delta != small)
|
||||
fprintf_filtered (stream, " <'small = %g>", (double) small);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print representation of special VAX floating-point type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_vax_floating_point_type (type, stream)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
fprintf_filtered (stream, "<float format %c>",
|
||||
ada_vax_float_type_suffix (type));
|
||||
}
|
||||
|
||||
/* Print simple (constrained) array type TYPE on STREAM. LEVEL is the
|
||||
recursion (indentation) level, in case the element type itself has
|
||||
nested structure, and SHOW is the number of levels of internal
|
||||
structure to show (see ada_print_type). */
|
||||
|
||||
static void
|
||||
print_array_type (type, stream, show, level)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
int bitsize;
|
||||
int n_indices;
|
||||
|
||||
bitsize = 0;
|
||||
fprintf_filtered (stream, "array (");
|
||||
|
||||
n_indices = -1;
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, "...");
|
||||
else
|
||||
{
|
||||
if (ada_is_packed_array_type (type))
|
||||
type = ada_coerce_to_simple_array_type (type);
|
||||
if (ada_is_simple_array (type))
|
||||
{
|
||||
struct type* range_desc_type =
|
||||
ada_find_parallel_type (type, "___XA");
|
||||
struct type* arr_type;
|
||||
|
||||
bitsize = 0;
|
||||
if (range_desc_type == NULL)
|
||||
{
|
||||
for (arr_type = type; TYPE_CODE (arr_type) == TYPE_CODE_ARRAY;
|
||||
arr_type = TYPE_TARGET_TYPE (arr_type))
|
||||
{
|
||||
if (arr_type != type)
|
||||
fprintf_filtered (stream, ", ");
|
||||
print_range (TYPE_INDEX_TYPE (arr_type), stream);
|
||||
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
|
||||
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
n_indices = TYPE_NFIELDS (range_desc_type);
|
||||
for (k = 0, arr_type = type;
|
||||
k < n_indices;
|
||||
k += 1, arr_type = TYPE_TARGET_TYPE (arr_type))
|
||||
{
|
||||
if (k > 0)
|
||||
fprintf_filtered (stream, ", ");
|
||||
print_range_type_named (TYPE_FIELD_NAME (range_desc_type, k),
|
||||
stream);
|
||||
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
|
||||
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, i0;
|
||||
for (i = i0 = ada_array_arity (type); i > 0; i -= 1)
|
||||
fprintf_filtered (stream, "%s<>", i == i0 ? "" : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, ") of ");
|
||||
wrap_here ("");
|
||||
ada_print_type (ada_array_element_type (type, n_indices), "", stream,
|
||||
show == 0 ? 0 : show-1, level+1);
|
||||
if (bitsize > 0)
|
||||
fprintf_filtered (stream, " <packed: %d-bit elements>", bitsize);
|
||||
}
|
||||
|
||||
/* Print the choices encoded by field FIELD_NUM of variant-part TYPE on
|
||||
STREAM, assuming the VAL_TYPE is the type of the values. */
|
||||
|
||||
static void
|
||||
print_choices (type, field_num, stream, val_type)
|
||||
struct type *type;
|
||||
int field_num;
|
||||
struct ui_file *stream;
|
||||
struct type *val_type;
|
||||
{
|
||||
int have_output;
|
||||
int p;
|
||||
const char* name = TYPE_FIELD_NAME (type, field_num);
|
||||
|
||||
have_output = 0;
|
||||
|
||||
/* Skip over leading 'V': NOTE soon to be obsolete. */
|
||||
if (name[0] == 'V')
|
||||
{
|
||||
if (! ada_scan_number (name, 1, NULL, &p))
|
||||
goto Huh;
|
||||
}
|
||||
else
|
||||
p = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (name[p])
|
||||
{
|
||||
default:
|
||||
return;
|
||||
case 'S':
|
||||
case 'R':
|
||||
case 'O':
|
||||
if (have_output)
|
||||
fprintf_filtered (stream, " | ");
|
||||
have_output = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (name[p])
|
||||
{
|
||||
case 'S':
|
||||
{
|
||||
LONGEST W;
|
||||
if (! ada_scan_number (name, p + 1, &W, &p))
|
||||
goto Huh;
|
||||
ada_print_scalar (val_type, W, stream);
|
||||
break;
|
||||
}
|
||||
case 'R':
|
||||
{
|
||||
LONGEST L, U;
|
||||
if (! ada_scan_number (name, p + 1, &L, &p)
|
||||
|| name[p] != 'T'
|
||||
|| ! ada_scan_number (name, p + 1, &U, &p))
|
||||
goto Huh;
|
||||
ada_print_scalar (val_type, L, stream);
|
||||
fprintf_filtered (stream, " .. ");
|
||||
ada_print_scalar (val_type, U, stream);
|
||||
break;
|
||||
}
|
||||
case 'O':
|
||||
fprintf_filtered (stream, "others");
|
||||
p += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Huh:
|
||||
fprintf_filtered (stream, "??");
|
||||
|
||||
}
|
||||
|
||||
/* Assuming that field FIELD_NUM of TYPE is a VARIANTS field whose
|
||||
discriminant is contained in OUTER_TYPE, print its variants on STREAM.
|
||||
LEVEL is the recursion
|
||||
(indentation) level, in case any of the fields themselves have
|
||||
nested structure, and SHOW is the number of levels of internal structure
|
||||
to show (see ada_print_type). For this purpose, fields nested in a
|
||||
variant part are taken to be at the same level as the fields
|
||||
immediately outside the variant part. */
|
||||
|
||||
static void
|
||||
print_variant_clauses (type, field_num, outer_type, stream, show, level)
|
||||
struct type *type;
|
||||
int field_num;
|
||||
struct type *outer_type;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
int i;
|
||||
struct type *var_type;
|
||||
struct type *discr_type;
|
||||
|
||||
var_type = TYPE_FIELD_TYPE (type, field_num);
|
||||
discr_type = ada_variant_discrim_type (var_type, outer_type);
|
||||
|
||||
if (TYPE_CODE (var_type) == TYPE_CODE_PTR)
|
||||
{
|
||||
var_type = TYPE_TARGET_TYPE (var_type);
|
||||
if (TYPE_FLAGS (var_type) & TYPE_FLAG_STUB)
|
||||
{
|
||||
var_type = ada_find_parallel_type (var_type, "___XVU");
|
||||
if (var_type == NULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (var_type); i += 1)
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*swhen ", level + 4, "");
|
||||
print_choices (var_type, i, stream, discr_type);
|
||||
fprintf_filtered (stream, " =>");
|
||||
if (print_record_field_types (TYPE_FIELD_TYPE (var_type, i),
|
||||
outer_type, stream, show, level+4) <= 0)
|
||||
fprintf_filtered (stream, " null;");
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming that field FIELD_NUM of TYPE is a variant part whose
|
||||
discriminants are contained in OUTER_TYPE, print a description of it
|
||||
on STREAM. LEVEL is the recursion (indentation) level, in case any of
|
||||
the fields themselves have nested structure, and SHOW is the number of
|
||||
levels of internal structure to show (see ada_print_type). For this
|
||||
purpose, fields nested in a variant part are taken to be at the same
|
||||
level as the fields immediately outside the variant part. */
|
||||
|
||||
static void
|
||||
print_variant_part (type, field_num, outer_type, stream, show, level)
|
||||
struct type *type;
|
||||
int field_num;
|
||||
struct type *outer_type;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*scase %s is", level + 4, "",
|
||||
ada_variant_discrim_name
|
||||
(TYPE_FIELD_TYPE (type, field_num)));
|
||||
print_variant_clauses (type, field_num, outer_type, stream, show, level + 4);
|
||||
fprintf_filtered (stream, "\n%*send case;", level + 4, "");
|
||||
}
|
||||
|
||||
/* Print a description on STREAM of the fields in record type TYPE, whose
|
||||
discriminants are in OUTER_TYPE. LEVEL is the recursion (indentation)
|
||||
level, in case any of the fields themselves have nested structure,
|
||||
and SHOW is the number of levels of internal structure to show
|
||||
(see ada_print_type). Does not print parent type information of TYPE.
|
||||
Returns 0 if no fields printed, -1 for an incomplete type, else > 0.
|
||||
Prints each field beginning on a new line, but does not put a new line at
|
||||
end. */
|
||||
|
||||
static int
|
||||
print_record_field_types (type, outer_type, stream, show, level)
|
||||
struct type *type;
|
||||
struct type *outer_type;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
int len, i, flds;
|
||||
|
||||
flds = 0;
|
||||
len = TYPE_NFIELDS (type);
|
||||
|
||||
if (len == 0 && (TYPE_FLAGS (type) & TYPE_FLAG_STUB) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
QUIT;
|
||||
|
||||
if (ada_is_parent_field (type, i)
|
||||
|| ada_is_ignored_field (type, i))
|
||||
;
|
||||
else if (ada_is_wrapper_field (type, i))
|
||||
flds += print_record_field_types (TYPE_FIELD_TYPE (type, i), type,
|
||||
stream, show, level);
|
||||
else if (ada_is_variant_part (type, i))
|
||||
{
|
||||
print_variant_part (type, i, outer_type, stream, show, level);
|
||||
flds = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
flds += 1;
|
||||
fprintf_filtered (stream, "\n%*s", level + 4, "");
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
fprintf_filtered (stream, ";");
|
||||
}
|
||||
}
|
||||
|
||||
return flds;
|
||||
}
|
||||
|
||||
/* Print record type TYPE on STREAM. LEVEL is the recursion (indentation)
|
||||
level, in case the element type itself has nested structure, and SHOW is
|
||||
the number of levels of internal structure to show (see ada_print_type). */
|
||||
|
||||
static void
|
||||
print_record_type (type0, stream, show, level)
|
||||
struct type* type0;
|
||||
struct ui_file* stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
struct type* parent_type;
|
||||
struct type* type;
|
||||
|
||||
type = type0;
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
|
||||
{
|
||||
struct type* type1 = ada_find_parallel_type (type, "___XVE");
|
||||
if (type1 != NULL)
|
||||
type = type1;
|
||||
}
|
||||
|
||||
parent_type = ada_parent_type (type);
|
||||
if (ada_type_name (parent_type) != NULL)
|
||||
fprintf_filtered (stream, "new %s with ",
|
||||
demangled_type_name (parent_type));
|
||||
else if (parent_type == NULL && ada_is_tagged_type (type))
|
||||
fprintf_filtered (stream, "tagged ");
|
||||
|
||||
fprintf_filtered (stream, "record");
|
||||
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, " ... end record");
|
||||
else
|
||||
{
|
||||
int flds;
|
||||
|
||||
flds = 0;
|
||||
if (parent_type != NULL && ada_type_name (parent_type) == NULL)
|
||||
flds += print_record_field_types (parent_type, parent_type,
|
||||
stream, show, level);
|
||||
flds += print_record_field_types (type, type, stream, show, level);
|
||||
|
||||
if (flds > 0)
|
||||
fprintf_filtered (stream, "\n%*send record", level, "");
|
||||
else if (flds < 0)
|
||||
fprintf_filtered (stream, " <incomplete type> end record");
|
||||
else
|
||||
fprintf_filtered (stream, " null; end record");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the unchecked union type TYPE in something resembling Ada
|
||||
format on STREAM. LEVEL is the recursion (indentation) level
|
||||
in case the element type itself has nested structure, and SHOW is the
|
||||
number of levels of internal structure to show (see ada_print_type). */
|
||||
static void
|
||||
print_unchecked_union_type (struct type* type, struct ui_file* stream,
|
||||
int show, int level)
|
||||
{
|
||||
fprintf_filtered (stream, "record (?) is");
|
||||
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, " ... end record");
|
||||
else if (TYPE_NFIELDS (type) == 0)
|
||||
fprintf_filtered (stream, " null; end record");
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf_filtered (stream, "\n%*scase ? is",
|
||||
level+4, "");
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (type); i += 1)
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*swhen ? =>\n%*s", level+8, "",
|
||||
level+12, "");
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 12);
|
||||
fprintf_filtered (stream, ";");
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, "\n%*send case;\n%*send record",
|
||||
level+4, "", level, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Print function or procedure type TYPE on STREAM. Make it a header
|
||||
for function or procedure NAME if NAME is not null. */
|
||||
|
||||
static void
|
||||
print_func_type (type, stream, name)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
char* name;
|
||||
{
|
||||
int i, len = TYPE_NFIELDS (type);
|
||||
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
|
||||
fprintf_filtered (stream, "procedure");
|
||||
else
|
||||
fprintf_filtered (stream, "function");
|
||||
|
||||
if (name != NULL && name[0] != '\0')
|
||||
fprintf_filtered (stream, " %s", name);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
fprintf_filtered (stream, " (");
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
fputs_filtered ("; ", stream);
|
||||
wrap_here (" ");
|
||||
}
|
||||
fprintf_filtered (stream, "a%d: ", i+1);
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, " return ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print a description of a type TYPE0.
|
||||
Output goes to STREAM (via stdio).
|
||||
If VARSTRING is a non-empty string, print as an Ada variable/field
|
||||
declaration.
|
||||
SHOW+1 is the maximum number of levels of internal type structure
|
||||
to show (this applies to record types, enumerated types, and
|
||||
array types).
|
||||
SHOW is the number of levels of internal type structure to show
|
||||
when there is a type name for the SHOWth deepest level (0th is
|
||||
outer level).
|
||||
When SHOW<0, no inner structure is shown.
|
||||
LEVEL indicates level of recursion (for nested definitions). */
|
||||
|
||||
void
|
||||
ada_print_type (type0, varstring, stream, show, level)
|
||||
struct type* type0;
|
||||
char* varstring;
|
||||
struct ui_file* stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
enum type_code code;
|
||||
int demangled_args;
|
||||
struct type* type = ada_completed_type (ada_get_base_type (type0));
|
||||
char* type_name = demangled_type_name (type);
|
||||
int is_var_decl = (varstring != NULL && varstring[0] != '\0');
|
||||
|
||||
if (type == NULL)
|
||||
{
|
||||
if (is_var_decl)
|
||||
fprintf_filtered (stream, "%.*s: ",
|
||||
ada_name_prefix_len(varstring),
|
||||
varstring);
|
||||
fprintf_filtered (stream, "<null type?>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (show > 0)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (is_var_decl && TYPE_CODE (type) != TYPE_CODE_FUNC)
|
||||
fprintf_filtered (stream, "%.*s: ",
|
||||
ada_name_prefix_len (varstring), varstring);
|
||||
|
||||
if (type_name != NULL && show <= 0)
|
||||
{
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (type_name), type_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ada_is_aligner_type (type))
|
||||
ada_print_type (ada_aligned_type (type), "", stream, show, level);
|
||||
else if (ada_is_packed_array_type (type))
|
||||
print_array_type (type, stream, show, level);
|
||||
else
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
default:
|
||||
fprintf_filtered (stream, "<");
|
||||
c_print_type (type, "", stream, show, level);
|
||||
fprintf_filtered (stream, ">");
|
||||
break;
|
||||
case TYPE_CODE_PTR:
|
||||
fprintf_filtered (stream, "access ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show,
|
||||
level);
|
||||
break;
|
||||
case TYPE_CODE_REF:
|
||||
fprintf_filtered (stream, "<ref> ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show,
|
||||
level);
|
||||
break;
|
||||
case TYPE_CODE_ARRAY:
|
||||
print_array_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_INT:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
print_fixed_point_type (type, stream);
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
print_vax_floating_point_type (type, stream);
|
||||
else
|
||||
{
|
||||
char* name = ada_type_name (type);
|
||||
if (! ada_is_range_type_name (name))
|
||||
fprintf_filtered (stream, "<%d-byte integer>", TYPE_LENGTH (type));
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "range ");
|
||||
print_range_type_named (name, stream);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_RANGE:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
print_fixed_point_type (type, stream);
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
print_vax_floating_point_type (type, stream);
|
||||
else if (ada_is_modular_type (type))
|
||||
fprintf_filtered (stream, "mod %ld", (long) ada_modulus (type));
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "range ");
|
||||
print_range (type, stream);
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_FLT:
|
||||
fprintf_filtered (stream, "<%d-byte float>", TYPE_LENGTH (type));
|
||||
break;
|
||||
case TYPE_CODE_ENUM:
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, "(...)");
|
||||
else
|
||||
print_enum_type (type, stream);
|
||||
break;
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (ada_is_array_descriptor (type))
|
||||
print_array_type (type, stream, show, level);
|
||||
else if (ada_is_bogus_array_descriptor (type))
|
||||
fprintf_filtered (stream, "array (?) of ? (<mal-formed descriptor>)");
|
||||
else
|
||||
print_record_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_UNION:
|
||||
print_unchecked_union_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_FUNC:
|
||||
print_func_type (type, stream, varstring);
|
||||
break;
|
||||
}
|
||||
}
|
||||
1058
gdb/ada-valprint.c
1058
gdb/ada-valprint.c
File diff suppressed because it is too large
Load Diff
1492
gdb/aix-thread.c
1492
gdb/aix-thread.c
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
/* Target-dependent code for GNU/Linux on Alpha.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
/* Under GNU/Linux, signal handler invocations can be identified by the
|
||||
designated code sequence that is used to return from a signal
|
||||
handler. In particular, the return address of a signal handler
|
||||
points to the following sequence (the first instruction is quadword
|
||||
aligned):
|
||||
|
||||
bis $30,$30,$16
|
||||
addq $31,0x67,$0
|
||||
call_pal callsys
|
||||
|
||||
Each instruction has a unique encoding, so we simply attempt to
|
||||
match the instruction the pc is pointing to with any of the above
|
||||
instructions. If there is a hit, we know the offset to the start
|
||||
of the designated sequence and can then check whether we really are
|
||||
executing in a designated sequence. If not, -1 is returned,
|
||||
otherwise the offset from the start of the desingated sequence is
|
||||
returned.
|
||||
|
||||
There is a slight chance of false hits: code could jump into the
|
||||
middle of the designated sequence, in which case there is no
|
||||
guarantee that we are in the middle of a sigreturn syscall. Don't
|
||||
think this will be a problem in praxis, though. */
|
||||
LONGEST
|
||||
alpha_linux_sigtramp_offset (CORE_ADDR pc)
|
||||
{
|
||||
unsigned int i[3], w;
|
||||
long off;
|
||||
|
||||
if (read_memory_nobpt (pc, (char *) &w, 4) != 0)
|
||||
return -1;
|
||||
|
||||
off = -1;
|
||||
switch (w)
|
||||
{
|
||||
case 0x47de0410:
|
||||
off = 0;
|
||||
break; /* bis $30,$30,$16 */
|
||||
case 0x43ecf400:
|
||||
off = 4;
|
||||
break; /* addq $31,0x67,$0 */
|
||||
case 0x00000083:
|
||||
off = 8;
|
||||
break; /* call_pal callsys */
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
pc -= off;
|
||||
if (pc & 0x7)
|
||||
{
|
||||
/* designated sequence is not quadword aligned */
|
||||
return -1;
|
||||
}
|
||||
if (read_memory_nobpt (pc, (char *) i, sizeof (i)) != 0)
|
||||
return -1;
|
||||
|
||||
if (i[0] == 0x47de0410 && i[1] == 0x43ecf400 && i[2] == 0x00000083)
|
||||
return off;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_linux_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
return (alpha_linux_sigtramp_offset (pc) >= 0);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_linux_sigcontext_addr (struct frame_info *frame)
|
||||
{
|
||||
return (frame->frame - 0x298); /* sizeof(struct sigcontext) */
|
||||
}
|
||||
|
||||
static void
|
||||
alpha_linux_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alpha_linux_pc_in_sigtramp);
|
||||
|
||||
tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset;
|
||||
tdep->sigcontext_addr = alpha_linux_sigcontext_addr;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alpha_linux_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_LINUX,
|
||||
alpha_linux_init_abi);
|
||||
}
|
||||
278
gdb/alpha-nat.c
278
gdb/alpha-nat.c
@@ -1,278 +0,0 @@
|
||||
/* Low level Alpha interface, for GDB when running native.
|
||||
Copyright 1993, 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#ifdef __linux__
|
||||
#include <asm/reg.h>
|
||||
#include <alpha/ptrace.h>
|
||||
#else
|
||||
#include <alpha/coreregs.h>
|
||||
#endif
|
||||
#include <sys/user.h>
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
||||
static void fetch_osf_core_registers (char *, unsigned, int, CORE_ADDR);
|
||||
static void fetch_elf_core_registers (char *, unsigned, int, CORE_ADDR);
|
||||
|
||||
/* Extract the register values out of the core file and store
|
||||
them where `read_register' will find them.
|
||||
|
||||
CORE_REG_SECT points to the register values themselves, read into memory.
|
||||
CORE_REG_SIZE is the size of that area.
|
||||
WHICH says which set of registers we are handling (0 = int, 2 = float
|
||||
on machines where they are discontiguous).
|
||||
REG_ADDR is the offset from u.u_ar0 to the register values relative to
|
||||
core_reg_sect. This is used with old-fashioned core files to
|
||||
locate the registers in a large upage-plus-stack ".reg" section.
|
||||
Original upage address X is at location core_reg_sect+x+reg_addr.
|
||||
*/
|
||||
|
||||
static void
|
||||
fetch_osf_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR reg_addr)
|
||||
{
|
||||
register int regno;
|
||||
register int addr;
|
||||
int bad_reg = -1;
|
||||
|
||||
/* Table to map a gdb regnum to an index in the core register
|
||||
section. The floating point register values are garbage in
|
||||
OSF/1.2 core files. OSF5 uses different names for the register
|
||||
enum list, need to handle two cases. The actual values are the
|
||||
same. */
|
||||
static int core_reg_mapping[ALPHA_NUM_REGS] =
|
||||
{
|
||||
#ifdef NCF_REGS
|
||||
#define EFL NCF_REGS
|
||||
CF_V0, CF_T0, CF_T1, CF_T2, CF_T3, CF_T4, CF_T5, CF_T6,
|
||||
CF_T7, CF_S0, CF_S1, CF_S2, CF_S3, CF_S4, CF_S5, CF_S6,
|
||||
CF_A0, CF_A1, CF_A2, CF_A3, CF_A4, CF_A5, CF_T8, CF_T9,
|
||||
CF_T10, CF_T11, CF_RA, CF_T12, CF_AT, CF_GP, CF_SP, -1,
|
||||
EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
|
||||
EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
|
||||
EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
|
||||
EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
|
||||
CF_PC, -1
|
||||
#else
|
||||
#define EFL (EF_SIZE / 8)
|
||||
EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
|
||||
EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
|
||||
EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
|
||||
EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
|
||||
EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
|
||||
EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
|
||||
EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
|
||||
EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
|
||||
EF_PC, -1
|
||||
#endif
|
||||
};
|
||||
static char zerobuf[ALPHA_MAX_REGISTER_RAW_SIZE] =
|
||||
{0};
|
||||
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
if (CANNOT_FETCH_REGISTER (regno))
|
||||
{
|
||||
supply_register (regno, zerobuf);
|
||||
continue;
|
||||
}
|
||||
addr = 8 * core_reg_mapping[regno];
|
||||
if (addr < 0 || addr >= core_reg_size)
|
||||
{
|
||||
if (bad_reg < 0)
|
||||
bad_reg = regno;
|
||||
}
|
||||
else
|
||||
{
|
||||
supply_register (regno, core_reg_sect + addr);
|
||||
}
|
||||
}
|
||||
if (bad_reg >= 0)
|
||||
{
|
||||
error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_elf_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR reg_addr)
|
||||
{
|
||||
if (core_reg_size < 32 * 8)
|
||||
{
|
||||
error ("Core file register section too small (%u bytes).", core_reg_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (which == 2)
|
||||
{
|
||||
/* The FPU Registers. */
|
||||
memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31 * 8);
|
||||
memset (®isters[REGISTER_BYTE (FP0_REGNUM + 31)], 0, 8);
|
||||
memset (®ister_valid[FP0_REGNUM], 1, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The General Registers. */
|
||||
memcpy (®isters[REGISTER_BYTE (ALPHA_V0_REGNUM)], core_reg_sect,
|
||||
31 * 8);
|
||||
memcpy (®isters[REGISTER_BYTE (PC_REGNUM)], core_reg_sect + 31 * 8, 8);
|
||||
memset (®isters[REGISTER_BYTE (ALPHA_ZERO_REGNUM)], 0, 8);
|
||||
memset (®ister_valid[ALPHA_V0_REGNUM], 1, 32);
|
||||
register_valid[PC_REGNUM] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Map gdb internal register number to a ptrace ``address''.
|
||||
These ``addresses'' are defined in <sys/ptrace.h> */
|
||||
|
||||
#define REGISTER_PTRACE_ADDR(regno) \
|
||||
(regno < FP0_REGNUM ? GPR_BASE + (regno) \
|
||||
: regno == PC_REGNUM ? PC \
|
||||
: regno >= FP0_REGNUM ? FPR_BASE + ((regno) - FP0_REGNUM) \
|
||||
: 0)
|
||||
|
||||
/* Return the ptrace ``address'' of register REGNO. */
|
||||
|
||||
CORE_ADDR
|
||||
register_addr (int regno, CORE_ADDR blockend)
|
||||
{
|
||||
return REGISTER_PTRACE_ADDR (regno);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_u_size (void)
|
||||
{
|
||||
return (sizeof (struct user));
|
||||
}
|
||||
|
||||
#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T)
|
||||
#include <sys/procfs.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/*
|
||||
* See the comment in m68k-tdep.c regarding the utility of these functions.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_gregset (gdb_gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register long *regp = ALPHA_REGSET_BASE (gregsetp);
|
||||
static char zerobuf[ALPHA_MAX_REGISTER_RAW_SIZE] =
|
||||
{0};
|
||||
|
||||
for (regi = 0; regi < 31; regi++)
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
|
||||
supply_register (PC_REGNUM, (char *) (regp + 31));
|
||||
|
||||
/* Fill inaccessible registers with zero. */
|
||||
supply_register (ALPHA_ZERO_REGNUM, zerobuf);
|
||||
supply_register (FP_REGNUM, zerobuf);
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gdb_gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
register long *regp = ALPHA_REGSET_BASE (gregsetp);
|
||||
|
||||
for (regi = 0; regi < 31; regi++)
|
||||
if ((regno == -1) || (regno == regi))
|
||||
*(regp + regi) = *(long *) ®isters[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == PC_REGNUM))
|
||||
*(regp + 31) = *(long *) ®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we do the same thing for floating-point registers.
|
||||
* Again, see the comments in m68k-tdep.c.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_fpregset (gdb_fpregset_t *fpregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
|
||||
|
||||
for (regi = 0; regi < 32; regi++)
|
||||
supply_register (regi + FP0_REGNUM, (char *) (regp + regi));
|
||||
}
|
||||
|
||||
void
|
||||
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
*(regp + regi - FP0_REGNUM) =
|
||||
*(long *) ®isters[REGISTER_BYTE (regi)];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Register that we are able to handle alpha core file formats. */
|
||||
|
||||
static struct core_fns alpha_osf_core_fns =
|
||||
{
|
||||
/* This really is bfd_target_unknown_flavour. */
|
||||
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_osf_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
static struct core_fns alpha_elf_core_fns =
|
||||
{
|
||||
bfd_target_elf_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_elf_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_core_alpha (void)
|
||||
{
|
||||
add_core_fns (&alpha_osf_core_fns);
|
||||
add_core_fns (&alpha_elf_core_fns);
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/* Target-dependent code for OSF/1 on Alpha.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
/* Under OSF/1, the __sigtramp routine is frameless and has a frame
|
||||
size of zero, but we are able to backtrace through it. */
|
||||
static CORE_ADDR
|
||||
alpha_osf1_skip_sigtramp_frame (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
char *name;
|
||||
|
||||
find_pc_partial_function (pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
|
||||
if (PC_IN_SIGTRAMP (pc, name))
|
||||
return frame->frame;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_osf1_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
return (func_name != NULL && STREQ ("__sigtramp", func_name));
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_osf1_sigcontext_addr (struct frame_info *frame)
|
||||
{
|
||||
return (read_memory_integer (frame->next ? frame->next->frame
|
||||
: frame->frame, 8));
|
||||
}
|
||||
|
||||
static void
|
||||
alpha_osf1_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alpha_osf1_pc_in_sigtramp);
|
||||
|
||||
tdep->skip_sigtramp_frame = alpha_osf1_skip_sigtramp_frame;
|
||||
tdep->sigcontext_addr = alpha_osf1_sigcontext_addr;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alpha_osf1_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_OSF1, alpha_osf1_init_abi);
|
||||
}
|
||||
2023
gdb/alpha-tdep.c
2023
gdb/alpha-tdep.c
File diff suppressed because it is too large
Load Diff
109
gdb/alpha-tdep.h
109
gdb/alpha-tdep.h
@@ -1,109 +0,0 @@
|
||||
/* Common target dependent code for GDB on Alpha systems.
|
||||
Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef ALPHA_TDEP_H
|
||||
#define ALPHA_TDEP_H
|
||||
|
||||
#include "osabi.h"
|
||||
|
||||
/* Say how long (ordinary) registers are. This is a piece of bogosity
|
||||
used in push_word and a few other places; REGISTER_RAW_SIZE is the
|
||||
real way to know how big a register is. */
|
||||
#define ALPHA_REGISTER_SIZE 8
|
||||
|
||||
/* Number of machine registers. */
|
||||
#define ALPHA_NUM_REGS 66
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state. */
|
||||
#define ALPHA_REGISTER_BYTES (ALPHA_NUM_REGS * 8)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
#define ALPHA_MAX_REGISTER_RAW_SIZE 8
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
#define ALPHA_MAX_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Register numbers of various important registers.
|
||||
Note that most of these values are "real" register numbers,
|
||||
and correspond to the general registers of the machine,
|
||||
and FP_REGNUM is a "phony" register number which is too large
|
||||
to be an actual register number as far as the user is concerned
|
||||
but serves to get the desired value when passed to read_register. */
|
||||
|
||||
#define ALPHA_V0_REGNUM 0 /* Function integer return value */
|
||||
#define ALPHA_T7_REGNUM 8 /* Return address register for OSF/1 __add* */
|
||||
#define ALPHA_GCC_FP_REGNUM 15 /* Used by gcc as frame register */
|
||||
#define ALPHA_A0_REGNUM 16 /* Loc of first arg during a subr call */
|
||||
#define ALPHA_T9_REGNUM 23 /* Return address register for OSF/1 __div* */
|
||||
#define ALPHA_T12_REGNUM 27 /* Contains start addr of current proc */
|
||||
#define ALPHA_SP_REGNUM 30 /* Contains address of top of stack */
|
||||
#define ALPHA_RA_REGNUM 26 /* Contains return address value */
|
||||
#define ALPHA_ZERO_REGNUM 31 /* Read-only register, always 0 */
|
||||
#define ALPHA_FP0_REGNUM 32 /* Floating point register 0 */
|
||||
#define ALPHA_FPA0_REGNUM 48 /* First float arg during a subr call */
|
||||
#define ALPHA_FPCR_REGNUM 63 /* Floating point control register */
|
||||
#define ALPHA_PC_REGNUM 64 /* Contains program counter */
|
||||
#define ALPHA_FP_REGNUM 65 /* Virtual frame pointer */
|
||||
|
||||
/* The alpha has two different virtual pointers for arguments and locals.
|
||||
|
||||
The virtual argument pointer is pointing to the bottom of the argument
|
||||
transfer area, which is located immediately below the virtual frame
|
||||
pointer. Its size is fixed for the native compiler, it is either zero
|
||||
(for the no arguments case) or large enough to hold all argument registers.
|
||||
gcc uses a variable sized argument transfer area. As it has
|
||||
to stay compatible with the native debugging tools it has to use the same
|
||||
virtual argument pointer and adjust the argument offsets accordingly.
|
||||
|
||||
The virtual local pointer is localoff bytes below the virtual frame
|
||||
pointer, the value of localoff is obtained from the PDR. */
|
||||
#define ALPHA_NUM_ARG_REGS 6
|
||||
|
||||
/* Target-dependent structure in gdbarch. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
enum gdb_osabi osabi; /* OS/ABI of inferior. */
|
||||
|
||||
CORE_ADDR vm_min_address; /* used by heuristic_proc_start */
|
||||
|
||||
/* If PC is inside a dynamically-generated signal trampoline function
|
||||
(i.e. one copied onto the user stack at run-time), return how many
|
||||
bytes PC is beyond the start of that function. Otherwise, return -1. */
|
||||
LONGEST (*dynamic_sigtramp_offset) (CORE_ADDR);
|
||||
|
||||
/* If FRAME refers to a sigtramp frame, return the address of the next
|
||||
frame. */
|
||||
CORE_ADDR (*skip_sigtramp_frame) (struct frame_info *, CORE_ADDR);
|
||||
|
||||
/* Translate a signal handler frame into the address of the sigcontext
|
||||
structure for that signal handler. */
|
||||
CORE_ADDR (*sigcontext_addr) (struct frame_info *);
|
||||
|
||||
int jb_pc; /* Offset to PC value in jump buffer.
|
||||
If htis is negative, longjmp support
|
||||
will be disabled. */
|
||||
size_t jb_elt_size; /* And the size of each entry in the buf. */
|
||||
};
|
||||
|
||||
void alpha_software_single_step (enum target_signal, int);
|
||||
|
||||
#endif /* ALPHA_TDEP_H */
|
||||
@@ -1,157 +0,0 @@
|
||||
/* Native-dependent code for Alpha BSD's.
|
||||
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
|
||||
#ifdef HAVE_SYS_PROCFS_H
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GREGSET_T
|
||||
typedef struct reg gregset_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FPREGSET_T
|
||||
typedef struct fpreg fpregset_t;
|
||||
#endif
|
||||
|
||||
#include "gregset.h"
|
||||
|
||||
/* Provide *regset() wrappers around the generic Alpha BSD register
|
||||
supply/fill routines. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
alphabsd_supply_reg ((char *) gregsetp, -1);
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
alphabsd_fill_reg ((char *) gregsetp, regno);
|
||||
}
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
alphabsd_supply_fpreg ((char *) fpregsetp, -1);
|
||||
}
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
alphabsd_fill_fpreg ((char *) fpregsetp, regno);
|
||||
}
|
||||
|
||||
/* Determine if PT_GETREGS fetches this register. */
|
||||
|
||||
static int
|
||||
getregs_supplies (int regno)
|
||||
{
|
||||
|
||||
return ((regno >= ALPHA_V0_REGNUM && regno <= ALPHA_ZERO_REGNUM)
|
||||
|| regno >= PC_REGNUM);
|
||||
}
|
||||
|
||||
|
||||
/* Fetch register REGNO from the inferior. If REGNO is -1, do this
|
||||
for all registers (including the floating point registers). */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
|
||||
if (regno == -1 || getregs_supplies (regno))
|
||||
{
|
||||
struct reg gregs;
|
||||
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
alphabsd_supply_reg ((char *) &gregs, regno);
|
||||
if (regno != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno == -1 || regno >= FP0_REGNUM)
|
||||
{
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
alphabsd_supply_fpreg ((char *) &fpregs, regno);
|
||||
}
|
||||
|
||||
/* Reset virtual frame pointer. */
|
||||
supply_register (FP_REGNUM, NULL);
|
||||
}
|
||||
|
||||
/* Store register REGNO back into the inferior. If REGNO is -1, do
|
||||
this for all registers (including the floating point registers). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
|
||||
if (regno == -1 || getregs_supplies (regno))
|
||||
{
|
||||
struct reg gregs;
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
alphabsd_fill_reg ((char *) &gregs, regno);
|
||||
|
||||
if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
perror_with_name ("Couldn't write registers");
|
||||
|
||||
if (regno != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno == -1 || regno >= FP0_REGNUM)
|
||||
{
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
alphabsd_fill_fpreg ((char *) &fpregs, regno);
|
||||
|
||||
if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't write floating point status");
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* Common target dependent code for GDB on Alpha systems running BSD.
|
||||
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
|
||||
/* Number of general-purpose registers. */
|
||||
#define NUM_GREGS 32
|
||||
|
||||
/* Number of floating-point registers. */
|
||||
#define NUM_FPREGS 31
|
||||
|
||||
/* Conviently, GDB uses the same register numbering as the
|
||||
ptrace register structure used by BSD on Alpha. */
|
||||
|
||||
void
|
||||
alphabsd_supply_reg (char *regs, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
{
|
||||
if (i == regno || regno == -1)
|
||||
{
|
||||
if (CANNOT_FETCH_REGISTER (i))
|
||||
supply_register (i, NULL);
|
||||
else
|
||||
supply_register (i, regs + (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
/* The PC travels in the ZERO slot. */
|
||||
if (regno == PC_REGNUM || regno == -1)
|
||||
supply_register (PC_REGNUM, regs + (31 * 8));
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_fill_reg (char *regs, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
|
||||
regcache_collect (i, regs + (i * 8));
|
||||
|
||||
/* The PC travels in the ZERO slot. */
|
||||
if (regno == PC_REGNUM || regno == -1)
|
||||
regcache_collect (PC_REGNUM, regs + (31 * 8));
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_supply_fpreg (char *fpregs, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + NUM_FPREGS; i++)
|
||||
{
|
||||
if (i == regno || regno == -1)
|
||||
{
|
||||
if (CANNOT_FETCH_REGISTER (i))
|
||||
supply_register (i, NULL);
|
||||
else
|
||||
supply_register (i, fpregs + ((i - FP0_REGNUM) * 8));
|
||||
}
|
||||
}
|
||||
|
||||
if (regno == ALPHA_FPCR_REGNUM || regno == -1)
|
||||
supply_register (ALPHA_FPCR_REGNUM, fpregs + (32 * 8));
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_fill_fpreg (char *fpregs, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + NUM_FPREGS; i++)
|
||||
if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
|
||||
regcache_collect (i, fpregs + ((i - FP0_REGNUM) * 8));
|
||||
|
||||
if (regno == ALPHA_FPCR_REGNUM || regno == -1)
|
||||
regcache_collect (ALPHA_FPCR_REGNUM, fpregs + (32 * 8));
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/* Common target dependent code for GDB on Alpha systems running BSD.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef ALPHABSD_TDEP_H
|
||||
#define ALPHABSD_TDEP_H
|
||||
|
||||
void alphabsd_supply_reg (char *, int);
|
||||
void alphabsd_fill_reg (char *, int);
|
||||
|
||||
void alphabsd_supply_fpreg (char *, int);
|
||||
void alphabsd_fill_fpreg (char *, int);
|
||||
|
||||
#define SIZEOF_STRUCT_REG (32 * 8)
|
||||
#define SIZEOF_STRUCT_FPREG (33 * 8)
|
||||
|
||||
#endif /* ALPHABSD_TDEP_H */
|
||||
@@ -1,83 +0,0 @@
|
||||
/* Target-dependent code for FreeBSD/Alpha.
|
||||
Copyright 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
static int
|
||||
alphafbsd_use_struct_convention (int gcc_p, struct type *type)
|
||||
{
|
||||
enum type_code code;
|
||||
int i;
|
||||
|
||||
/* All aggregate types that won't fit in a register must be returned
|
||||
in memory. */
|
||||
if (TYPE_LENGTH (type) > REGISTER_SIZE)
|
||||
return 1;
|
||||
|
||||
/* The only aggregate types that can be returned in a register are
|
||||
structs and unions. Arrays must be returned in memory. */
|
||||
code = TYPE_CODE (type);
|
||||
if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION)
|
||||
return 1;
|
||||
|
||||
/* We need to check if this struct/union is "integer" like. For
|
||||
this to be true, the offset of each adressable subfield must be
|
||||
zero. Note that bit fields are not addressable. */
|
||||
for (i = 0; i < TYPE_NFIELDS (type); i++)
|
||||
{
|
||||
/* If the field bitsize is non-zero, it isn't adressable. */
|
||||
if (TYPE_FIELD_BITPOS (type, i) != 0
|
||||
&& TYPE_FIELD_BITSIZE (type, i) == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
alphafbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
/* FIXME */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
alphafbsd_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alphafbsd_pc_in_sigtramp);
|
||||
|
||||
set_gdbarch_use_struct_convention (gdbarch, alphafbsd_use_struct_convention);
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alphafbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_FREEBSD_ELF,
|
||||
alphafbsd_init_abi);
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/* Target-dependent code for NetBSD/Alpha.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
Contributed by Wasabi Systems, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "solib-svr4.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR ignore)
|
||||
{
|
||||
char *regs, *fpregs;
|
||||
int regno;
|
||||
|
||||
/* Table to map a gdb register number to a trapframe register index. */
|
||||
static const int regmap[] =
|
||||
{
|
||||
0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15,
|
||||
30, 31, 32, 16,
|
||||
17, 18, 19, 20,
|
||||
21, 22, 23, 24,
|
||||
25, 29, 26
|
||||
};
|
||||
#define SIZEOF_TRAPFRAME (33 * 8)
|
||||
|
||||
/* We get everything from one section. */
|
||||
if (which != 0)
|
||||
return;
|
||||
|
||||
regs = core_reg_sect;
|
||||
fpregs = core_reg_sect + SIZEOF_TRAPFRAME;
|
||||
|
||||
if (core_reg_size < (SIZEOF_TRAPFRAME + SIZEOF_STRUCT_FPREG))
|
||||
{
|
||||
warning ("Wrong size register set in core file.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer registers. */
|
||||
for (regno = 0; regno < ALPHA_ZERO_REGNUM; regno++)
|
||||
supply_register (regno, regs + (regmap[regno] * 8));
|
||||
supply_register (ALPHA_ZERO_REGNUM, NULL);
|
||||
supply_register (FP_REGNUM, NULL);
|
||||
supply_register (PC_REGNUM, regs + (28 * 8));
|
||||
|
||||
/* Floating point registers. */
|
||||
alphabsd_supply_fpreg (fpregs, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR ignore)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0: /* Integer registers. */
|
||||
if (core_reg_size != SIZEOF_STRUCT_REG)
|
||||
warning ("Wrong size register set in core file.");
|
||||
else
|
||||
alphabsd_supply_reg (core_reg_sect, -1);
|
||||
break;
|
||||
|
||||
case 2: /* Floating point registers. */
|
||||
if (core_reg_size != SIZEOF_STRUCT_FPREG)
|
||||
warning ("Wrong size FP register set in core file.");
|
||||
else
|
||||
alphabsd_supply_fpreg (core_reg_sect, -1);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Don't know what kind of register request this is; just ignore it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct core_fns alphanbsd_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
static struct core_fns alphanbsd_elfcore_fns =
|
||||
{
|
||||
bfd_target_elf_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_elfcore_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
/* Under NetBSD/alpha, signal handler invocations can be identified by the
|
||||
designated code sequence that is used to return from a signal handler.
|
||||
In particular, the return address of a signal handler points to the
|
||||
following code sequence:
|
||||
|
||||
ldq a0, 0(sp)
|
||||
lda sp, 16(sp)
|
||||
lda v0, 295(zero) # __sigreturn14
|
||||
call_pal callsys
|
||||
|
||||
Each instruction has a unique encoding, so we simply attempt to match
|
||||
the instruction the PC is pointing to with any of the above instructions.
|
||||
If there is a hit, we know the offset to the start of the designated
|
||||
sequence and can then check whether we really are executing in the
|
||||
signal trampoline. If not, -1 is returned, otherwise the offset from the
|
||||
start of the return sequence is returned. */
|
||||
static const unsigned char sigtramp_retcode[] =
|
||||
{
|
||||
0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */
|
||||
0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */
|
||||
0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */
|
||||
0x83, 0x00, 0x00, 0x00, /* call_pal callsys */
|
||||
};
|
||||
#define RETCODE_NWORDS 4
|
||||
#define RETCODE_SIZE (RETCODE_NWORDS * 4)
|
||||
|
||||
LONGEST
|
||||
alphanbsd_sigtramp_offset (CORE_ADDR pc)
|
||||
{
|
||||
unsigned char ret[RETCODE_SIZE], w[4];
|
||||
LONGEST off;
|
||||
int i;
|
||||
|
||||
if (read_memory_nobpt (pc, (char *) w, 4) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < RETCODE_NWORDS; i++)
|
||||
{
|
||||
if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == RETCODE_NWORDS)
|
||||
return (-1);
|
||||
|
||||
off = i * 4;
|
||||
pc -= off;
|
||||
|
||||
if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0)
|
||||
return -1;
|
||||
|
||||
if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0)
|
||||
return off;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
alphanbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
return (alphanbsd_sigtramp_offset (pc) >= 0);
|
||||
}
|
||||
|
||||
static void
|
||||
alphanbsd_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alphanbsd_pc_in_sigtramp);
|
||||
|
||||
/* NetBSD/alpha does not provide single step support via ptrace(2); we
|
||||
must use software single-stepping. */
|
||||
set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
|
||||
|
||||
set_solib_svr4_fetch_link_map_offsets (gdbarch,
|
||||
nbsd_lp64_solib_svr4_fetch_link_map_offsets);
|
||||
|
||||
tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alphanbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, GDB_OSABI_NETBSD_ELF,
|
||||
alphanbsd_init_abi);
|
||||
|
||||
add_core_fns (&alphanbsd_core_fns);
|
||||
add_core_fns (&alphanbsd_elfcore_fns);
|
||||
}
|
||||
585
gdb/annotate.c
585
gdb/annotate.c
@@ -1,585 +0,0 @@
|
||||
/* Annotation routines for GDB.
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1998, 1999,
|
||||
2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "annotate.h"
|
||||
#include "value.h"
|
||||
#include "target.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "breakpoint.h"
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
|
||||
extern void _initialize_annotate (void);
|
||||
|
||||
static void print_value_flags (struct type *);
|
||||
|
||||
static void breakpoint_changed (struct breakpoint *);
|
||||
|
||||
void (*annotate_starting_hook) (void);
|
||||
void (*annotate_stopped_hook) (void);
|
||||
void (*annotate_signalled_hook) (void);
|
||||
void (*annotate_signal_hook) (void);
|
||||
void (*annotate_exited_hook) (void);
|
||||
|
||||
static int ignore_count_changed = 0;
|
||||
|
||||
static void
|
||||
print_value_flags (struct type *t)
|
||||
{
|
||||
if (can_dereference (t))
|
||||
printf_filtered ("*");
|
||||
else
|
||||
printf_filtered ("-");
|
||||
}
|
||||
|
||||
void
|
||||
breakpoints_changed (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
target_terminal_ours ();
|
||||
printf_unfiltered ("\n\032\032breakpoints-invalid\n");
|
||||
if (ignore_count_changed)
|
||||
ignore_count_changed = 0; /* Avoid multiple break annotations. */
|
||||
}
|
||||
}
|
||||
|
||||
/* The GUI needs to be informed of ignore_count changes, but we don't
|
||||
want to provide successive multiple breakpoints-invalid messages
|
||||
that are all caused by the fact that the ignore count is changing
|
||||
(which could keep the GUI very busy). One is enough, after the
|
||||
target actually "stops". */
|
||||
|
||||
void
|
||||
annotate_ignore_count_change (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
ignore_count_changed = 1;
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoint (int num)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032breakpoint %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_catchpoint (int num)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032catchpoint %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_watchpoint (int num)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032watchpoint %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_starting (void)
|
||||
{
|
||||
|
||||
if (annotate_starting_hook)
|
||||
annotate_starting_hook ();
|
||||
else
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032starting\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_stopped (void)
|
||||
{
|
||||
if (annotate_stopped_hook)
|
||||
annotate_stopped_hook ();
|
||||
else
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032stopped\n");
|
||||
}
|
||||
if (annotation_level > 1 && ignore_count_changed)
|
||||
{
|
||||
ignore_count_changed = 0;
|
||||
breakpoints_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_exited (int exitstatus)
|
||||
{
|
||||
if (annotate_exited_hook)
|
||||
annotate_exited_hook ();
|
||||
else
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032exited %d\n", exitstatus);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signalled (void)
|
||||
{
|
||||
if (annotate_signalled_hook)
|
||||
annotate_signalled_hook ();
|
||||
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signalled\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_name (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal-name\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_string (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal-string\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_string_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal-string-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal (void)
|
||||
{
|
||||
if (annotate_signal_hook)
|
||||
annotate_signal_hook ();
|
||||
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoints_headers (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032breakpoints-headers\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field (int num)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032field %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoints_table (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032breakpoints-table\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_record (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032record\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoints_table_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032breakpoints-table-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frames_invalid (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
target_terminal_ours ();
|
||||
printf_unfiltered ("\n\032\032frames-invalid\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_begin (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032field-begin ");
|
||||
print_value_flags (type);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032field-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032field-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032field-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_quit (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032quit\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_error (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032error\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_error_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_history_begin (int histindex, struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032value-history-begin %d ", histindex);
|
||||
print_value_flags (type);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_begin (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032value-begin ");
|
||||
print_value_flags (type);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_history_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032value-history-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_history_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032value-history-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032value-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_number_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-number-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_format (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-format\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_expression (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-expression\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_expression_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-expression-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032display-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032arg-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032arg-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_value (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032arg-value ");
|
||||
print_value_flags (type);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032arg-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_source (char *filename, int line, int character, int mid, CORE_ADDR pc)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032source ");
|
||||
else
|
||||
printf_filtered ("\032\032");
|
||||
|
||||
printf_filtered ("%s:%d:%d:%s:0x", filename,
|
||||
line, character,
|
||||
mid ? "middle" : "beg");
|
||||
print_address_numeric (pc, 0, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_begin (int level, CORE_ADDR pc)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032frame-begin %d 0x", level);
|
||||
print_address_numeric (pc, 0, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_function_call (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032function-call\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_handler_caller (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032signal-handler-caller\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_address (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-address\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_address_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-address-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_function_name (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-function-name\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_args (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-args\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-source-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_file (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-source-file\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_file_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-source-file-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_line (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-source-line\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-source-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_where (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-where\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032frame-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_array_section_begin (int index, struct type *elttype)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
printf_filtered ("\n\032\032array-section-begin %d ", index);
|
||||
print_value_flags (elttype);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
annotate_elt_rep (unsigned int repcount)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032elt-rep %u\n", repcount);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_elt_rep_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032elt-rep-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_elt (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032elt\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_array_section_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
printf_filtered ("\n\032\032array-section-end\n");
|
||||
}
|
||||
|
||||
static void
|
||||
breakpoint_changed (struct breakpoint *b)
|
||||
{
|
||||
breakpoints_changed ();
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_annotate (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
{
|
||||
delete_breakpoint_hook = breakpoint_changed;
|
||||
modify_breakpoint_hook = breakpoint_changed;
|
||||
}
|
||||
}
|
||||
106
gdb/annotate.h
106
gdb/annotate.h
@@ -1,106 +0,0 @@
|
||||
/* Annotation routines for GDB.
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1994, 1998, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
extern void breakpoints_changed (void);
|
||||
|
||||
extern void annotate_ignore_count_change (void);
|
||||
extern void annotate_breakpoint (int);
|
||||
extern void annotate_catchpoint (int);
|
||||
extern void annotate_watchpoint (int);
|
||||
extern void annotate_starting (void);
|
||||
extern void annotate_stopped (void);
|
||||
extern void annotate_exited (int);
|
||||
extern void annotate_signalled (void);
|
||||
extern void annotate_signal_name (void);
|
||||
extern void annotate_signal_name_end (void);
|
||||
extern void annotate_signal_string (void);
|
||||
extern void annotate_signal_string_end (void);
|
||||
extern void annotate_signal (void);
|
||||
|
||||
extern void annotate_breakpoints_headers (void);
|
||||
extern void annotate_field (int);
|
||||
extern void annotate_breakpoints_table (void);
|
||||
extern void annotate_record (void);
|
||||
extern void annotate_breakpoints_table_end (void);
|
||||
|
||||
extern void annotate_frames_invalid (void);
|
||||
|
||||
struct type;
|
||||
|
||||
extern void annotate_field_begin (struct type *);
|
||||
extern void annotate_field_name_end (void);
|
||||
extern void annotate_field_value (void);
|
||||
extern void annotate_field_end (void);
|
||||
|
||||
extern void annotate_quit (void);
|
||||
extern void annotate_error (void);
|
||||
extern void annotate_error_begin (void);
|
||||
|
||||
extern void annotate_value_history_begin (int, struct type *);
|
||||
extern void annotate_value_begin (struct type *);
|
||||
extern void annotate_value_history_value (void);
|
||||
extern void annotate_value_history_end (void);
|
||||
extern void annotate_value_end (void);
|
||||
|
||||
extern void annotate_display_begin (void);
|
||||
extern void annotate_display_number_end (void);
|
||||
extern void annotate_display_format (void);
|
||||
extern void annotate_display_expression (void);
|
||||
extern void annotate_display_expression_end (void);
|
||||
extern void annotate_display_value (void);
|
||||
extern void annotate_display_end (void);
|
||||
|
||||
extern void annotate_arg_begin (void);
|
||||
extern void annotate_arg_name_end (void);
|
||||
extern void annotate_arg_value (struct type *);
|
||||
extern void annotate_arg_end (void);
|
||||
|
||||
extern void annotate_source (char *, int, int, int, CORE_ADDR);
|
||||
|
||||
extern void annotate_frame_begin (int, CORE_ADDR);
|
||||
extern void annotate_function_call (void);
|
||||
extern void annotate_signal_handler_caller (void);
|
||||
extern void annotate_frame_address (void);
|
||||
extern void annotate_frame_address_end (void);
|
||||
extern void annotate_frame_function_name (void);
|
||||
extern void annotate_frame_args (void);
|
||||
extern void annotate_frame_source_begin (void);
|
||||
extern void annotate_frame_source_file (void);
|
||||
extern void annotate_frame_source_file_end (void);
|
||||
extern void annotate_frame_source_line (void);
|
||||
extern void annotate_frame_source_end (void);
|
||||
extern void annotate_frame_where (void);
|
||||
extern void annotate_frame_end (void);
|
||||
|
||||
extern void annotate_array_section_begin (int, struct type *);
|
||||
extern void annotate_elt_rep (unsigned int);
|
||||
extern void annotate_elt_rep_end (void);
|
||||
extern void annotate_elt (void);
|
||||
extern void annotate_array_section_end (void);
|
||||
|
||||
extern void (*annotate_starting_hook) (void);
|
||||
extern void (*annotate_stopped_hook) (void);
|
||||
extern void (*annotate_signalled_hook) (void);
|
||||
extern void (*annotate_signal_hook) (void);
|
||||
extern void (*annotate_exited_hook) (void);
|
||||
737
gdb/arc-tdep.c
737
gdb/arc-tdep.c
@@ -1,737 +0,0 @@
|
||||
/* ARC target-dependent stuff.
|
||||
Copyright 1995, 1996, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "floatformat.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* Local functions */
|
||||
|
||||
static int arc_set_cpu_type (char *str);
|
||||
|
||||
/* Current CPU, set with the "set cpu" command. */
|
||||
static int arc_bfd_mach_type;
|
||||
char *arc_cpu_type;
|
||||
char *tmp_arc_cpu_type;
|
||||
|
||||
/* Table of cpu names. */
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
int value;
|
||||
}
|
||||
arc_cpu_type_table[] =
|
||||
{
|
||||
{ "arc5", bfd_mach_arc_5 },
|
||||
{ "arc6", bfd_mach_arc_6 },
|
||||
{ "arc7", bfd_mach_arc_7 },
|
||||
{ "arc8", bfd_mach_arc_8 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Used by simulator. */
|
||||
int display_pipeline_p;
|
||||
int cpu_timer;
|
||||
/* This one must have the same type as used in the emulator.
|
||||
It's currently an enum so this should be ok for now. */
|
||||
int debug_pipeline_p;
|
||||
|
||||
#define ARC_CALL_SAVED_REG(r) ((r) >= 16 && (r) < 24)
|
||||
|
||||
#define OPMASK 0xf8000000
|
||||
|
||||
/* Instruction field accessor macros.
|
||||
See the Programmer's Reference Manual. */
|
||||
#define X_OP(i) (((i) >> 27) & 0x1f)
|
||||
#define X_A(i) (((i) >> 21) & 0x3f)
|
||||
#define X_B(i) (((i) >> 15) & 0x3f)
|
||||
#define X_C(i) (((i) >> 9) & 0x3f)
|
||||
#define X_D(i) ((((i) & 0x1ff) ^ 0x100) - 0x100)
|
||||
#define X_L(i) (((((i) >> 5) & 0x3ffffc) ^ 0x200000) - 0x200000)
|
||||
#define X_N(i) (((i) >> 5) & 3)
|
||||
#define X_Q(i) ((i) & 0x1f)
|
||||
|
||||
/* Return non-zero if X is a short immediate data indicator. */
|
||||
#define SHIMM_P(x) ((x) == 61 || (x) == 63)
|
||||
|
||||
/* Return non-zero if X is a "long" (32 bit) immediate data indicator. */
|
||||
#define LIMM_P(x) ((x) == 62)
|
||||
|
||||
/* Build a simple instruction. */
|
||||
#define BUILD_INSN(op, a, b, c, d) \
|
||||
((((op) & 31) << 27) \
|
||||
| (((a) & 63) << 21) \
|
||||
| (((b) & 63) << 15) \
|
||||
| (((c) & 63) << 9) \
|
||||
| ((d) & 511))
|
||||
|
||||
/* Codestream stuff. */
|
||||
static void codestream_read (unsigned int *, int);
|
||||
static void codestream_seek (CORE_ADDR);
|
||||
static unsigned int codestream_fill (int);
|
||||
|
||||
#define CODESTREAM_BUFSIZ 16
|
||||
static CORE_ADDR codestream_next_addr;
|
||||
static CORE_ADDR codestream_addr;
|
||||
/* FIXME assumes sizeof (int) == 32? */
|
||||
static unsigned int codestream_buf[CODESTREAM_BUFSIZ];
|
||||
static int codestream_off;
|
||||
static int codestream_cnt;
|
||||
|
||||
#define codestream_tell() \
|
||||
(codestream_addr + codestream_off * sizeof (codestream_buf[0]))
|
||||
#define codestream_peek() \
|
||||
(codestream_cnt == 0 \
|
||||
? codestream_fill (1) \
|
||||
: codestream_buf[codestream_off])
|
||||
#define codestream_get() \
|
||||
(codestream_cnt-- == 0 \
|
||||
? codestream_fill (0) \
|
||||
: codestream_buf[codestream_off++])
|
||||
|
||||
static unsigned int
|
||||
codestream_fill (int peek_flag)
|
||||
{
|
||||
codestream_addr = codestream_next_addr;
|
||||
codestream_next_addr += CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]);
|
||||
codestream_off = 0;
|
||||
codestream_cnt = CODESTREAM_BUFSIZ;
|
||||
read_memory (codestream_addr, (char *) codestream_buf,
|
||||
CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]));
|
||||
/* FIXME: check return code? */
|
||||
|
||||
|
||||
/* Handle byte order differences -> convert to host byte ordering. */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < CODESTREAM_BUFSIZ; i++)
|
||||
codestream_buf[i] =
|
||||
extract_unsigned_integer (&codestream_buf[i],
|
||||
sizeof (codestream_buf[i]));
|
||||
}
|
||||
|
||||
if (peek_flag)
|
||||
return codestream_peek ();
|
||||
else
|
||||
return codestream_get ();
|
||||
}
|
||||
|
||||
static void
|
||||
codestream_seek (CORE_ADDR place)
|
||||
{
|
||||
codestream_next_addr = place / CODESTREAM_BUFSIZ;
|
||||
codestream_next_addr *= CODESTREAM_BUFSIZ;
|
||||
codestream_cnt = 0;
|
||||
codestream_fill (1);
|
||||
while (codestream_tell () != place)
|
||||
codestream_get ();
|
||||
}
|
||||
|
||||
/* This function is currently unused but leave in for now. */
|
||||
|
||||
static void
|
||||
codestream_read (unsigned int *buf, int count)
|
||||
{
|
||||
unsigned int *p;
|
||||
int i;
|
||||
p = buf;
|
||||
for (i = 0; i < count; i++)
|
||||
*p++ = codestream_get ();
|
||||
}
|
||||
|
||||
/* Set up prologue scanning and return the first insn. */
|
||||
|
||||
static unsigned int
|
||||
setup_prologue_scan (CORE_ADDR pc)
|
||||
{
|
||||
unsigned int insn;
|
||||
|
||||
codestream_seek (pc);
|
||||
insn = codestream_get ();
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find & return amount a local space allocated, and advance codestream to
|
||||
* first register push (if any).
|
||||
* If entry sequence doesn't make sense, return -1, and leave
|
||||
* codestream pointer random.
|
||||
*/
|
||||
|
||||
static long
|
||||
arc_get_frame_setup (CORE_ADDR pc)
|
||||
{
|
||||
unsigned int insn;
|
||||
/* Size of frame or -1 if unrecognizable prologue. */
|
||||
int frame_size = -1;
|
||||
/* An initial "sub sp,sp,N" may or may not be for a stdarg fn. */
|
||||
int maybe_stdarg_decr = -1;
|
||||
|
||||
insn = setup_prologue_scan (pc);
|
||||
|
||||
/* The authority for what appears here is the home-grown ABI.
|
||||
The most recent version is 1.2. */
|
||||
|
||||
/* First insn may be "sub sp,sp,N" if stdarg fn. */
|
||||
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
|
||||
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
|
||||
{
|
||||
maybe_stdarg_decr = X_D (insn);
|
||||
insn = codestream_get ();
|
||||
}
|
||||
|
||||
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
|
||||
== BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
|
||||
{
|
||||
insn = codestream_get ();
|
||||
/* Frame may not be necessary, even though blink is saved.
|
||||
At least this is something we recognize. */
|
||||
frame_size = 0;
|
||||
}
|
||||
|
||||
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st fp,[sp] */
|
||||
== BUILD_INSN (2, 0, SP_REGNUM, FP_REGNUM, 0))
|
||||
{
|
||||
insn = codestream_get ();
|
||||
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
|
||||
!= BUILD_INSN (12, FP_REGNUM, SP_REGNUM, SP_REGNUM, 0))
|
||||
return -1;
|
||||
|
||||
/* Check for stack adjustment sub sp,sp,N. */
|
||||
insn = codestream_peek ();
|
||||
if ((insn & BUILD_INSN (-1, -1, -1, 0, 0))
|
||||
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, 0, 0))
|
||||
{
|
||||
if (LIMM_P (X_C (insn)))
|
||||
frame_size = codestream_get ();
|
||||
else if (SHIMM_P (X_C (insn)))
|
||||
frame_size = X_D (insn);
|
||||
else
|
||||
return -1;
|
||||
if (frame_size < 0)
|
||||
return -1;
|
||||
|
||||
codestream_get ();
|
||||
|
||||
/* This sequence is used to get the address of the return
|
||||
buffer for a function that returns a structure. */
|
||||
insn = codestream_peek ();
|
||||
if ((insn & OPMASK) == 0x60000000)
|
||||
codestream_get ();
|
||||
}
|
||||
/* Frameless fn. */
|
||||
else
|
||||
{
|
||||
frame_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a "sub sp,sp,N" and nothing else, it may or may not be a
|
||||
stdarg fn. The stdarg decrement is not treated as part of the frame size,
|
||||
so we have a dilemma: what do we return? For now, if we get a
|
||||
"sub sp,sp,N" and nothing else assume this isn't a stdarg fn. One way
|
||||
to fix this completely would be to add a bit to the function descriptor
|
||||
that says the function is a stdarg function. */
|
||||
|
||||
if (frame_size < 0 && maybe_stdarg_decr > 0)
|
||||
return maybe_stdarg_decr;
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
/* Given a pc value, skip it forward past the function prologue by
|
||||
disassembling instructions that appear to be a prologue.
|
||||
|
||||
If FRAMELESS_P is set, we are only testing to see if the function
|
||||
is frameless. If it is a frameless function, return PC unchanged.
|
||||
This allows a quicker answer. */
|
||||
|
||||
CORE_ADDR
|
||||
arc_skip_prologue (CORE_ADDR pc, int frameless_p)
|
||||
{
|
||||
unsigned int insn;
|
||||
int i, frame_size;
|
||||
|
||||
if ((frame_size = arc_get_frame_setup (pc)) < 0)
|
||||
return (pc);
|
||||
|
||||
if (frameless_p)
|
||||
return frame_size == 0 ? pc : codestream_tell ();
|
||||
|
||||
/* Skip over register saves. */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
insn = codestream_peek ();
|
||||
if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
|
||||
!= BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
|
||||
break; /* not st insn */
|
||||
if (!ARC_CALL_SAVED_REG (X_C (insn)))
|
||||
break;
|
||||
codestream_get ();
|
||||
}
|
||||
|
||||
return codestream_tell ();
|
||||
}
|
||||
|
||||
/* Is the prologue at PC frameless? */
|
||||
|
||||
int
|
||||
arc_prologue_frameless_p (CORE_ADDR pc)
|
||||
{
|
||||
return (pc == arc_skip_prologue (pc, 1));
|
||||
}
|
||||
|
||||
/* Return the return address for a frame.
|
||||
This is used to implement FRAME_SAVED_PC.
|
||||
This is taken from frameless_look_for_prologue. */
|
||||
|
||||
CORE_ADDR
|
||||
arc_frame_saved_pc (struct frame_info *frame)
|
||||
{
|
||||
CORE_ADDR func_start;
|
||||
unsigned int insn;
|
||||
|
||||
func_start = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
|
||||
if (func_start == 0)
|
||||
{
|
||||
/* Best guess. */
|
||||
return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
|
||||
}
|
||||
|
||||
/* The authority for what appears here is the home-grown ABI.
|
||||
The most recent version is 1.2. */
|
||||
|
||||
insn = setup_prologue_scan (func_start);
|
||||
|
||||
/* First insn may be "sub sp,sp,N" if stdarg fn. */
|
||||
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
|
||||
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
|
||||
insn = codestream_get ();
|
||||
|
||||
/* If the next insn is "st blink,[sp,4]" we can get blink from there.
|
||||
Otherwise this is a leaf function and we can use blink. Note that
|
||||
this still allows for the case where a leaf function saves/clobbers/
|
||||
restores blink. */
|
||||
|
||||
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
|
||||
!= BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
|
||||
return ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM));
|
||||
else
|
||||
return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the first few instructions of the function to see
|
||||
* what registers were stored.
|
||||
*
|
||||
* The startup sequence can be at the start of the function.
|
||||
* 'st blink,[sp+4], st fp,[sp], mov fp,sp'
|
||||
*
|
||||
* Local space is allocated just below by sub sp,sp,nnn.
|
||||
* Next, the registers used by this function are stored (as offsets from sp).
|
||||
*/
|
||||
|
||||
void
|
||||
frame_find_saved_regs (struct frame_info *fip, struct frame_saved_regs *fsrp)
|
||||
{
|
||||
long locals;
|
||||
unsigned int insn;
|
||||
CORE_ADDR dummy_bottom;
|
||||
CORE_ADDR adr;
|
||||
int i, regnum, offset;
|
||||
|
||||
memset (fsrp, 0, sizeof *fsrp);
|
||||
|
||||
/* If frame is the end of a dummy, compute where the beginning would be. */
|
||||
dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH;
|
||||
|
||||
/* Check if the PC is in the stack, in a dummy frame. */
|
||||
if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
|
||||
{
|
||||
/* all regs were saved by push_call_dummy () */
|
||||
adr = fip->frame;
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
{
|
||||
adr -= REGISTER_RAW_SIZE (i);
|
||||
fsrp->regs[i] = adr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
locals = arc_get_frame_setup (get_pc_function_start (fip->pc));
|
||||
|
||||
if (locals >= 0)
|
||||
{
|
||||
/* Set `adr' to the value of `sp'. */
|
||||
adr = fip->frame - locals;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
insn = codestream_get ();
|
||||
if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
|
||||
!= BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
|
||||
break;
|
||||
regnum = X_C (insn);
|
||||
offset = X_D (insn);
|
||||
fsrp->regs[regnum] = adr + offset;
|
||||
}
|
||||
}
|
||||
|
||||
fsrp->regs[PC_REGNUM] = fip->frame + 4;
|
||||
fsrp->regs[FP_REGNUM] = fip->frame;
|
||||
}
|
||||
|
||||
void
|
||||
arc_push_dummy_frame (void)
|
||||
{
|
||||
CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
int regnum;
|
||||
char regbuf[MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
read_register_gen (PC_REGNUM, regbuf);
|
||||
write_memory (sp + 4, regbuf, REGISTER_SIZE);
|
||||
read_register_gen (FP_REGNUM, regbuf);
|
||||
write_memory (sp, regbuf, REGISTER_SIZE);
|
||||
write_register (FP_REGNUM, sp);
|
||||
for (regnum = 0; regnum < NUM_REGS; regnum++)
|
||||
{
|
||||
read_register_gen (regnum, regbuf);
|
||||
sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
|
||||
}
|
||||
sp += (2 * REGISTER_SIZE);
|
||||
write_register (SP_REGNUM, sp);
|
||||
}
|
||||
|
||||
void
|
||||
arc_pop_frame (void)
|
||||
{
|
||||
struct frame_info *frame = get_current_frame ();
|
||||
CORE_ADDR fp;
|
||||
int regnum;
|
||||
struct frame_saved_regs fsr;
|
||||
char regbuf[MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
fp = FRAME_FP (frame);
|
||||
get_frame_saved_regs (frame, &fsr);
|
||||
for (regnum = 0; regnum < NUM_REGS; regnum++)
|
||||
{
|
||||
CORE_ADDR adr;
|
||||
adr = fsr.regs[regnum];
|
||||
if (adr)
|
||||
{
|
||||
read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
|
||||
write_register_bytes (REGISTER_BYTE (regnum), regbuf,
|
||||
REGISTER_RAW_SIZE (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 ();
|
||||
}
|
||||
|
||||
/* Simulate single-step. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NORMAL4, /* a normal 4 byte insn */
|
||||
NORMAL8, /* a normal 8 byte insn */
|
||||
BRANCH4, /* a 4 byte branch insn, including ones without delay slots */
|
||||
BRANCH8, /* an 8 byte branch insn, including ones with delay slots */
|
||||
}
|
||||
insn_type;
|
||||
|
||||
/* Return the type of INSN and store in TARGET the destination address of a
|
||||
branch if this is one. */
|
||||
/* ??? Need to verify all cases are properly handled. */
|
||||
|
||||
static insn_type
|
||||
get_insn_type (unsigned long insn, CORE_ADDR pc, CORE_ADDR *target)
|
||||
{
|
||||
unsigned long limm;
|
||||
|
||||
switch (insn >> 27)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: /* load/store insns */
|
||||
if (LIMM_P (X_A (insn))
|
||||
|| LIMM_P (X_B (insn))
|
||||
|| LIMM_P (X_C (insn)))
|
||||
return NORMAL8;
|
||||
return NORMAL4;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6: /* branch insns */
|
||||
*target = pc + 4 + X_L (insn);
|
||||
/* ??? It isn't clear that this is always the right answer.
|
||||
The problem occurs when the next insn is an 8 byte insn. If the
|
||||
branch is conditional there's no worry as there shouldn't be an 8
|
||||
byte insn following. The programmer may be cheating if s/he knows
|
||||
the branch will never be taken, but we don't deal with that.
|
||||
Note that the programmer is also allowed to play games by putting
|
||||
an insn with long immediate data in the delay slot and then duplicate
|
||||
the long immediate data at the branch target. Ugh! */
|
||||
if (X_N (insn) == 0)
|
||||
return BRANCH4;
|
||||
return BRANCH8;
|
||||
case 7: /* jump insns */
|
||||
if (LIMM_P (X_B (insn)))
|
||||
{
|
||||
limm = read_memory_integer (pc + 4, 4);
|
||||
*target = ARC_PC_TO_REAL_ADDRESS (limm);
|
||||
return BRANCH8;
|
||||
}
|
||||
if (SHIMM_P (X_B (insn)))
|
||||
*target = ARC_PC_TO_REAL_ADDRESS (X_D (insn));
|
||||
else
|
||||
*target = ARC_PC_TO_REAL_ADDRESS (read_register (X_B (insn)));
|
||||
if (X_Q (insn) == 0 && X_N (insn) == 0)
|
||||
return BRANCH4;
|
||||
return BRANCH8;
|
||||
default: /* arithmetic insns, etc. */
|
||||
if (LIMM_P (X_A (insn))
|
||||
|| LIMM_P (X_B (insn))
|
||||
|| LIMM_P (X_C (insn)))
|
||||
return NORMAL8;
|
||||
return NORMAL4;
|
||||
}
|
||||
}
|
||||
|
||||
/* single_step() is called just before we want to resume the inferior, if we
|
||||
want to single-step it but there is no hardware or kernel single-step
|
||||
support. We find all the possible targets of the coming instruction and
|
||||
breakpoint them.
|
||||
|
||||
single_step is also called just after the inferior stops. If we had
|
||||
set up a simulated single-step, we undo our damage. */
|
||||
|
||||
void
|
||||
arc_software_single_step (enum target_signal ignore, /* sig but we don't need it */
|
||||
int insert_breakpoints_p)
|
||||
{
|
||||
static CORE_ADDR next_pc, target;
|
||||
static int brktrg_p;
|
||||
typedef char binsn_quantum[BREAKPOINT_MAX];
|
||||
static binsn_quantum break_mem[2];
|
||||
|
||||
if (insert_breakpoints_p)
|
||||
{
|
||||
insn_type type;
|
||||
CORE_ADDR pc;
|
||||
unsigned long insn;
|
||||
|
||||
pc = read_register (PC_REGNUM);
|
||||
insn = read_memory_integer (pc, 4);
|
||||
type = get_insn_type (insn, pc, &target);
|
||||
|
||||
/* Always set a breakpoint for the insn after the branch. */
|
||||
next_pc = pc + ((type == NORMAL8 || type == BRANCH8) ? 8 : 4);
|
||||
target_insert_breakpoint (next_pc, break_mem[0]);
|
||||
|
||||
brktrg_p = 0;
|
||||
|
||||
if ((type == BRANCH4 || type == BRANCH8)
|
||||
/* Watch out for branches to the following location.
|
||||
We just stored a breakpoint there and another call to
|
||||
target_insert_breakpoint will think the real insn is the
|
||||
breakpoint we just stored there. */
|
||||
&& target != next_pc)
|
||||
{
|
||||
brktrg_p = 1;
|
||||
target_insert_breakpoint (target, break_mem[1]);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove breakpoints. */
|
||||
target_remove_breakpoint (next_pc, break_mem[0]);
|
||||
|
||||
if (brktrg_p)
|
||||
target_remove_breakpoint (target, break_mem[1]);
|
||||
|
||||
/* Fix the pc. */
|
||||
stop_pc -= DECR_PC_AFTER_BREAK;
|
||||
write_pc (stop_pc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Because of Multi-arch, GET_LONGJMP_TARGET is always defined. So test
|
||||
for a definition of JB_PC. */
|
||||
#ifdef JB_PC
|
||||
/* Figure out where the longjmp will land. Slurp the args out of the stack.
|
||||
We expect the first arg to be a pointer to the jmp_buf structure from which
|
||||
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
|
||||
This routine returns true on success. */
|
||||
|
||||
int
|
||||
get_longjmp_target (CORE_ADDR *pc)
|
||||
{
|
||||
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
|
||||
CORE_ADDR sp, jb_addr;
|
||||
|
||||
sp = read_register (SP_REGNUM);
|
||||
|
||||
if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
|
||||
buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* GET_LONGJMP_TARGET */
|
||||
|
||||
/* Disassemble one instruction. */
|
||||
|
||||
static int
|
||||
arc_print_insn (bfd_vma vma, disassemble_info *info)
|
||||
{
|
||||
static int current_mach;
|
||||
static int current_endian;
|
||||
static disassembler_ftype current_disasm;
|
||||
|
||||
if (current_disasm == NULL
|
||||
|| arc_bfd_mach_type != current_mach
|
||||
|| TARGET_BYTE_ORDER != current_endian)
|
||||
{
|
||||
current_mach = arc_bfd_mach_type;
|
||||
current_endian = TARGET_BYTE_ORDER;
|
||||
current_disasm = arc_get_disassembler (NULL);
|
||||
}
|
||||
|
||||
return (*current_disasm) (vma, info);
|
||||
}
|
||||
|
||||
/* Command to set cpu type. */
|
||||
|
||||
void
|
||||
arc_set_cpu_type_command (char *args, int from_tty)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (tmp_arc_cpu_type == NULL || *tmp_arc_cpu_type == '\0')
|
||||
{
|
||||
printf_unfiltered ("The known ARC cpu types are as follows:\n");
|
||||
for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
|
||||
printf_unfiltered ("%s\n", arc_cpu_type_table[i].name);
|
||||
|
||||
/* Restore the value. */
|
||||
tmp_arc_cpu_type = xstrdup (arc_cpu_type);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arc_set_cpu_type (tmp_arc_cpu_type))
|
||||
{
|
||||
error ("Unknown cpu type `%s'.", tmp_arc_cpu_type);
|
||||
/* Restore its value. */
|
||||
tmp_arc_cpu_type = xstrdup (arc_cpu_type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arc_show_cpu_type_command (char *args, int from_tty)
|
||||
{
|
||||
}
|
||||
|
||||
/* Modify the actual cpu type.
|
||||
Result is a boolean indicating success. */
|
||||
|
||||
static int
|
||||
arc_set_cpu_type (char *str)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
|
||||
{
|
||||
if (strcasecmp (str, arc_cpu_type_table[i].name) == 0)
|
||||
{
|
||||
arc_cpu_type = str;
|
||||
arc_bfd_mach_type = arc_cpu_type_table[i].value;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arc_tdep (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
|
||||
c = add_set_cmd ("cpu", class_support, var_string_noescape,
|
||||
(char *) &tmp_arc_cpu_type,
|
||||
"Set the type of ARC cpu in use.\n\
|
||||
This command has two purposes. In a multi-cpu system it lets one\n\
|
||||
change the cpu being debugged. It also gives one access to\n\
|
||||
cpu-type-specific registers and recognize cpu-type-specific instructions.\
|
||||
",
|
||||
&setlist);
|
||||
set_cmd_cfunc (c, arc_set_cpu_type_command);
|
||||
c = add_show_from_set (c, &showlist);
|
||||
set_cmd_cfunc (c, arc_show_cpu_type_command);
|
||||
|
||||
/* We have to use xstrdup() here because the `set' command frees it
|
||||
before setting a new value. */
|
||||
tmp_arc_cpu_type = xstrdup (DEFAULT_ARC_CPU_TYPE);
|
||||
arc_set_cpu_type (tmp_arc_cpu_type);
|
||||
|
||||
c = add_set_cmd ("displaypipeline", class_support, var_zinteger,
|
||||
(char *) &display_pipeline_p,
|
||||
"Set pipeline display (simulator only).\n\
|
||||
When enabled, the state of the pipeline after each cycle is displayed.",
|
||||
&setlist);
|
||||
c = add_show_from_set (c, &showlist);
|
||||
|
||||
c = add_set_cmd ("debugpipeline", class_support, var_zinteger,
|
||||
(char *) &debug_pipeline_p,
|
||||
"Set pipeline debug display (simulator only).\n\
|
||||
When enabled, debugging information about the pipeline is displayed.",
|
||||
&setlist);
|
||||
c = add_show_from_set (c, &showlist);
|
||||
|
||||
c = add_set_cmd ("cputimer", class_support, var_zinteger,
|
||||
(char *) &cpu_timer,
|
||||
"Set maximum cycle count (simulator only).\n\
|
||||
Control will return to gdb if the timer expires.\n\
|
||||
A negative value disables the timer.",
|
||||
&setlist);
|
||||
c = add_show_from_set (c, &showlist);
|
||||
|
||||
tm_print_insn = arc_print_insn;
|
||||
}
|
||||
911
gdb/arch-utils.c
911
gdb/arch-utils.c
@@ -1,911 +0,0 @@
|
||||
/* Dynamic architecture support for GDB, the GNU debugger.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#if GDB_MULTI_ARCH
|
||||
#include "arch-utils.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "inferior.h" /* enum CALL_DUMMY_LOCATION et.al. */
|
||||
#else
|
||||
/* Just include everything in sight so that the every old definition
|
||||
of macro is visible. */
|
||||
#include "gdb_string.h"
|
||||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "breakpoint.h"
|
||||
#include "gdb_wait.h"
|
||||
#include "gdbcore.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "target.h"
|
||||
#include "annotate.h"
|
||||
#endif
|
||||
#include "regcache.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "sim-regno.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "floatformat.h"
|
||||
|
||||
/* Use the program counter to determine the contents and size
|
||||
of a breakpoint instruction. If no target-dependent macro
|
||||
BREAKPOINT_FROM_PC has been defined to implement this function,
|
||||
assume that the breakpoint doesn't depend on the PC, and
|
||||
use the values of the BIG_BREAKPOINT and LITTLE_BREAKPOINT macros.
|
||||
Return a pointer to a string of bytes that encode a breakpoint
|
||||
instruction, stores the length of the string to *lenptr,
|
||||
and optionally adjust the pc to point to the correct memory location
|
||||
for inserting the breakpoint. */
|
||||
|
||||
const unsigned char *
|
||||
legacy_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
|
||||
{
|
||||
/* {BIG_,LITTLE_}BREAKPOINT is the sequence of bytes we insert for a
|
||||
breakpoint. On some machines, breakpoints are handled by the
|
||||
target environment and we don't have to worry about them here. */
|
||||
#ifdef BIG_BREAKPOINT
|
||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||
{
|
||||
static unsigned char big_break_insn[] = BIG_BREAKPOINT;
|
||||
*lenptr = sizeof (big_break_insn);
|
||||
return big_break_insn;
|
||||
}
|
||||
#endif
|
||||
#ifdef LITTLE_BREAKPOINT
|
||||
if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG)
|
||||
{
|
||||
static unsigned char little_break_insn[] = LITTLE_BREAKPOINT;
|
||||
*lenptr = sizeof (little_break_insn);
|
||||
return little_break_insn;
|
||||
}
|
||||
#endif
|
||||
#ifdef BREAKPOINT
|
||||
{
|
||||
static unsigned char break_insn[] = BREAKPOINT;
|
||||
*lenptr = sizeof (break_insn);
|
||||
return break_insn;
|
||||
}
|
||||
#endif
|
||||
*lenptr = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Implementation of extract return value that grubs around in the
|
||||
register cache. */
|
||||
void
|
||||
legacy_extract_return_value (struct type *type, struct regcache *regcache,
|
||||
char *valbuf)
|
||||
{
|
||||
char *registers = deprecated_grub_regcache_for_registers (regcache);
|
||||
DEPRECATED_EXTRACT_RETURN_VALUE (type, registers, valbuf);
|
||||
}
|
||||
|
||||
int
|
||||
legacy_register_sim_regno (int regnum)
|
||||
{
|
||||
/* Only makes sense to supply raw registers. */
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS);
|
||||
/* NOTE: cagney/2002-05-13: The old code did it this way and it is
|
||||
suspected that some GDB/SIM combinations may rely on this
|
||||
behavour. The default should be one2one_register_sim_regno
|
||||
(below). */
|
||||
if (REGISTER_NAME (regnum) != NULL
|
||||
&& REGISTER_NAME (regnum)[0] != '\0')
|
||||
return regnum;
|
||||
else
|
||||
return LEGACY_SIM_REGNO_IGNORE;
|
||||
}
|
||||
|
||||
int
|
||||
generic_frameless_function_invocation_not (struct frame_info *fi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_return_value_on_stack_not (struct type *type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
generic_skip_trampoline_code (CORE_ADDR pc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_solib_call_trampoline (CORE_ADDR pc, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
legacy_register_name (int i)
|
||||
{
|
||||
#ifdef REGISTER_NAMES
|
||||
static char *names[] = REGISTER_NAMES;
|
||||
if (i < 0 || i >= (sizeof (names) / sizeof (*names)))
|
||||
return NULL;
|
||||
else
|
||||
return names[i];
|
||||
#else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"legacy_register_name: called.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (CALL_DUMMY)
|
||||
LONGEST legacy_call_dummy_words[] = CALL_DUMMY;
|
||||
#else
|
||||
LONGEST legacy_call_dummy_words[1];
|
||||
#endif
|
||||
int legacy_sizeof_call_dummy_words = sizeof (legacy_call_dummy_words);
|
||||
|
||||
void
|
||||
generic_remote_translate_xfer_address (CORE_ADDR gdb_addr, int gdb_len,
|
||||
CORE_ADDR * rem_addr, int *rem_len)
|
||||
{
|
||||
*rem_addr = gdb_addr;
|
||||
*rem_len = gdb_len;
|
||||
}
|
||||
|
||||
int
|
||||
generic_prologue_frameless_p (CORE_ADDR ip)
|
||||
{
|
||||
return ip == SKIP_PROLOGUE (ip);
|
||||
}
|
||||
|
||||
/* New/multi-arched targets should use the correct gdbarch field
|
||||
instead of using this global pointer. */
|
||||
int
|
||||
legacy_print_insn (bfd_vma vma, disassemble_info *info)
|
||||
{
|
||||
return (*tm_print_insn) (vma, info);
|
||||
}
|
||||
|
||||
/* Helper functions for INNER_THAN */
|
||||
|
||||
int
|
||||
core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs)
|
||||
{
|
||||
return (lhs < rhs);
|
||||
}
|
||||
|
||||
int
|
||||
core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs)
|
||||
{
|
||||
return (lhs > rhs);
|
||||
}
|
||||
|
||||
|
||||
/* Helper functions for TARGET_{FLOAT,DOUBLE}_FORMAT */
|
||||
|
||||
const struct floatformat *
|
||||
default_float_format (struct gdbarch *gdbarch)
|
||||
{
|
||||
#if GDB_MULTI_ARCH
|
||||
int byte_order = gdbarch_byte_order (gdbarch);
|
||||
#else
|
||||
int byte_order = TARGET_BYTE_ORDER;
|
||||
#endif
|
||||
switch (byte_order)
|
||||
{
|
||||
case BFD_ENDIAN_BIG:
|
||||
return &floatformat_ieee_single_big;
|
||||
case BFD_ENDIAN_LITTLE:
|
||||
return &floatformat_ieee_single_little;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"default_float_format: bad byte order");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const struct floatformat *
|
||||
default_double_format (struct gdbarch *gdbarch)
|
||||
{
|
||||
#if GDB_MULTI_ARCH
|
||||
int byte_order = gdbarch_byte_order (gdbarch);
|
||||
#else
|
||||
int byte_order = TARGET_BYTE_ORDER;
|
||||
#endif
|
||||
switch (byte_order)
|
||||
{
|
||||
case BFD_ENDIAN_BIG:
|
||||
return &floatformat_ieee_double_big;
|
||||
case BFD_ENDIAN_LITTLE:
|
||||
return &floatformat_ieee_double_little;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"default_double_format: bad byte order");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
|
||||
struct frame_info *frame)
|
||||
{
|
||||
#ifdef FLOAT_INFO
|
||||
#if GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL
|
||||
#error "FLOAT_INFO defined in multi-arch"
|
||||
#endif
|
||||
FLOAT_INFO;
|
||||
#else
|
||||
fprintf_filtered (file, "\
|
||||
No floating point info available for this processor.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Misc helper functions for targets. */
|
||||
|
||||
int
|
||||
frame_num_args_unknown (struct frame_info *fi)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
generic_register_convertible_not (int num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Under some ABI's that specify the `struct convention' for returning
|
||||
structures by value, by the time we've returned from the function,
|
||||
the return value is sitting there in the caller's buffer, but GDB
|
||||
has no way to find the address of that buffer.
|
||||
|
||||
On such architectures, use this function as your
|
||||
extract_struct_value_address method. When asked to a struct
|
||||
returned by value in this fashion, GDB will print a nice error
|
||||
message, instead of garbage. */
|
||||
CORE_ADDR
|
||||
generic_cannot_extract_struct_value_address (char *dummy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
core_addr_identity (CORE_ADDR addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
int
|
||||
no_op_reg_to_regnum (int reg)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* For use by frame_args_address and frame_locals_address. */
|
||||
CORE_ADDR
|
||||
default_frame_address (struct frame_info *fi)
|
||||
{
|
||||
return fi->frame;
|
||||
}
|
||||
|
||||
/* Default prepare_to_procced(). */
|
||||
int
|
||||
default_prepare_to_proceed (int select_it)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generic prepare_to_proceed(). This one should be suitable for most
|
||||
targets that support threads. */
|
||||
int
|
||||
generic_prepare_to_proceed (int select_it)
|
||||
{
|
||||
ptid_t wait_ptid;
|
||||
struct target_waitstatus wait_status;
|
||||
|
||||
/* Get the last target status returned by target_wait(). */
|
||||
get_last_target_status (&wait_ptid, &wait_status);
|
||||
|
||||
/* Make sure we were stopped either at a breakpoint, or because
|
||||
of a Ctrl-C. */
|
||||
if (wait_status.kind != TARGET_WAITKIND_STOPPED
|
||||
|| (wait_status.value.sig != TARGET_SIGNAL_TRAP &&
|
||||
wait_status.value.sig != TARGET_SIGNAL_INT))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ptid_equal (wait_ptid, minus_one_ptid)
|
||||
&& !ptid_equal (inferior_ptid, wait_ptid))
|
||||
{
|
||||
/* Switched over from WAIT_PID. */
|
||||
CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
|
||||
|
||||
if (wait_pc != read_pc ())
|
||||
{
|
||||
if (select_it)
|
||||
{
|
||||
/* Switch back to WAIT_PID thread. */
|
||||
inferior_ptid = wait_ptid;
|
||||
|
||||
/* FIXME: This stuff came from switch_to_thread() in
|
||||
thread.c (which should probably be a public function). */
|
||||
flush_cached_frames ();
|
||||
registers_changed ();
|
||||
stop_pc = wait_pc;
|
||||
select_frame (get_current_frame ());
|
||||
}
|
||||
/* We return 1 to indicate that there is a breakpoint here,
|
||||
so we need to step over it before continuing to avoid
|
||||
hitting it straight away. */
|
||||
if (breakpoint_here_p (wait_pc))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
init_frame_pc_noop (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
init_frame_pc_default (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
if (fromleaf)
|
||||
prev->pc = SAVED_PC_AFTER_CALL (prev->next);
|
||||
else if (prev->next != NULL)
|
||||
prev->pc = FRAME_SAVED_PC (prev->next);
|
||||
else
|
||||
prev->pc = read_pc ();
|
||||
}
|
||||
|
||||
void
|
||||
default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
default_coff_make_msymbol_special (int val, struct minimal_symbol *msym)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
cannot_register_not (int regnum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Legacy version of target_virtual_frame_pointer(). Assumes that
|
||||
there is an FP_REGNUM and that it is the same, cooked or raw. */
|
||||
|
||||
void
|
||||
legacy_virtual_frame_pointer (CORE_ADDR pc,
|
||||
int *frame_regnum,
|
||||
LONGEST *frame_offset)
|
||||
{
|
||||
gdb_assert (FP_REGNUM >= 0);
|
||||
*frame_regnum = FP_REGNUM;
|
||||
*frame_offset = 0;
|
||||
}
|
||||
|
||||
/* Assume the world is sane, every register's virtual and real size
|
||||
is identical. */
|
||||
|
||||
int
|
||||
generic_register_size (int regnum)
|
||||
{
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
|
||||
return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
|
||||
}
|
||||
|
||||
#if !defined (IN_SIGTRAMP)
|
||||
#if defined (SIGTRAMP_START)
|
||||
#define IN_SIGTRAMP(pc, name) \
|
||||
((pc) >= SIGTRAMP_START(pc) \
|
||||
&& (pc) < SIGTRAMP_END(pc) \
|
||||
)
|
||||
#else
|
||||
#define IN_SIGTRAMP(pc, name) \
|
||||
(name && STREQ ("_sigtramp", name))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int
|
||||
legacy_pc_in_sigtramp (CORE_ADDR pc, char *name)
|
||||
{
|
||||
return IN_SIGTRAMP(pc, name);
|
||||
}
|
||||
|
||||
int
|
||||
legacy_convert_register_p (int regnum)
|
||||
{
|
||||
return REGISTER_CONVERTIBLE (regnum);
|
||||
}
|
||||
|
||||
void
|
||||
legacy_register_to_value (int regnum, struct type *type,
|
||||
char *from, char *to)
|
||||
{
|
||||
REGISTER_CONVERT_TO_VIRTUAL (regnum, type, from, to);
|
||||
}
|
||||
|
||||
void
|
||||
legacy_value_to_register (struct type *type, int regnum,
|
||||
char *from, char *to)
|
||||
{
|
||||
REGISTER_CONVERT_TO_RAW (type, regnum, from, to);
|
||||
}
|
||||
|
||||
|
||||
/* Functions to manipulate the endianness of the target. */
|
||||
|
||||
/* ``target_byte_order'' is only used when non- multi-arch.
|
||||
Multi-arch targets obtain the current byte order using the
|
||||
TARGET_BYTE_ORDER gdbarch method.
|
||||
|
||||
The choice of initial value is entirely arbitrary. During startup,
|
||||
the function initialize_current_architecture() updates this value
|
||||
based on default byte-order information extracted from BFD. */
|
||||
int target_byte_order = BFD_ENDIAN_BIG;
|
||||
int target_byte_order_auto = 1;
|
||||
|
||||
static const char endian_big[] = "big";
|
||||
static const char endian_little[] = "little";
|
||||
static const char endian_auto[] = "auto";
|
||||
static const char *endian_enum[] =
|
||||
{
|
||||
endian_big,
|
||||
endian_little,
|
||||
endian_auto,
|
||||
NULL,
|
||||
};
|
||||
static const char *set_endian_string;
|
||||
|
||||
/* Called by ``show endian''. */
|
||||
|
||||
static void
|
||||
show_endian (char *args, int from_tty)
|
||||
{
|
||||
if (TARGET_BYTE_ORDER_AUTO)
|
||||
printf_unfiltered ("The target endianness is set automatically (currently %s endian)\n",
|
||||
(TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little"));
|
||||
else
|
||||
printf_unfiltered ("The target is assumed to be %s endian\n",
|
||||
(TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little"));
|
||||
}
|
||||
|
||||
static void
|
||||
set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
if (set_endian_string == endian_auto)
|
||||
{
|
||||
target_byte_order_auto = 1;
|
||||
}
|
||||
else if (set_endian_string == endian_little)
|
||||
{
|
||||
target_byte_order_auto = 0;
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_LITTLE;
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
printf_unfiltered ("Little endian target not supported by GDB\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_byte_order = BFD_ENDIAN_LITTLE;
|
||||
}
|
||||
}
|
||||
else if (set_endian_string == endian_big)
|
||||
{
|
||||
target_byte_order_auto = 0;
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
printf_unfiltered ("Big endian target not supported by GDB\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_byte_order = BFD_ENDIAN_BIG;
|
||||
}
|
||||
}
|
||||
else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_endian: bad value");
|
||||
show_endian (NULL, from_tty);
|
||||
}
|
||||
|
||||
/* Set the endianness from a BFD. */
|
||||
|
||||
static void
|
||||
set_endian_from_file (bfd *abfd)
|
||||
{
|
||||
int want;
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_endian_from_file: not for multi-arch");
|
||||
if (bfd_big_endian (abfd))
|
||||
want = BFD_ENDIAN_BIG;
|
||||
else
|
||||
want = BFD_ENDIAN_LITTLE;
|
||||
if (TARGET_BYTE_ORDER_AUTO)
|
||||
target_byte_order = want;
|
||||
else if (TARGET_BYTE_ORDER != want)
|
||||
warning ("%s endian file does not match %s endian target.",
|
||||
want == BFD_ENDIAN_BIG ? "big" : "little",
|
||||
TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little");
|
||||
}
|
||||
|
||||
|
||||
/* Functions to manipulate the architecture of the target */
|
||||
|
||||
enum set_arch { set_arch_auto, set_arch_manual };
|
||||
|
||||
int target_architecture_auto = 1;
|
||||
|
||||
const char *set_architecture_string;
|
||||
|
||||
/* Old way of changing the current architecture. */
|
||||
|
||||
extern const struct bfd_arch_info bfd_default_arch_struct;
|
||||
const struct bfd_arch_info *target_architecture = &bfd_default_arch_struct;
|
||||
int (*target_architecture_hook) (const struct bfd_arch_info *ap);
|
||||
|
||||
static int
|
||||
arch_ok (const struct bfd_arch_info *arch)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"arch_ok: not multi-arched");
|
||||
/* Should be performing the more basic check that the binary is
|
||||
compatible with GDB. */
|
||||
/* Check with the target that the architecture is valid. */
|
||||
return (target_architecture_hook == NULL
|
||||
|| target_architecture_hook (arch));
|
||||
}
|
||||
|
||||
static void
|
||||
set_arch (const struct bfd_arch_info *arch,
|
||||
enum set_arch type)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_arch: not multi-arched");
|
||||
switch (type)
|
||||
{
|
||||
case set_arch_auto:
|
||||
if (!arch_ok (arch))
|
||||
warning ("Target may not support %s architecture",
|
||||
arch->printable_name);
|
||||
target_architecture = arch;
|
||||
break;
|
||||
case set_arch_manual:
|
||||
if (!arch_ok (arch))
|
||||
{
|
||||
printf_unfiltered ("Target does not support `%s' architecture.\n",
|
||||
arch->printable_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_architecture_auto = 0;
|
||||
target_architecture = arch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (gdbarch_debug)
|
||||
gdbarch_dump (current_gdbarch, gdb_stdlog);
|
||||
}
|
||||
|
||||
/* Set the architecture from arch/machine (deprecated) */
|
||||
|
||||
void
|
||||
set_architecture_from_arch_mach (enum bfd_architecture arch,
|
||||
unsigned long mach)
|
||||
{
|
||||
const struct bfd_arch_info *wanted = bfd_lookup_arch (arch, mach);
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture_from_arch_mach: not multi-arched");
|
||||
if (wanted != NULL)
|
||||
set_arch (wanted, set_arch_manual);
|
||||
else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"gdbarch: hardwired architecture/machine not recognized");
|
||||
}
|
||||
|
||||
/* Set the architecture from a BFD (deprecated) */
|
||||
|
||||
static void
|
||||
set_architecture_from_file (bfd *abfd)
|
||||
{
|
||||
const struct bfd_arch_info *wanted = bfd_get_arch_info (abfd);
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture_from_file: not multi-arched");
|
||||
if (target_architecture_auto)
|
||||
{
|
||||
set_arch (wanted, set_arch_auto);
|
||||
}
|
||||
else if (wanted != target_architecture)
|
||||
{
|
||||
warning ("%s architecture file may be incompatible with %s target.",
|
||||
wanted->printable_name,
|
||||
target_architecture->printable_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called if the user enters ``show architecture'' without an
|
||||
argument. */
|
||||
|
||||
static void
|
||||
show_architecture (char *args, int from_tty)
|
||||
{
|
||||
const char *arch;
|
||||
arch = TARGET_ARCHITECTURE->printable_name;
|
||||
if (target_architecture_auto)
|
||||
printf_filtered ("The target architecture is set automatically (currently %s)\n", arch);
|
||||
else
|
||||
printf_filtered ("The target architecture is assumed to be %s\n", arch);
|
||||
}
|
||||
|
||||
|
||||
/* Called if the user enters ``set architecture'' with or without an
|
||||
argument. */
|
||||
|
||||
static void
|
||||
set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
if (strcmp (set_architecture_string, "auto") == 0)
|
||||
{
|
||||
target_architecture_auto = 1;
|
||||
}
|
||||
else if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.bfd_arch_info = bfd_scan_arch (set_architecture_string);
|
||||
if (info.bfd_arch_info == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture: bfd_scan_arch failed");
|
||||
if (gdbarch_update_p (info))
|
||||
target_architecture_auto = 0;
|
||||
else
|
||||
printf_unfiltered ("Architecture `%s' not recognized.\n",
|
||||
set_architecture_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct bfd_arch_info *arch
|
||||
= bfd_scan_arch (set_architecture_string);
|
||||
if (arch == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture: bfd_scan_arch failed");
|
||||
set_arch (arch, set_arch_manual);
|
||||
}
|
||||
show_architecture (NULL, from_tty);
|
||||
}
|
||||
|
||||
/* Set the dynamic target-system-dependent parameters (architecture,
|
||||
byte-order) using information found in the BFD */
|
||||
|
||||
void
|
||||
set_gdbarch_from_file (bfd *abfd)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.abfd = abfd;
|
||||
if (! gdbarch_update_p (info))
|
||||
error ("Architecture of file not recognized.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
set_architecture_from_file (abfd);
|
||||
set_endian_from_file (abfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the current architecture. Update the ``set
|
||||
architecture'' command so that it specifies a list of valid
|
||||
architectures. */
|
||||
|
||||
#ifdef DEFAULT_BFD_ARCH
|
||||
extern const bfd_arch_info_type DEFAULT_BFD_ARCH;
|
||||
static const bfd_arch_info_type *default_bfd_arch = &DEFAULT_BFD_ARCH;
|
||||
#else
|
||||
static const bfd_arch_info_type *default_bfd_arch;
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULT_BFD_VEC
|
||||
extern const bfd_target DEFAULT_BFD_VEC;
|
||||
static const bfd_target *default_bfd_vec = &DEFAULT_BFD_VEC;
|
||||
#else
|
||||
static const bfd_target *default_bfd_vec;
|
||||
#endif
|
||||
|
||||
void
|
||||
initialize_current_architecture (void)
|
||||
{
|
||||
const char **arches = gdbarch_printable_names ();
|
||||
|
||||
/* determine a default architecture and byte order. */
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
|
||||
/* Find a default architecture. */
|
||||
if (info.bfd_arch_info == NULL
|
||||
&& default_bfd_arch != NULL)
|
||||
info.bfd_arch_info = default_bfd_arch;
|
||||
if (info.bfd_arch_info == NULL)
|
||||
{
|
||||
/* Choose the architecture by taking the first one
|
||||
alphabetically. */
|
||||
const char *chosen = arches[0];
|
||||
const char **arch;
|
||||
for (arch = arches; *arch != NULL; arch++)
|
||||
{
|
||||
if (strcmp (*arch, chosen) < 0)
|
||||
chosen = *arch;
|
||||
}
|
||||
if (chosen == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"initialize_current_architecture: No arch");
|
||||
info.bfd_arch_info = bfd_scan_arch (chosen);
|
||||
if (info.bfd_arch_info == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"initialize_current_architecture: Arch not found");
|
||||
}
|
||||
|
||||
/* Take several guesses at a byte order. */
|
||||
if (info.byte_order == BFD_ENDIAN_UNKNOWN
|
||||
&& default_bfd_vec != NULL)
|
||||
{
|
||||
/* Extract BFD's default vector's byte order. */
|
||||
switch (default_bfd_vec->byteorder)
|
||||
{
|
||||
case BFD_ENDIAN_BIG:
|
||||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
break;
|
||||
case BFD_ENDIAN_LITTLE:
|
||||
info.byte_order = BFD_ENDIAN_LITTLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (info.byte_order == BFD_ENDIAN_UNKNOWN)
|
||||
{
|
||||
/* look for ``*el-*'' in the target name. */
|
||||
const char *chp;
|
||||
chp = strchr (target_name, '-');
|
||||
if (chp != NULL
|
||||
&& chp - 2 >= target_name
|
||||
&& strncmp (chp - 2, "el", 2) == 0)
|
||||
info.byte_order = BFD_ENDIAN_LITTLE;
|
||||
}
|
||||
if (info.byte_order == BFD_ENDIAN_UNKNOWN)
|
||||
{
|
||||
/* Wire it to big-endian!!! */
|
||||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
}
|
||||
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"initialize_current_architecture: Selection of initial architecture failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the multi-arch logic comes up with a byte-order (from BFD)
|
||||
use it for the non-multi-arch case. */
|
||||
if (info.byte_order != BFD_ENDIAN_UNKNOWN)
|
||||
target_byte_order = info.byte_order;
|
||||
initialize_non_multiarch ();
|
||||
}
|
||||
|
||||
/* Create the ``set architecture'' command appending ``auto'' to the
|
||||
list of architectures. */
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
/* Append ``auto''. */
|
||||
int nr;
|
||||
for (nr = 0; arches[nr] != NULL; nr++);
|
||||
arches = xrealloc (arches, sizeof (char*) * (nr + 2));
|
||||
arches[nr + 0] = "auto";
|
||||
arches[nr + 1] = NULL;
|
||||
/* FIXME: add_set_enum_cmd() uses an array of ``char *'' instead
|
||||
of ``const char *''. We just happen to know that the casts are
|
||||
safe. */
|
||||
c = add_set_enum_cmd ("architecture", class_support,
|
||||
arches, &set_architecture_string,
|
||||
"Set architecture of target.",
|
||||
&setlist);
|
||||
set_cmd_sfunc (c, set_architecture);
|
||||
add_alias_cmd ("processor", "architecture", class_support, 1, &setlist);
|
||||
/* Don't use set_from_show - need to print both auto/manual and
|
||||
current setting. */
|
||||
add_cmd ("architecture", class_support, show_architecture,
|
||||
"Show the current target architecture", &showlist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize a gdbarch info to values that will be automatically
|
||||
overridden. Note: Originally, this ``struct info'' was initialized
|
||||
using memset(0). Unfortunatly, that ran into problems, namely
|
||||
BFD_ENDIAN_BIG is zero. An explicit initialization function that
|
||||
can explicitly set each field to a well defined value is used. */
|
||||
|
||||
void
|
||||
gdbarch_info_init (struct gdbarch_info *info)
|
||||
{
|
||||
memset (info, 0, sizeof (struct gdbarch_info));
|
||||
info->byte_order = BFD_ENDIAN_UNKNOWN;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
extern initialize_file_ftype _initialize_gdbarch_utils;
|
||||
|
||||
void
|
||||
_initialize_gdbarch_utils (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
c = add_set_enum_cmd ("endian", class_support,
|
||||
endian_enum, &set_endian_string,
|
||||
"Set endianness of target.",
|
||||
&setlist);
|
||||
set_cmd_sfunc (c, set_endian);
|
||||
/* Don't use set_from_show - need to print both auto/manual and
|
||||
current setting. */
|
||||
add_cmd ("endian", class_support, show_endian,
|
||||
"Show the current byte-order", &showlist);
|
||||
}
|
||||
180
gdb/arch-utils.h
180
gdb/arch-utils.h
@@ -1,180 +0,0 @@
|
||||
/* Dynamic architecture support for GDB, the GNU debugger.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef GDBARCH_UTILS_H
|
||||
#define GDBARCH_UTILS_H
|
||||
|
||||
/* gdbarch trace variable */
|
||||
extern int gdbarch_debug;
|
||||
|
||||
/* Fallback for register convertible. */
|
||||
extern gdbarch_register_convertible_ftype generic_register_convertible_not;
|
||||
|
||||
extern CORE_ADDR generic_cannot_extract_struct_value_address (char *dummy);
|
||||
|
||||
/* Helper function for targets that don't know how my arguments are
|
||||
being passed */
|
||||
extern gdbarch_frame_num_args_ftype frame_num_args_unknown;
|
||||
|
||||
/* Implementation of breakpoint from PC using any of the deprecated
|
||||
macros BREAKPOINT, LITTLE_BREAKPOINT, BIG_BREAPOINT. For legacy
|
||||
targets that don't yet implement their own breakpoint_from_pc(). */
|
||||
extern gdbarch_breakpoint_from_pc_ftype legacy_breakpoint_from_pc;
|
||||
|
||||
/* Implementation of extract return value that grubs around in the
|
||||
register cache. */
|
||||
extern gdbarch_extract_return_value_ftype legacy_extract_return_value;
|
||||
|
||||
/* Frameless functions not identifable. */
|
||||
extern gdbarch_frameless_function_invocation_ftype generic_frameless_function_invocation_not;
|
||||
|
||||
/* Only structures, unions, and arrays are returned using the struct
|
||||
convention. Note that arrays are never passed by value in the C
|
||||
language family, so that case is irrelevant for C. */
|
||||
extern gdbarch_return_value_on_stack_ftype generic_return_value_on_stack_not;
|
||||
|
||||
/* Map onto old REGISTER_NAMES. */
|
||||
extern const char *legacy_register_name (int i);
|
||||
|
||||
/* Accessor for old global function pointer for disassembly. */
|
||||
extern int legacy_print_insn (bfd_vma vma, disassemble_info *info);
|
||||
|
||||
/* Backward compatible call_dummy_words. */
|
||||
extern LONGEST legacy_call_dummy_words[];
|
||||
extern int legacy_sizeof_call_dummy_words;
|
||||
|
||||
/* Typical remote_translate_xfer_address */
|
||||
extern gdbarch_remote_translate_xfer_address_ftype generic_remote_translate_xfer_address;
|
||||
|
||||
/* Generic implementation of prologue_frameless_p. Just calls
|
||||
SKIP_PROLOG and checks the return value to see if it actually
|
||||
changed. */
|
||||
extern gdbarch_prologue_frameless_p_ftype generic_prologue_frameless_p;
|
||||
|
||||
/* The only possible cases for inner_than. */
|
||||
extern int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
||||
extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
||||
|
||||
/* Floating point values. */
|
||||
extern const struct floatformat *default_float_format (struct gdbarch *gdbarch);
|
||||
extern const struct floatformat *default_double_format (struct gdbarch *gdbarch);
|
||||
|
||||
/* Helper function for targets that don't know how my arguments are
|
||||
being passed */
|
||||
extern int frame_num_args_unknown (struct frame_info *fi);
|
||||
|
||||
|
||||
/* The following DEPRECATED interfaces are for pre- multi-arch legacy
|
||||
targets. */
|
||||
|
||||
/* DEPRECATED pre- multi-arch interface. Explicitly set the dynamic
|
||||
target-system-dependent parameters based on bfd_architecture and
|
||||
machine. This function is deprecated, use
|
||||
set_gdbarch_from_arch_machine(). */
|
||||
|
||||
extern void set_architecture_from_arch_mach (enum bfd_architecture, unsigned long);
|
||||
|
||||
/* DEPRECATED pre- multi-arch interface. Notify the target dependent
|
||||
backend of a change to the selected architecture. A zero return
|
||||
status indicates that the target did not like the change. */
|
||||
|
||||
extern int (*target_architecture_hook) (const struct bfd_arch_info *);
|
||||
|
||||
/* Identity function on a CORE_ADDR. Just returns its parameter. */
|
||||
|
||||
extern CORE_ADDR core_addr_identity (CORE_ADDR addr);
|
||||
|
||||
/* No-op conversion of reg to regnum. */
|
||||
|
||||
extern int no_op_reg_to_regnum (int reg);
|
||||
|
||||
/* Default frame_args_address and frame_locals_address. */
|
||||
|
||||
extern CORE_ADDR default_frame_address (struct frame_info *);
|
||||
|
||||
/* Default prepare_to_procced. */
|
||||
|
||||
extern int default_prepare_to_proceed (int select_it);
|
||||
|
||||
extern int generic_prepare_to_proceed (int select_it);
|
||||
|
||||
/* Versions of init_frame_pc(). Do nothing; do the default. */
|
||||
|
||||
void init_frame_pc_noop (int fromleaf, struct frame_info *prev);
|
||||
|
||||
void init_frame_pc_default (int fromleaf, struct frame_info *prev);
|
||||
|
||||
/* Do nothing version of elf_make_msymbol_special. */
|
||||
|
||||
void default_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym);
|
||||
|
||||
/* Do nothing version of coff_make_msymbol_special. */
|
||||
|
||||
void default_coff_make_msymbol_special (int val, struct minimal_symbol *msym);
|
||||
|
||||
/* Version of cannot_fetch_register() / cannot_store_register() that
|
||||
always fails. */
|
||||
|
||||
int cannot_register_not (int regnum);
|
||||
|
||||
/* Legacy version of target_virtual_frame_pointer(). Assumes that
|
||||
there is an FP_REGNUM and that it is the same, cooked or raw. */
|
||||
|
||||
extern gdbarch_virtual_frame_pointer_ftype legacy_virtual_frame_pointer;
|
||||
|
||||
extern CORE_ADDR generic_skip_trampoline_code (CORE_ADDR pc);
|
||||
|
||||
extern int generic_in_solib_call_trampoline (CORE_ADDR pc, char *name);
|
||||
|
||||
extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc);
|
||||
|
||||
extern void default_print_float_info (struct gdbarch *gdbarch,
|
||||
struct ui_file *file,
|
||||
struct frame_info *frame);
|
||||
|
||||
/* Assume that the world is sane, a registers raw and virtual size
|
||||
both match its type. */
|
||||
|
||||
extern int generic_register_size (int regnum);
|
||||
|
||||
/* Prop up old targets that use various IN_SIGTRAMP() macros. */
|
||||
extern int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name);
|
||||
|
||||
/* The orginal register_convert*() functions were overloaded. They
|
||||
were used to both: convert between virtual and raw register formats
|
||||
(something that is discouraged); and to convert a register to the
|
||||
type of a corresponding variable. These legacy functions preserve
|
||||
that overloaded behavour in existing targets. */
|
||||
extern int legacy_convert_register_p (int regnum);
|
||||
extern void legacy_register_to_value (int regnum, struct type *type, char *from, char *to);
|
||||
extern void legacy_value_to_register (struct type *type, int regnum, char *from, char *to);
|
||||
|
||||
/* For compatibility with older architectures, returns
|
||||
(LEGACY_SIM_REGNO_IGNORE) when the register doesn't have a valid
|
||||
name. */
|
||||
|
||||
extern int legacy_register_sim_regno (int regnum);
|
||||
|
||||
/* Initialize a ``struct info''. Can't use memset(0) since some
|
||||
default values are not zero. */
|
||||
extern void gdbarch_info_init (struct gdbarch_info *info);
|
||||
|
||||
#endif
|
||||
@@ -1,698 +0,0 @@
|
||||
/* GNU/Linux on ARM native support.
|
||||
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "gdb_string.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "arm-tdep.h"
|
||||
|
||||
#include <sys/user.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
extern int arm_apcs_32;
|
||||
|
||||
#define typeNone 0x00
|
||||
#define typeSingle 0x01
|
||||
#define typeDouble 0x02
|
||||
#define typeExtended 0x03
|
||||
#define FPWORDS 28
|
||||
#define ARM_CPSR_REGNUM 16
|
||||
|
||||
typedef union tagFPREG
|
||||
{
|
||||
unsigned int fSingle;
|
||||
unsigned int fDouble[2];
|
||||
unsigned int fExtended[3];
|
||||
}
|
||||
FPREG;
|
||||
|
||||
typedef struct tagFPA11
|
||||
{
|
||||
FPREG fpreg[8]; /* 8 floating point registers */
|
||||
unsigned int fpsr; /* floating point status register */
|
||||
unsigned int fpcr; /* floating point control register */
|
||||
unsigned char fType[8]; /* type of floating point value held in
|
||||
floating point registers. */
|
||||
int initflag; /* NWFPE initialization flag. */
|
||||
}
|
||||
FPA11;
|
||||
|
||||
/* The following variables are used to determine the version of the
|
||||
underlying GNU/Linux operating system. Examples:
|
||||
|
||||
GNU/Linux 2.0.35 GNU/Linux 2.2.12
|
||||
os_version = 0x00020023 os_version = 0x0002020c
|
||||
os_major = 2 os_major = 2
|
||||
os_minor = 0 os_minor = 2
|
||||
os_release = 35 os_release = 12
|
||||
|
||||
Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
|
||||
|
||||
These are initialized using get_linux_version() from
|
||||
_initialize_arm_linux_nat(). */
|
||||
|
||||
static unsigned int os_version, os_major, os_minor, os_release;
|
||||
|
||||
/* On GNU/Linux, threads are implemented as pseudo-processes, in which
|
||||
case we may be tracing more than one process at a time. In that
|
||||
case, inferior_ptid will contain the main process ID and the
|
||||
individual thread (process) ID. get_thread_id () is used to get
|
||||
the thread id if it's available, and the process id otherwise. */
|
||||
|
||||
int
|
||||
get_thread_id (ptid_t ptid)
|
||||
{
|
||||
int tid = TIDGET (ptid);
|
||||
if (0 == tid)
|
||||
tid = PIDGET (ptid);
|
||||
return tid;
|
||||
}
|
||||
#define GET_THREAD_ID(PTID) get_thread_id ((PTID));
|
||||
|
||||
static void
|
||||
fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
mem[0] = fpa11->fpreg[fn].fSingle;
|
||||
mem[1] = 0;
|
||||
mem[2] = 0;
|
||||
supply_register (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
mem[0] = fpa11->fpreg[fn].fDouble[1];
|
||||
mem[1] = fpa11->fpreg[fn].fDouble[0];
|
||||
mem[2] = 0;
|
||||
supply_register (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_nwfpe_none (unsigned int fn)
|
||||
{
|
||||
unsigned int mem[3] =
|
||||
{0, 0, 0};
|
||||
|
||||
supply_register (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
|
||||
mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
|
||||
mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
|
||||
supply_register (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_nwfpe_register (int regno, FPA11 * fpa11)
|
||||
{
|
||||
int fn = regno - ARM_F0_REGNUM;
|
||||
|
||||
switch (fpa11->fType[fn])
|
||||
{
|
||||
case typeSingle:
|
||||
fetch_nwfpe_single (fn, fpa11);
|
||||
break;
|
||||
|
||||
case typeDouble:
|
||||
fetch_nwfpe_double (fn, fpa11);
|
||||
break;
|
||||
|
||||
case typeExtended:
|
||||
fetch_nwfpe_extended (fn, fpa11);
|
||||
break;
|
||||
|
||||
default:
|
||||
fetch_nwfpe_none (fn);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_nwfpe_single (unsigned int fn, FPA11 *fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
fpa11->fpreg[fn].fSingle = mem[0];
|
||||
fpa11->fType[fn] = typeSingle;
|
||||
}
|
||||
|
||||
static void
|
||||
store_nwfpe_double (unsigned int fn, FPA11 *fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
fpa11->fpreg[fn].fDouble[1] = mem[0];
|
||||
fpa11->fpreg[fn].fDouble[0] = mem[1];
|
||||
fpa11->fType[fn] = typeDouble;
|
||||
}
|
||||
|
||||
void
|
||||
store_nwfpe_extended (unsigned int fn, FPA11 *fpa11)
|
||||
{
|
||||
unsigned int mem[3];
|
||||
|
||||
regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
|
||||
fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
|
||||
fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
|
||||
fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
|
||||
fpa11->fType[fn] = typeDouble;
|
||||
}
|
||||
|
||||
void
|
||||
store_nwfpe_register (int regno, FPA11 * fpa11)
|
||||
{
|
||||
if (register_cached (regno))
|
||||
{
|
||||
unsigned int fn = regno - ARM_F0_REGNUM;
|
||||
switch (fpa11->fType[fn])
|
||||
{
|
||||
case typeSingle:
|
||||
store_nwfpe_single (fn, fpa11);
|
||||
break;
|
||||
|
||||
case typeDouble:
|
||||
store_nwfpe_double (fn, fpa11);
|
||||
break;
|
||||
|
||||
case typeExtended:
|
||||
store_nwfpe_extended (fn, fpa11);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get the value of a particular register from the floating point
|
||||
state of the process and store it into regcache. */
|
||||
|
||||
static void
|
||||
fetch_fpregister (int regno)
|
||||
{
|
||||
int ret, tid;
|
||||
FPA11 fp;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Read the floating point state. */
|
||||
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch floating point register.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fetch fpsr. */
|
||||
if (ARM_FPS_REGNUM == regno)
|
||||
supply_register (ARM_FPS_REGNUM, (char *) &fp.fpsr);
|
||||
|
||||
/* Fetch the floating point register. */
|
||||
if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
|
||||
{
|
||||
int fn = regno - ARM_F0_REGNUM;
|
||||
|
||||
switch (fp.fType[fn])
|
||||
{
|
||||
case typeSingle:
|
||||
fetch_nwfpe_single (fn, &fp);
|
||||
break;
|
||||
|
||||
case typeDouble:
|
||||
fetch_nwfpe_double (fn, &fp);
|
||||
break;
|
||||
|
||||
case typeExtended:
|
||||
fetch_nwfpe_extended (fn, &fp);
|
||||
break;
|
||||
|
||||
default:
|
||||
fetch_nwfpe_none (fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the whole floating point state of the process and store it
|
||||
into regcache. */
|
||||
|
||||
static void
|
||||
fetch_fpregs (void)
|
||||
{
|
||||
int ret, regno, tid;
|
||||
FPA11 fp;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Read the floating point state. */
|
||||
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch the floating point registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fetch fpsr. */
|
||||
supply_register (ARM_FPS_REGNUM, (char *) &fp.fpsr);
|
||||
|
||||
/* Fetch the floating point registers. */
|
||||
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
|
||||
{
|
||||
int fn = regno - ARM_F0_REGNUM;
|
||||
|
||||
switch (fp.fType[fn])
|
||||
{
|
||||
case typeSingle:
|
||||
fetch_nwfpe_single (fn, &fp);
|
||||
break;
|
||||
|
||||
case typeDouble:
|
||||
fetch_nwfpe_double (fn, &fp);
|
||||
break;
|
||||
|
||||
case typeExtended:
|
||||
fetch_nwfpe_extended (fn, &fp);
|
||||
break;
|
||||
|
||||
default:
|
||||
fetch_nwfpe_none (fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save a particular register into the floating point state of the
|
||||
process using the contents from regcache. */
|
||||
|
||||
static void
|
||||
store_fpregister (int regno)
|
||||
{
|
||||
int ret, tid;
|
||||
FPA11 fp;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Read the floating point state. */
|
||||
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch the floating point registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store fpsr. */
|
||||
if (ARM_FPS_REGNUM == regno && register_cached (ARM_FPS_REGNUM))
|
||||
regcache_collect (ARM_FPS_REGNUM, (char *) &fp.fpsr);
|
||||
|
||||
/* Store the floating point register. */
|
||||
if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
|
||||
{
|
||||
store_nwfpe_register (regno, &fp);
|
||||
}
|
||||
|
||||
ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to store floating point register.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the whole floating point state of the process using
|
||||
the contents from regcache. */
|
||||
|
||||
static void
|
||||
store_fpregs (void)
|
||||
{
|
||||
int ret, regno, tid;
|
||||
FPA11 fp;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Read the floating point state. */
|
||||
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch the floating point registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store fpsr. */
|
||||
if (register_cached (ARM_FPS_REGNUM))
|
||||
regcache_collect (ARM_FPS_REGNUM, (char *) &fp.fpsr);
|
||||
|
||||
/* Store the floating point registers. */
|
||||
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
|
||||
{
|
||||
fetch_nwfpe_register (regno, &fp);
|
||||
}
|
||||
|
||||
ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to store floating point registers.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch a general register of the process and store into
|
||||
regcache. */
|
||||
|
||||
static void
|
||||
fetch_register (int regno)
|
||||
{
|
||||
int ret, tid;
|
||||
elf_gregset_t regs;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch general register.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM)
|
||||
supply_register (regno, (char *) ®s[regno]);
|
||||
|
||||
if (ARM_PS_REGNUM == regno)
|
||||
{
|
||||
if (arm_apcs_32)
|
||||
supply_register (ARM_PS_REGNUM, (char *) ®s[ARM_CPSR_REGNUM]);
|
||||
else
|
||||
supply_register (ARM_PS_REGNUM, (char *) ®s[ARM_PC_REGNUM]);
|
||||
}
|
||||
|
||||
if (ARM_PC_REGNUM == regno)
|
||||
{
|
||||
regs[ARM_PC_REGNUM] = ADDR_BITS_REMOVE (regs[ARM_PC_REGNUM]);
|
||||
supply_register (ARM_PC_REGNUM, (char *) ®s[ARM_PC_REGNUM]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch all general registers of the process and store into
|
||||
regcache. */
|
||||
|
||||
static void
|
||||
fetch_regs (void)
|
||||
{
|
||||
int ret, regno, tid;
|
||||
elf_gregset_t regs;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch general registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
|
||||
supply_register (regno, (char *) ®s[regno]);
|
||||
|
||||
if (arm_apcs_32)
|
||||
supply_register (ARM_PS_REGNUM, (char *) ®s[ARM_CPSR_REGNUM]);
|
||||
else
|
||||
supply_register (ARM_PS_REGNUM, (char *) ®s[ARM_PC_REGNUM]);
|
||||
|
||||
regs[ARM_PC_REGNUM] = ADDR_BITS_REMOVE (regs[ARM_PC_REGNUM]);
|
||||
supply_register (ARM_PC_REGNUM, (char *) ®s[ARM_PC_REGNUM]);
|
||||
}
|
||||
|
||||
/* Store all general registers of the process from the values in
|
||||
regcache. */
|
||||
|
||||
static void
|
||||
store_register (int regno)
|
||||
{
|
||||
int ret, tid;
|
||||
elf_gregset_t regs;
|
||||
|
||||
if (!register_cached (regno))
|
||||
return;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Get the general registers from the process. */
|
||||
ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch general registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
|
||||
regcache_collect (regno, (char *) ®s[regno]);
|
||||
|
||||
ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to store general register.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
store_regs (void)
|
||||
{
|
||||
int ret, regno, tid;
|
||||
elf_gregset_t regs;
|
||||
|
||||
/* Get the thread id for the ptrace call. */
|
||||
tid = GET_THREAD_ID (inferior_ptid);
|
||||
|
||||
/* Fetch the general registers. */
|
||||
ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to fetch general registers.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
|
||||
{
|
||||
if (register_cached (regno))
|
||||
regcache_collect (regno, (char *) ®s[regno]);
|
||||
}
|
||||
|
||||
ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("Unable to store general registers.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch registers from the child process. Fetch all registers if
|
||||
regno == -1, otherwise fetch all general registers or all floating
|
||||
point registers depending upon the value of regno. */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
if (-1 == regno)
|
||||
{
|
||||
fetch_regs ();
|
||||
fetch_fpregs ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
|
||||
fetch_register (regno);
|
||||
|
||||
if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
|
||||
fetch_fpregister (regno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store registers back into the inferior. Store all registers if
|
||||
regno == -1, otherwise store all general registers or all floating
|
||||
point registers depending upon the value of regno. */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
if (-1 == regno)
|
||||
{
|
||||
store_regs ();
|
||||
store_fpregs ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((regno < ARM_F0_REGNUM) || (regno > ARM_FPS_REGNUM))
|
||||
store_register (regno);
|
||||
|
||||
if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
|
||||
store_fpregister (regno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill register regno (if it is a general-purpose register) in
|
||||
*gregsetp with the appropriate value from GDB's register array.
|
||||
If regno is -1, do this for all registers. */
|
||||
|
||||
void
|
||||
fill_gregset (gdb_gregset_t *gregsetp, int regno)
|
||||
{
|
||||
if (-1 == regno)
|
||||
{
|
||||
int regnum;
|
||||
for (regnum = ARM_A1_REGNUM; regnum <= ARM_PC_REGNUM; regnum++)
|
||||
regcache_collect (regnum, (char *) &(*gregsetp)[regnum]);
|
||||
}
|
||||
else if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
|
||||
regcache_collect (regno, (char *) &(*gregsetp)[regno]);
|
||||
|
||||
if (ARM_PS_REGNUM == regno || -1 == regno)
|
||||
{
|
||||
if (arm_apcs_32)
|
||||
regcache_collect (ARM_PS_REGNUM,
|
||||
(char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
|
||||
else
|
||||
regcache_collect (ARM_PC_REGNUM,
|
||||
(char *) &(*gregsetp)[ARM_PC_REGNUM]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the general-purpose register values
|
||||
in *gregsetp. */
|
||||
|
||||
void
|
||||
supply_gregset (gdb_gregset_t *gregsetp)
|
||||
{
|
||||
int regno, reg_pc;
|
||||
|
||||
for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
|
||||
supply_register (regno, (char *) &(*gregsetp)[regno]);
|
||||
|
||||
if (arm_apcs_32)
|
||||
supply_register (ARM_PS_REGNUM, (char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
|
||||
else
|
||||
supply_register (ARM_PS_REGNUM, (char *) &(*gregsetp)[ARM_PC_REGNUM]);
|
||||
|
||||
reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[ARM_PC_REGNUM]);
|
||||
supply_register (ARM_PC_REGNUM, (char *) ®_pc);
|
||||
}
|
||||
|
||||
/* Fill register regno (if it is a floating-point register) in
|
||||
*fpregsetp with the appropriate value from GDB's register array.
|
||||
If regno is -1, do this for all registers. */
|
||||
|
||||
void
|
||||
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
FPA11 *fp = (FPA11 *) fpregsetp;
|
||||
|
||||
if (-1 == regno)
|
||||
{
|
||||
int regnum;
|
||||
for (regnum = ARM_F0_REGNUM; regnum <= ARM_F7_REGNUM; regnum++)
|
||||
store_nwfpe_register (regnum, fp);
|
||||
}
|
||||
else if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
|
||||
{
|
||||
store_nwfpe_register (regno, fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store fpsr. */
|
||||
if (ARM_FPS_REGNUM == regno || -1 == regno)
|
||||
regcache_collect (ARM_FPS_REGNUM, (char *) &fp->fpsr);
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the floating-point register values
|
||||
in *fpregsetp. */
|
||||
|
||||
void
|
||||
supply_fpregset (gdb_fpregset_t *fpregsetp)
|
||||
{
|
||||
int regno;
|
||||
FPA11 *fp = (FPA11 *) fpregsetp;
|
||||
|
||||
/* Fetch fpsr. */
|
||||
supply_register (ARM_FPS_REGNUM, (char *) &fp->fpsr);
|
||||
|
||||
/* Fetch the floating point registers. */
|
||||
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
|
||||
{
|
||||
fetch_nwfpe_register (regno, fp);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
arm_linux_kernel_u_size (void)
|
||||
{
|
||||
return (sizeof (struct user));
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_linux_version (unsigned int *vmajor,
|
||||
unsigned int *vminor,
|
||||
unsigned int *vrelease)
|
||||
{
|
||||
struct utsname info;
|
||||
char *pmajor, *pminor, *prelease, *tail;
|
||||
|
||||
if (-1 == uname (&info))
|
||||
{
|
||||
warning ("Unable to determine GNU/Linux version.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmajor = strtok (info.release, ".");
|
||||
pminor = strtok (NULL, ".");
|
||||
prelease = strtok (NULL, ".");
|
||||
|
||||
*vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
|
||||
*vminor = (unsigned int) strtoul (pminor, &tail, 0);
|
||||
*vrelease = (unsigned int) strtoul (prelease, &tail, 0);
|
||||
|
||||
return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arm_linux_nat (void)
|
||||
{
|
||||
os_version = get_linux_version (&os_major, &os_minor, &os_release);
|
||||
}
|
||||
@@ -1,547 +0,0 @@
|
||||
/* GNU/Linux on ARM target support.
|
||||
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "target.h"
|
||||
#include "value.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "floatformat.h"
|
||||
#include "gdbcore.h"
|
||||
#include "frame.h"
|
||||
#include "regcache.h"
|
||||
#include "doublest.h"
|
||||
|
||||
#include "arm-tdep.h"
|
||||
|
||||
/* For shared library handling. */
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
||||
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
|
||||
is to execute a particular software interrupt, rather than use a
|
||||
particular undefined instruction to provoke a trap. Upon exection
|
||||
of the software interrupt the kernel stops the inferior with a
|
||||
SIGTRAP, and wakes the debugger. Since ARM GNU/Linux is little
|
||||
endian, and doesn't support Thumb at the moment we only override
|
||||
the ARM little-endian breakpoint. */
|
||||
|
||||
static const char arm_linux_arm_le_breakpoint[] = {0x01,0x00,0x9f,0xef};
|
||||
|
||||
/* CALL_DUMMY_WORDS:
|
||||
This sequence of words is the instructions
|
||||
|
||||
mov lr, pc
|
||||
mov pc, r4
|
||||
swi bkpt_swi
|
||||
|
||||
Note this is 12 bytes. */
|
||||
|
||||
LONGEST arm_linux_call_dummy_words[] =
|
||||
{
|
||||
0xe1a0e00f, 0xe1a0f004, 0xef9f001
|
||||
};
|
||||
|
||||
/* Description of the longjmp buffer. */
|
||||
#define ARM_LINUX_JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE
|
||||
#define ARM_LINUX_JB_PC 21
|
||||
|
||||
/* 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. */
|
||||
/* FIXME rearnsha/2002-02-23: This function shouldn't be necessary.
|
||||
The ARM generic one should be able to handle the model used by
|
||||
linux and the low-level formatting of the registers should be
|
||||
hidden behind the regcache abstraction. */
|
||||
static void
|
||||
arm_linux_extract_return_value (struct type *type,
|
||||
char regbuf[REGISTER_BYTES],
|
||||
char *valbuf)
|
||||
{
|
||||
/* ScottB: This needs to be looked at to handle the different
|
||||
floating point emulators on ARM GNU/Linux. Right now the code
|
||||
assumes that fetch inferior registers does the right thing for
|
||||
GDB. I suspect this won't handle NWFPE registers correctly, nor
|
||||
will the default ARM version (arm_extract_return_value()). */
|
||||
|
||||
int regnum = ((TYPE_CODE_FLT == TYPE_CODE (type))
|
||||
? ARM_F0_REGNUM : ARM_A1_REGNUM);
|
||||
memcpy (valbuf, ®buf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
|
||||
}
|
||||
|
||||
/* Note: ScottB
|
||||
|
||||
This function does not support passing parameters using the FPA
|
||||
variant of the APCS. It passes any floating point arguments in the
|
||||
general registers and/or on the stack.
|
||||
|
||||
FIXME: This and arm_push_arguments should be merged. However this
|
||||
function breaks on a little endian host, big endian target
|
||||
using the COFF file format. ELF is ok.
|
||||
|
||||
ScottB. */
|
||||
|
||||
/* Addresses for calling Thumb functions have the bit 0 set.
|
||||
Here are some macros to test, set, or clear bit 0 of addresses. */
|
||||
#define IS_THUMB_ADDR(addr) ((addr) & 1)
|
||||
#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
|
||||
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
|
||||
|
||||
static CORE_ADDR
|
||||
arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
|
||||
int struct_return, CORE_ADDR struct_addr)
|
||||
{
|
||||
char *fp;
|
||||
int argnum, argreg, nstack_size;
|
||||
|
||||
/* Walk through the list of args and determine how large a temporary
|
||||
stack is required. Need to take care here as structs may be
|
||||
passed on the stack, and we have to to push them. */
|
||||
nstack_size = -4 * REGISTER_SIZE; /* Some arguments go into A1-A4. */
|
||||
|
||||
if (struct_return) /* The struct address goes in A1. */
|
||||
nstack_size += REGISTER_SIZE;
|
||||
|
||||
/* Walk through the arguments and add their size to nstack_size. */
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
int len;
|
||||
struct type *arg_type;
|
||||
|
||||
arg_type = check_typedef (VALUE_TYPE (args[argnum]));
|
||||
len = TYPE_LENGTH (arg_type);
|
||||
|
||||
/* ANSI C code passes float arguments as integers, K&R code
|
||||
passes float arguments as doubles. Correct for this here. */
|
||||
if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len)
|
||||
nstack_size += FP_REGISTER_VIRTUAL_SIZE;
|
||||
else
|
||||
nstack_size += len;
|
||||
}
|
||||
|
||||
/* Allocate room on the stack, and initialize our stack frame
|
||||
pointer. */
|
||||
fp = NULL;
|
||||
if (nstack_size > 0)
|
||||
{
|
||||
sp -= nstack_size;
|
||||
fp = (char *) sp;
|
||||
}
|
||||
|
||||
/* Initialize the integer argument register pointer. */
|
||||
argreg = ARM_A1_REGNUM;
|
||||
|
||||
/* The struct_return pointer occupies the first parameter passing
|
||||
register. */
|
||||
if (struct_return)
|
||||
write_register (argreg++, struct_addr);
|
||||
|
||||
/* Process arguments from left to right. Store as many as allowed
|
||||
in the parameter passing registers (A1-A4), and save the rest on
|
||||
the temporary stack. */
|
||||
for (argnum = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
int len;
|
||||
char *val;
|
||||
CORE_ADDR regval;
|
||||
enum type_code typecode;
|
||||
struct type *arg_type, *target_type;
|
||||
|
||||
arg_type = check_typedef (VALUE_TYPE (args[argnum]));
|
||||
target_type = TYPE_TARGET_TYPE (arg_type);
|
||||
len = TYPE_LENGTH (arg_type);
|
||||
typecode = TYPE_CODE (arg_type);
|
||||
val = (char *) VALUE_CONTENTS (args[argnum]);
|
||||
|
||||
/* ANSI C code passes float arguments as integers, K&R code
|
||||
passes float arguments as doubles. The .stabs record for
|
||||
for ANSI prototype floating point arguments records the
|
||||
type as FP_INTEGER, while a K&R style (no prototype)
|
||||
.stabs records the type as FP_FLOAT. In this latter case
|
||||
the compiler converts the float arguments to double before
|
||||
calling the function. */
|
||||
if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
|
||||
{
|
||||
DOUBLEST dblval;
|
||||
dblval = extract_floating (val, len);
|
||||
len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
|
||||
val = alloca (len);
|
||||
store_floating (val, len, dblval);
|
||||
}
|
||||
|
||||
/* If the argument is a pointer to a function, and it is a Thumb
|
||||
function, set the low bit of the pointer. */
|
||||
if (TYPE_CODE_PTR == typecode
|
||||
&& NULL != target_type
|
||||
&& TYPE_CODE_FUNC == TYPE_CODE (target_type))
|
||||
{
|
||||
CORE_ADDR regval = extract_address (val, len);
|
||||
if (arm_pc_is_thumb (regval))
|
||||
store_address (val, len, MAKE_THUMB_ADDR (regval));
|
||||
}
|
||||
|
||||
/* Copy the argument to general registers or the stack in
|
||||
register-sized pieces. Large arguments are split between
|
||||
registers and stack. */
|
||||
while (len > 0)
|
||||
{
|
||||
int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
|
||||
|
||||
if (argreg <= ARM_LAST_ARG_REGNUM)
|
||||
{
|
||||
/* It's an argument being passed in a general register. */
|
||||
regval = extract_address (val, partial_len);
|
||||
write_register (argreg++, regval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push the arguments onto the stack. */
|
||||
write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE);
|
||||
fp += REGISTER_SIZE;
|
||||
}
|
||||
|
||||
len -= partial_len;
|
||||
val += partial_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return adjusted stack pointer. */
|
||||
return sp;
|
||||
}
|
||||
|
||||
/*
|
||||
Dynamic Linking on ARM GNU/Linux
|
||||
--------------------------------
|
||||
|
||||
Note: PLT = procedure linkage table
|
||||
GOT = global offset table
|
||||
|
||||
As much as possible, ELF dynamic linking defers the resolution of
|
||||
jump/call addresses until the last minute. The technique used is
|
||||
inspired by the i386 ELF design, and is based on the following
|
||||
constraints.
|
||||
|
||||
1) The calling technique should not force a change in the assembly
|
||||
code produced for apps; it MAY cause changes in the way assembly
|
||||
code is produced for position independent code (i.e. shared
|
||||
libraries).
|
||||
|
||||
2) The technique must be such that all executable areas must not be
|
||||
modified; and any modified areas must not be executed.
|
||||
|
||||
To do this, there are three steps involved in a typical jump:
|
||||
|
||||
1) in the code
|
||||
2) through the PLT
|
||||
3) using a pointer from the GOT
|
||||
|
||||
When the executable or library is first loaded, each GOT entry is
|
||||
initialized to point to the code which implements dynamic name
|
||||
resolution and code finding. This is normally a function in the
|
||||
program interpreter (on ARM GNU/Linux this is usually
|
||||
ld-linux.so.2, but it does not have to be). On the first
|
||||
invocation, the function is located and the GOT entry is replaced
|
||||
with the real function address. Subsequent calls go through steps
|
||||
1, 2 and 3 and end up calling the real code.
|
||||
|
||||
1) In the code:
|
||||
|
||||
b function_call
|
||||
bl function_call
|
||||
|
||||
This is typical ARM code using the 26 bit relative branch or branch
|
||||
and link instructions. The target of the instruction
|
||||
(function_call is usually the address of the function to be called.
|
||||
In position independent code, the target of the instruction is
|
||||
actually an entry in the PLT when calling functions in a shared
|
||||
library. Note that this call is identical to a normal function
|
||||
call, only the target differs.
|
||||
|
||||
2) In the PLT:
|
||||
|
||||
The PLT is a synthetic area, created by the linker. It exists in
|
||||
both executables and libraries. It is an array of stubs, one per
|
||||
imported function call. It looks like this:
|
||||
|
||||
PLT[0]:
|
||||
str lr, [sp, #-4]! @push the return address (lr)
|
||||
ldr lr, [pc, #16] @load from 6 words ahead
|
||||
add lr, pc, lr @form an address for GOT[0]
|
||||
ldr pc, [lr, #8]! @jump to the contents of that addr
|
||||
|
||||
The return address (lr) is pushed on the stack and used for
|
||||
calculations. The load on the second line loads the lr with
|
||||
&GOT[3] - . - 20. The addition on the third leaves:
|
||||
|
||||
lr = (&GOT[3] - . - 20) + (. + 8)
|
||||
lr = (&GOT[3] - 12)
|
||||
lr = &GOT[0]
|
||||
|
||||
On the fourth line, the pc and lr are both updated, so that:
|
||||
|
||||
pc = GOT[2]
|
||||
lr = &GOT[0] + 8
|
||||
= &GOT[2]
|
||||
|
||||
NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
|
||||
"tight", but allows us to keep all the PLT entries the same size.
|
||||
|
||||
PLT[n+1]:
|
||||
ldr ip, [pc, #4] @load offset from gotoff
|
||||
add ip, pc, ip @add the offset to the pc
|
||||
ldr pc, [ip] @jump to that address
|
||||
gotoff: .word GOT[n+3] - .
|
||||
|
||||
The load on the first line, gets an offset from the fourth word of
|
||||
the PLT entry. The add on the second line makes ip = &GOT[n+3],
|
||||
which contains either a pointer to PLT[0] (the fixup trampoline) or
|
||||
a pointer to the actual code.
|
||||
|
||||
3) In the GOT:
|
||||
|
||||
The GOT contains helper pointers for both code (PLT) fixups and
|
||||
data fixups. The first 3 entries of the GOT are special. The next
|
||||
M entries (where M is the number of entries in the PLT) belong to
|
||||
the PLT fixups. The next D (all remaining) entries belong to
|
||||
various data fixups. The actual size of the GOT is 3 + M + D.
|
||||
|
||||
The GOT is also a synthetic area, created by the linker. It exists
|
||||
in both executables and libraries. When the GOT is first
|
||||
initialized , all the GOT entries relating to PLT fixups are
|
||||
pointing to code back at PLT[0].
|
||||
|
||||
The special entries in the GOT are:
|
||||
|
||||
GOT[0] = linked list pointer used by the dynamic loader
|
||||
GOT[1] = pointer to the reloc table for this module
|
||||
GOT[2] = pointer to the fixup/resolver code
|
||||
|
||||
The first invocation of function call comes through and uses the
|
||||
fixup/resolver code. On the entry to the fixup/resolver code:
|
||||
|
||||
ip = &GOT[n+3]
|
||||
lr = &GOT[2]
|
||||
stack[0] = return address (lr) of the function call
|
||||
[r0, r1, r2, r3] are still the arguments to the function call
|
||||
|
||||
This is enough information for the fixup/resolver code to work
|
||||
with. Before the fixup/resolver code returns, it actually calls
|
||||
the requested function and repairs &GOT[n+3]. */
|
||||
|
||||
/* Find the minimal symbol named NAME, and return both the minsym
|
||||
struct and its objfile. This probably ought to be in minsym.c, but
|
||||
everything there is trying to deal with things like C++ and
|
||||
SOFUN_ADDRESS_MAYBE_TURQUOISE, ... Since this is so simple, it may
|
||||
be considered too special-purpose for general consumption. */
|
||||
|
||||
static struct minimal_symbol *
|
||||
find_minsym_and_objfile (char *name, struct objfile **objfile_p)
|
||||
{
|
||||
struct objfile *objfile;
|
||||
|
||||
ALL_OBJFILES (objfile)
|
||||
{
|
||||
struct minimal_symbol *msym;
|
||||
|
||||
ALL_OBJFILE_MSYMBOLS (objfile, msym)
|
||||
{
|
||||
if (SYMBOL_NAME (msym)
|
||||
&& strcmp (SYMBOL_NAME (msym), name) == 0)
|
||||
{
|
||||
*objfile_p = objfile;
|
||||
return msym;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static CORE_ADDR
|
||||
skip_hurd_resolver (CORE_ADDR pc)
|
||||
{
|
||||
/* The HURD dynamic linker is part of the GNU C library, so many
|
||||
GNU/Linux distributions use it. (All ELF versions, as far as I
|
||||
know.) An unresolved PLT entry points to "_dl_runtime_resolve",
|
||||
which calls "fixup" to patch the PLT, and then passes control to
|
||||
the function.
|
||||
|
||||
We look for the symbol `_dl_runtime_resolve', and find `fixup' in
|
||||
the same objfile. If we are at the entry point of `fixup', then
|
||||
we set a breakpoint at the return address (at the top of the
|
||||
stack), and continue.
|
||||
|
||||
It's kind of gross to do all these checks every time we're
|
||||
called, since they don't change once the executable has gotten
|
||||
started. But this is only a temporary hack --- upcoming versions
|
||||
of GNU/Linux will provide a portable, efficient interface for
|
||||
debugging programs that use shared libraries. */
|
||||
|
||||
struct objfile *objfile;
|
||||
struct minimal_symbol *resolver
|
||||
= find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);
|
||||
|
||||
if (resolver)
|
||||
{
|
||||
struct minimal_symbol *fixup
|
||||
= lookup_minimal_symbol ("fixup", NULL, objfile);
|
||||
|
||||
if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
|
||||
return (SAVED_PC_AFTER_CALL (get_current_frame ()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c.
|
||||
This function:
|
||||
1) decides whether a PLT has sent us into the linker to resolve
|
||||
a function reference, and
|
||||
2) if so, tells us where to set a temporary breakpoint that will
|
||||
trigger when the dynamic linker is done. */
|
||||
|
||||
CORE_ADDR
|
||||
arm_linux_skip_solib_resolver (CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR result;
|
||||
|
||||
/* Plug in functions for other kinds of resolvers here. */
|
||||
result = skip_hurd_resolver (pc);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The constants below were determined by examining the following files
|
||||
in the linux kernel sources:
|
||||
|
||||
arch/arm/kernel/signal.c
|
||||
- see SWI_SYS_SIGRETURN and SWI_SYS_RT_SIGRETURN
|
||||
include/asm-arm/unistd.h
|
||||
- see __NR_sigreturn, __NR_rt_sigreturn, and __NR_SYSCALL_BASE */
|
||||
|
||||
#define ARM_LINUX_SIGRETURN_INSTR 0xef900077
|
||||
#define ARM_LINUX_RT_SIGRETURN_INSTR 0xef9000ad
|
||||
|
||||
/* arm_linux_in_sigtramp determines if PC points at one of the
|
||||
instructions which cause control to return to the Linux kernel upon
|
||||
return from a signal handler. FUNC_NAME is unused. */
|
||||
|
||||
int
|
||||
arm_linux_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
unsigned long inst;
|
||||
|
||||
inst = read_memory_integer (pc, 4);
|
||||
|
||||
return (inst == ARM_LINUX_SIGRETURN_INSTR
|
||||
|| inst == ARM_LINUX_RT_SIGRETURN_INSTR);
|
||||
|
||||
}
|
||||
|
||||
/* arm_linux_sigcontext_register_address returns the address in the
|
||||
sigcontext of register REGNO given a stack pointer value SP and
|
||||
program counter value PC. The value 0 is returned if PC is not
|
||||
pointing at one of the signal return instructions or if REGNO is
|
||||
not saved in the sigcontext struct. */
|
||||
|
||||
CORE_ADDR
|
||||
arm_linux_sigcontext_register_address (CORE_ADDR sp, CORE_ADDR pc, int regno)
|
||||
{
|
||||
unsigned long inst;
|
||||
CORE_ADDR reg_addr = 0;
|
||||
|
||||
inst = read_memory_integer (pc, 4);
|
||||
|
||||
if (inst == ARM_LINUX_SIGRETURN_INSTR
|
||||
|| inst == ARM_LINUX_RT_SIGRETURN_INSTR)
|
||||
{
|
||||
CORE_ADDR sigcontext_addr;
|
||||
|
||||
/* The sigcontext structure is at different places for the two
|
||||
signal return instructions. For ARM_LINUX_SIGRETURN_INSTR,
|
||||
it starts at the SP value. For ARM_LINUX_RT_SIGRETURN_INSTR,
|
||||
it is at SP+8. For the latter instruction, it may also be
|
||||
the case that the address of this structure may be determined
|
||||
by reading the 4 bytes at SP, but I'm not convinced this is
|
||||
reliable.
|
||||
|
||||
In any event, these magic constants (0 and 8) may be
|
||||
determined by examining struct sigframe and struct
|
||||
rt_sigframe in arch/arm/kernel/signal.c in the Linux kernel
|
||||
sources. */
|
||||
|
||||
if (inst == ARM_LINUX_RT_SIGRETURN_INSTR)
|
||||
sigcontext_addr = sp + 8;
|
||||
else /* inst == ARM_LINUX_SIGRETURN_INSTR */
|
||||
sigcontext_addr = sp + 0;
|
||||
|
||||
/* The layout of the sigcontext structure for ARM GNU/Linux is
|
||||
in include/asm-arm/sigcontext.h in the Linux kernel sources.
|
||||
|
||||
There are three 4-byte fields which precede the saved r0
|
||||
field. (This accounts for the 12 in the code below.) The
|
||||
sixteen registers (4 bytes per field) follow in order. The
|
||||
PSR value follows the sixteen registers which accounts for
|
||||
the constant 19 below. */
|
||||
|
||||
if (0 <= regno && regno <= ARM_PC_REGNUM)
|
||||
reg_addr = sigcontext_addr + 12 + (4 * regno);
|
||||
else if (regno == ARM_PS_REGNUM)
|
||||
reg_addr = sigcontext_addr + 19 * 4;
|
||||
}
|
||||
|
||||
return reg_addr;
|
||||
}
|
||||
|
||||
static void
|
||||
arm_linux_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
tdep->lowest_pc = 0x8000;
|
||||
tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
|
||||
tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
|
||||
|
||||
tdep->jb_pc = ARM_LINUX_JB_PC;
|
||||
tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
|
||||
|
||||
set_gdbarch_call_dummy_words (gdbarch, arm_linux_call_dummy_words);
|
||||
set_gdbarch_sizeof_call_dummy_words (gdbarch,
|
||||
sizeof (arm_linux_call_dummy_words));
|
||||
|
||||
/* The following two overrides shouldn't be needed. */
|
||||
set_gdbarch_deprecated_extract_return_value (gdbarch, arm_linux_extract_return_value);
|
||||
set_gdbarch_push_arguments (gdbarch, arm_linux_push_arguments);
|
||||
|
||||
/* Shared library handling. */
|
||||
set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
|
||||
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arm_linux_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_LINUX, arm_linux_init_abi);
|
||||
}
|
||||
3136
gdb/arm-tdep.c
3136
gdb/arm-tdep.c
File diff suppressed because it is too large
Load Diff
156
gdb/arm-tdep.h
156
gdb/arm-tdep.h
@@ -1,156 +0,0 @@
|
||||
/* Common target dependent code for GDB on ARM systems.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "osabi.h"
|
||||
|
||||
/* 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. */
|
||||
|
||||
enum gdb_regnum {
|
||||
ARM_A1_REGNUM = 0, /* first integer-like argument */
|
||||
ARM_A4_REGNUM = 3, /* last integer-like argument */
|
||||
ARM_AP_REGNUM = 11,
|
||||
ARM_SP_REGNUM = 13, /* Contains address of top of stack */
|
||||
ARM_LR_REGNUM = 14, /* address to return to from a function call */
|
||||
ARM_PC_REGNUM = 15, /* Contains program counter */
|
||||
ARM_F0_REGNUM = 16, /* first floating point register */
|
||||
ARM_F3_REGNUM = 19, /* last floating point argument register */
|
||||
ARM_F7_REGNUM = 23, /* last floating point register */
|
||||
ARM_FPS_REGNUM = 24, /* floating point status register */
|
||||
ARM_PS_REGNUM = 25, /* Contains processor status */
|
||||
ARM_FP_REGNUM = 11, /* Frame register in ARM code, if used. */
|
||||
THUMB_FP_REGNUM = 7, /* Frame register in Thumb code, if used. */
|
||||
ARM_NUM_ARG_REGS = 4,
|
||||
ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
|
||||
ARM_NUM_FP_ARG_REGS = 4,
|
||||
ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
|
||||
};
|
||||
|
||||
/* Used in target-specific code when we need to know the size of the
|
||||
largest type of register we need to handle. */
|
||||
#define ARM_MAX_REGISTER_RAW_SIZE 12
|
||||
#define ARM_MAX_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Size of integer registers. */
|
||||
#define INT_REGISTER_RAW_SIZE 4
|
||||
#define INT_REGISTER_VIRTUAL_SIZE 4
|
||||
|
||||
/* Say how long FP registers are. Used for documentation purposes and
|
||||
code readability in this header. IEEE extended doubles are 80
|
||||
bits. DWORD aligned they use 96 bits. */
|
||||
#define FP_REGISTER_RAW_SIZE 12
|
||||
|
||||
/* GCC doesn't support long doubles (extended IEEE values). The FP
|
||||
register virtual size is therefore 64 bits. Used for documentation
|
||||
purposes and code readability in this header. */
|
||||
#define FP_REGISTER_VIRTUAL_SIZE 8
|
||||
|
||||
/* Status registers are the same size as general purpose registers.
|
||||
Used for documentation purposes and code readability in this
|
||||
header. */
|
||||
#define STATUS_REGISTER_SIZE 4
|
||||
|
||||
/* Number of machine registers. The only define actually required
|
||||
is NUM_REGS. The other definitions are used for documentation
|
||||
purposes and code readability. */
|
||||
/* For 26 bit ARM code, a fake copy of the PC is placed in register 25 (PS)
|
||||
(and called PS for processor status) so the status bits can be cleared
|
||||
from the PC (register 15). For 32 bit ARM code, a copy of CPSR is placed
|
||||
in PS. */
|
||||
#define NUM_FREGS 8 /* Number of floating point registers. */
|
||||
#define NUM_SREGS 2 /* Number of status registers. */
|
||||
#define NUM_GREGS 16 /* Number of general purpose registers. */
|
||||
|
||||
|
||||
/* Instruction condition field values. */
|
||||
#define INST_EQ 0x0
|
||||
#define INST_NE 0x1
|
||||
#define INST_CS 0x2
|
||||
#define INST_CC 0x3
|
||||
#define INST_MI 0x4
|
||||
#define INST_PL 0x5
|
||||
#define INST_VS 0x6
|
||||
#define INST_VC 0x7
|
||||
#define INST_HI 0x8
|
||||
#define INST_LS 0x9
|
||||
#define INST_GE 0xa
|
||||
#define INST_LT 0xb
|
||||
#define INST_GT 0xc
|
||||
#define INST_LE 0xd
|
||||
#define INST_AL 0xe
|
||||
#define INST_NV 0xf
|
||||
|
||||
#define FLAG_N 0x80000000
|
||||
#define FLAG_Z 0x40000000
|
||||
#define FLAG_C 0x20000000
|
||||
#define FLAG_V 0x10000000
|
||||
|
||||
/* Type of floating-point code in use by inferior. There are really 3 models
|
||||
that are traditionally supported (plus the endianness issue), but gcc can
|
||||
only generate 2 of those. The third is APCS_FLOAT, where arguments to
|
||||
functions are passed in floating-point registers.
|
||||
|
||||
In addition to the traditional models, VFP adds two more. */
|
||||
|
||||
enum arm_float_model
|
||||
{
|
||||
ARM_FLOAT_SOFT,
|
||||
ARM_FLOAT_FPA,
|
||||
ARM_FLOAT_SOFT_VFP,
|
||||
ARM_FLOAT_VFP
|
||||
};
|
||||
|
||||
/* Target-dependent structure in gdbarch. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
enum gdb_osabi osabi; /* OS/ABI of inferior. */
|
||||
|
||||
enum arm_float_model fp_model; /* Floating point calling conventions. */
|
||||
|
||||
CORE_ADDR lowest_pc; /* Lowest address at which instructions
|
||||
will appear. */
|
||||
|
||||
const char *arm_breakpoint; /* Breakpoint pattern for an ARM insn. */
|
||||
int arm_breakpoint_size; /* And its size. */
|
||||
const char *thumb_breakpoint; /* Breakpoint pattern for an ARM insn. */
|
||||
int thumb_breakpoint_size; /* And its size. */
|
||||
|
||||
int jb_pc; /* Offset to PC value in jump buffer.
|
||||
If this is negative, longjmp support
|
||||
will be disabled. */
|
||||
size_t jb_elt_size; /* And the size of each entry in the buf. */
|
||||
};
|
||||
|
||||
#ifndef LOWEST_PC
|
||||
#define LOWEST_PC (gdbarch_tdep (current_gdbarch)->lowest_pc)
|
||||
#endif
|
||||
|
||||
/* Prototypes for internal interfaces needed by more than one MD file. */
|
||||
int arm_pc_is_thumb_dummy (CORE_ADDR);
|
||||
|
||||
int arm_pc_is_thumb (CORE_ADDR);
|
||||
|
||||
CORE_ADDR thumb_get_next_pc (CORE_ADDR);
|
||||
|
||||
CORE_ADDR arm_get_next_pc (CORE_ADDR);
|
||||
@@ -1,464 +0,0 @@
|
||||
/* Native-dependent code for BSD Unix running on ARM's, for GDB.
|
||||
Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#ifndef FETCH_INFERIOR_REGISTERS
|
||||
#error Not FETCH_INFERIOR_REGISTERS
|
||||
#endif /* !FETCH_INFERIOR_REGISTERS */
|
||||
|
||||
#include "arm-tdep.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/frame.h>
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
extern int arm_apcs_32;
|
||||
|
||||
static void
|
||||
supply_gregset (struct reg *gregset)
|
||||
{
|
||||
int regno;
|
||||
CORE_ADDR r_pc;
|
||||
|
||||
/* Integer registers. */
|
||||
for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
|
||||
supply_register (regno, (char *) &gregset->r[regno]);
|
||||
|
||||
supply_register (ARM_SP_REGNUM, (char *) &gregset->r_sp);
|
||||
supply_register (ARM_LR_REGNUM, (char *) &gregset->r_lr);
|
||||
/* This is ok: we're running native... */
|
||||
r_pc = ADDR_BITS_REMOVE (gregset->r_pc);
|
||||
supply_register (ARM_PC_REGNUM, (char *) &r_pc);
|
||||
|
||||
if (arm_apcs_32)
|
||||
supply_register (ARM_PS_REGNUM, (char *) &gregset->r_cpsr);
|
||||
else
|
||||
supply_register (ARM_PS_REGNUM, (char *) &gregset->r_pc);
|
||||
}
|
||||
|
||||
static void
|
||||
supply_fparegset (struct fpreg *fparegset)
|
||||
{
|
||||
int regno;
|
||||
|
||||
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
|
||||
supply_register
|
||||
(regno, (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]);
|
||||
|
||||
supply_register (ARM_FPS_REGNUM, (char *) &fparegset->fpr_fpsr);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_register (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
int ret;
|
||||
|
||||
ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch general register");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case ARM_SP_REGNUM:
|
||||
supply_register (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
|
||||
break;
|
||||
|
||||
case ARM_LR_REGNUM:
|
||||
supply_register (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
|
||||
break;
|
||||
|
||||
case ARM_PC_REGNUM:
|
||||
/* This is ok: we're running native... */
|
||||
inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
|
||||
supply_register (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
|
||||
break;
|
||||
|
||||
case ARM_PS_REGNUM:
|
||||
if (arm_apcs_32)
|
||||
supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
|
||||
else
|
||||
supply_register (ARM_PS_REGNUM, (char *) &inferior_registers.r_pc);
|
||||
break;
|
||||
|
||||
default:
|
||||
supply_register (regno, (char *) &inferior_registers.r[regno]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_regs (void)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
int ret;
|
||||
int regno;
|
||||
|
||||
ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch general registers");
|
||||
return;
|
||||
}
|
||||
|
||||
supply_gregset (&inferior_registers);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_fp_register (int regno)
|
||||
{
|
||||
struct fpreg inferior_fp_registers;
|
||||
int ret;
|
||||
|
||||
ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch floating-point register");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case ARM_FPS_REGNUM:
|
||||
supply_register (ARM_FPS_REGNUM,
|
||||
(char *) &inferior_fp_registers.fpr_fpsr);
|
||||
break;
|
||||
|
||||
default:
|
||||
supply_register
|
||||
(regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_fp_regs (void)
|
||||
{
|
||||
struct fpreg inferior_fp_registers;
|
||||
int ret;
|
||||
int regno;
|
||||
|
||||
ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch general registers");
|
||||
return;
|
||||
}
|
||||
|
||||
supply_fparegset (&inferior_fp_registers);
|
||||
}
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
|
||||
fetch_register (regno);
|
||||
else
|
||||
fetch_fp_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
fetch_regs ();
|
||||
fetch_fp_regs ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
store_register (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
int ret;
|
||||
|
||||
ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch general registers");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case ARM_SP_REGNUM:
|
||||
regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
|
||||
break;
|
||||
|
||||
case ARM_LR_REGNUM:
|
||||
regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
|
||||
break;
|
||||
|
||||
case ARM_PC_REGNUM:
|
||||
if (arm_apcs_32)
|
||||
regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
|
||||
else
|
||||
{
|
||||
unsigned pc_val;
|
||||
|
||||
regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
|
||||
|
||||
pc_val = ADDR_BITS_REMOVE (pc_val);
|
||||
inferior_registers.r_pc
|
||||
^= ADDR_BITS_REMOVE (inferior_registers.r_pc);
|
||||
inferior_registers.r_pc |= pc_val;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARM_PS_REGNUM:
|
||||
if (arm_apcs_32)
|
||||
regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
|
||||
else
|
||||
{
|
||||
unsigned psr_val;
|
||||
|
||||
regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
|
||||
|
||||
psr_val ^= ADDR_BITS_REMOVE (psr_val);
|
||||
inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc);
|
||||
inferior_registers.r_pc |= psr_val;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
regcache_collect (regno, (char *) &inferior_registers.r[regno]);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
warning ("unable to write register %d to inferior", regno);
|
||||
}
|
||||
|
||||
static void
|
||||
store_regs (void)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
int ret;
|
||||
int regno;
|
||||
|
||||
|
||||
for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++)
|
||||
regcache_collect (regno, (char *) &inferior_registers.r[regno]);
|
||||
|
||||
regcache_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp);
|
||||
regcache_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr);
|
||||
|
||||
if (arm_apcs_32)
|
||||
{
|
||||
regcache_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc);
|
||||
regcache_collect (ARM_PS_REGNUM, (char *) &inferior_registers.r_cpsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned pc_val;
|
||||
unsigned psr_val;
|
||||
|
||||
regcache_collect (ARM_PC_REGNUM, (char *) &pc_val);
|
||||
regcache_collect (ARM_PS_REGNUM, (char *) &psr_val);
|
||||
|
||||
pc_val = ADDR_BITS_REMOVE (pc_val);
|
||||
psr_val ^= ADDR_BITS_REMOVE (psr_val);
|
||||
|
||||
inferior_registers.r_pc = pc_val | psr_val;
|
||||
}
|
||||
|
||||
ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
warning ("unable to store general registers");
|
||||
}
|
||||
|
||||
static void
|
||||
store_fp_register (int regno)
|
||||
{
|
||||
struct fpreg inferior_fp_registers;
|
||||
int ret;
|
||||
|
||||
ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
warning ("unable to fetch floating-point registers");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case ARM_FPS_REGNUM:
|
||||
regcache_collect (ARM_FPS_REGNUM,
|
||||
(char *) &inferior_fp_registers.fpr_fpsr);
|
||||
break;
|
||||
|
||||
default:
|
||||
regcache_collect
|
||||
(regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
warning ("unable to write register %d to inferior", regno);
|
||||
}
|
||||
|
||||
static void
|
||||
store_fp_regs (void)
|
||||
{
|
||||
struct fpreg inferior_fp_registers;
|
||||
int ret;
|
||||
int regno;
|
||||
|
||||
|
||||
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
|
||||
regcache_collect
|
||||
(regno, (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]);
|
||||
|
||||
regcache_collect (ARM_FPS_REGNUM, (char *) &inferior_fp_registers.fpr_fpsr);
|
||||
|
||||
ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
|
||||
|
||||
if (ret < 0)
|
||||
warning ("unable to store floating-point registers");
|
||||
}
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
|
||||
store_register (regno);
|
||||
else
|
||||
store_fp_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
store_regs ();
|
||||
store_fp_regs ();
|
||||
}
|
||||
}
|
||||
|
||||
struct md_core
|
||||
{
|
||||
struct reg intreg;
|
||||
struct fpreg freg;
|
||||
};
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR ignore)
|
||||
{
|
||||
struct md_core *core_reg = (struct md_core *) core_reg_sect;
|
||||
int regno;
|
||||
CORE_ADDR r_pc;
|
||||
|
||||
supply_gregset (&core_reg->intreg);
|
||||
supply_fparegset (&core_reg->freg);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR ignore)
|
||||
{
|
||||
struct reg gregset;
|
||||
struct fpreg fparegset;
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case 0: /* Integer registers. */
|
||||
if (core_reg_size != sizeof (struct reg))
|
||||
warning ("wrong size of register set in core file");
|
||||
else
|
||||
{
|
||||
/* The memcpy may be unnecessary, but we can't really be sure
|
||||
of the alignment of the data in the core file. */
|
||||
memcpy (&gregset, core_reg_sect, sizeof (gregset));
|
||||
supply_gregset (&gregset);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (core_reg_size != sizeof (struct fpreg))
|
||||
warning ("wrong size of FPA register set in core file");
|
||||
else
|
||||
{
|
||||
/* The memcpy may be unnecessary, but we can't really be sure
|
||||
of the alignment of the data in the core file. */
|
||||
memcpy (&fparegset, core_reg_sect, sizeof (fparegset));
|
||||
supply_fparegset (&fparegset);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Don't know what kind of register request this is; just ignore it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct core_fns arm_netbsd_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flovour. */
|
||||
default_check_format, /* check_format. */
|
||||
default_core_sniffer, /* core_sniffer. */
|
||||
fetch_core_registers, /* core_read_registers. */
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct core_fns arm_netbsd_elfcore_fns =
|
||||
{
|
||||
bfd_target_elf_flavour, /* core_flovour. */
|
||||
default_check_format, /* check_format. */
|
||||
default_core_sniffer, /* core_sniffer. */
|
||||
fetch_elfcore_registers, /* core_read_registers. */
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_arm_netbsd_nat (void)
|
||||
{
|
||||
add_core_fns (&arm_netbsd_core_fns);
|
||||
add_core_fns (&arm_netbsd_elfcore_fns);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/* Target-specific functions for ARM running under NetBSD.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include "arm-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Description of the longjmp buffer. */
|
||||
#define JB_PC 24
|
||||
#define JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE
|
||||
|
||||
/* For compatibility with previous implemenations of GDB on arm/NetBSD,
|
||||
override the default little-endian breakpoint. */
|
||||
static const char arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6};
|
||||
|
||||
static int
|
||||
arm_netbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name)
|
||||
{
|
||||
if (strcmp (name, "_PROCEDURE_LINKAGE_TABLE_") == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
arm_netbsd_init_abi_common (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
tdep->lowest_pc = 0x8000;
|
||||
tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint;
|
||||
tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint);
|
||||
|
||||
tdep->jb_pc = JB_PC;
|
||||
tdep->jb_elt_size = JB_ELEMENT_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
arm_netbsd_aout_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
arm_netbsd_init_abi_common (info, gdbarch);
|
||||
|
||||
set_gdbarch_in_solib_call_trampoline
|
||||
(gdbarch, arm_netbsd_aout_in_solib_call_trampoline);
|
||||
tdep->fp_model = ARM_FLOAT_SOFT;
|
||||
}
|
||||
|
||||
static void
|
||||
arm_netbsd_elf_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
arm_netbsd_init_abi_common (info, gdbarch);
|
||||
|
||||
set_solib_svr4_fetch_link_map_offsets (gdbarch,
|
||||
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
|
||||
|
||||
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
|
||||
}
|
||||
|
||||
static enum gdb_osabi
|
||||
arm_netbsd_aout_osabi_sniffer (bfd *abfd)
|
||||
{
|
||||
if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0)
|
||||
return GDB_OSABI_NETBSD_AOUT;
|
||||
|
||||
return GDB_OSABI_UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arm_netbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour,
|
||||
arm_netbsd_aout_osabi_sniffer);
|
||||
|
||||
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_AOUT,
|
||||
arm_netbsd_aout_init_abi);
|
||||
gdbarch_register_osabi (bfd_arch_arm, GDB_OSABI_NETBSD_ELF,
|
||||
arm_netbsd_elf_init_abi);
|
||||
}
|
||||
1374
gdb/avr-tdep.c
1374
gdb/avr-tdep.c
File diff suppressed because it is too large
Load Diff
1859
gdb/ax-gdb.c
1859
gdb/ax-gdb.c
File diff suppressed because it is too large
Load Diff
112
gdb/ax-gdb.h
112
gdb/ax-gdb.h
@@ -1,112 +0,0 @@
|
||||
/* GDB-specific functions for operating on agent expressions
|
||||
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef AX_GDB_H
|
||||
#define AX_GDB_H
|
||||
|
||||
|
||||
/* Types and enums */
|
||||
|
||||
/* GDB stores expressions in the form of a flattened tree (struct
|
||||
expression), so we just walk that tree and generate agent bytecodes
|
||||
as we go along.
|
||||
|
||||
GDB's normal evaluation uses struct value, which contains the
|
||||
expression's value as well as its address or the register it came
|
||||
from. The `+' operator uses the value, whereas the unary `&'
|
||||
operator will use the address portion. The `=' operator will use
|
||||
the address or register number of its left hand side.
|
||||
|
||||
The issues are different when generating agent bytecode. Given a
|
||||
variable reference expression, we should not necessarily generate
|
||||
code to fetch its value, because the next operator may be `=' or
|
||||
unary `&'. Instead, when we recurse on a subexpression, we
|
||||
indicate whether we want that expression to produce an lvalue or an
|
||||
rvalue. If we requested an lvalue, then the recursive call tells
|
||||
us whether it generated code to compute an address on the stack, or
|
||||
whether the lvalue lives in a register.
|
||||
|
||||
The `axs' prefix here means `agent expression, static', because
|
||||
this is all static analysis of the expression, i.e. analysis which
|
||||
doesn't depend on the contents of memory and registers. */
|
||||
|
||||
|
||||
/* Different kinds of agent expression static values. */
|
||||
enum axs_lvalue_kind
|
||||
{
|
||||
/* We generated code to compute the subexpression's value.
|
||||
Constants and arithmetic operators yield this. */
|
||||
axs_rvalue,
|
||||
|
||||
/* We generated code to yield the subexpression's value's address on
|
||||
the top of the stack. If the caller needs an rvalue, it should
|
||||
call require_rvalue to produce the rvalue from this address. */
|
||||
axs_lvalue_memory,
|
||||
|
||||
/* We didn't generate any code, and the stack is undisturbed,
|
||||
because the subexpression's value lives in a register; u.reg is
|
||||
the register number. If the caller needs an rvalue, it should
|
||||
call require_rvalue to produce the rvalue from this register
|
||||
number. */
|
||||
axs_lvalue_register
|
||||
};
|
||||
|
||||
/* Structure describing what we got from a subexpression. Think of
|
||||
this as parallel to value.h's enum lval_type, except that we're
|
||||
describing a value which will exist when the expression is
|
||||
evaluated in the future, not a value we have in our hand. */
|
||||
struct axs_value
|
||||
{
|
||||
enum axs_lvalue_kind kind; /* see above */
|
||||
|
||||
/* The type of the subexpression. Even if lvalue == axs_lvalue_memory,
|
||||
this is the type of the value itself; the value on the stack is a
|
||||
"pointer to" an object of this type. */
|
||||
struct type *type;
|
||||
|
||||
union
|
||||
{
|
||||
/* if kind == axs_lvalue_register, this is the register number */
|
||||
int reg;
|
||||
}
|
||||
u;
|
||||
};
|
||||
|
||||
|
||||
/* Translating GDB expressions into agent expressions. */
|
||||
|
||||
/* Given a GDB expression EXPR, translate it into the agent bytecode,
|
||||
and return it. FLAGS are from enum expr_to_agent_flags. */
|
||||
extern struct agent_expr *expr_to_agent (struct expression *EXPR,
|
||||
struct axs_value *VALUE);
|
||||
|
||||
/* Given a GDB expression EXPR denoting an lvalue in memory, produce a
|
||||
string of agent bytecode which will leave its address and size on
|
||||
the top of stack. Return the agent expression. */
|
||||
extern struct agent_expr *expr_to_address_and_size (struct expression *EXPR);
|
||||
|
||||
/* Given a GDB expression EXPR, return bytecode to trace its value.
|
||||
The result will use the `trace' and `trace_quick' bytecodes to
|
||||
record the value of all memory touched by the expression, and leave
|
||||
no values on the stack. The caller can then use the ax_reqs
|
||||
function to discover which registers the expression uses. */
|
||||
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
|
||||
|
||||
#endif /* AX_GDB_H */
|
||||
541
gdb/ax-general.c
541
gdb/ax-general.c
@@ -1,541 +0,0 @@
|
||||
/* Functions for manipulating expressions designed to be executed on the agent
|
||||
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Despite what the above comment says about this file being part of
|
||||
GDB, we would like to keep these functions free of GDB
|
||||
dependencies, since we want to be able to use them in contexts
|
||||
outside of GDB (test suites, the stub, etc.) */
|
||||
|
||||
#include "defs.h"
|
||||
#include "ax.h"
|
||||
|
||||
#include "value.h"
|
||||
|
||||
static void grow_expr (struct agent_expr *x, int n);
|
||||
|
||||
static void append_const (struct agent_expr *x, LONGEST val, int n);
|
||||
|
||||
static LONGEST read_const (struct agent_expr *x, int o, int n);
|
||||
|
||||
static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
|
||||
|
||||
/* Functions for building expressions. */
|
||||
|
||||
/* Allocate a new, empty agent expression. */
|
||||
struct agent_expr *
|
||||
new_agent_expr (CORE_ADDR scope)
|
||||
{
|
||||
struct agent_expr *x = xmalloc (sizeof (*x));
|
||||
x->len = 0;
|
||||
x->size = 1; /* Change this to a larger value once
|
||||
reallocation code is tested. */
|
||||
x->buf = xmalloc (x->size);
|
||||
x->scope = scope;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Free a agent expression. */
|
||||
void
|
||||
free_agent_expr (struct agent_expr *x)
|
||||
{
|
||||
xfree (x->buf);
|
||||
xfree (x);
|
||||
}
|
||||
|
||||
static void
|
||||
do_free_agent_expr_cleanup (void *x)
|
||||
{
|
||||
free_agent_expr (x);
|
||||
}
|
||||
|
||||
struct cleanup *
|
||||
make_cleanup_free_agent_expr (struct agent_expr *x)
|
||||
{
|
||||
return make_cleanup (do_free_agent_expr_cleanup, x);
|
||||
}
|
||||
|
||||
|
||||
/* Make sure that X has room for at least N more bytes. This doesn't
|
||||
affect the length, just the allocated size. */
|
||||
static void
|
||||
grow_expr (struct agent_expr *x, int n)
|
||||
{
|
||||
if (x->len + n > x->size)
|
||||
{
|
||||
x->size *= 2;
|
||||
if (x->size < x->len + n)
|
||||
x->size = x->len + n + 10;
|
||||
x->buf = xrealloc (x->buf, x->size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Append the low N bytes of VAL as an N-byte integer to the
|
||||
expression X, in big-endian order. */
|
||||
static void
|
||||
append_const (struct agent_expr *x, LONGEST val, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
grow_expr (x, n);
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
{
|
||||
x->buf[x->len + i] = val & 0xff;
|
||||
val >>= 8;
|
||||
}
|
||||
x->len += n;
|
||||
}
|
||||
|
||||
|
||||
/* Extract an N-byte big-endian unsigned integer from expression X at
|
||||
offset O. */
|
||||
static LONGEST
|
||||
read_const (struct agent_expr *x, int o, int n)
|
||||
{
|
||||
int i;
|
||||
LONGEST accum = 0;
|
||||
|
||||
/* Make sure we're not reading off the end of the expression. */
|
||||
if (o + n > x->len)
|
||||
error ("GDB bug: ax-general.c (read_const): incomplete constant");
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
accum = (accum << 8) | x->buf[o + i];
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
||||
/* Append a simple operator OP to EXPR. */
|
||||
void
|
||||
ax_simple (struct agent_expr *x, enum agent_op op)
|
||||
{
|
||||
grow_expr (x, 1);
|
||||
x->buf[x->len++] = op;
|
||||
}
|
||||
|
||||
|
||||
/* Append a sign-extension or zero-extension instruction to EXPR, to
|
||||
extend an N-bit value. */
|
||||
static void
|
||||
generic_ext (struct agent_expr *x, enum agent_op op, int n)
|
||||
{
|
||||
/* N must fit in a byte. */
|
||||
if (n < 0 || n > 255)
|
||||
error ("GDB bug: ax-general.c (generic_ext): bit count out of range");
|
||||
/* That had better be enough range. */
|
||||
if (sizeof (LONGEST) * 8 > 255)
|
||||
error ("GDB bug: ax-general.c (generic_ext): opcode has inadequate range");
|
||||
|
||||
grow_expr (x, 2);
|
||||
x->buf[x->len++] = op;
|
||||
x->buf[x->len++] = n;
|
||||
}
|
||||
|
||||
|
||||
/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
|
||||
void
|
||||
ax_ext (struct agent_expr *x, int n)
|
||||
{
|
||||
generic_ext (x, aop_ext, n);
|
||||
}
|
||||
|
||||
|
||||
/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
|
||||
void
|
||||
ax_zero_ext (struct agent_expr *x, int n)
|
||||
{
|
||||
generic_ext (x, aop_zero_ext, n);
|
||||
}
|
||||
|
||||
|
||||
/* Append a trace_quick instruction to EXPR, to record N bytes. */
|
||||
void
|
||||
ax_trace_quick (struct agent_expr *x, int n)
|
||||
{
|
||||
/* N must fit in a byte. */
|
||||
if (n < 0 || n > 255)
|
||||
error ("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick");
|
||||
|
||||
grow_expr (x, 2);
|
||||
x->buf[x->len++] = aop_trace_quick;
|
||||
x->buf[x->len++] = n;
|
||||
}
|
||||
|
||||
|
||||
/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
|
||||
aop_if_goto). We assume we don't know the target offset yet,
|
||||
because it's probably a forward branch, so we leave space in EXPR
|
||||
for the target, and return the offset in EXPR of that space, so we
|
||||
can backpatch it once we do know the target offset. Use ax_label
|
||||
to do the backpatching. */
|
||||
int
|
||||
ax_goto (struct agent_expr *x, enum agent_op op)
|
||||
{
|
||||
grow_expr (x, 3);
|
||||
x->buf[x->len + 0] = op;
|
||||
x->buf[x->len + 1] = 0xff;
|
||||
x->buf[x->len + 2] = 0xff;
|
||||
x->len += 3;
|
||||
return x->len - 2;
|
||||
}
|
||||
|
||||
/* Suppose a given call to ax_goto returns some value PATCH. When you
|
||||
know the offset TARGET that goto should jump to, call
|
||||
ax_label (EXPR, PATCH, TARGET)
|
||||
to patch TARGET into the ax_goto instruction. */
|
||||
void
|
||||
ax_label (struct agent_expr *x, int patch, int target)
|
||||
{
|
||||
/* Make sure the value is in range. Don't accept 0xffff as an
|
||||
offset; that's our magic sentinel value for unpatched branches. */
|
||||
if (target < 0 || target >= 0xffff)
|
||||
error ("GDB bug: ax-general.c (ax_label): label target out of range");
|
||||
|
||||
x->buf[patch] = (target >> 8) & 0xff;
|
||||
x->buf[patch + 1] = target & 0xff;
|
||||
}
|
||||
|
||||
|
||||
/* Assemble code to push a constant on the stack. */
|
||||
void
|
||||
ax_const_l (struct agent_expr *x, LONGEST l)
|
||||
{
|
||||
static enum agent_op ops[]
|
||||
=
|
||||
{aop_const8, aop_const16, aop_const32, aop_const64};
|
||||
int size;
|
||||
int op;
|
||||
|
||||
/* How big is the number? 'op' keeps track of which opcode to use.
|
||||
Notice that we don't really care whether the original number was
|
||||
signed or unsigned; we always reproduce the value exactly, and
|
||||
use the shortest representation. */
|
||||
for (op = 0, size = 8; size < 64; size *= 2, op++)
|
||||
if (-((LONGEST) 1 << size) <= l && l < ((LONGEST) 1 << size))
|
||||
break;
|
||||
|
||||
/* Emit the right opcode... */
|
||||
ax_simple (x, ops[op]);
|
||||
|
||||
/* Emit the low SIZE bytes as an unsigned number. We know that
|
||||
sign-extending this will yield l. */
|
||||
append_const (x, l, size / 8);
|
||||
|
||||
/* Now, if it was negative, and not full-sized, sign-extend it. */
|
||||
if (l < 0 && size < 64)
|
||||
ax_ext (x, size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ax_const_d (struct agent_expr *x, LONGEST d)
|
||||
{
|
||||
/* FIXME: floating-point support not present yet. */
|
||||
error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
|
||||
}
|
||||
|
||||
|
||||
/* Assemble code to push the value of register number REG on the
|
||||
stack. */
|
||||
void
|
||||
ax_reg (struct agent_expr *x, int reg)
|
||||
{
|
||||
/* Make sure the register number is in range. */
|
||||
if (reg < 0 || reg > 0xffff)
|
||||
error ("GDB bug: ax-general.c (ax_reg): register number out of range");
|
||||
grow_expr (x, 3);
|
||||
x->buf[x->len] = aop_reg;
|
||||
x->buf[x->len + 1] = (reg >> 8) & 0xff;
|
||||
x->buf[x->len + 2] = (reg) & 0xff;
|
||||
x->len += 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Functions for disassembling agent expressions, and otherwise
|
||||
debugging the expression compiler. */
|
||||
|
||||
struct aop_map aop_map[] =
|
||||
{
|
||||
{0, 0, 0, 0, 0},
|
||||
{"float", 0, 0, 0, 0}, /* 0x01 */
|
||||
{"add", 0, 0, 2, 1}, /* 0x02 */
|
||||
{"sub", 0, 0, 2, 1}, /* 0x03 */
|
||||
{"mul", 0, 0, 2, 1}, /* 0x04 */
|
||||
{"div_signed", 0, 0, 2, 1}, /* 0x05 */
|
||||
{"div_unsigned", 0, 0, 2, 1}, /* 0x06 */
|
||||
{"rem_signed", 0, 0, 2, 1}, /* 0x07 */
|
||||
{"rem_unsigned", 0, 0, 2, 1}, /* 0x08 */
|
||||
{"lsh", 0, 0, 2, 1}, /* 0x09 */
|
||||
{"rsh_signed", 0, 0, 2, 1}, /* 0x0a */
|
||||
{"rsh_unsigned", 0, 0, 2, 1}, /* 0x0b */
|
||||
{"trace", 0, 0, 2, 0}, /* 0x0c */
|
||||
{"trace_quick", 1, 0, 1, 1}, /* 0x0d */
|
||||
{"log_not", 0, 0, 1, 1}, /* 0x0e */
|
||||
{"bit_and", 0, 0, 2, 1}, /* 0x0f */
|
||||
{"bit_or", 0, 0, 2, 1}, /* 0x10 */
|
||||
{"bit_xor", 0, 0, 2, 1}, /* 0x11 */
|
||||
{"bit_not", 0, 0, 1, 1}, /* 0x12 */
|
||||
{"equal", 0, 0, 2, 1}, /* 0x13 */
|
||||
{"less_signed", 0, 0, 2, 1}, /* 0x14 */
|
||||
{"less_unsigned", 0, 0, 2, 1}, /* 0x15 */
|
||||
{"ext", 1, 0, 1, 1}, /* 0x16 */
|
||||
{"ref8", 0, 8, 1, 1}, /* 0x17 */
|
||||
{"ref16", 0, 16, 1, 1}, /* 0x18 */
|
||||
{"ref32", 0, 32, 1, 1}, /* 0x19 */
|
||||
{"ref64", 0, 64, 1, 1}, /* 0x1a */
|
||||
{"ref_float", 0, 0, 1, 1}, /* 0x1b */
|
||||
{"ref_double", 0, 0, 1, 1}, /* 0x1c */
|
||||
{"ref_long_double", 0, 0, 1, 1}, /* 0x1d */
|
||||
{"l_to_d", 0, 0, 1, 1}, /* 0x1e */
|
||||
{"d_to_l", 0, 0, 1, 1}, /* 0x1f */
|
||||
{"if_goto", 2, 0, 1, 0}, /* 0x20 */
|
||||
{"goto", 2, 0, 0, 0}, /* 0x21 */
|
||||
{"const8", 1, 8, 0, 1}, /* 0x22 */
|
||||
{"const16", 2, 16, 0, 1}, /* 0x23 */
|
||||
{"const32", 4, 32, 0, 1}, /* 0x24 */
|
||||
{"const64", 8, 64, 0, 1}, /* 0x25 */
|
||||
{"reg", 2, 0, 0, 1}, /* 0x26 */
|
||||
{"end", 0, 0, 0, 0}, /* 0x27 */
|
||||
{"dup", 0, 0, 1, 2}, /* 0x28 */
|
||||
{"pop", 0, 0, 1, 0}, /* 0x29 */
|
||||
{"zero_ext", 1, 0, 1, 1}, /* 0x2a */
|
||||
{"swap", 0, 0, 2, 2}, /* 0x2b */
|
||||
{0, 0, 0, 0, 0}, /* 0x2c */
|
||||
{0, 0, 0, 0, 0}, /* 0x2d */
|
||||
{0, 0, 0, 0, 0}, /* 0x2e */
|
||||
{0, 0, 0, 0, 0}, /* 0x2f */
|
||||
{"trace16", 2, 0, 1, 1}, /* 0x30 */
|
||||
};
|
||||
|
||||
|
||||
/* Disassemble the expression EXPR, writing to F. */
|
||||
void
|
||||
ax_print (struct ui_file *f, struct agent_expr *x)
|
||||
{
|
||||
int i;
|
||||
int is_float = 0;
|
||||
|
||||
/* Check the size of the name array against the number of entries in
|
||||
the enum, to catch additions that people didn't sync. */
|
||||
if ((sizeof (aop_map) / sizeof (aop_map[0]))
|
||||
!= aop_last)
|
||||
error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
|
||||
|
||||
for (i = 0; i < x->len;)
|
||||
{
|
||||
enum agent_op op = x->buf[i];
|
||||
|
||||
if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
|
||||
|| !aop_map[op].name)
|
||||
{
|
||||
fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (i + 1 + aop_map[op].op_size > x->len)
|
||||
{
|
||||
fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
|
||||
i, aop_map[op].name);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
|
||||
if (aop_map[op].op_size > 0)
|
||||
{
|
||||
fputs_filtered (" ", f);
|
||||
|
||||
print_longest (f, 'd', 0,
|
||||
read_const (x, i + 1, aop_map[op].op_size));
|
||||
}
|
||||
fprintf_filtered (f, "\n");
|
||||
i += 1 + aop_map[op].op_size;
|
||||
|
||||
is_float = (op == aop_float);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Given an agent expression AX, fill in an agent_reqs structure REQS
|
||||
describing it. */
|
||||
void
|
||||
ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs)
|
||||
{
|
||||
int i;
|
||||
int height;
|
||||
|
||||
/* Bit vector for registers used. */
|
||||
int reg_mask_len = 1;
|
||||
unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
|
||||
|
||||
/* Jump target table. targets[i] is non-zero iff there is a jump to
|
||||
offset i. */
|
||||
char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
|
||||
|
||||
/* Instruction boundary table. boundary[i] is non-zero iff an
|
||||
instruction starts at offset i. */
|
||||
char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
|
||||
|
||||
/* Stack height record. iff either targets[i] or boundary[i] is
|
||||
non-zero, heights[i] is the height the stack should have before
|
||||
executing the bytecode at that point. */
|
||||
int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
|
||||
|
||||
/* Pointer to a description of the present op. */
|
||||
struct aop_map *op;
|
||||
|
||||
memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
|
||||
memset (targets, 0, ax->len * sizeof (targets[0]));
|
||||
memset (boundary, 0, ax->len * sizeof (boundary[0]));
|
||||
|
||||
reqs->max_height = reqs->min_height = height = 0;
|
||||
reqs->flaw = agent_flaw_none;
|
||||
reqs->max_data_size = 0;
|
||||
|
||||
for (i = 0; i < ax->len; i += 1 + op->op_size)
|
||||
{
|
||||
if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_instruction;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
op = &aop_map[ax->buf[i]];
|
||||
|
||||
if (!op->name)
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_instruction;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i + 1 + op->op_size > ax->len)
|
||||
{
|
||||
reqs->flaw = agent_flaw_incomplete_instruction;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this instruction is a jump target, does the current stack
|
||||
height match the stack height at the jump source? */
|
||||
if (targets[i] && (heights[i] != height))
|
||||
{
|
||||
reqs->flaw = agent_flaw_height_mismatch;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
boundary[i] = 1;
|
||||
heights[i] = height;
|
||||
|
||||
height -= op->consumed;
|
||||
if (height < reqs->min_height)
|
||||
reqs->min_height = height;
|
||||
height += op->produced;
|
||||
if (height > reqs->max_height)
|
||||
reqs->max_height = height;
|
||||
|
||||
if (op->data_size > reqs->max_data_size)
|
||||
reqs->max_data_size = op->data_size;
|
||||
|
||||
/* For jump instructions, check that the target is a valid
|
||||
offset. If it is, record the fact that that location is a
|
||||
jump target, and record the height we expect there. */
|
||||
if (aop_goto == op - aop_map
|
||||
|| aop_if_goto == op - aop_map)
|
||||
{
|
||||
int target = read_const (ax, i + 1, 2);
|
||||
if (target < 0 || target >= ax->len)
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_jump;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
/* Have we already found other jumps to the same location? */
|
||||
else if (targets[target])
|
||||
{
|
||||
if (heights[i] != height)
|
||||
{
|
||||
reqs->flaw = agent_flaw_height_mismatch;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targets[target] = 1;
|
||||
heights[target] = height;
|
||||
}
|
||||
}
|
||||
|
||||
/* For unconditional jumps with a successor, check that the
|
||||
successor is a target, and pick up its stack height. */
|
||||
if (aop_goto == op - aop_map
|
||||
&& i + 3 < ax->len)
|
||||
{
|
||||
if (!targets[i + 3])
|
||||
{
|
||||
reqs->flaw = agent_flaw_hole;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
height = heights[i + 3];
|
||||
}
|
||||
|
||||
/* For reg instructions, record the register in the bit mask. */
|
||||
if (aop_reg == op - aop_map)
|
||||
{
|
||||
int reg = read_const (ax, i + 1, 2);
|
||||
int byte = reg / 8;
|
||||
|
||||
/* Grow the bit mask if necessary. */
|
||||
if (byte >= reg_mask_len)
|
||||
{
|
||||
/* It's not appropriate to double here. This isn't a
|
||||
string buffer. */
|
||||
int new_len = byte + 1;
|
||||
reg_mask = xrealloc (reg_mask,
|
||||
new_len * sizeof (reg_mask[0]));
|
||||
memset (reg_mask + reg_mask_len, 0,
|
||||
(new_len - reg_mask_len) * sizeof (reg_mask[0]));
|
||||
reg_mask_len = new_len;
|
||||
}
|
||||
|
||||
reg_mask[byte] |= 1 << (reg % 8);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that all the targets are on boundaries. */
|
||||
for (i = 0; i < ax->len; i++)
|
||||
if (targets[i] && !boundary[i])
|
||||
{
|
||||
reqs->flaw = agent_flaw_bad_jump;
|
||||
xfree (reg_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
reqs->final_height = height;
|
||||
reqs->reg_mask_len = reg_mask_len;
|
||||
reqs->reg_mask = reg_mask;
|
||||
}
|
||||
292
gdb/ax.h
292
gdb/ax.h
@@ -1,292 +0,0 @@
|
||||
/* Definitions for expressions designed to be executed on the agent
|
||||
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef AGENTEXPR_H
|
||||
#define AGENTEXPR_H
|
||||
|
||||
#include "doublest.h" /* For DOUBLEST. */
|
||||
|
||||
/* It's sometimes useful to be able to debug programs that you can't
|
||||
really stop for more than a fraction of a second. To this end, the
|
||||
user can specify a tracepoint (like a breakpoint, but you don't
|
||||
stop at it), and specify a bunch of expressions to record the
|
||||
values of when that tracepoint is reached. As the program runs,
|
||||
GDB collects the values. At any point (possibly while values are
|
||||
still being collected), the user can display the collected values.
|
||||
|
||||
This is used with remote debugging; we don't really support it on
|
||||
native configurations.
|
||||
|
||||
This means that expressions are being evaluated by the remote agent,
|
||||
which doesn't have any access to the symbol table information, and
|
||||
needs to be small and simple.
|
||||
|
||||
The agent_expr routines and datatypes are a bytecode language
|
||||
designed to be executed by the agent. Agent expressions work in
|
||||
terms of fixed-width values, operators, memory references, and
|
||||
register references. You can evaluate a agent expression just given
|
||||
a bunch of memory and register values to sniff at; you don't need
|
||||
any symbolic information like variable names, types, etc.
|
||||
|
||||
GDB translates source expressions, whose meaning depends on
|
||||
symbolic information, into agent bytecode expressions, whose meaning
|
||||
is independent of symbolic information. This means the agent can
|
||||
evaluate them on the fly without reference to data only available
|
||||
to the host GDB. */
|
||||
|
||||
|
||||
/* Agent expression data structures. */
|
||||
|
||||
/* The type of an element of the agent expression stack.
|
||||
The bytecode operation indicates which element we should access;
|
||||
the value itself has no typing information. GDB generates all
|
||||
bytecode streams, so we don't have to worry about type errors. */
|
||||
|
||||
union agent_val
|
||||
{
|
||||
LONGEST l;
|
||||
DOUBLEST d;
|
||||
};
|
||||
|
||||
/* A buffer containing a agent expression. */
|
||||
struct agent_expr
|
||||
{
|
||||
unsigned char *buf;
|
||||
int len; /* number of characters used */
|
||||
int size; /* allocated size */
|
||||
CORE_ADDR scope;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* The actual values of the various bytecode operations.
|
||||
|
||||
Other independent implementations of the agent bytecode engine will
|
||||
rely on the exact values of these enums, and may not be recompiled
|
||||
when we change this table. The numeric values should remain fixed
|
||||
whenever possible. Thus, we assign them values explicitly here (to
|
||||
allow gaps to form safely), and the disassembly table in
|
||||
agentexpr.h behaves like an opcode map. If you want to see them
|
||||
grouped logically, see doc/agentexpr.texi. */
|
||||
|
||||
enum agent_op
|
||||
{
|
||||
aop_float = 0x01,
|
||||
aop_add = 0x02,
|
||||
aop_sub = 0x03,
|
||||
aop_mul = 0x04,
|
||||
aop_div_signed = 0x05,
|
||||
aop_div_unsigned = 0x06,
|
||||
aop_rem_signed = 0x07,
|
||||
aop_rem_unsigned = 0x08,
|
||||
aop_lsh = 0x09,
|
||||
aop_rsh_signed = 0x0a,
|
||||
aop_rsh_unsigned = 0x0b,
|
||||
aop_trace = 0x0c,
|
||||
aop_trace_quick = 0x0d,
|
||||
aop_log_not = 0x0e,
|
||||
aop_bit_and = 0x0f,
|
||||
aop_bit_or = 0x10,
|
||||
aop_bit_xor = 0x11,
|
||||
aop_bit_not = 0x12,
|
||||
aop_equal = 0x13,
|
||||
aop_less_signed = 0x14,
|
||||
aop_less_unsigned = 0x15,
|
||||
aop_ext = 0x16,
|
||||
aop_ref8 = 0x17,
|
||||
aop_ref16 = 0x18,
|
||||
aop_ref32 = 0x19,
|
||||
aop_ref64 = 0x1a,
|
||||
aop_ref_float = 0x1b,
|
||||
aop_ref_double = 0x1c,
|
||||
aop_ref_long_double = 0x1d,
|
||||
aop_l_to_d = 0x1e,
|
||||
aop_d_to_l = 0x1f,
|
||||
aop_if_goto = 0x20,
|
||||
aop_goto = 0x21,
|
||||
aop_const8 = 0x22,
|
||||
aop_const16 = 0x23,
|
||||
aop_const32 = 0x24,
|
||||
aop_const64 = 0x25,
|
||||
aop_reg = 0x26,
|
||||
aop_end = 0x27,
|
||||
aop_dup = 0x28,
|
||||
aop_pop = 0x29,
|
||||
aop_zero_ext = 0x2a,
|
||||
aop_swap = 0x2b,
|
||||
aop_trace16 = 0x30,
|
||||
aop_last
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Functions for building expressions. */
|
||||
|
||||
/* Allocate a new, empty agent expression. */
|
||||
extern struct agent_expr *new_agent_expr (CORE_ADDR);
|
||||
|
||||
/* Free a agent expression. */
|
||||
extern void free_agent_expr (struct agent_expr *);
|
||||
extern struct cleanup *make_cleanup_free_agent_expr (struct agent_expr *);
|
||||
|
||||
/* Append a simple operator OP to EXPR. */
|
||||
extern void ax_simple (struct agent_expr *EXPR, enum agent_op OP);
|
||||
|
||||
/* Append the floating-point prefix, for the next bytecode. */
|
||||
#define ax_float(EXPR) (ax_simple ((EXPR), aop_float))
|
||||
|
||||
/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
|
||||
extern void ax_ext (struct agent_expr *EXPR, int N);
|
||||
|
||||
/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
|
||||
extern void ax_zero_ext (struct agent_expr *EXPR, int N);
|
||||
|
||||
/* Append a trace_quick instruction to EXPR, to record N bytes. */
|
||||
extern void ax_trace_quick (struct agent_expr *EXPR, int N);
|
||||
|
||||
/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
|
||||
aop_if_goto). We assume we don't know the target offset yet,
|
||||
because it's probably a forward branch, so we leave space in EXPR
|
||||
for the target, and return the offset in EXPR of that space, so we
|
||||
can backpatch it once we do know the target offset. Use ax_label
|
||||
to do the backpatching. */
|
||||
extern int ax_goto (struct agent_expr *EXPR, enum agent_op OP);
|
||||
|
||||
/* Suppose a given call to ax_goto returns some value PATCH. When you
|
||||
know the offset TARGET that goto should jump to, call
|
||||
ax_label (EXPR, PATCH, TARGET)
|
||||
to patch TARGET into the ax_goto instruction. */
|
||||
extern void ax_label (struct agent_expr *EXPR, int patch, int target);
|
||||
|
||||
/* Assemble code to push a constant on the stack. */
|
||||
extern void ax_const_l (struct agent_expr *EXPR, LONGEST l);
|
||||
extern void ax_const_d (struct agent_expr *EXPR, LONGEST d);
|
||||
|
||||
/* Assemble code to push the value of register number REG on the
|
||||
stack. */
|
||||
extern void ax_reg (struct agent_expr *EXPR, int REG);
|
||||
|
||||
|
||||
/* Functions for printing out expressions, and otherwise debugging
|
||||
things. */
|
||||
|
||||
/* Disassemble the expression EXPR, writing to F. */
|
||||
extern void ax_print (struct ui_file *f, struct agent_expr * EXPR);
|
||||
|
||||
/* An entry in the opcode map. */
|
||||
struct aop_map
|
||||
{
|
||||
|
||||
/* The name of the opcode. Null means that this entry is not a
|
||||
valid opcode --- a hole in the opcode space. */
|
||||
char *name;
|
||||
|
||||
/* All opcodes take no operands from the bytecode stream, or take
|
||||
unsigned integers of various sizes. If this is a positive number
|
||||
n, then the opcode is followed by an n-byte operand, which should
|
||||
be printed as an unsigned integer. If this is zero, then the
|
||||
opcode takes no operands from the bytecode stream.
|
||||
|
||||
If we get more complicated opcodes in the future, don't add other
|
||||
magic values of this; that's a crock. Add an `enum encoding'
|
||||
field to this, or something like that. */
|
||||
int op_size;
|
||||
|
||||
/* The size of the data operated upon, in bits, for bytecodes that
|
||||
care about that (ref and const). Zero for all others. */
|
||||
int data_size;
|
||||
|
||||
/* Number of stack elements consumed, and number produced. */
|
||||
int consumed, produced;
|
||||
};
|
||||
|
||||
/* Map of the bytecodes, indexed by bytecode number. */
|
||||
extern struct aop_map aop_map[];
|
||||
|
||||
/* Different kinds of flaws an agent expression might have, as
|
||||
detected by agent_reqs. */
|
||||
enum agent_flaws
|
||||
{
|
||||
agent_flaw_none = 0, /* code is good */
|
||||
|
||||
/* There is an invalid instruction in the stream. */
|
||||
agent_flaw_bad_instruction,
|
||||
|
||||
/* There is an incomplete instruction at the end of the expression. */
|
||||
agent_flaw_incomplete_instruction,
|
||||
|
||||
/* agent_reqs was unable to prove that every jump target is to a
|
||||
valid offset. Valid offsets are within the bounds of the
|
||||
expression, and to a valid instruction boundary. */
|
||||
agent_flaw_bad_jump,
|
||||
|
||||
/* agent_reqs was unable to prove to its satisfaction that, for each
|
||||
jump target location, the stack will have the same height whether
|
||||
that location is reached via a jump or by straight execution. */
|
||||
agent_flaw_height_mismatch,
|
||||
|
||||
/* agent_reqs was unable to prove that every instruction following
|
||||
an unconditional jump was the target of some other jump. */
|
||||
agent_flaw_hole
|
||||
};
|
||||
|
||||
/* Structure describing the requirements of a bytecode expression. */
|
||||
struct agent_reqs
|
||||
{
|
||||
|
||||
/* If the following is not equal to agent_flaw_none, the rest of the
|
||||
information in this structure is suspect. */
|
||||
enum agent_flaws flaw;
|
||||
|
||||
/* Number of elements left on stack at end; may be negative if expr
|
||||
only consumes elements. */
|
||||
int final_height;
|
||||
|
||||
/* Maximum and minimum stack height, relative to initial height. */
|
||||
int max_height, min_height;
|
||||
|
||||
/* Largest `ref' or `const' opcode used, in bits. Zero means the
|
||||
expression has no such instructions. */
|
||||
int max_data_size;
|
||||
|
||||
/* Bit vector of registers used. Register R is used iff
|
||||
|
||||
reg_mask[R / 8] & (1 << (R % 8))
|
||||
|
||||
is non-zero. Note! You may not assume that this bitmask is long
|
||||
enough to hold bits for all the registers of the machine; the
|
||||
agent expression code has no idea how many registers the machine
|
||||
has. However, the bitmask is reg_mask_len bytes long, so the
|
||||
valid register numbers run from 0 to reg_mask_len * 8 - 1.
|
||||
|
||||
We're assuming eight-bit bytes. So sue me.
|
||||
|
||||
The caller should free reg_list when done. */
|
||||
int reg_mask_len;
|
||||
unsigned char *reg_mask;
|
||||
};
|
||||
|
||||
|
||||
/* Given an agent expression AX, fill in an agent_reqs structure REQS
|
||||
describing it. */
|
||||
extern void ax_reqs (struct agent_expr *ax, struct agent_reqs *reqs);
|
||||
|
||||
#endif /* AGENTEXPR_H */
|
||||
350
gdb/bcache.c
350
gdb/bcache.c
@@ -1,350 +0,0 @@
|
||||
/* Implement a cached obstack.
|
||||
Written by Fred Fish <fnf@cygnus.com>
|
||||
Rewritten by Jim Blandy <jimb@cygnus.com>
|
||||
|
||||
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "bcache.h"
|
||||
#include "gdb_string.h" /* For memcpy declaration */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The type used to hold a single bcache string. The user data is
|
||||
stored in d.data. Since it can be any type, it needs to have the
|
||||
same alignment as the most strict alignment of any type on the host
|
||||
machine. I don't know of any really correct way to do this in
|
||||
stock ANSI C, so just do it the same way obstack.h does. */
|
||||
|
||||
struct bstring
|
||||
{
|
||||
struct bstring *next;
|
||||
size_t length;
|
||||
|
||||
union
|
||||
{
|
||||
char data[1];
|
||||
double dummy;
|
||||
}
|
||||
d;
|
||||
};
|
||||
|
||||
|
||||
/* The structure for a bcache itself. The bcache is initialized, in
|
||||
bcache_xmalloc(), by filling it with zeros and then setting the
|
||||
corresponding obstack's malloc() and free() methods. */
|
||||
|
||||
struct bcache
|
||||
{
|
||||
/* All the bstrings are allocated here. */
|
||||
struct obstack cache;
|
||||
|
||||
/* How many hash buckets we're using. */
|
||||
unsigned int num_buckets;
|
||||
|
||||
/* Hash buckets. This table is allocated using malloc, so when we
|
||||
grow the table we can return the old table to the system. */
|
||||
struct bstring **bucket;
|
||||
|
||||
/* Statistics. */
|
||||
unsigned long unique_count; /* number of unique strings */
|
||||
long total_count; /* total number of strings cached, including dups */
|
||||
long unique_size; /* size of unique strings, in bytes */
|
||||
long total_size; /* total number of bytes cached, including dups */
|
||||
long structure_size; /* total size of bcache, including infrastructure */
|
||||
};
|
||||
|
||||
/* The old hash function was stolen from SDBM. This is what DB 3.0 uses now,
|
||||
* and is better than the old one.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
hash(const void *addr, int length)
|
||||
{
|
||||
const unsigned char *k, *e;
|
||||
unsigned long h;
|
||||
|
||||
k = (const unsigned char *)addr;
|
||||
e = k+length;
|
||||
for (h=0; k< e;++k)
|
||||
{
|
||||
h *=16777619;
|
||||
h ^= *k;
|
||||
}
|
||||
return (h);
|
||||
}
|
||||
|
||||
/* Growing the bcache's hash table. */
|
||||
|
||||
/* If the average chain length grows beyond this, then we want to
|
||||
resize our hash table. */
|
||||
#define CHAIN_LENGTH_THRESHOLD (5)
|
||||
|
||||
static void
|
||||
expand_hash_table (struct bcache *bcache)
|
||||
{
|
||||
/* A table of good hash table sizes. Whenever we grow, we pick the
|
||||
next larger size from this table. sizes[i] is close to 1 << (i+10),
|
||||
so we roughly double the table size each time. After we fall off
|
||||
the end of this table, we just double. Don't laugh --- there have
|
||||
been executables sighted with a gigabyte of debug info. */
|
||||
static unsigned long sizes[] = {
|
||||
1021, 2053, 4099, 8191, 16381, 32771,
|
||||
65537, 131071, 262144, 524287, 1048573, 2097143,
|
||||
4194301, 8388617, 16777213, 33554467, 67108859, 134217757,
|
||||
268435459, 536870923, 1073741827, 2147483659UL
|
||||
};
|
||||
unsigned int new_num_buckets;
|
||||
struct bstring **new_buckets;
|
||||
unsigned int i;
|
||||
|
||||
/* Find the next size. */
|
||||
new_num_buckets = bcache->num_buckets * 2;
|
||||
for (i = 0; i < (sizeof (sizes) / sizeof (sizes[0])); i++)
|
||||
if (sizes[i] > bcache->num_buckets)
|
||||
{
|
||||
new_num_buckets = sizes[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate the new table. */
|
||||
{
|
||||
size_t new_size = new_num_buckets * sizeof (new_buckets[0]);
|
||||
new_buckets = (struct bstring **) xmalloc (new_size);
|
||||
memset (new_buckets, 0, new_size);
|
||||
|
||||
bcache->structure_size -= (bcache->num_buckets
|
||||
* sizeof (bcache->bucket[0]));
|
||||
bcache->structure_size += new_size;
|
||||
}
|
||||
|
||||
/* Rehash all existing strings. */
|
||||
for (i = 0; i < bcache->num_buckets; i++)
|
||||
{
|
||||
struct bstring *s, *next;
|
||||
|
||||
for (s = bcache->bucket[i]; s; s = next)
|
||||
{
|
||||
struct bstring **new_bucket;
|
||||
next = s->next;
|
||||
|
||||
new_bucket = &new_buckets[(hash (&s->d.data, s->length)
|
||||
% new_num_buckets)];
|
||||
s->next = *new_bucket;
|
||||
*new_bucket = s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plug in the new table. */
|
||||
if (bcache->bucket)
|
||||
xfree (bcache->bucket);
|
||||
bcache->bucket = new_buckets;
|
||||
bcache->num_buckets = new_num_buckets;
|
||||
}
|
||||
|
||||
|
||||
/* Looking up things in the bcache. */
|
||||
|
||||
/* The number of bytes needed to allocate a struct bstring whose data
|
||||
is N bytes long. */
|
||||
#define BSTRING_SIZE(n) (offsetof (struct bstring, d.data) + (n))
|
||||
|
||||
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
|
||||
never seen those bytes before, add a copy of them to BCACHE. In
|
||||
either case, return a pointer to BCACHE's copy of that string. */
|
||||
void *
|
||||
bcache (const void *addr, int length, struct bcache *bcache)
|
||||
{
|
||||
int hash_index;
|
||||
struct bstring *s;
|
||||
|
||||
/* If our average chain length is too high, expand the hash table. */
|
||||
if (bcache->unique_count >= bcache->num_buckets * CHAIN_LENGTH_THRESHOLD)
|
||||
expand_hash_table (bcache);
|
||||
|
||||
bcache->total_count++;
|
||||
bcache->total_size += length;
|
||||
|
||||
hash_index = hash (addr, length) % bcache->num_buckets;
|
||||
|
||||
/* Search the hash bucket for a string identical to the caller's. */
|
||||
for (s = bcache->bucket[hash_index]; s; s = s->next)
|
||||
if (s->length == length
|
||||
&& ! memcmp (&s->d.data, addr, length))
|
||||
return &s->d.data;
|
||||
|
||||
/* The user's string isn't in the list. Insert it after *ps. */
|
||||
{
|
||||
struct bstring *new
|
||||
= obstack_alloc (&bcache->cache, BSTRING_SIZE (length));
|
||||
memcpy (&new->d.data, addr, length);
|
||||
new->length = length;
|
||||
new->next = bcache->bucket[hash_index];
|
||||
bcache->bucket[hash_index] = new;
|
||||
|
||||
bcache->unique_count++;
|
||||
bcache->unique_size += length;
|
||||
bcache->structure_size += BSTRING_SIZE (length);
|
||||
|
||||
return &new->d.data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allocating and freeing bcaches. */
|
||||
|
||||
struct bcache *
|
||||
bcache_xmalloc (void)
|
||||
{
|
||||
/* Allocate the bcache pre-zeroed. */
|
||||
struct bcache *b = XCALLOC (1, struct bcache);
|
||||
obstack_specify_allocation (&b->cache, 0, 0, xmalloc, xfree);
|
||||
return b;
|
||||
}
|
||||
|
||||
/* Free all the storage associated with BCACHE. */
|
||||
void
|
||||
bcache_xfree (struct bcache *bcache)
|
||||
{
|
||||
if (bcache == NULL)
|
||||
return;
|
||||
obstack_free (&bcache->cache, 0);
|
||||
xfree (bcache->bucket);
|
||||
xfree (bcache);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Printing statistics. */
|
||||
|
||||
static int
|
||||
compare_ints (const void *ap, const void *bp)
|
||||
{
|
||||
/* Because we know we're comparing two ints which are positive,
|
||||
there's no danger of overflow here. */
|
||||
return * (int *) ap - * (int *) bp;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_percentage (int portion, int total)
|
||||
{
|
||||
if (total == 0)
|
||||
printf_filtered ("(not applicable)\n");
|
||||
else
|
||||
printf_filtered ("%3d%%\n", portion * 100 / total);
|
||||
}
|
||||
|
||||
|
||||
/* Print statistics on BCACHE's memory usage and efficacity at
|
||||
eliminating duplication. NAME should describe the kind of data
|
||||
BCACHE holds. Statistics are printed using `printf_filtered' and
|
||||
its ilk. */
|
||||
void
|
||||
print_bcache_statistics (struct bcache *c, char *type)
|
||||
{
|
||||
int occupied_buckets;
|
||||
int max_chain_length;
|
||||
int median_chain_length;
|
||||
|
||||
/* Count the number of occupied buckets, and measure chain lengths. */
|
||||
{
|
||||
unsigned int b;
|
||||
int *chain_length
|
||||
= (int *) alloca (c->num_buckets * sizeof (*chain_length));
|
||||
|
||||
occupied_buckets = 0;
|
||||
|
||||
for (b = 0; b < c->num_buckets; b++)
|
||||
{
|
||||
struct bstring *s = c->bucket[b];
|
||||
|
||||
chain_length[b] = 0;
|
||||
|
||||
if (s)
|
||||
{
|
||||
occupied_buckets++;
|
||||
|
||||
while (s)
|
||||
{
|
||||
chain_length[b]++;
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* To compute the median, we need the set of chain lengths sorted. */
|
||||
qsort (chain_length, c->num_buckets, sizeof (chain_length[0]),
|
||||
compare_ints);
|
||||
|
||||
if (c->num_buckets > 0)
|
||||
{
|
||||
max_chain_length = chain_length[c->num_buckets - 1];
|
||||
median_chain_length = chain_length[c->num_buckets / 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
max_chain_length = 0;
|
||||
median_chain_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf_filtered (" Cached '%s' statistics:\n", type);
|
||||
printf_filtered (" Total object count: %ld\n", c->total_count);
|
||||
printf_filtered (" Unique object count: %lu\n", c->unique_count);
|
||||
printf_filtered (" Percentage of duplicates, by count: ");
|
||||
print_percentage (c->total_count - c->unique_count, c->total_count);
|
||||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Total object size: %ld\n", c->total_size);
|
||||
printf_filtered (" Unique object size: %ld\n", c->unique_size);
|
||||
printf_filtered (" Percentage of duplicates, by size: ");
|
||||
print_percentage (c->total_size - c->unique_size, c->total_size);
|
||||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Total memory used by bcache, including overhead: %ld\n",
|
||||
c->structure_size);
|
||||
printf_filtered (" Percentage memory overhead: ");
|
||||
print_percentage (c->structure_size - c->unique_size, c->unique_size);
|
||||
printf_filtered (" Net memory savings: ");
|
||||
print_percentage (c->total_size - c->structure_size, c->total_size);
|
||||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Hash table size: %3d\n", c->num_buckets);
|
||||
printf_filtered (" Hash table population: ");
|
||||
print_percentage (occupied_buckets, c->num_buckets);
|
||||
printf_filtered (" Median hash chain length: %3d\n",
|
||||
median_chain_length);
|
||||
printf_filtered (" Average hash chain length: ");
|
||||
if (c->num_buckets > 0)
|
||||
printf_filtered ("%3lu\n", c->unique_count / c->num_buckets);
|
||||
else
|
||||
printf_filtered ("(not applicable)\n");
|
||||
printf_filtered (" Maximum hash chain length: %3d\n", max_chain_length);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
|
||||
int
|
||||
bcache_memory_used (struct bcache *bcache)
|
||||
{
|
||||
return obstack_memory_used (&bcache->cache);
|
||||
}
|
||||
90
gdb/bcache.h
90
gdb/bcache.h
@@ -1,90 +0,0 @@
|
||||
/* Include file cached obstack implementation.
|
||||
Written by Fred Fish <fnf@cygnus.com>
|
||||
Rewritten by Jim Blandy <jimb@cygnus.com>
|
||||
|
||||
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef BCACHE_H
|
||||
#define BCACHE_H 1
|
||||
|
||||
/* A bcache is a data structure for factoring out duplication in
|
||||
read-only structures. You give the bcache some string of bytes S.
|
||||
If the bcache already contains a copy of S, it hands you back a
|
||||
pointer to its copy. Otherwise, it makes a fresh copy of S, and
|
||||
hands you back a pointer to that. In either case, you can throw
|
||||
away your copy of S, and use the bcache's.
|
||||
|
||||
The "strings" in question are arbitrary strings of bytes --- they
|
||||
can contain zero bytes. You pass in the length explicitly when you
|
||||
call the bcache function.
|
||||
|
||||
This means that you can put ordinary C objects in a bcache.
|
||||
However, if you do this, remember that structs can contain `holes'
|
||||
between members, added for alignment. These bytes usually contain
|
||||
garbage. If you try to bcache two objects which are identical from
|
||||
your code's point of view, but have different garbage values in the
|
||||
structure's holes, then the bcache will treat them as separate
|
||||
strings, and you won't get the nice elimination of duplicates you
|
||||
were hoping for. So, remember to memset your structures full of
|
||||
zeros before bcaching them!
|
||||
|
||||
You shouldn't modify the strings you get from a bcache, because:
|
||||
|
||||
- You don't necessarily know who you're sharing space with. If I
|
||||
stick eight bytes of text in a bcache, and then stick an
|
||||
eight-byte structure in the same bcache, there's no guarantee
|
||||
those two objects don't actually comprise the same sequence of
|
||||
bytes. If they happen to, the bcache will use a single byte
|
||||
string for both of them. Then, modifying the structure will
|
||||
change the string. In bizarre ways.
|
||||
|
||||
- Even if you know for some other reason that all that's okay,
|
||||
there's another problem. A bcache stores all its strings in a
|
||||
hash table. If you modify a string's contents, you will probably
|
||||
change its hash value. This means that the modified string is
|
||||
now in the wrong place in the hash table, and future bcache
|
||||
probes will never find it. So by mutating a string, you give up
|
||||
any chance of sharing its space with future duplicates. */
|
||||
|
||||
|
||||
struct bcache;
|
||||
|
||||
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
|
||||
never seen those bytes before, add a copy of them to BCACHE. In
|
||||
either case, return a pointer to BCACHE's copy of that string. */
|
||||
extern void *bcache (const void *addr, int length, struct bcache *bcache);
|
||||
|
||||
/* Free all the storage used by BCACHE. */
|
||||
extern void bcache_xfree (struct bcache *bcache);
|
||||
|
||||
/* Create a new bcache object. */
|
||||
extern struct bcache *bcache_xmalloc (void);
|
||||
|
||||
/* Print statistics on BCACHE's memory usage and efficacity at
|
||||
eliminating duplication. TYPE should be a string describing the
|
||||
kind of data BCACHE holds. Statistics are printed using
|
||||
`printf_filtered' and its ilk. */
|
||||
extern void print_bcache_statistics (struct bcache *bcache, char *type);
|
||||
extern int bcache_memory_used (struct bcache *bcache);
|
||||
|
||||
/* The hash function */
|
||||
extern unsigned long hash(const void *addr, int length);
|
||||
|
||||
#endif /* BCACHE_H */
|
||||
1588
gdb/blockframe.c
1588
gdb/blockframe.c
File diff suppressed because it is too large
Load Diff
7738
gdb/breakpoint.c
7738
gdb/breakpoint.c
File diff suppressed because it is too large
Load Diff
709
gdb/breakpoint.h
709
gdb/breakpoint.h
@@ -1,709 +0,0 @@
|
||||
/* Data structures associated with breakpoints in GDB.
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (BREAKPOINT_H)
|
||||
#define BREAKPOINT_H 1
|
||||
|
||||
#include "frame.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "gdb-events.h"
|
||||
|
||||
struct value;
|
||||
|
||||
/* This is the maximum number of bytes a breakpoint instruction can take.
|
||||
Feel free to increase it. It's just used in a few places to size
|
||||
arrays that should be independent of the target architecture. */
|
||||
|
||||
#define BREAKPOINT_MAX 16
|
||||
|
||||
/* Type of breakpoint. */
|
||||
/* FIXME In the future, we should fold all other breakpoint-like things into
|
||||
here. This includes:
|
||||
|
||||
* single-step (for machines where we have to simulate single stepping)
|
||||
(probably, though perhaps it is better for it to look as much as
|
||||
possible like a single-step to wait_for_inferior). */
|
||||
|
||||
enum bptype
|
||||
{
|
||||
bp_none = 0, /* Eventpoint has been deleted. */
|
||||
bp_breakpoint, /* Normal breakpoint */
|
||||
bp_hardware_breakpoint, /* Hardware assisted breakpoint */
|
||||
bp_until, /* used by until command */
|
||||
bp_finish, /* used by finish command */
|
||||
bp_watchpoint, /* Watchpoint */
|
||||
bp_hardware_watchpoint, /* Hardware assisted watchpoint */
|
||||
bp_read_watchpoint, /* read watchpoint, (hardware assisted) */
|
||||
bp_access_watchpoint, /* access watchpoint, (hardware assisted) */
|
||||
bp_longjmp, /* secret breakpoint to find longjmp() */
|
||||
bp_longjmp_resume, /* secret breakpoint to escape longjmp() */
|
||||
|
||||
/* Used by wait_for_inferior for stepping over subroutine calls, for
|
||||
stepping over signal handlers, and for skipping prologues. */
|
||||
bp_step_resume,
|
||||
|
||||
/* Used by wait_for_inferior for stepping over signal handlers. */
|
||||
bp_through_sigtramp,
|
||||
|
||||
/* Used to detect when a watchpoint expression has gone out of
|
||||
scope. These breakpoints are usually not visible to the user.
|
||||
|
||||
This breakpoint has some interesting properties:
|
||||
|
||||
1) There's always a 1:1 mapping between watchpoints
|
||||
on local variables and watchpoint_scope breakpoints.
|
||||
|
||||
2) It automatically deletes itself and the watchpoint it's
|
||||
associated with when hit.
|
||||
|
||||
3) It can never be disabled. */
|
||||
bp_watchpoint_scope,
|
||||
|
||||
/* The breakpoint at the end of a call dummy. */
|
||||
/* FIXME: What if the function we are calling longjmp()s out of the
|
||||
call, or the user gets out with the "return" command? We currently
|
||||
have no way of cleaning up the breakpoint in these (obscure) situations.
|
||||
(Probably can solve this by noticing longjmp, "return", etc., it's
|
||||
similar to noticing when a watchpoint on a local variable goes out
|
||||
of scope (with hardware support for watchpoints)). */
|
||||
bp_call_dummy,
|
||||
|
||||
/* Some dynamic linkers (HP, maybe Solaris) can arrange for special
|
||||
code in the inferior to run when significant events occur in the
|
||||
dynamic linker (for example a library is loaded or unloaded).
|
||||
|
||||
By placing a breakpoint in this magic code GDB will get control
|
||||
when these significant events occur. GDB can then re-examine
|
||||
the dynamic linker's data structures to discover any newly loaded
|
||||
dynamic libraries. */
|
||||
bp_shlib_event,
|
||||
|
||||
/* Some multi-threaded systems can arrange for a location in the
|
||||
inferior to be executed when certain thread-related events occur
|
||||
(such as thread creation or thread death).
|
||||
|
||||
By placing a breakpoint at one of these locations, GDB will get
|
||||
control when these events occur. GDB can then update its thread
|
||||
lists etc. */
|
||||
|
||||
bp_thread_event,
|
||||
|
||||
/* On the same principal, an overlay manager can arrange to call a
|
||||
magic location in the inferior whenever there is an interesting
|
||||
change in overlay status. GDB can update its overlay tables
|
||||
and fiddle with breakpoints in overlays when this breakpoint
|
||||
is hit. */
|
||||
|
||||
bp_overlay_event,
|
||||
|
||||
/* These breakpoints are used to implement the "catch load" command
|
||||
on platforms whose dynamic linkers support such functionality. */
|
||||
bp_catch_load,
|
||||
|
||||
/* These breakpoints are used to implement the "catch unload" command
|
||||
on platforms whose dynamic linkers support such functionality. */
|
||||
bp_catch_unload,
|
||||
|
||||
/* These are not really breakpoints, but are catchpoints that
|
||||
implement the "catch fork", "catch vfork" and "catch exec" commands
|
||||
on platforms whose kernel support such functionality. (I.e.,
|
||||
kernels which can raise an event when a fork or exec occurs, as
|
||||
opposed to the debugger setting breakpoints on functions named
|
||||
"fork" or "exec".) */
|
||||
bp_catch_fork,
|
||||
bp_catch_vfork,
|
||||
bp_catch_exec,
|
||||
|
||||
/* These are catchpoints to implement "catch catch" and "catch throw"
|
||||
commands for C++ exception handling. */
|
||||
bp_catch_catch,
|
||||
bp_catch_throw
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* States of enablement of breakpoint. */
|
||||
|
||||
enum enable_state
|
||||
{
|
||||
bp_disabled, /* The eventpoint is inactive, and cannot trigger. */
|
||||
bp_enabled, /* The eventpoint is active, and can trigger. */
|
||||
bp_shlib_disabled, /* The eventpoint's address is in an unloaded solib.
|
||||
The eventpoint will be automatically enabled
|
||||
and reset when that solib is loaded. */
|
||||
bp_call_disabled, /* The eventpoint has been disabled while a call
|
||||
into the inferior is "in flight", because some
|
||||
eventpoints interfere with the implementation of
|
||||
a call on some targets. The eventpoint will be
|
||||
automatically enabled and reset when the call
|
||||
"lands" (either completes, or stops at another
|
||||
eventpoint). */
|
||||
bp_permanent /* There is a breakpoint instruction hard-wired into
|
||||
the target's code. Don't try to write another
|
||||
breakpoint instruction on top of it, or restore
|
||||
its value. Step over it using the architecture's
|
||||
SKIP_INSN macro. */
|
||||
};
|
||||
|
||||
|
||||
/* Disposition of breakpoint. Ie: what to do after hitting it. */
|
||||
|
||||
enum bpdisp
|
||||
{
|
||||
disp_del, /* Delete it */
|
||||
disp_del_at_next_stop, /* Delete at next stop, whether hit or not */
|
||||
disp_disable, /* Disable it */
|
||||
disp_donttouch /* Leave it alone */
|
||||
};
|
||||
|
||||
enum target_hw_bp_type
|
||||
{
|
||||
hw_write = 0, /* Common HW watchpoint */
|
||||
hw_read = 1, /* Read HW watchpoint */
|
||||
hw_access = 2, /* Access HW watchpoint */
|
||||
hw_execute = 3 /* Execute HW breakpoint */
|
||||
};
|
||||
|
||||
/* Note that the ->silent field is not currently used by any commands
|
||||
(though the code is in there if it was to be, and set_raw_breakpoint
|
||||
does set it to 0). I implemented it because I thought it would be
|
||||
useful for a hack I had to put in; I'm going to leave it in because
|
||||
I can see how there might be times when it would indeed be useful */
|
||||
|
||||
/* This is for a breakpoint or a watchpoint. */
|
||||
|
||||
struct breakpoint
|
||||
{
|
||||
struct breakpoint *next;
|
||||
/* Type of breakpoint. */
|
||||
enum bptype type;
|
||||
/* Zero means disabled; remember the info but don't break here. */
|
||||
enum enable_state enable_state;
|
||||
/* What to do with this breakpoint after we hit it. */
|
||||
enum bpdisp disposition;
|
||||
/* Number assigned to distinguish breakpoints. */
|
||||
int number;
|
||||
|
||||
/* Address to break at.
|
||||
Note that zero is a perfectly valid code address on some
|
||||
platforms (for example, the mn10200 and mn10300 simulators).
|
||||
NULL is not a special value for this field. */
|
||||
CORE_ADDR address;
|
||||
|
||||
/* Line number of this address. */
|
||||
|
||||
int line_number;
|
||||
|
||||
/* Source file name of this address. */
|
||||
|
||||
char *source_file;
|
||||
|
||||
/* Non-zero means a silent breakpoint (don't print frame info
|
||||
if we stop here). */
|
||||
unsigned char silent;
|
||||
/* Number of stops at this breakpoint that should
|
||||
be continued automatically before really stopping. */
|
||||
int ignore_count;
|
||||
/* "Real" contents of byte where breakpoint has been inserted.
|
||||
Valid only when breakpoints are in the program. Under the complete
|
||||
control of the target insert_breakpoint and remove_breakpoint routines.
|
||||
No other code should assume anything about the value(s) here. */
|
||||
char shadow_contents[BREAKPOINT_MAX];
|
||||
/* Nonzero if this breakpoint is now inserted. */
|
||||
char inserted;
|
||||
/* Nonzero if this is not the first breakpoint in the list
|
||||
for the given address. */
|
||||
char duplicate;
|
||||
/* Chain of command lines to execute when this breakpoint is hit. */
|
||||
struct command_line *commands;
|
||||
/* Stack depth (address of frame). If nonzero, break only if fp
|
||||
equals this. */
|
||||
CORE_ADDR frame;
|
||||
/* Conditional. Break only if this expression's value is nonzero. */
|
||||
struct expression *cond;
|
||||
|
||||
/* String we used to set the breakpoint (malloc'd). */
|
||||
char *addr_string;
|
||||
/* Language we used to set the breakpoint. */
|
||||
enum language language;
|
||||
/* Input radix we used to set the breakpoint. */
|
||||
int input_radix;
|
||||
/* String form of the breakpoint condition (malloc'd), or NULL if there
|
||||
is no condition. */
|
||||
char *cond_string;
|
||||
/* String form of exp (malloc'd), or NULL if none. */
|
||||
char *exp_string;
|
||||
|
||||
/* The expression we are watching, or NULL if not a watchpoint. */
|
||||
struct expression *exp;
|
||||
/* The largest block within which it is valid, or NULL if it is
|
||||
valid anywhere (e.g. consists just of global symbols). */
|
||||
struct block *exp_valid_block;
|
||||
/* Value of the watchpoint the last time we checked it. */
|
||||
struct value *val;
|
||||
|
||||
/* Holds the value chain for a hardware watchpoint expression. */
|
||||
struct value *val_chain;
|
||||
|
||||
/* Holds the address of the related watchpoint_scope breakpoint
|
||||
when using watchpoints on local variables (might the concept
|
||||
of a related breakpoint be useful elsewhere, if not just call
|
||||
it the watchpoint_scope breakpoint or something like that. FIXME). */
|
||||
struct breakpoint *related_breakpoint;
|
||||
|
||||
/* Holds the frame address which identifies the frame this
|
||||
watchpoint should be evaluated in, or `null' if the watchpoint
|
||||
should be evaluated on the outermost frame. */
|
||||
struct frame_id watchpoint_frame;
|
||||
|
||||
/* Thread number for thread-specific breakpoint, or -1 if don't care */
|
||||
int thread;
|
||||
|
||||
/* Count of the number of times this breakpoint was taken, dumped
|
||||
with the info, but not used for anything else. Useful for
|
||||
seeing how many times you hit a break prior to the program
|
||||
aborting, so you can back up to just before the abort. */
|
||||
int hit_count;
|
||||
|
||||
/* Filename of a dynamically-linked library (dll), used for
|
||||
bp_catch_load and bp_catch_unload (malloc'd), or NULL if any
|
||||
library is significant. */
|
||||
char *dll_pathname;
|
||||
|
||||
/* Filename of a dll whose state change (e.g., load or unload)
|
||||
triggered this catchpoint. This field is only valid immediately
|
||||
after this catchpoint has triggered. */
|
||||
char *triggered_dll_pathname;
|
||||
|
||||
/* Process id of a child process whose forking triggered this
|
||||
catchpoint. This field is only valid immediately after this
|
||||
catchpoint has triggered. */
|
||||
int forked_inferior_pid;
|
||||
|
||||
/* Filename of a program whose exec triggered this catchpoint.
|
||||
This field is only valid immediately after this catchpoint has
|
||||
triggered. */
|
||||
char *exec_pathname;
|
||||
|
||||
asection *section;
|
||||
};
|
||||
|
||||
/* The following stuff is an abstract data type "bpstat" ("breakpoint
|
||||
status"). This provides the ability to determine whether we have
|
||||
stopped at a breakpoint, and what we should do about it. */
|
||||
|
||||
typedef struct bpstats *bpstat;
|
||||
|
||||
/* Interface: */
|
||||
/* Clear a bpstat so that it says we are not at any breakpoint.
|
||||
Also free any storage that is part of a bpstat. */
|
||||
extern void bpstat_clear (bpstat *);
|
||||
|
||||
/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
|
||||
is part of the bpstat is copied as well. */
|
||||
extern bpstat bpstat_copy (bpstat);
|
||||
|
||||
extern bpstat bpstat_stop_status (CORE_ADDR *, int);
|
||||
|
||||
/* This bpstat_what stuff tells wait_for_inferior what to do with a
|
||||
breakpoint (a challenging task). */
|
||||
|
||||
enum bpstat_what_main_action
|
||||
{
|
||||
/* Perform various other tests; that is, this bpstat does not
|
||||
say to perform any action (e.g. failed watchpoint and nothing
|
||||
else). */
|
||||
BPSTAT_WHAT_KEEP_CHECKING,
|
||||
|
||||
/* Rather than distinguish between noisy and silent stops here, it
|
||||
might be cleaner to have bpstat_print make that decision (also
|
||||
taking into account stop_print_frame and source_only). But the
|
||||
implications are a bit scary (interaction with auto-displays, etc.),
|
||||
so I won't try it. */
|
||||
|
||||
/* Stop silently. */
|
||||
BPSTAT_WHAT_STOP_SILENT,
|
||||
|
||||
/* Stop and print. */
|
||||
BPSTAT_WHAT_STOP_NOISY,
|
||||
|
||||
/* Remove breakpoints, single step once, then put them back in and
|
||||
go back to what we were doing. It's possible that this should be
|
||||
removed from the main_action and put into a separate field, to more
|
||||
cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */
|
||||
BPSTAT_WHAT_SINGLE,
|
||||
|
||||
/* Set longjmp_resume breakpoint, remove all other breakpoints,
|
||||
and continue. The "remove all other breakpoints" part is required
|
||||
if we are also stepping over another breakpoint as well as doing
|
||||
the longjmp handling. */
|
||||
BPSTAT_WHAT_SET_LONGJMP_RESUME,
|
||||
|
||||
/* Clear longjmp_resume breakpoint, then handle as
|
||||
BPSTAT_WHAT_KEEP_CHECKING. */
|
||||
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
|
||||
|
||||
/* Clear longjmp_resume breakpoint, then handle as BPSTAT_WHAT_SINGLE. */
|
||||
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE,
|
||||
|
||||
/* Clear step resume breakpoint, and keep checking. */
|
||||
BPSTAT_WHAT_STEP_RESUME,
|
||||
|
||||
/* Clear through_sigtramp breakpoint, muck with trap_expected, and keep
|
||||
checking. */
|
||||
BPSTAT_WHAT_THROUGH_SIGTRAMP,
|
||||
|
||||
/* Check the dynamic linker's data structures for new libraries, then
|
||||
keep checking. */
|
||||
BPSTAT_WHAT_CHECK_SHLIBS,
|
||||
|
||||
/* Check the dynamic linker's data structures for new libraries, then
|
||||
resume out of the dynamic linker's callback, stop and print. */
|
||||
BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK,
|
||||
|
||||
/* This is just used to keep track of how many enums there are. */
|
||||
BPSTAT_WHAT_LAST
|
||||
};
|
||||
|
||||
struct bpstat_what
|
||||
{
|
||||
enum bpstat_what_main_action main_action;
|
||||
|
||||
/* Did we hit a call dummy breakpoint? This only goes with a main_action
|
||||
of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
|
||||
continuing from a call dummy without popping the frame is not a
|
||||
useful one). */
|
||||
int call_dummy;
|
||||
};
|
||||
|
||||
/* The possible return values for print_bpstat, print_it_normal,
|
||||
print_it_done, print_it_noop. */
|
||||
enum print_stop_action
|
||||
{
|
||||
PRINT_UNKNOWN = -1,
|
||||
PRINT_SRC_AND_LOC,
|
||||
PRINT_SRC_ONLY,
|
||||
PRINT_NOTHING
|
||||
};
|
||||
|
||||
/* Tell what to do about this bpstat. */
|
||||
struct bpstat_what bpstat_what (bpstat);
|
||||
|
||||
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
|
||||
bpstat bpstat_find_breakpoint (bpstat, struct breakpoint *);
|
||||
|
||||
/* Find a step_resume breakpoint associated with this bpstat.
|
||||
(If there are multiple step_resume bp's on the list, this function
|
||||
will arbitrarily pick one.)
|
||||
|
||||
It is an error to use this function if BPSTAT doesn't contain a
|
||||
step_resume breakpoint.
|
||||
|
||||
See wait_for_inferior's use of this function.
|
||||
*/
|
||||
extern struct breakpoint *bpstat_find_step_resume_breakpoint (bpstat);
|
||||
|
||||
/* Nonzero if a signal that we got in wait() was due to circumstances
|
||||
explained by the BS. */
|
||||
/* Currently that is true if we have hit a breakpoint, or if there is
|
||||
a watchpoint enabled. */
|
||||
#define bpstat_explains_signal(bs) ((bs) != NULL)
|
||||
|
||||
/* Nonzero if we should step constantly (e.g. watchpoints on machines
|
||||
without hardware support). This isn't related to a specific bpstat,
|
||||
just to things like whether watchpoints are set. */
|
||||
extern int bpstat_should_step (void);
|
||||
|
||||
/* Nonzero if there are enabled hardware watchpoints. */
|
||||
extern int bpstat_have_active_hw_watchpoints (void);
|
||||
|
||||
/* Print a message indicating what happened. Returns nonzero to
|
||||
say that only the source line should be printed after this (zero
|
||||
return means print the frame as well as the source line). */
|
||||
extern enum print_stop_action bpstat_print (bpstat);
|
||||
|
||||
/* Return the breakpoint number of the first breakpoint we are stopped
|
||||
at. *BSP upon return is a bpstat which points to the remaining
|
||||
breakpoints stopped at (but which is not guaranteed to be good for
|
||||
anything but further calls to bpstat_num).
|
||||
Return 0 if passed a bpstat which does not indicate any breakpoints. */
|
||||
extern int bpstat_num (bpstat *);
|
||||
|
||||
/* Perform actions associated with having stopped at *BSP. Actually, we just
|
||||
use this for breakpoint commands. Perhaps other actions will go here
|
||||
later, but this is executed at a late time (from the command loop). */
|
||||
extern void bpstat_do_actions (bpstat *);
|
||||
|
||||
/* Modify BS so that the actions will not be performed. */
|
||||
extern void bpstat_clear_actions (bpstat);
|
||||
|
||||
/* Given a bpstat that records zero or more triggered eventpoints, this
|
||||
function returns another bpstat which contains only the catchpoints
|
||||
on that first list, if any.
|
||||
*/
|
||||
extern void bpstat_get_triggered_catchpoints (bpstat, bpstat *);
|
||||
|
||||
/* Implementation: */
|
||||
|
||||
/* Values used to tell the printing routine how to behave for this bpstat. */
|
||||
enum bp_print_how
|
||||
{
|
||||
/* This is used when we want to do a normal printing of the reason
|
||||
for stopping. The output will depend on the type of eventpoint
|
||||
we are dealing with. This is the default value, most commonly
|
||||
used. */
|
||||
print_it_normal,
|
||||
/* This is used when nothing should be printed for this bpstat entry. */
|
||||
print_it_noop,
|
||||
/* This is used when everything which needs to be printed has
|
||||
already been printed. But we still want to print the frame. */
|
||||
print_it_done
|
||||
};
|
||||
|
||||
struct bpstats
|
||||
{
|
||||
/* Linked list because there can be two breakpoints at the same
|
||||
place, and a bpstat reflects the fact that both have been hit. */
|
||||
bpstat next;
|
||||
/* Breakpoint that we are at. */
|
||||
struct breakpoint *breakpoint_at;
|
||||
/* Commands left to be done. */
|
||||
struct command_line *commands;
|
||||
/* Old value associated with a watchpoint. */
|
||||
struct value *old_val;
|
||||
|
||||
/* Nonzero if this breakpoint tells us to print the frame. */
|
||||
char print;
|
||||
|
||||
/* Nonzero if this breakpoint tells us to stop. */
|
||||
char stop;
|
||||
|
||||
/* Tell bpstat_print and print_bp_stop_message how to print stuff
|
||||
associated with this element of the bpstat chain. */
|
||||
enum bp_print_how print_it;
|
||||
};
|
||||
|
||||
enum inf_context
|
||||
{
|
||||
inf_starting,
|
||||
inf_running,
|
||||
inf_exited
|
||||
};
|
||||
|
||||
/* The possible return values for breakpoint_here_p.
|
||||
We guarantee that zero always means "no breakpoint here". */
|
||||
enum breakpoint_here
|
||||
{
|
||||
no_breakpoint_here = 0,
|
||||
ordinary_breakpoint_here,
|
||||
permanent_breakpoint_here
|
||||
};
|
||||
|
||||
|
||||
/* Prototypes for breakpoint-related functions. */
|
||||
|
||||
/* Forward declarations for prototypes */
|
||||
struct frame_info;
|
||||
|
||||
extern enum breakpoint_here breakpoint_here_p (CORE_ADDR);
|
||||
|
||||
extern int breakpoint_inserted_here_p (CORE_ADDR);
|
||||
|
||||
extern int frame_in_dummy (struct frame_info *);
|
||||
|
||||
extern int breakpoint_thread_match (CORE_ADDR, ptid_t);
|
||||
|
||||
extern void until_break_command (char *, int);
|
||||
|
||||
extern void breakpoint_re_set (void);
|
||||
|
||||
extern void breakpoint_re_set_thread (struct breakpoint *);
|
||||
|
||||
extern int ep_is_exception_catchpoint (struct breakpoint *);
|
||||
|
||||
extern struct breakpoint *set_momentary_breakpoint
|
||||
(struct symtab_and_line, struct frame_info *, enum bptype);
|
||||
|
||||
extern void set_ignore_count (int, int, int);
|
||||
|
||||
extern void set_default_breakpoint (int, CORE_ADDR, struct symtab *, int);
|
||||
|
||||
extern void mark_breakpoints_out (void);
|
||||
|
||||
extern void breakpoint_init_inferior (enum inf_context);
|
||||
|
||||
extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *);
|
||||
|
||||
extern struct cleanup *make_exec_cleanup_delete_breakpoint (struct breakpoint *);
|
||||
|
||||
extern void delete_breakpoint (struct breakpoint *);
|
||||
|
||||
extern void breakpoint_auto_delete (bpstat);
|
||||
|
||||
extern void breakpoint_clear_ignore_counts (void);
|
||||
|
||||
extern void break_command (char *, int);
|
||||
|
||||
extern void hbreak_command_wrapper (char *, int);
|
||||
extern void thbreak_command_wrapper (char *, int);
|
||||
extern void rbreak_command_wrapper (char *, int);
|
||||
extern void watch_command_wrapper (char *, int);
|
||||
extern void awatch_command_wrapper (char *, int);
|
||||
extern void rwatch_command_wrapper (char *, int);
|
||||
extern void tbreak_command (char *, int);
|
||||
|
||||
extern int insert_breakpoints (void);
|
||||
|
||||
extern int remove_breakpoints (void);
|
||||
|
||||
/* This function can be used to physically insert eventpoints from the
|
||||
specified traced inferior process, without modifying the breakpoint
|
||||
package's state. This can be useful for those targets which support
|
||||
following the processes of a fork() or vfork() system call, when both
|
||||
of the resulting two processes are to be followed. */
|
||||
extern int reattach_breakpoints (int);
|
||||
|
||||
/* This function can be used to update the breakpoint package's state
|
||||
after an exec() system call has been executed.
|
||||
|
||||
This function causes the following:
|
||||
|
||||
- All eventpoints are marked "not inserted".
|
||||
- All eventpoints with a symbolic address are reset such that
|
||||
the symbolic address must be reevaluated before the eventpoints
|
||||
can be reinserted.
|
||||
- The solib breakpoints are explicitly removed from the breakpoint
|
||||
list.
|
||||
- A step-resume breakpoint, if any, is explicitly removed from the
|
||||
breakpoint list.
|
||||
- All eventpoints without a symbolic address are removed from the
|
||||
breakpoint list. */
|
||||
extern void update_breakpoints_after_exec (void);
|
||||
|
||||
/* This function can be used to physically remove hardware breakpoints
|
||||
and watchpoints from the specified traced inferior process, without
|
||||
modifying the breakpoint package's state. This can be useful for
|
||||
those targets which support following the processes of a fork() or
|
||||
vfork() system call, when one of the resulting two processes is to
|
||||
be detached and allowed to run free.
|
||||
|
||||
It is an error to use this function on the process whose id is
|
||||
inferior_ptid. */
|
||||
extern int detach_breakpoints (int);
|
||||
|
||||
extern void enable_longjmp_breakpoint (void);
|
||||
extern void disable_longjmp_breakpoint (void);
|
||||
extern void enable_overlay_breakpoints (void);
|
||||
extern void disable_overlay_breakpoints (void);
|
||||
|
||||
extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_info *);
|
||||
/* These functions respectively disable or reenable all currently
|
||||
enabled watchpoints. When disabled, the watchpoints are marked
|
||||
call_disabled. When reenabled, they are marked enabled.
|
||||
|
||||
The intended client of these functions is infcmd.c\run_stack_dummy.
|
||||
|
||||
The inferior must be stopped, and all breakpoints removed, when
|
||||
these functions are used.
|
||||
|
||||
The need for these functions is that on some targets (e.g., HP-UX),
|
||||
gdb is unable to unwind through the dummy frame that is pushed as
|
||||
part of the implementation of a call command. Watchpoints can
|
||||
cause the inferior to stop in places where this frame is visible,
|
||||
and that can cause execution control to become very confused.
|
||||
|
||||
Note that if a user sets breakpoints in an interactively called
|
||||
function, the call_disabled watchpoints will have been reenabled
|
||||
when the first such breakpoint is reached. However, on targets
|
||||
that are unable to unwind through the call dummy frame, watches
|
||||
of stack-based storage may then be deleted, because gdb will
|
||||
believe that their watched storage is out of scope. (Sigh.) */
|
||||
extern void disable_watchpoints_before_interactive_call_start (void);
|
||||
|
||||
extern void enable_watchpoints_after_interactive_call_stop (void);
|
||||
|
||||
|
||||
extern void clear_breakpoint_hit_counts (void);
|
||||
|
||||
extern int get_number (char **);
|
||||
|
||||
extern int get_number_or_range (char **);
|
||||
|
||||
/* The following are for displays, which aren't really breakpoints, but
|
||||
here is as good a place as any for them. */
|
||||
|
||||
extern void disable_current_display (void);
|
||||
|
||||
extern void do_displays (void);
|
||||
|
||||
extern void disable_display (int);
|
||||
|
||||
extern void clear_displays (void);
|
||||
|
||||
extern void disable_breakpoint (struct breakpoint *);
|
||||
|
||||
extern void enable_breakpoint (struct breakpoint *);
|
||||
|
||||
extern void make_breakpoint_permanent (struct breakpoint *);
|
||||
|
||||
extern struct breakpoint *create_solib_event_breakpoint (CORE_ADDR);
|
||||
|
||||
extern struct breakpoint *create_thread_event_breakpoint (CORE_ADDR);
|
||||
|
||||
extern void remove_solib_event_breakpoints (void);
|
||||
|
||||
extern void remove_thread_event_breakpoints (void);
|
||||
|
||||
extern void disable_breakpoints_in_shlibs (int silent);
|
||||
|
||||
extern void re_enable_breakpoints_in_shlibs (void);
|
||||
|
||||
extern void create_solib_load_event_breakpoint (char *, int, char *, char *);
|
||||
|
||||
extern void create_solib_unload_event_breakpoint (char *, int,
|
||||
char *, char *);
|
||||
|
||||
extern void create_fork_event_catchpoint (int, char *);
|
||||
|
||||
extern void create_vfork_event_catchpoint (int, char *);
|
||||
|
||||
extern void create_exec_event_catchpoint (int, char *);
|
||||
|
||||
/* This function returns TRUE if ep is a catchpoint. */
|
||||
extern int ep_is_catchpoint (struct breakpoint *);
|
||||
|
||||
/* This function returns TRUE if ep is a catchpoint of a
|
||||
shared library (aka dynamically-linked library) event,
|
||||
such as a library load or unload. */
|
||||
extern int ep_is_shlib_catchpoint (struct breakpoint *);
|
||||
|
||||
extern struct breakpoint *set_breakpoint_sal (struct symtab_and_line);
|
||||
|
||||
/* Enable breakpoints and delete when hit. Called with ARG == NULL
|
||||
deletes all breakpoints. */
|
||||
extern void delete_command (char *arg, int from_tty);
|
||||
|
||||
/* Pull all H/W watchpoints from the target. Return non-zero if the
|
||||
remove fails. */
|
||||
extern int remove_hw_watchpoints (void);
|
||||
|
||||
#endif /* !defined (BREAKPOINT_H) */
|
||||
1168
gdb/buildsym.c
1168
gdb/buildsym.c
File diff suppressed because it is too large
Load Diff
305
gdb/buildsym.h
305
gdb/buildsym.h
@@ -1,305 +0,0 @@
|
||||
/* Build symbol tables in GDB's internal format.
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1996,
|
||||
1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (BUILDSYM_H)
|
||||
#define BUILDSYM_H 1
|
||||
|
||||
/* This module provides definitions used for creating and adding to
|
||||
the symbol table. These routines are called from various symbol-
|
||||
file-reading routines.
|
||||
|
||||
They originated in dbxread.c of gdb-4.2, and were split out to
|
||||
make xcoffread.c more maintainable by sharing code.
|
||||
|
||||
Variables declared in this file can be defined by #define-ing the
|
||||
name EXTERN to null. It is used to declare variables that are
|
||||
normally extern, but which get defined in a single module using
|
||||
this technique. */
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define HASHSIZE 127 /* Size of things hashed via
|
||||
hashname() */
|
||||
|
||||
/* Name of source file whose symbol data we are now processing. This
|
||||
comes from a symbol of type N_SO. */
|
||||
|
||||
EXTERN char *last_source_file;
|
||||
|
||||
/* Core address of start of text of current source file. This too
|
||||
comes from the N_SO symbol. */
|
||||
|
||||
EXTERN CORE_ADDR last_source_start_addr;
|
||||
|
||||
/* The list of sub-source-files within the current individual
|
||||
compilation. Each file gets its own symtab with its own linetable
|
||||
and associated info, but they all share one blockvector. */
|
||||
|
||||
struct subfile
|
||||
{
|
||||
struct subfile *next;
|
||||
char *name;
|
||||
char *dirname;
|
||||
struct linetable *line_vector;
|
||||
int line_vector_length;
|
||||
enum language language;
|
||||
char *debugformat;
|
||||
};
|
||||
|
||||
EXTERN struct subfile *subfiles;
|
||||
|
||||
EXTERN struct subfile *current_subfile;
|
||||
|
||||
/* Global variable which, when set, indicates that we are processing a
|
||||
.o file compiled with gcc */
|
||||
|
||||
EXTERN unsigned char processing_gcc_compilation;
|
||||
|
||||
/* When set, we are processing a .o file compiled by sun acc. This is
|
||||
misnamed; it refers to all stabs-in-elf implementations which use
|
||||
N_UNDF the way Sun does, including Solaris gcc. Hopefully all
|
||||
stabs-in-elf implementations ever invented will choose to be
|
||||
compatible. */
|
||||
|
||||
EXTERN unsigned char processing_acc_compilation;
|
||||
|
||||
/* elz: added this flag to know when a block is compiled with HP
|
||||
compilers (cc, aCC). This is necessary because of the macro
|
||||
COERCE_FLOAT_TO_DOUBLE defined in tm_hppa.h, which causes a
|
||||
coercion of float to double to always occur in parameter passing
|
||||
for a function called by gdb (see the function value_arg_coerce in
|
||||
valops.c). This is necessary only if the target was compiled with
|
||||
gcc, not with HP compilers or with g++ */
|
||||
|
||||
EXTERN unsigned char processing_hp_compilation;
|
||||
|
||||
/* Count symbols as they are processed, for error messages. */
|
||||
|
||||
EXTERN unsigned int symnum;
|
||||
|
||||
/* Record the symbols defined for each context in a list. We don't
|
||||
create a struct block for the context until we know how long to
|
||||
make it. */
|
||||
|
||||
#define PENDINGSIZE 100
|
||||
|
||||
struct pending
|
||||
{
|
||||
struct pending *next;
|
||||
int nsyms;
|
||||
struct symbol *symbol[PENDINGSIZE];
|
||||
};
|
||||
|
||||
/* Here are the three lists that symbols are put on. */
|
||||
|
||||
/* static at top level, and types */
|
||||
|
||||
EXTERN struct pending *file_symbols;
|
||||
|
||||
/* global functions and variables */
|
||||
|
||||
EXTERN struct pending *global_symbols;
|
||||
|
||||
/* everything local to lexical context */
|
||||
|
||||
EXTERN struct pending *local_symbols;
|
||||
|
||||
/* func params local to lexical context */
|
||||
|
||||
EXTERN struct pending *param_symbols;
|
||||
|
||||
/* Stack representing unclosed lexical contexts (that will become
|
||||
blocks, eventually). */
|
||||
|
||||
struct context_stack
|
||||
{
|
||||
/* Outer locals at the time we entered */
|
||||
|
||||
struct pending *locals;
|
||||
|
||||
/* Pending func params at the time we entered */
|
||||
|
||||
struct pending *params;
|
||||
|
||||
/* Pointer into blocklist as of entry */
|
||||
|
||||
struct pending_block *old_blocks;
|
||||
|
||||
/* Name of function, if any, defining context */
|
||||
|
||||
struct symbol *name;
|
||||
|
||||
/* PC where this context starts */
|
||||
|
||||
CORE_ADDR start_addr;
|
||||
|
||||
/* Temp slot for exception handling. */
|
||||
|
||||
CORE_ADDR end_addr;
|
||||
|
||||
/* For error-checking matching push/pop */
|
||||
|
||||
int depth;
|
||||
|
||||
};
|
||||
|
||||
EXTERN struct context_stack *context_stack;
|
||||
|
||||
/* Index of first unused entry in context stack. */
|
||||
|
||||
EXTERN int context_stack_depth;
|
||||
|
||||
/* Currently allocated size of context stack. */
|
||||
|
||||
EXTERN int context_stack_size;
|
||||
|
||||
/* Macro "function" for popping contexts from the stack. Pushing is
|
||||
done by a real function, push_context. This returns a pointer to a
|
||||
struct context_stack. */
|
||||
|
||||
#define pop_context() (&context_stack[--context_stack_depth]);
|
||||
|
||||
/* Nonzero if within a function (so symbols should be local, if
|
||||
nothing says specifically). */
|
||||
|
||||
EXTERN int within_function;
|
||||
|
||||
/* List of blocks already made (lexical contexts already closed).
|
||||
This is used at the end to make the blockvector. */
|
||||
|
||||
struct pending_block
|
||||
{
|
||||
struct pending_block *next;
|
||||
struct block *block;
|
||||
};
|
||||
|
||||
/* Pointer to the head of a linked list of symbol blocks which have
|
||||
already been finalized (lexical contexts already closed) and which
|
||||
are just waiting to be built into a blockvector when finalizing the
|
||||
associated symtab. */
|
||||
|
||||
EXTERN struct pending_block *pending_blocks;
|
||||
|
||||
|
||||
struct subfile_stack
|
||||
{
|
||||
struct subfile_stack *next;
|
||||
char *name;
|
||||
};
|
||||
|
||||
EXTERN struct subfile_stack *subfile_stack;
|
||||
|
||||
#define next_symbol_text(objfile) (*next_symbol_text_func)(objfile)
|
||||
|
||||
/* Function to invoke get the next symbol. Return the symbol name. */
|
||||
|
||||
EXTERN char *(*next_symbol_text_func) (struct objfile *);
|
||||
|
||||
/* Vector of types defined so far, indexed by their type numbers.
|
||||
Used for both stabs and coff. (In newer sun systems, dbx uses a
|
||||
pair of numbers in parens, as in "(SUBFILENUM,NUMWITHINSUBFILE)".
|
||||
Then these numbers must be translated through the type_translations
|
||||
hash table to get the index into the type vector.) */
|
||||
|
||||
EXTERN struct type **type_vector;
|
||||
|
||||
/* Number of elements allocated for type_vector currently. */
|
||||
|
||||
EXTERN int type_vector_length;
|
||||
|
||||
/* Initial size of type vector. Is realloc'd larger if needed, and
|
||||
realloc'd down to the size actually used, when completed. */
|
||||
|
||||
#define INITIAL_TYPE_VECTOR_LENGTH 160
|
||||
|
||||
extern void add_free_pendings (struct pending *list);
|
||||
|
||||
extern void add_symbol_to_list (struct symbol *symbol,
|
||||
struct pending **listhead);
|
||||
|
||||
extern struct symbol *find_symbol_in_list (struct pending *list,
|
||||
char *name, int length);
|
||||
|
||||
extern void finish_block (struct symbol *symbol,
|
||||
struct pending **listhead,
|
||||
struct pending_block *old_blocks,
|
||||
CORE_ADDR start, CORE_ADDR end,
|
||||
struct objfile *objfile);
|
||||
|
||||
extern void really_free_pendings (PTR dummy);
|
||||
|
||||
extern void start_subfile (char *name, char *dirname);
|
||||
|
||||
extern void patch_subfile_names (struct subfile *subfile, char *name);
|
||||
|
||||
extern void push_subfile (void);
|
||||
|
||||
extern char *pop_subfile (void);
|
||||
|
||||
extern struct symtab *end_symtab (CORE_ADDR end_addr,
|
||||
struct objfile *objfile, int section);
|
||||
|
||||
/* Defined in stabsread.c. */
|
||||
|
||||
extern void scan_file_globals (struct objfile *objfile);
|
||||
|
||||
extern void buildsym_new_init (void);
|
||||
|
||||
extern void buildsym_init (void);
|
||||
|
||||
extern struct context_stack *push_context (int desc, CORE_ADDR valu);
|
||||
|
||||
extern void record_line (struct subfile *subfile, int line, CORE_ADDR pc);
|
||||
|
||||
extern void start_symtab (char *name, char *dirname, CORE_ADDR start_addr);
|
||||
|
||||
extern int hashname (char *name);
|
||||
|
||||
extern void free_pending_blocks (void);
|
||||
|
||||
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
|
||||
which should be fixed to not need direct access to
|
||||
make_blockvector. */
|
||||
|
||||
extern struct blockvector *make_blockvector (struct objfile *objfile);
|
||||
|
||||
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
|
||||
which should be fixed to not need direct access to
|
||||
record_pending_block. */
|
||||
|
||||
extern void record_pending_block (struct objfile *objfile,
|
||||
struct block *block,
|
||||
struct pending_block *opblock);
|
||||
|
||||
extern void record_debugformat (char *format);
|
||||
|
||||
extern void merge_symbol_lists (struct pending **srclist,
|
||||
struct pending **targetlist);
|
||||
|
||||
/* The macro table for the compilation unit whose symbols we're
|
||||
currently reading. All the symtabs for this CU will point to this. */
|
||||
EXTERN struct macro_table *pending_macros;
|
||||
|
||||
#undef EXTERN
|
||||
|
||||
#endif /* defined (BUILDSYM_H) */
|
||||
@@ -1,77 +0,0 @@
|
||||
/* Builtin registers, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Red Hat.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "builtin-regs.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "gdb_string.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
/* Implement builtin register types. Builtin registers have regnum's
|
||||
that live above of the range [0 .. NUM_REGS + NUM_PSEUDO_REGS)
|
||||
(which is controlled by the target). The target should never see a
|
||||
builtin register's regnum value. */
|
||||
|
||||
/* An array of builtin registers. Always append, never delete. By
|
||||
doing this, the relative regnum (offset from NUM_REGS +
|
||||
NUM_PSEUDO_REGS) assigned to each builtin register never changes. */
|
||||
|
||||
struct builtin_reg
|
||||
{
|
||||
const char *name;
|
||||
struct value *(*value) (struct frame_info * frame);
|
||||
};
|
||||
|
||||
static struct builtin_reg *builtin_regs;
|
||||
int nr_builtin_regs;
|
||||
|
||||
void
|
||||
add_builtin_reg (const char *name, struct value *(*value) (struct frame_info * frame))
|
||||
{
|
||||
nr_builtin_regs++;
|
||||
builtin_regs = xrealloc (builtin_regs,
|
||||
nr_builtin_regs * sizeof (builtin_regs[0]));
|
||||
builtin_regs[nr_builtin_regs - 1].name = name;
|
||||
builtin_regs[nr_builtin_regs - 1].value = value;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_reg_map_name_to_regnum (const char *name, int len)
|
||||
{
|
||||
int reg;
|
||||
for (reg = 0; reg < nr_builtin_regs; reg++)
|
||||
{
|
||||
if (len == strlen (builtin_regs[reg].name)
|
||||
&& strncmp (builtin_regs[reg].name, name, len) == 0)
|
||||
return NUM_REGS + NUM_PSEUDO_REGS + reg;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct value *
|
||||
value_of_builtin_reg (int regnum, struct frame_info *frame)
|
||||
{
|
||||
int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
|
||||
gdb_assert (reg >= 0 && reg < nr_builtin_regs);
|
||||
return builtin_regs[reg].value (frame);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Builtin registers, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Red Hat.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef BUILTIN_REGS_H
|
||||
#define BUILTIN_REGS_H
|
||||
|
||||
extern int builtin_reg_map_name_to_regnum (const char *str, int len);
|
||||
|
||||
extern struct value *value_of_builtin_reg (int regnum,
|
||||
struct frame_info *frame);
|
||||
|
||||
extern void add_builtin_reg (const char *name,
|
||||
struct value *(value) (struct frame_info * frame));
|
||||
|
||||
#endif
|
||||
1803
gdb/c-exp.y
1803
gdb/c-exp.y
File diff suppressed because it is too large
Load Diff
673
gdb/c-lang.c
673
gdb/c-lang.c
@@ -1,673 +0,0 @@
|
||||
/* C language support routines for GDB, the GNU debugger.
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "c-lang.h"
|
||||
#include "valprint.h"
|
||||
#include "macroscope.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
extern void _initialize_c_language (void);
|
||||
static void c_emit_char (int c, struct ui_file * stream, int quoter);
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string whose delimiter is QUOTER. Note that that format for printing
|
||||
characters and strings is language specific. */
|
||||
|
||||
static void
|
||||
c_emit_char (register int c, struct ui_file *stream, int quoter)
|
||||
{
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
if (PRINT_LITERAL_FORM (c))
|
||||
{
|
||||
if (c == '\\' || c == quoter)
|
||||
{
|
||||
fputs_filtered ("\\", stream);
|
||||
}
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
fputs_filtered ("\\n", stream);
|
||||
break;
|
||||
case '\b':
|
||||
fputs_filtered ("\\b", stream);
|
||||
break;
|
||||
case '\t':
|
||||
fputs_filtered ("\\t", stream);
|
||||
break;
|
||||
case '\f':
|
||||
fputs_filtered ("\\f", stream);
|
||||
break;
|
||||
case '\r':
|
||||
fputs_filtered ("\\r", stream);
|
||||
break;
|
||||
case '\013':
|
||||
fputs_filtered ("\\v", stream);
|
||||
break;
|
||||
case '\033':
|
||||
fputs_filtered ("\\e", stream);
|
||||
break;
|
||||
case '\007':
|
||||
fputs_filtered ("\\a", stream);
|
||||
break;
|
||||
case '\0':
|
||||
fputs_filtered ("\\0", stream);
|
||||
break;
|
||||
default:
|
||||
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
c_printchar (int c, struct ui_file *stream)
|
||||
{
|
||||
fputc_filtered ('\'', stream);
|
||||
LA_EMIT_CHAR (c, stream, '\'');
|
||||
fputc_filtered ('\'', stream);
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH characters.
|
||||
LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes
|
||||
long. Printing stops early if the number hits print_max; repeat counts are
|
||||
printed as appropriate. Print ellipses at the end if we had to stop before
|
||||
printing LENGTH characters, or if FORCE_ELLIPSES. */
|
||||
|
||||
void
|
||||
c_printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int width, int force_ellipses)
|
||||
{
|
||||
register unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
extern int inspect_it;
|
||||
|
||||
/* If the string was not truncated due to `set print elements', and
|
||||
the last byte of it is a null, we don't print that, in traditional C
|
||||
style. */
|
||||
if (!force_ellipses
|
||||
&& length > 0
|
||||
&& (extract_unsigned_integer (string + (length - 1) * width, width)
|
||||
== '\0'))
|
||||
length--;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length && things_printed < print_max; ++i)
|
||||
{
|
||||
/* Position of the character we are examining
|
||||
to see whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
unsigned long current_char;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
current_char = extract_unsigned_integer (string + i * width, width);
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length
|
||||
&& extract_unsigned_integer (string + rep1 * width, width)
|
||||
== current_char)
|
||||
{
|
||||
++rep1;
|
||||
++reps;
|
||||
}
|
||||
|
||||
if (reps > repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\", ", stream);
|
||||
else
|
||||
fputs_filtered ("\", ", stream);
|
||||
in_quotes = 0;
|
||||
}
|
||||
LA_PRINT_CHAR (current_char, stream);
|
||||
fprintf_filtered (stream, " <repeats %u times>", reps);
|
||||
i = rep1 - 1;
|
||||
things_printed += repeat_count_threshold;
|
||||
need_comma = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\"", stream);
|
||||
else
|
||||
fputs_filtered ("\"", stream);
|
||||
in_quotes = 1;
|
||||
}
|
||||
LA_EMIT_CHAR (current_char, stream, '"');
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\"", stream);
|
||||
else
|
||||
fputs_filtered ("\"", stream);
|
||||
}
|
||||
|
||||
if (force_ellipses || i < length)
|
||||
fputs_filtered ("...", stream);
|
||||
}
|
||||
|
||||
/* Create a fundamental C type using default reasonable for the current
|
||||
target machine.
|
||||
|
||||
Some object/debugging file formats (DWARF version 1, COFF, etc) do not
|
||||
define fundamental types such as "int" or "double". Others (stabs or
|
||||
DWARF version 2, etc) do define fundamental types. For the formats which
|
||||
don't provide fundamental types, gdb can create such types using this
|
||||
function.
|
||||
|
||||
FIXME: Some compilers distinguish explicitly signed integral types
|
||||
(signed short, signed int, signed long) from "regular" integral types
|
||||
(short, int, long) in the debugging information. There is some dis-
|
||||
agreement as to how useful this feature is. In particular, gcc does
|
||||
not support this. Also, only some debugging formats allow the
|
||||
distinction to be passed on to a debugger. For now, we always just
|
||||
use "short", "int", or "long" as the type name, for both the implicit
|
||||
and explicitly signed types. This also makes life easier for the
|
||||
gdb test suite since we don't have to account for the differences
|
||||
in output depending upon what the compiler and debugging format
|
||||
support. We will probably have to re-examine the issue when gdb
|
||||
starts taking it's fundamental type information directly from the
|
||||
debugging information supplied by the compiler. fnf@cygnus.com */
|
||||
|
||||
struct type *
|
||||
c_create_fundamental_type (struct objfile *objfile, int typeid)
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
|
||||
switch (typeid)
|
||||
{
|
||||
default:
|
||||
/* FIXME: For now, if we are asked to produce a type not in this
|
||||
language, create the equivalent of a C integer type with the
|
||||
name "<?type?>". When all the dust settles from the type
|
||||
reconstruction work, this should probably become an error. */
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "<?type?>", objfile);
|
||||
warning ("internal error: no C/C++ fundamental type %d", typeid);
|
||||
break;
|
||||
case FT_VOID:
|
||||
type = init_type (TYPE_CODE_VOID,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "void", objfile);
|
||||
break;
|
||||
case FT_BOOLEAN:
|
||||
type = init_type (TYPE_CODE_BOOL,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "bool", objfile);
|
||||
break;
|
||||
case FT_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_NOSIGN, "char", objfile);
|
||||
break;
|
||||
case FT_SIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "signed char", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
|
||||
break;
|
||||
case FT_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "short", objfile);
|
||||
break;
|
||||
case FT_SIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "short", objfile); /* FIXME-fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
|
||||
break;
|
||||
case FT_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "int", objfile);
|
||||
break;
|
||||
case FT_SIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "int", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
|
||||
break;
|
||||
case FT_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
|
||||
break;
|
||||
case FT_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "signed long long", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "float", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "double", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "long double", objfile);
|
||||
break;
|
||||
case FT_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex float", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "float", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex double", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "double", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex long double", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "long double", objfile);
|
||||
break;
|
||||
case FT_TEMPLATE_ARG:
|
||||
type = init_type (TYPE_CODE_TEMPLATE_ARG,
|
||||
0,
|
||||
0, "<template arg>", objfile);
|
||||
break;
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
||||
/* Preprocessing and parsing C and C++ expressions. */
|
||||
|
||||
|
||||
/* When we find that lexptr (the global var defined in parse.c) is
|
||||
pointing at a macro invocation, we expand the invocation, and call
|
||||
scan_macro_expansion to save the old lexptr here and point lexptr
|
||||
into the expanded text. When we reach the end of that, we call
|
||||
end_macro_expansion to pop back to the value we saved here. The
|
||||
macro expansion code promises to return only fully-expanded text,
|
||||
so we don't need to "push" more than one level.
|
||||
|
||||
This is disgusting, of course. It would be cleaner to do all macro
|
||||
expansion beforehand, and then hand that to lexptr. But we don't
|
||||
really know where the expression ends. Remember, in a command like
|
||||
|
||||
(gdb) break *ADDRESS if CONDITION
|
||||
|
||||
we evaluate ADDRESS in the scope of the current frame, but we
|
||||
evaluate CONDITION in the scope of the breakpoint's location. So
|
||||
it's simply wrong to try to macro-expand the whole thing at once. */
|
||||
static char *macro_original_text;
|
||||
static char *macro_expanded_text;
|
||||
|
||||
|
||||
void
|
||||
scan_macro_expansion (char *expansion)
|
||||
{
|
||||
/* We'd better not be trying to push the stack twice. */
|
||||
gdb_assert (! macro_original_text);
|
||||
gdb_assert (! macro_expanded_text);
|
||||
|
||||
/* Save the old lexptr value, so we can return to it when we're done
|
||||
parsing the expanded text. */
|
||||
macro_original_text = lexptr;
|
||||
lexptr = expansion;
|
||||
|
||||
/* Save the expanded text, so we can free it when we're finished. */
|
||||
macro_expanded_text = expansion;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
scanning_macro_expansion (void)
|
||||
{
|
||||
return macro_original_text != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
finished_macro_expansion (void)
|
||||
{
|
||||
/* There'd better be something to pop back to, and we better have
|
||||
saved a pointer to the start of the expanded text. */
|
||||
gdb_assert (macro_original_text);
|
||||
gdb_assert (macro_expanded_text);
|
||||
|
||||
/* Pop back to the original text. */
|
||||
lexptr = macro_original_text;
|
||||
macro_original_text = 0;
|
||||
|
||||
/* Free the expanded text. */
|
||||
xfree (macro_expanded_text);
|
||||
macro_expanded_text = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scan_macro_cleanup (void *dummy)
|
||||
{
|
||||
if (macro_original_text)
|
||||
finished_macro_expansion ();
|
||||
}
|
||||
|
||||
|
||||
/* We set these global variables before calling c_parse, to tell it
|
||||
how it to find macro definitions for the expression at hand. */
|
||||
macro_lookup_ftype *expression_macro_lookup_func;
|
||||
void *expression_macro_lookup_baton;
|
||||
|
||||
|
||||
static struct macro_definition *
|
||||
null_macro_lookup (const char *name, void *baton)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
c_preprocess_and_parse (void)
|
||||
{
|
||||
/* Set up a lookup function for the macro expander. */
|
||||
struct macro_scope *scope = 0;
|
||||
struct cleanup *back_to = make_cleanup (free_current_contents, &scope);
|
||||
|
||||
if (expression_context_block)
|
||||
scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
|
||||
else
|
||||
scope = default_macro_scope ();
|
||||
|
||||
if (scope)
|
||||
{
|
||||
expression_macro_lookup_func = standard_macro_lookup;
|
||||
expression_macro_lookup_baton = (void *) scope;
|
||||
}
|
||||
else
|
||||
{
|
||||
expression_macro_lookup_func = null_macro_lookup;
|
||||
expression_macro_lookup_baton = 0;
|
||||
}
|
||||
|
||||
gdb_assert (! macro_original_text);
|
||||
make_cleanup (scan_macro_cleanup, 0);
|
||||
|
||||
{
|
||||
int result = c_parse ();
|
||||
do_cleanups (back_to);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
const struct op_print c_op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{">>", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"<<", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"%", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
|
||||
{"*", UNOP_IND, PREC_PREFIX, 0},
|
||||
{"&", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
|
||||
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
struct type **const (c_builtin_types[]) =
|
||||
{
|
||||
&builtin_type_int,
|
||||
&builtin_type_long,
|
||||
&builtin_type_short,
|
||||
&builtin_type_char,
|
||||
&builtin_type_float,
|
||||
&builtin_type_double,
|
||||
&builtin_type_void,
|
||||
&builtin_type_long_long,
|
||||
&builtin_type_signed_char,
|
||||
&builtin_type_unsigned_char,
|
||||
&builtin_type_unsigned_short,
|
||||
&builtin_type_unsigned_int,
|
||||
&builtin_type_unsigned_long,
|
||||
&builtin_type_unsigned_long_long,
|
||||
&builtin_type_long_double,
|
||||
&builtin_type_complex,
|
||||
&builtin_type_double_complex,
|
||||
0
|
||||
};
|
||||
|
||||
const struct language_defn c_language_defn =
|
||||
{
|
||||
"c", /* Language name */
|
||||
language_c,
|
||||
c_builtin_types,
|
||||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
c_create_fundamental_type, /* Create fundamental type in this language */
|
||||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
{"0x%lx", "0x", "x", ""}, /* Hex format info */
|
||||
c_op_print_tab, /* expression operators for printing */
|
||||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
struct type **const (cplus_builtin_types[]) =
|
||||
{
|
||||
&builtin_type_int,
|
||||
&builtin_type_long,
|
||||
&builtin_type_short,
|
||||
&builtin_type_char,
|
||||
&builtin_type_float,
|
||||
&builtin_type_double,
|
||||
&builtin_type_void,
|
||||
&builtin_type_long_long,
|
||||
&builtin_type_signed_char,
|
||||
&builtin_type_unsigned_char,
|
||||
&builtin_type_unsigned_short,
|
||||
&builtin_type_unsigned_int,
|
||||
&builtin_type_unsigned_long,
|
||||
&builtin_type_unsigned_long_long,
|
||||
&builtin_type_long_double,
|
||||
&builtin_type_complex,
|
||||
&builtin_type_double_complex,
|
||||
&builtin_type_bool,
|
||||
0
|
||||
};
|
||||
|
||||
const struct language_defn cplus_language_defn =
|
||||
{
|
||||
"c++", /* Language name */
|
||||
language_cplus,
|
||||
cplus_builtin_types,
|
||||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
c_create_fundamental_type, /* Create fundamental type in this language */
|
||||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
{"0x%lx", "0x", "x", ""}, /* Hex format info */
|
||||
c_op_print_tab, /* expression operators for printing */
|
||||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
const struct language_defn asm_language_defn =
|
||||
{
|
||||
"asm", /* Language name */
|
||||
language_asm,
|
||||
c_builtin_types,
|
||||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
c_create_fundamental_type, /* Create fundamental type in this language */
|
||||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
{"0x%lx", "0x", "x", ""}, /* Hex format info */
|
||||
c_op_print_tab, /* expression operators for printing */
|
||||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_c_language (void)
|
||||
{
|
||||
add_language (&c_language_defn);
|
||||
add_language (&cplus_language_defn);
|
||||
add_language (&asm_language_defn);
|
||||
}
|
||||
92
gdb/c-lang.h
92
gdb/c-lang.h
@@ -1,92 +0,0 @@
|
||||
/* C language support definitions for GDB, the GNU debugger.
|
||||
Copyright 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#if !defined (C_LANG_H)
|
||||
#define C_LANG_H 1
|
||||
|
||||
#include "value.h"
|
||||
#include "macroexp.h"
|
||||
|
||||
|
||||
extern int c_parse (void); /* Defined in c-exp.y */
|
||||
|
||||
extern void c_error (char *); /* Defined in c-exp.y */
|
||||
|
||||
/* Defined in c-typeprint.c */
|
||||
extern void c_print_type (struct type *, char *, struct ui_file *, int,
|
||||
int);
|
||||
|
||||
extern int c_val_print (struct type *, char *, int, CORE_ADDR,
|
||||
struct ui_file *, int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
extern int c_value_print (struct value *, struct ui_file *, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
/* These are in c-lang.c: */
|
||||
|
||||
extern void c_printchar (int, struct ui_file *);
|
||||
|
||||
extern void c_printstr (struct ui_file * stream, char *string,
|
||||
unsigned int length, int width,
|
||||
int force_ellipses);
|
||||
|
||||
extern void scan_macro_expansion (char *expansion);
|
||||
extern int scanning_macro_expansion (void);
|
||||
extern void finished_macro_expansion (void);
|
||||
|
||||
extern macro_lookup_ftype *expression_macro_lookup_func;
|
||||
extern void *expression_macro_lookup_baton;
|
||||
|
||||
extern struct type *c_create_fundamental_type (struct objfile *, int);
|
||||
|
||||
extern struct type **const (c_builtin_types[]);
|
||||
|
||||
/* These are in c-typeprint.c: */
|
||||
|
||||
extern void c_type_print_base (struct type *, struct ui_file *, int, int);
|
||||
|
||||
extern void c_type_print_varspec_prefix (struct type *, struct ui_file *,
|
||||
int, int);
|
||||
|
||||
/* These are in cp-valprint.c */
|
||||
|
||||
extern int vtblprint; /* Controls printing of vtbl's */
|
||||
|
||||
extern int static_field_print;
|
||||
|
||||
extern void cp_print_class_member (char *, struct type *, struct ui_file *,
|
||||
char *);
|
||||
|
||||
extern void cp_print_class_method (char *, struct type *, struct ui_file *);
|
||||
|
||||
extern void cp_print_value_fields (struct type *, struct type *, char *,
|
||||
int, CORE_ADDR, struct ui_file *, int,
|
||||
int, enum val_prettyprint,
|
||||
struct type **, int);
|
||||
|
||||
extern int cp_is_vtbl_ptr_type (struct type *);
|
||||
|
||||
extern int cp_is_vtbl_member (struct type *);
|
||||
|
||||
|
||||
#endif /* !defined (C_LANG_H) */
|
||||
1187
gdb/c-typeprint.c
1187
gdb/c-typeprint.c
File diff suppressed because it is too large
Load Diff
598
gdb/c-valprint.c
598
gdb/c-valprint.c
@@ -1,598 +0,0 @@
|
||||
/* Support for printing C values for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "valprint.h"
|
||||
#include "language.h"
|
||||
#include "c-lang.h"
|
||||
#include "cp-abi.h"
|
||||
|
||||
|
||||
/* Print function pointer with inferior address ADDRESS onto stdio
|
||||
stream STREAM. */
|
||||
|
||||
static void
|
||||
print_function_pointer_address (CORE_ADDR address, struct ui_file *stream)
|
||||
{
|
||||
CORE_ADDR func_addr = CONVERT_FROM_FUNC_PTR_ADDR (address);
|
||||
|
||||
/* If the function pointer is represented by a description, print the
|
||||
address of the description. */
|
||||
if (addressprint && func_addr != address)
|
||||
{
|
||||
fputs_filtered ("@", stream);
|
||||
print_address_numeric (address, 1, stream);
|
||||
fputs_filtered (": ", stream);
|
||||
}
|
||||
print_address_demangle (func_addr, stream, demangle);
|
||||
}
|
||||
|
||||
|
||||
/* Print data of type TYPE located at VALADDR (within GDB), which came from
|
||||
the inferior at address ADDRESS, onto stdio stream STREAM according to
|
||||
FORMAT (a letter or 0 for natural format). The data at VALADDR is in
|
||||
target byte order.
|
||||
|
||||
If the data are a string pointer, returns the number of string characters
|
||||
printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references, otherwise just print
|
||||
them like pointers.
|
||||
|
||||
The PRETTY parameter controls prettyprinting. */
|
||||
|
||||
int
|
||||
c_val_print (struct type *type, char *valaddr, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
register unsigned int i = 0; /* Number of characters printed */
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
unsigned eltlen;
|
||||
LONGEST val;
|
||||
CORE_ADDR addr;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
|
||||
{
|
||||
eltlen = TYPE_LENGTH (elttype);
|
||||
len = TYPE_LENGTH (type) / eltlen;
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
/* For an array of chars, print with string syntax. */
|
||||
if (eltlen == 1 &&
|
||||
((TYPE_CODE (elttype) == TYPE_CODE_INT)
|
||||
|| ((current_language->la_language == language_m2)
|
||||
&& (TYPE_CODE (elttype) == TYPE_CODE_CHAR)))
|
||||
&& (format == 0 || format == 's'))
|
||||
{
|
||||
/* If requested, look for the first null char and only print
|
||||
elements up to it. */
|
||||
if (stop_print_at_null)
|
||||
{
|
||||
unsigned int temp_len;
|
||||
|
||||
/* Look for a NULL char. */
|
||||
for (temp_len = 0;
|
||||
(valaddr + embedded_offset)[temp_len]
|
||||
&& temp_len < len && temp_len < print_max;
|
||||
temp_len++);
|
||||
len = temp_len;
|
||||
}
|
||||
|
||||
LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0);
|
||||
i = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "{");
|
||||
/* If this is a virtual function table, print the 0th
|
||||
entry specially, and the rest of the members normally. */
|
||||
if (cp_is_vtbl_ptr_type (elttype))
|
||||
{
|
||||
i = 1;
|
||||
fprintf_filtered (stream, "%d vtable entries", len - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
val_print_array_elements (type, valaddr + embedded_offset, address, stream,
|
||||
format, deref_ref, recurse, pretty, i);
|
||||
fprintf_filtered (stream, "}");
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Array of unspecified length: treat like pointer to first elt. */
|
||||
addr = address;
|
||||
goto print_unpacked_pointer;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
if (format && format != 's')
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
if (vtblprint && cp_is_vtbl_ptr_type (type))
|
||||
{
|
||||
/* Print the unmangled name if desired. */
|
||||
/* Print vtable entry - we only get here if we ARE using
|
||||
-fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */
|
||||
CORE_ADDR addr
|
||||
= extract_typed_address (valaddr + embedded_offset, type);
|
||||
print_function_pointer_address (addr, stream);
|
||||
break;
|
||||
}
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
|
||||
{
|
||||
cp_print_class_method (valaddr + embedded_offset, type, stream);
|
||||
}
|
||||
else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
|
||||
{
|
||||
cp_print_class_member (valaddr + embedded_offset,
|
||||
TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
|
||||
stream, "&");
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = unpack_pointer (type, valaddr + embedded_offset);
|
||||
print_unpacked_pointer:
|
||||
|
||||
if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
|
||||
{
|
||||
/* Try to print what function it points to. */
|
||||
print_function_pointer_address (addr, stream);
|
||||
/* Return value is irrelevant except for string pointers. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (addressprint && format != 's')
|
||||
{
|
||||
print_address_numeric (addr, 1, stream);
|
||||
}
|
||||
|
||||
/* For a pointer to char or unsigned char, also print the string
|
||||
pointed to, unless pointer is null. */
|
||||
/* FIXME: need to handle wchar_t here... */
|
||||
|
||||
if (TYPE_LENGTH (elttype) == 1
|
||||
&& TYPE_CODE (elttype) == TYPE_CODE_INT
|
||||
&& (format == 0 || format == 's')
|
||||
&& addr != 0)
|
||||
{
|
||||
i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
|
||||
}
|
||||
else if (cp_is_vtbl_member (type))
|
||||
{
|
||||
/* print vtbl's nicely */
|
||||
CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset);
|
||||
|
||||
struct minimal_symbol *msymbol =
|
||||
lookup_minimal_symbol_by_pc (vt_address);
|
||||
if ((msymbol != NULL) &&
|
||||
(vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
|
||||
{
|
||||
fputs_filtered (" <", stream);
|
||||
fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream);
|
||||
fputs_filtered (">", stream);
|
||||
}
|
||||
if (vt_address && vtblprint)
|
||||
{
|
||||
struct value *vt_val;
|
||||
struct symbol *wsym = (struct symbol *) NULL;
|
||||
struct type *wtype;
|
||||
struct symtab *s;
|
||||
struct block *block = (struct block *) NULL;
|
||||
int is_this_fld;
|
||||
|
||||
if (msymbol != NULL)
|
||||
wsym = lookup_symbol (SYMBOL_NAME (msymbol), block,
|
||||
VAR_NAMESPACE, &is_this_fld, &s);
|
||||
|
||||
if (wsym)
|
||||
{
|
||||
wtype = SYMBOL_TYPE (wsym);
|
||||
}
|
||||
else
|
||||
{
|
||||
wtype = TYPE_TARGET_TYPE (type);
|
||||
}
|
||||
vt_val = value_at (wtype, vt_address, NULL);
|
||||
val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), 0,
|
||||
VALUE_ADDRESS (vt_val), stream, format,
|
||||
deref_ref, recurse + 1, pretty);
|
||||
if (pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return number of characters printed, including the terminating
|
||||
'\0' if we reached the end. val_print_string takes care including
|
||||
the terminating '\0' if necessary. */
|
||||
return i;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
error ("not implemented: member type in c_val_print");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
|
||||
{
|
||||
cp_print_class_member (valaddr + embedded_offset,
|
||||
TYPE_DOMAIN_TYPE (elttype),
|
||||
stream, "");
|
||||
break;
|
||||
}
|
||||
if (addressprint)
|
||||
{
|
||||
CORE_ADDR addr
|
||||
= extract_typed_address (valaddr + embedded_offset, type);
|
||||
fprintf_filtered (stream, "@");
|
||||
print_address_numeric (addr, 1, stream);
|
||||
if (deref_ref)
|
||||
fputs_filtered (": ", stream);
|
||||
}
|
||||
/* De-reference the reference. */
|
||||
if (deref_ref)
|
||||
{
|
||||
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
struct value *deref_val =
|
||||
value_at
|
||||
(TYPE_TARGET_TYPE (type),
|
||||
unpack_pointer (lookup_pointer_type (builtin_type_void),
|
||||
valaddr + embedded_offset),
|
||||
NULL);
|
||||
val_print (VALUE_TYPE (deref_val),
|
||||
VALUE_CONTENTS (deref_val),
|
||||
0,
|
||||
VALUE_ADDRESS (deref_val),
|
||||
stream,
|
||||
format,
|
||||
deref_ref,
|
||||
recurse,
|
||||
pretty);
|
||||
}
|
||||
else
|
||||
fputs_filtered ("???", stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNION:
|
||||
if (recurse && !unionprint)
|
||||
{
|
||||
fprintf_filtered (stream, "{...}");
|
||||
break;
|
||||
}
|
||||
/* Fall through. */
|
||||
case TYPE_CODE_STRUCT:
|
||||
/*FIXME: Abstract this away */
|
||||
if (vtblprint && cp_is_vtbl_ptr_type (type))
|
||||
{
|
||||
/* Print the unmangled name if desired. */
|
||||
/* Print vtable entry - we only get here if NOT using
|
||||
-fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */
|
||||
int offset = (embedded_offset +
|
||||
TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8);
|
||||
struct type *field_type = TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET);
|
||||
CORE_ADDR addr
|
||||
= extract_typed_address (valaddr + offset, field_type);
|
||||
|
||||
print_function_pointer_address (addr, stream);
|
||||
}
|
||||
else
|
||||
cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, format,
|
||||
recurse, pretty, NULL, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (type, valaddr + embedded_offset);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (val == TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
/* FIXME, we should consider, at least for ANSI C language, eliminating
|
||||
the distinction made between FUNCs and POINTERs to FUNCs. */
|
||||
fprintf_filtered (stream, "{");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, "} ");
|
||||
/* Try to print what function it points to, and its address. */
|
||||
print_address_demangle (address, stream, demangle);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
else
|
||||
{
|
||||
val = unpack_long (type, valaddr + embedded_offset);
|
||||
if (val == 0)
|
||||
fputs_filtered ("false", stream);
|
||||
else if (val == 1)
|
||||
fputs_filtered ("true", stream);
|
||||
else
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
/* FIXME: create_range_type does not set the unsigned bit in a
|
||||
range type (I think it probably should copy it from the target
|
||||
type), so we won't print values which are too large to
|
||||
fit in a signed integer correctly. */
|
||||
/* FIXME: Doesn't handle ranges of enums correctly. (Can't just
|
||||
print with the target type, though, because the size of our type
|
||||
and the target type might differ). */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
val_print_type_code_int (type, valaddr + embedded_offset, stream);
|
||||
/* C and C++ has no single byte int type, char is used instead.
|
||||
Since we don't know whether the value is really intended to
|
||||
be used as an integer or a character, print the character
|
||||
equivalent as well. */
|
||||
if (TYPE_LENGTH (type) == 1)
|
||||
{
|
||||
fputs_filtered (" ", stream);
|
||||
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset),
|
||||
stream);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = unpack_long (type, valaddr + embedded_offset);
|
||||
if (TYPE_UNSIGNED (type))
|
||||
fprintf_filtered (stream, "%u", (unsigned int) val);
|
||||
else
|
||||
fprintf_filtered (stream, "%d", (int) val);
|
||||
fputs_filtered (" ", stream);
|
||||
LA_PRINT_CHAR ((unsigned char) val, stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_floating (valaddr + embedded_offset, type, stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_METHOD:
|
||||
{
|
||||
struct value *v = value_at (type, address, NULL);
|
||||
cp_print_class_method (VALUE_CONTENTS (value_addr (v)),
|
||||
lookup_pointer_type (type), stream);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf_filtered (stream, "void");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ERROR:
|
||||
fprintf_filtered (stream, "<error type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
/* This happens (without TYPE_FLAG_STUB set) on systems which don't use
|
||||
dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
|
||||
and no complete type for struct foo in that file. */
|
||||
fprintf_filtered (stream, "<incomplete type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_COMPLEX:
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr + embedded_offset,
|
||||
TYPE_TARGET_TYPE (type),
|
||||
format, 0, stream);
|
||||
else
|
||||
print_floating (valaddr + embedded_offset, TYPE_TARGET_TYPE (type),
|
||||
stream);
|
||||
fprintf_filtered (stream, " + ");
|
||||
if (format)
|
||||
print_scalar_formatted (valaddr + embedded_offset
|
||||
+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)),
|
||||
TYPE_TARGET_TYPE (type),
|
||||
format, 0, stream);
|
||||
else
|
||||
print_floating (valaddr + embedded_offset
|
||||
+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)),
|
||||
TYPE_TARGET_TYPE (type),
|
||||
stream);
|
||||
fprintf_filtered (stream, " * I");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type));
|
||||
}
|
||||
gdb_flush (stream);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
c_value_print (struct value *val, struct ui_file *stream, int format,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
struct type *type = VALUE_TYPE (val);
|
||||
struct type *real_type;
|
||||
int full, top, using_enc;
|
||||
|
||||
/* If it is a pointer, indicate what it points to.
|
||||
|
||||
Print type also if it is a reference.
|
||||
|
||||
C++: if it is a member pointer, we will take care
|
||||
of that when we print it. */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR ||
|
||||
TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
{
|
||||
/* Hack: remove (char *) for char strings. Their
|
||||
type is indicated by the quoted string anyway. */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR &&
|
||||
TYPE_NAME (type) == NULL &&
|
||||
TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
|
||||
STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char"))
|
||||
{
|
||||
/* Print nothing */
|
||||
}
|
||||
else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
|
||||
{
|
||||
|
||||
if (TYPE_CODE(type) == TYPE_CODE_REF)
|
||||
{
|
||||
/* Copy value, change to pointer, so we don't get an
|
||||
* error about a non-pointer type in value_rtti_target_type
|
||||
*/
|
||||
struct value *temparg;
|
||||
temparg=value_copy(val);
|
||||
VALUE_TYPE (temparg) = lookup_pointer_type(TYPE_TARGET_TYPE(type));
|
||||
val=temparg;
|
||||
}
|
||||
/* Pointer to class, check real type of object */
|
||||
fprintf_filtered (stream, "(");
|
||||
real_type = value_rtti_target_type (val, &full, &top, &using_enc);
|
||||
if (real_type)
|
||||
{
|
||||
/* RTTI entry found */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||||
{
|
||||
/* create a pointer type pointing to the real type */
|
||||
type = lookup_pointer_type (real_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create a reference type referencing the real type */
|
||||
type = lookup_reference_type (real_type);
|
||||
}
|
||||
/* JYG: Need to adjust pointer value. */
|
||||
val->aligner.contents[0] -= top;
|
||||
|
||||
/* Note: When we look up RTTI entries, we don't get any
|
||||
information on const or volatile attributes */
|
||||
}
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal case */
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
}
|
||||
if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
|
||||
{
|
||||
/* Attempt to determine real type of object */
|
||||
real_type = value_rtti_type (val, &full, &top, &using_enc);
|
||||
if (real_type)
|
||||
{
|
||||
/* We have RTTI information, so use it */
|
||||
val = value_full_object (val, real_type, full, top, using_enc);
|
||||
fprintf_filtered (stream, "(%s%s) ",
|
||||
TYPE_NAME (real_type),
|
||||
full ? "" : " [incomplete object]");
|
||||
/* Print out object: enclosing type is same as real_type if full */
|
||||
return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
|
||||
VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
|
||||
/* Note: When we look up RTTI entries, we don't get any information on
|
||||
const or volatile attributes */
|
||||
}
|
||||
else if (type != VALUE_ENCLOSING_TYPE (val))
|
||||
{
|
||||
/* No RTTI information, so let's do our best */
|
||||
fprintf_filtered (stream, "(%s ?) ",
|
||||
TYPE_NAME (VALUE_ENCLOSING_TYPE (val)));
|
||||
return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
|
||||
VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
|
||||
}
|
||||
/* Otherwise, we end up at the return outside this "if" */
|
||||
}
|
||||
|
||||
return val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val),
|
||||
VALUE_ADDRESS (val),
|
||||
stream, format, 1, 0, pretty);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/* ***DEPRECATED*** The gdblib files must not be calling/using things in any
|
||||
of the possible command languages. If necessary, a hook (that may be
|
||||
present or not) must be used and set to the appropriate routine by any
|
||||
command language that cares about it. If you are having to include this
|
||||
file you are possibly doing things the old way. This file will disapear.
|
||||
2000-12-01 fnasser@redhat.com */
|
||||
|
||||
/* Prototypes for GDB commands that are called internally by other functions.
|
||||
Copyright 1992, 2000, 2001 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef CALL_CMDS_H
|
||||
#define CALL_CMDS_H
|
||||
|
||||
extern void initialize_all_files (void);
|
||||
|
||||
extern void core_file_command (char *, int);
|
||||
|
||||
extern void break_command (char *, int);
|
||||
|
||||
#endif
|
||||
2233
gdb/ch-exp.c
2233
gdb/ch-exp.c
File diff suppressed because it is too large
Load Diff
663
gdb/ch-lang.c
663
gdb/ch-lang.c
@@ -1,663 +0,0 @@
|
||||
/* Chill language support routines for GDB, the GNU debugger.
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "value.h"
|
||||
#include "expression.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "ch-lang.h"
|
||||
#include "valprint.h"
|
||||
|
||||
extern void _initialize_chill_language (void);
|
||||
|
||||
static struct value *evaluate_subexp_chill (struct type *, struct expression *,
|
||||
int *, enum noside);
|
||||
|
||||
static struct value *value_chill_max_min (enum exp_opcode, struct value *);
|
||||
|
||||
static struct value *value_chill_card (struct value *);
|
||||
|
||||
static struct value *value_chill_length (struct value *);
|
||||
|
||||
static struct type *chill_create_fundamental_type (struct objfile *, int);
|
||||
|
||||
static void chill_printstr (struct ui_file * stream, char *string,
|
||||
unsigned int length, int width,
|
||||
int force_ellipses);
|
||||
|
||||
static void chill_printchar (int, struct ui_file *);
|
||||
|
||||
/* For now, Chill uses a simple mangling algorithm whereby you simply
|
||||
discard everything after the occurance of two successive CPLUS_MARKER
|
||||
characters to derive the demangled form. */
|
||||
|
||||
char *
|
||||
chill_demangle (const char *mangled)
|
||||
{
|
||||
const char *joiner = NULL;
|
||||
char *demangled;
|
||||
const char *cp = mangled;
|
||||
|
||||
while (*cp)
|
||||
{
|
||||
if (is_cplus_marker (*cp))
|
||||
{
|
||||
joiner = cp;
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
if (joiner != NULL && *(joiner + 1) == *joiner)
|
||||
{
|
||||
demangled = savestring (mangled, joiner - mangled);
|
||||
}
|
||||
else
|
||||
{
|
||||
demangled = NULL;
|
||||
}
|
||||
return (demangled);
|
||||
}
|
||||
|
||||
static void
|
||||
chill_printchar (register int c, struct ui_file *stream)
|
||||
{
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
if (PRINT_LITERAL_FORM (c))
|
||||
{
|
||||
if (c == '\'' || c == '^')
|
||||
fprintf_filtered (stream, "'%c%c'", c, c);
|
||||
else
|
||||
fprintf_filtered (stream, "'%c'", c);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "'^(%u)'", (unsigned int) c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH characters.
|
||||
Printing stops early if the number hits print_max; repeat counts
|
||||
are printed as appropriate. Print ellipses at the end if we
|
||||
had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
|
||||
Note that gdb maintains the length of strings without counting the
|
||||
terminating null byte, while chill strings are typically written with
|
||||
an explicit null byte. So we always assume an implied null byte
|
||||
until gdb is able to maintain non-null terminated strings as well
|
||||
as null terminated strings (FIXME).
|
||||
*/
|
||||
|
||||
static void
|
||||
chill_printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int width, int force_ellipses)
|
||||
{
|
||||
register unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_literal_form = 0;
|
||||
int in_control_form = 0;
|
||||
int need_slashslash = 0;
|
||||
unsigned int c;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length && things_printed < print_max; ++i)
|
||||
{
|
||||
/* Position of the character we are examining
|
||||
to see whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_slashslash)
|
||||
{
|
||||
fputs_filtered ("//", stream);
|
||||
need_slashslash = 0;
|
||||
}
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length && string[rep1] == string[i])
|
||||
{
|
||||
++rep1;
|
||||
++reps;
|
||||
}
|
||||
|
||||
c = string[i];
|
||||
if (reps > repeat_count_threshold)
|
||||
{
|
||||
if (in_control_form || in_literal_form)
|
||||
{
|
||||
if (in_control_form)
|
||||
fputs_filtered (")", stream);
|
||||
fputs_filtered ("\"//", stream);
|
||||
in_control_form = in_literal_form = 0;
|
||||
}
|
||||
chill_printchar (c, stream);
|
||||
fprintf_filtered (stream, "<repeats %u times>", reps);
|
||||
i = rep1 - 1;
|
||||
things_printed += repeat_count_threshold;
|
||||
need_slashslash = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_literal_form && !in_control_form)
|
||||
fputs_filtered ("\"", stream);
|
||||
if (PRINT_LITERAL_FORM (c))
|
||||
{
|
||||
if (!in_literal_form)
|
||||
{
|
||||
if (in_control_form)
|
||||
{
|
||||
fputs_filtered (")", stream);
|
||||
in_control_form = 0;
|
||||
}
|
||||
in_literal_form = 1;
|
||||
}
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
if (c == '"' || c == '^')
|
||||
/* duplicate this one as must be done at input */
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_control_form)
|
||||
{
|
||||
if (in_literal_form)
|
||||
{
|
||||
in_literal_form = 0;
|
||||
}
|
||||
fputs_filtered ("^(", stream);
|
||||
in_control_form = 1;
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, ",");
|
||||
c = c & 0xff;
|
||||
fprintf_filtered (stream, "%u", (unsigned int) c);
|
||||
}
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_control_form)
|
||||
{
|
||||
fputs_filtered (")", stream);
|
||||
}
|
||||
if (in_literal_form || in_control_form)
|
||||
{
|
||||
fputs_filtered ("\"", stream);
|
||||
}
|
||||
if (force_ellipses || (i < length))
|
||||
{
|
||||
fputs_filtered ("...", stream);
|
||||
}
|
||||
}
|
||||
|
||||
static struct type *
|
||||
chill_create_fundamental_type (struct objfile *objfile, int typeid)
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
|
||||
switch (typeid)
|
||||
{
|
||||
default:
|
||||
/* FIXME: For now, if we are asked to produce a type not in this
|
||||
language, create the equivalent of a C integer type with the
|
||||
name "<?type?>". When all the dust settles from the type
|
||||
reconstruction work, this should probably become an error. */
|
||||
type = init_type (TYPE_CODE_INT, 2, 0, "<?type?>", objfile);
|
||||
warning ("internal error: no chill fundamental type %d", typeid);
|
||||
break;
|
||||
case FT_VOID:
|
||||
/* FIXME: Currently the GNU Chill compiler emits some DWARF entries for
|
||||
typedefs, unrelated to anything directly in the code being compiled,
|
||||
that have some FT_VOID types. Just fake it for now. */
|
||||
type = init_type (TYPE_CODE_VOID, 0, 0, "<?VOID?>", objfile);
|
||||
break;
|
||||
case FT_BOOLEAN:
|
||||
type = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "BOOL", objfile);
|
||||
break;
|
||||
case FT_CHAR:
|
||||
type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile);
|
||||
break;
|
||||
case FT_SIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT, 1, 0, "BYTE", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, "UBYTE", objfile);
|
||||
break;
|
||||
case FT_SHORT: /* Chill ints are 2 bytes */
|
||||
type = init_type (TYPE_CODE_INT, 2, 0, "INT", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_SHORT: /* Chill ints are 2 bytes */
|
||||
type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, "UINT", objfile);
|
||||
break;
|
||||
case FT_INTEGER: /* FIXME? */
|
||||
case FT_SIGNED_INTEGER: /* FIXME? */
|
||||
case FT_LONG: /* Chill longs are 4 bytes */
|
||||
case FT_SIGNED_LONG: /* Chill longs are 4 bytes */
|
||||
type = init_type (TYPE_CODE_INT, 4, 0, "LONG", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_INTEGER: /* FIXME? */
|
||||
case FT_UNSIGNED_LONG: /* Chill longs are 4 bytes */
|
||||
type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "ULONG", objfile);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT, 4, 0, "REAL", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT, 8, 0, "LONG_REAL", objfile);
|
||||
break;
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
||||
|
||||
/* Table of operators and their precedences for printing expressions. */
|
||||
|
||||
static const struct op_print chill_op_print_tab[] =
|
||||
{
|
||||
{"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
|
||||
{"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
|
||||
{"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"MOD", BINOP_MOD, PREC_MUL, 0},
|
||||
{"REM", BINOP_REM, PREC_MUL, 0},
|
||||
{"SIZE", UNOP_SIZEOF, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"LOWER", UNOP_LOWER, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"UPPER", UNOP_UPPER, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"CARD", UNOP_CARD, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"MAX", UNOP_CHMAX, PREC_BUILTIN_FUNCTION, 0},
|
||||
{"MIN", UNOP_CHMIN, PREC_BUILTIN_FUNCTION, 0},
|
||||
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"//", BINOP_CONCAT, PREC_PREFIX, 0}, /* FIXME: precedence? */
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"->", UNOP_IND, PREC_SUFFIX, 1},
|
||||
{"->", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{":", BINOP_RANGE, PREC_ASSIGN, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* The built-in types of Chill. */
|
||||
|
||||
struct type *builtin_type_chill_bool;
|
||||
struct type *builtin_type_chill_char;
|
||||
struct type *builtin_type_chill_long;
|
||||
struct type *builtin_type_chill_ulong;
|
||||
struct type *builtin_type_chill_real;
|
||||
|
||||
struct type **const (chill_builtin_types[]) =
|
||||
{
|
||||
&builtin_type_chill_bool,
|
||||
&builtin_type_chill_char,
|
||||
&builtin_type_chill_long,
|
||||
&builtin_type_chill_ulong,
|
||||
&builtin_type_chill_real,
|
||||
0
|
||||
};
|
||||
|
||||
/* Calculate LOWER or UPPER of TYPE.
|
||||
Returns the result as an integer.
|
||||
*RESULT_TYPE is the appropriate type for the result. */
|
||||
|
||||
LONGEST
|
||||
type_lower_upper (enum exp_opcode op, /* Either UNOP_LOWER or UNOP_UPPER */
|
||||
struct type *type, struct type **result_type)
|
||||
{
|
||||
LONGEST low, high;
|
||||
*result_type = type;
|
||||
CHECK_TYPEDEF (type);
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_STRUCT:
|
||||
*result_type = builtin_type_int;
|
||||
if (chill_varying_type (type))
|
||||
return type_lower_upper (op, TYPE_FIELD_TYPE (type, 1), result_type);
|
||||
break;
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_STRING:
|
||||
type = TYPE_FIELD_TYPE (type, 0); /* Get index type */
|
||||
|
||||
/* ... fall through ... */
|
||||
case TYPE_CODE_RANGE:
|
||||
*result_type = TYPE_TARGET_TYPE (type);
|
||||
return op == UNOP_LOWER ? TYPE_LOW_BOUND (type) : TYPE_HIGH_BOUND (type);
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
case TYPE_CODE_BOOL:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_CHAR:
|
||||
if (get_discrete_bounds (type, &low, &high) >= 0)
|
||||
{
|
||||
*result_type = type;
|
||||
return op == UNOP_LOWER ? low : high;
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_FLT:
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_SET:
|
||||
case TYPE_CODE_ERROR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_METHOD:
|
||||
case TYPE_CODE_REF:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
error ("unknown mode for LOWER/UPPER builtin");
|
||||
}
|
||||
|
||||
static struct value *
|
||||
value_chill_length (struct value *val)
|
||||
{
|
||||
LONGEST tmp;
|
||||
struct type *type = VALUE_TYPE (val);
|
||||
struct type *ttype;
|
||||
CHECK_TYPEDEF (type);
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_STRING:
|
||||
tmp = type_lower_upper (UNOP_UPPER, type, &ttype)
|
||||
- type_lower_upper (UNOP_LOWER, type, &ttype) + 1;
|
||||
break;
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (chill_varying_type (type))
|
||||
{
|
||||
tmp = unpack_long (TYPE_FIELD_TYPE (type, 0), VALUE_CONTENTS (val));
|
||||
break;
|
||||
}
|
||||
/* ... else fall through ... */
|
||||
default:
|
||||
error ("bad argument to LENGTH builtin");
|
||||
}
|
||||
return value_from_longest (builtin_type_int, tmp);
|
||||
}
|
||||
|
||||
static struct value *
|
||||
value_chill_card (struct value *val)
|
||||
{
|
||||
LONGEST tmp = 0;
|
||||
struct type *type = VALUE_TYPE (val);
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_SET)
|
||||
{
|
||||
struct type *range_type = TYPE_INDEX_TYPE (type);
|
||||
LONGEST lower_bound, upper_bound;
|
||||
int i;
|
||||
|
||||
get_discrete_bounds (range_type, &lower_bound, &upper_bound);
|
||||
for (i = lower_bound; i <= upper_bound; i++)
|
||||
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
|
||||
tmp++;
|
||||
}
|
||||
else
|
||||
error ("bad argument to CARD builtin");
|
||||
|
||||
return value_from_longest (builtin_type_int, tmp);
|
||||
}
|
||||
|
||||
static struct value *
|
||||
value_chill_max_min (enum exp_opcode op, struct value *val)
|
||||
{
|
||||
LONGEST tmp = 0;
|
||||
struct type *type = VALUE_TYPE (val);
|
||||
struct type *elttype;
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (TYPE_CODE (type) == TYPE_CODE_SET)
|
||||
{
|
||||
LONGEST lower_bound, upper_bound;
|
||||
int i, empty = 1;
|
||||
|
||||
elttype = TYPE_INDEX_TYPE (type);
|
||||
CHECK_TYPEDEF (elttype);
|
||||
get_discrete_bounds (elttype, &lower_bound, &upper_bound);
|
||||
|
||||
if (op == UNOP_CHMAX)
|
||||
{
|
||||
for (i = upper_bound; i >= lower_bound; i--)
|
||||
{
|
||||
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
|
||||
{
|
||||
tmp = i;
|
||||
empty = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = lower_bound; i <= upper_bound; i++)
|
||||
{
|
||||
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
|
||||
{
|
||||
tmp = i;
|
||||
empty = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty)
|
||||
error ("%s for empty powerset", op == UNOP_CHMAX ? "MAX" : "MIN");
|
||||
}
|
||||
else
|
||||
error ("bad argument to %s builtin", op == UNOP_CHMAX ? "MAX" : "MIN");
|
||||
|
||||
return value_from_longest (TYPE_CODE (elttype) == TYPE_CODE_RANGE
|
||||
? TYPE_TARGET_TYPE (elttype)
|
||||
: elttype,
|
||||
tmp);
|
||||
}
|
||||
|
||||
static struct value *
|
||||
evaluate_subexp_chill (struct type *expect_type,
|
||||
register struct expression *exp, register int *pos,
|
||||
enum noside noside)
|
||||
{
|
||||
int pc = *pos;
|
||||
struct type *type;
|
||||
int tem, nargs;
|
||||
struct value *arg1;
|
||||
struct value **argvec;
|
||||
enum exp_opcode op = exp->elts[*pos].opcode;
|
||||
switch (op)
|
||||
{
|
||||
case MULTI_SUBSCRIPT:
|
||||
if (noside == EVAL_SKIP)
|
||||
break;
|
||||
(*pos) += 3;
|
||||
nargs = longest_to_int (exp->elts[pc + 1].longconst);
|
||||
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
type = check_typedef (VALUE_TYPE (arg1));
|
||||
|
||||
if (nargs == 1 && TYPE_CODE (type) == TYPE_CODE_INT)
|
||||
{
|
||||
/* Looks like string repetition. */
|
||||
struct value *string = evaluate_subexp_with_coercion (exp, pos,
|
||||
noside);
|
||||
return value_concat (arg1, string);
|
||||
}
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_PTR:
|
||||
type = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (!type || TYPE_CODE (type) != TYPE_CODE_FUNC)
|
||||
error ("reference value used as function");
|
||||
/* ... fall through ... */
|
||||
case TYPE_CODE_FUNC:
|
||||
/* It's a function call. */
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
break;
|
||||
|
||||
/* Allocate arg vector, including space for the function to be
|
||||
called in argvec[0] and a terminating NULL */
|
||||
argvec = (struct value **) alloca (sizeof (struct value *)
|
||||
* (nargs + 2));
|
||||
argvec[0] = arg1;
|
||||
tem = 1;
|
||||
for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
|
||||
{
|
||||
argvec[tem]
|
||||
= evaluate_subexp_chill (TYPE_FIELD_TYPE (type, tem - 1),
|
||||
exp, pos, noside);
|
||||
}
|
||||
for (; tem <= nargs; tem++)
|
||||
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||
argvec[tem] = 0; /* signal end of arglist */
|
||||
|
||||
return call_function_by_hand (argvec[0], nargs, argvec + 1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (nargs-- > 0)
|
||||
{
|
||||
struct value *index = evaluate_subexp_with_coercion (exp, pos,
|
||||
noside);
|
||||
arg1 = value_subscript (arg1, index);
|
||||
}
|
||||
return (arg1);
|
||||
|
||||
case UNOP_LOWER:
|
||||
case UNOP_UPPER:
|
||||
(*pos)++;
|
||||
if (noside == EVAL_SKIP)
|
||||
{
|
||||
(*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, EVAL_SKIP);
|
||||
goto nosideret;
|
||||
}
|
||||
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos,
|
||||
EVAL_AVOID_SIDE_EFFECTS);
|
||||
tem = type_lower_upper (op, VALUE_TYPE (arg1), &type);
|
||||
return value_from_longest (type, tem);
|
||||
|
||||
case UNOP_LENGTH:
|
||||
(*pos)++;
|
||||
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
|
||||
return value_chill_length (arg1);
|
||||
|
||||
case UNOP_CARD:
|
||||
(*pos)++;
|
||||
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
|
||||
return value_chill_card (arg1);
|
||||
|
||||
case UNOP_CHMAX:
|
||||
case UNOP_CHMIN:
|
||||
(*pos)++;
|
||||
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
|
||||
return value_chill_max_min (op, arg1);
|
||||
|
||||
case BINOP_COMMA:
|
||||
error ("',' operator used in invalid context");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return evaluate_subexp_standard (expect_type, exp, pos, noside);
|
||||
nosideret:
|
||||
return value_from_longest (builtin_type_long, (LONGEST) 1);
|
||||
}
|
||||
|
||||
const struct language_defn chill_language_defn =
|
||||
{
|
||||
"chill",
|
||||
language_chill,
|
||||
chill_builtin_types,
|
||||
range_check_on,
|
||||
type_check_on,
|
||||
case_sensitive_on,
|
||||
chill_parse, /* parser */
|
||||
chill_error, /* parser error function */
|
||||
evaluate_subexp_chill,
|
||||
chill_printchar, /* print a character constant */
|
||||
chill_printstr, /* function to print a string constant */
|
||||
NULL, /* Function to print a single char */
|
||||
chill_create_fundamental_type, /* Create fundamental type in this language */
|
||||
chill_print_type, /* Print a type using appropriate syntax */
|
||||
chill_val_print, /* Print a value using appropriate syntax */
|
||||
chill_value_print, /* Print a top-levl value */
|
||||
{"", "B'", "", ""}, /* Binary format info */
|
||||
{"O'%lo", "O'", "o", ""}, /* Octal format info */
|
||||
{"D'%ld", "D'", "d", ""}, /* Decimal format info */
|
||||
{"H'%lx", "H'", "x", ""}, /* Hex format info */
|
||||
chill_op_print_tab, /* expression operators for printing */
|
||||
0, /* arrays are first-class (not c-style) */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_chill_char, /* Type of string elements */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
/* Initialization for Chill */
|
||||
|
||||
void
|
||||
_initialize_chill_language (void)
|
||||
{
|
||||
builtin_type_chill_bool =
|
||||
init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"BOOL", (struct objfile *) NULL);
|
||||
builtin_type_chill_char =
|
||||
init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"CHAR", (struct objfile *) NULL);
|
||||
builtin_type_chill_long =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"LONG", (struct objfile *) NULL);
|
||||
builtin_type_chill_ulong =
|
||||
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED,
|
||||
"ULONG", (struct objfile *) NULL);
|
||||
builtin_type_chill_real =
|
||||
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0,
|
||||
"LONG_REAL", (struct objfile *) NULL);
|
||||
|
||||
add_language (&chill_language_defn);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* Chill language support definitions for GDB, the GNU debugger.
|
||||
Copyright 1992, 1994, 1996, 1998, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Forward decls for prototypes */
|
||||
struct value;
|
||||
|
||||
extern int chill_parse (void); /* Defined in ch-exp.y */
|
||||
|
||||
extern void chill_error (char *); /* Defined in ch-exp.y */
|
||||
|
||||
/* Defined in ch-typeprint.c */
|
||||
extern void chill_print_type (struct type *, char *, struct ui_file *, int,
|
||||
int);
|
||||
|
||||
extern int chill_val_print (struct type *, char *, int, CORE_ADDR,
|
||||
struct ui_file *, int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
extern int chill_value_print (struct value *, struct ui_file *,
|
||||
int, enum val_prettyprint);
|
||||
|
||||
extern LONGEST
|
||||
type_lower_upper (enum exp_opcode, struct type *, struct type **);
|
||||
@@ -1,340 +0,0 @@
|
||||
/* Support for printing Chill types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "bfd.h" /* Binary File Description */
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "language.h"
|
||||
#include "ch-lang.h"
|
||||
#include "typeprint.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
#include <errno.h>
|
||||
|
||||
static void chill_type_print_base (struct type *, struct ui_file *, int, int);
|
||||
|
||||
void
|
||||
chill_print_type (struct type *type, char *varstring, struct ui_file *stream,
|
||||
int show, int level)
|
||||
{
|
||||
if (varstring != NULL && *varstring != '\0')
|
||||
{
|
||||
fputs_filtered (varstring, stream);
|
||||
fputs_filtered (" ", stream);
|
||||
}
|
||||
chill_type_print_base (type, stream, show, level);
|
||||
}
|
||||
|
||||
/* Print the name of the type (or the ultimate pointer target,
|
||||
function value or array element).
|
||||
|
||||
SHOW nonzero means don't print this type as just its name;
|
||||
show its real definition even if it has a name.
|
||||
SHOW zero means print just typename or tag if there is one
|
||||
SHOW negative means abbreviate structure elements.
|
||||
SHOW is decremented for printing of structure elements.
|
||||
|
||||
LEVEL is the depth to indent by.
|
||||
We increase it for some recursive calls. */
|
||||
|
||||
static void
|
||||
chill_type_print_base (struct type *type, struct ui_file *stream, int show,
|
||||
int level)
|
||||
{
|
||||
register int len;
|
||||
register int i;
|
||||
struct type *index_type;
|
||||
struct type *range_type;
|
||||
LONGEST low_bound;
|
||||
LONGEST high_bound;
|
||||
|
||||
QUIT;
|
||||
|
||||
wrap_here (" ");
|
||||
if (type == NULL)
|
||||
{
|
||||
fputs_filtered ("<type unknown>", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* When SHOW is zero or less, and there is a valid type name, then always
|
||||
just print the type name directly from the type. */
|
||||
|
||||
if ((show <= 0) && (TYPE_NAME (type) != NULL))
|
||||
{
|
||||
fputs_filtered (TYPE_NAME (type), stream);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
|
||||
break;
|
||||
case TYPE_CODE_PTR:
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream,
|
||||
TYPE_NAME (type) ? TYPE_NAME (type) : "PTR");
|
||||
break;
|
||||
}
|
||||
fprintf_filtered (stream, "REF ");
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
/* FIXME: we should probably just print the TYPE_NAME, in case
|
||||
anyone ever fixes the compiler to give us the real names
|
||||
in the presence of the chill equivalent of typedef (assuming
|
||||
there is one). */
|
||||
fprintf_filtered (stream,
|
||||
TYPE_NAME (type) ? TYPE_NAME (type) : "BOOL");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
fputs_filtered ("ARRAY (", stream);
|
||||
range_type = TYPE_FIELD_TYPE (type, 0);
|
||||
if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
|
||||
chill_print_type (range_type, "", stream, 0, level);
|
||||
else
|
||||
{
|
||||
index_type = TYPE_TARGET_TYPE (range_type);
|
||||
low_bound = TYPE_FIELD_BITPOS (range_type, 0);
|
||||
high_bound = TYPE_FIELD_BITPOS (range_type, 1);
|
||||
print_type_scalar (index_type, low_bound, stream);
|
||||
fputs_filtered (":", stream);
|
||||
print_type_scalar (index_type, high_bound, stream);
|
||||
}
|
||||
fputs_filtered (") ", stream);
|
||||
chill_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BITSTRING:
|
||||
fprintf_filtered (stream, "BOOLS (%d)",
|
||||
TYPE_FIELD_BITPOS (TYPE_FIELD_TYPE (type, 0), 1) + 1);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_SET:
|
||||
fputs_filtered ("POWERSET ", stream);
|
||||
chill_print_type (TYPE_INDEX_TYPE (type), "", stream,
|
||||
show - 1, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRING:
|
||||
range_type = TYPE_FIELD_TYPE (type, 0);
|
||||
index_type = TYPE_TARGET_TYPE (range_type);
|
||||
high_bound = TYPE_FIELD_BITPOS (range_type, 1);
|
||||
fputs_filtered ("CHARS (", stream);
|
||||
print_type_scalar (index_type, high_bound + 1, stream);
|
||||
fputs_filtered (")", stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
fprintf_filtered (stream, "MEMBER ");
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
|
||||
break;
|
||||
case TYPE_CODE_REF:
|
||||
fprintf_filtered (stream, "/*LOC*/ ");
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_FUNC:
|
||||
fprintf_filtered (stream, "PROC (");
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
struct type *param_type = TYPE_FIELD_TYPE (type, i);
|
||||
if (i > 0)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
wrap_here (" ");
|
||||
}
|
||||
if (TYPE_CODE (param_type) == TYPE_CODE_REF)
|
||||
{
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (param_type),
|
||||
stream, 0, level);
|
||||
fputs_filtered (" LOC", stream);
|
||||
}
|
||||
else
|
||||
chill_type_print_base (param_type, stream, show, level);
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fputs_filtered (" RETURNS (", stream);
|
||||
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
|
||||
fputs_filtered (")", stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (chill_varying_type (type))
|
||||
{
|
||||
chill_type_print_base (TYPE_FIELD_TYPE (type, 1),
|
||||
stream, 0, level);
|
||||
fputs_filtered (" VARYING", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "STRUCT ");
|
||||
|
||||
fprintf_filtered (stream, "(\n");
|
||||
if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
|
||||
{
|
||||
if (TYPE_STUB (type))
|
||||
{
|
||||
fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintfi_filtered (level + 4, stream, "<no data fields>\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
|
||||
{
|
||||
struct type *field_type = TYPE_FIELD_TYPE (type, i);
|
||||
QUIT;
|
||||
print_spaces_filtered (level + 4, stream);
|
||||
if (TYPE_CODE (field_type) == TYPE_CODE_UNION)
|
||||
{
|
||||
int j; /* variant number */
|
||||
fputs_filtered ("CASE OF\n", stream);
|
||||
for (j = 0; j < TYPE_NFIELDS (field_type); j++)
|
||||
{
|
||||
int k; /* variant field index */
|
||||
struct type *variant_type
|
||||
= TYPE_FIELD_TYPE (field_type, j);
|
||||
int var_len = TYPE_NFIELDS (variant_type);
|
||||
print_spaces_filtered (level + 4, stream);
|
||||
if (strcmp (TYPE_FIELD_NAME (field_type, j),
|
||||
"else") == 0)
|
||||
fputs_filtered ("ELSE\n", stream);
|
||||
else
|
||||
fputs_filtered (":\n", stream);
|
||||
if (TYPE_CODE (variant_type) != TYPE_CODE_STRUCT)
|
||||
error ("variant record confusion");
|
||||
for (k = 0; k < var_len; k++)
|
||||
{
|
||||
print_spaces_filtered (level + 8, stream);
|
||||
chill_print_type (TYPE_FIELD_TYPE (variant_type, k),
|
||||
TYPE_FIELD_NAME (variant_type, k),
|
||||
stream, show - 1, level + 8);
|
||||
if (k < (var_len - 1))
|
||||
fputs_filtered (",", stream);
|
||||
fputs_filtered ("\n", stream);
|
||||
}
|
||||
}
|
||||
print_spaces_filtered (level + 4, stream);
|
||||
fputs_filtered ("ESAC", stream);
|
||||
}
|
||||
else
|
||||
chill_print_type (field_type,
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
if (i < (len - 1))
|
||||
{
|
||||
fputs_filtered (",", stream);
|
||||
}
|
||||
fputs_filtered ("\n", stream);
|
||||
}
|
||||
}
|
||||
fprintfi_filtered (level, stream, ")");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
{
|
||||
struct type *target = TYPE_TARGET_TYPE (type);
|
||||
if (target && TYPE_NAME (target))
|
||||
fputs_filtered (TYPE_NAME (target), stream);
|
||||
else
|
||||
fputs_filtered ("RANGE", stream);
|
||||
if (target == NULL)
|
||||
target = builtin_type_long;
|
||||
fputs_filtered (" (", stream);
|
||||
print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
|
||||
fputs_filtered (":", stream);
|
||||
print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
|
||||
fputs_filtered (")", stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
{
|
||||
register int lastval = 0;
|
||||
fprintf_filtered (stream, "SET (");
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (i)
|
||||
fprintf_filtered (stream, ", ");
|
||||
wrap_here (" ");
|
||||
fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
|
||||
if (lastval != TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i));
|
||||
lastval = TYPE_FIELD_BITPOS (type, i);
|
||||
}
|
||||
lastval++;
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_ERROR:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_METHOD:
|
||||
error ("missing language support in chill_type_print_base");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Handle types not explicitly handled by the other cases,
|
||||
such as fundamental types. For these, just print whatever
|
||||
the type name is, as recorded in the type itself. If there
|
||||
is no type name, then complain. */
|
||||
|
||||
if (TYPE_NAME (type) != NULL)
|
||||
{
|
||||
fputs_filtered (TYPE_NAME (type), stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("Unrecognized type code (%d) in symbol table.",
|
||||
TYPE_CODE (type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,605 +0,0 @@
|
||||
/* Support for printing Chill values for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "valprint.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "demangle.h"
|
||||
#include "c-lang.h" /* For c_val_print */
|
||||
#include "typeprint.h"
|
||||
#include "ch-lang.h"
|
||||
#include "annotate.h"
|
||||
|
||||
static void chill_print_value_fields (struct type *, char *,
|
||||
struct ui_file *, int, int,
|
||||
enum val_prettyprint, struct type **);
|
||||
|
||||
static void chill_print_type_scalar (struct type *, LONGEST,
|
||||
struct ui_file *);
|
||||
|
||||
static void chill_val_print_array_elements (struct type *, char *,
|
||||
CORE_ADDR, struct ui_file *,
|
||||
int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
|
||||
/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM.
|
||||
Used to print data from type structures in a specified type. For example,
|
||||
array bounds may be characters or booleans in some languages, and this
|
||||
allows the ranges to be printed in their "natural" form rather than as
|
||||
decimal integer values. */
|
||||
|
||||
static void
|
||||
chill_print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
|
||||
{
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_RANGE:
|
||||
if (TYPE_TARGET_TYPE (type))
|
||||
{
|
||||
chill_print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_ENUM:
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_FLT:
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_SET:
|
||||
case TYPE_CODE_STRING:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_ERROR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_METHOD:
|
||||
case TYPE_CODE_REF:
|
||||
case TYPE_CODE_CHAR:
|
||||
case TYPE_CODE_BOOL:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
print_type_scalar (type, val, stream);
|
||||
}
|
||||
|
||||
/* Print the elements of an array.
|
||||
Similar to val_print_array_elements, but prints
|
||||
element indexes (in Chill syntax). */
|
||||
|
||||
static void
|
||||
chill_val_print_array_elements (struct type *type, char *valaddr,
|
||||
CORE_ADDR address, struct ui_file *stream,
|
||||
int format, int deref_ref, int recurse,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
unsigned int things_printed = 0;
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
struct type *range_type = TYPE_FIELD_TYPE (type, 0);
|
||||
struct type *index_type = TYPE_TARGET_TYPE (range_type);
|
||||
unsigned eltlen;
|
||||
/* Position of the array element we are examining to see
|
||||
whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
LONGEST low_bound = TYPE_FIELD_BITPOS (range_type, 0);
|
||||
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
eltlen = TYPE_LENGTH (elttype);
|
||||
len = TYPE_LENGTH (type) / eltlen;
|
||||
|
||||
annotate_array_section_begin (i, elttype);
|
||||
|
||||
for (; i < len && things_printed < print_max; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
fprintf_filtered (stream, ",\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
}
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while ((rep1 < len) &&
|
||||
!memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen))
|
||||
{
|
||||
++reps;
|
||||
++rep1;
|
||||
}
|
||||
|
||||
fputs_filtered ("(", stream);
|
||||
chill_print_type_scalar (index_type, low_bound + i, stream);
|
||||
if (reps > 1)
|
||||
{
|
||||
fputs_filtered (":", stream);
|
||||
chill_print_type_scalar (index_type, low_bound + i + reps - 1,
|
||||
stream);
|
||||
fputs_filtered ("): ", stream);
|
||||
val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
|
||||
deref_ref, recurse + 1, pretty);
|
||||
|
||||
i = rep1 - 1;
|
||||
things_printed += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs_filtered ("): ", stream);
|
||||
val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
|
||||
deref_ref, recurse + 1, pretty);
|
||||
annotate_elt ();
|
||||
things_printed++;
|
||||
}
|
||||
}
|
||||
annotate_array_section_end ();
|
||||
if (i < len)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print data of type TYPE located at VALADDR (within GDB), which came from
|
||||
the inferior at address ADDRESS, onto stdio stream STREAM according to
|
||||
FORMAT (a letter or 0 for natural format). The data at VALADDR is in
|
||||
target byte order.
|
||||
|
||||
If the data are a string pointer, returns the number of string characters
|
||||
printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references, otherwise just print
|
||||
them like pointers.
|
||||
|
||||
The PRETTY parameter controls prettyprinting. */
|
||||
|
||||
int
|
||||
chill_val_print (struct type *type, char *valaddr, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
LONGEST val;
|
||||
unsigned int i = 0; /* Number of characters printed. */
|
||||
struct type *elttype;
|
||||
CORE_ADDR addr;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
fprintf_filtered (stream, "[");
|
||||
chill_val_print_array_elements (type, valaddr, address, stream,
|
||||
format, deref_ref, recurse, pretty);
|
||||
fprintf_filtered (stream, "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("unimplemented in chill_val_print; unspecified array length");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
val_print_type_code_int (type, valaddr, stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
|
||||
stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_floating (valaddr, type, stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Why is this using builtin_type_chill_bool not type? */
|
||||
val = unpack_long (builtin_type_chill_bool, valaddr);
|
||||
fprintf_filtered (stream, val ? "TRUE" : "FALSE");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
/* This happens (without TYPE_FLAG_STUB set) on systems which don't use
|
||||
dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
|
||||
and no complete type for struct foo in that file. */
|
||||
fprintf_filtered (stream, "<incomplete type>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
if (format && format != 's')
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
addr = unpack_pointer (type, valaddr);
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
|
||||
/* We assume a NULL pointer is all zeros ... */
|
||||
if (addr == 0)
|
||||
{
|
||||
fputs_filtered ("NULL", stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
|
||||
{
|
||||
/* Try to print what function it points to. */
|
||||
print_address_demangle (addr, stream, demangle);
|
||||
/* Return value is irrelevant except for string pointers. */
|
||||
return (0);
|
||||
}
|
||||
if (addressprint && format != 's')
|
||||
{
|
||||
print_address_numeric (addr, 1, stream);
|
||||
}
|
||||
|
||||
/* For a pointer to char or unsigned char, also print the string
|
||||
pointed to, unless pointer is null. */
|
||||
if (TYPE_LENGTH (elttype) == 1
|
||||
&& TYPE_CODE (elttype) == TYPE_CODE_CHAR
|
||||
&& (format == 0 || format == 's')
|
||||
&& addr != 0
|
||||
&& /* If print_max is UINT_MAX, the alloca below will fail.
|
||||
In that case don't try to print the string. */
|
||||
print_max < UINT_MAX)
|
||||
i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
|
||||
|
||||
/* Return number of characters printed, plus one for the
|
||||
terminating null if we have "reached the end". */
|
||||
return (i + (print_max && i != print_max));
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRING:
|
||||
i = TYPE_LENGTH (type);
|
||||
LA_PRINT_STRING (stream, valaddr, i, 1, 0);
|
||||
/* Return number of characters printed, plus one for the terminating
|
||||
null if we have "reached the end". */
|
||||
return (i + (print_max && i != print_max));
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_SET:
|
||||
elttype = TYPE_INDEX_TYPE (type);
|
||||
CHECK_TYPEDEF (elttype);
|
||||
if (TYPE_STUB (elttype))
|
||||
{
|
||||
fprintf_filtered (stream, "<incomplete type>");
|
||||
gdb_flush (stream);
|
||||
break;
|
||||
}
|
||||
{
|
||||
struct type *range = elttype;
|
||||
LONGEST low_bound, high_bound;
|
||||
int i;
|
||||
int is_bitstring = TYPE_CODE (type) == TYPE_CODE_BITSTRING;
|
||||
int need_comma = 0;
|
||||
|
||||
if (is_bitstring)
|
||||
fputs_filtered ("B'", stream);
|
||||
else
|
||||
fputs_filtered ("[", stream);
|
||||
|
||||
i = get_discrete_bounds (range, &low_bound, &high_bound);
|
||||
maybe_bad_bstring:
|
||||
if (i < 0)
|
||||
{
|
||||
fputs_filtered ("<error value>", stream);
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = low_bound; i <= high_bound; i++)
|
||||
{
|
||||
int element = value_bit_index (type, valaddr, i);
|
||||
if (element < 0)
|
||||
{
|
||||
i = element;
|
||||
goto maybe_bad_bstring;
|
||||
}
|
||||
if (is_bitstring)
|
||||
fprintf_filtered (stream, "%d", element);
|
||||
else if (element)
|
||||
{
|
||||
if (need_comma)
|
||||
fputs_filtered (", ", stream);
|
||||
chill_print_type_scalar (range, (LONGEST) i, stream);
|
||||
need_comma = 1;
|
||||
|
||||
/* Look for a continuous range of true elements. */
|
||||
if (i + 1 <= high_bound && value_bit_index (type, valaddr, ++i))
|
||||
{
|
||||
int j = i; /* j is the upper bound so far of the range */
|
||||
fputs_filtered (":", stream);
|
||||
while (i + 1 <= high_bound
|
||||
&& value_bit_index (type, valaddr, ++i))
|
||||
j = i;
|
||||
chill_print_type_scalar (range, (LONGEST) j, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (is_bitstring)
|
||||
fputs_filtered ("'", stream);
|
||||
else
|
||||
fputs_filtered ("]", stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (chill_varying_type (type))
|
||||
{
|
||||
struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 1));
|
||||
long length = unpack_long (TYPE_FIELD_TYPE (type, 0), valaddr);
|
||||
char *data_addr = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
|
||||
|
||||
switch (TYPE_CODE (inner))
|
||||
{
|
||||
case TYPE_CODE_STRING:
|
||||
if (length > TYPE_LENGTH (type) - 2)
|
||||
{
|
||||
fprintf_filtered (stream,
|
||||
"<dynamic length %ld > static length %d> *invalid*",
|
||||
length, TYPE_LENGTH (type));
|
||||
|
||||
/* Don't print the string; doing so might produce a
|
||||
segfault. */
|
||||
return length;
|
||||
}
|
||||
LA_PRINT_STRING (stream, data_addr, length, 1, 0);
|
||||
return length;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
|
||||
0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
if (addressprint)
|
||||
{
|
||||
fprintf_filtered (stream, "LOC(");
|
||||
print_address_numeric
|
||||
(extract_address (valaddr, TARGET_PTR_BIT / HOST_CHAR_BIT),
|
||||
1,
|
||||
stream);
|
||||
fprintf_filtered (stream, ")");
|
||||
if (deref_ref)
|
||||
fputs_filtered (": ", stream);
|
||||
}
|
||||
/* De-reference the reference. */
|
||||
if (deref_ref)
|
||||
{
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
struct value *deref_val =
|
||||
value_at
|
||||
(TYPE_TARGET_TYPE (type),
|
||||
unpack_pointer (lookup_pointer_type (builtin_type_void),
|
||||
valaddr),
|
||||
NULL);
|
||||
val_print (VALUE_TYPE (deref_val),
|
||||
VALUE_CONTENTS (deref_val),
|
||||
0,
|
||||
VALUE_ADDRESS (deref_val), stream, format,
|
||||
deref_ref, recurse + 1, pretty);
|
||||
}
|
||||
else
|
||||
fputs_filtered ("???", stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
c_val_print (type, valaddr, 0, address, stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
if (TYPE_TARGET_TYPE (type))
|
||||
chill_val_print (TYPE_TARGET_TYPE (type), valaddr, 0, address, stream,
|
||||
format, deref_ref, recurse, pretty);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_ERROR:
|
||||
default:
|
||||
/* Let's defer printing to the C printer, rather than
|
||||
print an error message. FIXME! */
|
||||
c_val_print (type, valaddr, 0, address, stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
}
|
||||
gdb_flush (stream);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Mutually recursive subroutines of cplus_print_value and c_val_print to
|
||||
print out a structure's fields: cp_print_value_fields and cplus_print_value.
|
||||
|
||||
TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
|
||||
same meanings as in cplus_print_value and c_val_print.
|
||||
|
||||
DONT_PRINT is an array of baseclass types that we
|
||||
should not print, or zero if called from top level. */
|
||||
|
||||
static void
|
||||
chill_print_value_fields (struct type *type, char *valaddr,
|
||||
struct ui_file *stream, int format, int recurse,
|
||||
enum val_prettyprint pretty, struct type **dont_print)
|
||||
{
|
||||
int i, len;
|
||||
int fields_seen = 0;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
fprintf_filtered (stream, "[");
|
||||
len = TYPE_NFIELDS (type);
|
||||
if (len == 0)
|
||||
{
|
||||
fprintf_filtered (stream, "<No data fields>");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (fields_seen)
|
||||
{
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
fields_seen = 1;
|
||||
if (pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
}
|
||||
fputs_filtered (".", stream);
|
||||
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
|
||||
language_chill, DMGL_NO_OPTS);
|
||||
fputs_filtered (": ", stream);
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
struct value *v;
|
||||
|
||||
/* Bitfields require special handling, especially due to byte
|
||||
order problems. */
|
||||
v = value_from_longest (TYPE_FIELD_TYPE (type, i),
|
||||
unpack_field_as_long (type, valaddr, i));
|
||||
|
||||
chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, 0,
|
||||
stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
else
|
||||
{
|
||||
chill_val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0,
|
||||
0, stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
}
|
||||
if (pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 * recurse, stream);
|
||||
}
|
||||
}
|
||||
fprintf_filtered (stream, "]");
|
||||
}
|
||||
|
||||
int
|
||||
chill_value_print (struct value *val, struct ui_file *stream, int format,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
struct type *type = VALUE_TYPE (val);
|
||||
struct type *real_type = check_typedef (type);
|
||||
|
||||
/* If it is a pointer, indicate what it points to.
|
||||
|
||||
Print type also if it is a reference. */
|
||||
|
||||
if (TYPE_CODE (real_type) == TYPE_CODE_PTR ||
|
||||
TYPE_CODE (real_type) == TYPE_CODE_REF)
|
||||
{
|
||||
char *valaddr = VALUE_CONTENTS (val);
|
||||
CORE_ADDR addr = unpack_pointer (type, valaddr);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_PTR || addr != 0)
|
||||
{
|
||||
int i;
|
||||
char *name = TYPE_NAME (type);
|
||||
if (name)
|
||||
fputs_filtered (name, stream);
|
||||
else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
|
||||
fputs_filtered ("PTR", stream);
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
fprintf_filtered (stream, "(");
|
||||
i = val_print (type, valaddr, 0, VALUE_ADDRESS (val),
|
||||
stream, format, 1, 0, pretty);
|
||||
fprintf_filtered (stream, ")");
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return (val_print (type, VALUE_CONTENTS (val), 0,
|
||||
VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
|
||||
}
|
||||
373
gdb/cli-out.c
373
gdb/cli-out.c
@@ -1,373 +0,0 @@
|
||||
/* Output generating routines for GDB CLI.
|
||||
|
||||
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Cygnus Solutions.
|
||||
Written by Fernando Nasser for Cygnus.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "ui-out.h"
|
||||
#include "cli-out.h"
|
||||
#include "gdb_string.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
struct ui_out_data
|
||||
{
|
||||
struct ui_file *stream;
|
||||
int suppress_output;
|
||||
};
|
||||
|
||||
/* These are the CLI output functions */
|
||||
|
||||
static void cli_table_begin (struct ui_out *uiout, int nbrofcols,
|
||||
int nr_rows, const char *tblid);
|
||||
static void cli_table_body (struct ui_out *uiout);
|
||||
static void cli_table_end (struct ui_out *uiout);
|
||||
static void cli_table_header (struct ui_out *uiout, int width,
|
||||
enum ui_align alig, const char *col_name,
|
||||
const char *colhdr);
|
||||
static void cli_begin (struct ui_out *uiout, enum ui_out_type type,
|
||||
int level, const char *lstid);
|
||||
static void cli_end (struct ui_out *uiout, enum ui_out_type type, int level);
|
||||
static void cli_field_int (struct ui_out *uiout, int fldno, int width,
|
||||
enum ui_align alig, const char *fldname, int value);
|
||||
static void cli_field_skip (struct ui_out *uiout, int fldno, int width,
|
||||
enum ui_align alig, const char *fldname);
|
||||
static void cli_field_string (struct ui_out *uiout, int fldno, int width,
|
||||
enum ui_align alig, const char *fldname,
|
||||
const char *string);
|
||||
static void cli_field_fmt (struct ui_out *uiout, int fldno,
|
||||
int width, enum ui_align align,
|
||||
const char *fldname, const char *format,
|
||||
va_list args);
|
||||
static void cli_spaces (struct ui_out *uiout, int numspaces);
|
||||
static void cli_text (struct ui_out *uiout, const char *string);
|
||||
static void cli_message (struct ui_out *uiout, int verbosity,
|
||||
const char *format, va_list args);
|
||||
static void cli_wrap_hint (struct ui_out *uiout, char *identstring);
|
||||
static void cli_flush (struct ui_out *uiout);
|
||||
|
||||
/* This is the CLI ui-out implementation functions vector */
|
||||
|
||||
/* FIXME: This can be initialized dynamically after default is set to
|
||||
handle initial output in main.c */
|
||||
|
||||
static struct ui_out_impl cli_ui_out_impl =
|
||||
{
|
||||
cli_table_begin,
|
||||
cli_table_body,
|
||||
cli_table_end,
|
||||
cli_table_header,
|
||||
cli_begin,
|
||||
cli_end,
|
||||
cli_field_int,
|
||||
cli_field_skip,
|
||||
cli_field_string,
|
||||
cli_field_fmt,
|
||||
cli_spaces,
|
||||
cli_text,
|
||||
cli_message,
|
||||
cli_wrap_hint,
|
||||
cli_flush,
|
||||
0, /* Does not need MI hacks (i.e. needs CLI hacks). */
|
||||
};
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
extern void _initialize_cli_out (void);
|
||||
|
||||
static void field_separator (void);
|
||||
|
||||
static void out_field_fmt (struct ui_out *uiout, int fldno,
|
||||
const char *fldname,
|
||||
const char *format,...);
|
||||
|
||||
/* local variables */
|
||||
|
||||
/* (none yet) */
|
||||
|
||||
/* Mark beginning of a table */
|
||||
|
||||
void
|
||||
cli_table_begin (struct ui_out *uiout, int nbrofcols,
|
||||
int nr_rows,
|
||||
const char *tblid)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (nr_rows == 0)
|
||||
data->suppress_output = 1;
|
||||
else
|
||||
/* Only the table suppresses the output and, fortunatly, a table
|
||||
is not a recursive data structure. */
|
||||
gdb_assert (data->suppress_output == 0);
|
||||
}
|
||||
|
||||
/* Mark beginning of a table body */
|
||||
|
||||
void
|
||||
cli_table_body (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
/* first, close the table header line */
|
||||
cli_text (uiout, "\n");
|
||||
}
|
||||
|
||||
/* Mark end of a table */
|
||||
|
||||
void
|
||||
cli_table_end (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
data->suppress_output = 0;
|
||||
}
|
||||
|
||||
/* Specify table header */
|
||||
|
||||
void
|
||||
cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
|
||||
const char *col_name,
|
||||
const char *colhdr)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
cli_field_string (uiout, 0, width, alignment, 0, colhdr);
|
||||
}
|
||||
|
||||
/* Mark beginning of a list */
|
||||
|
||||
void
|
||||
cli_begin (struct ui_out *uiout,
|
||||
enum ui_out_type type,
|
||||
int level,
|
||||
const char *id)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Mark end of a list */
|
||||
|
||||
void
|
||||
cli_end (struct ui_out *uiout,
|
||||
enum ui_out_type type,
|
||||
int level)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
}
|
||||
|
||||
/* output an int field */
|
||||
|
||||
void
|
||||
cli_field_int (struct ui_out *uiout, int fldno, int width,
|
||||
enum ui_align alignment,
|
||||
const char *fldname, int value)
|
||||
{
|
||||
char buffer[20]; /* FIXME: how many chars long a %d can become? */
|
||||
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
sprintf (buffer, "%d", value);
|
||||
cli_field_string (uiout, fldno, width, alignment, fldname, buffer);
|
||||
}
|
||||
|
||||
/* used to ommit a field */
|
||||
|
||||
void
|
||||
cli_field_skip (struct ui_out *uiout, int fldno, int width,
|
||||
enum ui_align alignment,
|
||||
const char *fldname)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
cli_field_string (uiout, fldno, width, alignment, fldname, "");
|
||||
}
|
||||
|
||||
/* other specific cli_field_* end up here so alignment and field
|
||||
separators are both handled by cli_field_string */
|
||||
|
||||
void
|
||||
cli_field_string (struct ui_out *uiout,
|
||||
int fldno,
|
||||
int width,
|
||||
enum ui_align align,
|
||||
const char *fldname,
|
||||
const char *string)
|
||||
{
|
||||
int before = 0;
|
||||
int after = 0;
|
||||
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
|
||||
if ((align != ui_noalign) && string)
|
||||
{
|
||||
before = width - strlen (string);
|
||||
if (before <= 0)
|
||||
before = 0;
|
||||
else
|
||||
{
|
||||
if (align == ui_right)
|
||||
after = 0;
|
||||
else if (align == ui_left)
|
||||
{
|
||||
after = before;
|
||||
before = 0;
|
||||
}
|
||||
else
|
||||
/* ui_center */
|
||||
{
|
||||
after = before / 2;
|
||||
before -= after;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (before)
|
||||
ui_out_spaces (uiout, before);
|
||||
if (string)
|
||||
out_field_fmt (uiout, fldno, fldname, "%s", string);
|
||||
if (after)
|
||||
ui_out_spaces (uiout, after);
|
||||
|
||||
if (align != ui_noalign)
|
||||
field_separator ();
|
||||
}
|
||||
|
||||
/* This is the only field function that does not align */
|
||||
|
||||
void
|
||||
cli_field_fmt (struct ui_out *uiout, int fldno,
|
||||
int width, enum ui_align align,
|
||||
const char *fldname,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
|
||||
vfprintf_filtered (data->stream, format, args);
|
||||
|
||||
if (align != ui_noalign)
|
||||
field_separator ();
|
||||
}
|
||||
|
||||
void
|
||||
cli_spaces (struct ui_out *uiout, int numspaces)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
print_spaces_filtered (numspaces, data->stream);
|
||||
}
|
||||
|
||||
void
|
||||
cli_text (struct ui_out *uiout, const char *string)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
fputs_filtered (string, data->stream);
|
||||
}
|
||||
|
||||
void
|
||||
cli_message (struct ui_out *uiout, int verbosity,
|
||||
const char *format, va_list args)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
if (ui_out_get_verblvl (uiout) >= verbosity)
|
||||
vfprintf_unfiltered (data->stream, format, args);
|
||||
}
|
||||
|
||||
void
|
||||
cli_wrap_hint (struct ui_out *uiout, char *identstring)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
wrap_here (identstring);
|
||||
}
|
||||
|
||||
void
|
||||
cli_flush (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
gdb_flush (data->stream);
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
|
||||
/* Like cli_field_fmt, but takes a variable number of args
|
||||
and makes a va_list and does not insert a separator */
|
||||
|
||||
/* VARARGS */
|
||||
static void
|
||||
out_field_fmt (struct ui_out *uiout, int fldno,
|
||||
const char *fldname,
|
||||
const char *format,...)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
vfprintf_filtered (data->stream, format, args);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* access to ui_out format private members */
|
||||
|
||||
static void
|
||||
field_separator (void)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
fputc_filtered (' ', data->stream);
|
||||
}
|
||||
|
||||
/* initalize private members at startup */
|
||||
|
||||
struct ui_out *
|
||||
cli_out_new (struct ui_file *stream)
|
||||
{
|
||||
int flags = ui_source_list;
|
||||
|
||||
struct ui_out_data *data = XMALLOC (struct ui_out_data);
|
||||
data->stream = stream;
|
||||
data->suppress_output = 0;
|
||||
return ui_out_new (&cli_ui_out_impl, data, flags);
|
||||
}
|
||||
|
||||
/* standard gdb initialization hook */
|
||||
void
|
||||
_initialize_cli_out (void)
|
||||
{
|
||||
/* nothing needs to be done */
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/* Output generating routines for GDB CLI.
|
||||
Copyright 1999, 2000 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef CLI_OUT_H
|
||||
#define CLI_OUT_H
|
||||
|
||||
extern struct ui_out *cli_out_new (struct ui_file *stream);
|
||||
|
||||
#endif
|
||||
@@ -1,838 +0,0 @@
|
||||
/* GDB CLI commands.
|
||||
|
||||
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "completer.h"
|
||||
#include "target.h" /* For baud_rate, remote_debug and remote_timeout */
|
||||
#include "gdb_wait.h" /* For shell escape implementation */
|
||||
#include "gdb_regex.h" /* Used by apropos_command */
|
||||
#include "filenames.h" /* for DOSish file names */
|
||||
|
||||
#include "ui-out.h"
|
||||
|
||||
#include "top.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-script.h"
|
||||
#include "cli/cli-setshow.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
|
||||
#ifndef GDBINIT_FILENAME
|
||||
#define GDBINIT_FILENAME ".gdbinit"
|
||||
#endif
|
||||
|
||||
/* From gdb/top.c */
|
||||
|
||||
extern void dont_repeat (void);
|
||||
|
||||
extern void set_verbose (char *, int, struct cmd_list_element *);
|
||||
|
||||
extern void show_history (char *, int);
|
||||
|
||||
extern void set_history (char *, int);
|
||||
|
||||
extern void show_commands (char *, int);
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void complete_command (char *, int);
|
||||
|
||||
static void echo_command (char *, int);
|
||||
|
||||
static void pwd_command (char *, int);
|
||||
|
||||
static void show_version (char *, int);
|
||||
|
||||
static void validate_comname (char *);
|
||||
|
||||
static void help_command (char *, int);
|
||||
|
||||
static void show_command (char *, int);
|
||||
|
||||
static void info_command (char *, int);
|
||||
|
||||
static void show_debug (char *, int);
|
||||
|
||||
static void set_debug (char *, int);
|
||||
|
||||
static void show_user (char *, int);
|
||||
|
||||
static void make_command (char *, int);
|
||||
|
||||
static void shell_escape (char *, int);
|
||||
|
||||
void apropos_command (char *, int);
|
||||
|
||||
/* Limit the call depth of user-defined commands */
|
||||
int max_user_call_depth;
|
||||
|
||||
/* Define all cmd_list_elements. */
|
||||
|
||||
/* Chain containing all defined commands. */
|
||||
|
||||
struct cmd_list_element *cmdlist;
|
||||
|
||||
/* Chain containing all defined info subcommands. */
|
||||
|
||||
struct cmd_list_element *infolist;
|
||||
|
||||
/* Chain containing all defined enable subcommands. */
|
||||
|
||||
struct cmd_list_element *enablelist;
|
||||
|
||||
/* Chain containing all defined disable subcommands. */
|
||||
|
||||
struct cmd_list_element *disablelist;
|
||||
|
||||
/* Chain containing all defined toggle subcommands. */
|
||||
|
||||
struct cmd_list_element *togglelist;
|
||||
|
||||
/* Chain containing all defined stop subcommands. */
|
||||
|
||||
struct cmd_list_element *stoplist;
|
||||
|
||||
/* Chain containing all defined delete subcommands. */
|
||||
|
||||
struct cmd_list_element *deletelist;
|
||||
|
||||
/* Chain containing all defined "enable breakpoint" subcommands. */
|
||||
|
||||
struct cmd_list_element *enablebreaklist;
|
||||
|
||||
/* Chain containing all defined set subcommands */
|
||||
|
||||
struct cmd_list_element *setlist;
|
||||
|
||||
/* Chain containing all defined unset subcommands */
|
||||
|
||||
struct cmd_list_element *unsetlist;
|
||||
|
||||
/* Chain containing all defined show subcommands. */
|
||||
|
||||
struct cmd_list_element *showlist;
|
||||
|
||||
/* Chain containing all defined \"set history\". */
|
||||
|
||||
struct cmd_list_element *sethistlist;
|
||||
|
||||
/* Chain containing all defined \"show history\". */
|
||||
|
||||
struct cmd_list_element *showhistlist;
|
||||
|
||||
/* Chain containing all defined \"unset history\". */
|
||||
|
||||
struct cmd_list_element *unsethistlist;
|
||||
|
||||
/* Chain containing all defined maintenance subcommands. */
|
||||
|
||||
struct cmd_list_element *maintenancelist;
|
||||
|
||||
/* Chain containing all defined "maintenance info" subcommands. */
|
||||
|
||||
struct cmd_list_element *maintenanceinfolist;
|
||||
|
||||
/* Chain containing all defined "maintenance print" subcommands. */
|
||||
|
||||
struct cmd_list_element *maintenanceprintlist;
|
||||
|
||||
struct cmd_list_element *setprintlist;
|
||||
|
||||
struct cmd_list_element *showprintlist;
|
||||
|
||||
struct cmd_list_element *setdebuglist;
|
||||
|
||||
struct cmd_list_element *showdebuglist;
|
||||
|
||||
struct cmd_list_element *setchecklist;
|
||||
|
||||
struct cmd_list_element *showchecklist;
|
||||
|
||||
/* Utility used everywhere when at least one argument is needed and
|
||||
none is supplied. */
|
||||
|
||||
void
|
||||
error_no_arg (char *why)
|
||||
{
|
||||
error ("Argument required (%s).", why);
|
||||
}
|
||||
|
||||
/* The "info" command is defined as a prefix, with allow_unknown = 0.
|
||||
Therefore, its own definition is called only for "info" with no args. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
info_command (char *arg, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"info\" must be followed by the name of an info command.\n");
|
||||
help_list (infolist, "info ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
/* The "show" command with no arguments shows all the settings. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_command (char *arg, int from_tty)
|
||||
{
|
||||
cmd_show_list (showlist, from_tty, "");
|
||||
}
|
||||
|
||||
/* Provide documentation on command or list given by COMMAND. FROM_TTY
|
||||
is ignored. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
help_command (char *command, int from_tty)
|
||||
{
|
||||
help_cmd (command, gdb_stdout);
|
||||
}
|
||||
|
||||
/* String compare function for qsort. */
|
||||
static int
|
||||
compare_strings (const void *arg1, const void *arg2)
|
||||
{
|
||||
const char **s1 = (const char **) arg1;
|
||||
const char **s2 = (const char **) arg2;
|
||||
return strcmp (*s1, *s2);
|
||||
}
|
||||
|
||||
/* The "complete" command is used by Emacs to implement completion. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
complete_command (char *arg, int from_tty)
|
||||
{
|
||||
int i;
|
||||
int argpoint;
|
||||
char **completions;
|
||||
|
||||
dont_repeat ();
|
||||
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
argpoint = strlen (arg);
|
||||
|
||||
completions = complete_line (arg, arg, argpoint);
|
||||
|
||||
if (completions)
|
||||
{
|
||||
int item, size;
|
||||
|
||||
for (size = 0; completions[size]; ++size)
|
||||
;
|
||||
qsort (completions, size, sizeof (char *), compare_strings);
|
||||
|
||||
/* We do extra processing here since we only want to print each
|
||||
unique item once. */
|
||||
item = 0;
|
||||
while (item < size)
|
||||
{
|
||||
int next_item;
|
||||
printf_unfiltered ("%s\n", completions[item]);
|
||||
next_item = item + 1;
|
||||
while (next_item < size
|
||||
&& ! strcmp (completions[item], completions[next_item]))
|
||||
{
|
||||
xfree (completions[next_item]);
|
||||
++next_item;
|
||||
}
|
||||
|
||||
xfree (completions[item]);
|
||||
item = next_item;
|
||||
}
|
||||
|
||||
xfree (completions);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
is_complete_command (struct cmd_list_element *c)
|
||||
{
|
||||
return cmd_cfunc_eq (c, complete_command);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_version (char *args, int from_tty)
|
||||
{
|
||||
immediate_quit++;
|
||||
print_gdb_version (gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
immediate_quit--;
|
||||
}
|
||||
|
||||
/* Handle the quit command. */
|
||||
|
||||
void
|
||||
quit_command (char *args, int from_tty)
|
||||
{
|
||||
if (!quit_confirm ())
|
||||
error ("Not confirmed.");
|
||||
quit_force (args, from_tty);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
pwd_command (char *args, int from_tty)
|
||||
{
|
||||
if (args)
|
||||
error ("The \"pwd\" command does not take an argument: %s", args);
|
||||
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
|
||||
|
||||
if (!STREQ (gdb_dirbuf, current_directory))
|
||||
printf_unfiltered ("Working directory %s\n (canonically %s).\n",
|
||||
current_directory, gdb_dirbuf);
|
||||
else
|
||||
printf_unfiltered ("Working directory %s.\n", current_directory);
|
||||
}
|
||||
|
||||
void
|
||||
cd_command (char *dir, int from_tty)
|
||||
{
|
||||
int len;
|
||||
/* Found something other than leading repetitions of "/..". */
|
||||
int found_real_path;
|
||||
char *p;
|
||||
|
||||
/* If the new directory is absolute, repeat is a no-op; if relative,
|
||||
repeat might be useful but is more likely to be a mistake. */
|
||||
dont_repeat ();
|
||||
|
||||
if (dir == 0)
|
||||
error_no_arg ("new working directory");
|
||||
|
||||
dir = tilde_expand (dir);
|
||||
make_cleanup (xfree, dir);
|
||||
|
||||
if (chdir (dir) < 0)
|
||||
perror_with_name (dir);
|
||||
|
||||
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|
||||
/* There's too much mess with DOSish names like "d:", "d:.",
|
||||
"d:./foo" etc. Instead of having lots of special #ifdef'ed code,
|
||||
simply get the canonicalized name of the current directory. */
|
||||
dir = getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
|
||||
#endif
|
||||
|
||||
len = strlen (dir);
|
||||
if (IS_DIR_SEPARATOR (dir[len - 1]))
|
||||
{
|
||||
/* Remove the trailing slash unless this is a root directory
|
||||
(including a drive letter on non-Unix systems). */
|
||||
if (!(len == 1) /* "/" */
|
||||
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|
||||
&& !(len == 3 && dir[1] == ':') /* "d:/" */
|
||||
#endif
|
||||
)
|
||||
len--;
|
||||
}
|
||||
|
||||
dir = savestring (dir, len);
|
||||
if (IS_ABSOLUTE_PATH (dir))
|
||||
current_directory = dir;
|
||||
else
|
||||
{
|
||||
if (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]))
|
||||
current_directory = concat (current_directory, dir, NULL);
|
||||
else
|
||||
current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
|
||||
xfree (dir);
|
||||
}
|
||||
|
||||
/* Now simplify any occurrences of `.' and `..' in the pathname. */
|
||||
|
||||
found_real_path = 0;
|
||||
for (p = current_directory; *p;)
|
||||
{
|
||||
if (IS_DIR_SEPARATOR (p[0]) && p[1] == '.'
|
||||
&& (p[2] == 0 || IS_DIR_SEPARATOR (p[2])))
|
||||
strcpy (p, p + 2);
|
||||
else if (IS_DIR_SEPARATOR (p[0]) && p[1] == '.' && p[2] == '.'
|
||||
&& (p[3] == 0 || IS_DIR_SEPARATOR (p[3])))
|
||||
{
|
||||
if (found_real_path)
|
||||
{
|
||||
/* Search backwards for the directory just before the "/.."
|
||||
and obliterate it and the "/..". */
|
||||
char *q = p;
|
||||
while (q != current_directory && !IS_DIR_SEPARATOR (q[-1]))
|
||||
--q;
|
||||
|
||||
if (q == current_directory)
|
||||
/* current_directory is
|
||||
a relative pathname ("can't happen"--leave it alone). */
|
||||
++p;
|
||||
else
|
||||
{
|
||||
strcpy (q - 1, p + 3);
|
||||
p = q - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* We are dealing with leading repetitions of "/..", for example
|
||||
"/../..", which is the Mach super-root. */
|
||||
p += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
found_real_path = 1;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
forget_cached_source_info ();
|
||||
|
||||
if (from_tty)
|
||||
pwd_command ((char *) 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
source_command (char *args, int from_tty)
|
||||
{
|
||||
FILE *stream;
|
||||
struct cleanup *old_cleanups;
|
||||
char *file = args;
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
error ("source command requires pathname of file to source.");
|
||||
}
|
||||
|
||||
file = tilde_expand (file);
|
||||
old_cleanups = make_cleanup (xfree, file);
|
||||
|
||||
stream = fopen (file, FOPEN_RT);
|
||||
if (!stream)
|
||||
{
|
||||
if (from_tty)
|
||||
perror_with_name (file);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
script_from_file (stream, file);
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
echo_command (char *text, int from_tty)
|
||||
{
|
||||
char *p = text;
|
||||
register int c;
|
||||
|
||||
if (text)
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
if (c == '\\')
|
||||
{
|
||||
/* \ at end of argument is used after spaces
|
||||
so they won't be lost. */
|
||||
if (*p == 0)
|
||||
return;
|
||||
|
||||
c = parse_escape (&p);
|
||||
if (c >= 0)
|
||||
printf_filtered ("%c", c);
|
||||
}
|
||||
else
|
||||
printf_filtered ("%c", c);
|
||||
}
|
||||
|
||||
/* Force this output to appear now. */
|
||||
wrap_here ("");
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
shell_escape (char *arg, int from_tty)
|
||||
{
|
||||
#ifdef CANT_FORK
|
||||
/* If ARG is NULL, they want an inferior shell, but `system' just
|
||||
reports if the shell is available when passed a NULL arg. */
|
||||
int rc = system (arg ? arg : "");
|
||||
|
||||
if (!arg)
|
||||
arg = "inferior shell";
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", arg,
|
||||
safe_strerror (errno));
|
||||
gdb_flush (gdb_stderr);
|
||||
}
|
||||
else if (rc)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "%s exited with status %d\n", arg, rc);
|
||||
gdb_flush (gdb_stderr);
|
||||
}
|
||||
#ifdef GLOBAL_CURDIR
|
||||
/* Make sure to return to the directory GDB thinks it is, in case the
|
||||
shell command we just ran changed it. */
|
||||
chdir (current_directory);
|
||||
#endif
|
||||
#else /* Can fork. */
|
||||
int rc, status, pid;
|
||||
char *p, *user_shell;
|
||||
|
||||
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
|
||||
user_shell = "/bin/sh";
|
||||
|
||||
/* Get the name of the shell for arg0 */
|
||||
if ((p = strrchr (user_shell, '/')) == NULL)
|
||||
p = user_shell;
|
||||
else
|
||||
p++; /* Get past '/' */
|
||||
|
||||
if ((pid = fork ()) == 0)
|
||||
{
|
||||
if (!arg)
|
||||
execl (user_shell, p, 0);
|
||||
else
|
||||
execl (user_shell, p, "-c", arg, 0);
|
||||
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
|
||||
safe_strerror (errno));
|
||||
gdb_flush (gdb_stderr);
|
||||
_exit (0177);
|
||||
}
|
||||
|
||||
if (pid != -1)
|
||||
while ((rc = wait (&status)) != pid && rc != -1)
|
||||
;
|
||||
else
|
||||
error ("Fork failed");
|
||||
#endif /* Can fork. */
|
||||
}
|
||||
|
||||
static void
|
||||
make_command (char *arg, int from_tty)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (arg == 0)
|
||||
p = "make";
|
||||
else
|
||||
{
|
||||
p = xmalloc (sizeof ("make ") + strlen (arg));
|
||||
strcpy (p, "make ");
|
||||
strcpy (p + sizeof ("make ") - 1, arg);
|
||||
}
|
||||
|
||||
shell_escape (p, from_tty);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_user (char *args, int from_tty)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
extern struct cmd_list_element *cmdlist;
|
||||
|
||||
if (args)
|
||||
{
|
||||
c = lookup_cmd (&args, cmdlist, "", 0, 1);
|
||||
if (c->class != class_user)
|
||||
error ("Not a user command.");
|
||||
show_user_1 (c, gdb_stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = cmdlist; c; c = c->next)
|
||||
{
|
||||
if (c->class == class_user)
|
||||
show_user_1 (c, gdb_stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Search through names of commands and documentations for a certain
|
||||
regular expression.
|
||||
*/
|
||||
void
|
||||
apropos_command (char *searchstr, int from_tty)
|
||||
{
|
||||
extern struct cmd_list_element *cmdlist; /*This is the main command list*/
|
||||
regex_t pattern;
|
||||
char *pattern_fastmap;
|
||||
char errorbuffer[512];
|
||||
pattern_fastmap = xcalloc (256, sizeof (char));
|
||||
if (searchstr == NULL)
|
||||
error("REGEXP string is empty");
|
||||
|
||||
if (regcomp(&pattern,searchstr,REG_ICASE) == 0)
|
||||
{
|
||||
pattern.fastmap=pattern_fastmap;
|
||||
re_compile_fastmap(&pattern);
|
||||
apropos_cmd (gdb_stdout,cmdlist,&pattern,"");
|
||||
}
|
||||
else
|
||||
{
|
||||
regerror(regcomp(&pattern,searchstr,REG_ICASE),NULL,errorbuffer,512);
|
||||
error("Error in regular expression:%s",errorbuffer);
|
||||
}
|
||||
xfree (pattern_fastmap);
|
||||
}
|
||||
|
||||
static void
|
||||
set_debug (char *arg, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"set debug\" must be followed by the name of a print subcommand.\n");
|
||||
help_list (setdebuglist, "set debug ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
show_debug (char *args, int from_tty)
|
||||
{
|
||||
cmd_show_list (showdebuglist, from_tty, "");
|
||||
}
|
||||
|
||||
void
|
||||
init_cmd_lists (void)
|
||||
{
|
||||
max_user_call_depth = 1024;
|
||||
|
||||
cmdlist = NULL;
|
||||
infolist = NULL;
|
||||
enablelist = NULL;
|
||||
disablelist = NULL;
|
||||
togglelist = NULL;
|
||||
stoplist = NULL;
|
||||
deletelist = NULL;
|
||||
enablebreaklist = NULL;
|
||||
setlist = NULL;
|
||||
unsetlist = NULL;
|
||||
showlist = NULL;
|
||||
sethistlist = NULL;
|
||||
showhistlist = NULL;
|
||||
unsethistlist = NULL;
|
||||
maintenancelist = NULL;
|
||||
maintenanceinfolist = NULL;
|
||||
maintenanceprintlist = NULL;
|
||||
setprintlist = NULL;
|
||||
showprintlist = NULL;
|
||||
setchecklist = NULL;
|
||||
showchecklist = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
init_cli_cmds (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
|
||||
/* Define the classes of commands.
|
||||
They will appear in the help list in the reverse of this order. */
|
||||
|
||||
add_cmd ("internals", class_maintenance, NULL,
|
||||
"Maintenance commands.\n\
|
||||
Some gdb commands are provided just for use by gdb maintainers.\n\
|
||||
These commands are subject to frequent change, and may not be as\n\
|
||||
well documented as user commands.",
|
||||
&cmdlist);
|
||||
add_cmd ("obscure", class_obscure, NULL, "Obscure features.", &cmdlist);
|
||||
add_cmd ("aliases", class_alias, NULL, "Aliases of other commands.", &cmdlist);
|
||||
add_cmd ("user-defined", class_user, NULL, "User-defined commands.\n\
|
||||
The commands in this class are those defined by the user.\n\
|
||||
Use the \"define\" command to define a command.", &cmdlist);
|
||||
add_cmd ("support", class_support, NULL, "Support facilities.", &cmdlist);
|
||||
if (!dbx_commands)
|
||||
add_cmd ("status", class_info, NULL, "Status inquiries.", &cmdlist);
|
||||
add_cmd ("files", class_files, NULL, "Specifying and examining files.", &cmdlist);
|
||||
add_cmd ("breakpoints", class_breakpoint, NULL, "Making program stop at certain points.", &cmdlist);
|
||||
add_cmd ("data", class_vars, NULL, "Examining data.", &cmdlist);
|
||||
add_cmd ("stack", class_stack, NULL, "Examining the stack.\n\
|
||||
The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\
|
||||
counting from zero for the innermost (currently executing) frame.\n\n\
|
||||
At any time gdb identifies one frame as the \"selected\" frame.\n\
|
||||
Variable lookups are done with respect to the selected frame.\n\
|
||||
When the program being debugged stops, gdb selects the innermost frame.\n\
|
||||
The commands below can be used to select other frames by number or address.",
|
||||
&cmdlist);
|
||||
add_cmd ("running", class_run, NULL, "Running the program.", &cmdlist);
|
||||
|
||||
/* Define general commands. */
|
||||
|
||||
add_com ("pwd", class_files, pwd_command,
|
||||
"Print working directory. This is used for your program as well.");
|
||||
c = add_cmd ("cd", class_files, cd_command,
|
||||
"Set working directory to DIR for debugger and program being debugged.\n\
|
||||
The change does not take effect for the program being debugged\n\
|
||||
until the next time it is started.", &cmdlist);
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
add_com ("echo", class_support, echo_command,
|
||||
"Print a constant string. Give string as argument.\n\
|
||||
C escape sequences may be used in the argument.\n\
|
||||
No newline is added at the end of the argument;\n\
|
||||
use \"\\n\" if you want a newline to be printed.\n\
|
||||
Since leading and trailing whitespace are ignored in command arguments,\n\
|
||||
if you want to print some you must use \"\\\" before leading whitespace\n\
|
||||
to be printed or after trailing whitespace.");
|
||||
add_com ("document", class_support, document_command,
|
||||
"Document a user-defined command.\n\
|
||||
Give command name as argument. Give documentation on following lines.\n\
|
||||
End with a line of just \"end\".");
|
||||
add_com ("define", class_support, define_command,
|
||||
"Define a new command name. Command name is argument.\n\
|
||||
Definition appears on following lines, one command per line.\n\
|
||||
End with a line of just \"end\".\n\
|
||||
Use the \"document\" command to give documentation for the new command.\n\
|
||||
Commands defined in this way may have up to ten arguments.");
|
||||
|
||||
c = add_cmd ("source", class_support, source_command,
|
||||
"Read commands from a file named FILE.\n\
|
||||
Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\
|
||||
when gdb is started.", &cmdlist);
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
add_com ("quit", class_support, quit_command, "Exit gdb.");
|
||||
c = add_com ("help", class_support, help_command, "Print list of commands.");
|
||||
set_cmd_completer (c, command_completer);
|
||||
add_com_alias ("q", "quit", class_support, 1);
|
||||
add_com_alias ("h", "help", class_support, 1);
|
||||
|
||||
c = add_set_cmd ("verbose", class_support, var_boolean, (char *) &info_verbose,
|
||||
"Set ",
|
||||
&setlist),
|
||||
add_show_from_set (c, &showlist);
|
||||
set_cmd_sfunc (c, set_verbose);
|
||||
set_verbose (NULL, 0, c);
|
||||
|
||||
add_prefix_cmd ("history", class_support, set_history,
|
||||
"Generic command for setting command history parameters.",
|
||||
&sethistlist, "set history ", 0, &setlist);
|
||||
add_prefix_cmd ("history", class_support, show_history,
|
||||
"Generic command for showing command history parameters.",
|
||||
&showhistlist, "show history ", 0, &showlist);
|
||||
|
||||
add_show_from_set
|
||||
(add_set_cmd ("expansion", no_class, var_boolean, (char *) &history_expansion_p,
|
||||
"Set history expansion on command input.\n\
|
||||
Without an argument, history expansion is enabled.", &sethistlist),
|
||||
&showhistlist);
|
||||
|
||||
add_prefix_cmd ("info", class_info, info_command,
|
||||
"Generic command for showing things about the program being debugged.",
|
||||
&infolist, "info ", 0, &cmdlist);
|
||||
add_com_alias ("i", "info", class_info, 1);
|
||||
|
||||
add_com ("complete", class_obscure, complete_command,
|
||||
"List the completions for the rest of the line as a command.");
|
||||
|
||||
add_prefix_cmd ("show", class_info, show_command,
|
||||
"Generic command for showing things about the debugger.",
|
||||
&showlist, "show ", 0, &cmdlist);
|
||||
/* Another way to get at the same thing. */
|
||||
add_info ("set", show_command, "Show all GDB settings.");
|
||||
|
||||
add_cmd ("commands", no_class, show_commands,
|
||||
"Show the history of commands you typed.\n\
|
||||
You can supply a command number to start with, or a `+' to start after\n\
|
||||
the previous command number shown.",
|
||||
&showlist);
|
||||
|
||||
add_cmd ("version", no_class, show_version,
|
||||
"Show what version of GDB this is.", &showlist);
|
||||
|
||||
add_com ("while", class_support, while_command,
|
||||
"Execute nested commands WHILE the conditional expression is non zero.\n\
|
||||
The conditional expression must follow the word `while' and must in turn be\n\
|
||||
followed by a new line. The nested commands must be entered one per line,\n\
|
||||
and should be terminated by the word `end'.");
|
||||
|
||||
add_com ("if", class_support, if_command,
|
||||
"Execute nested commands once IF the conditional expression is non zero.\n\
|
||||
The conditional expression must follow the word `if' and must in turn be\n\
|
||||
followed by a new line. The nested commands must be entered one per line,\n\
|
||||
and should be terminated by the word 'else' or `end'. If an else clause\n\
|
||||
is used, the same rules apply to its nested commands as to the first ones.");
|
||||
|
||||
/* If target is open when baud changes, it doesn't take effect until the
|
||||
next open (I think, not sure). */
|
||||
add_show_from_set (add_set_cmd ("remotebaud", no_class,
|
||||
var_zinteger, (char *) &baud_rate,
|
||||
"Set baud rate for remote serial I/O.\n\
|
||||
This value is used to set the speed of the serial port when debugging\n\
|
||||
using remote targets.", &setlist),
|
||||
&showlist);
|
||||
|
||||
c = add_set_cmd ("remotedebug", no_class, var_zinteger,
|
||||
(char *) &remote_debug,
|
||||
"Set debugging of remote protocol.\n\
|
||||
When enabled, each packet sent or received with the remote target\n\
|
||||
is displayed.", &setlist);
|
||||
deprecate_cmd (c, "set debug remote");
|
||||
deprecate_cmd (add_show_from_set (c, &showlist), "show debug remote");
|
||||
|
||||
add_show_from_set (add_set_cmd ("remote", no_class, var_zinteger,
|
||||
(char *) &remote_debug,
|
||||
"Set debugging of remote protocol.\n\
|
||||
When enabled, each packet sent or received with the remote target\n\
|
||||
is displayed.", &setdebuglist),
|
||||
&showdebuglist);
|
||||
|
||||
add_show_from_set (
|
||||
add_set_cmd ("remotetimeout", no_class, var_integer, (char *) &remote_timeout,
|
||||
"Set timeout limit to wait for target to respond.\n\
|
||||
This value is used to set the time limit for gdb to wait for a response\n\
|
||||
from the target.", &setlist),
|
||||
&showlist);
|
||||
|
||||
add_prefix_cmd ("debug", no_class, set_debug,
|
||||
"Generic command for setting gdb debugging flags",
|
||||
&setdebuglist, "set debug ", 0, &setlist);
|
||||
|
||||
add_prefix_cmd ("debug", no_class, show_debug,
|
||||
"Generic command for showing gdb debugging flags",
|
||||
&showdebuglist, "show debug ", 0, &showlist);
|
||||
|
||||
c = 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.");
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
/* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would
|
||||
be a really useful feature. Unfortunately, the below wont do
|
||||
this. Instead it adds support for the form ``(gdb) ! ls''
|
||||
(i.e. the space is required). If the ``!'' command below is
|
||||
added the complains about no ``!'' command would be replaced by
|
||||
complains about how the ``!'' command is broken :-) */
|
||||
if (xdb_commands)
|
||||
add_com_alias ("!", "shell", class_support, 0);
|
||||
|
||||
c = add_com ("make", class_support, make_command,
|
||||
"Run the ``make'' program using the rest of the line as arguments.");
|
||||
set_cmd_completer (c, filename_completer);
|
||||
add_cmd ("user", no_class, show_user,
|
||||
"Show definitions of user defined commands.\n\
|
||||
Argument is the name of the user defined command.\n\
|
||||
With no argument, show definitions of all user defined commands.", &showlist);
|
||||
add_com ("apropos", class_support, apropos_command, "Search for commands matching a REGEXP");
|
||||
|
||||
add_show_from_set (
|
||||
add_set_cmd ("max-user-call-depth", no_class, var_integer,
|
||||
(char *) &max_user_call_depth,
|
||||
"Set the max call depth for user-defined commands.\n",
|
||||
&setlist),
|
||||
&showlist);
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/* Header file for GDB CLI command implementation library.
|
||||
Copyright 2000 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (CLI_CMDS_H)
|
||||
#define CLI_CMDS_H 1
|
||||
|
||||
/* Chain containing all defined commands. */
|
||||
|
||||
extern struct cmd_list_element *cmdlist;
|
||||
|
||||
/* Chain containing all defined info subcommands. */
|
||||
|
||||
extern struct cmd_list_element *infolist;
|
||||
|
||||
/* Chain containing all defined enable subcommands. */
|
||||
|
||||
extern struct cmd_list_element *enablelist;
|
||||
|
||||
/* Chain containing all defined disable subcommands. */
|
||||
|
||||
extern struct cmd_list_element *disablelist;
|
||||
|
||||
/* Chain containing all defined delete subcommands. */
|
||||
|
||||
extern struct cmd_list_element *deletelist;
|
||||
|
||||
/* Chain containing all defined toggle subcommands. */
|
||||
|
||||
extern struct cmd_list_element *togglelist;
|
||||
|
||||
/* Chain containing all defined stop subcommands. */
|
||||
|
||||
extern struct cmd_list_element *stoplist;
|
||||
|
||||
/* Chain containing all defined "enable breakpoint" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *enablebreaklist;
|
||||
|
||||
/* Chain containing all defined set subcommands */
|
||||
|
||||
extern struct cmd_list_element *setlist;
|
||||
|
||||
/* Chain containing all defined unset subcommands */
|
||||
|
||||
extern struct cmd_list_element *unsetlist;
|
||||
|
||||
/* Chain containing all defined show subcommands. */
|
||||
|
||||
extern struct cmd_list_element *showlist;
|
||||
|
||||
/* Chain containing all defined \"set history\". */
|
||||
|
||||
extern struct cmd_list_element *sethistlist;
|
||||
|
||||
/* Chain containing all defined \"show history\". */
|
||||
|
||||
extern struct cmd_list_element *showhistlist;
|
||||
|
||||
/* Chain containing all defined \"unset history\". */
|
||||
|
||||
extern struct cmd_list_element *unsethistlist;
|
||||
|
||||
/* Chain containing all defined maintenance subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenancelist;
|
||||
|
||||
/* Chain containing all defined "maintenance info" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenanceinfolist;
|
||||
|
||||
/* Chain containing all defined "maintenance print" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenanceprintlist;
|
||||
|
||||
extern struct cmd_list_element *setprintlist;
|
||||
|
||||
extern struct cmd_list_element *showprintlist;
|
||||
|
||||
extern struct cmd_list_element *setdebuglist;
|
||||
|
||||
extern struct cmd_list_element *showdebuglist;
|
||||
|
||||
extern struct cmd_list_element *setchecklist;
|
||||
|
||||
extern struct cmd_list_element *showchecklist;
|
||||
|
||||
/* Exported to gdb/top.c */
|
||||
|
||||
void init_cmd_lists (void);
|
||||
|
||||
void init_cli_cmds (void);
|
||||
|
||||
int is_complete_command (struct cmd_list_element *cmd);
|
||||
|
||||
/* Exported to gdb/main.c */
|
||||
|
||||
extern void cd_command (char *, int);
|
||||
|
||||
/* Exported to gdb/top.c and gdb/main.c */
|
||||
|
||||
extern void quit_command (char *, int);
|
||||
|
||||
extern void source_command (char *, int);
|
||||
|
||||
/* Used everywhere whenever at least one parameter is required and
|
||||
none is specified. */
|
||||
|
||||
extern NORETURN void error_no_arg (char *) ATTR_NORETURN;
|
||||
|
||||
#endif /* !defined (CLI_CMDS_H) */
|
||||
1527
gdb/cli/cli-decode.c
1527
gdb/cli/cli-decode.c
File diff suppressed because it is too large
Load Diff
@@ -1,321 +0,0 @@
|
||||
/* Header file for GDB command decoding library.
|
||||
Copyright 2000 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (CLI_DECODE_H)
|
||||
#define CLI_DECODE_H 1
|
||||
|
||||
#include "gdb_regex.h" /* Needed by apropos_cmd. */
|
||||
#include "command.h"
|
||||
|
||||
#if 0
|
||||
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
|
||||
cmd_types'' can be moved from "command.h" to "cli-decode.h". */
|
||||
/* Not a set/show command. Note that some commands which begin with
|
||||
"set" or "show" might be in this category, if their syntax does
|
||||
not fall into one of the following categories. */
|
||||
typedef enum cmd_types
|
||||
{
|
||||
not_set_cmd,
|
||||
set_cmd,
|
||||
show_cmd
|
||||
}
|
||||
cmd_types;
|
||||
#endif
|
||||
|
||||
/* This structure records one command'd definition. */
|
||||
|
||||
|
||||
/* This flag is used by the code executing commands to warn the user
|
||||
the first time a deprecated command is used, see the 'flags' field in
|
||||
the following struct.
|
||||
*/
|
||||
#define CMD_DEPRECATED 0x1
|
||||
#define DEPRECATED_WARN_USER 0x2
|
||||
#define MALLOCED_REPLACEMENT 0x4
|
||||
|
||||
struct cmd_list_element
|
||||
{
|
||||
/* Points to next command in this list. */
|
||||
struct cmd_list_element *next;
|
||||
|
||||
/* Name of this command. */
|
||||
char *name;
|
||||
|
||||
/* Command class; class values are chosen by application program. */
|
||||
enum command_class class;
|
||||
|
||||
/* Function definition of this command. NULL for command class
|
||||
names and for help topics that are not really commands. NOTE:
|
||||
cagney/2002-02-02: This function signature is evolving. For
|
||||
the moment suggest sticking with either set_cmd_cfunc() or
|
||||
set_cmd_sfunc(). */
|
||||
void (*func) (struct cmd_list_element *c, char *args, int from_tty);
|
||||
/* The command's real callback. At present func() bounces through
|
||||
to one of the below. */
|
||||
union
|
||||
{
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
cmd_cfunc_ftype *cfunc;
|
||||
/* If type is set_cmd or show_cmd, first set the variables,
|
||||
and then call this: */
|
||||
cmd_sfunc_ftype *sfunc;
|
||||
}
|
||||
function;
|
||||
|
||||
/* Local state (context) for this command. This can be anything. */
|
||||
void *context;
|
||||
|
||||
/* Documentation of this command (or help topic).
|
||||
First line is brief documentation; remaining lines form, with it,
|
||||
the full documentation. First line should end with a period.
|
||||
Entire string should also end with a period, not a newline. */
|
||||
char *doc;
|
||||
|
||||
/* flags : a bitfield
|
||||
|
||||
bit 0: (LSB) CMD_DEPRECATED, when 1 indicated that this command
|
||||
is deprecated. It may be removed from gdb's command set in the
|
||||
future.
|
||||
|
||||
bit 1: DEPRECATED_WARN_USER, the user needs to be warned that
|
||||
this is a deprecated command. The user should only be warned
|
||||
the first time a command is used.
|
||||
|
||||
bit 2: MALLOCED_REPLACEMENT, when functions are deprecated at
|
||||
compile time (this is the way it should, in general, be done)
|
||||
the memory containing the replacement string is statically
|
||||
allocated. In some cases it makes sense to deprecate commands
|
||||
at runtime (the testsuite is one example). In this case the
|
||||
memory for replacement is malloc'ed. When a command is
|
||||
undeprecated or re-deprecated at runtime we don't want to risk
|
||||
calling free on statically allocated memory, so we check this
|
||||
flag.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/* if this command is deprecated, this is the replacement name */
|
||||
char *replacement;
|
||||
|
||||
/* If this command represents a show command, then this function
|
||||
is called before the variable's value is examined. */
|
||||
void (*pre_show_hook) (struct cmd_list_element *c);
|
||||
|
||||
/* Hook for another command to be executed before this command. */
|
||||
struct cmd_list_element *hook_pre;
|
||||
|
||||
/* Hook for another command to be executed after this command. */
|
||||
struct cmd_list_element *hook_post;
|
||||
|
||||
/* Flag that specifies if this command is already running it's hook. */
|
||||
/* Prevents the possibility of hook recursion. */
|
||||
int hook_in;
|
||||
|
||||
/* Nonzero identifies a prefix command. For them, the address
|
||||
of the variable containing the list of subcommands. */
|
||||
struct cmd_list_element **prefixlist;
|
||||
|
||||
/* For prefix commands only:
|
||||
String containing prefix commands to get here: this one
|
||||
plus any others needed to get to it. Should end in a space.
|
||||
It is used before the word "command" in describing the
|
||||
commands reached through this prefix. */
|
||||
char *prefixname;
|
||||
|
||||
/* For prefix commands only:
|
||||
nonzero means do not get an error if subcommand is not
|
||||
recognized; call the prefix's own function in that case. */
|
||||
char allow_unknown;
|
||||
|
||||
/* Nonzero says this is an abbreviation, and should not
|
||||
be mentioned in lists of commands.
|
||||
This allows "br<tab>" to complete to "break", which it
|
||||
otherwise wouldn't. */
|
||||
char abbrev_flag;
|
||||
|
||||
/* Completion routine for this command. TEXT is the text beyond
|
||||
what was matched for the command itself (leading whitespace is
|
||||
skipped). It stops where we are supposed to stop completing
|
||||
(rl_point) and is '\0' terminated.
|
||||
|
||||
Return value is a malloc'd vector of pointers to possible completions
|
||||
terminated with NULL. If there are no completions, returning a pointer
|
||||
to a NULL would work but returning NULL itself is also valid.
|
||||
WORD points in the same buffer as TEXT, and completions should be
|
||||
returned relative to this position. For example, suppose TEXT is "foo"
|
||||
and we want to complete to "foobar". If WORD is "oo", return
|
||||
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
||||
char **(*completer) (char *text, char *word);
|
||||
|
||||
/* Type of "set" or "show" command (or SET_NOT_SET if not "set"
|
||||
or "show"). */
|
||||
cmd_types type;
|
||||
|
||||
/* Pointer to variable affected by "set" and "show". Doesn't matter
|
||||
if type is not_set. */
|
||||
void *var;
|
||||
|
||||
/* What kind of variable is *VAR? */
|
||||
var_types var_type;
|
||||
|
||||
/* Pointer to NULL terminated list of enumerated values (like argv). */
|
||||
const char **enums;
|
||||
|
||||
/* Pointer to command strings of user-defined commands */
|
||||
struct command_line *user_commands;
|
||||
|
||||
/* Pointer to command that is hooked by this one, (by hook_pre)
|
||||
so the hook can be removed when this one is deleted. */
|
||||
struct cmd_list_element *hookee_pre;
|
||||
|
||||
/* Pointer to command that is hooked by this one, (by hook_post)
|
||||
so the hook can be removed when this one is deleted. */
|
||||
struct cmd_list_element *hookee_post;
|
||||
|
||||
/* Pointer to command that is aliased by this one, so the
|
||||
aliased command can be located in case it has been hooked. */
|
||||
struct cmd_list_element *cmd_pointer;
|
||||
};
|
||||
|
||||
/* API to the manipulation of command lists. */
|
||||
|
||||
extern struct cmd_list_element *add_cmd (char *, enum command_class,
|
||||
void (*fun) (char *, int), char *,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_alias_cmd (char *, char *,
|
||||
enum command_class, int,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_prefix_cmd (char *, enum command_class,
|
||||
void (*fun) (char *, int),
|
||||
char *,
|
||||
struct cmd_list_element **,
|
||||
char *, int,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_abbrev_prefix_cmd (char *,
|
||||
enum command_class,
|
||||
void (*fun) (char *,
|
||||
int),
|
||||
char *,
|
||||
struct cmd_list_element
|
||||
**, char *, int,
|
||||
struct cmd_list_element
|
||||
**);
|
||||
|
||||
/* Set the commands corresponding callback. */
|
||||
|
||||
extern void set_cmd_cfunc (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
|
||||
extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||
void (*sfunc) (char *args, int from_tty,
|
||||
struct cmd_list_element * c));
|
||||
|
||||
extern void set_cmd_completer (struct cmd_list_element *cmd,
|
||||
char **(*completer) (char *text, char *word));
|
||||
|
||||
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
|
||||
around in cmd objects to test the value of the commands sfunc(). */
|
||||
extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
|
||||
/* Access to the command's local context. */
|
||||
extern void set_cmd_context (struct cmd_list_element *cmd, void *context);
|
||||
extern void *get_cmd_context (struct cmd_list_element *cmd);
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd (char **,
|
||||
struct cmd_list_element *, char *,
|
||||
int, int);
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd_1 (char **,
|
||||
struct cmd_list_element *,
|
||||
struct cmd_list_element **,
|
||||
int);
|
||||
|
||||
extern struct cmd_list_element *
|
||||
deprecate_cmd (struct cmd_list_element *, char * );
|
||||
|
||||
extern void
|
||||
deprecated_cmd_warning (char **);
|
||||
|
||||
extern int
|
||||
lookup_cmd_composition (char *text,
|
||||
struct cmd_list_element **alias,
|
||||
struct cmd_list_element **prefix_cmd,
|
||||
struct cmd_list_element **cmd);
|
||||
|
||||
extern struct cmd_list_element *add_com (char *, enum command_class,
|
||||
void (*fun) (char *, int), char *);
|
||||
|
||||
extern struct cmd_list_element *add_com_alias (char *, char *,
|
||||
enum command_class, int);
|
||||
|
||||
extern struct cmd_list_element *add_info (char *, void (*fun) (char *, int),
|
||||
char *);
|
||||
|
||||
extern struct cmd_list_element *add_info_alias (char *, char *, int);
|
||||
|
||||
extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *);
|
||||
|
||||
extern char **complete_on_enum (const char *enumlist[], char *, char *);
|
||||
|
||||
extern void delete_cmd (char *, struct cmd_list_element **);
|
||||
|
||||
extern void help_cmd_list (struct cmd_list_element *, enum command_class,
|
||||
char *, int, struct ui_file *);
|
||||
|
||||
extern struct cmd_list_element *add_set_cmd (char *name, enum
|
||||
command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_set_enum_cmd (char *name,
|
||||
enum command_class class,
|
||||
const char *enumlist[],
|
||||
const char **var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_show_from_set (struct cmd_list_element *,
|
||||
struct cmd_list_element
|
||||
**);
|
||||
|
||||
/* Functions that implement commands about CLI commands. */
|
||||
|
||||
extern void help_cmd (char *, struct ui_file *);
|
||||
|
||||
extern void help_list (struct cmd_list_element *, char *,
|
||||
enum command_class, struct ui_file *);
|
||||
|
||||
extern void apropos_cmd (struct ui_file *, struct cmd_list_element *,
|
||||
struct re_pattern_buffer *, char *);
|
||||
|
||||
/* Used to mark commands that don't do anything. If we just leave the
|
||||
function field NULL, the command is interpreted as a help topic, or
|
||||
as a class of commands. */
|
||||
|
||||
extern void not_just_help_class_command (char *arg, int from_tty);
|
||||
|
||||
/* Exported to cli/cli-setshow.c */
|
||||
|
||||
extern void print_doc_line (struct ui_file *, char *);
|
||||
|
||||
|
||||
#endif /* !defined (CLI_DECODE_H) */
|
||||
@@ -1,821 +0,0 @@
|
||||
/* Dump-to-file commands, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Red Hat.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_string.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "value.h"
|
||||
#include "completer.h"
|
||||
#include "cli/cli-dump.h"
|
||||
#include "gdb_assert.h"
|
||||
#include <ctype.h>
|
||||
#include "target.h"
|
||||
|
||||
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
|
||||
|
||||
|
||||
char *
|
||||
skip_spaces (char *chp)
|
||||
{
|
||||
if (chp == NULL)
|
||||
return NULL;
|
||||
while (isspace (*chp))
|
||||
chp++;
|
||||
return chp;
|
||||
}
|
||||
|
||||
char *
|
||||
scan_expression_with_cleanup (char **cmd, const char *def)
|
||||
{
|
||||
if ((*cmd) == NULL || (**cmd) == '\0')
|
||||
{
|
||||
char *exp = xstrdup (def);
|
||||
make_cleanup (xfree, exp);
|
||||
return exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *exp;
|
||||
char *end;
|
||||
|
||||
end = (*cmd) + strcspn (*cmd, " \t");
|
||||
exp = savestring ((*cmd), end - (*cmd));
|
||||
make_cleanup (xfree, exp);
|
||||
(*cmd) = skip_spaces (end);
|
||||
return exp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_fclose_cleanup (void *arg)
|
||||
{
|
||||
FILE *file = arg;
|
||||
fclose (arg);
|
||||
}
|
||||
|
||||
static struct cleanup *
|
||||
make_cleanup_fclose (FILE *file)
|
||||
{
|
||||
return make_cleanup (do_fclose_cleanup, file);
|
||||
}
|
||||
|
||||
char *
|
||||
scan_filename_with_cleanup (char **cmd, const char *defname)
|
||||
{
|
||||
char *filename;
|
||||
char *fullname;
|
||||
|
||||
/* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
|
||||
|
||||
/* File. */
|
||||
if ((*cmd) == NULL)
|
||||
{
|
||||
if (defname == NULL)
|
||||
error ("Missing filename.");
|
||||
filename = xstrdup (defname);
|
||||
make_cleanup (xfree, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: should parse a possibly quoted string. */
|
||||
char *end;
|
||||
|
||||
(*cmd) = skip_spaces (*cmd);
|
||||
end = *cmd + strcspn (*cmd, " \t");
|
||||
filename = savestring ((*cmd), end - (*cmd));
|
||||
make_cleanup (xfree, filename);
|
||||
(*cmd) = skip_spaces (end);
|
||||
}
|
||||
gdb_assert (filename != NULL);
|
||||
|
||||
fullname = tilde_expand (filename);
|
||||
make_cleanup (xfree, fullname);
|
||||
|
||||
return fullname;
|
||||
}
|
||||
|
||||
FILE *
|
||||
fopen_with_cleanup (char *filename, const char *mode)
|
||||
{
|
||||
FILE *file = fopen (filename, mode);
|
||||
if (file == NULL)
|
||||
perror_with_name (filename);
|
||||
make_cleanup_fclose (file);
|
||||
return file;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
bfd_openr_with_cleanup (const char *filename, const char *target)
|
||||
{
|
||||
bfd *ibfd;
|
||||
|
||||
if ((ibfd = bfd_openr (filename, target)) == NULL)
|
||||
error ("Failed to open %s: %s.", filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
make_cleanup_bfd_close (ibfd);
|
||||
if (!bfd_check_format (ibfd, bfd_object))
|
||||
error ("'%s' is not a recognized file format.", filename);
|
||||
|
||||
return ibfd;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
bfd_openw_with_cleanup (char *filename, const char *target, char *mode)
|
||||
{
|
||||
bfd *obfd;
|
||||
|
||||
if (*mode == 'w') /* Write: create new file */
|
||||
{
|
||||
if ((obfd = bfd_openw (filename, target)) == NULL)
|
||||
error ("Failed to open %s: %s.", filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
make_cleanup_bfd_close (obfd);
|
||||
if (!bfd_set_format (obfd, bfd_object))
|
||||
error ("bfd_openw_with_cleanup: %s.", bfd_errmsg (bfd_get_error ()));
|
||||
}
|
||||
else if (*mode == 'a') /* Append to existing file */
|
||||
{ /* FIXME -- doesn't work... */
|
||||
error ("bfd_openw does not work with append.");
|
||||
}
|
||||
else
|
||||
error ("bfd_openw_with_cleanup: unknown mode %s.", mode);
|
||||
|
||||
return obfd;
|
||||
}
|
||||
|
||||
struct cmd_list_element *dump_cmdlist;
|
||||
struct cmd_list_element *append_cmdlist;
|
||||
struct cmd_list_element *srec_cmdlist;
|
||||
struct cmd_list_element *ihex_cmdlist;
|
||||
struct cmd_list_element *tekhex_cmdlist;
|
||||
struct cmd_list_element *binary_dump_cmdlist;
|
||||
struct cmd_list_element *binary_append_cmdlist;
|
||||
|
||||
static void
|
||||
dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump\" must be followed by a subcommand.\n\n");
|
||||
help_list (dump_cmdlist, "dump ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
append_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"append\" must be followed by a subcommand.\n\n");
|
||||
help_list (dump_cmdlist, "append ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_file (char *filename, char *mode,
|
||||
char *buf, int len)
|
||||
{
|
||||
FILE *file;
|
||||
int status;
|
||||
|
||||
file = fopen_with_cleanup (filename, mode);
|
||||
status = fwrite (buf, len, 1, file);
|
||||
if (status != 1)
|
||||
perror_with_name (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_bfd_file (char *filename, char *mode,
|
||||
char *target, CORE_ADDR vaddr,
|
||||
char *buf, int len)
|
||||
{
|
||||
bfd *obfd;
|
||||
asection *osection;
|
||||
|
||||
obfd = bfd_openw_with_cleanup (filename, target, mode);
|
||||
osection = bfd_make_section_anyway (obfd, ".newsec");
|
||||
bfd_set_section_size (obfd, osection, len);
|
||||
bfd_set_section_vma (obfd, osection, vaddr);
|
||||
bfd_set_section_alignment (obfd, osection, 0);
|
||||
bfd_set_section_flags (obfd, osection, 0x203);
|
||||
osection->entsize = 0;
|
||||
bfd_set_section_contents (obfd, osection, buf, 0, len);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_memory_to_file (char *cmd, char *mode, char *file_format)
|
||||
{
|
||||
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
|
||||
CORE_ADDR lo;
|
||||
CORE_ADDR hi;
|
||||
ULONGEST count;
|
||||
char *filename;
|
||||
void *buf;
|
||||
char *lo_exp;
|
||||
char *hi_exp;
|
||||
int len;
|
||||
|
||||
/* Open the file. */
|
||||
filename = scan_filename_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the low address. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("Missing start address.");
|
||||
lo_exp = scan_expression_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the second address - rest of line. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("Missing stop address.");
|
||||
hi_exp = cmd;
|
||||
|
||||
lo = parse_and_eval_address (lo_exp);
|
||||
hi = parse_and_eval_address (hi_exp);
|
||||
if (hi <= lo)
|
||||
error ("Invalid memory address range (start >= end).");
|
||||
count = hi - lo;
|
||||
|
||||
/* FIXME: Should use read_memory_partial() and a magic blocking
|
||||
value. */
|
||||
buf = xmalloc (count);
|
||||
make_cleanup (xfree, buf);
|
||||
target_read_memory (lo, buf, count);
|
||||
|
||||
/* Have everything. Open/write the data. */
|
||||
if (file_format == NULL || strcmp (file_format, "binary") == 0)
|
||||
{
|
||||
dump_binary_file (filename, mode, buf, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_bfd_file (filename, mode, file_format, lo, buf, count);
|
||||
}
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_memory_command (char *cmd, char *mode)
|
||||
{
|
||||
dump_memory_to_file (cmd, mode, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_value_to_file (char *cmd, char *mode, char *file_format)
|
||||
{
|
||||
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
|
||||
struct value *val;
|
||||
char *filename;
|
||||
|
||||
/* Open the file. */
|
||||
filename = scan_filename_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the value. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("No value to %s.", *mode == 'a' ? "append" : "dump");
|
||||
val = parse_and_eval (cmd);
|
||||
if (val == NULL)
|
||||
error ("Invalid expression.");
|
||||
|
||||
/* Have everything. Open/write the data. */
|
||||
if (file_format == NULL || strcmp (file_format, "binary") == 0)
|
||||
{
|
||||
dump_binary_file (filename, mode, VALUE_CONTENTS (val),
|
||||
TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_ADDR vaddr;
|
||||
|
||||
if (VALUE_LVAL (val))
|
||||
{
|
||||
vaddr = VALUE_ADDRESS (val);
|
||||
}
|
||||
else
|
||||
{
|
||||
vaddr = 0;
|
||||
warning ("value is not an lval: address assumed to be zero");
|
||||
}
|
||||
|
||||
dump_bfd_file (filename, mode, file_format, vaddr,
|
||||
VALUE_CONTENTS (val),
|
||||
TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
}
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_value_command (char *cmd, char *mode)
|
||||
{
|
||||
dump_value_to_file (cmd, mode, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_filetype (char *cmd, char *mode, char *filetype)
|
||||
{
|
||||
char *suffix = cmd;
|
||||
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("Missing subcommand: try 'help %s %s'.",
|
||||
mode[0] == 'a' ? "append" : "dump",
|
||||
filetype);
|
||||
|
||||
suffix += strcspn (cmd, " \t");
|
||||
|
||||
if (suffix != cmd)
|
||||
{
|
||||
if (strncmp ("memory", cmd, suffix - cmd) == 0)
|
||||
{
|
||||
dump_memory_to_file (suffix, mode, filetype);
|
||||
return;
|
||||
}
|
||||
else if (strncmp ("value", cmd, suffix - cmd) == 0)
|
||||
{
|
||||
dump_value_to_file (suffix, mode, filetype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error ("dump %s: unknown subcommand '%s' -- try 'value' or 'memory'.",
|
||||
filetype, cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_srec_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, "w", "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_srec_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, "w", "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, "w", "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, "w", "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, "w", "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, "w", "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, "w", "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, "w", "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, "a", "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, "a", "binary");
|
||||
}
|
||||
|
||||
struct dump_context
|
||||
{
|
||||
void (*func) (char *cmd, char *mode);
|
||||
char *mode;
|
||||
};
|
||||
|
||||
static void
|
||||
call_dump_func (struct cmd_list_element *c, char *args, int from_tty)
|
||||
{
|
||||
struct dump_context *d = get_cmd_context (c);
|
||||
d->func (args, d->mode);
|
||||
}
|
||||
|
||||
void
|
||||
add_dump_command (char *name, void (*func) (char *args, char *mode),
|
||||
char *descr)
|
||||
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
struct dump_context *d;
|
||||
|
||||
c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist);
|
||||
c->completer = filename_completer;
|
||||
d = XMALLOC (struct dump_context);
|
||||
d->func = func;
|
||||
d->mode = "w";
|
||||
set_cmd_context (c, d);
|
||||
c->func = call_dump_func;
|
||||
|
||||
c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist);
|
||||
c->completer = filename_completer;
|
||||
d = XMALLOC (struct dump_context);
|
||||
d->func = func;
|
||||
d->mode = "a";
|
||||
set_cmd_context (c, d);
|
||||
c->func = call_dump_func;
|
||||
|
||||
/* Replace "Dump " at start of docstring with "Append "
|
||||
(borrowed from add_show_from_set). */
|
||||
if ( c->doc[0] == 'W'
|
||||
&& c->doc[1] == 'r'
|
||||
&& c->doc[2] == 'i'
|
||||
&& c->doc[3] == 't'
|
||||
&& c->doc[4] == 'e'
|
||||
&& c->doc[5] == ' ')
|
||||
c->doc = concat ("Append ", c->doc + 6, NULL);
|
||||
}
|
||||
|
||||
/* Opaque data for restore_section_callback. */
|
||||
struct callback_data {
|
||||
unsigned long load_offset;
|
||||
CORE_ADDR load_start;
|
||||
CORE_ADDR load_end;
|
||||
};
|
||||
|
||||
/* Function: restore_section_callback.
|
||||
|
||||
Callback function for bfd_map_over_sections.
|
||||
Selectively loads the sections into memory. */
|
||||
|
||||
static void
|
||||
restore_section_callback (bfd *ibfd, asection *isec, void *args)
|
||||
{
|
||||
struct callback_data *data = args;
|
||||
bfd_vma sec_start = bfd_section_vma (ibfd, isec);
|
||||
bfd_size_type size = bfd_section_size (ibfd, isec);
|
||||
bfd_vma sec_end = sec_start + size;
|
||||
bfd_size_type sec_offset = 0;
|
||||
bfd_size_type sec_load_count = size;
|
||||
struct cleanup *old_chain;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
/* Ignore non-loadable sections, eg. from elf files. */
|
||||
if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
|
||||
return;
|
||||
|
||||
/* Does the section overlap with the desired restore range? */
|
||||
if (sec_end <= data->load_start
|
||||
|| (data->load_end > 0 && sec_start >= data->load_end))
|
||||
{
|
||||
/* No, no useable data in this section. */
|
||||
printf_filtered ("skipping section %s...\n",
|
||||
bfd_section_name (ibfd, isec));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compare section address range with user-requested
|
||||
address range (if any). Compute where the actual
|
||||
transfer should start and end. */
|
||||
if (sec_start < data->load_start)
|
||||
sec_offset = data->load_start - sec_start;
|
||||
/* Size of a partial transfer: */
|
||||
sec_load_count -= sec_offset;
|
||||
if (data->load_end > 0 && sec_end > data->load_end)
|
||||
sec_load_count -= sec_end - data->load_end;
|
||||
|
||||
/* Get the data. */
|
||||
buf = xmalloc (size);
|
||||
old_chain = make_cleanup (xfree, buf);
|
||||
if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
|
||||
error ("Failed to read bfd file %s: '%s'.", bfd_get_filename (ibfd),
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
|
||||
bfd_section_name (ibfd, isec),
|
||||
(unsigned long) sec_start,
|
||||
(unsigned long) sec_end);
|
||||
|
||||
if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
|
||||
printf_filtered (" into memory (0x%s to 0x%s)\n",
|
||||
paddr_nz ((unsigned long) sec_start
|
||||
+ sec_offset + data->load_offset),
|
||||
paddr_nz ((unsigned long) sec_start + sec_offset
|
||||
+ data->load_offset + sec_load_count));
|
||||
else
|
||||
puts_filtered ("\n");
|
||||
|
||||
/* Write the data. */
|
||||
ret = target_write_memory (sec_start + sec_offset + data->load_offset,
|
||||
buf + sec_offset, sec_load_count);
|
||||
if (ret != 0)
|
||||
warning ("restore: memory write failed (%s).", safe_strerror (ret));
|
||||
do_cleanups (old_chain);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_binary_file (char *filename, struct callback_data *data)
|
||||
{
|
||||
FILE *file = fopen_with_cleanup (filename, "r");
|
||||
int status;
|
||||
char *buf;
|
||||
long len;
|
||||
|
||||
/* Get the file size for reading. */
|
||||
if (fseek (file, 0, SEEK_END) == 0)
|
||||
len = ftell (file);
|
||||
else
|
||||
perror_with_name (filename);
|
||||
|
||||
if (len <= data->load_start)
|
||||
error ("Start address is greater than length of binary file %s.",
|
||||
filename);
|
||||
|
||||
/* Chop off "len" if it exceeds the requested load_end addr. */
|
||||
if (data->load_end != 0 && data->load_end < len)
|
||||
len = data->load_end;
|
||||
/* Chop off "len" if the requested load_start addr skips some bytes. */
|
||||
if (data->load_start > 0)
|
||||
len -= data->load_start;
|
||||
|
||||
printf_filtered
|
||||
("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
|
||||
filename,
|
||||
(unsigned long) data->load_start + data->load_offset,
|
||||
(unsigned long) data->load_start + data->load_offset + len);
|
||||
|
||||
/* Now set the file pos to the requested load start pos. */
|
||||
if (fseek (file, data->load_start, SEEK_SET) != 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
/* Now allocate a buffer and read the file contents. */
|
||||
buf = xmalloc (len);
|
||||
make_cleanup (xfree, buf);
|
||||
if (fread (buf, 1, len, file) != len)
|
||||
perror_with_name (filename);
|
||||
|
||||
/* Now write the buffer into target memory. */
|
||||
len = target_write_memory (data->load_start + data->load_offset, buf, len);
|
||||
if (len != 0)
|
||||
warning ("restore: memory write failed (%s).", safe_strerror (len));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_command (char *args, int from_tty)
|
||||
{
|
||||
char *filename;
|
||||
struct callback_data data;
|
||||
bfd *ibfd;
|
||||
int binary_flag = 0;
|
||||
|
||||
if (!target_has_execution)
|
||||
noprocess ();
|
||||
|
||||
data.load_offset = 0;
|
||||
data.load_start = 0;
|
||||
data.load_end = 0;
|
||||
|
||||
/* Parse the input arguments. First is filename (required). */
|
||||
filename = scan_filename_with_cleanup (&args, NULL);
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
char *binary_string = "binary";
|
||||
|
||||
/* Look for optional "binary" flag. */
|
||||
if (strncmp (args, binary_string, strlen (binary_string)) == 0)
|
||||
{
|
||||
binary_flag = 1;
|
||||
args += strlen (binary_string);
|
||||
args = skip_spaces (args);
|
||||
}
|
||||
/* Parse offset (optional). */
|
||||
if (args != NULL && *args != '\0')
|
||||
data.load_offset =
|
||||
parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
/* Parse start address (optional). */
|
||||
data.load_start =
|
||||
parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
/* Parse end address (optional). */
|
||||
data.load_end = parse_and_eval_long (args);
|
||||
if (data.load_end <= data.load_start)
|
||||
error ("Start must be less than end.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info_verbose)
|
||||
printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
|
||||
filename, (unsigned long) data.load_offset,
|
||||
(unsigned long) data.load_start,
|
||||
(unsigned long) data.load_end);
|
||||
|
||||
if (binary_flag)
|
||||
{
|
||||
restore_binary_file (filename, &data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open the file for loading. */
|
||||
ibfd = bfd_openr_with_cleanup (filename, NULL);
|
||||
|
||||
/* Process the sections. */
|
||||
bfd_map_over_sections (ibfd, restore_section_callback, &data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
srec_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n");
|
||||
help_list (srec_cmdlist, "dump srec ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
ihex_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n");
|
||||
help_list (ihex_cmdlist, "dump ihex ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
tekhex_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n");
|
||||
help_list (tekhex_cmdlist, "dump tekhex ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
binary_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n");
|
||||
help_list (binary_dump_cmdlist, "dump binary ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
binary_append_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n");
|
||||
help_list (binary_append_cmdlist, "append binary ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_cli_dump (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
add_prefix_cmd ("dump", class_vars, dump_command, "\
|
||||
Dump target code/data to a local file.",
|
||||
&dump_cmdlist, "dump ",
|
||||
0/*allow-unknown*/,
|
||||
&cmdlist);
|
||||
add_prefix_cmd ("append", class_vars, append_command, "\
|
||||
Append target code/data to a local file.",
|
||||
&append_cmdlist, "append ",
|
||||
0/*allow-unknown*/,
|
||||
&cmdlist);
|
||||
|
||||
add_dump_command ("memory", dump_memory_command, "\
|
||||
Write contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within the\n\
|
||||
range [START .. STOP) to the specifed FILE in raw target ordered bytes.");
|
||||
|
||||
add_dump_command ("value", dump_value_command, "\
|
||||
Write the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
|
||||
the specified FILE in raw target ordered bytes.");
|
||||
|
||||
add_prefix_cmd ("srec", all_commands, srec_dump_command, "\
|
||||
Write target code/data to an srec file.",
|
||||
&srec_cmdlist, "dump srec ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("ihex", all_commands, ihex_dump_command, "\
|
||||
Write target code/data to an intel hex file.",
|
||||
&ihex_cmdlist, "dump ihex ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, "\
|
||||
Write target code/data to a tekhex file.",
|
||||
&tekhex_cmdlist, "dump tekhex ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("binary", all_commands, binary_dump_command, "\
|
||||
Write target code/data to a raw binary file.",
|
||||
&binary_dump_cmdlist, "dump binary ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("binary", all_commands, binary_append_command, "\
|
||||
Append target code/data to a raw binary file.",
|
||||
&binary_append_cmdlist, "append binary ",
|
||||
0 /*allow-unknown*/,
|
||||
&append_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_srec_memory, "\
|
||||
Write contents of memory to an srec file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in srec format.",
|
||||
&srec_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_srec_value, "\
|
||||
Write the value of an expression to an srec file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in srec format.",
|
||||
&srec_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_ihex_memory, "\
|
||||
Write contents of memory to an ihex file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within\n\
|
||||
the range [START .. STOP) to the specifed FILE in intel hex format.",
|
||||
&ihex_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_ihex_value, "\
|
||||
Write the value of an expression to an ihex file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in intel hex format.",
|
||||
&ihex_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_tekhex_memory, "\
|
||||
Write contents of memory to a tekhex file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in tekhex format.",
|
||||
&tekhex_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_tekhex_value, "\
|
||||
Write the value of an expression to a tekhex file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in tekhex format.",
|
||||
&tekhex_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_binary_memory, "\
|
||||
Write contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in binary format.",
|
||||
&binary_dump_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_binary_value, "\
|
||||
Write the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in raw target ordered bytes.",
|
||||
&binary_dump_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, append_binary_memory, "\
|
||||
Append contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within the\n\
|
||||
range [START .. STOP) to the specifed FILE in raw target ordered bytes.",
|
||||
&binary_append_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, append_binary_value, "\
|
||||
Append the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in raw target ordered bytes.",
|
||||
&binary_append_cmdlist);
|
||||
|
||||
c = add_com ("restore", class_vars, restore_command,
|
||||
"Restore the contents of FILE to target memory.\n\
|
||||
Arguments are FILE OFFSET START END where all except FILE are optional.\n\
|
||||
OFFSET will be added to the base address of the file (default zero).\n\
|
||||
If START and END are given, only the file contents within that range\n\
|
||||
(file relative) will be restored to target memory.");
|
||||
c->completer = filename_completer;
|
||||
/* FIXME: completers for other commands. */
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/* Dump-to-file commands, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef CLI_DUMP_H
|
||||
#define CLI_DUMP_H
|
||||
|
||||
extern void add_dump_command (char *name,
|
||||
void (*func) (char *args, char *mode),
|
||||
char *descr);
|
||||
|
||||
/* Utilities for doing the dump. */
|
||||
extern char *scan_filename_with_cleanup (char **cmd, const char *defname);
|
||||
|
||||
extern char *scan_expression_with_cleanup (char **cmd, const char *defname);
|
||||
|
||||
extern FILE *fopen_with_cleanup (char *filename, const char *mode);
|
||||
|
||||
extern char *skip_spaces (char *inp);
|
||||
|
||||
extern struct value *parse_and_eval_with_error (char *exp, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
|
||||
|
||||
#endif
|
||||
1279
gdb/cli/cli-script.c
1279
gdb/cli/cli-script.c
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
/* Header file for GDB CLI command implementation library.
|
||||
Copyright 2000, 2002 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (CLI_SCRIPT_H)
|
||||
#define CLI_SCRIPT_H 1
|
||||
|
||||
/* Exported to cli/cli-cmds.c */
|
||||
|
||||
extern void script_from_file (FILE *stream, char *file);
|
||||
|
||||
extern void document_command (char *, int);
|
||||
|
||||
extern void define_command (char *, int);
|
||||
|
||||
extern void while_command (char *arg, int from_tty);
|
||||
|
||||
extern void if_command (char *arg, int from_tty);
|
||||
|
||||
extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
|
||||
|
||||
/* Exported to gdb/breakpoint.c */
|
||||
|
||||
extern enum command_control_type
|
||||
execute_control_command (struct command_line *cmd);
|
||||
|
||||
extern void print_command_lines (struct ui_out *,
|
||||
struct command_line *, unsigned int);
|
||||
|
||||
/* Exported to gdb/infrun.c */
|
||||
|
||||
extern void execute_user_command (struct cmd_list_element *c, char *args);
|
||||
|
||||
#endif /* !defined (CLI_SCRIPT_H) */
|
||||
@@ -1,381 +0,0 @@
|
||||
/* Handle set and show GDB commands.
|
||||
|
||||
Copyright 2000, 2001, 2002 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "value.h"
|
||||
#include <ctype.h>
|
||||
#if 0
|
||||
#include "gdb_string.h"
|
||||
#endif
|
||||
|
||||
#include "ui-out.h"
|
||||
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "cli/cli-setshow.h"
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static int parse_binary_operation (char *);
|
||||
|
||||
|
||||
static enum auto_boolean
|
||||
parse_auto_binary_operation (const char *arg)
|
||||
{
|
||||
if (arg != NULL && *arg != '\0')
|
||||
{
|
||||
int length = strlen (arg);
|
||||
while (isspace (arg[length - 1]) && length > 0)
|
||||
length--;
|
||||
if (strncmp (arg, "on", length) == 0
|
||||
|| strncmp (arg, "1", length) == 0
|
||||
|| strncmp (arg, "yes", length) == 0
|
||||
|| strncmp (arg, "enable", length) == 0)
|
||||
return AUTO_BOOLEAN_TRUE;
|
||||
else if (strncmp (arg, "off", length) == 0
|
||||
|| strncmp (arg, "0", length) == 0
|
||||
|| strncmp (arg, "no", length) == 0
|
||||
|| strncmp (arg, "disable", length) == 0)
|
||||
return AUTO_BOOLEAN_FALSE;
|
||||
else if (strncmp (arg, "auto", length) == 0
|
||||
|| (strncmp (arg, "-1", length) == 0 && length > 1))
|
||||
return AUTO_BOOLEAN_AUTO;
|
||||
}
|
||||
error ("\"on\", \"off\" or \"auto\" expected.");
|
||||
return AUTO_BOOLEAN_AUTO; /* pacify GCC */
|
||||
}
|
||||
|
||||
static int
|
||||
parse_binary_operation (char *arg)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (!arg || !*arg)
|
||||
return 1;
|
||||
|
||||
length = strlen (arg);
|
||||
|
||||
while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
|
||||
length--;
|
||||
|
||||
if (strncmp (arg, "on", length) == 0
|
||||
|| strncmp (arg, "1", length) == 0
|
||||
|| strncmp (arg, "yes", length) == 0
|
||||
|| strncmp (arg, "enable", length) == 0)
|
||||
return 1;
|
||||
else if (strncmp (arg, "off", length) == 0
|
||||
|| strncmp (arg, "0", length) == 0
|
||||
|| strncmp (arg, "no", length) == 0
|
||||
|| strncmp (arg, "disable", length) == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
error ("\"on\" or \"off\" expected.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
|
||||
of the argument, and FROM_TTY is nonzero if this command is being entered
|
||||
directly by the user (i.e. these are just like any other
|
||||
command). C is the command list element for the command. */
|
||||
|
||||
void
|
||||
do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
||||
{
|
||||
if (c->type == set_cmd)
|
||||
{
|
||||
switch (c->var_type)
|
||||
{
|
||||
case var_string:
|
||||
{
|
||||
char *new;
|
||||
char *p;
|
||||
char *q;
|
||||
int ch;
|
||||
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
new = (char *) xmalloc (strlen (arg) + 2);
|
||||
p = arg;
|
||||
q = new;
|
||||
while ((ch = *p++) != '\000')
|
||||
{
|
||||
if (ch == '\\')
|
||||
{
|
||||
/* \ at end of argument is used after spaces
|
||||
so they won't be lost. */
|
||||
/* This is obsolete now that we no longer strip
|
||||
trailing whitespace and actually, the backslash
|
||||
didn't get here in my test, readline or
|
||||
something did something funky with a backslash
|
||||
right before a newline. */
|
||||
if (*p == 0)
|
||||
break;
|
||||
ch = parse_escape (&p);
|
||||
if (ch == 0)
|
||||
break; /* C loses */
|
||||
else if (ch > 0)
|
||||
*q++ = ch;
|
||||
}
|
||||
else
|
||||
*q++ = ch;
|
||||
}
|
||||
#if 0
|
||||
if (*(p - 1) != '\\')
|
||||
*q++ = ' ';
|
||||
#endif
|
||||
*q++ = '\0';
|
||||
new = (char *) xrealloc (new, q - new);
|
||||
if (*(char **) c->var != NULL)
|
||||
xfree (*(char **) c->var);
|
||||
*(char **) c->var = new;
|
||||
}
|
||||
break;
|
||||
case var_string_noescape:
|
||||
if (arg == NULL)
|
||||
arg = "";
|
||||
if (*(char **) c->var != NULL)
|
||||
xfree (*(char **) c->var);
|
||||
*(char **) c->var = savestring (arg, strlen (arg));
|
||||
break;
|
||||
case var_filename:
|
||||
if (arg == NULL)
|
||||
error_no_arg ("filename to set it to.");
|
||||
if (*(char **) c->var != NULL)
|
||||
xfree (*(char **) c->var);
|
||||
*(char **) c->var = tilde_expand (arg);
|
||||
break;
|
||||
case var_boolean:
|
||||
*(int *) c->var = parse_binary_operation (arg);
|
||||
break;
|
||||
case var_auto_boolean:
|
||||
*(enum auto_boolean *) c->var = parse_auto_binary_operation (arg);
|
||||
break;
|
||||
case var_uinteger:
|
||||
if (arg == NULL)
|
||||
error_no_arg ("integer to set it to.");
|
||||
*(unsigned int *) c->var = parse_and_eval_long (arg);
|
||||
if (*(unsigned int *) c->var == 0)
|
||||
*(unsigned int *) c->var = UINT_MAX;
|
||||
break;
|
||||
case var_integer:
|
||||
{
|
||||
unsigned int val;
|
||||
if (arg == NULL)
|
||||
error_no_arg ("integer to set it to.");
|
||||
val = parse_and_eval_long (arg);
|
||||
if (val == 0)
|
||||
*(int *) c->var = INT_MAX;
|
||||
else if (val >= INT_MAX)
|
||||
error ("integer %u out of range", val);
|
||||
else
|
||||
*(int *) c->var = val;
|
||||
break;
|
||||
}
|
||||
case var_zinteger:
|
||||
if (arg == NULL)
|
||||
error_no_arg ("integer to set it to.");
|
||||
*(int *) c->var = parse_and_eval_long (arg);
|
||||
break;
|
||||
case var_enum:
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
int nmatches;
|
||||
const char *match = NULL;
|
||||
char *p;
|
||||
|
||||
/* if no argument was supplied, print an informative error message */
|
||||
if (arg == NULL)
|
||||
{
|
||||
char msg[1024];
|
||||
strcpy (msg, "Requires an argument. Valid arguments are ");
|
||||
for (i = 0; c->enums[i]; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
strcat (msg, ", ");
|
||||
strcat (msg, c->enums[i]);
|
||||
}
|
||||
strcat (msg, ".");
|
||||
error (msg);
|
||||
}
|
||||
|
||||
p = strchr (arg, ' ');
|
||||
|
||||
if (p)
|
||||
len = p - arg;
|
||||
else
|
||||
len = strlen (arg);
|
||||
|
||||
nmatches = 0;
|
||||
for (i = 0; c->enums[i]; i++)
|
||||
if (strncmp (arg, c->enums[i], len) == 0)
|
||||
{
|
||||
if (c->enums[i][len] == '\0')
|
||||
{
|
||||
match = c->enums[i];
|
||||
nmatches = 1;
|
||||
break; /* exact match. */
|
||||
}
|
||||
else
|
||||
{
|
||||
match = c->enums[i];
|
||||
nmatches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nmatches <= 0)
|
||||
error ("Undefined item: \"%s\".", arg);
|
||||
|
||||
if (nmatches > 1)
|
||||
error ("Ambiguous item \"%s\".", arg);
|
||||
|
||||
*(const char **) c->var = match;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error ("gdb internal error: bad var_type in do_setshow_command");
|
||||
}
|
||||
}
|
||||
else if (c->type == show_cmd)
|
||||
{
|
||||
struct cleanup *old_chain;
|
||||
struct ui_stream *stb;
|
||||
int quote;
|
||||
|
||||
stb = ui_out_stream_new (uiout);
|
||||
old_chain = make_cleanup_ui_out_stream_delete (stb);
|
||||
|
||||
/* Possibly call the pre hook. */
|
||||
if (c->pre_show_hook)
|
||||
(c->pre_show_hook) (c);
|
||||
|
||||
/* Print doc minus "show" at start. */
|
||||
print_doc_line (gdb_stdout, c->doc + 5);
|
||||
|
||||
ui_out_text (uiout, " is ");
|
||||
ui_out_wrap_hint (uiout, " ");
|
||||
quote = 0;
|
||||
switch (c->var_type)
|
||||
{
|
||||
case var_string:
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
if (*(unsigned char **) c->var)
|
||||
fputstr_filtered (*(unsigned char **) c->var, '"', stb->stream);
|
||||
quote = 1;
|
||||
}
|
||||
break;
|
||||
case var_string_noescape:
|
||||
case var_filename:
|
||||
case var_enum:
|
||||
if (*(char **) c->var)
|
||||
fputs_filtered (*(char **) c->var, stb->stream);
|
||||
quote = 1;
|
||||
break;
|
||||
case var_boolean:
|
||||
fputs_filtered (*(int *) c->var ? "on" : "off", stb->stream);
|
||||
break;
|
||||
case var_auto_boolean:
|
||||
switch (*(enum auto_boolean*) c->var)
|
||||
{
|
||||
case AUTO_BOOLEAN_TRUE:
|
||||
fputs_filtered ("on", stb->stream);
|
||||
break;
|
||||
case AUTO_BOOLEAN_FALSE:
|
||||
fputs_filtered ("off", stb->stream);
|
||||
break;
|
||||
case AUTO_BOOLEAN_AUTO:
|
||||
fputs_filtered ("auto", stb->stream);
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"do_setshow_command: invalid var_auto_boolean");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case var_uinteger:
|
||||
if (*(unsigned int *) c->var == UINT_MAX)
|
||||
{
|
||||
fputs_filtered ("unlimited", stb->stream);
|
||||
break;
|
||||
}
|
||||
/* else fall through */
|
||||
case var_zinteger:
|
||||
fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var);
|
||||
break;
|
||||
case var_integer:
|
||||
if (*(int *) c->var == INT_MAX)
|
||||
{
|
||||
fputs_filtered ("unlimited", stb->stream);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stb->stream, "%d", *(int *) c->var);
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("gdb internal error: bad var_type in do_setshow_command");
|
||||
}
|
||||
if (quote)
|
||||
ui_out_text (uiout, "\"");
|
||||
ui_out_field_stream (uiout, "value", stb);
|
||||
if (quote)
|
||||
ui_out_text (uiout, "\"");
|
||||
ui_out_text (uiout, ".\n");
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
else
|
||||
error ("gdb internal error: bad cmd_type in do_setshow_command");
|
||||
c->func (c, NULL, from_tty);
|
||||
if (c->type == set_cmd && set_hook)
|
||||
set_hook (c);
|
||||
}
|
||||
|
||||
/* Show all the settings in a list of show commands. */
|
||||
|
||||
void
|
||||
cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "showlist");
|
||||
for (; list != NULL; list = list->next)
|
||||
{
|
||||
/* If we find a prefix, run its list, prefixing our output by its
|
||||
prefix (with "show " skipped). */
|
||||
if (list->prefixlist && !list->abbrev_flag)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "optionlist");
|
||||
ui_out_field_string (uiout, "prefix", list->prefixname + 5);
|
||||
cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
|
||||
ui_out_tuple_end (uiout);
|
||||
}
|
||||
if (list->type == show_cmd)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "option");
|
||||
ui_out_text (uiout, prefix);
|
||||
ui_out_field_string (uiout, "name", list->name);
|
||||
ui_out_text (uiout, ": ");
|
||||
do_setshow_command ((char *) NULL, from_tty, list);
|
||||
ui_out_tuple_end (uiout);
|
||||
}
|
||||
}
|
||||
ui_out_tuple_end (uiout);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/* Header file for GDB CLI set and show commands implementation.
|
||||
Copyright 2000, 2001 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (CLI_SETSHOW_H)
|
||||
#define CLI_SETSHOW_H 1
|
||||
|
||||
/* Exported to cli/cli-cmds.c and gdb/top.c */
|
||||
|
||||
/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
|
||||
of the argument, and FROM_TTY is nonzero if this command is being entered
|
||||
directly by the user (i.e. these are just like any other
|
||||
command). C is the command list element for the command. */
|
||||
extern void do_setshow_command (char *arg, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
|
||||
/* Exported to cli/cli-cmds.c and gdb/top.c, language.c and valprint.c */
|
||||
|
||||
extern void cmd_show_list (struct cmd_list_element *list, int from_tty,
|
||||
char *prefix);
|
||||
|
||||
#endif /* !defined (CLI_SETSHOW_H) */
|
||||
@@ -1,21 +0,0 @@
|
||||
/* GDB CLI utility library.
|
||||
Copyright 2001 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "cli/cli-utils.h"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Header file for GDB CLI utility library.
|
||||
Copyright 2001 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (CLI_UTILS_H)
|
||||
# define CLI_UTILS_H 1
|
||||
|
||||
#endif /* !defined (CLI_UTILS_H) */
|
||||
134
gdb/coff-solib.c
134
gdb/coff-solib.c
@@ -1,134 +0,0 @@
|
||||
/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
|
||||
Copyright 1993, 1994, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include "frame.h"
|
||||
#include "bfd.h"
|
||||
#include "gdbcore.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
||||
/*
|
||||
|
||||
GLOBAL FUNCTION
|
||||
|
||||
coff_solib_add -- add a shared library files to the symtab list. We
|
||||
examine the `.lib' section of the exec file and determine the names of
|
||||
the shared libraries.
|
||||
|
||||
This function is responsible for discovering those names and
|
||||
addresses, and saving sufficient information about them to allow
|
||||
their symbols to be read at a later time.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
void coff_solib_add (char *arg_string, int from_tty,
|
||||
struct target_ops *target, int readsyms)
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
*/
|
||||
|
||||
void
|
||||
coff_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
|
||||
{
|
||||
asection *libsect;
|
||||
|
||||
if (!readsyms)
|
||||
return;
|
||||
|
||||
libsect = bfd_get_section_by_name (exec_bfd, ".lib");
|
||||
|
||||
if (libsect)
|
||||
{
|
||||
int libsize;
|
||||
unsigned char *lib;
|
||||
struct libent
|
||||
{
|
||||
bfd_byte len[4];
|
||||
bfd_byte nameoffset[4];
|
||||
};
|
||||
|
||||
libsize = bfd_section_size (exec_bfd, libsect);
|
||||
|
||||
lib = (unsigned char *) alloca (libsize);
|
||||
|
||||
bfd_get_section_contents (exec_bfd, libsect, lib, 0, libsize);
|
||||
|
||||
while (libsize > 0)
|
||||
{
|
||||
struct libent *ent;
|
||||
struct objfile *objfile;
|
||||
int len, nameoffset;
|
||||
char *filename;
|
||||
|
||||
ent = (struct libent *) lib;
|
||||
|
||||
len = bfd_get_32 (exec_bfd, ent->len);
|
||||
|
||||
nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
|
||||
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
filename = (char *) ent + nameoffset * 4;
|
||||
|
||||
objfile = symbol_file_add (filename, from_tty,
|
||||
NULL, /* no offsets */
|
||||
0, /* not mainline */
|
||||
OBJF_SHARED); /* flags */
|
||||
|
||||
libsize -= len * 4;
|
||||
lib += len * 4;
|
||||
}
|
||||
|
||||
/* Getting new symbols may change our opinion about what is
|
||||
frameless. */
|
||||
reinit_frame_cache ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
GLOBAL FUNCTION
|
||||
|
||||
coff_solib_create_inferior_hook -- shared library startup support
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
void coff_solib_create_inferior_hook()
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
When gdb starts up the inferior, the kernel maps in the shared
|
||||
libraries. We get here with the target stopped at it's first
|
||||
instruction, and the libraries already mapped. At this point, this
|
||||
function gets called via expansion of the macro
|
||||
SOLIB_CREATE_INFERIOR_HOOK.
|
||||
*/
|
||||
|
||||
void
|
||||
coff_solib_create_inferior_hook (void)
|
||||
{
|
||||
coff_solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
|
||||
}
|
||||
186
gdb/coff-solib.h
186
gdb/coff-solib.h
@@ -1,186 +0,0 @@
|
||||
/* COFF (SVR3) Shared library declarations for GDB, the GNU Debugger.
|
||||
Copyright 1992, 1993, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Forward decl's for prototypes */
|
||||
struct target_ops;
|
||||
|
||||
/* Called when we free all symtabs, to free the shared library information
|
||||
as well. */
|
||||
|
||||
#if 0
|
||||
#define CLEAR_SOLIB coff_clear_solib
|
||||
|
||||
extern void coff_clear_solib (void);
|
||||
#endif
|
||||
|
||||
/* Called to add symbols from a shared library to gdb's symbol table. */
|
||||
|
||||
#define SOLIB_ADD(filename, from_tty, targ, readsyms) \
|
||||
coff_solib_add (filename, from_tty, targ, readsyms)
|
||||
|
||||
extern void coff_solib_add (char *, int, struct target_ops *, int);
|
||||
|
||||
/* Function to be called when the inferior starts up, to discover the names
|
||||
of shared libraries that are dynamically linked, the base addresses to
|
||||
which they are linked, and sufficient information to read in their symbols
|
||||
at a later time. */
|
||||
|
||||
#define SOLIB_CREATE_INFERIOR_HOOK(PID) coff_solib_create_inferior_hook()
|
||||
|
||||
extern void coff_solib_create_inferior_hook (void); /* solib.c */
|
||||
|
||||
/* Function to be called to remove the connection between debugger and
|
||||
dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
|
||||
(This operation does not remove shared library information from
|
||||
the debugger, as CLEAR_SOLIB does.)
|
||||
|
||||
This functionality is presently not implemented for this target.
|
||||
*/
|
||||
#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
|
||||
|
||||
/* This function is called by the "catch load" command. It allows
|
||||
the debugger to be notified by the dynamic linker when a specified
|
||||
library file (or any library file, if filename is NULL) is loaded.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
|
||||
/* This function is called by the "catch unload" command. It allows
|
||||
the debugger to be notified by the dynamic linker when a specified
|
||||
library file (or any library file, if filename is NULL) is unloaded.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
|
||||
/* This function returns TRUE if the dynamic linker has just reported
|
||||
a load of a library.
|
||||
|
||||
This function must be used only when the inferior has stopped in
|
||||
the dynamic linker hook, or undefined results are guaranteed.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
/*
|
||||
#define SOLIB_HAVE_LOAD_EVENT(pid) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
*/
|
||||
|
||||
#define SOLIB_HAVE_LOAD_EVENT(pid) \
|
||||
(0)
|
||||
|
||||
/* This function returns a pointer to the string representation of the
|
||||
pathname of the dynamically-linked library that has just been loaded.
|
||||
|
||||
This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
|
||||
or undefined results are guaranteed.
|
||||
|
||||
This string's contents are only valid immediately after the inferior
|
||||
has stopped in the dynamic linker hook, and becomes invalid as soon
|
||||
as the inferior is continued. Clients should make a copy of this
|
||||
string if they wish to continue the inferior and then access the string.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
|
||||
/*
|
||||
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
*/
|
||||
|
||||
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
|
||||
(0)
|
||||
|
||||
/* This function returns TRUE if the dynamic linker has just reported
|
||||
an unload of a library.
|
||||
|
||||
This function must be used only when the inferior has stopped in
|
||||
the dynamic linker hook, or undefined results are guaranteed.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
/*
|
||||
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
*/
|
||||
|
||||
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
|
||||
(0)
|
||||
|
||||
/* This function returns a pointer to the string representation of the
|
||||
pathname of the dynamically-linked library that has just been unloaded.
|
||||
|
||||
This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
|
||||
or undefined results are guaranteed.
|
||||
|
||||
This string's contents are only valid immediately after the inferior
|
||||
has stopped in the dynamic linker hook, and becomes invalid as soon
|
||||
as the inferior is continued. Clients should make a copy of this
|
||||
string if they wish to continue the inferior and then access the string.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
/*
|
||||
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
*/
|
||||
|
||||
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
|
||||
(0)
|
||||
|
||||
/* This function returns TRUE if pc is the address of an instruction that
|
||||
lies within the dynamic linker (such as the event hook, or the dld
|
||||
itself).
|
||||
|
||||
This function must be used only when a dynamic linker event has been
|
||||
caught, and the inferior is being stepped out of the hook, or undefined
|
||||
results are guaranteed.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
|
||||
/*
|
||||
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
|
||||
error("catch of library loads/unloads not yet implemented on this platform")
|
||||
*/
|
||||
|
||||
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
|
||||
(0)
|
||||
|
||||
/* This function must be called when the inferior is killed, and the program
|
||||
restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
|
||||
any symbol tables.
|
||||
|
||||
Presently, this functionality is not implemented.
|
||||
*/
|
||||
#define SOLIB_RESTART() \
|
||||
(0)
|
||||
|
||||
/* If we can't set a breakpoint, and it's in a shared library, just
|
||||
disable it. */
|
||||
|
||||
#if 0
|
||||
#define DISABLE_UNSETTABLE_BREAK(addr) coff_solib_address(addr)
|
||||
|
||||
extern int solib_address (CORE_ADDR); /* solib.c */
|
||||
#endif
|
||||
2148
gdb/coffread.c
2148
gdb/coffread.c
File diff suppressed because it is too large
Load Diff
289
gdb/command.h
289
gdb/command.h
@@ -1,289 +0,0 @@
|
||||
/* Header file for command-reading library command.c.
|
||||
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1999,
|
||||
2000, 2002 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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (COMMAND_H)
|
||||
#define COMMAND_H 1
|
||||
|
||||
/* Command classes are top-level categories into which commands are broken
|
||||
down for "help" purposes.
|
||||
Notes on classes: class_alias is for alias commands which are not
|
||||
abbreviations of the original command. class-pseudo is for
|
||||
commands which are not really commands nor help topics ("stop"). */
|
||||
|
||||
enum command_class
|
||||
{
|
||||
/* Special args to help_list */
|
||||
class_deprecated, all_classes = -2, all_commands = -1,
|
||||
/* Classes of commands */
|
||||
no_class = -1, class_run = 0, class_vars, class_stack,
|
||||
class_files, class_support, class_info, class_breakpoint, class_trace,
|
||||
class_alias, class_obscure, class_user, class_maintenance,
|
||||
class_pseudo, class_tui, class_xdb
|
||||
};
|
||||
|
||||
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
|
||||
cmd_types'' can be moved from "command.h" to "cli-decode.h". */
|
||||
/* Not a set/show command. Note that some commands which begin with
|
||||
"set" or "show" might be in this category, if their syntax does
|
||||
not fall into one of the following categories. */
|
||||
typedef enum cmd_types
|
||||
{
|
||||
not_set_cmd,
|
||||
set_cmd,
|
||||
show_cmd
|
||||
}
|
||||
cmd_types;
|
||||
|
||||
/* Types of "set" or "show" command. */
|
||||
typedef enum var_types
|
||||
{
|
||||
/* "on" or "off". *VAR is an integer which is nonzero for on,
|
||||
zero for off. */
|
||||
var_boolean,
|
||||
|
||||
/* "on" / "true" / "enable" or "off" / "false" / "disable" or
|
||||
"auto. *VAR is an ``enum auto_boolean''. NOTE: In general a
|
||||
custom show command will need to be implemented - one that for
|
||||
"auto" prints both the "auto" and the current auto-selected
|
||||
value. */
|
||||
var_auto_boolean,
|
||||
|
||||
/* Unsigned Integer. *VAR is an unsigned int. The user can type 0
|
||||
to mean "unlimited", which is stored in *VAR as UINT_MAX. */
|
||||
var_uinteger,
|
||||
|
||||
/* Like var_uinteger but signed. *VAR is an int. The user can type 0
|
||||
to mean "unlimited", which is stored in *VAR as INT_MAX. */
|
||||
var_integer,
|
||||
|
||||
/* String which the user enters with escapes (e.g. the user types \n and
|
||||
it is a real newline in the stored string).
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_string,
|
||||
/* String which stores what the user types verbatim.
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_string_noescape,
|
||||
/* String which stores a filename.
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_filename,
|
||||
/* ZeroableInteger. *VAR is an int. Like Unsigned Integer except
|
||||
that zero really means zero. */
|
||||
var_zinteger,
|
||||
/* Enumerated type. Can only have one of the specified values. *VAR is a
|
||||
char pointer to the name of the element that we find. */
|
||||
var_enum
|
||||
}
|
||||
var_types;
|
||||
|
||||
/* This structure records one command'd definition. */
|
||||
struct cmd_list_element;
|
||||
|
||||
/* Forward-declarations of the entry-points of cli/cli-decode.c. */
|
||||
|
||||
extern struct cmd_list_element *add_cmd (char *, enum command_class,
|
||||
void (*fun) (char *, int), char *,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_alias_cmd (char *, char *,
|
||||
enum command_class, int,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_prefix_cmd (char *, enum command_class,
|
||||
void (*fun) (char *, int),
|
||||
char *,
|
||||
struct cmd_list_element **,
|
||||
char *, int,
|
||||
struct cmd_list_element **);
|
||||
|
||||
extern struct cmd_list_element *add_abbrev_prefix_cmd (char *,
|
||||
enum command_class,
|
||||
void (*fun) (char *,
|
||||
int),
|
||||
char *,
|
||||
struct cmd_list_element
|
||||
**, char *, int,
|
||||
struct cmd_list_element
|
||||
**);
|
||||
|
||||
/* Set the commands corresponding callback. */
|
||||
|
||||
typedef void cmd_cfunc_ftype (char *args, int from_tty);
|
||||
extern void set_cmd_cfunc (struct cmd_list_element *cmd,
|
||||
cmd_cfunc_ftype *cfunc);
|
||||
|
||||
typedef void cmd_sfunc_ftype (char *args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||
cmd_sfunc_ftype *sfunc);
|
||||
|
||||
extern void set_cmd_completer (struct cmd_list_element *cmd,
|
||||
char **(*completer) (char *text, char *word));
|
||||
|
||||
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
|
||||
around in cmd objects to test the value of the commands sfunc(). */
|
||||
extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
|
||||
/* Each command object has a local context attached to it. . */
|
||||
extern void set_cmd_context (struct cmd_list_element *cmd, void *context);
|
||||
extern void *get_cmd_context (struct cmd_list_element *cmd);
|
||||
|
||||
|
||||
/* Execute CMD's pre/post hook. Throw an error if the command fails.
|
||||
If already executing this pre/post hook, or there is no pre/post
|
||||
hook, the call is silently ignored. */
|
||||
extern void execute_cmd_pre_hook (struct cmd_list_element *cmd);
|
||||
extern void execute_cmd_post_hook (struct cmd_list_element *cmd);
|
||||
|
||||
/* Return the type of the command. */
|
||||
/* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
|
||||
the set command passed as a parameter. The clone operation will
|
||||
include (BUG?) any ``set'' command callback, if present. Commands
|
||||
like ``info set'' call all the ``show'' command callbacks.
|
||||
Unfortunatly, for ``show'' commands cloned from ``set'', this
|
||||
includes callbacks belonging to ``set'' commands. Making this
|
||||
worse, this only occures if add_show_from_set() is called after
|
||||
add_cmd_sfunc() (BUG?). */
|
||||
extern enum cmd_types cmd_type (struct cmd_list_element *cmd);
|
||||
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd (char **,
|
||||
struct cmd_list_element *, char *,
|
||||
int, int);
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd_1 (char **,
|
||||
struct cmd_list_element *,
|
||||
struct cmd_list_element **,
|
||||
int);
|
||||
|
||||
extern struct cmd_list_element *
|
||||
deprecate_cmd (struct cmd_list_element *, char * );
|
||||
|
||||
extern void
|
||||
deprecated_cmd_warning (char **);
|
||||
|
||||
extern int
|
||||
lookup_cmd_composition (char *text,
|
||||
struct cmd_list_element **alias,
|
||||
struct cmd_list_element **prefix_cmd,
|
||||
struct cmd_list_element **cmd);
|
||||
|
||||
extern struct cmd_list_element *add_com (char *, enum command_class,
|
||||
void (*fun) (char *, int), char *);
|
||||
|
||||
extern struct cmd_list_element *add_com_alias (char *, char *,
|
||||
enum command_class, int);
|
||||
|
||||
extern struct cmd_list_element *add_info (char *, void (*fun) (char *, int),
|
||||
char *);
|
||||
|
||||
extern struct cmd_list_element *add_info_alias (char *, char *, int);
|
||||
|
||||
extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *);
|
||||
|
||||
extern char **complete_on_enum (const char *enumlist[], char *, char *);
|
||||
|
||||
extern void delete_cmd (char *, struct cmd_list_element **);
|
||||
|
||||
extern void help_cmd (char *, struct ui_file *);
|
||||
|
||||
extern void help_list (struct cmd_list_element *, char *,
|
||||
enum command_class, struct ui_file *);
|
||||
|
||||
extern void help_cmd_list (struct cmd_list_element *, enum command_class,
|
||||
char *, int, struct ui_file *);
|
||||
|
||||
extern void add_setshow_cmd (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern void add_setshow_cmd_full (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list,
|
||||
struct cmd_list_element **set_result,
|
||||
struct cmd_list_element **show_result);
|
||||
|
||||
extern struct cmd_list_element *add_set_cmd (char *name, enum
|
||||
command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_set_enum_cmd (char *name,
|
||||
enum command_class class,
|
||||
const char *enumlist[],
|
||||
const char **var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern void add_setshow_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum auto_boolean *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern void add_setshow_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var,
|
||||
char *set_doc,
|
||||
char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern struct cmd_list_element *add_show_from_set (struct cmd_list_element *,
|
||||
struct cmd_list_element
|
||||
**);
|
||||
|
||||
/* Do a "show" command for each thing on a command list. */
|
||||
|
||||
extern void cmd_show_list (struct cmd_list_element *, int, char *);
|
||||
|
||||
extern NORETURN void error_no_arg (char *) ATTR_NORETURN;
|
||||
|
||||
extern void dont_repeat (void);
|
||||
|
||||
/* Used to mark commands that don't do anything. If we just leave the
|
||||
function field NULL, the command is interpreted as a help topic, or
|
||||
as a class of commands. */
|
||||
|
||||
extern void not_just_help_class_command (char *, int);
|
||||
|
||||
/* check function pointer */
|
||||
extern int cmd_func_p (struct cmd_list_element *cmd);
|
||||
|
||||
/* call the command function */
|
||||
extern void cmd_func (struct cmd_list_element *cmd, char *args, int from_tty);
|
||||
|
||||
#endif /* !defined (COMMAND_H) */
|
||||
168
gdb/complaints.c
168
gdb/complaints.c
@@ -1,168 +0,0 @@
|
||||
/* Support for complaint handling during symbol reading in GDB.
|
||||
Copyright 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
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 2 of the License, 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., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "complaints.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
extern void _initialize_complaints (void);
|
||||
|
||||
/* Structure to manage complaints about symbol file contents. */
|
||||
|
||||
struct complaint complaint_root[1] =
|
||||
{
|
||||
{
|
||||
(char *) NULL, /* Complaint message */
|
||||
0, /* Complaint counter */
|
||||
complaint_root /* Next complaint. */
|
||||
}
|
||||
};
|
||||
|
||||
/* How many complaints about a particular thing should be printed before
|
||||
we stop whining about it? Default is no whining at all, since so many
|
||||
systems have ill-constructed symbol files. */
|
||||
|
||||
static unsigned int stop_whining = 0;
|
||||
|
||||
/* Should each complaint be self explanatory, or should we assume that
|
||||
a series of complaints is being produced?
|
||||
case 0: self explanatory message.
|
||||
case 1: First message of a series that must start off with explanation.
|
||||
case 2: Subsequent message, when user already knows we are reading
|
||||
symbols and we can just state our piece. */
|
||||
|
||||
static int complaint_series = 0;
|
||||
|
||||
|
||||
|
||||
/* Functions to handle complaints during symbol reading. */
|
||||
|
||||
/* Print a complaint about the input symbols, and link the complaint block
|
||||
into a chain for later handling. */
|
||||
|
||||
void
|
||||
complain (struct complaint *complaint,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, complaint);
|
||||
|
||||
complaint->counter++;
|
||||
if (complaint->next == NULL)
|
||||
{
|
||||
complaint->next = complaint_root->next;
|
||||
complaint_root->next = complaint;
|
||||
}
|
||||
if (complaint->counter > stop_whining)
|
||||
{
|
||||
return;
|
||||
}
|
||||
wrap_here ("");
|
||||
|
||||
switch (complaint_series + (info_verbose << 1))
|
||||
{
|
||||
|
||||
/* Isolated messages, must be self-explanatory. */
|
||||
case 0:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
begin_line ();
|
||||
fputs_filtered ("During symbol reading, ", gdb_stderr);
|
||||
wrap_here ("");
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered (".\n", gdb_stderr);
|
||||
}
|
||||
break;
|
||||
|
||||
/* First of a series, without `set verbose'. */
|
||||
case 1:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
begin_line ();
|
||||
fputs_filtered ("During symbol reading...", gdb_stderr);
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered ("...", gdb_stderr);
|
||||
wrap_here ("");
|
||||
complaint_series++;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Subsequent messages of a series, or messages under `set verbose'.
|
||||
(We'll already have produced a "Reading in symbols for XXX..."
|
||||
message and will clean up at the end with a newline.) */
|
||||
default:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered ("...", gdb_stderr);
|
||||
wrap_here ("");
|
||||
}
|
||||
}
|
||||
/* If GDB dumps core, we'd like to see the complaints first. Presumably
|
||||
GDB will not be sending so many complaints that this becomes a
|
||||
performance hog. */
|
||||
gdb_flush (gdb_stderr);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* Clear out all complaint counters that have ever been incremented.
|
||||
If sym_reading is 1, be less verbose about successive complaints,
|
||||
since the messages are appearing all together during a command that
|
||||
reads symbols (rather than scattered around as psymtabs get fleshed
|
||||
out into symtabs at random times). If noisy is 1, we are in a
|
||||
noisy symbol reading command, and our caller will print enough
|
||||
context for the user to figure it out. */
|
||||
|
||||
void
|
||||
clear_complaints (int sym_reading, int noisy)
|
||||
{
|
||||
struct complaint *p;
|
||||
|
||||
for (p = complaint_root->next; p != complaint_root; p = p->next)
|
||||
{
|
||||
p->counter = 0;
|
||||
}
|
||||
|
||||
if (!sym_reading && !noisy && complaint_series > 1 && !warning_hook)
|
||||
{
|
||||
/* Terminate previous series, since caller won't. */
|
||||
puts_filtered ("\n");
|
||||
}
|
||||
|
||||
complaint_series = sym_reading ? 1 + noisy : 0;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_complaints (void)
|
||||
{
|
||||
add_show_from_set
|
||||
(add_set_cmd ("complaints", class_support, var_zinteger,
|
||||
(char *) &stop_whining,
|
||||
"Set max number of complaints about incorrect symbols.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user