mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
1 Commits
gdb-10.2-r
...
binutils-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3192601f34 |
52
djunpack.bat
52
djunpack.bat
@@ -1,52 +0,0 @@
|
||||
@echo off
|
||||
Rem
|
||||
Rem WARNING WARNING WARNING: This file needs to have DOS CRLF end-of-line
|
||||
Rem format, or else stock DOS/Windows shells will refuse to run it.
|
||||
Rem
|
||||
Rem This batch file unpacks the GDB distribution while simultaneously
|
||||
Rem renaming some of the files whose names are invalid on DOS or conflict
|
||||
Rem with other file names after truncation to DOS 8+3 namespace.
|
||||
Rem
|
||||
Rem Invoke like this:
|
||||
Rem
|
||||
Rem djunpack gdb-XYZ.tar
|
||||
Rem
|
||||
Rem where XYZ is the version number. If the argument includes leading
|
||||
Rem directories, it MUST use backslashes, not forward slashes.
|
||||
Rem
|
||||
Rem The following 2 lines need to be changed with each new GDB release, to
|
||||
Rem be identical to the name of the top-level directory where the GDB
|
||||
Rem distribution unpacks itself.
|
||||
set GDBVER=gdb-5.0
|
||||
if "%GDBVER%"=="gdb-5.0" GoTo EnvOk
|
||||
Rem If their environment space is too small, re-exec with a larger one
|
||||
command.com /e:4096 /c %0 %1
|
||||
GoTo End
|
||||
:EnvOk
|
||||
if not exist %1 GoTo NoArchive
|
||||
djtar -x -p -o %GDBVER%/gdb/config/djgpp/fnchange.lst %1 > fnchange.tmp
|
||||
Rem The following uses a feature of COPY whereby it does not copy
|
||||
Rem empty files. We need that because the previous line will create
|
||||
Rem an empty fnchange.tmp even if the command failed for some reason.
|
||||
copy fnchange.tmp junk.tmp > nul
|
||||
if not exist junk.tmp GoTo NoDjTar
|
||||
del junk.tmp
|
||||
sed -e 's,@V@,%GDBVER%,g' < fnchange.tmp > fnchange.lst
|
||||
Rem See the comment above about the reason for using COPY.
|
||||
copy fnchange.lst junk.tmp > nul
|
||||
if not exist junk.tmp GoTo NoSed
|
||||
del junk.tmp
|
||||
djtar -x -n fnchange.lst %1
|
||||
GoTo End
|
||||
:NoSed
|
||||
echo FAIL: Sed is not available.
|
||||
GoTo End
|
||||
:NoDjTar
|
||||
echo FAIL: DJTAR is not available or no fnchange.lst file in %1.
|
||||
GoTo End
|
||||
:NoArchive
|
||||
echo FAIL: the file %1 does not seem to exist.
|
||||
echo Remember that %1 cannot use forward slashes, only backslashes.
|
||||
GoTo End
|
||||
:End
|
||||
set GDBVER=
|
||||
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.
|
||||
5174
gdb/ChangeLog
5174
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
15039
gdb/ChangeLog-2002
15039
gdb/ChangeLog-2002
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
421
gdb/MAINTAINERS
421
gdb/MAINTAINERS
@@ -1,421 +0,0 @@
|
||||
GDB Maintainers
|
||||
|
||||
|
||||
Global Maintainers
|
||||
(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
|
||||
Daniel Jacobowitz dan@debian.org
|
||||
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 a global 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 Instruction Set Architectures:
|
||||
|
||||
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-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
arc Deleted.
|
||||
|
||||
arm --target=arm-elf ,-Werror
|
||||
Scott Bambrough scottb@netwinder.org
|
||||
Richard Earnshaw rearnsha@arm.com
|
||||
|
||||
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 Deleted.
|
||||
|
||||
fr30 Deleted.
|
||||
|
||||
h8300 --target=h8300hms ,-Werror
|
||||
Maintenance only
|
||||
|
||||
h8500 (--target=h8500hms OBSOLETE)
|
||||
|
||||
i386 --target=i386-elf ,-Werror
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
|
||||
i960 Deleted.
|
||||
|
||||
ia64 --target=ia64-linux-gnu ,-Werror
|
||||
(--target=ia64-elf broken)
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
m32r (--target=m32r-elf OBSOLETE)
|
||||
|
||||
m68hc11 --target=m68hc11-elf ,-Werror ,
|
||||
Stephane Carrez stcarrez@nerim.fr
|
||||
|
||||
m68k --target=m68k-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
m88k Deleted.
|
||||
|
||||
mcore --target=mcore-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
mips --target=mips-elf ,-Werror
|
||||
Andrew Cagney cagney@redhat.com
|
||||
|
||||
mn10200 (--target=mn10200-elf OBSOLETE)
|
||||
|
||||
mn10300 --target=mn10300-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
ns32k --target=ns32k-netbsd ,-Werror
|
||||
Maintenance only
|
||||
|
||||
pa (--target=hppa-elf broken)
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
powerpc --target=powerpc-eabi ,-Werror
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
s390 --target=s390-linux-gnu ,-Werror
|
||||
(contact DJ Barrow djbarrow@de.ibm.com)
|
||||
|
||||
sh --target=sh-elf ,-Werror
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
|
||||
sparc --target=sparc-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
tic80 Deleted.
|
||||
|
||||
v850 --target=v850-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
vax --target=vax-netbsd ,-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 OBSOLETE)
|
||||
|
||||
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 gdb_mbuild.sh can be used to rebuild all the
|
||||
above targets.
|
||||
|
||||
|
||||
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, '00, 9x, Me, XP) host & native
|
||||
Chris Faylor cgf@redhat.com
|
||||
GNU/Linux/x86 native & host
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
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
|
||||
|
||||
event loop Elena Zannoni ezannoni@redhat.com
|
||||
For the part of top.c related to the event loop,
|
||||
send questions to 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 Elena Zannoni ezannoni@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
|
||||
language support (Blanket Write Privs Maintainers)
|
||||
C++ Daniel Jacobowitz dan@debian.org
|
||||
Java support (Global Maintainers)
|
||||
Pascal support Pierre Muller muller@sources.redhat.com
|
||||
|
||||
shared libs (devolved) 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 (vacant)
|
||||
rdi/adp protocol (vacant)
|
||||
documentation Eli Zaretskii eliz@gnu.org
|
||||
testsuite (Global Maintainers)
|
||||
config Mark Salter msalter@redhat.com
|
||||
lib Fernando Nasser fnasser@redhat.com
|
||||
Mark Salter msalter@redhat.com
|
||||
gdbtk (gdb.gdbtk) Keith Seitz keiths@redhat.com
|
||||
c++ (gdb.c++) Michael Chastain mec@shout.net
|
||||
David Carlton carlton@math.stanford.edu
|
||||
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 (Global Maintainers)
|
||||
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 Stephane Carrez stcarrez@nerim.fr
|
||||
(Global Maintainers)
|
||||
|
||||
|
||||
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
|
||||
David Carlton carlton@math.stanford.edu
|
||||
Stephane Carrez stcarrez@nerim.fr
|
||||
Michael Chastain mec@shout.net
|
||||
Eric Christopher echristo@redhat.com
|
||||
Nick Clifton nickc@redhat.com
|
||||
DJ Delorie dj@redhat.com
|
||||
Chris G. Demetriou cgd@broadcom.com
|
||||
Philippe De Muyter phdm@macqel.be
|
||||
Klee Dienes kdienes@apple.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
|
||||
Adam Fedor fedor@gnu.org
|
||||
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@cs.umass.edu
|
||||
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
|
||||
Jeff Johnston jjohnstn@redhat.com
|
||||
Geoff Keating geoffk@redhat.com
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
Jim Kingdon jkingdon@engr.sgi.com ++
|
||||
Jonathan Larmour jlarmour@redhat.co.uk
|
||||
Jeff Law law@redhat.com
|
||||
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
|
||||
Marko Mlinar markom@opencores.org
|
||||
Alan Modra amodra@bigpond.net.au
|
||||
Jason Molenda jmolenda@apple.com
|
||||
Pierre Muller muller@sources.redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
Hans-Peter Nilsson hp@bitrange.com
|
||||
David O'Brien obrien@freebsd.org
|
||||
Alexandre Oliva aoliva@redhat.com
|
||||
Tom Rix trix@redhat.com
|
||||
Bob Rossi bob_rossi@cox.net
|
||||
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
|
||||
Stan Shebs shebs@apple.com
|
||||
Aidan Skinner aidan@velvet.net
|
||||
Jiri Smid smid@suse.cz
|
||||
David Smith dsmith@redhat.com
|
||||
Stephen P. Smith ischis2@cox.net
|
||||
Jackie Smith Cashion jsmith@redhat.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
|
||||
D Venkatasubramanian dvenkat@noida.hcltech.com
|
||||
Corinna Vinschen vinschen@redhat.com
|
||||
Keith Walker keith.walker@arm.com
|
||||
Kris Warkentin kewarken@qnx.com
|
||||
Jim Wilson wilson@tuliptree.org
|
||||
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
|
||||
Per Bothner (Java) per at bothner dot com
|
||||
Anthony Green (Java) green 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.
|
||||
2727
gdb/Makefile.in
2727
gdb/Makefile.in
File diff suppressed because it is too large
Load Diff
80
gdb/PROBLEMS
80
gdb/PROBLEMS
@@ -1,80 +0,0 @@
|
||||
|
||||
Known problems in GDB 5.3
|
||||
|
||||
See also: http://www.gnu.org/software/gdb/bugs/
|
||||
|
||||
|
||||
*-*-freebsd*
|
||||
---------------
|
||||
|
||||
Due to a kernel bug (kern/35175), detaching from an attached process
|
||||
will very likely cause the process to be stop or die with a Trace/BPT
|
||||
trap.
|
||||
|
||||
|
||||
i386-*-freebsd[34]*
|
||||
-------------------
|
||||
|
||||
There is a bug (bin/41671) in FreeBSD's gcc that causes it to emit bad
|
||||
debug information when using the stabs format (which is the default).
|
||||
As a result GDB tends to place breakpoints on functions before the
|
||||
function prologue, and information about function parameters and local
|
||||
variables is lost. In earlier versions of GDB the effects were rather
|
||||
limited, but starting with GDB 5.3 the influence is much more
|
||||
prominent. As a workaround, compile your code with -gdwarf-2.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
alpha*-*-osf*
|
||||
-------------
|
||||
|
||||
gdb/816: When building GDB with GCC 3.0.1, GDB is unable to load a core
|
||||
file properly. It generates several errors and warnings regarding
|
||||
unhandled core file section types, incorrect endianness, the failure to
|
||||
load the registers. Are also incorrectly reported: The program name, the
|
||||
cause of the program death, and the call stack at the moment of the
|
||||
death. This problem has been reported on alpha-osf4.0f and alpha-osf5.1a.
|
||||
To work-around the problem, add -D__digital__ to the CFLAGS when
|
||||
building GDB vis:
|
||||
|
||||
$ make CFLAGS='-O2 -D__digital__'
|
||||
|
||||
|
||||
i[3456]86-*-linux*
|
||||
------------------
|
||||
|
||||
gdb/660: gdb does not build with GNU/Linux libc5. The symptom is a
|
||||
parse error before `uintptr_t' or an error message about `uintptr_t'.
|
||||
Upgrade to glibc 2.1.3 or later, which defines uintptr_t.
|
||||
|
||||
gdb/1030: GNU binutils 2.12.1 and earlier versions do not work properly
|
||||
with gdb. If you use GNU binutils, upgrade to version 2.13 or later.
|
||||
You can check the version of binutils with the command:
|
||||
|
||||
$ ld --version
|
||||
574
gdb/README
574
gdb/README
@@ -1,574 +0,0 @@
|
||||
README for gdb-5.3 release
|
||||
Updated 5th September, 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.3 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.3.tar.gz file, you'll find a directory
|
||||
called `gdb-5.3', 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.3
|
||||
./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.3/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.3/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'.
|
||||
|
||||
Make sure that your 'configure' line ends in 'gdb-5.3/configure':
|
||||
|
||||
/berman/migchain/source/gdb-5.3/configure # RIGHT
|
||||
/berman/migchain/source/gdb-5.3/gdb/configure # WRONG
|
||||
|
||||
The gdb package contains several subdirectories, such as 'gdb',
|
||||
'bfd', and 'readline'. If your 'configure' line ends in
|
||||
'gdb-5.3/gdb/configure', then you are configuring only the gdb
|
||||
subdirectory, not the whole gdb package. This leads to build errors
|
||||
such as:
|
||||
|
||||
make: *** No rule to make target `../bfd/bfd.h', needed by `gdb.o'. Stop.
|
||||
|
||||
If you get other 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.3/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.3', in the case of version 5.3), 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.3/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.3/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.3/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.3 distribution is in the `gdb-5.3'
|
||||
directory. That directory contains:
|
||||
|
||||
`gdb-5.3/{COPYING,COPYING.LIB}'
|
||||
Standard GNU license files. Please read them.
|
||||
|
||||
`gdb-5.3/bfd'
|
||||
source for the Binary File Descriptor library
|
||||
|
||||
`gdb-5.3/config*'
|
||||
script for configuring GDB, along with other support files
|
||||
|
||||
`gdb-5.3/gdb'
|
||||
the source specific to GDB itself
|
||||
|
||||
`gdb-5.3/include'
|
||||
GNU include files
|
||||
|
||||
`gdb-5.3/libiberty'
|
||||
source for the `-liberty' free software library
|
||||
|
||||
`gdb-5.3/mmalloc'
|
||||
source for the GNU memory-mapped malloc package
|
||||
|
||||
`gdb-5.3/opcodes'
|
||||
source for the library of opcode tables and disassemblers
|
||||
|
||||
`gdb-5.3/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.3/sim'
|
||||
source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc)
|
||||
|
||||
`gdb-5.3/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.3/texinfo'
|
||||
The `texinfo.tex' file, which you need in order to make a printed
|
||||
manual using TeX.
|
||||
|
||||
`gdb-5.3/etc'
|
||||
Coding standards, useful files for editing GDB, and other
|
||||
miscellanea.
|
||||
|
||||
`gdb-5.3/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.3' 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.3
|
||||
./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.3'
|
||||
source directory for version 5.3, `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.3, type the following to configure only
|
||||
the `bfd' subdirectory:
|
||||
|
||||
cd gdb-5.3/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.3, you can build GDB in a separate
|
||||
directory for a Sun 4 like this:
|
||||
|
||||
cd gdb-5.3
|
||||
mkdir ../gdb-sun4
|
||||
cd ../gdb-sun4
|
||||
../gdb-5.3/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.3' (or in a separate configured directory configured with
|
||||
`--srcdir=PATH/gdb-5.3'), 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.3', for version 5.3).
|
||||
|
||||
|
||||
`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-array.c Array Tech RAID controller
|
||||
remote-e7000.c Hitachi E7000 ICE
|
||||
remote-est.c EST emulator
|
||||
remote-hms.c Hitachi Micro Systems H8/300 monitor
|
||||
remote-mips.c MIPS remote debugging protocol
|
||||
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-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.
|
||||
|
||||
|
||||
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.3), 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/links/
|
||||
|
||||
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.3
|
||||
make check-gdb
|
||||
|
||||
or
|
||||
|
||||
(2) cd gdb-5.3/gdb
|
||||
make check
|
||||
|
||||
or
|
||||
|
||||
(3) cd gdb-5.3/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:
|
||||
337
gdb/TODO
337
gdb/TODO
@@ -1,337 +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.
|
||||
|
||||
--
|
||||
|
||||
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.
|
||||
|
||||
--
|
||||
|
||||
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:
|
||||
180
gdb/abug-rom.c
180
gdb/abug-rom.c
@@ -1,180 +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"
|
||||
|
||||
#include "m68k-tdep.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' + M68K_D0_REGNUM;
|
||||
break;
|
||||
case 'A':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + M68K_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);
|
||||
}
|
||||
167
gdb/acconfig.h
167
gdb/acconfig.h
@@ -1,167 +0,0 @@
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
/* Multi-arch enabled. */
|
||||
#undef GDB_MULTI_ARCH
|
||||
|
||||
/* hostfile */
|
||||
#undef GDB_XM_FILE
|
||||
|
||||
/* targetfile */
|
||||
#undef GDB_TM_FILE
|
||||
|
||||
/* nativefile */
|
||||
#undef GDB_NM_FILE
|
||||
945
gdb/acinclude.m4
945
gdb/acinclude.m4
@@ -1,945 +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_CC_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)
|
||||
])
|
||||
|
||||
|
||||
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
|
||||
])
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
|
||||
done
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_func_iconv=yes)
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_lib_iconv=yes
|
||||
am_cv_func_iconv=yes)
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
fi
|
||||
LIBICONV=
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
LIBICONV="-liconv"
|
||||
fi
|
||||
AC_SUBST(LIBICONV)
|
||||
])
|
||||
|
||||
# AC_GNU_SOURCE
|
||||
# -------------
|
||||
# FIXME: Remove thise once we start using Autoconf 2.5x (x>=4).
|
||||
AC_DEFUN([AC_GNU_SOURCE],
|
||||
[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl
|
||||
AC_BEFORE([$0], [AC_TRY_RUN])dnl
|
||||
AC_DEFINE([_GNU_SOURCE])
|
||||
])
|
||||
|
||||
dnl written by Guido Draheim <guidod@gmx.de>, original by Alexandre Oliva
|
||||
dnl Version 1.3 (2001/03/02)
|
||||
dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html
|
||||
|
||||
AC_DEFUN([AC_DEFINE_DIR], [
|
||||
test "x$prefix" = xNONE && prefix="$ac_default_prefix"
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
ac_define_dir=`eval echo [$]$2`
|
||||
ac_define_dir=`eval echo [$]ac_define_dir`
|
||||
ifelse($3, ,
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir"),
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3))
|
||||
])
|
||||
|
||||
987
gdb/aclocal.m4
vendored
987
gdb/aclocal.m4
vendored
@@ -1,987 +0,0 @@
|
||||
dnl aclocal.m4 generated automatically by aclocal 1.4
|
||||
|
||||
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
dnl PARTICULAR PURPOSE.
|
||||
|
||||
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_CC_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)
|
||||
])
|
||||
|
||||
|
||||
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],)
|
||||
])
|
||||
|
||||
|
||||
# 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
|
||||
])
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
|
||||
done
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_func_iconv=yes)
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_lib_iconv=yes
|
||||
am_cv_func_iconv=yes)
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
fi
|
||||
LIBICONV=
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
LIBICONV="-liconv"
|
||||
fi
|
||||
AC_SUBST(LIBICONV)
|
||||
])
|
||||
|
||||
# AC_GNU_SOURCE
|
||||
# -------------
|
||||
# FIXME: Remove thise once we start using Autoconf 2.5x (x>=4).
|
||||
AC_DEFUN([AC_GNU_SOURCE],
|
||||
[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl
|
||||
AC_BEFORE([$0], [AC_TRY_RUN])dnl
|
||||
AC_DEFINE([_GNU_SOURCE])
|
||||
])
|
||||
|
||||
dnl written by Guido Draheim <guidod@gmx.de>, original by Alexandre Oliva
|
||||
dnl Version 1.3 (2001/03/02)
|
||||
dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html
|
||||
|
||||
AC_DEFUN([AC_DEFINE_DIR], [
|
||||
test "x$prefix" = xNONE && prefix="$ac_default_prefix"
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
ac_define_dir=`eval echo [$]$2`
|
||||
ac_define_dir=`eval echo [$]ac_define_dir`
|
||||
ifelse($3, ,
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir"),
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3))
|
||||
])
|
||||
|
||||
|
||||
# Add --enable-maintainer-mode option to configure.
|
||||
# From Jim Meyering
|
||||
|
||||
# serial 1
|
||||
|
||||
AC_DEFUN(AM_MAINTAINER_MODE,
|
||||
[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
|
||||
dnl maintainer-mode is disabled by default
|
||||
AC_ARG_ENABLE(maintainer-mode,
|
||||
[ --enable-maintainer-mode enable make rules and dependencies not useful
|
||||
(and sometimes confusing) to the casual installer],
|
||||
USE_MAINTAINER_MODE=$enableval,
|
||||
USE_MAINTAINER_MODE=no)
|
||||
AC_MSG_RESULT($USE_MAINTAINER_MODE)
|
||||
AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
|
||||
MAINT=$MAINTAINER_MODE_TRUE
|
||||
AC_SUBST(MAINT)dnl
|
||||
]
|
||||
)
|
||||
|
||||
# Define a conditional.
|
||||
|
||||
AC_DEFUN(AM_CONDITIONAL,
|
||||
[AC_SUBST($1_TRUE)
|
||||
AC_SUBST($1_FALSE)
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi])
|
||||
|
||||
969
gdb/ada-exp.y
969
gdb/ada-exp.y
@@ -1,969 +0,0 @@
|
||||
/* YACC parser for Ada expressions, for GDB.
|
||||
Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003
|
||||
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"
|
||||
#include "block.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 */
|
||||
#define yyname ada_name /* With YYDEBUG defined */
|
||||
#define yyrule ada_rule /* 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 = DEPRECATED_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",
|
||||
DEPRECATED_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;
|
||||
}
|
||||
8315
gdb/ada-lang.c
8315
gdb/ada-lang.c
File diff suppressed because it is too large
Load Diff
392
gdb/ada-lang.h
392
gdb/ada-lang.h
@@ -1,392 +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
|
||||
|
||||
struct partial_symbol;
|
||||
|
||||
#include "value.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
struct block;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
820
gdb/ada-tasks.c
820
gdb/ada-tasks.c
@@ -1,820 +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 (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 (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 (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 (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 (void)
|
||||
{
|
||||
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 (int task)
|
||||
{
|
||||
return get_entry_vptr (task) != NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
get_self_id (void)
|
||||
{
|
||||
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 (void)
|
||||
{
|
||||
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 (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 (void)
|
||||
{
|
||||
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 (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 (void)
|
||||
{
|
||||
gdbtk_task_initialization = 1;
|
||||
info_tasks ("", gdb_stdout);
|
||||
|
||||
return (task_list != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
info_tasks_command (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 (void *tid, void *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 (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 (deprecated_selected_frame, frame_relative_level (deprecated_selected_frame)); */
|
||||
printf_filtered ("[Switching to task %d]\n", num);
|
||||
print_stack_frame (deprecated_selected_frame,
|
||||
frame_relative_level (deprecated_selected_frame), 1);
|
||||
}
|
||||
else
|
||||
printf_filtered ("Unable to switch to task %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_tasks (void)
|
||||
{
|
||||
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,852 +0,0 @@
|
||||
/* Support for printing Ada types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1997, 2003 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 "gdb_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 "gdb_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 (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 (struct type *type, struct symbol *new,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
fprintf_filtered (stream, "type %.*s is ",
|
||||
ada_name_prefix_len (SYMBOL_PRINT_NAME (new)),
|
||||
SYMBOL_PRINT_NAME (new));
|
||||
type_print (type, "", stream, 1);
|
||||
}
|
||||
|
||||
/* Print range type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_range (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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;
|
||||
}
|
||||
}
|
||||
@@ -1,988 +0,0 @@
|
||||
/* Support for printing Ada values for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1997, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "demangle.h"
|
||||
#include "valprint.h"
|
||||
#include "language.h"
|
||||
#include "annotate.h"
|
||||
#include "ada-lang.h"
|
||||
#include "c-lang.h"
|
||||
#include "infcall.h"
|
||||
|
||||
/* Encapsulates arguments to ada_val_print. */
|
||||
struct ada_val_print_args
|
||||
{
|
||||
struct type *type;
|
||||
char *valaddr0;
|
||||
int embedded_offset;
|
||||
CORE_ADDR address;
|
||||
struct ui_file *stream;
|
||||
int format;
|
||||
int deref_ref;
|
||||
int recurse;
|
||||
enum val_prettyprint pretty;
|
||||
};
|
||||
|
||||
extern int inspect_it;
|
||||
extern unsigned int repeat_count_threshold;
|
||||
|
||||
static void print_record (struct type *, char *, struct ui_file *, int,
|
||||
int, enum val_prettyprint);
|
||||
|
||||
static int print_field_values (struct type *, char *, struct ui_file *,
|
||||
int, int, enum val_prettyprint,
|
||||
int, struct type *, char *);
|
||||
|
||||
static int print_variant_part (struct type *, int, char *,
|
||||
struct ui_file *, int, int,
|
||||
enum val_prettyprint, int, struct type *,
|
||||
char *);
|
||||
|
||||
static void val_print_packed_array_elements (struct type *, char *valaddr,
|
||||
int, struct ui_file *, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
static void adjust_type_signedness (struct type *);
|
||||
|
||||
static int ada_val_print_stub (void *args0);
|
||||
|
||||
static int ada_val_print_1 (struct type *, char *, int, CORE_ADDR,
|
||||
struct ui_file *, int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
|
||||
/* Make TYPE unsigned if its range of values includes no negatives. */
|
||||
static void
|
||||
adjust_type_signedness (struct type *type)
|
||||
{
|
||||
if (type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE
|
||||
&& TYPE_LOW_BOUND (type) >= 0)
|
||||
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
|
||||
}
|
||||
|
||||
/* Assuming TYPE is a simple array type, prints its lower bound on STREAM,
|
||||
if non-standard (i.e., other than 1 for numbers, other than lower bound
|
||||
of index type for enumerated type). Returns 1 if something printed,
|
||||
otherwise 0. */
|
||||
|
||||
static int
|
||||
print_optional_low_bound (struct ui_file *stream, struct type *type)
|
||||
{
|
||||
struct type *index_type;
|
||||
long low_bound;
|
||||
|
||||
index_type = TYPE_INDEX_TYPE (type);
|
||||
low_bound = 0;
|
||||
|
||||
if (index_type == NULL)
|
||||
return 0;
|
||||
if (TYPE_CODE (index_type) == TYPE_CODE_RANGE)
|
||||
{
|
||||
low_bound = TYPE_LOW_BOUND (index_type);
|
||||
index_type = TYPE_TARGET_TYPE (index_type);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
switch (TYPE_CODE (index_type))
|
||||
{
|
||||
case TYPE_CODE_ENUM:
|
||||
if (low_bound == TYPE_FIELD_BITPOS (index_type, 0))
|
||||
return 0;
|
||||
break;
|
||||
case TYPE_CODE_UNDEF:
|
||||
index_type = builtin_type_long;
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
if (low_bound == 1)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ada_print_scalar (index_type, (LONGEST) low_bound, stream);
|
||||
fprintf_filtered (stream, " => ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Version of val_print_array_elements for GNAT-style packed arrays.
|
||||
Prints elements of packed array of type TYPE at bit offset
|
||||
BITOFFSET from VALADDR on STREAM. Formats according to FORMAT and
|
||||
separates with commas. RECURSE is the recursion (nesting) level.
|
||||
If PRETTY, uses "prettier" format. TYPE must have been decoded (as
|
||||
by ada_coerce_to_simple_array). */
|
||||
|
||||
static void
|
||||
val_print_packed_array_elements (struct type *type, char *valaddr,
|
||||
int bitoffset, struct ui_file *stream,
|
||||
int format, int recurse,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
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;
|
||||
unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
|
||||
struct value *mark = value_mark ();
|
||||
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
eltlen = TYPE_LENGTH (check_typedef (elttype));
|
||||
|
||||
{
|
||||
LONGEST low, high;
|
||||
if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), &low, &high) < 0)
|
||||
len = 1;
|
||||
else
|
||||
len = high - low + 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
annotate_array_section_begin (i, elttype);
|
||||
|
||||
while (i < len && things_printed < print_max)
|
||||
{
|
||||
struct value *v0, *v1;
|
||||
int i0;
|
||||
|
||||
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));
|
||||
|
||||
i0 = i;
|
||||
v0 = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
(i0 * bitsize) / HOST_CHAR_BIT,
|
||||
(i0 * bitsize) % HOST_CHAR_BIT,
|
||||
bitsize, elttype);
|
||||
while (1)
|
||||
{
|
||||
i += 1;
|
||||
if (i >= len)
|
||||
break;
|
||||
v1 = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
(i * bitsize) / HOST_CHAR_BIT,
|
||||
(i * bitsize) % HOST_CHAR_BIT,
|
||||
bitsize, elttype);
|
||||
if (memcmp (VALUE_CONTENTS (v0), VALUE_CONTENTS (v1), eltlen) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i - i0 > repeat_count_threshold)
|
||||
{
|
||||
val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
|
||||
0, recurse + 1, pretty);
|
||||
annotate_elt_rep (i - i0);
|
||||
fprintf_filtered (stream, " <repeats %u times>", i - i0);
|
||||
annotate_elt_rep_end ();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int j;
|
||||
for (j = i0; j < i; j += 1)
|
||||
{
|
||||
if (j > i0)
|
||||
{
|
||||
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));
|
||||
}
|
||||
val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
|
||||
0, recurse + 1, pretty);
|
||||
annotate_elt ();
|
||||
}
|
||||
}
|
||||
things_printed += i - i0;
|
||||
}
|
||||
annotate_array_section_end ();
|
||||
if (i < len)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
|
||||
value_free_to_mark (mark);
|
||||
}
|
||||
|
||||
static struct type *
|
||||
printable_val_type (struct type *type, char *valaddr)
|
||||
{
|
||||
return ada_to_fixed_type (ada_aligned_type (type), valaddr, 0, NULL);
|
||||
}
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string whose delimiter is QUOTER. TYPE_LEN is the length in bytes
|
||||
(1 or 2) of the character. */
|
||||
|
||||
void
|
||||
ada_emit_char (int c, struct ui_file *stream, int quoter, int type_len)
|
||||
{
|
||||
if (type_len != 2)
|
||||
type_len = 1;
|
||||
|
||||
c &= (1 << (type_len * TARGET_CHAR_BIT)) - 1;
|
||||
|
||||
if (isascii (c) && isprint (c))
|
||||
{
|
||||
if (c == quoter && c == '"')
|
||||
fprintf_filtered (stream, "[\"%c\"]", quoter);
|
||||
else
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "[\"%0*x\"]", type_len * 2, c);
|
||||
}
|
||||
|
||||
/* Character #I of STRING, given that TYPE_LEN is the size in bytes (1
|
||||
or 2) of a character. */
|
||||
|
||||
static int
|
||||
char_at (char *string, int i, int type_len)
|
||||
{
|
||||
if (type_len == 1)
|
||||
return string[i];
|
||||
else
|
||||
return (int) extract_unsigned_integer (string + 2 * i, 2);
|
||||
}
|
||||
|
||||
void
|
||||
ada_printchar (int c, struct ui_file *stream)
|
||||
{
|
||||
fputs_filtered ("'", stream);
|
||||
ada_emit_char (c, stream, '\'', 1);
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
/* [From print_type_scalar in typeprint.c]. Print VAL on STREAM in a
|
||||
form appropriate for TYPE. */
|
||||
|
||||
void
|
||||
ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned len;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (TYPE_FIELD_BITPOS (type, i) == val)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
LA_PRINT_CHAR ((unsigned char) val, stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
fprintf_filtered (stream, val ? "true" : "false");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
ada_print_scalar (TYPE_TARGET_TYPE (type), val, stream);
|
||||
return;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_FLT:
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_SET:
|
||||
case TYPE_CODE_STRING:
|
||||
case TYPE_CODE_ERROR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_METHOD:
|
||||
case TYPE_CODE_REF:
|
||||
warning ("internal error: unhandled type in ada_print_scalar");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid type code in symbol table.");
|
||||
}
|
||||
gdb_flush (stream);
|
||||
}
|
||||
|
||||
/* 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. TYPE_LEN is the length (1 or 2) of the character type.
|
||||
*/
|
||||
|
||||
static void
|
||||
printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int force_ellipses, int type_len)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length && things_printed < print_max; i += 1)
|
||||
{
|
||||
/* 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_comma)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length &&
|
||||
char_at (string, rep1, type_len) == char_at (string, i,
|
||||
type_len))
|
||||
{
|
||||
rep1 += 1;
|
||||
reps += 1;
|
||||
}
|
||||
|
||||
if (reps > repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\", ", stream);
|
||||
else
|
||||
fputs_filtered ("\", ", stream);
|
||||
in_quotes = 0;
|
||||
}
|
||||
fputs_filtered ("'", stream);
|
||||
ada_emit_char (char_at (string, i, type_len), stream, '\'',
|
||||
type_len);
|
||||
fputs_filtered ("'", 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;
|
||||
}
|
||||
ada_emit_char (char_at (string, i, type_len), stream, '"',
|
||||
type_len);
|
||||
things_printed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void
|
||||
ada_printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int force_ellipses, int width)
|
||||
{
|
||||
printstr (stream, string, length, force_ellipses, width);
|
||||
}
|
||||
|
||||
|
||||
/* 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 as for the printf % codes or 0 for natural format).
|
||||
The data at VALADDR is in target byte order.
|
||||
|
||||
If the data is printed as a string, returns the number of string characters
|
||||
printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references, otherwise just print
|
||||
them like pointers.
|
||||
|
||||
RECURSE indicates the amount of indentation to supply before
|
||||
continuation lines; this amount is roughly twice the value of RECURSE.
|
||||
|
||||
When PRETTY is non-zero, prints record fields on separate lines.
|
||||
(For some reason, the current version of gdb instead uses a global
|
||||
variable---prettyprint_arrays--- to causes a similar effect on
|
||||
arrays.) */
|
||||
|
||||
int
|
||||
ada_val_print (struct type *type, char *valaddr0, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
struct ada_val_print_args args;
|
||||
args.type = type;
|
||||
args.valaddr0 = valaddr0;
|
||||
args.embedded_offset = embedded_offset;
|
||||
args.address = address;
|
||||
args.stream = stream;
|
||||
args.format = format;
|
||||
args.deref_ref = deref_ref;
|
||||
args.recurse = recurse;
|
||||
args.pretty = pretty;
|
||||
|
||||
return catch_errors (ada_val_print_stub, &args, NULL, RETURN_MASK_ALL);
|
||||
}
|
||||
|
||||
/* Helper for ada_val_print; used as argument to catch_errors to
|
||||
unmarshal the arguments to ada_val_print_1, which does the work. */
|
||||
static int
|
||||
ada_val_print_stub (void * args0)
|
||||
{
|
||||
struct ada_val_print_args *argsp = (struct ada_val_print_args *) args0;
|
||||
return ada_val_print_1 (argsp->type, argsp->valaddr0,
|
||||
argsp->embedded_offset, argsp->address,
|
||||
argsp->stream, argsp->format, argsp->deref_ref,
|
||||
argsp->recurse, argsp->pretty);
|
||||
}
|
||||
|
||||
/* See the comment on ada_val_print. This function differs in that it
|
||||
* does not catch evaluation errors (leaving that to ada_val_print). */
|
||||
|
||||
static int
|
||||
ada_val_print_1 (struct type *type, char *valaddr0, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
unsigned int len;
|
||||
int i;
|
||||
struct type *elttype;
|
||||
unsigned int eltlen;
|
||||
LONGEST val;
|
||||
CORE_ADDR addr;
|
||||
char *valaddr = valaddr0 + embedded_offset;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (ada_is_array_descriptor (type) || ada_is_packed_array_type (type))
|
||||
{
|
||||
int retn;
|
||||
struct value *mark = value_mark ();
|
||||
struct value *val;
|
||||
val = value_from_contents_and_address (type, valaddr, address);
|
||||
val = ada_coerce_to_simple_array_ptr (val);
|
||||
if (val == NULL)
|
||||
{
|
||||
fprintf_filtered (stream, "(null)");
|
||||
retn = 0;
|
||||
}
|
||||
else
|
||||
retn = ada_val_print_1 (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
|
||||
VALUE_ADDRESS (val), stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
value_free_to_mark (mark);
|
||||
return retn;
|
||||
}
|
||||
|
||||
valaddr = ada_aligned_value_addr (type, valaddr);
|
||||
embedded_offset -= valaddr - valaddr0 - embedded_offset;
|
||||
type = printable_val_type (type, valaddr);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
default:
|
||||
return c_val_print (type, valaddr0, embedded_offset, address, stream,
|
||||
format, deref_ref, recurse, pretty);
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_RANGE:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
{
|
||||
LONGEST v = unpack_long (type, valaddr);
|
||||
int len = TYPE_LENGTH (type);
|
||||
|
||||
fprintf_filtered (stream, len < 4 ? "%.11g" : "%.17g",
|
||||
(double) ada_fixed_to_float (type, v));
|
||||
return 0;
|
||||
}
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
{
|
||||
struct value *val =
|
||||
value_from_contents_and_address (type, valaddr, address);
|
||||
struct value *func = ada_vax_float_print_function (type);
|
||||
if (func != 0)
|
||||
{
|
||||
static struct type *parray_of_char = NULL;
|
||||
struct value *printable_val;
|
||||
|
||||
if (parray_of_char == NULL)
|
||||
parray_of_char =
|
||||
make_pointer_type
|
||||
(create_array_type
|
||||
(NULL, builtin_type_char,
|
||||
create_range_type (NULL, builtin_type_int, 0, 32)), NULL);
|
||||
|
||||
printable_val =
|
||||
value_ind (value_cast (parray_of_char,
|
||||
call_function_by_hand (func, 1,
|
||||
&val)));
|
||||
|
||||
fprintf_filtered (stream, "%s", VALUE_CONTENTS (printable_val));
|
||||
return 0;
|
||||
}
|
||||
/* No special printing function. Do as best we can. */
|
||||
}
|
||||
else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
|
||||
{
|
||||
struct type *target_type = TYPE_TARGET_TYPE (type);
|
||||
if (TYPE_LENGTH (type) != TYPE_LENGTH (target_type))
|
||||
{
|
||||
/* Obscure case of range type that has different length from
|
||||
its base type. Perform a conversion, or we will get a
|
||||
nonsense value. Actually, we could use the same
|
||||
code regardless of lengths; I'm just avoiding a cast. */
|
||||
struct value *v = value_cast (target_type,
|
||||
value_from_contents_and_address
|
||||
(type, valaddr, 0));
|
||||
return ada_val_print_1 (target_type, VALUE_CONTENTS (v), 0, 0,
|
||||
stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
else
|
||||
return ada_val_print_1 (TYPE_TARGET_TYPE (type),
|
||||
valaddr0, embedded_offset,
|
||||
address, stream, format, deref_ref,
|
||||
recurse, pretty);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
val_print_type_code_int (type, valaddr, stream);
|
||||
if (ada_is_character_type (type))
|
||||
{
|
||||
fputs_filtered (" ", stream);
|
||||
ada_printchar ((unsigned char) unpack_long (type, valaddr),
|
||||
stream);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (type, valaddr);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (val == TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
const char *name = ada_enum_name (TYPE_FIELD_NAME (type, i));
|
||||
if (name[0] == '\'')
|
||||
fprintf_filtered (stream, "%ld %s", (long) val, name);
|
||||
else
|
||||
fputs_filtered (name, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (ada_is_bogus_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(...?)");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_record (type, valaddr, stream, format, recurse, pretty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
|
||||
{
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
eltlen = TYPE_LENGTH (elttype);
|
||||
len = TYPE_LENGTH (type) / eltlen;
|
||||
|
||||
/* For an array of chars, print with string syntax. */
|
||||
if (ada_is_string_type (type) && (format == 0 || format == 's'))
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
/* If requested, look for the first null char and only print
|
||||
elements up to it. */
|
||||
if (stop_print_at_null)
|
||||
{
|
||||
int temp_len;
|
||||
|
||||
/* Look for a NULL char. */
|
||||
for (temp_len = 0;
|
||||
temp_len < len && temp_len < print_max
|
||||
&& char_at (valaddr, temp_len, eltlen) != 0;
|
||||
temp_len += 1);
|
||||
len = temp_len;
|
||||
}
|
||||
|
||||
printstr (stream, valaddr, len, 0, eltlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
fprintf_filtered (stream, "(");
|
||||
print_optional_low_bound (stream, type);
|
||||
if (TYPE_FIELD_BITSIZE (type, 0) > 0)
|
||||
val_print_packed_array_elements (type, valaddr, 0, stream,
|
||||
format, recurse, pretty);
|
||||
else
|
||||
val_print_array_elements (type, valaddr, address, stream,
|
||||
format, deref_ref, recurse,
|
||||
pretty, 0);
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
gdb_flush (stream);
|
||||
return len;
|
||||
}
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (addressprint)
|
||||
{
|
||||
fprintf_filtered (stream, "@");
|
||||
print_address_numeric
|
||||
(extract_address (valaddr,
|
||||
TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream);
|
||||
if (deref_ref)
|
||||
fputs_filtered (": ", stream);
|
||||
}
|
||||
/* De-reference the reference */
|
||||
if (deref_ref)
|
||||
{
|
||||
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
LONGEST deref_val_int = (LONGEST)
|
||||
unpack_pointer (lookup_pointer_type (builtin_type_void),
|
||||
valaddr);
|
||||
if (deref_val_int != 0)
|
||||
{
|
||||
struct value *deref_val =
|
||||
ada_value_ind (value_from_longest
|
||||
(lookup_pointer_type (elttype),
|
||||
deref_val_int));
|
||||
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 ("(null)", stream);
|
||||
}
|
||||
else
|
||||
fputs_filtered ("???", stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
print_variant_part (struct type *type, int field_num, char *valaddr,
|
||||
struct ui_file *stream, int format, int recurse,
|
||||
enum val_prettyprint pretty, int comma_needed,
|
||||
struct type *outer_type, char *outer_valaddr)
|
||||
{
|
||||
struct type *var_type = TYPE_FIELD_TYPE (type, field_num);
|
||||
int which = ada_which_variant_applies (var_type, outer_type, outer_valaddr);
|
||||
|
||||
if (which < 0)
|
||||
return 0;
|
||||
else
|
||||
return print_field_values
|
||||
(TYPE_FIELD_TYPE (var_type, which),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT
|
||||
+ TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT,
|
||||
stream, format, recurse, pretty,
|
||||
comma_needed, outer_type, outer_valaddr);
|
||||
}
|
||||
|
||||
int
|
||||
ada_value_print (struct value *val0, struct ui_file *stream, int format,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
char *valaddr = VALUE_CONTENTS (val0);
|
||||
CORE_ADDR address = VALUE_ADDRESS (val0) + VALUE_OFFSET (val0);
|
||||
struct type *type =
|
||||
ada_to_fixed_type (VALUE_TYPE (val0), valaddr, address, NULL);
|
||||
struct value *val =
|
||||
value_from_contents_and_address (type, valaddr, address);
|
||||
|
||||
/* If it is a pointer, indicate what it points to. */
|
||||
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_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof (char) &&
|
||||
TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT &&
|
||||
!TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)))
|
||||
{
|
||||
/* Print nothing */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
}
|
||||
else if (ada_is_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
else if (ada_is_bogus_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") (...?)");
|
||||
return 0;
|
||||
}
|
||||
return (val_print (type, VALUE_CONTENTS (val), 0, address,
|
||||
stream, format, 1, 0, pretty));
|
||||
}
|
||||
|
||||
static void
|
||||
print_record (struct type *type, char *valaddr, struct ui_file *stream,
|
||||
int format, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
|
||||
if (print_field_values (type, valaddr, stream, format, recurse, pretty,
|
||||
0, type, valaddr) != 0 && pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 * recurse, stream);
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
/* Print out fields of value at VALADDR having structure type TYPE.
|
||||
|
||||
TYPE, VALADDR, STREAM, FORMAT, RECURSE, and PRETTY have the
|
||||
same meanings as in ada_print_value and ada_val_print.
|
||||
|
||||
OUTER_TYPE and OUTER_VALADDR give type and address of enclosing record
|
||||
(used to get discriminant values when printing variant parts).
|
||||
|
||||
COMMA_NEEDED is 1 if fields have been printed at the current recursion
|
||||
level, so that a comma is needed before any field printed by this
|
||||
call.
|
||||
|
||||
Returns 1 if COMMA_NEEDED or any fields were printed. */
|
||||
|
||||
static int
|
||||
print_field_values (struct type *type, char *valaddr, struct ui_file *stream,
|
||||
int format, int recurse, enum val_prettyprint pretty,
|
||||
int comma_needed, struct type *outer_type,
|
||||
char *outer_valaddr)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
len = TYPE_NFIELDS (type);
|
||||
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
if (ada_is_ignored_field (type, i))
|
||||
continue;
|
||||
|
||||
if (ada_is_wrapper_field (type, i))
|
||||
{
|
||||
comma_needed =
|
||||
print_field_values (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr
|
||||
+ TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
|
||||
stream, format, recurse, pretty,
|
||||
comma_needed, type, valaddr);
|
||||
continue;
|
||||
}
|
||||
else if (ada_is_variant_part (type, i))
|
||||
{
|
||||
comma_needed =
|
||||
print_variant_part (type, i, valaddr,
|
||||
stream, format, recurse, pretty, comma_needed,
|
||||
outer_type, outer_valaddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_needed)
|
||||
fprintf_filtered (stream, ", ");
|
||||
comma_needed = 1;
|
||||
|
||||
if (pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
}
|
||||
if (inspect_it)
|
||||
{
|
||||
if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
|
||||
fputs_filtered ("\"( ptr \"", stream);
|
||||
else
|
||||
fputs_filtered ("\"( nodef \"", stream);
|
||||
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
|
||||
language_cplus, DMGL_NO_OPTS);
|
||||
fputs_filtered ("\" \"", stream);
|
||||
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
|
||||
language_cplus, DMGL_NO_OPTS);
|
||||
fputs_filtered ("\") \"", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
annotate_field_begin (TYPE_FIELD_TYPE (type, i));
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (TYPE_FIELD_NAME (type, i)),
|
||||
TYPE_FIELD_NAME (type, i));
|
||||
annotate_field_name_end ();
|
||||
fputs_filtered (" => ", stream);
|
||||
annotate_field_value ();
|
||||
}
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
struct value *v;
|
||||
|
||||
/* Bitfields require special handling, especially due to byte
|
||||
order problems. */
|
||||
if (TYPE_CPLUS_SPECIFIC (type) != NULL
|
||||
&& TYPE_FIELD_IGNORE (type, i))
|
||||
{
|
||||
fputs_filtered ("<optimized out or zero length>", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
int bit_pos = TYPE_FIELD_BITPOS (type, i);
|
||||
int bit_size = TYPE_FIELD_BITSIZE (type, i);
|
||||
|
||||
adjust_type_signedness (TYPE_FIELD_TYPE (type, i));
|
||||
v = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
bit_pos / HOST_CHAR_BIT,
|
||||
bit_pos % HOST_CHAR_BIT,
|
||||
bit_size,
|
||||
TYPE_FIELD_TYPE (type, i));
|
||||
val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, 0,
|
||||
stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
}
|
||||
else
|
||||
ada_val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
|
||||
0, 0, stream, format, 0, recurse + 1, pretty);
|
||||
annotate_field_end ();
|
||||
}
|
||||
|
||||
return comma_needed;
|
||||
}
|
||||
1707
gdb/aix-thread.c
1707
gdb/aix-thread.c
File diff suppressed because it is too large
Load Diff
@@ -1,122 +0,0 @@
|
||||
/* Target-dependent code for GNU/Linux on Alpha.
|
||||
Copyright 2002, 2003 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 "osabi.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 (get_frame_base (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, 0, GDB_OSABI_LINUX,
|
||||
alpha_linux_init_abi);
|
||||
}
|
||||
292
gdb/alpha-nat.c
292
gdb/alpha-nat.c
@@ -1,292 +0,0 @@
|
||||
/* Low level Alpha interface, for GDB when running native.
|
||||
Copyright 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003
|
||||
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 "gdb_string.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 (&deprecated_registers[REGISTER_BYTE (FP0_REGNUM)],
|
||||
core_reg_sect, 31 * 8);
|
||||
memset (&deprecated_registers[REGISTER_BYTE (FP0_REGNUM + 31)], 0, 8);
|
||||
memset (&deprecated_register_valid[FP0_REGNUM], 1, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The General Registers. */
|
||||
memcpy (&deprecated_registers[REGISTER_BYTE (ALPHA_V0_REGNUM)],
|
||||
core_reg_sect, 31 * 8);
|
||||
memcpy (&deprecated_registers[REGISTER_BYTE (PC_REGNUM)],
|
||||
core_reg_sect + 31 * 8, 8);
|
||||
memset (&deprecated_registers[REGISTER_BYTE (ALPHA_ZERO_REGNUM)], 0, 8);
|
||||
memset (&deprecated_register_valid[ALPHA_V0_REGNUM], 1, 32);
|
||||
deprecated_register_valid[PC_REGNUM] = 1;
|
||||
|
||||
if (core_reg_size >= 33 * 8)
|
||||
{
|
||||
memcpy (&deprecated_registers[REGISTER_BYTE (ALPHA_UNIQUE_REGNUM)],
|
||||
core_reg_sect + 32 * 8, 8);
|
||||
deprecated_register_valid[ALPHA_UNIQUE_REGNUM] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Map gdb internal register number to a ptrace ``address''.
|
||||
These ``addresses'' are defined in <sys/ptrace.h>, with
|
||||
the exception of ALPHA_UNIQUE_PTRACE_ADDR. */
|
||||
|
||||
#ifndef ALPHA_UNIQUE_PTRACE_ADDR
|
||||
#define ALPHA_UNIQUE_PTRACE_ADDR 0
|
||||
#endif
|
||||
|
||||
CORE_ADDR
|
||||
register_addr (int regno, CORE_ADDR blockend)
|
||||
{
|
||||
if (regno == PC_REGNUM)
|
||||
return PC;
|
||||
if (regno == ALPHA_UNIQUE_REGNUM)
|
||||
return ALPHA_UNIQUE_PTRACE_ADDR;
|
||||
if (regno < FP0_REGNUM)
|
||||
return GPR_BASE + regno;
|
||||
else
|
||||
return FPR_BASE + regno - FP0_REGNUM;
|
||||
}
|
||||
|
||||
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 *) &deprecated_registers[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == PC_REGNUM))
|
||||
*(regp + 31) = *(long *) &deprecated_registers[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 *) &deprecated_registers[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,80 +0,0 @@
|
||||
/* Target-dependent code for OSF/1 on Alpha.
|
||||
Copyright 2002, 2003 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 "osabi.h"
|
||||
#include "gdb_string.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 && strcmp ("__sigtramp", func_name) == 0);
|
||||
}
|
||||
|
||||
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);
|
||||
/* The next/step support via procfs on OSF1 is broken when running
|
||||
on multi-processor machines. We need to use software single stepping
|
||||
instead. */
|
||||
set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
|
||||
|
||||
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, 0, GDB_OSABI_OSF1,
|
||||
alpha_osf1_init_abi);
|
||||
}
|
||||
1947
gdb/alpha-tdep.c
1947
gdb/alpha-tdep.c
File diff suppressed because it is too large
Load Diff
106
gdb/alpha-tdep.h
106
gdb/alpha-tdep.h
@@ -1,106 +0,0 @@
|
||||
/* Common target dependent code for GDB on Alpha systems.
|
||||
Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003 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
|
||||
|
||||
/* 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 67
|
||||
|
||||
/* 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 */
|
||||
#define ALPHA_UNIQUE_REGNUM 66 /* PAL_rduniq value */
|
||||
|
||||
/* 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
|
||||
{
|
||||
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,84 +0,0 @@
|
||||
/* Target-dependent code for FreeBSD/Alpha.
|
||||
Copyright 2001, 2002, 2003 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 "osabi.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, 0, GDB_OSABI_FREEBSD_ELF,
|
||||
alphafbsd_init_abi);
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
/* Target-dependent code for NetBSD/Alpha.
|
||||
Copyright 2002, 2003 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 "frame.h"
|
||||
#include "regcache.h"
|
||||
#include "value.h"
|
||||
#include "osabi.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 (nbsd_pc_in_sigtramp (pc, func_name)
|
||||
|| alphanbsd_sigtramp_offset (pc) >= 0);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alphanbsd_sigcontext_addr (struct frame_info *frame)
|
||||
{
|
||||
/* FIXME: This is not correct for all versions of NetBSD/alpha.
|
||||
We will probably need to disassemble the trampoline to figure
|
||||
out which trampoline frame type we have. */
|
||||
return frame->frame;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alphanbsd_skip_sigtramp_frame (struct frame_info *frame, CORE_ADDR pc)
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* FIXME: This is not correct for all versions of NetBSD/alpha.
|
||||
We will probably need to disassemble the trampoline to figure
|
||||
out which trampoline frame type we have. */
|
||||
find_pc_partial_function (pc, &name, (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
|
||||
if (PC_IN_SIGTRAMP (pc, name))
|
||||
return frame->frame;
|
||||
return 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->skip_sigtramp_frame = alphanbsd_skip_sigtramp_frame;
|
||||
tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
|
||||
tdep->sigcontext_addr = alphanbsd_sigcontext_addr;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alphanbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, 0, 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);
|
||||
940
gdb/arch-utils.c
940
gdb/arch-utils.c
@@ -1,940 +0,0 @@
|
||||
/* Dynamic architecture support for GDB, the GNU debugger.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001, 2002, 2003 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 "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 "gdb_string.h"
|
||||
#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,
|
||||
void *valbuf)
|
||||
{
|
||||
char *registers = deprecated_grub_regcache_for_registers (regcache);
|
||||
bfd_byte *buf = valbuf;
|
||||
DEPRECATED_EXTRACT_RETURN_VALUE (type, registers, buf); /* OK */
|
||||
}
|
||||
|
||||
/* Implementation of store return value that grubs the register cache.
|
||||
Takes a local copy of the buffer to avoid const problems. */
|
||||
void
|
||||
legacy_store_return_value (struct type *type, struct regcache *regcache,
|
||||
const void *buf)
|
||||
{
|
||||
bfd_byte *b = alloca (TYPE_LENGTH (type));
|
||||
gdb_assert (regcache == current_regcache);
|
||||
memcpy (b, buf, TYPE_LENGTH (type));
|
||||
DEPRECATED_STORE_RETURN_VALUE (type, b);
|
||||
}
|
||||
|
||||
|
||||
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_solib_return_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");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
init_frame_pc_noop (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
/* Do nothing, implies return the same PC value. */
|
||||
return get_frame_pc (prev);
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
init_frame_pc_default (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
if (fromleaf && DEPRECATED_SAVED_PC_AFTER_CALL_P ())
|
||||
return DEPRECATED_SAVED_PC_AFTER_CALL (get_next_frame (prev));
|
||||
else if (get_next_frame (prev) != NULL)
|
||||
return DEPRECATED_FRAME_SAVED_PC (get_next_frame (prev));
|
||||
else
|
||||
return 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)
|
||||
{
|
||||
/* FIXME: cagney/2002-09-13: This code is used when identifying the
|
||||
frame pointer of the current PC. It is assuming that a single
|
||||
register and an offset can determine this. I think it should
|
||||
instead generate a byte code expression as that would work better
|
||||
with things like Dwarf2's CFI. */
|
||||
if (FP_REGNUM >= 0 && FP_REGNUM < NUM_REGS)
|
||||
*frame_regnum = FP_REGNUM;
|
||||
else if (SP_REGNUM >= 0 && SP_REGNUM < NUM_REGS)
|
||||
*frame_regnum = SP_REGNUM;
|
||||
else
|
||||
/* Should this be an internal error? I guess so, it is reflecting
|
||||
an architectural limitation in the current design. */
|
||||
internal_error (__FILE__, __LINE__, "No virtual frame pointer available");
|
||||
*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);
|
||||
if (gdbarch_register_type_p (current_gdbarch))
|
||||
return TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum));
|
||||
else
|
||||
/* FIXME: cagney/2003-03-01: Once all architectures implement
|
||||
gdbarch_register_type(), this entire function can go away. It
|
||||
is made obsolete by register_size(). */
|
||||
return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum)); /* OK */
|
||||
}
|
||||
|
||||
/* Assume all registers are adjacent. */
|
||||
|
||||
int
|
||||
generic_register_byte (int regnum)
|
||||
{
|
||||
int byte;
|
||||
int i;
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
|
||||
byte = 0;
|
||||
for (i = 0; i < regnum; i++)
|
||||
{
|
||||
byte += generic_register_size (i);
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
legacy_pc_in_sigtramp (CORE_ADDR pc, char *name)
|
||||
{
|
||||
#if !defined (IN_SIGTRAMP)
|
||||
if (SIGTRAMP_START_P ())
|
||||
return (pc) >= SIGTRAMP_START (pc) && (pc) < SIGTRAMP_END (pc);
|
||||
else
|
||||
return name && strcmp ("_sigtramp", name) == 0;
|
||||
#else
|
||||
return IN_SIGTRAMP (pc, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
info->osabi = GDB_OSABI_UNINITIALIZED;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
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);
|
||||
}
|
||||
186
gdb/arch-utils.h
186
gdb/arch-utils.h
@@ -1,186 +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
|
||||
|
||||
struct gdbarch;
|
||||
struct frame_info;
|
||||
struct minimal_symbol;
|
||||
struct type;
|
||||
struct gdbarch_info;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Implementation of store return value that grubs the register cache. */
|
||||
extern gdbarch_store_return_value_ftype legacy_store_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 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. */
|
||||
|
||||
extern CORE_ADDR init_frame_pc_noop (int fromleaf, struct frame_info *prev);
|
||||
|
||||
extern CORE_ADDR 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_solib_return_trampoline (CORE_ADDR pc, char *name);
|
||||
|
||||
extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc);
|
||||
|
||||
/* Assume that the world is sane, a registers raw and virtual size
|
||||
both match its type. */
|
||||
|
||||
extern int generic_register_size (int regnum);
|
||||
|
||||
/* Assume that the world is sane, the registers are all adjacent. */
|
||||
extern int generic_register_byte (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,551 +0,0 @@
|
||||
/* GNU/Linux on ARM target support.
|
||||
Copyright 1999, 2000, 2001, 2002, 2003 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 "osabi.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 = deprecated_extract_floating (val, len);
|
||||
len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
|
||||
val = alloca (len);
|
||||
deprecated_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 (DEPRECATED_SYMBOL_NAME (msym)
|
||||
&& strcmp (DEPRECATED_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 (DEPRECATED_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->fp_model = ARM_FLOAT_FPA;
|
||||
|
||||
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_deprecated_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, 0, GDB_OSABI_LINUX,
|
||||
arm_linux_init_abi);
|
||||
}
|
||||
3218
gdb/arm-tdep.c
3218
gdb/arm-tdep.c
File diff suppressed because it is too large
Load Diff
160
gdb/arm-tdep.h
160
gdb/arm-tdep.h
@@ -1,160 +0,0 @@
|
||||
/* Common target dependent code for GDB on ARM systems.
|
||||
Copyright 2002, 2003 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. */
|
||||
|
||||
/* 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.
|
||||
|
||||
If you update this enum, don't forget to update fp_model_strings in
|
||||
arm-tdep.c. */
|
||||
|
||||
enum arm_float_model
|
||||
{
|
||||
ARM_FLOAT_AUTO, /* Automatic detection. Do not set in tdep. */
|
||||
ARM_FLOAT_SOFT_FPA, /* Traditional soft-float (mixed-endian on LE ARM). */
|
||||
ARM_FLOAT_FPA, /* FPA co-processor. GCC calling convention. */
|
||||
ARM_FLOAT_SOFT_VFP, /* Soft-float with pure-endian doubles. */
|
||||
ARM_FLOAT_VFP, /* Full VFP calling convention. */
|
||||
ARM_FLOAT_LAST /* Keep at end. */
|
||||
};
|
||||
|
||||
/* A method to the setting based on user's choice and ABI setting. */
|
||||
enum arm_float_model arm_get_fp_model (struct gdbarch *);
|
||||
|
||||
/* Target-dependent structure in gdbarch. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
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,105 +0,0 @@
|
||||
/* Target-specific functions for ARM running under NetBSD.
|
||||
Copyright 2002, 2003 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 "osabi.h"
|
||||
|
||||
#include "arm-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Description of the longjmp buffer. */
|
||||
#define ARM_NBSD_JB_PC 24
|
||||
#define ARM_NBSD_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 = ARM_NBSD_JB_PC;
|
||||
tdep->jb_elt_size = ARM_NBSD_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_FPA;
|
||||
}
|
||||
|
||||
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, 0, GDB_OSABI_NETBSD_AOUT,
|
||||
arm_netbsd_aout_init_abi);
|
||||
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_ELF,
|
||||
arm_netbsd_elf_init_abi);
|
||||
}
|
||||
1313
gdb/avr-tdep.c
1313
gdb/avr-tdep.c
File diff suppressed because it is too large
Load Diff
1869
gdb/ax-gdb.c
1869
gdb/ax-gdb.c
File diff suppressed because it is too large
Load Diff
113
gdb/ax-gdb.h
113
gdb/ax-gdb.h
@@ -1,113 +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
|
||||
|
||||
struct expression;
|
||||
|
||||
/* 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 */
|
||||
542
gdb/ax-general.c
542
gdb/ax-general.c
@@ -1,542 +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"
|
||||
#include "gdb_string.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 "gdb_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 */
|
||||
201
gdb/block.c
201
gdb/block.c
@@ -1,201 +0,0 @@
|
||||
/* Block-related functions for the GNU debugger, GDB.
|
||||
|
||||
Copyright 2003 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 "block.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "cp-support.h"
|
||||
|
||||
/* This is used by struct block to store namespace-related info for
|
||||
C++ files, namely using declarations and the current namespace in
|
||||
scope. */
|
||||
|
||||
struct block_namespace_info
|
||||
{
|
||||
const char *scope;
|
||||
struct using_direct *using;
|
||||
};
|
||||
|
||||
static void block_initialize_namespace (struct block *block,
|
||||
struct obstack *obstack);
|
||||
|
||||
/* Return Nonzero if block a is lexically nested within block b,
|
||||
or if a and b have the same pc range.
|
||||
Return zero otherwise. */
|
||||
|
||||
int
|
||||
contained_in (struct block *a, struct block *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return 0;
|
||||
return BLOCK_START (a) >= BLOCK_START (b)
|
||||
&& BLOCK_END (a) <= BLOCK_END (b);
|
||||
}
|
||||
|
||||
|
||||
/* Return the symbol for the function which contains a specified
|
||||
lexical block, described by a struct block BL. */
|
||||
|
||||
struct symbol *
|
||||
block_function (struct block *bl)
|
||||
{
|
||||
while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
|
||||
bl = BLOCK_SUPERBLOCK (bl);
|
||||
|
||||
return BLOCK_FUNCTION (bl);
|
||||
}
|
||||
|
||||
/* Return the blockvector immediately containing the innermost lexical block
|
||||
containing the specified pc value and section, or 0 if there is none.
|
||||
PINDEX is a pointer to the index value of the block. If PINDEX
|
||||
is NULL, we don't pass this information back to the caller. */
|
||||
|
||||
struct blockvector *
|
||||
blockvector_for_pc_sect (register CORE_ADDR pc, struct sec *section,
|
||||
int *pindex, struct symtab *symtab)
|
||||
{
|
||||
register struct block *b;
|
||||
register int bot, top, half;
|
||||
struct blockvector *bl;
|
||||
|
||||
if (symtab == 0) /* if no symtab specified by caller */
|
||||
{
|
||||
/* First search all symtabs for one whose file contains our pc */
|
||||
if ((symtab = find_pc_sect_symtab (pc, section)) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bl = BLOCKVECTOR (symtab);
|
||||
b = BLOCKVECTOR_BLOCK (bl, 0);
|
||||
|
||||
/* Then search that symtab for the smallest block that wins. */
|
||||
/* Use binary search to find the last block that starts before PC. */
|
||||
|
||||
bot = 0;
|
||||
top = BLOCKVECTOR_NBLOCKS (bl);
|
||||
|
||||
while (top - bot > 1)
|
||||
{
|
||||
half = (top - bot + 1) >> 1;
|
||||
b = BLOCKVECTOR_BLOCK (bl, bot + half);
|
||||
if (BLOCK_START (b) <= pc)
|
||||
bot += half;
|
||||
else
|
||||
top = bot + half;
|
||||
}
|
||||
|
||||
/* Now search backward for a block that ends after PC. */
|
||||
|
||||
while (bot >= 0)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bl, bot);
|
||||
if (BLOCK_END (b) > pc)
|
||||
{
|
||||
if (pindex)
|
||||
*pindex = bot;
|
||||
return bl;
|
||||
}
|
||||
bot--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the blockvector immediately containing the innermost lexical block
|
||||
containing the specified pc value, or 0 if there is none.
|
||||
Backward compatibility, no section. */
|
||||
|
||||
struct blockvector *
|
||||
blockvector_for_pc (register CORE_ADDR pc, int *pindex)
|
||||
{
|
||||
return blockvector_for_pc_sect (pc, find_pc_mapped_section (pc),
|
||||
pindex, NULL);
|
||||
}
|
||||
|
||||
/* Return the innermost lexical block containing the specified pc value
|
||||
in the specified section, or 0 if there is none. */
|
||||
|
||||
struct block *
|
||||
block_for_pc_sect (register CORE_ADDR pc, struct sec *section)
|
||||
{
|
||||
register struct blockvector *bl;
|
||||
int index;
|
||||
|
||||
bl = blockvector_for_pc_sect (pc, section, &index, NULL);
|
||||
if (bl)
|
||||
return BLOCKVECTOR_BLOCK (bl, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the innermost lexical block containing the specified pc value,
|
||||
or 0 if there is none. Backward compatibility, no section. */
|
||||
|
||||
struct block *
|
||||
block_for_pc (register CORE_ADDR pc)
|
||||
{
|
||||
return block_for_pc_sect (pc, find_pc_mapped_section (pc));
|
||||
}
|
||||
|
||||
/* Now come some functions designed to deal with C++ namespace
|
||||
issues. */
|
||||
|
||||
/* Set BLOCK's scope member to SCOPE; if needed, allocate memory via
|
||||
OBSTACK. (It won't make a copy of SCOPE, however, so that already
|
||||
has to be allocated correctly.) */
|
||||
|
||||
void
|
||||
block_set_scope (struct block *block, const char *scope,
|
||||
struct obstack *obstack)
|
||||
{
|
||||
block_initialize_namespace (block, obstack);
|
||||
|
||||
BLOCK_NAMESPACE (block)->scope = scope;
|
||||
}
|
||||
|
||||
/* Set BLOCK's using member to USING; if needed, allocate memory via
|
||||
OBSTACK. (It won't make a copy of USING, however, so that already
|
||||
has to be allocated correctly.) */
|
||||
|
||||
void
|
||||
block_set_using (struct block *block,
|
||||
struct using_direct *using,
|
||||
struct obstack *obstack)
|
||||
{
|
||||
block_initialize_namespace (block, obstack);
|
||||
|
||||
BLOCK_NAMESPACE (block)->using = using;
|
||||
}
|
||||
|
||||
/* If BLOCK_NAMESPACE (block) is NULL, allocate it via OBSTACK and
|
||||
ititialize its members to zero. */
|
||||
|
||||
static void
|
||||
block_initialize_namespace (struct block *block, struct obstack *obstack)
|
||||
{
|
||||
if (BLOCK_NAMESPACE (block) == NULL)
|
||||
{
|
||||
BLOCK_NAMESPACE (block)
|
||||
= obstack_alloc (obstack, sizeof (struct block_namespace_info));
|
||||
BLOCK_NAMESPACE (block)->scope = NULL;
|
||||
BLOCK_NAMESPACE (block)->using = NULL;
|
||||
}
|
||||
}
|
||||
210
gdb/block.h
210
gdb/block.h
@@ -1,210 +0,0 @@
|
||||
/* Code dealing with blocks for GDB.
|
||||
|
||||
Copyright 2003 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 BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
/* Opaque declarations. */
|
||||
|
||||
struct symbol;
|
||||
struct symtab;
|
||||
struct block_namespace_info;
|
||||
struct using_direct;
|
||||
struct obstack;
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
are represented by `struct block' objects.
|
||||
All of these objects are pointed to by the blockvector.
|
||||
|
||||
Each block represents one name scope.
|
||||
Each lexical context has its own block.
|
||||
|
||||
The blockvector begins with some special blocks.
|
||||
The GLOBAL_BLOCK contains all the symbols defined in this compilation
|
||||
whose scope is the entire program linked together.
|
||||
The STATIC_BLOCK contains all the symbols whose scope is the
|
||||
entire compilation excluding other separate compilations.
|
||||
Blocks starting with the FIRST_LOCAL_BLOCK are not special.
|
||||
|
||||
Each block records a range of core addresses for the code that
|
||||
is in the scope of the block. The STATIC_BLOCK and GLOBAL_BLOCK
|
||||
give, for the range of code, the entire range of code produced
|
||||
by the compilation that the symbol segment belongs to.
|
||||
|
||||
The blocks appear in the blockvector
|
||||
in order of increasing starting-address,
|
||||
and, within that, in order of decreasing ending-address.
|
||||
|
||||
This implies that within the body of one function
|
||||
the blocks appear in the order of a depth-first tree walk. */
|
||||
|
||||
struct block
|
||||
{
|
||||
|
||||
/* Addresses in the executable code that are in this block. */
|
||||
|
||||
CORE_ADDR startaddr;
|
||||
CORE_ADDR endaddr;
|
||||
|
||||
/* The symbol that names this block, if the block is the body of a
|
||||
function; otherwise, zero. */
|
||||
|
||||
struct symbol *function;
|
||||
|
||||
/* The `struct block' for the containing block, or 0 if none.
|
||||
|
||||
The superblock of a top-level local block (i.e. a function in the
|
||||
case of C) is the STATIC_BLOCK. The superblock of the
|
||||
STATIC_BLOCK is the GLOBAL_BLOCK. */
|
||||
|
||||
struct block *superblock;
|
||||
|
||||
/* Used for language-specific info. */
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* Contains information about namespace-related info relevant to
|
||||
this block: using directives and the current namespace
|
||||
scope. */
|
||||
|
||||
struct block_namespace_info *namespace;
|
||||
}
|
||||
cplus_specific;
|
||||
}
|
||||
language_specific;
|
||||
|
||||
/* Version of GCC used to compile the function corresponding
|
||||
to this block, or 0 if not compiled with GCC. When possible,
|
||||
GCC should be compatible with the native compiler, or if that
|
||||
is not feasible, the differences should be fixed during symbol
|
||||
reading. As of 16 Apr 93, this flag is never used to distinguish
|
||||
between gcc2 and the native compiler.
|
||||
|
||||
If there is no function corresponding to this block, this meaning
|
||||
of this flag is undefined. */
|
||||
|
||||
unsigned char gcc_compile_flag;
|
||||
|
||||
/* The symbols for this block are either in a simple linear list or
|
||||
in a simple hashtable. Blocks which correspond to a function
|
||||
(which have a list of symbols corresponding to arguments) use
|
||||
a linear list, as do some older symbol readers (currently only
|
||||
mdebugread and dstread). Other blocks are hashed.
|
||||
|
||||
The hashtable uses the same hash function as the minsym hashtables,
|
||||
found in minsyms.c:minsym_hash_iw. Symbols are hashed based on
|
||||
their demangled name if appropriate, and on their name otherwise.
|
||||
The hash function ignores space, and stops at the beginning of the
|
||||
argument list if any.
|
||||
|
||||
The table is laid out in NSYMS/5 buckets and symbols are chained via
|
||||
their hash_next field. */
|
||||
|
||||
/* If this is really a hashtable of the symbols, this flag is 1. */
|
||||
|
||||
unsigned char hashtable;
|
||||
|
||||
/* Number of local symbols. */
|
||||
|
||||
int nsyms;
|
||||
|
||||
/* The symbols. If some of them are arguments, then they must be
|
||||
in the order in which we would like to print them. */
|
||||
|
||||
struct symbol *sym[1];
|
||||
};
|
||||
|
||||
#define BLOCK_START(bl) (bl)->startaddr
|
||||
#define BLOCK_END(bl) (bl)->endaddr
|
||||
#define BLOCK_FUNCTION(bl) (bl)->function
|
||||
#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
|
||||
#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
|
||||
#define BLOCK_NAMESPACE(bl) (bl)->language_specific.cplus_specific.namespace
|
||||
#define BLOCK_HASHTABLE(bl) (bl)->hashtable
|
||||
|
||||
/* For blocks without a hashtable (BLOCK_HASHTABLE (bl) == 0) only. */
|
||||
#define BLOCK_NSYMS(bl) (bl)->nsyms
|
||||
#define BLOCK_SYM(bl, n) (bl)->sym[n]
|
||||
|
||||
/* For blocks with a hashtable, but these are valid for non-hashed blocks as
|
||||
well - each symbol will appear to be one bucket by itself. */
|
||||
#define BLOCK_BUCKETS(bl) (bl)->nsyms
|
||||
#define BLOCK_BUCKET(bl, n) (bl)->sym[n]
|
||||
|
||||
/* Macro used to set the size of a hashtable for N symbols. */
|
||||
#define BLOCK_HASHTABLE_SIZE(n) ((n)/5 + 1)
|
||||
|
||||
/* Macro to loop through all symbols in a block BL, in no particular order.
|
||||
i counts which bucket we are in, and sym points to the current symbol. */
|
||||
|
||||
#define ALL_BLOCK_SYMBOLS(bl, i, sym) \
|
||||
for ((i) = 0; (i) < BLOCK_BUCKETS ((bl)); (i)++) \
|
||||
for ((sym) = BLOCK_BUCKET ((bl), (i)); (sym); \
|
||||
(sym) = (sym)->hash_next)
|
||||
|
||||
/* Nonzero if symbols of block BL should be sorted alphabetically.
|
||||
Don't sort a block which corresponds to a function. If we did the
|
||||
sorting would have to preserve the order of the symbols for the
|
||||
arguments. Also don't sort any block that we chose to hash. */
|
||||
|
||||
#define BLOCK_SHOULD_SORT(bl) (! BLOCK_HASHTABLE (bl) \
|
||||
&& BLOCK_FUNCTION (bl) == NULL)
|
||||
|
||||
struct blockvector
|
||||
{
|
||||
/* Number of blocks in the list. */
|
||||
int nblocks;
|
||||
/* The blocks themselves. */
|
||||
struct block *block[1];
|
||||
};
|
||||
|
||||
#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
|
||||
#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
|
||||
|
||||
/* Special block numbers */
|
||||
|
||||
#define GLOBAL_BLOCK 0
|
||||
#define STATIC_BLOCK 1
|
||||
#define FIRST_LOCAL_BLOCK 2
|
||||
|
||||
extern struct symbol *block_function (struct block *);
|
||||
|
||||
extern int contained_in (struct block *, struct block *);
|
||||
|
||||
extern struct blockvector *blockvector_for_pc (CORE_ADDR, int *);
|
||||
|
||||
extern struct blockvector *blockvector_for_pc_sect (CORE_ADDR, asection *,
|
||||
int *, struct symtab *);
|
||||
|
||||
extern struct block *block_for_pc (CORE_ADDR);
|
||||
|
||||
extern struct block *block_for_pc_sect (CORE_ADDR, asection *);
|
||||
|
||||
extern void block_set_scope (struct block *block, const char *scope,
|
||||
struct obstack *obstack);
|
||||
|
||||
extern void block_set_using (struct block *block,
|
||||
struct using_direct *using,
|
||||
struct obstack *obstack);
|
||||
|
||||
#endif /* BLOCK_H */
|
||||
596
gdb/blockframe.c
596
gdb/blockframe.c
@@ -1,596 +0,0 @@
|
||||
/* Get info from stack frames; convert between frames, blocks,
|
||||
functions and pc values.
|
||||
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
|
||||
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 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 "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "value.h" /* for read_register */
|
||||
#include "target.h" /* for target_has_stack */
|
||||
#include "inferior.h" /* for read_pc */
|
||||
#include "annotate.h"
|
||||
#include "regcache.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "dummy-frame.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "block.h"
|
||||
|
||||
/* Prototypes for exported functions. */
|
||||
|
||||
void _initialize_blockframe (void);
|
||||
|
||||
/* Is ADDR inside the startup file? Note that if your machine has a
|
||||
way to detect the bottom of the stack, there is no need to call
|
||||
this function from DEPRECATED_FRAME_CHAIN_VALID; the reason for
|
||||
doing so is that some machines have no way of detecting bottom of
|
||||
stack.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
inside_entry_file (CORE_ADDR addr)
|
||||
{
|
||||
if (addr == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
|
||||
{
|
||||
/* Do not stop backtracing if the pc is in the call dummy
|
||||
at the entry point. */
|
||||
/* FIXME: Won't always work with zeros for the last two arguments */
|
||||
if (DEPRECATED_PC_IN_CALL_DUMMY (addr, 0, 0))
|
||||
return 0;
|
||||
}
|
||||
return (addr >= symfile_objfile->ei.entry_file_lowpc &&
|
||||
addr < symfile_objfile->ei.entry_file_highpc);
|
||||
}
|
||||
|
||||
/* Test a specified PC value to see if it is in the range of addresses
|
||||
that correspond to the main() function. See comments above for why
|
||||
we might want to do this.
|
||||
|
||||
Typically called from DEPRECATED_FRAME_CHAIN_VALID.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
inside_main_func (CORE_ADDR pc)
|
||||
{
|
||||
if (pc == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
|
||||
/* If the addr range is not set up at symbol reading time, set it up
|
||||
now. This is for DEPRECATED_FRAME_CHAIN_VALID_ALTERNATE. I do
|
||||
this for coff, because it is unable to set it up and symbol
|
||||
reading time. */
|
||||
|
||||
if (symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC &&
|
||||
symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
|
||||
{
|
||||
struct symbol *mainsym;
|
||||
|
||||
mainsym = lookup_symbol (main_name (), NULL, VAR_NAMESPACE, NULL, NULL);
|
||||
if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK)
|
||||
{
|
||||
symfile_objfile->ei.main_func_lowpc =
|
||||
BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
|
||||
symfile_objfile->ei.main_func_highpc =
|
||||
BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
|
||||
}
|
||||
}
|
||||
return (symfile_objfile->ei.main_func_lowpc <= pc &&
|
||||
symfile_objfile->ei.main_func_highpc > pc);
|
||||
}
|
||||
|
||||
/* Test a specified PC value to see if it is in the range of addresses
|
||||
that correspond to the process entry point function. See comments
|
||||
in objfiles.h for why we might want to do this.
|
||||
|
||||
Typically called from DEPRECATED_FRAME_CHAIN_VALID.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
inside_entry_func (CORE_ADDR pc)
|
||||
{
|
||||
if (pc == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
|
||||
{
|
||||
/* Do not stop backtracing if the pc is in the call dummy
|
||||
at the entry point. */
|
||||
/* FIXME: Won't always work with zeros for the last two arguments */
|
||||
if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
|
||||
return 0;
|
||||
}
|
||||
return (symfile_objfile->ei.entry_func_lowpc <= pc &&
|
||||
symfile_objfile->ei.entry_func_highpc > pc);
|
||||
}
|
||||
|
||||
/* Return nonzero if the function for this frame lacks a prologue. Many
|
||||
machines can define FRAMELESS_FUNCTION_INVOCATION to just call this
|
||||
function. */
|
||||
|
||||
int
|
||||
frameless_look_for_prologue (struct frame_info *frame)
|
||||
{
|
||||
CORE_ADDR func_start, after_prologue;
|
||||
|
||||
func_start = get_frame_func (frame);
|
||||
if (func_start)
|
||||
{
|
||||
func_start += FUNCTION_START_OFFSET;
|
||||
/* This is faster, since only care whether there *is* a
|
||||
prologue, not how long it is. */
|
||||
return PROLOGUE_FRAMELESS_P (func_start);
|
||||
}
|
||||
else if (get_frame_pc (frame) == 0)
|
||||
/* A frame with a zero PC is usually created by dereferencing a
|
||||
NULL function pointer, normally causing an immediate core dump
|
||||
of the inferior. Mark function as frameless, as the inferior
|
||||
has no chance of setting up a stack frame. */
|
||||
return 1;
|
||||
else
|
||||
/* If we can't find the start of the function, we don't really
|
||||
know whether the function is frameless, but we should be able
|
||||
to get a reasonable (i.e. best we can do under the
|
||||
circumstances) backtrace by saying that it isn't. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return the address of the PC for the given FRAME, ie the current PC value
|
||||
if FRAME is the innermost frame, or the address adjusted to point to the
|
||||
call instruction if not. */
|
||||
|
||||
CORE_ADDR
|
||||
frame_address_in_block (struct frame_info *frame)
|
||||
{
|
||||
CORE_ADDR pc = get_frame_pc (frame);
|
||||
|
||||
/* If we are not in the innermost frame, and we are not interrupted
|
||||
by a signal, frame->pc points to the instruction following the
|
||||
call. As a consequence, we need to get the address of the previous
|
||||
instruction. Unfortunately, this is not straightforward to do, so
|
||||
we just use the address minus one, which is a good enough
|
||||
approximation. */
|
||||
/* FIXME: cagney/2002-11-10: Should this instead test for
|
||||
NORMAL_FRAME? A dummy frame (in fact all the abnormal frames)
|
||||
save the PC value in the block. */
|
||||
if (get_next_frame (frame) != 0
|
||||
&& get_frame_type (get_next_frame (frame)) != SIGTRAMP_FRAME)
|
||||
--pc;
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* Return the innermost lexical block in execution
|
||||
in a specified stack frame. The frame address is assumed valid.
|
||||
|
||||
If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the exact code
|
||||
address we used to choose the block. We use this to find a source
|
||||
line, to decide which macro definitions are in scope.
|
||||
|
||||
The value returned in *ADDR_IN_BLOCK isn't necessarily the frame's
|
||||
PC, and may not really be a valid PC at all. For example, in the
|
||||
caller of a function declared to never return, the code at the
|
||||
return address will never be reached, so the call instruction may
|
||||
be the very last instruction in the block. So the address we use
|
||||
to choose the block is actually one byte before the return address
|
||||
--- hopefully pointing us at the call instruction, or its delay
|
||||
slot instruction. */
|
||||
|
||||
struct block *
|
||||
get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
|
||||
{
|
||||
const CORE_ADDR pc = frame_address_in_block (frame);
|
||||
|
||||
if (addr_in_block)
|
||||
*addr_in_block = pc;
|
||||
|
||||
return block_for_pc (pc);
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
get_pc_function_start (CORE_ADDR pc)
|
||||
{
|
||||
register struct block *bl;
|
||||
register struct symbol *symbol;
|
||||
register struct minimal_symbol *msymbol;
|
||||
CORE_ADDR fstart;
|
||||
|
||||
if ((bl = block_for_pc (pc)) != NULL &&
|
||||
(symbol = block_function (bl)) != NULL)
|
||||
{
|
||||
bl = SYMBOL_BLOCK_VALUE (symbol);
|
||||
fstart = BLOCK_START (bl);
|
||||
}
|
||||
else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
|
||||
{
|
||||
fstart = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
if (!find_pc_section (fstart))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fstart = 0;
|
||||
}
|
||||
return (fstart);
|
||||
}
|
||||
|
||||
/* Return the symbol for the function executing in frame FRAME. */
|
||||
|
||||
struct symbol *
|
||||
get_frame_function (struct frame_info *frame)
|
||||
{
|
||||
register struct block *bl = get_frame_block (frame, 0);
|
||||
if (bl == 0)
|
||||
return 0;
|
||||
return block_function (bl);
|
||||
}
|
||||
|
||||
|
||||
/* Return the function containing pc value PC in section SECTION.
|
||||
Returns 0 if function is not known. */
|
||||
|
||||
struct symbol *
|
||||
find_pc_sect_function (CORE_ADDR pc, struct sec *section)
|
||||
{
|
||||
register struct block *b = block_for_pc_sect (pc, section);
|
||||
if (b == 0)
|
||||
return 0;
|
||||
return block_function (b);
|
||||
}
|
||||
|
||||
/* Return the function containing pc value PC.
|
||||
Returns 0 if function is not known. Backward compatibility, no section */
|
||||
|
||||
struct symbol *
|
||||
find_pc_function (CORE_ADDR pc)
|
||||
{
|
||||
return find_pc_sect_function (pc, find_pc_mapped_section (pc));
|
||||
}
|
||||
|
||||
/* These variables are used to cache the most recent result
|
||||
* of find_pc_partial_function. */
|
||||
|
||||
static CORE_ADDR cache_pc_function_low = 0;
|
||||
static CORE_ADDR cache_pc_function_high = 0;
|
||||
static char *cache_pc_function_name = 0;
|
||||
static struct sec *cache_pc_function_section = NULL;
|
||||
|
||||
/* Clear cache, e.g. when symbol table is discarded. */
|
||||
|
||||
void
|
||||
clear_pc_function_cache (void)
|
||||
{
|
||||
cache_pc_function_low = 0;
|
||||
cache_pc_function_high = 0;
|
||||
cache_pc_function_name = (char *) 0;
|
||||
cache_pc_function_section = NULL;
|
||||
}
|
||||
|
||||
/* Finds the "function" (text symbol) that is smaller than PC but
|
||||
greatest of all of the potential text symbols in SECTION. Sets
|
||||
*NAME and/or *ADDRESS conditionally if that pointer is non-null.
|
||||
If ENDADDR is non-null, then set *ENDADDR to be the end of the
|
||||
function (exclusive), but passing ENDADDR as non-null means that
|
||||
the function might cause symbols to be read. This function either
|
||||
succeeds or fails (not halfway succeeds). If it succeeds, it sets
|
||||
*NAME, *ADDRESS, and *ENDADDR to real information and returns 1.
|
||||
If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero and
|
||||
returns 0. */
|
||||
|
||||
int
|
||||
find_pc_sect_partial_function (CORE_ADDR pc, asection *section, char **name,
|
||||
CORE_ADDR *address, CORE_ADDR *endaddr)
|
||||
{
|
||||
struct partial_symtab *pst;
|
||||
struct symbol *f;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct partial_symbol *psb;
|
||||
struct obj_section *osect;
|
||||
int i;
|
||||
CORE_ADDR mapped_pc;
|
||||
|
||||
mapped_pc = overlay_mapped_address (pc, section);
|
||||
|
||||
if (mapped_pc >= cache_pc_function_low
|
||||
&& mapped_pc < cache_pc_function_high
|
||||
&& section == cache_pc_function_section)
|
||||
goto return_cached_value;
|
||||
|
||||
/* If sigtramp is in the u area, it counts as a function (especially
|
||||
important for step_1). */
|
||||
if (SIGTRAMP_START_P () && PC_IN_SIGTRAMP (mapped_pc, (char *) NULL))
|
||||
{
|
||||
cache_pc_function_low = SIGTRAMP_START (mapped_pc);
|
||||
cache_pc_function_high = SIGTRAMP_END (mapped_pc);
|
||||
cache_pc_function_name = "<sigtramp>";
|
||||
cache_pc_function_section = section;
|
||||
goto return_cached_value;
|
||||
}
|
||||
|
||||
msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
|
||||
pst = find_pc_sect_psymtab (mapped_pc, section);
|
||||
if (pst)
|
||||
{
|
||||
/* Need to read the symbols to get a good value for the end address. */
|
||||
if (endaddr != NULL && !pst->readin)
|
||||
{
|
||||
/* Need to get the terminal in case symbol-reading produces
|
||||
output. */
|
||||
target_terminal_ours_for_output ();
|
||||
PSYMTAB_TO_SYMTAB (pst);
|
||||
}
|
||||
|
||||
if (pst->readin)
|
||||
{
|
||||
/* Checking whether the msymbol has a larger value is for the
|
||||
"pathological" case mentioned in print_frame_info. */
|
||||
f = find_pc_sect_function (mapped_pc, section);
|
||||
if (f != NULL
|
||||
&& (msymbol == NULL
|
||||
|| (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
|
||||
>= SYMBOL_VALUE_ADDRESS (msymbol))))
|
||||
{
|
||||
cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
|
||||
cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
|
||||
cache_pc_function_name = DEPRECATED_SYMBOL_NAME (f);
|
||||
cache_pc_function_section = section;
|
||||
goto return_cached_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now that static symbols go in the minimal symbol table, perhaps
|
||||
we could just ignore the partial symbols. But at least for now
|
||||
we use the partial or minimal symbol, whichever is larger. */
|
||||
psb = find_pc_sect_psymbol (pst, mapped_pc, section);
|
||||
|
||||
if (psb
|
||||
&& (msymbol == NULL ||
|
||||
(SYMBOL_VALUE_ADDRESS (psb)
|
||||
>= SYMBOL_VALUE_ADDRESS (msymbol))))
|
||||
{
|
||||
/* This case isn't being cached currently. */
|
||||
if (address)
|
||||
*address = SYMBOL_VALUE_ADDRESS (psb);
|
||||
if (name)
|
||||
*name = DEPRECATED_SYMBOL_NAME (psb);
|
||||
/* endaddr non-NULL can't happen here. */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not in the normal symbol tables, see if the pc is in a known section.
|
||||
If it's not, then give up. This ensures that anything beyond the end
|
||||
of the text seg doesn't appear to be part of the last function in the
|
||||
text segment. */
|
||||
|
||||
osect = find_pc_sect_section (mapped_pc, section);
|
||||
|
||||
if (!osect)
|
||||
msymbol = NULL;
|
||||
|
||||
/* Must be in the minimal symbol table. */
|
||||
if (msymbol == NULL)
|
||||
{
|
||||
/* No available symbol. */
|
||||
if (name != NULL)
|
||||
*name = 0;
|
||||
if (address != NULL)
|
||||
*address = 0;
|
||||
if (endaddr != NULL)
|
||||
*endaddr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
cache_pc_function_name = DEPRECATED_SYMBOL_NAME (msymbol);
|
||||
cache_pc_function_section = section;
|
||||
|
||||
/* Use the lesser of the next minimal symbol in the same section, or
|
||||
the end of the section, as the end of the function. */
|
||||
|
||||
/* Step over other symbols at this same address, and symbols in
|
||||
other sections, to find the next symbol in this section with
|
||||
a different address. */
|
||||
|
||||
for (i = 1; DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL; i++)
|
||||
{
|
||||
if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol)
|
||||
&& SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol))
|
||||
break;
|
||||
}
|
||||
|
||||
if (DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL
|
||||
&& SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
|
||||
cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
|
||||
else
|
||||
/* We got the start address from the last msymbol in the objfile.
|
||||
So the end address is the end of the section. */
|
||||
cache_pc_function_high = osect->endaddr;
|
||||
|
||||
return_cached_value:
|
||||
|
||||
if (address)
|
||||
{
|
||||
if (pc_in_unmapped_range (pc, section))
|
||||
*address = overlay_unmapped_address (cache_pc_function_low, section);
|
||||
else
|
||||
*address = cache_pc_function_low;
|
||||
}
|
||||
|
||||
if (name)
|
||||
*name = cache_pc_function_name;
|
||||
|
||||
if (endaddr)
|
||||
{
|
||||
if (pc_in_unmapped_range (pc, section))
|
||||
{
|
||||
/* Because the high address is actually beyond the end of
|
||||
the function (and therefore possibly beyond the end of
|
||||
the overlay), we must actually convert (high - 1) and
|
||||
then add one to that. */
|
||||
|
||||
*endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1,
|
||||
section);
|
||||
}
|
||||
else
|
||||
*endaddr = cache_pc_function_high;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Backward compatibility, no section argument. */
|
||||
|
||||
int
|
||||
find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
|
||||
CORE_ADDR *endaddr)
|
||||
{
|
||||
asection *section;
|
||||
|
||||
section = find_pc_overlay (pc);
|
||||
return find_pc_sect_partial_function (pc, section, name, address, endaddr);
|
||||
}
|
||||
|
||||
/* Return the innermost stack frame executing inside of BLOCK,
|
||||
or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */
|
||||
|
||||
struct frame_info *
|
||||
block_innermost_frame (struct block *block)
|
||||
{
|
||||
struct frame_info *frame;
|
||||
register CORE_ADDR start;
|
||||
register CORE_ADDR end;
|
||||
CORE_ADDR calling_pc;
|
||||
|
||||
if (block == NULL)
|
||||
return NULL;
|
||||
|
||||
start = BLOCK_START (block);
|
||||
end = BLOCK_END (block);
|
||||
|
||||
frame = NULL;
|
||||
while (1)
|
||||
{
|
||||
frame = get_prev_frame (frame);
|
||||
if (frame == NULL)
|
||||
return NULL;
|
||||
calling_pc = frame_address_in_block (frame);
|
||||
if (calling_pc >= start && calling_pc < end)
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK
|
||||
below is for infrun.c, which may give the macro a pc without that
|
||||
subtracted out. */
|
||||
|
||||
/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
|
||||
top of the stack frame which we are checking, where "bottom" and
|
||||
"top" refer to some section of memory which contains the code for
|
||||
the call dummy. Calls to this macro assume that the contents of
|
||||
SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
|
||||
are the things to pass.
|
||||
|
||||
This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
|
||||
have that meaning, but the 29k doesn't use ON_STACK. This could be
|
||||
fixed by generalizing this scheme, perhaps by passing in a frame
|
||||
and adding a few fields, at least on machines which need them for
|
||||
DEPRECATED_PC_IN_CALL_DUMMY.
|
||||
|
||||
Something simpler, like checking for the stack segment, doesn't work,
|
||||
since various programs (threads implementations, gcc nested function
|
||||
stubs, etc) may either allocate stack frames in another segment, or
|
||||
allocate other kinds of code on the stack. */
|
||||
|
||||
int
|
||||
deprecated_pc_in_call_dummy_on_stack (CORE_ADDR pc, CORE_ADDR sp,
|
||||
CORE_ADDR frame_address)
|
||||
{
|
||||
return (INNER_THAN ((sp), (pc))
|
||||
&& (frame_address != 0)
|
||||
&& INNER_THAN ((pc), (frame_address)));
|
||||
}
|
||||
|
||||
int
|
||||
deprecated_pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp,
|
||||
CORE_ADDR frame_address)
|
||||
{
|
||||
return ((pc) >= CALL_DUMMY_ADDRESS ()
|
||||
&& (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK));
|
||||
}
|
||||
|
||||
/* Returns true for a user frame or a call_function_by_hand dummy
|
||||
frame, and false for the CRT0 start-up frame. Purpose is to
|
||||
terminate backtrace. */
|
||||
|
||||
int
|
||||
legacy_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
|
||||
{
|
||||
/* Don't prune CALL_DUMMY frames. */
|
||||
if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
|
||||
&& DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
|
||||
return 1;
|
||||
|
||||
/* If the new frame pointer is zero, then it isn't valid. */
|
||||
if (fp == 0)
|
||||
return 0;
|
||||
|
||||
/* If the new frame would be inside (younger than) the previous frame,
|
||||
then it isn't valid. */
|
||||
if (INNER_THAN (fp, get_frame_base (fi)))
|
||||
return 0;
|
||||
|
||||
/* If the architecture has a custom DEPRECATED_FRAME_CHAIN_VALID,
|
||||
call it now. */
|
||||
if (DEPRECATED_FRAME_CHAIN_VALID_P ())
|
||||
return DEPRECATED_FRAME_CHAIN_VALID (fp, fi);
|
||||
|
||||
/* If we're already inside the entry function for the main objfile, then it
|
||||
isn't valid. */
|
||||
if (inside_entry_func (get_frame_pc (fi)))
|
||||
return 0;
|
||||
|
||||
/* If we're inside the entry file, it isn't valid. */
|
||||
/* NOTE/drow 2002-12-25: should there be a way to disable this check? It
|
||||
assumes a single small entry file, and the way some debug readers (e.g.
|
||||
dbxread) figure out which object is the entry file is somewhat hokey. */
|
||||
if (inside_entry_file (frame_pc_unwind (fi)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
7542
gdb/breakpoint.c
7542
gdb/breakpoint.c
File diff suppressed because it is too large
Load Diff
712
gdb/breakpoint.h
712
gdb/breakpoint.h
@@ -1,712 +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;
|
||||
struct block;
|
||||
|
||||
/* 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 OBSOLETE 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. */
|
||||
struct frame_id frame_id;
|
||||
/* 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 *pc, int not_a_sw_breakpoint);
|
||||
|
||||
/* 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. */
|
||||
|
||||
extern enum breakpoint_here breakpoint_here_p (CORE_ADDR);
|
||||
|
||||
extern int breakpoint_inserted_here_p (CORE_ADDR);
|
||||
|
||||
/* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
|
||||
implements a functional superset of this function. The only reason
|
||||
it hasn't been removed is because some architectures still don't
|
||||
use the new framework. Once they have been fixed, this can go. */
|
||||
struct frame_info;
|
||||
extern int deprecated_frame_in_dummy (struct frame_info *);
|
||||
|
||||
extern int breakpoint_thread_match (CORE_ADDR, ptid_t);
|
||||
|
||||
extern void until_break_command (char *, int, 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_id, 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_id);
|
||||
/* 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 call_function_by_hand.
|
||||
|
||||
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) */
|
||||
1200
gdb/buildsym.c
1200
gdb/buildsym.c
File diff suppressed because it is too large
Load Diff
293
gdb/buildsym.h
293
gdb/buildsym.h
@@ -1,293 +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, 2002, 2003 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
|
||||
|
||||
struct objfile;
|
||||
struct symbol;
|
||||
|
||||
/* 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. */
|
||||
|
||||
struct block;
|
||||
|
||||
#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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Non-zero if the context stack is empty. */
|
||||
#define outermost_context_p() (context_stack_depth == 0)
|
||||
|
||||
/* 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 (void *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 struct context_stack *pop_context (void);
|
||||
|
||||
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
|
||||
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,86 +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;
|
||||
}
|
||||
|
||||
const char *
|
||||
builtin_reg_map_regnum_to_name (int regnum)
|
||||
{
|
||||
int reg = regnum - (NUM_REGS + NUM_PSEUDO_REGS);
|
||||
if (reg < 0 || reg >= nr_builtin_regs)
|
||||
return NULL;
|
||||
return builtin_regs[reg].name;
|
||||
}
|
||||
|
||||
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,39 +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
|
||||
|
||||
struct frame_info;
|
||||
|
||||
extern int builtin_reg_map_name_to_regnum (const char *str, int len);
|
||||
|
||||
extern const char *builtin_reg_map_regnum_to_name (int regnum);
|
||||
|
||||
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
|
||||
1815
gdb/c-exp.y
1815
gdb/c-exp.y
File diff suppressed because it is too large
Load Diff
660
gdb/c-lang.c
660
gdb/c-lang.c
@@ -1,660 +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"
|
||||
#include "charset.h"
|
||||
#include "gdb_string.h"
|
||||
#include "demangle.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)
|
||||
{
|
||||
const char *escape;
|
||||
int host_char;
|
||||
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
escape = c_target_char_has_backslash_escape (c);
|
||||
if (escape)
|
||||
{
|
||||
if (quoter == '"' && strcmp (escape, "0") == 0)
|
||||
/* Print nulls embedded in double quoted strings as \000 to
|
||||
prevent ambiguity. */
|
||||
fprintf_filtered (stream, "\\000");
|
||||
else
|
||||
fprintf_filtered (stream, "\\%s", escape);
|
||||
}
|
||||
else if (target_char_to_host (c, &host_char)
|
||||
&& host_char_print_literally (host_char))
|
||||
{
|
||||
if (host_char == '\\' || host_char == quoter)
|
||||
fputs_filtered ("\\", stream);
|
||||
fprintf_filtered (stream, "%c", host_char);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
|
||||
}
|
||||
|
||||
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 */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* 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 */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
cplus_demangle, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* 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 */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* 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);
|
||||
}
|
||||
91
gdb/c-lang.h
91
gdb/c-lang.h
@@ -1,91 +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
|
||||
|
||||
struct ui_file;
|
||||
|
||||
#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);
|
||||
|
||||
/* 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) */
|
||||
1204
gdb/c-typeprint.c
1204
gdb/c-typeprint.c
File diff suppressed because it is too large
Load Diff
599
gdb/c-valprint.c
599
gdb/c-valprint.c
@@ -1,599 +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, 2003 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 "gdb_string.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_PRINT_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 (DEPRECATED_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 &&
|
||||
strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0)
|
||||
{
|
||||
/* 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
|
||||
1275
gdb/charset.c
1275
gdb/charset.c
File diff suppressed because it is too large
Load Diff
120
gdb/charset.h
120
gdb/charset.h
@@ -1,120 +0,0 @@
|
||||
/* Character set conversion support for GDB.
|
||||
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 CHARSET_H
|
||||
#define CHARSET_H
|
||||
|
||||
|
||||
/* If the target program uses a different character set than the host,
|
||||
GDB has some support for translating between the two; GDB converts
|
||||
characters and strings to the host character set before displaying
|
||||
them, and converts characters and strings appearing in expressions
|
||||
entered by the user to the target character set.
|
||||
|
||||
At the moment, GDB only supports single-byte, stateless character
|
||||
sets. This includes the ISO-8859 family (ASCII extended with
|
||||
accented characters, and (I think) Cyrillic, for European
|
||||
languages), and the EBCDIC family (used on IBM's mainframes).
|
||||
Unfortunately, it excludes many Asian scripts, the fixed- and
|
||||
variable-width Unicode encodings, and other desireable things.
|
||||
Patches are welcome! (For example, it would be nice if the Java
|
||||
string support could simply get absorbed into some more general
|
||||
multi-byte encoding support.)
|
||||
|
||||
Furthermore, GDB's code pretty much assumes that the host character
|
||||
set is some superset of ASCII; there are plenty if ('0' + n)
|
||||
expressions and the like.
|
||||
|
||||
When the `iconv' library routine supports a character set meeting
|
||||
the requirements above, it's easy to plug an entry into GDB's table
|
||||
that uses iconv to handle the details. */
|
||||
|
||||
|
||||
/* Set the host character set to CHARSET. CHARSET must be a superset
|
||||
of ASCII, since GDB's code assumes this. */
|
||||
void set_host_charset (const char *charset);
|
||||
|
||||
|
||||
/* Set the target character set to CHARSET. */
|
||||
void set_target_charset (const char *charset);
|
||||
|
||||
|
||||
/* Return the name of the current host/target character set. The
|
||||
result is owned by the charset module; the caller should not free
|
||||
it. */
|
||||
const char *host_charset (void);
|
||||
const char *target_charset (void);
|
||||
|
||||
|
||||
/* In general, the set of C backslash escapes (\n, \f) is specific to
|
||||
the character set. Not all character sets will have form feed
|
||||
characters, for example.
|
||||
|
||||
The following functions allow GDB to parse and print control
|
||||
characters in a character-set-independent way. They are both
|
||||
language-specific (to C and C++) and character-set-specific.
|
||||
Putting them here is a compromise. */
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR have a backslash escape in the
|
||||
C language (i.e., a character like 'n' or 't'), return the host
|
||||
character string that should follow the backslash. Otherwise,
|
||||
return zero.
|
||||
|
||||
When this function returns non-zero, the string it returns is
|
||||
statically allocated; the caller is not responsible for freeing it. */
|
||||
const char *c_target_char_has_backslash_escape (int target_char);
|
||||
|
||||
|
||||
/* If the host character HOST_CHAR is a valid backslash escape in the
|
||||
C language for the target character set, return non-zero, and set
|
||||
*TARGET_CHAR to the target character the backslash escape represents.
|
||||
Otherwise, return zero. */
|
||||
int c_parse_backslash (int host_char, int *target_char);
|
||||
|
||||
|
||||
/* Return non-zero if the host character HOST_CHAR can be printed
|
||||
literally --- that is, if it can be readably printed as itself in a
|
||||
character or string constant. Return zero if it should be printed
|
||||
using some kind of numeric escape, like '\031' in C, '^(25)' in
|
||||
Chill, or #25 in Pascal. */
|
||||
int host_char_print_literally (int host_char);
|
||||
|
||||
|
||||
/* If the host character HOST_CHAR has an equivalent in the target
|
||||
character set, set *TARGET_CHAR to that equivalent, and return
|
||||
non-zero. Otherwise, return zero. */
|
||||
int host_char_to_target (int host_char, int *target_char);
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR has an equivalent in the host
|
||||
character set, set *HOST_CHAR to that equivalent, and return
|
||||
non-zero. Otherwise, return zero. */
|
||||
int target_char_to_host (int target_char, int *host_char);
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR has a corresponding control
|
||||
character (also in the target character set), set *TARGET_CTRL_CHAR
|
||||
to the control character, and return non-zero. Otherwise, return
|
||||
zero. */
|
||||
int target_char_to_control_char (int target_char, int *target_ctrl_char);
|
||||
|
||||
|
||||
#endif /* CHARSET_H */
|
||||
383
gdb/cli-out.c
383
gdb/cli-out.c
@@ -1,383 +0,0 @@
|
||||
/* Output generating routines for GDB CLI.
|
||||
|
||||
Copyright 1999, 2000, 2002, 2003 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;
|
||||
};
|
||||
typedef struct ui_out_data cli_out_data;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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? */
|
||||
|
||||
cli_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)
|
||||
{
|
||||
cli_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;
|
||||
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
wrap_here (identstring);
|
||||
}
|
||||
|
||||
void
|
||||
cli_flush (struct ui_out *uiout)
|
||||
{
|
||||
cli_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,...)
|
||||
{
|
||||
cli_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)
|
||||
{
|
||||
cli_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;
|
||||
|
||||
cli_out_data *data = XMALLOC (cli_out_data);
|
||||
data->stream = stream;
|
||||
data->suppress_output = 0;
|
||||
return ui_out_new (&cli_ui_out_impl, data, flags);
|
||||
}
|
||||
|
||||
struct ui_file *
|
||||
cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
|
||||
{
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
struct ui_file *old = data->stream;
|
||||
data->stream = stream;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* standard gdb initialization hook */
|
||||
void
|
||||
_initialize_cli_out (void)
|
||||
{
|
||||
/* nothing needs to be done */
|
||||
}
|
||||
@@ -1,32 +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
|
||||
|
||||
struct ui_file;
|
||||
|
||||
extern struct ui_out *cli_out_new (struct ui_file *stream);
|
||||
|
||||
extern struct ui_file *cli_out_set_stream (struct ui_out *uiout,
|
||||
struct ui_file *stream);
|
||||
|
||||
#endif
|
||||
1292
gdb/cli/cli-cmds.c
1292
gdb/cli/cli-cmds.c
File diff suppressed because it is too large
Load Diff
@@ -1,129 +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;
|
||||
|
||||
/* Chain containing all defined "maintenance list" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenancelistlist;
|
||||
|
||||
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) */
|
||||
1536
gdb/cli/cli-decode.c
1536
gdb/cli/cli-decode.c
File diff suppressed because it is too large
Load Diff
@@ -1,323 +0,0 @@
|
||||
/* Header file for GDB command decoding library.
|
||||
|
||||
Copyright 2000, 2003 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 "command.h"
|
||||
|
||||
struct re_pattern_buffer;
|
||||
|
||||
#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,824 +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"
|
||||
#include <readline/readline.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;
|
||||
|
||||
ibfd = bfd_openr (filename, target);
|
||||
if (ibfd == 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 */
|
||||
{
|
||||
obfd = bfd_openw (filename, target);
|
||||
if (obfd == 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, FOPEN_WB, "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_srec_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_AB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_AB, "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 = FOPEN_WB;
|
||||
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 = FOPEN_AB;
|
||||
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, FOPEN_RB);
|
||||
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
|
||||
@@ -1,138 +0,0 @@
|
||||
/* CLI Definitions for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002, 2003 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 "interps.h"
|
||||
#include "wrapper.h"
|
||||
#include "event-top.h"
|
||||
#include "ui-out.h"
|
||||
#include "cli-out.h"
|
||||
#include "top.h" /* for "execute_command" */
|
||||
#include "gdb_string.h"
|
||||
|
||||
struct ui_out *cli_uiout;
|
||||
|
||||
/* These are the ui_out and the interpreter for the console interpreter. */
|
||||
|
||||
/* Longjmp-safe wrapper for "execute_command" */
|
||||
static int do_captured_execute_command (struct ui_out *uiout, void *data);
|
||||
static enum gdb_rc safe_execute_command (struct ui_out *uiout, char *command,
|
||||
int from_tty);
|
||||
struct captured_execute_command_args
|
||||
{
|
||||
char *command;
|
||||
int from_tty;
|
||||
};
|
||||
|
||||
/* These implement the cli out interpreter: */
|
||||
|
||||
static void *
|
||||
cli_interpreter_init (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_resume (void *data)
|
||||
{
|
||||
/*sync_execution = 1; */
|
||||
gdb_setup_readline ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_suspend (void *data)
|
||||
{
|
||||
gdb_disable_readline ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Don't display the prompt if we are set quiet. */
|
||||
static int
|
||||
cli_interpreter_display_prompt_p (void *data)
|
||||
{
|
||||
if (interp_quiet_p (NULL))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_exec (void *data, const char *command_str)
|
||||
{
|
||||
int result;
|
||||
struct ui_file *old_stream;
|
||||
|
||||
/* FIXME: cagney/2003-02-01: Need to const char *propogate
|
||||
safe_execute_command. */
|
||||
char *str = strcpy (alloca (strlen (command_str) + 1), command_str);
|
||||
|
||||
/* gdb_stdout could change between the time cli_uiout was initialized
|
||||
and now. Since we're probably using a different interpreter which has
|
||||
a new ui_file for gdb_stdout, use that one instead of the default.
|
||||
|
||||
It is important that it gets reset everytime, since the user could
|
||||
set gdb to use a different interpreter. */
|
||||
old_stream = cli_out_set_stream (cli_uiout, gdb_stdout);
|
||||
result = safe_execute_command (cli_uiout, str, 1);
|
||||
cli_out_set_stream (cli_uiout, old_stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_captured_execute_command (struct ui_out *uiout, void *data)
|
||||
{
|
||||
struct captured_execute_command_args *args =
|
||||
(struct captured_execute_command_args *) data;
|
||||
execute_command (args->command, args->from_tty);
|
||||
return GDB_RC_OK;
|
||||
}
|
||||
|
||||
static enum gdb_rc
|
||||
safe_execute_command (struct ui_out *uiout, char *command, int from_tty)
|
||||
{
|
||||
struct captured_execute_command_args args;
|
||||
args.command = command;
|
||||
args.from_tty = from_tty;
|
||||
return catch_exceptions (uiout, do_captured_execute_command, &args,
|
||||
NULL, RETURN_MASK_ALL);
|
||||
}
|
||||
|
||||
|
||||
/* standard gdb initialization hook */
|
||||
void
|
||||
_initialize_cli_interp (void)
|
||||
{
|
||||
static const struct interp_procs procs = {
|
||||
cli_interpreter_init, /* init_proc */
|
||||
cli_interpreter_resume, /* resume_proc */
|
||||
cli_interpreter_suspend, /* suspend_proc */
|
||||
cli_interpreter_exec, /* exec_proc */
|
||||
cli_interpreter_display_prompt_p /* prompt_proc_p */
|
||||
};
|
||||
struct interp *cli_interp;
|
||||
|
||||
/* Create a default uiout builder for the CLI. */
|
||||
cli_uiout = cli_out_new (gdb_stdout);
|
||||
cli_interp = interp_new (INTERP_CONSOLE, NULL, cli_uiout, &procs);
|
||||
|
||||
interp_add (cli_interp);
|
||||
}
|
||||
1310
gdb/cli/cli-script.c
1310
gdb/cli/cli-script.c
File diff suppressed because it is too large
Load Diff
@@ -1,54 +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
|
||||
|
||||
struct ui_file;
|
||||
struct command_line;
|
||||
struct cmd_list_element;
|
||||
|
||||
/* 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);
|
||||
|
||||
extern struct command_line * copy_command_lines (struct command_line *cmds);
|
||||
|
||||
/* Exported to gdb/infrun.c */
|
||||
|
||||
extern void execute_user_command (struct cmd_list_element *c, char *args);
|
||||
|
||||
#endif /* !defined (CLI_SCRIPT_H) */
|
||||
@@ -1,387 +0,0 @@
|
||||
/* Handle set and show GDB commands.
|
||||
|
||||
Copyright 2000, 2001, 2002, 2003 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 <readline/tilde.h>
|
||||
#include "value.h"
|
||||
#include <ctype.h>
|
||||
#include "gdb_string.h"
|
||||
|
||||
#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)
|
||||
{
|
||||
struct cleanup *showlist_chain;
|
||||
|
||||
showlist_chain = make_cleanup_ui_out_tuple_begin_end (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)
|
||||
{
|
||||
struct cleanup *optionlist_chain
|
||||
= make_cleanup_ui_out_tuple_begin_end (uiout, "optionlist");
|
||||
ui_out_field_string (uiout, "prefix", list->prefixname + 5);
|
||||
cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
|
||||
/* Close the tuple. */
|
||||
do_cleanups (optionlist_chain);
|
||||
}
|
||||
if (list->type == show_cmd)
|
||||
{
|
||||
struct cleanup *option_chain
|
||||
= make_cleanup_ui_out_tuple_begin_end (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);
|
||||
/* Close the tuple. */
|
||||
do_cleanups (option_chain);
|
||||
}
|
||||
}
|
||||
/* Close the tuple. */
|
||||
do_cleanups (showlist_chain);
|
||||
}
|
||||
|
||||
@@ -1,38 +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
|
||||
|
||||
struct cmd_list_element;
|
||||
|
||||
/* 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) */
|
||||
@@ -1,346 +0,0 @@
|
||||
/* Read the export table symbols from a portable executable and
|
||||
convert to internal format, for GDB. Used as a last resort if no
|
||||
debugging symbols recognized.
|
||||
|
||||
Copyright 2003 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.
|
||||
|
||||
Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
|
||||
|
||||
#include "coff-pe-read.h"
|
||||
|
||||
#include "bfd.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
||||
/* Internal section information */
|
||||
|
||||
struct read_pe_section_data
|
||||
{
|
||||
CORE_ADDR vma_offset; /* Offset to loaded address of section. */
|
||||
unsigned long rva_start; /* Start offset within the pe. */
|
||||
unsigned long rva_end; /* End offset within the pe. */
|
||||
enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */
|
||||
};
|
||||
|
||||
#define PE_SECTION_INDEX_TEXT 0
|
||||
#define PE_SECTION_INDEX_DATA 1
|
||||
#define PE_SECTION_INDEX_BSS 2
|
||||
#define PE_SECTION_TABLE_SIZE 3
|
||||
#define PE_SECTION_INDEX_INVALID -1
|
||||
|
||||
/* Get the index of the named section in our own array, which contains
|
||||
text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
|
||||
if passed an unrecognised section name. */
|
||||
|
||||
static int
|
||||
read_pe_section_index (const char *section_name)
|
||||
{
|
||||
if (strcmp (section_name, ".text") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_TEXT;
|
||||
}
|
||||
|
||||
else if (strcmp (section_name, ".data") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_DATA;
|
||||
}
|
||||
|
||||
else if (strcmp (section_name, ".bss") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_BSS;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return PE_SECTION_INDEX_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record the virtual memory address of a section. */
|
||||
|
||||
static void
|
||||
get_section_vmas (bfd *abfd, asection *sectp, void *context)
|
||||
{
|
||||
struct read_pe_section_data *sections = context;
|
||||
int sectix = read_pe_section_index (sectp->name);
|
||||
|
||||
if (sectix != PE_SECTION_INDEX_INVALID)
|
||||
{
|
||||
/* Data within the section start at rva_start in the pe and at
|
||||
bfd_get_section_vma() within memory. Store the offset. */
|
||||
|
||||
sections[sectix].vma_offset
|
||||
= bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a minimal symbol entry for an exported symbol. */
|
||||
|
||||
static void
|
||||
add_pe_exported_sym (char *sym_name,
|
||||
unsigned long func_rva,
|
||||
const struct read_pe_section_data *section_data,
|
||||
const char *dll_name, struct objfile *objfile)
|
||||
{
|
||||
/* Add the stored offset to get the loaded address of the symbol. */
|
||||
|
||||
CORE_ADDR vma = func_rva + section_data->vma_offset;
|
||||
|
||||
char *qualified_name = 0;
|
||||
int dll_name_len = strlen (dll_name);
|
||||
int count;
|
||||
|
||||
/* Generate a (hopefully unique) qualified name using the first part
|
||||
of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
|
||||
used by windbg from the "Microsoft Debugging Tools for Windows". */
|
||||
|
||||
qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2);
|
||||
|
||||
strncpy (qualified_name, dll_name, dll_name_len);
|
||||
qualified_name[dll_name_len] = '!';
|
||||
strcpy (qualified_name + dll_name_len + 1, sym_name);
|
||||
|
||||
prim_record_minimal_symbol (qualified_name,
|
||||
vma, section_data->ms_type, objfile);
|
||||
|
||||
xfree (qualified_name);
|
||||
|
||||
/* Enter the plain name as well, which might not be unique. */
|
||||
prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile);
|
||||
}
|
||||
|
||||
/* Truncate a dll_name at the first dot character. */
|
||||
|
||||
static void
|
||||
read_pe_truncate_name (char *dll_name)
|
||||
{
|
||||
while (*dll_name)
|
||||
{
|
||||
if ((*dll_name) == '.')
|
||||
{
|
||||
*dll_name = '\0'; /* truncates and causes loop exit. */
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
++dll_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Low-level support functions, direct from the ld module pe-dll.c. */
|
||||
static unsigned int
|
||||
pe_get16 (bfd *abfd, int where)
|
||||
{
|
||||
unsigned char b[2];
|
||||
|
||||
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
|
||||
bfd_bread (b, (bfd_size_type) 2, abfd);
|
||||
return b[0] + (b[1] << 8);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pe_get32 (bfd *abfd, int where)
|
||||
{
|
||||
unsigned char b[4];
|
||||
|
||||
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
|
||||
bfd_bread (b, (bfd_size_type) 4, abfd);
|
||||
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pe_as32 (void *ptr)
|
||||
{
|
||||
unsigned char *b = ptr;
|
||||
|
||||
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
|
||||
}
|
||||
|
||||
/* Read the (non-debug) export symbol table from a portable
|
||||
executable. Code originally lifted from the ld function
|
||||
pe_implied_import_dll in pe-dll.c. */
|
||||
|
||||
void
|
||||
read_pe_exported_syms (struct objfile *objfile)
|
||||
{
|
||||
bfd *dll = objfile->obfd;
|
||||
unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
|
||||
unsigned long export_rva, export_size, nsections, secptr, expptr;
|
||||
unsigned long exp_funcbase;
|
||||
unsigned char *expdata, *erva;
|
||||
unsigned long name_rvas, ordinals, nexp, ordbase;
|
||||
char *dll_name;
|
||||
|
||||
/* Array elements are for text, data and bss in that order
|
||||
Initialization with start_rva > end_rva guarantees that
|
||||
unused sections won't be matched. */
|
||||
struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
|
||||
= { {0, 1, 0, mst_text},
|
||||
{0, 1, 0, mst_data},
|
||||
{0, 1, 0, mst_bss}
|
||||
};
|
||||
|
||||
struct cleanup *back_to = 0;
|
||||
|
||||
char const *target = bfd_get_target (objfile->obfd);
|
||||
|
||||
if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0))
|
||||
{
|
||||
/* This is not an i386 format file. Abort now, because the code
|
||||
is untested on anything else. *FIXME* test on further
|
||||
architectures and loosen or remove this test. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get pe_header, optional header and numbers of export entries. */
|
||||
pe_header_offset = pe_get32 (dll, 0x3c);
|
||||
opthdr_ofs = pe_header_offset + 4 + 20;
|
||||
num_entries = pe_get32 (dll, opthdr_ofs + 92);
|
||||
|
||||
if (num_entries < 1) /* No exports. */
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
export_rva = pe_get32 (dll, opthdr_ofs + 96);
|
||||
export_size = pe_get32 (dll, opthdr_ofs + 100);
|
||||
nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
|
||||
secptr = (pe_header_offset + 4 + 20 +
|
||||
pe_get16 (dll, pe_header_offset + 4 + 16));
|
||||
expptr = 0;
|
||||
|
||||
/* Get the rva and size of the export section. */
|
||||
for (i = 0; i < nsections; i++)
|
||||
{
|
||||
char sname[8];
|
||||
unsigned long secptr1 = secptr + 40 * i;
|
||||
unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
|
||||
unsigned long vsize = pe_get32 (dll, secptr1 + 16);
|
||||
unsigned long fptr = pe_get32 (dll, secptr1 + 20);
|
||||
|
||||
bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
|
||||
bfd_bread (sname, (bfd_size_type) 8, dll);
|
||||
|
||||
if (vaddr <= export_rva && vaddr + vsize > export_rva)
|
||||
{
|
||||
expptr = fptr + (export_rva - vaddr);
|
||||
if (export_rva + export_size > vaddr + vsize)
|
||||
export_size = vsize - (export_rva - vaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (export_size == 0)
|
||||
{
|
||||
/* Empty export table. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan sections and store the base and size of the relevant sections. */
|
||||
for (i = 0; i < nsections; i++)
|
||||
{
|
||||
unsigned long secptr1 = secptr + 40 * i;
|
||||
unsigned long vsize = pe_get32 (dll, secptr1 + 8);
|
||||
unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
|
||||
unsigned long flags = pe_get32 (dll, secptr1 + 36);
|
||||
char sec_name[9];
|
||||
int sectix;
|
||||
|
||||
sec_name[8] = '\0';
|
||||
bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
|
||||
bfd_bread (sec_name, (bfd_size_type) 8, dll);
|
||||
|
||||
sectix = read_pe_section_index (sec_name);
|
||||
|
||||
if (sectix != PE_SECTION_INDEX_INVALID)
|
||||
{
|
||||
section_data[sectix].rva_start = vaddr;
|
||||
section_data[sectix].rva_end = vaddr + vsize;
|
||||
}
|
||||
}
|
||||
|
||||
expdata = (unsigned char *) xmalloc (export_size);
|
||||
back_to = make_cleanup (xfree, expdata);
|
||||
|
||||
bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
|
||||
bfd_bread (expdata, (bfd_size_type) export_size, dll);
|
||||
erva = expdata - export_rva;
|
||||
|
||||
nexp = pe_as32 (expdata + 24);
|
||||
name_rvas = pe_as32 (expdata + 32);
|
||||
ordinals = pe_as32 (expdata + 36);
|
||||
ordbase = pe_as32 (expdata + 16);
|
||||
exp_funcbase = pe_as32 (expdata + 28);
|
||||
|
||||
/* Use internal dll name instead of full pathname. */
|
||||
dll_name = pe_as32 (expdata + 12) + erva;
|
||||
|
||||
bfd_map_over_sections (dll, get_section_vmas, section_data);
|
||||
|
||||
/* Adjust the vma_offsets in case this PE got relocated. This
|
||||
assumes that *all* sections share the same relocation offset
|
||||
as the text section. */
|
||||
for (i = 0; i < PE_SECTION_TABLE_SIZE; i++)
|
||||
{
|
||||
section_data[i].vma_offset
|
||||
+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
||||
}
|
||||
|
||||
printf_filtered ("Minimal symbols from %s...", dll_name);
|
||||
wrap_here ("");
|
||||
|
||||
/* Truncate name at first dot. Should maybe also convert to all
|
||||
lower case for convenience on Windows. */
|
||||
read_pe_truncate_name (dll_name);
|
||||
|
||||
/* Iterate through the list of symbols. */
|
||||
for (i = 0; i < nexp; i++)
|
||||
{
|
||||
/* Pointer to the names vector. */
|
||||
unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
|
||||
|
||||
/* Pointer to the function address vector. */
|
||||
unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
|
||||
|
||||
/* Find this symbol's section in our own array. */
|
||||
int sectix = 0;
|
||||
|
||||
for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix)
|
||||
{
|
||||
if ((func_rva >= section_data[sectix].rva_start)
|
||||
&& (func_rva < section_data[sectix].rva_end))
|
||||
{
|
||||
add_pe_exported_sym (erva + name_rva,
|
||||
func_rva,
|
||||
section_data + sectix, dll_name, objfile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* discard expdata. */
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Interface to coff-pe-read.c (portable-executable-specific symbol reader).
|
||||
|
||||
Copyright 2003 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.
|
||||
|
||||
Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
|
||||
|
||||
#if !defined (COFF_PE_READ_H)
|
||||
#define COFF_PE_READ_H
|
||||
|
||||
struct objfile;
|
||||
|
||||
/* Read the export table and convert it to minimal symbol table entries */
|
||||
extern void read_pe_exported_syms (struct objfile *objfile);
|
||||
|
||||
#endif /* !defined (COFF_PE_READ_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
|
||||
2160
gdb/coffread.c
2160
gdb/coffread.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user