Remove WAD and swig.spec.1 - not used or maintained
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12070 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
27056fbd9f
commit
5aaf531b5a
51 changed files with 0 additions and 7404 deletions
|
|
@ -1,25 +0,0 @@
|
|||
WAD 0.3 - June 2, 2002
|
||||
|
||||
- Added to the SWIG distribution.
|
||||
|
||||
WAD 0.2 - June 24, 2001
|
||||
|
||||
- Minor changes. Added the wadtrace file
|
||||
|
||||
- Put everything under the LGPL.
|
||||
|
||||
WAD 0.1 - March 23, 2001
|
||||
|
||||
- Extensive changes to WAD core. WAD now builds an exception
|
||||
object that can be queried and manipulated after a fault
|
||||
occurs.
|
||||
|
||||
- Better collection of debugging information. WAD is now
|
||||
able to determine basic datatypes and other information
|
||||
from stabs data.
|
||||
|
||||
- Better reliability overall.
|
||||
|
||||
WAD 0.0 - January, 2001
|
||||
|
||||
beazley - Initial "release". Not much of a release really.
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 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.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, 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 library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete 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 distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
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 Library or any portion
|
||||
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
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 Library, 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 Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you 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.
|
||||
|
||||
If distribution of 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 satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be 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.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library 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.
|
||||
|
||||
9. 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 Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
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 with
|
||||
this License.
|
||||
|
||||
11. 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 Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library 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 Library.
|
||||
|
||||
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.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library 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.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser 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 Library
|
||||
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 Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
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
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. 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 LIBRARY 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
|
||||
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; 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.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
The WAD Developers Guide
|
||||
|
||||
David Beazley (beazley@cs.uchicago.edu)
|
||||
|
||||
$Id$
|
||||
|
||||
1. Introduction
|
||||
|
||||
This short document is intended for anyone who feels inclined to work
|
||||
on WAD and make improvements. It is by no means complete. However,
|
||||
it contains random commentary on the current implementation.
|
||||
|
||||
2. A brief word on the execution environment
|
||||
|
||||
Because WAD is embedded in the same application it is intended to
|
||||
debug, it must take an extremely conservative approach to its own
|
||||
execution environment. Specifically, it can not rely upon the correct
|
||||
operation of C library--especially with respect to memory management
|
||||
and other basic operations. Because of this, the implementation of
|
||||
WAD makes every effort to be as self-contained as possible--thus
|
||||
minimizing its exposure to corrupted libraries in the faulting
|
||||
application. Closely related to this, WAD does not rely on any
|
||||
third-party libraries (e.g., libbfd) since it is almost impossible to
|
||||
fully verify the way in which such libraries might use other programming
|
||||
libraries.
|
||||
|
||||
With that said, you might keep the following rules in mind:
|
||||
|
||||
rule 1: Trust nothing--it might be broken.
|
||||
rule 2: When in doubt, see rule 1.
|
||||
|
||||
(Of course, we can probably get away with assuming that the OS isn't
|
||||
hosed).
|
||||
|
||||
3. Memory management
|
||||
|
||||
There are two problems here: first, the dynamic memory
|
||||
allocator may be corrupted or broken (e.g., as might occur when
|
||||
you double-free memory or free memory not allocated by malloc).
|
||||
Second, the WAD signal handler prefers to execute own on its own
|
||||
signal handling stack. This stack is of limited size so it is not
|
||||
a reliable place to put large amounts of data.
|
||||
|
||||
Small buffers and scratch areas are managed through the use of static
|
||||
variables allocated in the WAD data-segment.
|
||||
|
||||
For dynamic memory management, WAD provides its own memory allocator
|
||||
in the function wad_malloc(). This function allocates memory by using
|
||||
mmap() to grab anonymous memory regions (mapped to /dev/zero). This
|
||||
memory is currently allocated in chunks of 64Kbytes as needed.
|
||||
|
||||
To simplify the implementation and prevent potential memory problems
|
||||
in WAD itself, WAD never releases the memory that it allocates. There
|
||||
is no wad_free() operation nor is there any way to release all of the
|
||||
memory previously allocated.
|
||||
|
||||
Although memory is never released, WAD tries to intern commonly used
|
||||
strings. An internal string hash is built as WAD runs and in most
|
||||
cases, each string is mapped to a single instance of the string in
|
||||
this hash table. The function wad_string_lookup(char *s) is used to
|
||||
return a pointer to the string s in the hash table. If no entry
|
||||
exists, it is created and a pointer is returned.
|
||||
|
||||
4. I/O
|
||||
|
||||
It is probably a bad idea to use buffered I/O with WAD. This may
|
||||
result in implicit calls to malloc() and related functions.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wad.h
|
||||
*
|
||||
* WAD header file (obviously)
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2001. University of Chicago. All rights reserved.
|
||||
*
|
||||
* $Id$
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
#include <procfs.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Core datatypes */
|
||||
|
||||
typedef int int32;
|
||||
typedef unsigned uint32;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 1024
|
||||
#endif
|
||||
|
||||
#define WAD_SRC_WINDOW 2
|
||||
|
||||
/* --- Low level memory management functions --- */
|
||||
|
||||
extern int wad_memory_init();
|
||||
extern void *wad_malloc(int nbytes);
|
||||
extern char *wad_strdup(const char *c);
|
||||
extern void wad_memory_debug();
|
||||
extern void wad_memcpy(void *t, const void *s, unsigned len);
|
||||
|
||||
/* --- Low level string handling --- */
|
||||
|
||||
extern char *wad_string_lookup(char *s);
|
||||
extern void wad_string_debug();
|
||||
extern char *wad_strcpy(char *t, const char *s);
|
||||
extern char *wad_strcat(char *t, const char *s);
|
||||
extern int wad_strlen(const char *s);
|
||||
|
||||
/* --- I/O, Debugging --- */
|
||||
|
||||
extern void wad_printf(const char *fmt, ...);
|
||||
extern char *wad_format_hex(unsigned long u, int leading);
|
||||
extern char *wad_format_unsigned(unsigned long u, int width);
|
||||
extern char *wad_format_signed(long s, int width);
|
||||
|
||||
/* --- Memory segments --- */
|
||||
typedef struct WadSegment {
|
||||
char *base; /* Base address for symbol lookup */
|
||||
char *vaddr; /* Virtual address start */
|
||||
unsigned long size; /* Size of the segment (bytes) */
|
||||
unsigned long offset; /* Offset into mapped object */
|
||||
char *mapname; /* Filename mapped to this region */
|
||||
char *mappath; /* Full path to mapname */
|
||||
struct WadSegment *next; /* Next segment */
|
||||
} WadSegment;
|
||||
|
||||
extern int wad_segment_read();
|
||||
extern WadSegment *wad_segment_find(void *vaddr);
|
||||
extern int wad_segment_valid(void *vaddr);
|
||||
|
||||
/* --- Object files --- */
|
||||
typedef struct WadObjectFile {
|
||||
void *ptr; /* Pointer to data */
|
||||
int len; /* Length of data */
|
||||
int type; /* Type of the object file */
|
||||
char *path; /* Path name of this object */
|
||||
struct WadObjectFile *next;
|
||||
} WadObjectFile;
|
||||
|
||||
extern void wad_object_reset();
|
||||
extern WadObjectFile *wad_object_load(const char *path);
|
||||
extern int wad_file_check(void *);
|
||||
|
||||
#define SYM_LOCAL 1
|
||||
#define SYM_GLOBAL 2
|
||||
|
||||
/* Signal handling */
|
||||
extern void wad_init();
|
||||
extern void wad_signalhandler(int, siginfo_t *, void *);
|
||||
extern void wad_signal_init();
|
||||
extern void wad_signal_clear();
|
||||
extern void wad_set_return(const char *name, long value);
|
||||
extern void wad_set_return_value(long value);
|
||||
extern void wad_set_return_func(void (*f)(void));
|
||||
|
||||
typedef struct WadLocal {
|
||||
char *name; /* Name of the local */
|
||||
void *ptr; /* Pointer to the actual data (if known) */
|
||||
int size; /* Size of the data (if known) */
|
||||
int type; /* Data type */
|
||||
|
||||
/* Debugging information */
|
||||
|
||||
int loc; /* Location: register or stack */
|
||||
int stack; /* location on the stack */
|
||||
int reg; /* Register number */
|
||||
int line; /* Line number where defined */
|
||||
struct WadLocal *next;
|
||||
} WadLocal;
|
||||
|
||||
#define PARM_REGISTER 1
|
||||
#define PARM_STACK 2
|
||||
|
||||
/* Type codes for local variables */
|
||||
|
||||
#define WAD_TYPE_UNKNOWN 0
|
||||
#define WAD_TYPE_INT32 1
|
||||
#define WAD_TYPE_INT16 2
|
||||
#define WAD_TYPE_INT8 3
|
||||
#define WAD_TYPE_INT64 4
|
||||
#define WAD_TYPE_UINT32 5
|
||||
#define WAD_TYPE_UINT16 6
|
||||
#define WAD_TYPE_UINT8 7
|
||||
#define WAD_TYPE_UINT64 8
|
||||
#define WAD_TYPE_FLOAT 9
|
||||
#define WAD_TYPE_DOUBLE 10
|
||||
#define WAD_TYPE_POINTER 11
|
||||
#define WAD_TYPE_CHAR 12
|
||||
|
||||
extern long wad_local_as_long(WadLocal *loc);
|
||||
extern double wad_local_as_double(WadLocal *loc);
|
||||
|
||||
/* Data structure containing information about each stack frame */
|
||||
|
||||
typedef struct WadFrame {
|
||||
long frameno; /* Frame number */
|
||||
struct WadFrame *next; /* Next frame up the stack */
|
||||
struct WadFrame *prev; /* Previous frame down the stack */
|
||||
|
||||
/* Stack context information */
|
||||
long pc; /* Real PC */
|
||||
long sp; /* Real SP */
|
||||
long fp; /* Real FP */
|
||||
char *stack; /* Pointer to where a copy of the stack frame is stored */
|
||||
int stack_size; /* Stack frame size (fp-sp) */
|
||||
|
||||
/* Loading information. Contains information from /proc as well as a pointer to
|
||||
the executable or shared library in which the PC is located */
|
||||
|
||||
WadSegment *segment; /* Memory segment corresponding to PC */
|
||||
WadObjectFile *object; /* Object file corresponding to PC */
|
||||
|
||||
/* Symbol table information for PC */
|
||||
|
||||
char *sym_name; /* Symbol name */
|
||||
int sym_nlen; /* Symbol name length */
|
||||
char *sym_file; /* Source file (if any) */
|
||||
unsigned long sym_base; /* Symbol base address */
|
||||
unsigned long sym_size; /* Symbol size */
|
||||
int sym_type; /* Symbol type */
|
||||
int sym_bind; /* Symbol binding */
|
||||
|
||||
/* Location information */
|
||||
char *loc_objfile; /* Object filename */
|
||||
char *loc_srcfile; /* Source filename */
|
||||
int loc_line; /* Source line */
|
||||
|
||||
/* Debugging information */
|
||||
int debug_check; /* Checked debugging information */
|
||||
int debug_nargs; /* Number of arguments */
|
||||
WadLocal *debug_args; /* Arguments */
|
||||
WadLocal *debug_lastarg; /* Last argument */
|
||||
int debug_nlocals; /* Number of locals */
|
||||
WadLocal *debug_locals; /* Local variables */
|
||||
WadLocal *debug_lastlocal; /* Last local */
|
||||
|
||||
/* Output strings */
|
||||
char *debug_str; /* Debugging string */
|
||||
char *debug_srcstr; /* Source string */
|
||||
|
||||
int last; /* Last frame flag */
|
||||
} WadFrame;
|
||||
|
||||
extern WadFrame *wad_stack_trace(unsigned long, unsigned long, unsigned long);
|
||||
extern void wad_stack_debug(WadFrame *f);
|
||||
|
||||
extern char *wad_strip_dir(char *);
|
||||
extern void wad_default_callback(int signo, WadFrame *frame, char *ret);
|
||||
extern void wad_dump_trace(int fd, int signo, WadFrame *frame, char *ret);
|
||||
|
||||
extern void wad_set_callback(void (*h)(int, WadFrame *, char *));
|
||||
extern char *wad_load_source(char *, int line);
|
||||
extern void wad_release_source();
|
||||
extern void wad_release_trace();
|
||||
extern long wad_steal_arg(WadFrame *f, char *symbol, int argno, int *error);
|
||||
extern long wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error);
|
||||
|
||||
extern char *wad_arg_string(WadFrame *f);
|
||||
|
||||
typedef struct {
|
||||
char name[128];
|
||||
long value;
|
||||
} WadReturnFunc;
|
||||
|
||||
extern void wad_set_returns(WadReturnFunc *rf);
|
||||
extern WadReturnFunc *wad_check_return(const char *name);
|
||||
|
||||
extern int wad_search_stab(void *stab, int size, char *stabstr, WadFrame *f);
|
||||
|
||||
extern void wad_find_object(WadFrame *f);
|
||||
extern void wad_find_symbol(WadFrame *f);
|
||||
extern void wad_find_debug(WadFrame *f);
|
||||
extern void wad_build_vars(WadFrame *f);
|
||||
extern char *wad_format_var(WadLocal *l);
|
||||
|
||||
extern void wad_debug_make_strings(WadFrame *f);
|
||||
|
||||
/* --- Debugging Interface --- */
|
||||
|
||||
#define DEBUG_SEGMENT 0x1
|
||||
#define DEBUG_SYMBOL 0x2
|
||||
#define DEBUG_STABS 0x4
|
||||
#define DEBUG_OBJECT 0x8
|
||||
#define DEBUG_FILE 0x10
|
||||
#define DEBUG_HOLD 0x20
|
||||
#define DEBUG_RETURN 0x40
|
||||
#define DEBUG_SYMBOL_SEARCH 0x80
|
||||
#define DEBUG_INIT 0x100
|
||||
#define DEBUG_NOSTACK 0x200
|
||||
#define DEBUG_ONESHOT 0x400
|
||||
#define DEBUG_STACK 0x800
|
||||
#define DEBUG_UNWIND 0x1000
|
||||
#define DEBUG_SIGNAL 0x2000
|
||||
#define DEBUG_STRING 0x4000
|
||||
#define DEBUG_MEMORY 0x8000
|
||||
|
||||
extern int wad_debug_mode;
|
||||
extern int wad_heap_overflow;
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
#define WAD_LITTLE_ENDIAN
|
||||
#endif
|
||||
#ifdef WAD_SOLARIS
|
||||
#define WAD_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Generated automatically from Makefile.in by configure.
|
||||
|
||||
SHELL = /bin/sh
|
||||
prefix = @prefix@
|
||||
execprefix= @exec_prefix@
|
||||
LIB = $(execprefix)/lib
|
||||
|
||||
# Location of your Python installation
|
||||
PYINCLUDE = @PYINCLUDE@
|
||||
|
||||
# Location of your Tcl installation
|
||||
TCLINCLUDE = @TCLINCLUDE@
|
||||
|
||||
# Location of your Perl installation
|
||||
PERLINCLUDE = @PERL5EXT@
|
||||
|
||||
all: wad @MAKEPYTHON@ @MAKETCL@ #@MAKEPERL@
|
||||
|
||||
wad:
|
||||
@cd Wad; $(MAKE) wad
|
||||
|
||||
python:
|
||||
@cd Python; $(MAKE) SINCLUDE='$(PYINCLUDE)' python
|
||||
|
||||
tcl:
|
||||
@cd Tcl; $(MAKE) SINCLUDE='$(TCLINCLUDE)' tcl
|
||||
|
||||
perl:
|
||||
@cd Wad; $(MAKE) SINCLUDE='$(PERLINCLUDE)' perl
|
||||
|
||||
install:
|
||||
cp libwad*.so $(LIB)
|
||||
chmod a+rx $(LIB)/libwad*.so
|
||||
|
||||
semi:
|
||||
@cd Wad; $(MAKE) semi
|
||||
@cd Python; $(MAKE) semi
|
||||
@cd Tcl; $(MAKE) semi
|
||||
|
||||
clean:
|
||||
@cd Wad; $(MAKE) clean
|
||||
@cd Python; $(MAKE) clean
|
||||
@cd Tcl; $(MAKE) clean
|
||||
@cd Test; $(MAKE) clean
|
||||
rm *.so
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* segment.c
|
||||
*
|
||||
* This file provides access to the virtual memory map of a process
|
||||
* including the location of the executable, data segments, shared
|
||||
* libraries, and memory mapped regions. This information is
|
||||
* obtained through /proc.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
Papers about WAD can be obtained at:
|
||||
|
||||
http://systems.cs.uchicago.edu/wad
|
||||
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Generated automatically from Makefile.in by configure.
|
||||
|
||||
SHELL = /bin/sh
|
||||
prefix = @prefix@
|
||||
execprefix= @exec_prefix@
|
||||
LIB = $(execprefix)/lib
|
||||
|
||||
install:
|
||||
cp libwad*.so $(LIB)
|
||||
chmod a+rx $(LIB)/libwad*.so
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Generated automatically from Makefile.in by configure.
|
||||
|
||||
SHELL = /bin/sh
|
||||
prefix = @prefix@
|
||||
execprefix= @exec_prefix@
|
||||
LIB = $(execprefix)/lib
|
||||
|
||||
install:
|
||||
cp libwad*.so $(LIB)
|
||||
chmod a+rx $(LIB)/libwad*.so
|
||||
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
#######################################################################
|
||||
# WAD Makefile
|
||||
#
|
||||
# David Beazley
|
||||
# January 1, 2001
|
||||
#######################################################################
|
||||
|
||||
# These are the files that make up the WAD core
|
||||
SRCS = type.c python.c
|
||||
OBJS = type.o python.o
|
||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||
WADOPT = @WADOPT@
|
||||
|
||||
# Location of your Python installation
|
||||
PYINCLUDE = @PYINCLUDE@
|
||||
PYSRCS = wadpyinit.cxx
|
||||
PYOBJS = wadpyinit.o
|
||||
|
||||
# C Compiler
|
||||
CC = @CC@
|
||||
CFLAGS = #@CCSHARED@
|
||||
|
||||
# C++ Compiler
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = #@CXXSHARED@
|
||||
|
||||
# Linking options
|
||||
CLINK =
|
||||
CXXLINK = @CXXLINK@
|
||||
|
||||
# Rules for creation of a .o file from .cxx
|
||||
.SUFFIXES: .cxx
|
||||
.cxx.o:
|
||||
$(CXX) $(CXXFLAGS) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(PYINCLUDE) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
python: $(OBJS) $(PYOBJS)
|
||||
$(CXXLINK) $(OBJS) $(PYOBJS) -o libwadpy.so -L.. -lwadcore
|
||||
cp libwadpy.so ..
|
||||
|
||||
wc::
|
||||
wc $(SRCS)
|
||||
|
||||
semi::
|
||||
@egrep ";" $(SRCS) $(PYSRCS) | wc
|
||||
|
||||
clean::
|
||||
rm -f *.o *.so *~
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* python.c
|
||||
*
|
||||
* Dynamically loadable python module for wad.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "Python.h"
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* These are the python exception objects we will add
|
||||
SegFault, BusError, AbortError */
|
||||
|
||||
static PyObject *segfault_exc = 0;
|
||||
static PyObject *buserror_exc = 0;
|
||||
static PyObject *abort_exc = 0;
|
||||
static PyObject *illegal_exc = 0;
|
||||
|
||||
extern PyObject *new_wadobject(WadFrame *f,int);
|
||||
|
||||
/* Function return points and values */
|
||||
|
||||
static WadReturnFunc retpts[] = {
|
||||
{"call_builtin", 0},
|
||||
{"_PyImport_LoadDynamicModule", 0},
|
||||
{"PyEval_EvalCode", 0},
|
||||
{"PyObject_GetAttrString", 0},
|
||||
{"PyObject_SetAttrString", -1},
|
||||
{"PyObject_Repr", 0},
|
||||
{"PyObject_Print", -1},
|
||||
{"PyObject_CallFunction", 0},
|
||||
{"PyObject_CallMethod", 0},
|
||||
{"PyObject_CallObject", 0},
|
||||
{"PyObject_Cmp", -1},
|
||||
{"PyObject_Compare", -1},
|
||||
{"PyObject_DelAttrString",-1},
|
||||
{"PyObject_DelItem",-1},
|
||||
{"PyObject_GetItem",0},
|
||||
{"PyObject_SetItem",-1},
|
||||
{"PyObject_HasAttrString",-1},
|
||||
{"PyObject_Hash",-1},
|
||||
{"PyObject_Length",-1},
|
||||
{"PyObject_Str",0},
|
||||
{"PyObject_Type", 0},
|
||||
|
||||
{"PyNumber_Absolute", 0},
|
||||
{"PyNumber_Add",0},
|
||||
{"PyNumber_And",0},
|
||||
{"PyNumber_Coerce",0},
|
||||
{"PyNumber_Divide",0},
|
||||
{"PyNumber_Divmod",0},
|
||||
{"PyNumber_Float",0},
|
||||
{"PyNumber_Int",0},
|
||||
{"PyNumber_Invert",0},
|
||||
{"PyNumber_Long",0},
|
||||
{"PyNumber_Lshift",0},
|
||||
{"PyNumber_Multiply", 0},
|
||||
{"PyNumber_Negative", 0},
|
||||
{"PyNumber_Or",0},
|
||||
{"PyNumber_Positive", 0},
|
||||
{"PyNumber_Power",0},
|
||||
{"PyNumber_Remainder",0},
|
||||
{"PyNumber_Rshift",0},
|
||||
{"PyNumber_Subtract",0},
|
||||
{"PyNumber_Xor",0},
|
||||
|
||||
{"PySequence_Concat",0},
|
||||
{"PySequence_Count",-1},
|
||||
{"PySequence_Delitem",-1},
|
||||
{"PySequence_DelSlice",-1},
|
||||
{"PySequence_Getitem",0},
|
||||
{"PySequence_GetSlice",0},
|
||||
{"PySequence_In",-1},
|
||||
{"PySequence_Index",-1},
|
||||
{"PySequence_Repeat",0},
|
||||
{"PySequence_SetItem",-1},
|
||||
{"PySequence_SetSlice",-1},
|
||||
{"PySequence_Tuple",0},
|
||||
|
||||
{"PyMapping_Clear",-1},
|
||||
{"PyMapping_DelItem",-1},
|
||||
{"PyMapping_DelItemString",-1},
|
||||
{"PyMapping_GetItemString",0},
|
||||
{"PyMapping_HasKey",-1},
|
||||
{"PyMapping_HasKeyString",-1},
|
||||
{"PyMapping_Items",0},
|
||||
{"PyMapping_Keys",0},
|
||||
{"PyMapping_Length", -1},
|
||||
{"PyMapping_SetItemString", -1},
|
||||
{"PyMapping_Values", 0},
|
||||
{"",0}};
|
||||
|
||||
/* Handler function */
|
||||
static void handler(int signo, WadFrame *frame, char *ret) {
|
||||
static char message[65536];
|
||||
static char temp[1024];
|
||||
int len = 0;
|
||||
PyObject *type;
|
||||
char *name;
|
||||
WadFrame *f;
|
||||
WadFrame *fline = 0;
|
||||
char *srcstr = 0;
|
||||
|
||||
/* printf("python handler.\n"); */
|
||||
if (!ret) {
|
||||
wad_default_callback(signo, frame, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(message,"[ C stack trace ]\n\n");
|
||||
switch(signo) {
|
||||
case SIGSEGV:
|
||||
type = segfault_exc;
|
||||
break;
|
||||
case SIGBUS:
|
||||
type = buserror_exc;
|
||||
break;
|
||||
case SIGABRT:
|
||||
type = abort_exc;
|
||||
break;
|
||||
case SIGFPE:
|
||||
type = PyExc_FloatingPointError;
|
||||
break;
|
||||
case SIGILL:
|
||||
type = illegal_exc;
|
||||
break;
|
||||
default:
|
||||
type = PyExc_RuntimeError;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef OLD
|
||||
f = frame;
|
||||
/* Find the last exception frame */
|
||||
while (!f->last) {
|
||||
f= f->next;
|
||||
}
|
||||
/* Now work backwards */
|
||||
f = f->prev;
|
||||
while (f) {
|
||||
strcat(message, f->debug_str);
|
||||
if (f->debug_srcstr) srcstr = f->debug_srcstr;
|
||||
f = f->prev;
|
||||
}
|
||||
if (srcstr) {
|
||||
strcat(message,"\n");
|
||||
strcat(message, srcstr);
|
||||
strcat(message,"\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wad_heap_overflow) {
|
||||
write(2, "WAD: Heap overflow detected.\n", 30);
|
||||
wad_default_callback(signo, frame, ret);
|
||||
}
|
||||
|
||||
/* Note: if the heap is blown, there is a very good chance that this
|
||||
function will not succeed and we'll dump core. However, the check
|
||||
above should dump a stack trace to stderr just in case we don't make it
|
||||
back. */
|
||||
|
||||
#ifdef OLD
|
||||
PyErr_SetString(type, message);
|
||||
#endif
|
||||
PyErr_SetObject(type, new_wadobject(frame,0));
|
||||
|
||||
}
|
||||
|
||||
void pywadinit() {
|
||||
PyObject *d, *m;
|
||||
m = PyImport_ImportModule((char *)"__builtin__");
|
||||
d = PyModule_GetDict(m);
|
||||
printf("WAD Enabled\n");
|
||||
|
||||
segfault_exc = PyErr_NewException((char *)"exceptions.SegFault", NULL, NULL);
|
||||
PyDict_SetItemString(d,(char *)"SegFault",segfault_exc);
|
||||
|
||||
buserror_exc = PyErr_NewException((char *)"exceptions.BusError", NULL, NULL);
|
||||
PyDict_SetItemString(d,(char *)"BusError",buserror_exc);
|
||||
|
||||
abort_exc = PyErr_NewException((char*)"exceptions.AbortError", NULL, NULL);
|
||||
PyDict_SetItemString(d,(char *)"AbortError",abort_exc);
|
||||
|
||||
illegal_exc = PyErr_NewException((char *)"exceptions.IllegalInstruction", NULL, NULL);
|
||||
PyDict_SetItemString(d,(char *)"IllegalInstruction",illegal_exc);
|
||||
|
||||
wad_init();
|
||||
wad_set_callback(handler);
|
||||
wad_set_returns(retpts);
|
||||
}
|
||||
|
||||
static PyMethodDef wadmethods[] = {
|
||||
{0,0},
|
||||
};
|
||||
|
||||
void initlibwadpy() {
|
||||
Py_InitModule((char *)"libwadpy",wadmethods);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* type.c
|
||||
*
|
||||
* This file defines a new python type that contains information from
|
||||
* the WAD stack trace.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "wad.h"
|
||||
#include "Python.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
WadFrame *frame; /* Wad Stack frame object */
|
||||
int count; /* Number of frames */
|
||||
} wadobject;
|
||||
|
||||
staticforward PyTypeObject WadObjectType;
|
||||
|
||||
|
||||
PyObject *
|
||||
new_wadobject(WadFrame *f, int count) {
|
||||
wadobject *self;
|
||||
self = PyObject_NEW(wadobject, &WadObjectType);
|
||||
if (self == NULL) return NULL;
|
||||
|
||||
self->frame = f;
|
||||
if (count > 0) {
|
||||
self->count = count;
|
||||
} else {
|
||||
self->count = 0;
|
||||
while (f) {
|
||||
self->count++;
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
return (PyObject *) self;
|
||||
}
|
||||
|
||||
/* release a wad object */
|
||||
static void
|
||||
wadobject_dealloc(wadobject *self) {
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
static char message[65536];
|
||||
static PyObject *
|
||||
wadobject_repr(wadobject *self) {
|
||||
char *srcstr = 0;
|
||||
WadFrame *fp = 0;
|
||||
int n;
|
||||
WadFrame *f = self->frame;
|
||||
|
||||
message[0] = 0;
|
||||
/* Find the last exception frame */
|
||||
n = self->count;
|
||||
while (f && n) {
|
||||
fp = f;
|
||||
f= f->next;
|
||||
n--;
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
/* Now work backwards */
|
||||
f = fp;
|
||||
while (f) {
|
||||
strcat(message, f->debug_str);
|
||||
if (f->debug_srcstr) srcstr = f->debug_srcstr;
|
||||
if (f == self->frame) break;
|
||||
f = f->prev;
|
||||
}
|
||||
if (srcstr) {
|
||||
strcat(message,"\n");
|
||||
strcat(message, srcstr);
|
||||
strcat(message,"\n");
|
||||
}
|
||||
}
|
||||
return PyString_FromString(message);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
wadobject_str(wadobject *self) {
|
||||
char *srcstr = 0;
|
||||
int n;
|
||||
|
||||
WadFrame *f = self->frame;
|
||||
n = self->count;
|
||||
strcpy(message,"[ C stack trace ]\n\n");
|
||||
/* Find the last exception frame */
|
||||
while (!f->last && n) {
|
||||
f= f->next;
|
||||
n--;
|
||||
}
|
||||
/* Now work backwards */
|
||||
if (n <= 0) {
|
||||
f = f->prev;
|
||||
}
|
||||
while (f) {
|
||||
strcat(message, f->debug_str);
|
||||
if (f->debug_srcstr) srcstr = f->debug_srcstr;
|
||||
if (self->frame == f) break;
|
||||
f = f->prev;
|
||||
}
|
||||
if (srcstr) {
|
||||
strcat(message,"\n");
|
||||
strcat(message, srcstr);
|
||||
strcat(message,"\n");
|
||||
}
|
||||
return PyString_FromString(message);
|
||||
}
|
||||
|
||||
static int
|
||||
wadobject_len(wadobject *self) {
|
||||
int n = 0;
|
||||
WadFrame *f = self->frame;
|
||||
while (f) {
|
||||
n++;
|
||||
f = f->next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
wadobject_getitem(wadobject *self, int n) {
|
||||
int i;
|
||||
WadFrame *f;
|
||||
if (n < 0) {
|
||||
n = self->count + n;
|
||||
}
|
||||
if ((n < 0) || (n >= self->count)) {
|
||||
PyErr_SetString(PyExc_IndexError,"Stack frame out of range");
|
||||
return NULL;
|
||||
}
|
||||
f = self->frame;
|
||||
for (i = 0; i <n; i++) {
|
||||
f = f->next;
|
||||
}
|
||||
return new_wadobject(f,1);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
wadobject_getslice(wadobject *self, int start, int end) {
|
||||
int i;
|
||||
WadFrame *f;
|
||||
|
||||
f = self->frame;
|
||||
for (i = 0; i < start; i++) {
|
||||
f = f->next;
|
||||
}
|
||||
return new_wadobject(f,(end-start));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
wadobject_getattr(wadobject *self, char *name) {
|
||||
if (strcmp(name,"__NAME__") == 0) {
|
||||
return Py_BuildValue("z", self->frame->sym_name);
|
||||
} else if (strcmp(name,"__EXE__") == 0) {
|
||||
return Py_BuildValue("z", self->frame->object->path);
|
||||
} else if (strcmp(name,"__FILE__") == 0) {
|
||||
return Py_BuildValue("z", self->frame->loc_srcfile);
|
||||
} else if (strcmp(name,"__OBJECT__") == 0) {
|
||||
return Py_BuildValue("z", self->frame->loc_objfile);
|
||||
} else if (strcmp(name,"__LINE__") == 0) {
|
||||
return Py_BuildValue("i", self->frame->loc_line);
|
||||
} else if (strcmp(name,"__SOURCE__") == 0) {
|
||||
return Py_BuildValue("z",self->frame->debug_srcstr);
|
||||
} else if (strcmp(name,"__PC__") == 0) {
|
||||
return PyLong_FromUnsignedLong(self->frame->pc);
|
||||
} else if (strcmp(name,"__SP__") == 0) {
|
||||
return PyLong_FromUnsignedLong(self->frame->sp);
|
||||
} else if (strcmp(name,"__FP__") == 0) {
|
||||
return PyLong_FromUnsignedLong(self->frame->fp);
|
||||
} else if (strcmp(name,"__STACK__") == 0) {
|
||||
return PyString_FromStringAndSize(self->frame->stack, self->frame->stack_size);
|
||||
} else if (strcmp(name,"__NARGS__") == 0) {
|
||||
return PyInt_FromLong(self->frame->debug_nargs);
|
||||
} else if (strcmp(name,"__LAST__") == 0) {
|
||||
return PyInt_FromLong(self->frame->last);
|
||||
} else if (strcmp(name,"__WHERE__") == 0) {
|
||||
return Py_BuildValue("z",self->frame->debug_str);
|
||||
} else if (strcmp(name,"__WAD__") == 0) {
|
||||
return PyInt_FromLong(1);
|
||||
}
|
||||
|
||||
|
||||
/* Put a check for local variables */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) {
|
||||
WadLocal *loc;
|
||||
if (i == 0) loc = self->frame->debug_locals;
|
||||
else loc = self->frame->debug_args;
|
||||
while (loc) {
|
||||
if (strcmp(name,loc->name) == 0) {
|
||||
switch(loc->type) {
|
||||
case WAD_TYPE_INT32:
|
||||
case WAD_TYPE_INT16:
|
||||
case WAD_TYPE_INT8:
|
||||
return PyLong_FromLong(wad_local_as_long(loc));
|
||||
break;
|
||||
case WAD_TYPE_UINT8:
|
||||
case WAD_TYPE_UINT16:
|
||||
case WAD_TYPE_UINT32:
|
||||
return PyLong_FromUnsignedLong((unsigned long) wad_local_as_long(loc));
|
||||
break;
|
||||
case WAD_TYPE_CHAR:
|
||||
return Py_BuildValue("c", (char) (PyLong_FromLong(wad_local_as_long(loc))));
|
||||
break;
|
||||
case WAD_TYPE_FLOAT:
|
||||
case WAD_TYPE_DOUBLE:
|
||||
return PyFloat_FromDouble(wad_local_as_double(loc));
|
||||
break;
|
||||
default:
|
||||
return PyLong_FromUnsignedLong((unsigned long) wad_local_as_long(loc));
|
||||
}
|
||||
}
|
||||
loc = loc->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_NameError,"Unknown attribute.");
|
||||
return NULL;
|
||||
}
|
||||
static PySequenceMethods wadobject_as_sequence = {
|
||||
(inquiry) wadobject_len,
|
||||
0,
|
||||
0,
|
||||
(intargfunc) wadobject_getitem, /* get item */
|
||||
(intintargfunc) wadobject_getslice, /* get slice */
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static PyTypeObject WadObjectType = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"WadObject",
|
||||
sizeof(wadobject),
|
||||
0,
|
||||
(destructor) wadobject_dealloc,
|
||||
0, /* printfunc */
|
||||
(getattrfunc) wadobject_getattr,
|
||||
(setattrfunc) 0,
|
||||
(cmpfunc) 0,
|
||||
(reprfunc) wadobject_repr,
|
||||
|
||||
0, /* number */
|
||||
&wadobject_as_sequence, /* sequence */
|
||||
0, /* mapping */
|
||||
0, /* hash */
|
||||
0, /* call */
|
||||
(reprfunc) wadobject_str, /* str */
|
||||
};
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wadpyinit.cxx
|
||||
*
|
||||
* C++ automatic initializer for Python module.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
extern "C" void pywadinit();
|
||||
|
||||
/* This hack is used to auto-initialize wad regardless of whether we are
|
||||
used as an imported module or as a link-library for another module */
|
||||
|
||||
class wadinitializer {
|
||||
public:
|
||||
wadinitializer() {
|
||||
pywadinit();
|
||||
}
|
||||
};
|
||||
|
||||
static wadinitializer wi;
|
||||
|
||||
|
||||
376
Tools/WAD/README
376
Tools/WAD/README
|
|
@ -1,376 +0,0 @@
|
|||
WAD (Wrapped Application Debugger)
|
||||
|
||||
Author(s):
|
||||
David M. Beazley (beazley@cs.uchicago.edu)
|
||||
|
||||
Copyright (C) 2001
|
||||
University of Chicago
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
See the file COPYING for a complete copy of the LGPL.
|
||||
|
||||
$Id$
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!!!!!!! DISCLAIMER !!!!!!!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
THIS IS EXPERIMENTAL UNMAINTAINED RESEARCH SOFTWARE THAT REPRESENTS
|
||||
WORK IN PROGRESS. IT IS NOT PORTABLE, IT HAS NOT BEEN EXHAUSTIVELY
|
||||
TESTED, AND IT MIGHT NOT WORK AT ALL. PLEASE KEEP AWAY FROM SMALL
|
||||
CHILDREN, PETS, NUCLEAR REACTORS, AIR-TRAFFIC CONTROL, AND VOTING
|
||||
MACHINES.
|
||||
|
||||
0. Supported Platforms
|
||||
|
||||
This software is currently only known to work with 32-bit applications
|
||||
on Sun Sparc Solaris 2.8 and recent i386-Linux systems. In addition,
|
||||
there are numerous issues concerning the interaction of this software
|
||||
with signal handling, thread libraries, and compilers. Please read
|
||||
this entire document before proceeding.
|
||||
|
||||
1. Introduction
|
||||
|
||||
WAD is an embedded error-recovery mechanism that attempts to convert
|
||||
fatal errors such as SIGSEGV, SIGBUS, and SIGFPE into sensible error
|
||||
messages and exceptions. It is primarily designed to support
|
||||
scripting language extension programming although it can also be used
|
||||
with stand-alone C programs.
|
||||
|
||||
The primary goal of this system is to explore an alternative approach
|
||||
to mixed scripting-compiled debugging. It requires no modifications
|
||||
or recompilation of existing software. Therefore, it should be
|
||||
relatively easy to try out. Feedback is welcome. Contributions and
|
||||
modifications are even more welcome.
|
||||
|
||||
2. Compilation and Installation
|
||||
|
||||
WAD is not particularly portable and at this time, only two platforms
|
||||
are supported: Sun Sparc Solaris and i386-Linux.
|
||||
|
||||
Installation is as follows:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
The build process creates the following shared libraries:
|
||||
|
||||
libwad.so - Standalone WAD. Can be linked with C/C++
|
||||
programs.
|
||||
|
||||
libwadpy.so - Python WAD. Can be linked to Python extension
|
||||
modules or imported on its own as 'import libwadpy'
|
||||
|
||||
libwadtcl.so - Tcl WAD. Can be linked to Tcl extension
|
||||
modules or loaded as 'load libwadtcl.so'.
|
||||
|
||||
libwadpl.so - Perl WAD. Can be linked to Perl extension
|
||||
modules or loaded as 'libwadpl'.
|
||||
|
||||
To install the libraries, simply type 'make install'. This copies the libraries
|
||||
to /usr/local/lib (unless you modify the makefile).
|
||||
|
||||
Notes:
|
||||
|
||||
- The Sun version of WAD has only been tested when compiled with the
|
||||
Sun Workshop C/C++ compilers. However WAD works with other programs
|
||||
that have been compiled with gcc. If gcc is installed on your
|
||||
machine, you may want to set the following environment variables
|
||||
before running configure:
|
||||
|
||||
setenv CC cc
|
||||
setenv CXX CC
|
||||
./configure
|
||||
|
||||
- You may need to modify the Makefile to point to the installed locations
|
||||
of various scripting language libraries if you have installed
|
||||
them in non-traditional locations.
|
||||
|
||||
- The Linux version has only been tested with 2.2-12 and 2.2-14 kernels
|
||||
and the RedHat 6.x distribution. Your mileage may vary. There
|
||||
may be some compatibility issues related to glibc and other parts
|
||||
of the system as well.
|
||||
|
||||
3. Using WAD
|
||||
|
||||
WAD has no functional API nor does it have any command line options so
|
||||
it's pretty easy to describe---simply link the appropriate WAD library with
|
||||
your C code. For example:
|
||||
|
||||
% cc blah.c -lwad
|
||||
|
||||
Once linked, fatal errors will now produce stack traces. For example:
|
||||
|
||||
% ./a.out seg
|
||||
starting.
|
||||
Segmentation fault.
|
||||
#2 0x400571eb in __libc_start_main() in 'libc-start.c', line 90
|
||||
#1 0x08048b39 in main(argc=0x2,argv=0xbffffce4) in 'debug.c', line 62
|
||||
#0 0x080489b3 in seg_crash(n=0x0) in 'debug.c', line 9
|
||||
|
||||
/r0/beazley/Projects/WAD/Wad/debug.c, line 9
|
||||
|
||||
int *a = 0;
|
||||
if (n > 0) seg_crash(n-1);
|
||||
=> *a = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
For scripting languages, WAD works in a similar manner--simply link
|
||||
your scripting language extension module with the appropriate WAD library
|
||||
(wadpy, wadtcl, wadpl). For example:
|
||||
|
||||
% ld -G $(OBJS) -lwadpy -o pymodule.so
|
||||
|
||||
When the scripting module is loaded into the interpreter, WAD should
|
||||
automatically initialize.
|
||||
|
||||
4. Debugging Modes
|
||||
|
||||
Due to WAD's experimental nature, a number of debugging modes can be set
|
||||
through the use of environment variables. These variables control WAD's
|
||||
runtime behavior and cause the system to dump debugging information for
|
||||
various stages of error recovery. A lot of this data is pretty ugly and
|
||||
probably only of interest to you if you are trying to debug WAD itself.
|
||||
|
||||
WAD_DEBUG_SEGMENT - Displays information about the virtual memory
|
||||
map and mapping of addresses to segments.
|
||||
|
||||
WAD_DEBUG_SYMBOL - Symbol table mapping.
|
||||
|
||||
WAD_DEBUG_OBJECT - Loading/Unloading of object files.
|
||||
|
||||
WAD_DEBUG_FILE - Loading/Unloading of raw files.
|
||||
|
||||
WAD_DEBUG_HOLD - Freezes WAD before it returns from the signal handler.
|
||||
Useful if you need to attach a debugger to WAD itself.
|
||||
|
||||
WAD_DEBUG_STABS - Display stabs data.
|
||||
|
||||
WAD_DEBUG_RETURN - Display information about WAD return points.
|
||||
|
||||
WAD_DEBUG_SYMBOL_SEARCH - Display all symbols in the symbol table that are
|
||||
searched.
|
||||
|
||||
WAD_DEBUG_UNWIND - Display information about stack unwinding.
|
||||
|
||||
WAD_DEBUG_SIGNAL - Display information about signal handling.
|
||||
|
||||
WAD_DEBUG_INIT - Print initialization information.
|
||||
|
||||
WAD_NOSTACK - Do NOT use an alternative signal handling stack.
|
||||
This may be necessary on certain Linux systems when
|
||||
threads are being used.
|
||||
|
||||
WAD_ONESHOT - Disable WAD signal handler after first signal has
|
||||
been received.
|
||||
|
||||
WAD_DEBUG_MEMORY - Print information about WAD memory use.
|
||||
|
||||
WAD_DEBUG_STRINGS - Print information about WAD string manager.
|
||||
|
||||
5. Platform Specific Issues
|
||||
|
||||
General:
|
||||
|
||||
- WAD does not gracefully recover from errors that corrupt the call
|
||||
stack (i.e., buffer overlow).
|
||||
|
||||
- Errors that destroy the process heap may or may not be recoverable
|
||||
depending on what has been destroyed.
|
||||
|
||||
- WAD does not currently support 64 bit applications on any platform.
|
||||
|
||||
- If executables have been stripped, their symbol tables might not
|
||||
have enough information to recover from errors. Therefore, if you
|
||||
are using Python, Tcl, or Perl from a binary distribution, you
|
||||
may want to rebuild non-stripped versions of these packages yourself.
|
||||
|
||||
- WAD only works with programs that utilize the ELF32 linking format
|
||||
and stabs debugging data. Newer formats such as DWARF2 are not
|
||||
supported at this time.
|
||||
|
||||
- WAD does not correctly report argument values for structures or
|
||||
floating point numbers yet.
|
||||
|
||||
- Overly aggressive compiler optimization may lead to very strange
|
||||
WAD output.
|
||||
|
||||
Solaris:
|
||||
|
||||
- WAD is extremely slow at collecting debugging information
|
||||
from large applications.
|
||||
|
||||
Linux:
|
||||
|
||||
- The interaction of threads and signals are particularly problematic
|
||||
on this platform and may cause WAD not to work at all. Here are
|
||||
some specific thread-based issues that may arise:
|
||||
|
||||
1. WAD causes the program to crash immediately upon startup.
|
||||
This appears to be caused by a bug in in the implementation
|
||||
of sigaction() and the initialization of signals. This
|
||||
only occurs if WAD is directly linked to an executable
|
||||
using threads. It does not occur when WAD is dynamically
|
||||
loaded into a threaded application.
|
||||
|
||||
2. Programs may lock up when an error occurs. This is sometimes
|
||||
caused by an apparently broken implementation of sigaltstack().
|
||||
One solution to this is to set the following environment
|
||||
variable:
|
||||
|
||||
setenv WAD_NOSTACK
|
||||
|
||||
in which case the WAD signal handler will use the same
|
||||
stack as the thread/process that generates the error.
|
||||
|
||||
3. WAD just crashes altogether and doesn't seem to do anything.
|
||||
It appears that some versions of Linux threads do *not*
|
||||
pass CPU context information correctly to signal handlers
|
||||
defined in threaded programs. There is no known fix to
|
||||
this at this time. Upgrade your system.
|
||||
|
||||
- WAD does not work if it is compiled as PIC code. The WAD libraries
|
||||
should be compiled *without* the -fpic option.
|
||||
|
||||
- WAD has to rely upon a heuristic register recovery scheme when it
|
||||
returns to scripting language interpreters. It seems to
|
||||
work, but it relies upon a very specific compiler code generation
|
||||
convention for saving registers in function prologues. It also
|
||||
relies upon the register save conventions described in the Linux
|
||||
Assembly HOWTO.
|
||||
|
||||
- If you are using WAD with pre-installed binaries for Python, Tcl,
|
||||
and other scripting languages, it may not work correctly due to
|
||||
stripped symbol tables. Most Linux installs such as Redhat strip
|
||||
symbol tables from executables. This makes it difficult for WAD
|
||||
to determine context correctly (although it may still work since
|
||||
the dynamic loading symbol table is still available in most cases).
|
||||
|
||||
6. Language specific issues
|
||||
|
||||
If WAD is linked with a normal C/C++ program, errors simply produce a stack trace
|
||||
that is printed on standard error.
|
||||
|
||||
Python:
|
||||
|
||||
WAD tries to raise a Python exception and return. At this time, the exception
|
||||
merely contains a traceback string. However, in future versions, it may be
|
||||
possible to access a complete exception object.
|
||||
|
||||
Tcl:
|
||||
|
||||
WAD returns a Tcl and places the stack trace into the Tcl variable $errorInfo.
|
||||
The wish shell uses this to dump error information.
|
||||
|
||||
Perl:
|
||||
|
||||
Perl doesn't seem to have a very well-defined exception handling
|
||||
mechanism. Standard functions tend to just exit. The WAD handler
|
||||
produces a C stack trace and produces a Perl stack trace using some
|
||||
code derived from the sigtrap module.
|
||||
|
||||
Note: 3/23/01 - Perl support is currently broken.
|
||||
|
||||
7. Testing and Examples
|
||||
|
||||
The Test directory contains some very simple code for testing WAD. In the
|
||||
most simple form, compile the stand-along test program 'debug' as follows:
|
||||
|
||||
% cd Test
|
||||
% make
|
||||
|
||||
Now, running it:
|
||||
|
||||
% debug
|
||||
WAD debug program.
|
||||
|
||||
Usage: debug type
|
||||
seg - Fail with an uninitialized pointer.
|
||||
bus - Fail with a bus error.
|
||||
abort - Fail with an assertion error.
|
||||
math - Fail with a math error.
|
||||
heap - Blow the process heap.
|
||||
overflow - Buffer overflow on the stack.
|
||||
|
||||
% debug seg
|
||||
WAD debug program.
|
||||
Segmentation fault.
|
||||
#2 0x400581eb in __libc_start_main() in 'libc-start.c', line 90
|
||||
#1 0x08048b61 in main(argc=0x2,argv=0xbffffc54) in 'debug.c', line 85
|
||||
#0 0x080489d0 in seg_crash() in 'debug.c', line 15
|
||||
|
||||
/r0/beazley/Projects/WAD/Test/debug.c, line 15
|
||||
|
||||
int seg_crash() {
|
||||
int *a = 0;
|
||||
=> *a = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Additional targets 'make python', 'make tcl', and 'make perl' are also available.
|
||||
The scripts debug.py, debug.tcl, debug.pl can be used to test these extensions.
|
||||
|
||||
8. Documentation
|
||||
|
||||
No official documentation exists at this time. However, details
|
||||
of WAD's design and implementation can be found in papers presented
|
||||
at the Ninth International Python Conference and the 2000 USENIX
|
||||
Technical Conference. Both papers can be obtained at:
|
||||
|
||||
http://systems.cs.uchicago.edu/wad
|
||||
|
||||
|
||||
9. To-Do
|
||||
|
||||
If you find WAD to be interesting or useful, there are a variety of
|
||||
ways to contribute. Here is the short to-do list:
|
||||
|
||||
- Better register management. Try to implement in a more portable
|
||||
way. Add some support code for recovering local variables
|
||||
that happen to be stored in registers.
|
||||
|
||||
- Add heuristic for recovering functions called through an
|
||||
-fomit-frame-pointer compiler optimization scheme. This
|
||||
can probably be determined by looking at the function preamble
|
||||
machine code. Then one can back-trace to the calling function
|
||||
and look at it's preamble.
|
||||
|
||||
- Continued clean up and modularization of the core. Many of the
|
||||
internal APIs could be greatly improved.
|
||||
|
||||
- Support for ELF64 linking format.
|
||||
|
||||
- Support for DWARF2 debugging data.
|
||||
|
||||
- Improved support for stack-overflow and heap-corruption. Although WAD
|
||||
probably won't be able to recover, it still might be able to produce some
|
||||
informative diagnostics.
|
||||
|
||||
- Removal of printf() and other high-level library calls which may not
|
||||
operate with a corrupted heap.
|
||||
|
||||
- Better integration with scripting languages.
|
||||
|
||||
- Support for new platforms.
|
||||
|
||||
- Support for new scripting languages.
|
||||
|
||||
Please contact me if you are interested in working on any of these projects.
|
||||
|
||||
Dave Beazley (beazley@cs.uchicago.edu)
|
||||
June 24, 2001
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
#######################################################################
|
||||
# WAD Makefile
|
||||
#
|
||||
# David Beazley
|
||||
# January 1, 2001
|
||||
#######################################################################
|
||||
|
||||
# These are the files that make up the WAD core
|
||||
SRCS = wadtcl.c
|
||||
OBJS = wadtcl.o
|
||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||
WADOPT = @WADOPT@
|
||||
|
||||
# Location of your Tcl installation
|
||||
TCLINCLUDE = @TCLINCLUDE@
|
||||
TCLSRCS = wadtclinit.cxx
|
||||
TCLOBJS = wadtclinit.o
|
||||
|
||||
# C Compiler
|
||||
CC = @CC@
|
||||
CFLAGS = #@CCSHARED@
|
||||
|
||||
# C++ Compiler
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = #@CXXSHARED@
|
||||
|
||||
# Linking options
|
||||
CLINK =
|
||||
CXXLINK = @CXXLINK@
|
||||
|
||||
# Rules for creation of a .o file from .cxx
|
||||
.SUFFIXES: .cxx
|
||||
.cxx.o:
|
||||
$(CXX) $(CXXFLAGS) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(TCLINCLUDE) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
tcl: $(OBJS) $(TCLOBJS)
|
||||
$(CXXLINK) $(OBJS) $(TCLOBJS) -o libwadtcl.so -L.. -lwadcore
|
||||
cp libwadtcl.so ..
|
||||
|
||||
wc::
|
||||
wc $(SRCS)
|
||||
|
||||
semi::
|
||||
@egrep ";" $(SRCS) $(TCLSRCS) | wc
|
||||
|
||||
clean::
|
||||
rm -f *.o *.so *~
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wadtcl.c
|
||||
*
|
||||
* Dynamically loadable Tcl module for wad.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include <tcl.h>
|
||||
#include "wad.h"
|
||||
#include <signal.h>
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Handler function */
|
||||
static void handler(int signo, WadFrame *frame, char *ret) {
|
||||
static char message[65536];
|
||||
static char temp[1024];
|
||||
int len = 0;
|
||||
char *name;
|
||||
WadFrame *f;
|
||||
WadFrame *fline = 0;
|
||||
char *srcstr= 0;
|
||||
Tcl_Interp *interp;
|
||||
int err;
|
||||
char *type;
|
||||
|
||||
if (!ret) {
|
||||
wad_default_callback(signo, frame, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(message,"[ C stack trace ]\n\n");
|
||||
switch(signo) {
|
||||
case SIGSEGV:
|
||||
type = (char*)"Segmentation fault.";
|
||||
break;
|
||||
case SIGBUS:
|
||||
type = (char*)"Bus error.";
|
||||
break;
|
||||
case SIGABRT:
|
||||
type = (char*)"Abort.";
|
||||
break;
|
||||
case SIGFPE:
|
||||
type = (char*)"Floating point exception.";
|
||||
break;
|
||||
default:
|
||||
type = (char*)"Unknown.";
|
||||
break;
|
||||
}
|
||||
|
||||
f = frame;
|
||||
/* Find the last exception frame */
|
||||
while (!f->last) {
|
||||
f= f->next;
|
||||
}
|
||||
/* Now work backwards */
|
||||
f = f->prev;
|
||||
while (f) {
|
||||
strcat(message, f->debug_str);
|
||||
if (f->debug_srcstr) srcstr = f->debug_srcstr;
|
||||
f = f->prev;
|
||||
}
|
||||
if (srcstr) {
|
||||
strcat(message,"\n");
|
||||
strcat(message, srcstr);
|
||||
strcat(message,"\n");
|
||||
}
|
||||
|
||||
if (wad_heap_overflow) {
|
||||
write(2, "WAD: Heap overflow detected.\n", 30);
|
||||
wad_default_callback(signo, frame, ret);
|
||||
}
|
||||
|
||||
/* Note: if the heap is blown, there is a very good chance that this
|
||||
function will not succeed and we'll dump core. However, the check
|
||||
above should dump a stack trace to stderr just in case we don't make it
|
||||
back. */
|
||||
|
||||
/* Try to get the Tcl interpreter through magic */
|
||||
if (ret) {
|
||||
interp = (Tcl_Interp *) wad_steal_outarg(frame,ret,1,&err);
|
||||
if (err == 0) {
|
||||
Tcl_SetResult(interp,type,TCL_STATIC);
|
||||
Tcl_AddErrorInfo(interp,message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tclwadinit() {
|
||||
printf("WAD Enabled\n");
|
||||
wad_init();
|
||||
wad_set_callback(handler);
|
||||
wad_set_return("TclExecuteByteCode", TCL_ERROR);
|
||||
wad_set_return("EvalObjv", TCL_ERROR);
|
||||
}
|
||||
|
||||
int Wad_Init(Tcl_Interp *interp) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int Wadtcl_Init(Tcl_Interp *interp) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wadtclinit.cxx
|
||||
*
|
||||
* C++ initializer for Tcl wad.
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
extern "C" void tclwadinit();
|
||||
|
||||
/* This hack is used to auto-initialize wad regardless of whether we are
|
||||
used as an imported module or as a link-library for another module */
|
||||
|
||||
class wadinitializer {
|
||||
public:
|
||||
wadinitializer() {
|
||||
tclwadinit();
|
||||
}
|
||||
};
|
||||
|
||||
static wadinitializer wi;
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#######################################################################
|
||||
# WAD Test makefile
|
||||
#
|
||||
# Build some WAD test programs.
|
||||
#######################################################################
|
||||
|
||||
CC= @CC@
|
||||
CCSHARED = @CCSHARED@
|
||||
LDSHARED = @LDSHARED@
|
||||
RPATH = @RPATH@
|
||||
|
||||
PYINCLUDE = @PYINCLUDE@
|
||||
TCLINCLUDE = @TCLINCLUDE@
|
||||
PERLINCLUDE = @PERL5EXT@
|
||||
INCLUDE = -I../Include
|
||||
WADLIB = ..
|
||||
WADLINK = -L$(WADLIB) $(RPATH)$(WADLIB)
|
||||
|
||||
test:
|
||||
$(CC) -g -DNEED_MAIN debug.c $(INCLUDE) $(WADLINK) -lwad -o debug
|
||||
|
||||
python: pydebug.c
|
||||
$(CC) $(CCSHARED) -c -g debug.c pydebug.c $(PYINCLUDE)
|
||||
$(LDSHARED) debug.o pydebug.o $(WADLINK) -lwadpy -o debugmodule.so
|
||||
|
||||
tcl: tcldebug.c
|
||||
$(CC) $(CCSHARED) -c -g debug.c tcldebug.c $(TCLINCLUDE)
|
||||
$(LDSHARED) debug.o tcldebug.o $(WADLINK) -lwadtcl -o debug.so
|
||||
|
||||
perl: pldebug.c
|
||||
$(CC) $(CCSHARED) -c -Dbool=char -g debug.c pldebug.c $(PERLINCLUDE)
|
||||
$(LDSHARED) debug.o pldebug.o $(WADLINK) -lwadpl -o debug.so
|
||||
|
||||
pydebug.c:
|
||||
swig -python -o pydebug.c debug.i
|
||||
|
||||
tcldebug.c:
|
||||
swig -tcl -o tcldebug.c debug.i
|
||||
|
||||
pldebug.c:
|
||||
swig -perl5 -o pldebug.c debug.i
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o debug *_wrap*
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
Simple test programs for WAD. This is currently incomplete.
|
||||
|
||||
Note: To completely rebuild the Python, Perl, and Tcl tests,
|
||||
you need to have SWIG installed (www.swig.org).
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import debug
|
||||
from Tkinter import *
|
||||
|
||||
def death_by_segmentation():
|
||||
debug.seg_crash()
|
||||
|
||||
def death_by_bus():
|
||||
debug.bus_crash()
|
||||
|
||||
def death_by_abort():
|
||||
debug.abort_crash(-1)
|
||||
|
||||
def death_by_math():
|
||||
debug.math_crash(37,0)
|
||||
|
||||
def death_by_buffer():
|
||||
debug.overflow_crash()
|
||||
|
||||
def death(f):
|
||||
ty = f.tvar.get()
|
||||
if ty == 1:
|
||||
death_by_segmentation()
|
||||
elif ty == 2:
|
||||
death_by_abort()
|
||||
elif ty == 3:
|
||||
death_by_math()
|
||||
elif ty == 4:
|
||||
death_by_bus()
|
||||
elif ty == 5:
|
||||
death_by_buffer()
|
||||
|
||||
class death_options(Frame):
|
||||
def __init__(self):
|
||||
Frame.__init__(self)
|
||||
tvar = IntVar()
|
||||
Radiobutton(self,text="Segmentation fault", variable=tvar, value=1).pack(anchor=W)
|
||||
Radiobutton(self,text="Failed assertion", variable=tvar, value=2).pack(anchor=W)
|
||||
Radiobutton(self,text="Math error", variable=tvar, value=3).pack(anchor=W)
|
||||
Radiobutton(self,text="Bus error", variable=tvar, value=4).pack(anchor=W)
|
||||
Radiobutton(self,text="Stack overflow", variable=tvar, value=5).pack(anchor=W)
|
||||
Button(self,text="Die", command=lambda x=self: death(x)).pack(expand=1, fill=BOTH)
|
||||
self.tvar = tvar
|
||||
tvar.set(1)
|
||||
|
||||
def death_wizard():
|
||||
root = Tk()
|
||||
l = Label(text="How would you like to die today?")
|
||||
l.pack()
|
||||
death_options().pack()
|
||||
root.title("Death Wizard")
|
||||
death_wizard()
|
||||
|
||||
#root.mainloop()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
load ./debug[info sharedlibextension]
|
||||
|
||||
proc death_by_segmentation { } {
|
||||
seg_crash
|
||||
}
|
||||
|
||||
proc death_by_bus { } {
|
||||
bus_crash
|
||||
}
|
||||
|
||||
proc death_by_abort { } {
|
||||
abort_crash -1
|
||||
}
|
||||
|
||||
proc death_by_math { } {
|
||||
math_crash 37 0
|
||||
}
|
||||
|
||||
proc death_by_buffer { } {
|
||||
overflow_crash
|
||||
}
|
||||
|
||||
set method 1
|
||||
proc death {} {
|
||||
global method
|
||||
if { $method == 1 } {
|
||||
death_by_segmentation
|
||||
}
|
||||
if { $method == 2 } {
|
||||
death_by_abort
|
||||
}
|
||||
if { $method == 3 } {
|
||||
death_by_math
|
||||
}
|
||||
if { $method == 4 } {
|
||||
death_by_bus
|
||||
}
|
||||
if { $method == 5 } {
|
||||
death_by_buffer
|
||||
}
|
||||
}
|
||||
|
||||
label .l -text "How would you like to die today?"
|
||||
pack .l
|
||||
|
||||
radiobutton .r1 -text "Segmentation fault" -variable method -value 1
|
||||
pack .r1 -anchor w
|
||||
|
||||
radiobutton .r2 -text "Failed assertion" -variable method -value 2
|
||||
pack .r2 -anchor w
|
||||
|
||||
radiobutton .r3 -text "Math error" -variable method -value 3
|
||||
pack .r3 -anchor w
|
||||
|
||||
radiobutton .r4 -text "Bus error" -variable method -value 4
|
||||
pack .r4 -anchor w
|
||||
|
||||
radiobutton .r5 -text "Stack overflow" -variable method -value 5
|
||||
pack .r5 -anchor w
|
||||
|
||||
button .b -text "Die" -command death
|
||||
pack .b -fill both -expand 1
|
||||
|
||||
wm title . "Death Wizard"
|
||||
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* debug.c
|
||||
*
|
||||
* This file contains a variety of different programming errors to test with
|
||||
* WAD.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef double Real;
|
||||
typedef Real Float;
|
||||
|
||||
char buffer[256];
|
||||
|
||||
/* A simple segmentation fault on an uninitialized pointer */
|
||||
int seg_crash() {
|
||||
int *a = 0;
|
||||
*a = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Blow the process heap */
|
||||
|
||||
int blowheap_crash() {
|
||||
int i;
|
||||
int *a = (int *) malloc(sizeof(int));
|
||||
|
||||
for (i = 0;; i++) {
|
||||
a[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buffer overflow crash on the stack */
|
||||
int overflow_crash() {
|
||||
int a[512];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
a[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* A simple bus error. */
|
||||
int bus_crash() {
|
||||
double *a = (double *) (buffer+1);
|
||||
*a = 3.4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* An assertion */
|
||||
int abort_crash(int n) {
|
||||
assert(n > 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A math error (maybe) */
|
||||
int math_crash(int x, int y) {
|
||||
return x/y;
|
||||
}
|
||||
|
||||
void type_crash(int a, short b, char c, unsigned long d, float f, double g) {
|
||||
int la;
|
||||
short lb;
|
||||
char lc;
|
||||
long ld;
|
||||
float lf;
|
||||
double lg;
|
||||
long ll;
|
||||
|
||||
la = a;
|
||||
lb = b;
|
||||
lc = c;
|
||||
ld = ld;
|
||||
lf = lf;
|
||||
lg = lg;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#ifdef NEED_MAIN
|
||||
|
||||
static const char *usage="\n\
|
||||
Usage: debug type\n\
|
||||
seg - Fail with an uninitialized pointer.\n\
|
||||
bus - Fail with a bus error.\n\
|
||||
abort - Fail with an assertion error.\n\
|
||||
math - Fail with a math error.\n\
|
||||
heap - Blow the process heap.\n\
|
||||
overflow - Buffer overflow on the stack.\n\
|
||||
";
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int n;
|
||||
|
||||
printf("WAD debug program.\n");
|
||||
|
||||
if (argc < 2) {
|
||||
printf("%s\n", usage);
|
||||
exit(0);
|
||||
}
|
||||
if (strcmp(argv[1],"abort") == 0) {
|
||||
abort_crash(-4);
|
||||
} else if (strcmp(argv[1],"seg") ==0) {
|
||||
seg_crash();
|
||||
} else if (strcmp(argv[1],"bus") == 0) {
|
||||
bus_crash();
|
||||
} else if (strcmp(argv[1],"math") == 0) {
|
||||
math_crash(3,0);
|
||||
} else if (strcmp(argv[1],"heap") == 0) {
|
||||
blowheap_crash();
|
||||
} else if (strcmp(argv[1],"overflow") == 0) {
|
||||
overflow_crash();
|
||||
} else if (strcmp(argv[1],"type") == 0) {
|
||||
type_crash(0,2,'x',420000,3.14159,2.1828);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
%module debug
|
||||
|
||||
extern int seg_crash();
|
||||
extern int bus_crash();
|
||||
extern int blowheap_crash();
|
||||
extern int overflow_crash();
|
||||
extern int abort_crash(int);
|
||||
extern int math_crash(int x, int y);
|
||||
extern void type_crash(int, short, char, unsigned long, float, double);
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# WAD debugging module for python
|
||||
|
||||
import debug
|
||||
import sys
|
||||
|
||||
try:
|
||||
name = sys.argv[1]
|
||||
except:
|
||||
print """
|
||||
usage: debug.py test
|
||||
|
||||
seg - Segmentation fault due to uninitialized pointer.
|
||||
bus - Bus error.
|
||||
abort - Failed assertion.
|
||||
math - Math error.
|
||||
heap - Blown heap.
|
||||
overflow - Buffer overflow.
|
||||
"""
|
||||
sys.exit(1)
|
||||
|
||||
if name == "seg":
|
||||
debug.seg_crash()
|
||||
elif name == "bus":
|
||||
debug.bus_crash()
|
||||
elif name == "abort":
|
||||
debug.abort_crash(-2)
|
||||
elif name == "math":
|
||||
debug.math_crash(3,0)
|
||||
elif name == "heap":
|
||||
debug.blowheap_crash()
|
||||
elif name == "overflow":
|
||||
debug.overflow_crash()
|
||||
elif name == "type":
|
||||
debug.type_crash(37,42, 'x', 420000, 3.14159, 2.1828)
|
||||
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# WAD debugging module for Tcl. This should be executed with wish
|
||||
|
||||
load ./debug[info sharedlibextension]
|
||||
|
||||
message .t -text "This program tests various program faults. Note: Not all of these errors can be gracefully handled."
|
||||
|
||||
button .b1 -text "Segmentation fault" -command "seg_crash"
|
||||
button .b2 -text "Bus error (not on Linux)" -command "bus_crash"
|
||||
button .b3 -text "Abort" -command "abort_crash -1"
|
||||
button .b4 -text "Math" -command "math_crash 3 0"
|
||||
button .b5 -text "Blow Heap" -command "blowheap_crash"
|
||||
button .b6 -text "Buffer overflow" -command "overflow_crash"
|
||||
button .q -text "Quit" -command "exit"
|
||||
|
||||
pack .t -fill x
|
||||
|
||||
pack .b1 -fill x
|
||||
pack .b2 -fill x
|
||||
pack .b3 -fill x
|
||||
pack .b4 -fill x
|
||||
pack .b5 -fill x
|
||||
pack .b6 -fill x
|
||||
pack .q -fill x
|
||||
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import debug
|
||||
|
||||
def foo():
|
||||
debug.abort_crash(-1)
|
||||
|
||||
def bar():
|
||||
foo()
|
||||
|
||||
def spam():
|
||||
bar()
|
||||
|
||||
from Tkinter import *
|
||||
|
||||
root = Tk()
|
||||
|
||||
button = Button(text="Press me", command=spam)
|
||||
button.pack()
|
||||
|
||||
#root.mainloop()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# Wad port-mortem debugger
|
||||
#
|
||||
# David Beazley
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
|
||||
_last_exc = None
|
||||
_last_level = 0
|
||||
|
||||
print "WAD port-mortem"
|
||||
|
||||
class where_impl:
|
||||
def __repr__(self):
|
||||
global _last_exc, _last_level
|
||||
if sys.last_value:
|
||||
if sys.last_value[0] != _last_exc:
|
||||
_last_exc = sys.last_value[0]
|
||||
_last_level = 0
|
||||
else:
|
||||
raise RuntimeError,"No pending error."
|
||||
print repr(_last_exc)
|
||||
return ""
|
||||
|
||||
where = where_impl()
|
||||
|
||||
class up_impl:
|
||||
def __repr__(self):
|
||||
global _last_exc, _last_level
|
||||
if not _last_exc:
|
||||
return ""
|
||||
_last_level += 1
|
||||
print repr(_last_exc[_last_level])
|
||||
return ""
|
||||
|
||||
up = up_impl()
|
||||
|
||||
class down_impl:
|
||||
def __repr__(self):
|
||||
global _last_exc, _last_level
|
||||
if not _last_exc:
|
||||
return ""
|
||||
_last_level -= 1
|
||||
print repr(_last_exc[_last_level])
|
||||
return ""
|
||||
|
||||
down = down_impl()
|
||||
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# WAD Post-mortem debugger
|
||||
#
|
||||
# This program can be used to walk up and down the call stack of a mixed
|
||||
# Python-C program. The following commands are supported:
|
||||
#
|
||||
# w - A stack traceback
|
||||
# u - Go up the call stack
|
||||
# d - Go down the call stack
|
||||
# e - Edit a file
|
||||
# c - Clear the debugger.
|
||||
#
|
||||
# David Beazley
|
||||
# Copyright (C) 2001
|
||||
# University of Chicago
|
||||
# All Rights Reserved
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import os
|
||||
import traceback
|
||||
import types
|
||||
import linecache
|
||||
|
||||
|
||||
print "**************************************************"
|
||||
print "* WAD Debugger *"
|
||||
print "**************************************************"
|
||||
|
||||
# Save a local copy of the last exception and value objects from sys
|
||||
|
||||
_last_type = sys.last_type
|
||||
_last_value = sys.last_value
|
||||
_last_traceback = sys.last_traceback
|
||||
_last_level = 0
|
||||
|
||||
_cstack = None # Stack of C-only code
|
||||
_pystack = None # Stack of Python only code
|
||||
_combined_stack = None # Combined C-python stack
|
||||
|
||||
_allmode = 0 # Show entire C stack
|
||||
|
||||
# Generalized object for holding stack frames
|
||||
|
||||
class wad_frame:
|
||||
def __init__(self,frame, n = 0):
|
||||
if isinstance(frame,types.TupleType):
|
||||
# A Python traceback object
|
||||
self.__FILE__ = frame[0]
|
||||
self.__LINE__ = frame[1]
|
||||
self.__NAME__ = frame[2]
|
||||
self.__ARGSTR__ = frame[3]
|
||||
self.__FRAMENO__ = n
|
||||
# Make the debugging string
|
||||
self.__DEBUGSTR__ = "#%-3d [ Python ] in %s in %s, line %d" % (self.__FRAMENO__, self.__ARGSTR__, self.__FILE__, self.__LINE__)
|
||||
|
||||
# Try to get source data
|
||||
self.__SOURCE__ = "%s, Line %d\n\n" % (self.__FILE__, self.__LINE__)
|
||||
for i in range(self.__LINE__-2,self.__LINE__+3):
|
||||
l = linecache.getline(self.__FILE__,i)
|
||||
if not l: l = '\n'
|
||||
if (i == self.__LINE__):
|
||||
self.__SOURCE__ += " => "
|
||||
else:
|
||||
self.__SOURCE__ += " "
|
||||
self.__SOURCE__ += l
|
||||
self.__frame__ = None
|
||||
|
||||
elif hasattr(frame,"__WAD__"):
|
||||
# A WAD traceback object
|
||||
self.__FILE__ = frame.__FILE__
|
||||
self.__LINE__ = frame.__LINE__
|
||||
self.__NAME__ = frame.__NAME__
|
||||
self.__DEBUGSTR__ = frame.__WHERE__
|
||||
self.__SOURCE__ = frame.__SOURCE__
|
||||
self.__frame__ = frame
|
||||
|
||||
def __str__(self):
|
||||
return self.__DEBUGSTR__.strip()
|
||||
|
||||
def __getattr__(self,name):
|
||||
if self.__frame__:
|
||||
return getattr(self.__frame__,name)
|
||||
raise AttributeError
|
||||
|
||||
def output(self):
|
||||
print self
|
||||
if self.__SOURCE__:
|
||||
print "\n%s" % (self.__SOURCE__)
|
||||
|
||||
|
||||
def wad_build_info():
|
||||
global _last_type,_last_value, _last_traceback, _cstack, _combined_stack,_pystack
|
||||
|
||||
_last_type = None
|
||||
_last_value = None
|
||||
_last_traceback = None
|
||||
_cstack = None
|
||||
_combined_stack = []
|
||||
|
||||
# Check to see if any exception is defined
|
||||
if not sys.last_type:
|
||||
print "No exception has occurred."
|
||||
return
|
||||
|
||||
# Save a copy of previous exception
|
||||
_last_type = sys.last_type
|
||||
_last_value = sys.last_value
|
||||
_last_traceback = sys.last_traceback
|
||||
_last_level = 0
|
||||
|
||||
start_frame = 0
|
||||
# Test to see what kind of object it is
|
||||
if issubclass(_last_type,StandardError):
|
||||
# Python exception
|
||||
print "Python exception"
|
||||
elif hasattr(_last_value[0],"__WAD__"):
|
||||
# A wad exception frame object
|
||||
w = sys.last_value[0]
|
||||
i = 0
|
||||
_cstack = []
|
||||
while not w[i].__LAST__:
|
||||
start_frame += 1
|
||||
wf = wad_frame(w[i])
|
||||
_cstack.append(wf)
|
||||
i = i + 1
|
||||
|
||||
# wf = wad_frame(w[i])
|
||||
# _cstack.append(wf)
|
||||
# start_frame += 1
|
||||
|
||||
# Build the rest of the c stack
|
||||
_combined_stack = _cstack[:]
|
||||
while i < len(w):
|
||||
wf = wad_frame(w[i])
|
||||
_cstack.append(wf)
|
||||
i = i + 1
|
||||
|
||||
else:
|
||||
print "Unknown error"
|
||||
|
||||
# Build the Python call stack
|
||||
_pystack = []
|
||||
t = sys.last_traceback
|
||||
tp = None
|
||||
while hasattr(t,"tb_frame"):
|
||||
tp = t
|
||||
t = t.tb_next
|
||||
|
||||
fr = traceback.extract_stack(tp.tb_frame)
|
||||
for i in range(len(fr),0,-1):
|
||||
f = wad_frame(fr[i-1], start_frame)
|
||||
start_frame += 1
|
||||
_pystack.append(f)
|
||||
_combined_stack.extend(_pystack)
|
||||
|
||||
|
||||
wad_build_info()
|
||||
|
||||
class where_impl:
|
||||
def __init__(self):
|
||||
self.all = 0;
|
||||
self.cstack = 0
|
||||
|
||||
def __repr__(self):
|
||||
global _combined_stack, _cstack, _last_level
|
||||
if (self.cstack):
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
|
||||
if not stack:
|
||||
print "No current exception."
|
||||
return ""
|
||||
|
||||
last_source = None
|
||||
for i in range(len(stack),0,-1):
|
||||
f = stack[i-1]
|
||||
print f
|
||||
if (f.__SOURCE__):
|
||||
last_source = f.__SOURCE__
|
||||
_last_level = i-1
|
||||
if last_source: print "\n%s" % last_source
|
||||
return ""
|
||||
|
||||
def __getitem__(self,n):
|
||||
global _last_level, _cstack, _combined_stack
|
||||
if (self.cstack):
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
_last_level = n
|
||||
stack[_last_level].output()
|
||||
return None
|
||||
|
||||
def __len__(self):
|
||||
return len(frame)
|
||||
|
||||
|
||||
where = where_impl()
|
||||
w = where
|
||||
|
||||
class up_impl:
|
||||
def __repr__(self):
|
||||
global _last_level, _combined_stack, _cstack
|
||||
if where.cstack:
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
|
||||
if not stack:
|
||||
return ""
|
||||
_last_level += 1
|
||||
stack[_last_level].output()
|
||||
return ""
|
||||
|
||||
up = up_impl()
|
||||
u = up
|
||||
|
||||
class down_impl:
|
||||
def __repr__(self):
|
||||
global _last_level, _combined_stack, _cstack
|
||||
if where.cstack:
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
|
||||
if not stack:
|
||||
return ""
|
||||
_last_level -= 1
|
||||
stack[_last_level].output()
|
||||
return ""
|
||||
|
||||
down = down_impl()
|
||||
d = down
|
||||
|
||||
class clear_impl:
|
||||
def __repr__(self):
|
||||
global _last_exc, _last_level, frame
|
||||
_last_exc = None
|
||||
frame = None
|
||||
|
||||
clear = clear_impl()
|
||||
c = clear
|
||||
|
||||
class edit_impl:
|
||||
def __repr__(self):
|
||||
global _last_level, _combined_stack, _cstack
|
||||
if where.cstack:
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
|
||||
if not stack:
|
||||
return ""
|
||||
f = stack[_last_level]
|
||||
e = os.getenv("EDITOR","vi")
|
||||
if f.__FILE__:
|
||||
os.system("%s +%d %s" % (e,f.__LINE__,f.__FILE__))
|
||||
return ""
|
||||
|
||||
edit = edit_impl()
|
||||
e = edit
|
||||
|
||||
class var_impl:
|
||||
def __getattr__(self,name):
|
||||
if (w.cstack):
|
||||
stack = _cstack
|
||||
else:
|
||||
stack = _combined_stack
|
||||
|
||||
return getattr(stack[_last_level],name)
|
||||
|
||||
|
||||
v = var_impl()
|
||||
|
||||
|
||||
repr(w)
|
||||
|
||||
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#######################################################################
|
||||
# WAD Makefile
|
||||
#
|
||||
# David Beazley
|
||||
# January 1, 2001
|
||||
#######################################################################
|
||||
|
||||
# These are the files that make up the WAD core
|
||||
WADSRCS = string.c vars.c io.c memory.c return.c default.c stack.c stab.c elf.c object.c init.c segment.c signal.c
|
||||
WADOBJS = string.o vars.o io.o memory.o return.o default.o stack.o stab.o elf.o object.o signal.o segment.o init.o
|
||||
INCLUDE = -I../Include -I. $(SINCLUDE)
|
||||
WADOPT = @WADOPT@
|
||||
|
||||
|
||||
# Location of your Perl installation
|
||||
PERLINCLUDE = @PERL5EXT@
|
||||
PERLSRCS = wadpl.cxx
|
||||
PERLOBJS = wadpl.o
|
||||
|
||||
# C Compiler
|
||||
CC = @CC@
|
||||
CFLAGS = #@CCSHARED@
|
||||
|
||||
# C++ Compiler
|
||||
CXX = @CXX@
|
||||
CXXFLAGS = #@CXXSHARED@
|
||||
|
||||
# Linking options
|
||||
CLINK =
|
||||
CXXLINK = @CXXLINK@
|
||||
|
||||
# AR
|
||||
AR = @AR@
|
||||
|
||||
# Rules for creation of a .o file from .cxx
|
||||
.SUFFIXES: .cxx
|
||||
.cxx.o:
|
||||
$(CXX) $(CXXFLAGS) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(WADOPT) $(INCLUDE) -c -o $*.o $<
|
||||
|
||||
wad: $(WADOBJS) main.o
|
||||
$(CXXLINK) $(WADOBJS) main.o -o libwad.so
|
||||
$(AR) cr libwadcore.a $(WADOBJS)
|
||||
cp libwad.so ..
|
||||
cp libwadcore.a ..
|
||||
|
||||
perl: wad_perl_handler.c $(WADOBJS) $(PERLOBJS)
|
||||
$(CXXLINK) $(WADOBJS) $(PERLOBJS) -o libwadpl.so
|
||||
cp libwadpl.so ..
|
||||
|
||||
wad_perl_handler.c:
|
||||
python makehandler.py
|
||||
|
||||
debug::
|
||||
cc -g debug.c $(INCLUDE) -L. -R. -lwad
|
||||
|
||||
plus::
|
||||
CC -g debug.cxx $(INCLUDE) -L. -R. -lwad
|
||||
|
||||
wc::
|
||||
wc $(SRCS)
|
||||
|
||||
semi::
|
||||
@egrep ";" $(WADSRCS) plat/*.c | wc
|
||||
|
||||
clean::
|
||||
rm -f *.o *.so *~
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "wad.h"
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct Foo {
|
||||
double a;
|
||||
double b;
|
||||
float c;
|
||||
} Foo;
|
||||
|
||||
static int type_crash(int n, short m, char c, double x, float y, Foo f, void *ptr) {
|
||||
int *a = 0;
|
||||
*a = 3;
|
||||
return 1;
|
||||
}
|
||||
static int seg_crash(int n, double x,
|
||||
float y) {
|
||||
int *a = 0;
|
||||
if (n > 0) seg_crash(n-1,x,y);
|
||||
*a = 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bus_crash(int n) {
|
||||
int b;
|
||||
int *a = &b;
|
||||
a = (int *) ((int) a | 0x1);
|
||||
if (n > 0) bus_crash(n-1);
|
||||
*a = 3;
|
||||
printf("well, well, well.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int abort_crash(int n) {
|
||||
assert(n > 0);
|
||||
abort_crash(n-1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
double double_crash(double a, double b) {
|
||||
double *c;
|
||||
*c = a+b;
|
||||
return *c;
|
||||
}
|
||||
|
||||
int math_crash(int x, int y) {
|
||||
return x/y;
|
||||
}
|
||||
|
||||
int call_func(int n, int (*f)(int)) {
|
||||
|
||||
int ret;
|
||||
ret = (*f)(n);
|
||||
if (ret <= 0) {
|
||||
printf("An error occurred!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int multi(char a, short b, int c, double d) {
|
||||
a = 'x';
|
||||
b = 15236;
|
||||
c = 12345678;
|
||||
d = 3.14159;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int test(int x, int (*f)(int)) {
|
||||
return (*f)(-x);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int n;
|
||||
int (*f)(int);
|
||||
Foo foo = { 3.14, 28.18, 1.0 };
|
||||
|
||||
printf("starting.\n");
|
||||
|
||||
if (strcmp(argv[1],"abort") == 0) {
|
||||
abort_crash(0);
|
||||
} else if (strcmp(argv[1],"seg") ==0) {
|
||||
seg_crash(0,1,2);
|
||||
} else if (strcmp(argv[1],"bus") == 0) {
|
||||
bus_crash(0);
|
||||
} else if (strcmp(argv[1],"ret") == 0) {
|
||||
call_func(4,abort_crash);
|
||||
} else if (strcmp(argv[1],"test") == 0) {
|
||||
test(-1000,abort_crash);
|
||||
} else if (strcmp(argv[1],"double") == 0) {
|
||||
double_crash(3.14159,2.1828);
|
||||
} else if (strcmp(argv[1],"math") == 0) {
|
||||
math_crash(3,0);
|
||||
} else if (strcmp(argv[1],"type") == 0) {
|
||||
type_crash(34,42,17, 3.14159, 2.1828, foo, &foo);
|
||||
}
|
||||
multi(3,5,10,3.14);
|
||||
}
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* default.c
|
||||
*
|
||||
* Default signal handler. Just prints a stack trace and returns.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
/* This function tries to produce some kind of sensible argument
|
||||
string for a stack frame. If no debugging information is available,
|
||||
we'll just dump the %i0-%i5 registers in hex. If debugging information
|
||||
is available, we'll try to do something a little more sensible */
|
||||
|
||||
char *wad_arg_string(WadFrame *frame) {
|
||||
static char str[1024];
|
||||
WadLocal *wp;
|
||||
long *stack;
|
||||
long *nextstack;
|
||||
long *prevstack;
|
||||
int i;
|
||||
WadFrame *nf;
|
||||
WadFrame *pf;
|
||||
|
||||
nf = frame->next;
|
||||
if (nf)
|
||||
nextstack = (long *) nf->stack;
|
||||
else
|
||||
nextstack = 0;
|
||||
|
||||
pf = frame->prev;
|
||||
if (pf)
|
||||
prevstack = (long *) pf->stack;
|
||||
else
|
||||
prevstack = 0;
|
||||
|
||||
str[0] = 0;
|
||||
stack = (long *) frame->stack;
|
||||
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
if (!nf) {
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((frame->debug_nargs < 0) || (0)){
|
||||
/* No argument information is available. If we are on SPARC, we'll dump
|
||||
the %in registers since these usually hold input parameters. On
|
||||
Linux, we do nothing */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
for (i = 0; i < 6; i++) {
|
||||
wad_strcat(str,"0x");
|
||||
wad_strcat(str,wad_format_hex((unsigned long) stack[8+i],0));
|
||||
if (i < 5)
|
||||
wad_strcat(str,",");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/* We were able to get some argument information out the debugging table */
|
||||
wp = frame->debug_args;
|
||||
for (i = 0; i < frame->debug_nargs; i++, wp = wp->next) {
|
||||
wad_strcat(str,wp->name);
|
||||
wad_strcat(str,"=");
|
||||
wad_strcat(str,wad_format_var(wp));
|
||||
if (i < (frame->debug_nargs-1)) wad_strcat(str,",");
|
||||
}
|
||||
}
|
||||
return str;
|
||||
|
||||
}
|
||||
|
||||
char *wad_strip_dir(char *name) {
|
||||
char *c;
|
||||
/* printf("strip: '%s'\n", name); */
|
||||
c = name + strlen(name);
|
||||
while (c != name) {
|
||||
if (*c == '/') {
|
||||
c++;
|
||||
return c;
|
||||
}
|
||||
c--;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *src_file = 0;
|
||||
static int src_len = 0;
|
||||
static char src_path[1024] = "";
|
||||
|
||||
/* Opens up a source file and tries to locate a specific line number */
|
||||
|
||||
char *wad_load_source(char *path, int line) {
|
||||
int fd;
|
||||
char *c;
|
||||
char *start;
|
||||
int n;
|
||||
|
||||
if (strcmp(src_path,path)) {
|
||||
if (src_file) {
|
||||
munmap(src_file, src_len);
|
||||
src_file = 0;
|
||||
src_len = 0;
|
||||
}
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) return 0;
|
||||
src_len = lseek(fd, 0, SEEK_END);
|
||||
lseek(fd,0,SEEK_SET);
|
||||
src_file = (char *)mmap(NULL,src_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
if (src_file == MAP_FAILED) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
wad_strcpy(src_path,path);
|
||||
}
|
||||
n = 0;
|
||||
start = src_file;
|
||||
c = src_file;
|
||||
while (n < src_len) {
|
||||
if (*c == '\n') {
|
||||
line--;
|
||||
if (line == 0) {
|
||||
return start;
|
||||
}
|
||||
start = c+1;
|
||||
}
|
||||
c++;
|
||||
n++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wad_release_source() {
|
||||
if (src_file) {
|
||||
munmap(src_file,src_len);
|
||||
src_file = 0;
|
||||
src_len = 0;
|
||||
src_path[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_debug_src_code(WadFrame *f)
|
||||
*
|
||||
* Get source code for a frame
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *wad_debug_src_string(WadFrame *f, int window) {
|
||||
static char temp[16384];
|
||||
|
||||
if (f->loc_srcfile && strlen(f->loc_srcfile) && (f->loc_line > 0)) {
|
||||
char *line, *c;
|
||||
int i;
|
||||
int first, last;
|
||||
first = f->loc_line - window;
|
||||
last = f->loc_line + window;
|
||||
if (first < 1) first = 1;
|
||||
line = wad_load_source(f->loc_srcfile,first);
|
||||
if (line) {
|
||||
wad_strcpy(temp,f->loc_srcfile);
|
||||
wad_strcat(temp,", line ");
|
||||
wad_strcat(temp,wad_format_signed(f->loc_line,-1));
|
||||
wad_strcat(temp,"\n\n");
|
||||
for (i = first; i <= last; i++) {
|
||||
if (i == f->loc_line) wad_strcat(temp," => ");
|
||||
else wad_strcat(temp," ");
|
||||
c = strchr(line,'\n');
|
||||
if (c) {
|
||||
*c = 0;
|
||||
wad_strcat(temp,line);
|
||||
wad_strcat(temp,"\n");
|
||||
*c = '\n';
|
||||
} else {
|
||||
wad_strcat(temp,line);
|
||||
wad_strcat(temp,"\n");
|
||||
break;
|
||||
}
|
||||
line = c+1;
|
||||
}
|
||||
f->debug_srcstr = wad_strdup(temp);
|
||||
return f->debug_srcstr;
|
||||
}
|
||||
}
|
||||
f->debug_srcstr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_debug_make_strings(WadFrame *f)
|
||||
*
|
||||
* This function walks the stack trace and tries to generate a debugging string
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_debug_make_strings(WadFrame *f) {
|
||||
static char msg[16384];
|
||||
while (f) {
|
||||
wad_strcpy(msg,"#");
|
||||
wad_strcat(msg,wad_format_signed(f->frameno,3));
|
||||
wad_strcat(msg," 0x");
|
||||
wad_strcat(msg,wad_format_hex(f->pc,1));
|
||||
wad_strcat(msg," in ");
|
||||
wad_strcat(msg, f->sym_name ? f->sym_name : "?");
|
||||
wad_strcat(msg,"(");
|
||||
wad_strcat(msg,wad_arg_string(f));
|
||||
wad_strcat(msg,")");
|
||||
if (f->loc_srcfile && strlen(f->loc_srcfile)) {
|
||||
wad_strcat(msg," in '");
|
||||
wad_strcat(msg, wad_strip_dir(f->loc_srcfile));
|
||||
wad_strcat(msg,"'");
|
||||
if (f->loc_line > 0) {
|
||||
wad_strcat(msg,", line ");
|
||||
wad_strcat(msg,wad_format_signed(f->loc_line,-1));
|
||||
/* Try to locate the source file */
|
||||
wad_debug_src_string(f, WAD_SRC_WINDOW);
|
||||
}
|
||||
} else {
|
||||
if (f->loc_objfile && strlen(f->loc_objfile)) {
|
||||
wad_strcat(msg," from '");
|
||||
wad_strcat(msg, wad_strip_dir(f->loc_objfile));
|
||||
wad_strcat(msg,"'");
|
||||
}
|
||||
}
|
||||
wad_strcat(msg,"\n");
|
||||
f->debug_str = wad_strdup(msg);
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump trace to a file */
|
||||
void wad_dump_trace(int fd, int signo, WadFrame *f, char *ret) {
|
||||
static char buffer[128];
|
||||
char *srcstr = 0;
|
||||
|
||||
switch(signo) {
|
||||
case SIGSEGV:
|
||||
write(fd,"WAD: Segmentation fault.\n", 25);
|
||||
break;
|
||||
case SIGBUS:
|
||||
write(fd,"WAD: Bus error.\n",17);
|
||||
break;
|
||||
case SIGABRT:
|
||||
write(fd,"WAD: Abort.\n",12);
|
||||
break;
|
||||
case SIGFPE:
|
||||
write(fd,"WAD: Floating point exception.\n", 31);
|
||||
break;
|
||||
case SIGILL:
|
||||
write(fd,"WAD: Illegal instruction.\n", 26);
|
||||
break;
|
||||
default:
|
||||
sprintf(buffer,"WAD: Signal %d\n", signo);
|
||||
write(fd,buffer,strlen(buffer));
|
||||
break;
|
||||
}
|
||||
/* Find the last exception frame */
|
||||
|
||||
while (f && !(f->last)) {
|
||||
f = f->next;
|
||||
}
|
||||
|
||||
while (f) {
|
||||
write(fd,f->debug_str,strlen(f->debug_str));
|
||||
if (f->debug_srcstr) {
|
||||
srcstr = f->debug_srcstr;
|
||||
}
|
||||
f = f->prev;
|
||||
}
|
||||
if (srcstr) {
|
||||
write(fd,"\n",1);
|
||||
write(fd,srcstr,strlen(srcstr));
|
||||
write(fd,"\n",1);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Default callback
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_default_callback(int signo, WadFrame *f, char *ret) {
|
||||
wad_dump_trace(2,signo,f,ret);
|
||||
}
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* demangle.c
|
||||
*
|
||||
* This file performs C++ partial name demangling to the extent that it
|
||||
* seems reasonable.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
char *wad_cplus_demangle(WadSymbol *ws) {
|
||||
static char buffer[4096];
|
||||
strcpy(buffer,ws->name);
|
||||
return buffer;
|
||||
}
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* elf.c
|
||||
*
|
||||
* ELF file management. This file contains functions for accessing ELF
|
||||
* file data from a raw memory mapped ELF file (as performed by the
|
||||
* functions in object.c).
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
#include <sys/elf.h>
|
||||
#endif
|
||||
#ifdef WAD_LINUX
|
||||
#include <elf.h>
|
||||
#endif
|
||||
|
||||
/* --- What's needed here (high level interface) :
|
||||
- Mapping of addresses to symbols
|
||||
- Mapping of symbols to file+line
|
||||
*/
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_check()
|
||||
*
|
||||
* Checks to see if an object file is an ELF file. Returns 1 on success and
|
||||
* changes the type flag of wo to indicate the type of ELF file.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_check(WadObjectFile *wo) {
|
||||
if (strncmp((char *)wo->ptr,ELFMAG, SELFMAG) != 0)
|
||||
return 0;
|
||||
|
||||
/* Probably need to put some kind of 32/64 bit check here */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_phdrcnt()
|
||||
*
|
||||
* Return number of entries in the ELF program header section
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_phdrcnt(WadObjectFile *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
return eh->e_phnum;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_phdrpos()
|
||||
*
|
||||
* Return the location of the ELF program header.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *
|
||||
wad_elf_phdrpos(WadObjectFile *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *c;
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
c = (char *) wo->ptr;
|
||||
return (void *) (c+eh->e_phoff);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_shdrcnt()
|
||||
*
|
||||
* Return number of entries in the ELF section header
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_shdrcnt(WadObjectFile *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
return eh->e_shnum;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_shdrpos()
|
||||
*
|
||||
* Return the location of the section headers
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *
|
||||
wad_elf_shdrpos(WadObjectFile *wo) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *c;
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
c = (char *) wo->ptr;
|
||||
return (void *) (c+eh->e_shoff);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_header()
|
||||
*
|
||||
* Get a specific section number
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_elf_section_header(WadObjectFile *wo, int sn) {
|
||||
Elf32_Ehdr *eh;
|
||||
char *r;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
if ((sn < 0) || (sn >= eh->e_shnum)) return 0;
|
||||
|
||||
r = (char *) wad_elf_shdrpos(wo) + (sn*eh->e_shentsize);
|
||||
return (void *) r;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_data()
|
||||
*
|
||||
* Get section data
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_elf_section_data(WadObjectFile *wo, int sn) {
|
||||
Elf32_Shdr *sh;
|
||||
char *r;
|
||||
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return 0;
|
||||
|
||||
r = ((char *) wo->ptr) + sh->sh_offset;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_size()
|
||||
* Return section size
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int wad_elf_section_size(WadObjectFile *wo, int sn) {
|
||||
Elf32_Shdr *sh;
|
||||
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return -1;
|
||||
return sh->sh_size;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_name()
|
||||
*
|
||||
* Returns the name of an ELF section
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *wad_elf_section_name(WadObjectFile *wo, int sn) {
|
||||
Elf32_Ehdr *eh;
|
||||
Elf32_Shdr *sh;
|
||||
char *sectionstr;
|
||||
|
||||
eh = (Elf32_Ehdr *) wo->ptr;
|
||||
|
||||
/* Get the string table */
|
||||
sectionstr = (char *) wad_elf_section_data(wo,eh->e_shstrndx);
|
||||
if (!sectionstr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the section header for the section */
|
||||
sh = (Elf32_Shdr *) wad_elf_section_header(wo,sn);
|
||||
if (!sh) return 0;
|
||||
return sectionstr + sh->sh_name;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_section_byname()
|
||||
*
|
||||
* Get section data given a section name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_section_byname(WadObjectFile *wo, char *name) {
|
||||
int i;
|
||||
char *sn;
|
||||
int n;
|
||||
|
||||
n = wad_elf_shdrcnt(wo);
|
||||
for (i = 0; i <n; i++) {
|
||||
sn = wad_elf_section_name(wo,i);
|
||||
if (strcmp(sn,name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_find_symbol()
|
||||
*
|
||||
* Tries to find the symbol associated with a given address. base is the
|
||||
* base address of the object file.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static
|
||||
int elf_search_section_sym(WadFrame *f, char *secname, char *strname) {
|
||||
int nsymtab;
|
||||
int nstrtab;
|
||||
int symtab_size;
|
||||
Elf32_Sym *sym;
|
||||
int nsym;
|
||||
char *str;
|
||||
int i;
|
||||
unsigned long vaddr, base;
|
||||
char *name;
|
||||
char *localfile = 0;
|
||||
|
||||
vaddr = (unsigned long) f->pc;
|
||||
base = (unsigned long) f->segment->base;
|
||||
|
||||
nsymtab = wad_elf_section_byname(f->object,secname);
|
||||
if (nsymtab < 0) return 0;
|
||||
nstrtab = wad_elf_section_byname(f->object,strname);
|
||||
if (nstrtab < 0) return 0;
|
||||
|
||||
symtab_size = wad_elf_section_size(f->object,nsymtab);
|
||||
sym = (Elf32_Sym *) wad_elf_section_data(f->object,nsymtab);
|
||||
str = (char *) wad_elf_section_data(f->object,nstrtab);
|
||||
|
||||
nsym = (symtab_size/sizeof(Elf32_Sym));
|
||||
for (i = 0; i < nsym; i++) {
|
||||
name = str + sym[i].st_name;
|
||||
/* Look for filename in case the symbol maps to a local symbol */
|
||||
if (ELF32_ST_TYPE(sym[i].st_info) == STT_FILE) {
|
||||
localfile = name;
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_SYMBOL_SEARCH) {
|
||||
wad_printf("%x(%x): %s %x + %x, %x, %x\n", base, vaddr, name, sym[i].st_value, sym[i].st_size, sym[i].st_info, sym[i].st_shndx);
|
||||
}
|
||||
if (((base + sym[i].st_value) <= vaddr) && (vaddr <= (base+sym[i].st_value + sym[i].st_size))) {
|
||||
#ifdef WAD_LINUX
|
||||
/* If the section index is 0, the symbol is undefined */
|
||||
if (sym[i].st_shndx == 0) continue;
|
||||
#endif
|
||||
f->sym_name = name;
|
||||
f->sym_nlen = strlen(name);
|
||||
f->sym_base = base + sym[i].st_value;
|
||||
f->sym_size = sym[i].st_size;
|
||||
if (ELF32_ST_BIND(sym[i].st_info) == STB_LOCAL) {
|
||||
f->sym_file = localfile;
|
||||
f->sym_bind = SYM_LOCAL;
|
||||
} else {
|
||||
f->sym_bind = SYM_GLOBAL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wad_elf_find_symbol(WadFrame *f) {
|
||||
/* We simply try a few possible sections */
|
||||
if (elf_search_section_sym(f,".symtab",".strtab")) return;
|
||||
if (elf_search_section_sym(f,".dynsym",".dynstr")) return;
|
||||
|
||||
/* Hmmm. No match found. Oh well */
|
||||
return;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_debug_info()
|
||||
*
|
||||
* Gather debugging information about a function (if possible)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_elf_debug_info(WadFrame *f) {
|
||||
int nstab, nstabstr, nstabindex, nstabindexstr, nstabexcl, nstabexclstr;
|
||||
int ret;
|
||||
void *stab;
|
||||
char *stabstr;
|
||||
int stabsize;
|
||||
|
||||
nstab = wad_elf_section_byname(f->object,".stab");
|
||||
nstabstr = wad_elf_section_byname(f->object,".stabstr");
|
||||
nstabindex = wad_elf_section_byname(f->object,".stab.index");
|
||||
nstabindexstr = wad_elf_section_byname(f->object,".stab.indexstr");
|
||||
nstabexcl = wad_elf_section_byname(f->object,".stab.excl");
|
||||
nstabexclstr = wad_elf_section_byname(f->object,".stab.exclstr");
|
||||
|
||||
#ifdef DEBUG_DEBUG
|
||||
wad_printf("nstab = %d\n", nstab);
|
||||
wad_printf("nstabstr = %d\n", nstabstr);
|
||||
wad_printf("nstabindex = %d\n", nstabindex);
|
||||
wad_printf("nstabindexstr = %d\n", nstabindexstr);
|
||||
wad_printf("nstabexcl = %d\n", nstabexcl);
|
||||
wad_printf("nstabexclstr = %d\n", nstabexclstr);
|
||||
#endif
|
||||
|
||||
/* Now start searching stabs */
|
||||
|
||||
/* Look in the .stab section */
|
||||
if (nstab > 0) {
|
||||
stab = wad_elf_section_data(f->object,nstab);
|
||||
stabsize = wad_elf_section_size(f->object,nstab);
|
||||
stabstr = (char *) wad_elf_section_data(f->object,nstabstr);
|
||||
|
||||
|
||||
if (wad_search_stab(stab,stabsize,stabstr, f)) return 1;
|
||||
}
|
||||
|
||||
/* Look in the .stab.excl section. A solaris oddity? */
|
||||
|
||||
if (nstabexcl > 0) {
|
||||
stab = wad_elf_section_data(f->object,nstabexcl);
|
||||
stabsize = wad_elf_section_size(f->object, nstabexcl);
|
||||
stabstr = (char *) wad_elf_section_data(f->object, nstabexclstr);
|
||||
|
||||
if (wad_search_stab(stab,stabsize,stabstr, f)) return 1;
|
||||
}
|
||||
|
||||
/* Look in the .stab.index section. A Solaris oddity? */
|
||||
if (nstabindex > 0) {
|
||||
|
||||
stab = wad_elf_section_data(f->object,nstabindex);
|
||||
stabsize = wad_elf_section_size(f->object, nstabindex);
|
||||
stabstr = (char *) wad_elf_section_data(f->object, nstabindexstr);
|
||||
|
||||
if (wad_search_stab(stab,stabsize,stabstr, f)) {
|
||||
/* Hmmm. Might be in a different file */
|
||||
WadObjectFile *wo1, *wold;
|
||||
char objfile[MAX_PATH];
|
||||
/* printf("DEBUG %s\n", f->sym_name); */
|
||||
wad_strcpy(objfile, f->loc_objfile);
|
||||
wo1 = wad_object_load(objfile);
|
||||
if (wo1) {
|
||||
wold = f->object;
|
||||
f->object = wo1;
|
||||
wad_find_debug(f);
|
||||
f->object = wold;
|
||||
return ret;
|
||||
} else {
|
||||
/* wad_printf("couldn't load %s\n", objfile); */
|
||||
}
|
||||
/* if (!ret) return wad_search_stab(stab,stabsize,stabstr,f);*/
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_elf_debug()
|
||||
*
|
||||
* Print some debugging information about an object
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_elf_debug(WadObjectFile *wo) {
|
||||
int i;
|
||||
wad_printf("ELF Debug : obj = %x (%s)\n", wo, wo->path);
|
||||
wad_printf(" phdrcnt = %d\n", wad_elf_phdrcnt(wo));
|
||||
wad_printf(" phdrpos = %x\n", wad_elf_phdrpos(wo));
|
||||
wad_printf(" shdrcnt = %d\n", wad_elf_shdrcnt(wo));
|
||||
wad_printf(" shdrpos = %x\n", wad_elf_shdrpos(wo));
|
||||
for (i = 0; i < wad_elf_shdrcnt(wo); i++) {
|
||||
wad_printf(" section '%s': data = 0x%x, size = %d\n",
|
||||
wad_elf_section_name(wo,i),
|
||||
wad_elf_section_data(wo,i),
|
||||
wad_elf_section_size(wo,i));
|
||||
}
|
||||
}
|
||||
|
||||
/* general purpose functions exposed to the outside world */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_find_symbol()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_find_symbol(WadFrame *f) {
|
||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||
wad_printf("wad: Searching for 0x%08x --> ", f->pc);
|
||||
}
|
||||
if (f->object)
|
||||
wad_elf_find_symbol(f);
|
||||
if (wad_debug_mode & DEBUG_SYMBOL) {
|
||||
if (f->sym_name) {
|
||||
wad_printf("%s", f->sym_name);
|
||||
if (f->sym_file)
|
||||
wad_printf(" in '%s'\n", f->sym_file);
|
||||
else
|
||||
wad_printf("\n");
|
||||
} else {
|
||||
wad_printf("?\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wad_find_debug(WadFrame *f) {
|
||||
/* if (f->debug_check) return; */
|
||||
if (f->object) {
|
||||
wad_elf_debug_info(f);
|
||||
}
|
||||
/* f->debug_check = 1; */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* init.c
|
||||
*
|
||||
* Initialize the wad system. This sets up a signal handler for catching
|
||||
* SIGSEGV, SIGBUS, and SIGABRT.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Debugging flag */
|
||||
int wad_debug_mode = 0;
|
||||
|
||||
/* Initialize wad */
|
||||
void wad_init() {
|
||||
static int init = 0;
|
||||
|
||||
wad_memory_init();
|
||||
if (getenv("WAD_DEBUG_SEGMENT")) {
|
||||
wad_debug_mode |= DEBUG_SEGMENT;
|
||||
}
|
||||
if (getenv("WAD_DEBUG_SYMBOL")) {
|
||||
wad_debug_mode |= DEBUG_SYMBOL;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_OBJECT")) {
|
||||
wad_debug_mode |= DEBUG_OBJECT;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_FILE")) {
|
||||
wad_debug_mode |= DEBUG_FILE;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_HOLD")) {
|
||||
wad_debug_mode |= DEBUG_HOLD;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_STABS")) {
|
||||
wad_debug_mode |= DEBUG_STABS;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_RETURN")) {
|
||||
wad_debug_mode |= DEBUG_RETURN;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_SYMBOL_SEARCH")) {
|
||||
wad_debug_mode |= DEBUG_SYMBOL_SEARCH;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_INIT")) {
|
||||
wad_debug_mode |= DEBUG_INIT;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_STACK")) {
|
||||
wad_debug_mode |= DEBUG_STACK;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_UNWIND")) {
|
||||
wad_debug_mode |= DEBUG_UNWIND;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_SIGNAL")) {
|
||||
wad_debug_mode |= DEBUG_SIGNAL;
|
||||
}
|
||||
|
||||
if (getenv("WAD_NOSTACK")) {
|
||||
wad_debug_mode |= DEBUG_NOSTACK;
|
||||
}
|
||||
|
||||
if (getenv("WAD_ONESHOT")) {
|
||||
wad_debug_mode |= DEBUG_ONESHOT;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_STRING")) {
|
||||
wad_debug_mode |= DEBUG_STRING;
|
||||
}
|
||||
|
||||
if (getenv("WAD_DEBUG_MEMORY")) {
|
||||
wad_debug_mode |= DEBUG_MEMORY;
|
||||
}
|
||||
|
||||
if (wad_debug_mode & DEBUG_INIT) {
|
||||
wad_printf("WAD: initializing\n");
|
||||
}
|
||||
|
||||
|
||||
if (!init) {
|
||||
wad_signal_init();
|
||||
wad_object_reset();
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* io.c
|
||||
*
|
||||
* This file provides some I/O routines so that WAD can produce
|
||||
* debugging output without using buffered I/O.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Utility functions used to generate strings that are guaranteed not to
|
||||
rely upon malloc() and related functions */
|
||||
|
||||
char *wad_format_hex(unsigned long u, int leading) {
|
||||
static char result[64];
|
||||
int i;
|
||||
char *c;
|
||||
c = &result[63];
|
||||
*c = 0;
|
||||
for (i = 0; i < (sizeof(unsigned long)*2); i++) {
|
||||
int d;
|
||||
d = (int) (u & 0xf);
|
||||
c--;
|
||||
if (d < 10) {
|
||||
*c = '0' + d;
|
||||
} else {
|
||||
*c = 'a' + (d-10);
|
||||
}
|
||||
if (!u && !leading) break;
|
||||
u = u >> 4;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
char *wad_format_unsigned(unsigned long u, int width) {
|
||||
static char result[128];
|
||||
static char digits[] = "0123456789";
|
||||
char *c, *w;
|
||||
int count = 0;
|
||||
int i;
|
||||
c = &result[64];
|
||||
while (u) {
|
||||
int digit = u % 10;
|
||||
*(--c) = digits[digit];
|
||||
count++;
|
||||
u = u / 10;
|
||||
}
|
||||
if (!count) {
|
||||
*(--c) = '0';
|
||||
count++;
|
||||
}
|
||||
w = &result[64];
|
||||
for (i = count; i < width; i++) {
|
||||
*(w++) = ' ';
|
||||
}
|
||||
*w = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
char *wad_format_signed(signed long s, int width) {
|
||||
static char result[128];
|
||||
unsigned long u;
|
||||
char *c = result;
|
||||
if (s < 0) {
|
||||
*(c++) = '-';
|
||||
width--;
|
||||
u = (unsigned long) (-s);
|
||||
if (u == 0) {
|
||||
u = (unsigned long) s;
|
||||
}
|
||||
} else {
|
||||
u = (unsigned long) s;
|
||||
}
|
||||
*c = 0;
|
||||
wad_strcat(result, wad_format_unsigned(u,width));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void wad_printf(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr,fmt,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package libwadpl;
|
||||
require Exporter;
|
||||
require DynaLoader;
|
||||
@ISA = qw(Exporter DynaLoader);
|
||||
package libwadpl;
|
||||
bootstrap libwadpl;
|
||||
@EXPORT = qw( );
|
||||
1;
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
extern "C" {
|
||||
#include "wad.h"
|
||||
}
|
||||
|
||||
/* This is a sick hack to force initialization upon loading */
|
||||
|
||||
class StartDebug {
|
||||
public:
|
||||
StartDebug() {
|
||||
wad_init();
|
||||
}
|
||||
};
|
||||
|
||||
static StartDebug s;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#!/usr/local/bin/python
|
||||
import string
|
||||
f = open("wadhandler.pl")
|
||||
data = f.read()
|
||||
f.close()
|
||||
|
||||
data = string.replace(data,"\\", "\\\\")
|
||||
data = string.replace(data,"\"", "\\\"")
|
||||
data = string.replace(data,"\n", "\\n\\\n")
|
||||
|
||||
f = open("wad_perl_handler.c","w")
|
||||
|
||||
f.write("static char wad_perl_handler[] = \"")
|
||||
f.write(data)
|
||||
f.write("\";\n");
|
||||
f.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* memory.c
|
||||
*
|
||||
* This file provides simple mmap() based memory management for WAD. Since
|
||||
* the process heap-allocator might be corrupted when WAD is invoked, we
|
||||
* have to do all of our own memory management. However, since WAD mostly
|
||||
* just collects data, we only provide the function wad_malloc(). To
|
||||
* release all allocated memory, the wad_release_memory() function should
|
||||
* be used.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
typedef struct _WadMemory {
|
||||
int npages; /* Number of pages */
|
||||
int last; /* Last offset in page */
|
||||
struct _WadMemory *next; /* Pointer to next allocation */
|
||||
} WadMemory;
|
||||
|
||||
static WadMemory *current = 0; /* Current memory block */
|
||||
static int pagesize = 0; /* System page size */
|
||||
static int devzero = 0;
|
||||
static int npalloc = 8; /* Number of pages per alloc */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_memory_init()
|
||||
*
|
||||
* Initialize the WAD allocator.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int wad_memory_init() {
|
||||
pagesize = getpagesize();
|
||||
devzero = open("/dev/zero", O_RDWR);
|
||||
if (devzero < 0) {
|
||||
wad_printf("WAD: couldn't open /dev/zero.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_page_alloc()
|
||||
*
|
||||
* Allocate pages using mmap
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_page_alloc(int npages) {
|
||||
void *m;
|
||||
m = mmap(NULL, npages*pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, devzero, 0);
|
||||
if (((long) m) == -1) return 0;
|
||||
/* printf("page_alloc: %x - %x\n", m, ((char *) m) + npages*pagesize); */
|
||||
return m;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_malloc()
|
||||
*
|
||||
* Allocate memory using mmap(). If the allocation is smaller than half a page,
|
||||
* We'll look at current to see if there is enough space. If so, we'll just
|
||||
* use that memory. Otherwise, we'll allocate a new page. If the allocation
|
||||
* request is larger than a page, we'll round up to the nearest page size and
|
||||
* do a special allocation.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void *wad_malloc(int nbytes) {
|
||||
void *ptr;
|
||||
WadMemory *wm;
|
||||
char *c;
|
||||
int npages;
|
||||
/* wad_printf("wad_malloc: %d\n", nbytes); */
|
||||
if (nbytes >= ((npalloc*pagesize) >> 2)) {
|
||||
/* Large allocation. */
|
||||
npages = ((nbytes + sizeof(WadMemory))/pagesize) + 1;
|
||||
ptr = wad_page_alloc(npages);
|
||||
if (!ptr) return 0;
|
||||
wm = (WadMemory *)ptr;
|
||||
wm->npages = npages;
|
||||
wm->last = sizeof(WadMemory) + 8;
|
||||
wm->next = current;
|
||||
current = wm;
|
||||
c = (char *) current + (current->last);
|
||||
current->last += ((nbytes & ~0x7) + 8);
|
||||
return c;
|
||||
}
|
||||
/* Small allocation. See if there are any regions big enough */
|
||||
wm = current;
|
||||
while (wm) {
|
||||
if (((wm->npages*pagesize) - wm->last) > nbytes) {
|
||||
/* Yep. Found a region */
|
||||
break;
|
||||
}
|
||||
wm = wm->next;
|
||||
}
|
||||
if (!wm) {
|
||||
/* wad_printf("wad_malloc: new page\n", nbytes);*/
|
||||
wm = (WadMemory *) wad_page_alloc(npalloc);
|
||||
if (!wm) return 0;
|
||||
wm->npages = npalloc;
|
||||
wm->last = sizeof(WadMemory) + 8;
|
||||
wm->next = current;
|
||||
current = wm;
|
||||
}
|
||||
c = ((char *) wm) + (wm->last);
|
||||
wm->last += ((nbytes & ~0x7) + 8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_strdup()
|
||||
*
|
||||
* Duplicate a string
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
char *wad_strdup(const char *c) {
|
||||
char *t;
|
||||
if (!c) c = "";
|
||||
t = (char *) wad_malloc(strlen(c)+1);
|
||||
wad_strcpy(t,c);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_memcpy()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_memcpy(void *t, const void *s, unsigned len) {
|
||||
char *tc, *sc;
|
||||
int i;
|
||||
tc = (char *) t;
|
||||
sc = (char *) s;
|
||||
for (i = 0; i < len; i++, tc++, sc++)
|
||||
*tc = *sc;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_memory_debug()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_memory_debug() {
|
||||
int total_alloc = 0;
|
||||
int inuse = 0;
|
||||
WadMemory *m;
|
||||
if (wad_debug_mode & DEBUG_MEMORY) {
|
||||
m = current;
|
||||
while (m) {
|
||||
total_alloc += (m->npages)*pagesize;
|
||||
inuse += m->last;
|
||||
m = m->next;
|
||||
}
|
||||
wad_printf("WAD: memory allocated %d bytes (%d bytes used).\n", total_alloc, inuse);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,303 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* object.c
|
||||
*
|
||||
* This file provides access to raw object files, executables, and
|
||||
* library files. Memory management is handled through mmap() to
|
||||
* avoid the use of heap/stack space.
|
||||
*
|
||||
* All of the files and objects created by this module persist
|
||||
* until the process exits. Since WAD may be invoked multiple times
|
||||
* over the course of program execution, it makes little sense to keep
|
||||
* loading and unloading files---subsequent invocations of the handler
|
||||
* can simply used previously loaded copies. Caveat: things probably
|
||||
* won't work right if a program is doing lots of low-level manipulation
|
||||
* of the dynamic loader.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
#include <ar.h>
|
||||
|
||||
typedef struct WadFile {
|
||||
void *addr; /* Base address of the file */
|
||||
int size; /* Size in bytes */
|
||||
char *path; /* Path name */
|
||||
struct WadFile *next; /* Next file */
|
||||
} WadFile;
|
||||
|
||||
static WadFile *wad_files = 0; /* Linked list of loaded files */
|
||||
|
||||
/* private function to manage the loading of raw files into memory */
|
||||
static WadFile *
|
||||
load_file(const char *path) {
|
||||
int fd;
|
||||
WadFile *wf = wad_files;
|
||||
|
||||
if (wad_debug_mode & DEBUG_FILE) {
|
||||
wad_printf("wad: Loading file '%s' ... ", path);
|
||||
}
|
||||
while (wf) {
|
||||
if (strcmp(wf->path,path) == 0) {
|
||||
if (wad_debug_mode & DEBUG_FILE) wad_printf("cached.\n");
|
||||
return wf;
|
||||
}
|
||||
wf = wf->next;
|
||||
}
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (wad_debug_mode & DEBUG_FILE) wad_printf("not found!\n");
|
||||
return 0; /* Doesn't exist. Oh well */
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_FILE) wad_printf("loaded.\n");
|
||||
wf = (WadFile *) wad_malloc(sizeof(WadFile));
|
||||
wf->path = wad_strdup(path);
|
||||
|
||||
/* Get file length */
|
||||
wf->size = lseek(fd,0,SEEK_END);
|
||||
lseek(fd,0,SEEK_SET);
|
||||
|
||||
/* Try to mmap the file */
|
||||
wf->addr = mmap(NULL,wf->size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
if (wf->addr == MAP_FAILED) {
|
||||
if (wad_debug_mode & DEBUG_FILE) wad_printf("wad: Couldn't mmap '%s'\n", path);
|
||||
return 0;
|
||||
}
|
||||
wf->next = wad_files;
|
||||
wad_files = wf;
|
||||
return wf;
|
||||
}
|
||||
|
||||
static WadObjectFile *wad_objects = 0; /* Linked list of object files */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_cleanup()
|
||||
*
|
||||
* Reset the object file loader. This unmaps the files themselves, but
|
||||
* memory will leak for object files pointers themselves.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
wad_object_reset() {
|
||||
WadFile *f = wad_files;
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
wad_printf("wad: Releasing all files.\n");
|
||||
}
|
||||
/* Unmap all of the loaded files */
|
||||
while (f) {
|
||||
if (f->addr) {
|
||||
munmap(f->addr, f->size);
|
||||
}
|
||||
f = f->next;
|
||||
}
|
||||
/* Reset the linked lists */
|
||||
wad_files = 0;
|
||||
wad_objects = 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_object_load()
|
||||
*
|
||||
* Load an object file into memory using mmap. Returns 0 if the object does
|
||||
* not exist or if we're out of memory.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadObjectFile *
|
||||
wad_object_load(const char *path) {
|
||||
WadObjectFile *wo;
|
||||
WadFile *wf;
|
||||
WadObjectFile *wad_arobject_load(const char *path, const char *name);
|
||||
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
wad_printf("wad: Loading object '%s'", path);
|
||||
}
|
||||
for (wo = wad_objects; wo; wo=wo->next) {
|
||||
if (strcmp(wo->path,path) == 0) {
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
wad_printf(" (cached)\n");
|
||||
}
|
||||
return wo;
|
||||
}
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_OBJECT) {
|
||||
wad_printf("\n");
|
||||
}
|
||||
/* Didn't find it. Now we need to go load some files */
|
||||
|
||||
/* If this is an archive reference like /path/libfoo.a(blah.o), we need to
|
||||
split up the name a little bit */
|
||||
{
|
||||
char realfile[MAX_PATH];
|
||||
char *objfile;
|
||||
char *c;
|
||||
c = strchr(path,'(');
|
||||
if (c) {
|
||||
wad_strcpy(realfile,path);
|
||||
c = strchr(realfile,'(');
|
||||
*c = 0;
|
||||
objfile = c+1;
|
||||
c = strchr(objfile,')');
|
||||
*c = 0;
|
||||
|
||||
/* Okay, I'm going to attempt to map this as a library file */
|
||||
wo = wad_arobject_load(realfile,objfile);
|
||||
if (wo) {
|
||||
/* Reset the path */
|
||||
wo->path = wad_strdup(path);
|
||||
wo->next = wad_objects;
|
||||
wad_objects = wo;
|
||||
return wo;
|
||||
}
|
||||
}
|
||||
}
|
||||
wf = load_file(path);
|
||||
if (!wf) return 0;
|
||||
|
||||
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
|
||||
wo->path = wad_strdup(path);
|
||||
wo->ptr = wf->addr;
|
||||
wo->len = wf->size;
|
||||
wo->next = wad_objects;
|
||||
wad_objects = wo;
|
||||
return wo;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_arobject_load()
|
||||
*
|
||||
* Load an object file stored in an archive file created with an archive. The
|
||||
* pathname should be the path of the .a file and robjname should be the name
|
||||
* of the object file stored in the object file.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadObjectFile *
|
||||
wad_arobject_load(const char *arpath, const char *robjname) {
|
||||
WadObjectFile *wo;
|
||||
WadFile *wf;
|
||||
int arlen;
|
||||
char *arptr;
|
||||
struct ar_hdr *ah;
|
||||
int offset;
|
||||
int msize;
|
||||
char *strtab = 0;
|
||||
int sobjname;
|
||||
char objname[MAX_PATH];
|
||||
|
||||
wad_strcpy(objname,robjname);
|
||||
wad_strcat(objname,"/");
|
||||
sobjname = strlen(objname);
|
||||
|
||||
wf = load_file(arpath);
|
||||
if (!wf) return 0; /* Doesn't exit */
|
||||
|
||||
arptr = (char *) wf->addr;
|
||||
arlen = wf->size;
|
||||
|
||||
/* Now take a look at the archive */
|
||||
if (strncmp(arptr,ARMAG,SARMAG) == 0) {
|
||||
/* printf("Got an archive\n"); */
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search the archive for the request member */
|
||||
strtab = 0;
|
||||
offset = SARMAG;
|
||||
while (offset < arlen) {
|
||||
char mname[MAX_PATH];
|
||||
ah = (struct ar_hdr *) (arptr + offset);
|
||||
if (strncmp(ah->ar_name,"// ", 3) == 0) {
|
||||
strtab = arptr + offset + sizeof(struct ar_hdr);
|
||||
}
|
||||
msize = atoi(ah->ar_size);
|
||||
|
||||
offset += sizeof(struct ar_hdr);
|
||||
/* Try to figure out the filename */
|
||||
if ((ah->ar_name[0] == '/') && (isdigit(ah->ar_name[1]))) {
|
||||
int soff;
|
||||
char *e;
|
||||
/* Must be in the string offset table */
|
||||
soff = atoi(ah->ar_name+1);
|
||||
if (!strtab) {
|
||||
/* No offset table */
|
||||
return 0;
|
||||
}
|
||||
e = strchr(strtab+soff,'\n');
|
||||
if (e) {
|
||||
strncpy(mname, strtab+soff, (e - (strtab+soff)));
|
||||
mname[e-(strtab+soff)] = 0;
|
||||
} else {
|
||||
mname[0] = 0;
|
||||
}
|
||||
} else {
|
||||
/* Name must be in the name field */
|
||||
strncpy(mname,ah->ar_name,16);
|
||||
mname[16] = 0;
|
||||
}
|
||||
/* Compare the names */
|
||||
if (strncmp(mname,objname,sobjname) == 0) {
|
||||
/* Found the archive */
|
||||
wo = (WadObjectFile *) wad_malloc(sizeof(WadObjectFile));
|
||||
wo->ptr = (void *) (arptr + offset);
|
||||
wo->len = msize;
|
||||
wo->path = 0;
|
||||
return wo;
|
||||
}
|
||||
offset += msize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_find_object(WadFrame *f)
|
||||
*
|
||||
* Given a stack frame. Try to locate the object file
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_find_object(WadFrame *f) {
|
||||
if (f->segment) {
|
||||
f->object = wad_object_load(f->segment->mappath);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_file_check(void *addr)
|
||||
*
|
||||
* Given an address, this function checks to see if it corresponds to a file
|
||||
* we already mapped.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_file_check(void *addr) {
|
||||
WadFile *f = wad_files;
|
||||
while (f) {
|
||||
if ((((char *) f->addr) <= ((char *) addr)) &&
|
||||
(((char *) addr) < (((char *) f->addr) + f->size))) {
|
||||
return 1;
|
||||
}
|
||||
f = f->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* return.c
|
||||
*
|
||||
* This file manages the set of return-points for the WAD signal handler.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Maximum number of return points */
|
||||
#define WAD_NUMBER_RETURN 128
|
||||
|
||||
static WadReturnFunc return_points[WAD_NUMBER_RETURN];
|
||||
static int num_return = 0;
|
||||
|
||||
void wad_set_return(const char *name, long value) {
|
||||
WadReturnFunc *rp;
|
||||
rp = &return_points[num_return];
|
||||
wad_strcpy(rp->name,name);
|
||||
rp->value = value;
|
||||
num_return++;
|
||||
if (wad_debug_mode & DEBUG_RETURN) {
|
||||
printf("wad: Setting return ('%s', %d)\n", name,value);
|
||||
}
|
||||
}
|
||||
|
||||
void wad_set_returns(WadReturnFunc *rf) {
|
||||
int i = 0;
|
||||
while (strlen(rf[i].name)) {
|
||||
wad_set_return(rf[i].name, rf[i].value);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
WadReturnFunc *wad_check_return(const char *name) {
|
||||
int i;
|
||||
if (!name) return 0;
|
||||
for (i = 0; i < num_return; i++) {
|
||||
if (strcmp(name,return_points[i].name) == 0) {
|
||||
if (wad_debug_mode & DEBUG_RETURN) {
|
||||
printf("wad: Found return ('%s', %d)\n", return_points[i].name, return_points[i].value);
|
||||
}
|
||||
return &return_points[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* segment.c
|
||||
*
|
||||
* This file provides access to the virtual memory map of a process
|
||||
* including the location of the executable, data segments, shared
|
||||
* libraries, and memory mapped regions.
|
||||
*
|
||||
* The primary purpose of this module is to collect this information
|
||||
* and store it in a form that hides platform specific details (the
|
||||
* WadSegment structure).
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Include the proper code for reading the segment map */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
|
||||
/* This code is used to read the process virtual memory map on Solaris machines */
|
||||
|
||||
static int
|
||||
segment_open() {
|
||||
int f;
|
||||
f = open("/proc/self/map", O_RDONLY);
|
||||
return f;
|
||||
}
|
||||
|
||||
static int
|
||||
segment_read(int fs, WadSegment *s) {
|
||||
int dz;
|
||||
int n;
|
||||
prmap_t pmap;
|
||||
|
||||
n = read(fs, &pmap, sizeof(prmap_t));
|
||||
if (n <= 0) return 0;
|
||||
s->mapname = wad_strdup(pmap.pr_mapname);
|
||||
s->mappath = (char *) wad_malloc(20+strlen(pmap.pr_mapname));
|
||||
wad_strcpy(s->mappath,"/proc/self/object/");
|
||||
strcat(s->mappath,pmap.pr_mapname);
|
||||
s->vaddr = (char *) pmap.pr_vaddr;
|
||||
|
||||
/* This is a solaris oddity. a.out section starts 1 page up, but
|
||||
symbols are relative to a base of 0 */
|
||||
|
||||
if (strcmp(s->mapname,"a.out") == 0) s->base = 0;
|
||||
else s->base = s->vaddr;
|
||||
|
||||
s->size = pmap.pr_size;
|
||||
s->offset = pmap.pr_offset;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* WAD_SOLARIS */
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
static char linux_firstsegment[1024];
|
||||
static int linux_first = 1;
|
||||
|
||||
static int
|
||||
segment_open() {
|
||||
FILE *f;
|
||||
f = fopen("/proc/self/maps", "r");
|
||||
linux_first =1;
|
||||
return (int) f;
|
||||
}
|
||||
|
||||
static int
|
||||
segment_read(int fd, WadSegment *s)
|
||||
{
|
||||
char pbuffer[1024];
|
||||
char *c;
|
||||
int len;
|
||||
FILE *fs = (FILE *) fd;
|
||||
c = fgets(pbuffer,1024,fs);
|
||||
if (!c) return 0;
|
||||
|
||||
pbuffer[strlen(pbuffer)-1] = 0; /* Chop off endline */
|
||||
|
||||
/* Break up the field into records */
|
||||
/* 0-8 : Starting address
|
||||
9-17 : Ending Address
|
||||
18 : r
|
||||
19 : w
|
||||
20 : x
|
||||
21 : p
|
||||
23-31 : Offset
|
||||
49- : Filename */
|
||||
|
||||
len = strlen(pbuffer);
|
||||
pbuffer[8] = 0;
|
||||
pbuffer[17] = 0;
|
||||
pbuffer[31] = 0;
|
||||
if (len >= 49) {
|
||||
s->mapname = wad_strdup(pbuffer+49);
|
||||
s->mappath = s->mapname;
|
||||
} else {
|
||||
s->mapname = "";
|
||||
s->mappath = s->mapname;
|
||||
}
|
||||
if (linux_first) {
|
||||
wad_strcpy(linux_firstsegment, s->mappath);
|
||||
linux_first = 0;
|
||||
}
|
||||
s->vaddr = (char *) strtoul(pbuffer,NULL,16);
|
||||
s->size = strtoul(pbuffer+9,NULL,16) - (long) (s->vaddr);
|
||||
s->offset = strtoul(pbuffer+23,NULL,16);
|
||||
if (strcmp(linux_firstsegment, s->mappath) == 0) {
|
||||
s->base = 0;
|
||||
} else {
|
||||
s->base = s->vaddr;
|
||||
}
|
||||
s++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* WAD_LINUX */
|
||||
|
||||
static WadSegment *segments = 0; /* Linked list of segments */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_read()
|
||||
*
|
||||
* Read all of the memory segments into a linked list. Any previous segment
|
||||
* map is simply lost. The only way to reclaim this memory is to call
|
||||
* wad_release_memory().
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
wad_segment_read() {
|
||||
int fs;
|
||||
int n;
|
||||
WadSegment *s, *lasts;
|
||||
|
||||
segments = 0;
|
||||
lasts = 0;
|
||||
fs = segment_open();
|
||||
|
||||
while (1) {
|
||||
s = (WadSegment *) wad_malloc(sizeof(WadSegment));
|
||||
skip:
|
||||
n = segment_read(fs,s);
|
||||
if (n <= 0) break;
|
||||
if (wad_file_check(s->vaddr)) goto skip; /* Skip files we already loaded */
|
||||
s->next = 0;
|
||||
if (!lasts) {
|
||||
segments = s;
|
||||
lasts = s;
|
||||
} else {
|
||||
lasts->next = s;
|
||||
lasts = s;
|
||||
}
|
||||
if (wad_debug_mode & DEBUG_SEGMENT) {
|
||||
wad_printf("wad_segment: read : %08x-%08x, base=%x in %s\n", s->vaddr, ((char *) s->vaddr) + s->size, s->base, s->mappath);
|
||||
}
|
||||
}
|
||||
close(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_find()
|
||||
*
|
||||
* Try to find the virtual memory segment corresponding to a virtual address.
|
||||
* If a segment is mapped to a file, this function actually returns the *first*
|
||||
* segment that is mapped. This is because symbol relocations are always
|
||||
* performed relative to the beginning of the file (so we need the base address)
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadSegment *
|
||||
wad_segment_find(void *vaddr) {
|
||||
WadSegment *ls;
|
||||
WadSegment *s;
|
||||
char *addr = (char *)vaddr;
|
||||
|
||||
s = segments;
|
||||
ls = segments;
|
||||
while (s) {
|
||||
if (strcmp(s->mapname,ls->mapname) || (!strlen(ls->mapname))) {
|
||||
ls = s; /* First segment for a given name */
|
||||
}
|
||||
if ((addr >= s->vaddr) && (addr < (s->vaddr + s->size))) {
|
||||
if (wad_debug_mode & DEBUG_SEGMENT) {
|
||||
wad_printf("wad_segment: %08x --> %08x-%08x in %s\n", vaddr, s->vaddr, ((char *) s->vaddr) + s->size, s->mappath);
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_segment_valid()
|
||||
*
|
||||
* Checks to see if a memory address is valid or not based on data in the
|
||||
* segment map
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int wad_segment_valid(void *vaddr) {
|
||||
return wad_segment_find(vaddr) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,520 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* signal.c
|
||||
*
|
||||
* WAD signal handler.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
extern void wad_stab_debug();
|
||||
|
||||
/* For some odd reason, certain linux distributions do not seem to define the
|
||||
register constants in a way that is easily accessible to us. This is a hack */
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
#ifndef ESP
|
||||
#define ESP 7
|
||||
#endif
|
||||
#ifndef EBP
|
||||
#define EBP 6
|
||||
#endif
|
||||
#ifndef EIP
|
||||
#define EIP 14
|
||||
#endif
|
||||
#ifndef ESI
|
||||
#define ESI 5
|
||||
#endif
|
||||
#ifndef EDI
|
||||
#define EDI 4
|
||||
#endif
|
||||
#ifndef EBX
|
||||
#define EBX 8
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Signal handling stack */
|
||||
#define STACK_SIZE 4*SIGSTKSZ
|
||||
char wad_sig_stack[STACK_SIZE];
|
||||
|
||||
/* This variable is set if the signal handler thinks that the
|
||||
heap has overflowed */
|
||||
|
||||
int wad_heap_overflow = 0;
|
||||
|
||||
static void (*sig_callback)(int signo, WadFrame *data, char *ret) = 0;
|
||||
|
||||
void wad_set_callback(void (*s)(int,WadFrame *,char *ret)) {
|
||||
sig_callback = s;
|
||||
}
|
||||
|
||||
/* This bit of nastiness is used to make a non-local return from the
|
||||
signal handler to a configurable location on the call stack. In a nutshell,
|
||||
this works by repeatedly calling "restore" to roll back the
|
||||
register windows and stack pointer. Then we fake a return value and
|
||||
return to the caller as if the function had actually completed
|
||||
normally. */
|
||||
|
||||
int wad_nlr_levels = 0;
|
||||
static volatile int *volatile nlr_p = &wad_nlr_levels;
|
||||
long wad_nlr_value = 0;
|
||||
void (*wad_nlr_func)(void) = 0;
|
||||
|
||||
/* Set the return value from another module */
|
||||
void wad_set_return_value(long value) {
|
||||
wad_nlr_value = value;
|
||||
}
|
||||
|
||||
/* Set the return function */
|
||||
void wad_set_return_func(void(*f)(void)) {
|
||||
wad_nlr_func = f;
|
||||
}
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
static void nonlocalret() {
|
||||
long a;
|
||||
|
||||
a = wad_nlr_value;
|
||||
/* We never call this procedure as a function. This code
|
||||
causes an immediate return if someone does this */
|
||||
|
||||
asm("jmp %i7 + 8");
|
||||
asm("restore");
|
||||
|
||||
/* This is the real entry point */
|
||||
/* asm(".globl _returnsignal");*/
|
||||
asm(".type _returnsignal,2");
|
||||
asm("_returnsignal:");
|
||||
|
||||
while (*nlr_p > 0) {
|
||||
(*nlr_p)--;
|
||||
asm("restore");
|
||||
}
|
||||
|
||||
asm("sethi %hi(wad_nlr_value), %o0");
|
||||
asm("or %o0, %lo(wad_nlr_value), %o0");
|
||||
asm("ld [%o0], %i0");
|
||||
|
||||
/* If there is a non-local return function. We're going to go ahead
|
||||
and transfer control to it */
|
||||
|
||||
if (wad_nlr_func)
|
||||
(*wad_nlr_func)();
|
||||
|
||||
asm("jmp %i7 + 8");
|
||||
asm("restore");
|
||||
asm(".size _returnsignal,(.-_returnsignal)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
|
||||
/* Saved values of the machine registers */
|
||||
|
||||
long wad_saved_esi = 0;
|
||||
long wad_saved_edi = 0;
|
||||
long wad_saved_ebx = 0;
|
||||
|
||||
static void nonlocalret() {
|
||||
asm("_returnsignal:");
|
||||
while (*nlr_p > 0) {
|
||||
(*nlr_p)--;
|
||||
asm("leave");
|
||||
}
|
||||
|
||||
if (wad_nlr_func)
|
||||
(*wad_nlr_func)();
|
||||
|
||||
/* Restore the registers */
|
||||
asm("movl wad_saved_esi, %esi");
|
||||
asm("movl wad_saved_edi, %edi");
|
||||
asm("movl wad_saved_ebx, %ebx");
|
||||
asm("movl wad_nlr_value, %eax");
|
||||
asm("leave");
|
||||
asm("ret");
|
||||
}
|
||||
|
||||
/* This function uses a heuristic to restore the callee-save registers on i386.
|
||||
According to the Linux Assembly HOWTO, the %esi, %edi, %ebx, and %ebp registers
|
||||
are callee-saved. All others are caller saved. To restore the callee-save
|
||||
registers, we use the fact that the C compiler saves the callee-save registers
|
||||
(if any) at the beginning of function execution. Therefore, we can scan the
|
||||
instructions at the start of each function in the stack trace to try and find
|
||||
where they are.
|
||||
|
||||
The following heuristic is used:
|
||||
|
||||
1. Each function starts with a preamble like this which saves the %ebp
|
||||
register:
|
||||
|
||||
55 89 e5 ---> push %ebp
|
||||
mov %esp, %ebp
|
||||
|
||||
2. Next, space is allocated for local variables, using one of two schemes:
|
||||
|
||||
83 ec xx ---> Less than 256 bytes of local storage
|
||||
^^^
|
||||
length
|
||||
|
||||
81 ec xx xx xx xx --> More than 256 bytes of local storage
|
||||
^^^^^^^^^^^
|
||||
length
|
||||
|
||||
3. After this, a collection of 1-byte stack push op codes might appear
|
||||
|
||||
56 = pushl %esi
|
||||
57 = pushl %edi
|
||||
53 = pushl %ebx
|
||||
|
||||
|
||||
Based on the size of local variable storage and the order in which
|
||||
the %esi, %edi, and %ebx registers are pushed on the stack, we can
|
||||
determine where in memory the registers are saved and restore them to
|
||||
their proper values.
|
||||
*/
|
||||
|
||||
void wad_restore_i386_registers(WadFrame *f, int nlevels) {
|
||||
WadFrame *lastf = f;
|
||||
int localsize = 0;
|
||||
unsigned char *pc;
|
||||
unsigned long *saved;
|
||||
int i, j;
|
||||
int pci;
|
||||
for (i = 0; i <= nlevels; i++, f=f->next) {
|
||||
|
||||
/* This gets the starting instruction for the stack frame */
|
||||
pc = (unsigned char *) f->sym_base;
|
||||
/* printf("pc = %x, base = %x, %s\n", f->pc, f->sym_base, SYMBOL(f)); */
|
||||
if (!pc) continue;
|
||||
|
||||
/* Look for the standard prologue 0x55 0x89 0xe5 */
|
||||
if ((pc[0] == 0x55) && (pc[1] == 0x89) && (pc[2] == 0xe5)) {
|
||||
/* Determine the size */
|
||||
pci = 3;
|
||||
if ((pc[3] == 0x83) && (pc[4] == 0xec)) {
|
||||
/* printf("8-bit size\n");*/
|
||||
localsize = (int) pc[5];
|
||||
pci = 6;
|
||||
}
|
||||
if ((pc[3] == 0x81) && (pc[4] == 0xec)) {
|
||||
/* printf("32-bit size\n"); */
|
||||
localsize = (int) *((long *) (pc+5));
|
||||
pci = 10;
|
||||
}
|
||||
saved = (long *) (f->fp - localsize - sizeof(long));
|
||||
/* printf("saved = %x, fp = %x\n", saved, f->fp);
|
||||
printf("localsize = %d\n", localsize);
|
||||
*/
|
||||
for (j = 0; j < 3; j++, saved--, pci++) {
|
||||
if (pc[pci] == 0x57) {
|
||||
wad_saved_edi = *saved;
|
||||
/* printf("restored edi = %x\n", wad_saved_edi); */
|
||||
}
|
||||
else if (pc[pci] == 0x56) {
|
||||
wad_saved_esi = *saved;
|
||||
/* printf("restored esi = %x\n", wad_saved_esi); */
|
||||
}
|
||||
else if (pc[pci] == 0x53) {
|
||||
wad_saved_ebx = *saved;
|
||||
/* printf("restored ebx = %x\n", wad_saved_ebx); */
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void wad_signalhandler(int sig, siginfo_t *si, void *vcontext) {
|
||||
greg_t *pc;
|
||||
greg_t *npc;
|
||||
greg_t *sp;
|
||||
greg_t *fp;
|
||||
#ifdef WAD_LINUX
|
||||
greg_t *esi;
|
||||
greg_t *edi;
|
||||
greg_t *ebx;
|
||||
#endif
|
||||
|
||||
unsigned long addr;
|
||||
ucontext_t *context;
|
||||
unsigned long p_sp; /* process stack pointer */
|
||||
unsigned long p_pc; /* Process program counter */
|
||||
unsigned long p_fp; /* Process frame pointer */
|
||||
int nlevels = 0;
|
||||
int found = 0;
|
||||
void _returnsignal();
|
||||
WadFrame *frame, *origframe;
|
||||
char *framedata;
|
||||
char *retname = 0;
|
||||
unsigned long current_brk;
|
||||
|
||||
/* Reset all of the signals while running WAD */
|
||||
wad_signal_clear();
|
||||
|
||||
wad_nlr_func = 0;
|
||||
|
||||
context = (ucontext_t *) vcontext;
|
||||
|
||||
wad_printf("WAD: Collecting debugging information...\n");
|
||||
|
||||
/* Read the segments */
|
||||
if (wad_segment_read() < 0) {
|
||||
wad_printf("WAD: Unable to read segment map\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wad_debug_mode & DEBUG_SIGNAL) {
|
||||
wad_printf("WAD: siginfo = %x, context = %x\n", si, vcontext);
|
||||
}
|
||||
|
||||
current_brk = (long) sbrk(0);
|
||||
|
||||
/* Get some information about the current context */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
pc = &((context->uc_mcontext).gregs[REG_PC]);
|
||||
npc = &((context->uc_mcontext).gregs[REG_nPC]);
|
||||
sp = &((context->uc_mcontext).gregs[REG_SP]);
|
||||
#endif
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
sp = &((context->uc_mcontext).gregs[ESP]); /* Top of stack */
|
||||
fp = &((context->uc_mcontext).gregs[EBP]); /* Stack base - frame pointer */
|
||||
pc = &((context->uc_mcontext).gregs[EIP]); /* Current instruction */
|
||||
esi = &((context->uc_mcontext).gregs[ESI]);
|
||||
edi = &((context->uc_mcontext).gregs[EDI]);
|
||||
ebx = &((context->uc_mcontext).gregs[EBX]);
|
||||
|
||||
wad_saved_esi = (unsigned long) (*esi);
|
||||
wad_saved_edi = (unsigned long) (*edi);
|
||||
wad_saved_ebx = (unsigned long) (*ebx);
|
||||
|
||||
/* printf("esi = %x, edi = %x, ebx = %x\n", wad_saved_esi, wad_saved_edi, wad_saved_ebx); */
|
||||
|
||||
/* printf("&sp = %x, &pc = %x\n", sp, pc); */
|
||||
#endif
|
||||
|
||||
/* Get some information out of the signal handler stack */
|
||||
addr = (unsigned long) si->si_addr;
|
||||
|
||||
/* See if this might be a stack overflow */
|
||||
|
||||
p_pc = (unsigned long) (*pc);
|
||||
p_sp = (unsigned long) (*sp);
|
||||
#ifdef WAD_LINUX
|
||||
p_fp = (unsigned long) (*fp);
|
||||
#endif
|
||||
#ifdef WAD_SOLARIS
|
||||
p_fp = (unsigned long) *(((long *) p_sp) + 14);
|
||||
#endif
|
||||
|
||||
if (wad_debug_mode & DEBUG_SIGNAL) {
|
||||
wad_printf("fault at address %x, pc = %x, sp = %x, fp = %x\n", addr, p_pc, p_sp, p_fp);
|
||||
}
|
||||
frame = wad_stack_trace(p_pc, p_sp, p_fp);
|
||||
|
||||
if (!frame) {
|
||||
/* We're really hosed. Not possible to generate a stack trace */
|
||||
wad_printf("WAD: Unable to generate stack trace.\n");
|
||||
wad_printf("WAD: Maybe the call stack has been corrupted by buffer overflow.\n");
|
||||
wad_signal_clear();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
WadFrame *f = frame;
|
||||
while (f) {
|
||||
wad_find_object(f);
|
||||
wad_find_symbol(f);
|
||||
f = f->next;
|
||||
}
|
||||
f = frame;
|
||||
while (f) {
|
||||
wad_find_debug(f);
|
||||
wad_build_vars(f);
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
wad_heap_overflow = 0;
|
||||
if (sig == SIGSEGV) {
|
||||
if (addr >= current_brk) wad_heap_overflow = 1;
|
||||
}
|
||||
|
||||
wad_stack_debug(frame);
|
||||
|
||||
/* Generate debugging strings */
|
||||
wad_debug_make_strings(frame);
|
||||
|
||||
wad_stab_debug();
|
||||
|
||||
/* Walk the exception frames and try to find a return point */
|
||||
origframe = frame;
|
||||
while (frame) {
|
||||
WadReturnFunc *wr = wad_check_return(frame->sym_name);
|
||||
if (wr) {
|
||||
found = 1;
|
||||
wad_nlr_value = wr->value;
|
||||
retname = wr->name;
|
||||
}
|
||||
if (found) {
|
||||
frame->last = 1; /* Cut off top of the stack trace */
|
||||
break;
|
||||
}
|
||||
frame = frame->next;
|
||||
nlevels++;
|
||||
}
|
||||
|
||||
|
||||
if (found) {
|
||||
wad_nlr_levels = nlevels - 1;
|
||||
#ifdef WAD_LINUX
|
||||
wad_restore_i386_registers(origframe, wad_nlr_levels);
|
||||
#endif
|
||||
} else {
|
||||
wad_nlr_levels = -1;
|
||||
}
|
||||
|
||||
wad_string_debug();
|
||||
wad_memory_debug();
|
||||
|
||||
/* Before we do anything with callbacks, we are going
|
||||
to attempt to dump a wad-core */
|
||||
|
||||
{
|
||||
int fd;
|
||||
static int already = 0;
|
||||
fd = open("wadtrace",O_WRONLY | O_CREAT | (already*O_APPEND) | ((already==0)*O_TRUNC),0666);
|
||||
if (fd > 0) {
|
||||
wad_dump_trace(fd,sig,origframe,retname);
|
||||
close(fd);
|
||||
already=1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sig_callback) {
|
||||
(*sig_callback)(sig,origframe,retname);
|
||||
} else {
|
||||
/* No signal handler defined. Go invoke the default */
|
||||
|
||||
wad_default_callback(sig, origframe,retname);
|
||||
}
|
||||
|
||||
if (wad_debug_mode & DEBUG_HOLD) while(1);
|
||||
|
||||
/* If we found a function to which we should return, we jump to
|
||||
an alternative piece of code that unwinds the stack and
|
||||
initiates a non-local return. */
|
||||
|
||||
if (wad_nlr_levels >= 0) {
|
||||
*(pc) = (greg_t) _returnsignal;
|
||||
#ifdef WAD_SOLARIS
|
||||
*(npc) = *(pc) + 4;
|
||||
#endif
|
||||
if (!(wad_debug_mode & DEBUG_ONESHOT)) {
|
||||
wad_signal_init();
|
||||
}
|
||||
return;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_signal_init()
|
||||
*
|
||||
* Resets the signal handler.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_signal_init() {
|
||||
struct sigaction newvec;
|
||||
static stack_t sigstk;
|
||||
static int initstack = 0;
|
||||
|
||||
if (wad_debug_mode & DEBUG_INIT) {
|
||||
wad_printf("WAD: Initializing signal handler.\n");
|
||||
}
|
||||
/* This is buggy in Linux and threads. disabled by default */
|
||||
|
||||
#ifndef WAD_LINUX
|
||||
|
||||
if (!initstack) {
|
||||
/* Set up an alternative stack */
|
||||
|
||||
sigstk.ss_sp = (char *) wad_sig_stack;
|
||||
sigstk.ss_size = STACK_SIZE;
|
||||
sigstk.ss_flags = 0;
|
||||
if (!(wad_debug_mode & DEBUG_NOSTACK)) {
|
||||
if (sigaltstack(&sigstk, (stack_t*)0) < 0) {
|
||||
perror("sigaltstack");
|
||||
}
|
||||
}
|
||||
initstack=1;
|
||||
}
|
||||
#endif
|
||||
|
||||
sigemptyset(&newvec.sa_mask);
|
||||
sigaddset(&newvec.sa_mask, SIGSEGV);
|
||||
sigaddset(&newvec.sa_mask, SIGBUS);
|
||||
sigaddset(&newvec.sa_mask, SIGABRT);
|
||||
sigaddset(&newvec.sa_mask, SIGILL);
|
||||
sigaddset(&newvec.sa_mask, SIGFPE);
|
||||
newvec.sa_flags = SA_SIGINFO;
|
||||
|
||||
if (wad_debug_mode & DEBUG_ONESHOT) {
|
||||
newvec.sa_flags |= SA_RESETHAND;
|
||||
}
|
||||
#ifndef WAD_LINUX
|
||||
if (!(wad_debug_mode & DEBUG_NOSTACK)) {
|
||||
newvec.sa_flags |= SA_ONSTACK;
|
||||
}
|
||||
#endif
|
||||
newvec.sa_sigaction = ((void (*)(int,siginfo_t *, void *)) wad_signalhandler);
|
||||
if (sigaction(SIGSEGV, &newvec, NULL) < 0) goto werror;
|
||||
if (sigaction(SIGBUS, &newvec, NULL) < 0) goto werror;
|
||||
if (sigaction(SIGABRT, &newvec, NULL) < 0) goto werror;
|
||||
if (sigaction(SIGFPE, &newvec, NULL) < 0) goto werror;
|
||||
if (sigaction(SIGILL, &newvec, NULL) < 0) goto werror;
|
||||
|
||||
return;
|
||||
werror:
|
||||
wad_printf("WAD: Couldn't install signal handler!\n");
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* clear signals
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_signal_clear() {
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,682 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* stab.c
|
||||
*
|
||||
* This file reads stabs data and looks for various properties of a
|
||||
* given symbol.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* stabs data structure. This appears to be somewhat universal. */
|
||||
typedef struct Stab {
|
||||
unsigned n_strx; /* index into file string table */
|
||||
unsigned char n_type; /* type flag (N_TEXT,..) */
|
||||
char n_other; /* used by N_SLINE stab */
|
||||
unsigned short n_desc; /* see stabs documentation */
|
||||
unsigned n_value; /* value of symbol (or sdb offset) */
|
||||
} Stab;
|
||||
|
||||
/* stabs data types used by this module */
|
||||
|
||||
#define N_UNDF 0x0 /* undefined */
|
||||
#define N_FUN 0x24 /* function */
|
||||
#define N_OBJ 0x38 /* object file path */
|
||||
#define N_RSYM 0x40 /* Register symbol */
|
||||
#define N_SLINE 0x44 /* Source line */
|
||||
#define N_SO 0x64 /* Source file name */
|
||||
#define N_LSYM 0x80 /* Local symbol */
|
||||
#define N_PSYM 0xa0 /* Parameter */
|
||||
#define N_LBRAC 0xc0 /* Left brace */
|
||||
#define N_RBRAC 0xe0 /* Right brace */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* stabs type handler
|
||||
*
|
||||
* Type names are defined as N_LSYM types. We need to keep a hash table of
|
||||
* logical type names and stabs type names.
|
||||
*
|
||||
* We also need to keep a hash table of stabs types.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct stabtype {
|
||||
char *name;
|
||||
char *value;
|
||||
struct stabtype *next;
|
||||
int visit;
|
||||
} stabtype;
|
||||
|
||||
#define HASH_SIZE 113
|
||||
|
||||
static int stab_type_init = 0;
|
||||
static stabtype *lnames[HASH_SIZE]; /* Hash of local names */
|
||||
static stabtype *deadnames[HASH_SIZE]; /* Hash of dead names */
|
||||
|
||||
/* Initialize the hash table */
|
||||
|
||||
static void init_hash() {
|
||||
int i;
|
||||
stabtype *s, *sp = 0;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
if (stab_type_init) {
|
||||
/* Add stabs to dead list */
|
||||
s = lnames[i];
|
||||
sp = 0;
|
||||
while (s) {
|
||||
sp = s;
|
||||
s = s->next;
|
||||
}
|
||||
if (sp) {
|
||||
sp->next = deadnames[i];
|
||||
deadnames[i] = lnames[i];
|
||||
}
|
||||
}
|
||||
lnames[i] = 0;
|
||||
}
|
||||
stab_type_init = 1;
|
||||
}
|
||||
|
||||
static int thash(char *name) {
|
||||
unsigned int h = 0;
|
||||
int i;
|
||||
for (i = 0; i < 8 && (*name); i++, name++) {
|
||||
h = ((h << 7) + *name);
|
||||
}
|
||||
return (h % HASH_SIZE);
|
||||
}
|
||||
|
||||
/* Add a symbol to the hash */
|
||||
|
||||
static void type_add(char *name, char *value) {
|
||||
int h;
|
||||
stabtype *s;
|
||||
char sc =0;
|
||||
char *v;
|
||||
char *vr;
|
||||
char *split;
|
||||
|
||||
if (!stab_type_init) {
|
||||
init_hash();
|
||||
stab_type_init = 1;
|
||||
}
|
||||
|
||||
/* Split the "value" up into a type name and a value */
|
||||
|
||||
split = strchr(value,'=');
|
||||
if (value[0] != '(') split = 0;
|
||||
if (split) {
|
||||
sc = *split;
|
||||
v = value;
|
||||
*split = 0;
|
||||
vr = split+1;
|
||||
} else {
|
||||
v = value;
|
||||
sc = 0;
|
||||
vr = 0;
|
||||
}
|
||||
|
||||
h = thash(name);
|
||||
s = lnames[h];
|
||||
while (s) {
|
||||
if (strcmp(s->name,name) == 0) {
|
||||
if (strcmp(s->value,v)) {
|
||||
s->value = wad_string_lookup(v);
|
||||
}
|
||||
goto add_more;
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
s = deadnames[h];
|
||||
if (!s) {
|
||||
s = (stabtype *) wad_malloc(sizeof(stabtype));
|
||||
} else {
|
||||
deadnames[h] = s->next;
|
||||
}
|
||||
s->name = wad_string_lookup(name);
|
||||
s->value = wad_string_lookup(v);
|
||||
s->next = lnames[h];
|
||||
s->visit = 0;
|
||||
lnames[h] = s;
|
||||
|
||||
/* Now take a look at the value. If it is contains other types, we might be able to define more stuff */
|
||||
add_more:
|
||||
if (vr) {
|
||||
/* There is a mapping to another type */
|
||||
type_add(v,vr);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
char *type_resolve(char *name) {
|
||||
int h;
|
||||
stabtype *s;
|
||||
h = thash(name);
|
||||
s = lnames[h];
|
||||
while(s) {
|
||||
if (strcmp(s->name,name) == 0) {
|
||||
if (!s->visit) {
|
||||
char *c;
|
||||
/* The visit flag is set so that we don't get in infinite loops */
|
||||
s->visit = 1;
|
||||
c = type_resolve(s->value);
|
||||
s->visit = 0;
|
||||
return c;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/* This function tries to resolve base stabs types into a machine equivalent */
|
||||
static
|
||||
int type_typecode(char *name) {
|
||||
char *range;
|
||||
|
||||
if (name[0] == '*') {
|
||||
return WAD_TYPE_POINTER;
|
||||
}
|
||||
|
||||
range = strchr(name,';');
|
||||
if (!range) return WAD_TYPE_UNKNOWN;
|
||||
range++;
|
||||
|
||||
if (name[0] == 'r') {
|
||||
/* GNU-style range specifiers */
|
||||
if (
|
||||
(strcmp(range,"0000000000000;0037777777777;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_UINT32;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"0020000000000;0017777777777;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_INT32;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"-32768;32767;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_INT16;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"0;65535;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_UINT16;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"0;127;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_CHAR;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"-128;127;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_INT8;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"0;255;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_UINT8;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"4;0;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_FLOAT;
|
||||
}
|
||||
if (
|
||||
(strcmp(range,"8;0;") == 0)
|
||||
) {
|
||||
return WAD_TYPE_DOUBLE;
|
||||
}
|
||||
}
|
||||
/* Traditional built-in types */
|
||||
if (strcmp(name,"bs4;0;32;") == 0) {
|
||||
return WAD_TYPE_INT32;
|
||||
}
|
||||
if (strcmp(name,"bs2;0;16;") == 0) {
|
||||
return WAD_TYPE_INT16;
|
||||
}
|
||||
if (strcmp(name,"bs1;0;8;") == 0) {
|
||||
return WAD_TYPE_INT8;
|
||||
}
|
||||
if (strcmp(name,"bsc1;0;8;") == 0) {
|
||||
return WAD_TYPE_CHAR;
|
||||
}
|
||||
if (strcmp(name,"bu4;0;32;") == 0) {
|
||||
return WAD_TYPE_UINT32;
|
||||
}
|
||||
if (strcmp(name,"bu2;0;16;") == 0) {
|
||||
return WAD_TYPE_UINT16;
|
||||
}
|
||||
if (strcmp(name,"bu1;0;8;") == 0) {
|
||||
return WAD_TYPE_UINT8;
|
||||
}
|
||||
if (strcmp(name,"R1;4;") == 0) {
|
||||
return WAD_TYPE_FLOAT;
|
||||
}
|
||||
if (strcmp(name,"R2;8;") == 0) {
|
||||
return WAD_TYPE_DOUBLE;
|
||||
}
|
||||
return WAD_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static void types_print() {
|
||||
stabtype *s;
|
||||
int i;
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
s = lnames[i];
|
||||
while (s) {
|
||||
wad_printf("%20s %s\n", s->name, s->value);
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wad_stab_debug() {
|
||||
/* types_print();*/
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* match_stab_symbol()
|
||||
*
|
||||
* Match a stabs symbol name against a stab string. The stab string may contain
|
||||
* extra information delimited by a colon which is not used in the comparsion.
|
||||
* Returns 1 on match, 0 on mismatch.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
match_stab_symbol(char *symbol, char *stabtext, int slen) {
|
||||
if (strcmp(symbol,stabtext) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((strncmp(symbol, stabtext, slen) == 0) && (*(stabtext+slen) == ':')) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
stab_string_parm(char *str) {
|
||||
return strchr(str,':');
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* stab_symbol(Stab *s, char *stabstr)
|
||||
*
|
||||
* Process stab symbol specifier N_LSYM
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
stab_symbol(Stab *s, char *stabstr) {
|
||||
char *str;
|
||||
char *pstr;
|
||||
char name[1024];
|
||||
char value[65536];
|
||||
|
||||
str = stabstr+s->n_strx;
|
||||
pstr = stab_string_parm(str);
|
||||
if (!pstr) return;
|
||||
|
||||
strncpy(name,str, pstr-str);
|
||||
name[(int)(pstr-str)] = 0;
|
||||
if ((pstr[1] == 't') || (pstr[1] == 'p') || (pstr[1] == 'r')) {
|
||||
/* A stabs type definition */
|
||||
/* printf("stab lsym: other=%d, desc=%d, value=%d, str='%s'\n", s->n_other,s->n_desc,s->n_value,
|
||||
stabstr+s->n_strx); */
|
||||
/* wad_printf("name = '%s', pstr='%s'\n", name, pstr+2); */
|
||||
wad_strcpy(value,pstr+2);
|
||||
type_add(name,value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* scan_function()
|
||||
*
|
||||
* Collect stabs data for a function definition.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
scan_function(Stab *s, char *stabstr, int ns, WadFrame *f) {
|
||||
int i;
|
||||
unsigned long offset;
|
||||
int get_parms = 1;
|
||||
int nbrace = 0;
|
||||
|
||||
offset = f->pc - f->sym_base;
|
||||
if (wad_debug_mode & DEBUG_STABS) {
|
||||
wad_printf("---[ %s ] --------------\n", f->sym_name);
|
||||
}
|
||||
|
||||
for (i = 0; i < ns; i++,s++) {
|
||||
if (wad_debug_mode & DEBUG_STABS) {
|
||||
wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
||||
stabstr+s->n_strx);
|
||||
|
||||
}
|
||||
|
||||
if ((s->n_type == N_UNDF) || (s->n_type == N_SO) || /* (s->n_type == N_FUN) || */
|
||||
(s->n_type == N_OBJ)) return i;
|
||||
|
||||
if ((s->n_type == N_FUN) && !(strlen(stabstr+s->n_strx))) return 1;
|
||||
|
||||
if (s->n_type == N_LBRAC) {
|
||||
nbrace++;
|
||||
get_parms = 0;
|
||||
}
|
||||
if (s->n_type == N_RBRAC) {
|
||||
nbrace--;
|
||||
if (nbrace <= 0) return i;
|
||||
}
|
||||
/* Local variable declaration */
|
||||
|
||||
if (s->n_type == N_LSYM) {
|
||||
/* This might be a local variable definition */
|
||||
/* wad_printf("local: n_value = %d, offset = %d\n", s->n_value, offset);*/
|
||||
if (s->n_desc <= f->loc_line)
|
||||
{
|
||||
/* Okay. We can pay attention to it */
|
||||
char *pname;
|
||||
char *c;
|
||||
int len;
|
||||
WadLocal *arg, *a;
|
||||
pname = stabstr+s->n_strx;
|
||||
c = strchr(pname,':');
|
||||
if (*(c+1) != '(') continue;
|
||||
if (c) {
|
||||
len = (c-pname);
|
||||
} else {
|
||||
len = strlen(pname);
|
||||
}
|
||||
/* printf("local\n"); */
|
||||
stab_symbol(s,stabstr);
|
||||
a = f->debug_locals;
|
||||
while (a) {
|
||||
if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
|
||||
/* We already saw this argument. Given a choice between a register and a stack
|
||||
argument. We will choose the stack version */
|
||||
a->loc = PARM_STACK;
|
||||
a->stack = s->n_value;
|
||||
break;
|
||||
}
|
||||
a = a->next;
|
||||
}
|
||||
if (a) continue; /* We got an argument match. Just skip to the next stab */
|
||||
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
|
||||
{
|
||||
char t = pname[len];
|
||||
pname[len] = 0;
|
||||
arg->name = wad_string_lookup(pname);
|
||||
pname[len] = t;
|
||||
}
|
||||
arg->loc = PARM_STACK;
|
||||
arg->line = s->n_desc;
|
||||
arg->stack = s->n_value;
|
||||
arg->type = 0;
|
||||
arg->next = 0;
|
||||
{
|
||||
char tname[128];
|
||||
char *t = tname;
|
||||
|
||||
c+=1;
|
||||
while ((*c) && (*c != '=')) {
|
||||
*t++ = *c++;
|
||||
}
|
||||
*t = 0;
|
||||
t = type_resolve(tname);
|
||||
arg->type = type_typecode(t);
|
||||
if (wad_debug_mode & DEBUG_STABS) {
|
||||
wad_printf("type_resolve '%s' -> '%s' (%d)\n", tname, t, arg->type);
|
||||
}
|
||||
}
|
||||
if (f->debug_locals) {
|
||||
f->debug_lastlocal->next = arg;
|
||||
f->debug_lastlocal = arg;
|
||||
} else {
|
||||
f->debug_locals = arg;
|
||||
f->debug_lastlocal = arg;
|
||||
f->debug_nlocals= 0;
|
||||
}
|
||||
f->debug_nlocals++;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->n_type == N_SLINE) {
|
||||
get_parms = 0;
|
||||
if (s->n_value <= offset) {
|
||||
f->loc_line = s->n_desc;
|
||||
}
|
||||
} else if (((s->n_type == N_PSYM) || (s->n_type == N_RSYM)) && get_parms) {
|
||||
/* Parameter counting */
|
||||
char *pname;
|
||||
char *c;
|
||||
int len;
|
||||
WadLocal *arg;
|
||||
pname = stabstr+s->n_strx;
|
||||
c = strchr(pname,':');
|
||||
if (c) {
|
||||
len = (c-pname);
|
||||
} else {
|
||||
len = strlen(pname);
|
||||
}
|
||||
/* Get type information */
|
||||
|
||||
stab_symbol(s,stabstr);
|
||||
|
||||
/* Check if the argument was already used */
|
||||
/* In this case, the first stab simply identifies an argument. The second
|
||||
one identifies its location for the debugger */
|
||||
|
||||
{
|
||||
/* Need to do some fix up for linux here */
|
||||
WadLocal *a = f->debug_args;
|
||||
while (a) {
|
||||
if ((strncmp(a->name,pname,len) == 0) && (strlen(a->name) == len)) {
|
||||
/* We already saw this argument. Given a choice between a register and a stack
|
||||
argument. We will choose the stack version */
|
||||
|
||||
if (a->loc == PARM_STACK) {
|
||||
break;
|
||||
}
|
||||
/* Go ahead and use the new argument */
|
||||
if (s->n_type == N_RSYM) {
|
||||
a->loc = PARM_REGISTER;
|
||||
a->reg = s->n_value;
|
||||
} else {
|
||||
a->loc = PARM_STACK;
|
||||
a->stack = s->n_value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
a = a->next;
|
||||
}
|
||||
if (a) continue; /* We got an argument match. Just skip to the next stab */
|
||||
}
|
||||
|
||||
arg = (WadLocal *) wad_malloc(sizeof(WadLocal));
|
||||
{
|
||||
char t = pname[len];
|
||||
pname[len] = 0;
|
||||
arg->name = wad_string_lookup(pname);
|
||||
pname[len] = t;
|
||||
}
|
||||
if (s->n_type == N_RSYM) {
|
||||
arg->loc = PARM_REGISTER;
|
||||
arg->reg = s->n_value;
|
||||
arg->stack = 0;
|
||||
} else {
|
||||
arg->loc = PARM_STACK;
|
||||
arg->line = s->n_desc;
|
||||
arg->stack = s->n_value;
|
||||
}
|
||||
arg->type = 0;
|
||||
arg->next = 0;
|
||||
{
|
||||
char tname[128];
|
||||
char *t = tname;
|
||||
|
||||
c+=2;
|
||||
while ((*c) && (*c != '=')) {
|
||||
*t++ = *c++;
|
||||
}
|
||||
*t = 0;
|
||||
t = type_resolve(tname);
|
||||
arg->type = type_typecode(t);
|
||||
if (wad_debug_mode & DEBUG_STABS) {
|
||||
wad_printf("type_resolve '%s' -> '%s' (%d)\n", tname, t, arg->type);
|
||||
}
|
||||
}
|
||||
if (f->debug_args) {
|
||||
f->debug_lastarg->next = arg;
|
||||
f->debug_lastarg = arg;
|
||||
} else {
|
||||
f->debug_args = arg;
|
||||
f->debug_lastarg = arg;
|
||||
f->debug_nargs= 0;
|
||||
}
|
||||
f->debug_nargs++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Given a stabs data segment (obtained somehow), this function tries to
|
||||
collect as much information as it can about a given symbol.
|
||||
|
||||
s points to the stab data. stabstr points to the stab string section,
|
||||
ns is the size of the stab section, symbol is the item of interest,
|
||||
and offset is the offset in the object file of the symbol
|
||||
|
||||
Note: this function may recurse upon itself if there are multiple
|
||||
stabs sections.
|
||||
|
||||
Note: If a symbol corresponds to a local symbol, it's entirely possible
|
||||
that the only stabs data we will find is a file specifier. In this case,
|
||||
*/
|
||||
|
||||
int
|
||||
wad_search_stab(void *sp, int size, char *stabstr, WadFrame *f) {
|
||||
Stab *s;
|
||||
int ns;
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
char *file, *lastfile = 0;
|
||||
|
||||
char srcfile[MAX_PATH];
|
||||
char objfile[MAX_PATH];
|
||||
|
||||
/* It appears to be necessary to clear the types table on each new stabs section */
|
||||
|
||||
init_hash();
|
||||
|
||||
if (!f->sym_name) return 0;
|
||||
|
||||
s = (Stab *) sp; /* Stabs data */
|
||||
ns = size/sizeof(Stab); /* number of stabs */
|
||||
|
||||
srcfile[0] = 0;
|
||||
objfile[0] = 0;
|
||||
|
||||
for (i = 0; i < ns; i++, s++) {
|
||||
if (wad_debug_mode & DEBUG_STABS) {
|
||||
/* wad_printf(" %10d %10x %10d %10d %10d: '%s'\n", s->n_strx, s->n_type, s->n_other, s->n_desc, s->n_value,
|
||||
stabstr+s->n_strx); */
|
||||
|
||||
}
|
||||
if (s->n_type == N_LSYM) {
|
||||
stab_symbol(s,stabstr);
|
||||
continue;
|
||||
}
|
||||
if ((s->n_type == N_UNDF)) { /* && (s->n_desc >= 0)) { */
|
||||
/* New stabs section. We need to be a little careful here. Do a recursive
|
||||
search of the subsection. */
|
||||
|
||||
if (wad_search_stab(s+1,s->n_desc*sizeof(Stab), stabstr, f)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* On solaris, each stabs section seems to increment the stab string pointer. On Linux,
|
||||
the linker seems to do a certain amount of optimization that results in a single
|
||||
string table. */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
stabstr += s->n_value; /* Update the string table location*/
|
||||
#endif
|
||||
i += s->n_desc;
|
||||
s += s->n_desc;
|
||||
objfile[0] = 0;
|
||||
srcfile[0] = 0;
|
||||
continue;
|
||||
} else if (s->n_type == N_SO) {
|
||||
/* Source file specification */
|
||||
/* Look for directory */
|
||||
file = stabstr+s->n_strx;
|
||||
if (strlen(file) && (file[strlen(file)-1] == '/')) {
|
||||
wad_strcpy(srcfile,file);
|
||||
} else {
|
||||
wad_strcat(srcfile,file);
|
||||
}
|
||||
objfile[0] = 0;
|
||||
/* If we have a file match, we might be looking for a local symbol. If so,
|
||||
we'll go ahead and set the srcfile field of the frame */
|
||||
|
||||
/* We're going to check for a file match. Maybe we're looking for a local symbol */
|
||||
if (f->sym_file && strcmp(f->sym_file,file) == 0) {
|
||||
found = 1;
|
||||
}
|
||||
lastfile = file;
|
||||
} else if (s->n_type == N_OBJ) {
|
||||
/* Object file specifier */
|
||||
if (objfile[0]) {
|
||||
wad_strcat(objfile,"/");
|
||||
}
|
||||
wad_strcat(objfile,stabstr+s->n_strx);
|
||||
} else if (s->n_type == N_FUN) {
|
||||
if (match_stab_symbol(f->sym_name, stabstr+s->n_strx, f->sym_nlen)) {
|
||||
if (!f->sym_file || (strcmp(f->sym_file,lastfile) == 0)) {
|
||||
int n;
|
||||
/* Go find debugging information for the function */
|
||||
n = scan_function(s+1, stabstr, ns -i - 1, f);
|
||||
f->loc_srcfile = wad_string_lookup(srcfile);
|
||||
f->loc_objfile = wad_string_lookup(objfile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If found, but no other debugging information was filled in, go ahead and copy the
|
||||
source and objfile information */
|
||||
|
||||
if ((found) && (!f->debug_check)) {
|
||||
f->loc_srcfile = wad_string_lookup(srcfile);
|
||||
f->loc_objfile = wad_string_lookup(objfile);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* stack.c
|
||||
*
|
||||
* This file unwinds the C call stack and creates a list of stack frames.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* new_frame()
|
||||
*
|
||||
* Create a new stack frame object and initialize all of the fields.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static WadFrame *
|
||||
new_frame() {
|
||||
WadFrame *f;
|
||||
f = (WadFrame *) wad_malloc(sizeof(WadFrame));
|
||||
f->frameno = 0;
|
||||
f->segment = 0;
|
||||
f->object = 0;
|
||||
f->pc = 0;
|
||||
f->sp = 0;
|
||||
f->sp = 0;
|
||||
f->stack = 0;
|
||||
f->stack_size = 0;
|
||||
|
||||
f->sym_name = 0;
|
||||
f->sym_nlen = 0;
|
||||
f->sym_file = 0;
|
||||
f->sym_base = 0;
|
||||
f->sym_size = 0;
|
||||
f->sym_type = 0;
|
||||
f->sym_bind = 0;
|
||||
|
||||
f->loc_objfile = 0;
|
||||
f->loc_srcfile = 0;
|
||||
f->loc_line = 0;
|
||||
|
||||
f->debug_check = 0;
|
||||
f->debug_nargs = -1;
|
||||
f->debug_args = 0;
|
||||
f->debug_lastarg = 0;
|
||||
f->debug_nlocals = 0;
|
||||
f->debug_locals = 0;
|
||||
f->debug_lastlocal = 0;
|
||||
f->debug_str = 0;
|
||||
f->debug_srcstr = 0;
|
||||
|
||||
f->last = 0;
|
||||
f->next = 0;
|
||||
f->prev = 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* stack_unwind()
|
||||
*
|
||||
* This function performs a single level of stack unwinding given the stack pointer
|
||||
* frame pointer and program counter. Validations are made to make sure the stack
|
||||
* and frame pointers are in valid memory. Updates the values of the sp, pc, and fp
|
||||
* in-place. Returns a stack frame object on success, 0 if memory is invalid
|
||||
* or the end of the stack has been reached.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static WadFrame *
|
||||
stack_unwind(unsigned long *pc, unsigned long *sp, unsigned long *fp) {
|
||||
WadSegment *sp_seg, *fp_seg;
|
||||
WadFrame *f;
|
||||
unsigned long fake_fp;
|
||||
|
||||
if (wad_debug_mode & DEBUG_UNWIND) {
|
||||
wad_printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
|
||||
}
|
||||
|
||||
/* Verify that the sp and fp are in mapped memory */
|
||||
sp_seg = wad_segment_find((void *) *sp);
|
||||
fp_seg = wad_segment_find((void *) *fp);
|
||||
|
||||
/* Make sure the stack pointer is in memory */
|
||||
if (!sp_seg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fp_seg) {
|
||||
/* Hmmm. If no frame pointer, we must be off the top of the call stack */
|
||||
fake_fp = (unsigned long) (sp_seg->vaddr + sp_seg->size);
|
||||
fp_seg = sp_seg;
|
||||
} else {
|
||||
fake_fp = *fp;
|
||||
}
|
||||
if (sp_seg != fp_seg) {
|
||||
/* Whoa. Stack pointer and frame pointer are in different memory segments. */
|
||||
wad_printf("WAD: Warning. Stack pointer and frame pointer are in different regions.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check to see if the PC is valid */
|
||||
if (!wad_segment_valid((void *) *pc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
f = new_frame();
|
||||
f->pc = *pc;
|
||||
f->sp = *sp;
|
||||
f->fp = fake_fp;
|
||||
f->segment = wad_segment_find((void *) *pc);
|
||||
f->stack_size = fake_fp - *sp;
|
||||
/* Make a copy of the call stack */
|
||||
f->stack = (char *) wad_malloc(f->stack_size);
|
||||
wad_memcpy(f->stack,(void *) *sp, f->stack_size);
|
||||
|
||||
/* Update the sp, fp, and pc */
|
||||
|
||||
#ifdef WAD_SOLARIS
|
||||
*pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
|
||||
*sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
|
||||
if (wad_segment_valid((void *) *sp)) {
|
||||
*fp = *((unsigned long *) *sp+14);
|
||||
} else {
|
||||
*fp = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WAD_LINUX
|
||||
if (wad_segment_valid((void *) ((unsigned long *) *fp+1))) {
|
||||
*pc = *((unsigned long *) *fp+1);
|
||||
*sp = *fp;
|
||||
} else {
|
||||
*sp = 0;
|
||||
}
|
||||
if (wad_segment_valid((void *) ((unsigned long *) *fp))) {
|
||||
*fp = *((unsigned long *) *fp);
|
||||
} else {
|
||||
*fp = 0;
|
||||
}
|
||||
#endif
|
||||
return f;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_stack_trace()
|
||||
*
|
||||
* Create a stack trace of the process. Returns a linked list of stack frames
|
||||
* with a limited about debugging information and other details.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
WadFrame *
|
||||
wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
|
||||
WadFrame *firstframe=0, *lastframe=0, *frame=0;
|
||||
unsigned long p_pc;
|
||||
unsigned long p_sp;
|
||||
unsigned long p_fp;
|
||||
int n = 0;
|
||||
|
||||
/* Try to do a stack traceback */
|
||||
|
||||
p_pc = pc;
|
||||
p_sp = sp;
|
||||
p_fp = fp;
|
||||
|
||||
while ((frame = stack_unwind(&p_pc, &p_sp, &p_fp))) {
|
||||
/* Got a frame successfully */
|
||||
frame->frameno = n;
|
||||
if (lastframe) {
|
||||
lastframe->next = frame;
|
||||
frame->prev = lastframe;
|
||||
lastframe = frame;
|
||||
} else {
|
||||
firstframe = frame;
|
||||
lastframe = frame;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
if (lastframe)
|
||||
lastframe->last = 1;
|
||||
return firstframe;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_stack_debug()
|
||||
*
|
||||
* Make a dump of a stack trace
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_stack_debug(WadFrame *frame) {
|
||||
if (wad_debug_mode & DEBUG_STACK) {
|
||||
/* Walk the exception frames and try to find a return point */
|
||||
while (frame) {
|
||||
/* Print out detailed stack trace information */
|
||||
wad_printf("::: Stack frame - 0x%08x :::\n", frame);
|
||||
wad_printf(" pc = %x\n", frame->pc);
|
||||
wad_printf(" sp = %x\n", frame->sp);
|
||||
wad_printf(" fp = %x\n", frame->fp);
|
||||
wad_printf(" stack = %x\n", frame->stack);
|
||||
wad_printf(" size = %x\n", frame->stack_size);
|
||||
wad_printf(" segment = %x (%s)\n", frame->segment, frame->segment ? frame->segment->mappath : "?");
|
||||
wad_printf(" object = %x (%s)\n", frame->object, frame->object ? frame->object->path : "?");
|
||||
|
||||
if (frame->sym_name) {
|
||||
wad_printf(" sym_name = %s\n", frame->sym_name);
|
||||
wad_printf(" sym_base = %x\n", frame->sym_base);
|
||||
wad_printf(" sym_size = %x\n", frame->sym_size);
|
||||
wad_printf(" sym_bind = %x\n", frame->sym_bind);
|
||||
wad_printf(" sym_file = %s\n", frame->sym_file ? frame->sym_file : "");
|
||||
}
|
||||
|
||||
if (frame->loc_srcfile) {
|
||||
wad_printf(" loc_srcfile = %s\n", frame->loc_srcfile);
|
||||
}
|
||||
|
||||
if (frame->loc_objfile) {
|
||||
wad_printf(" loc_objfile = %s\n", frame->loc_objfile);
|
||||
}
|
||||
wad_printf(" loc_line = %d\n", frame->loc_line);
|
||||
|
||||
|
||||
wad_printf(" debug_nargs = %d\n", frame->debug_nargs);
|
||||
if (frame->debug_args) {
|
||||
int i = 0;
|
||||
WadLocal *p = frame->debug_args;
|
||||
wad_printf(" debug_args = [ \n");
|
||||
while (p) {
|
||||
wad_printf(" arg[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
wad_printf(" ]\n");
|
||||
|
||||
wad_printf(" debug_nlocal = %d\n", frame->debug_nlocals);
|
||||
if (frame->debug_locals) {
|
||||
int i = 0;
|
||||
WadLocal *p = frame->debug_locals;
|
||||
wad_printf(" debug_locals = [ \n");
|
||||
while (p) {
|
||||
wad_printf(" loc[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
wad_printf(" ]\n");
|
||||
|
||||
frame = frame->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_steal_outarg()
|
||||
*
|
||||
* Steal an output argument
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
long
|
||||
wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
|
||||
long *regs;
|
||||
WadFrame *lastf = 0;
|
||||
|
||||
*error = 0;
|
||||
/* Start searching */
|
||||
while (f) {
|
||||
if (f->sym_name && (strcmp(f->sym_name,symbol) == 0)) {
|
||||
/* Got a match */
|
||||
if (lastf) {
|
||||
#ifdef WAD_SOLARIS
|
||||
regs = (long *) lastf->stack;
|
||||
return regs[8+argno];
|
||||
#endif
|
||||
#ifdef WAD_LINUX
|
||||
regs = (long *) f->stack;
|
||||
return regs[argno+2];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
lastf = f;
|
||||
f = f->next;
|
||||
}
|
||||
*error = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* string.c
|
||||
*
|
||||
* This file provides support for string storage in WAD. Since strings are
|
||||
* used frequently in WAD, this file implements string interning and
|
||||
* some lookup functions that can be used to return a previously stored
|
||||
* string rather than making a new copy.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* Hash table containing stab strings and such */
|
||||
typedef struct stringtype {
|
||||
char *str;
|
||||
struct stringtype *next;
|
||||
} stringtype;
|
||||
|
||||
#define STRING_HASH_SIZE 1013
|
||||
|
||||
static stringtype *strings[STRING_HASH_SIZE];
|
||||
static int strings_init = 0;
|
||||
|
||||
static int shash(char *name) {
|
||||
unsigned int h = 0;
|
||||
char *c;
|
||||
int i;
|
||||
c = name;
|
||||
for (i = 0; (i < 16) && (*c); i++, c++) {
|
||||
h = ((h^~i) << 6) + *c;
|
||||
}
|
||||
return h % STRING_HASH_SIZE;
|
||||
}
|
||||
|
||||
char *
|
||||
wad_string_lookup(char *s) {
|
||||
int h;
|
||||
int i;
|
||||
stringtype *st;
|
||||
|
||||
if (!strings_init) {
|
||||
for (i = 0; i < STRING_HASH_SIZE; i++) {
|
||||
strings[i] = 0;
|
||||
}
|
||||
strings_init = 1;
|
||||
}
|
||||
|
||||
h = shash(s);
|
||||
st = strings[h];
|
||||
while (st) {
|
||||
if (strcmp(st->str,s) == 0) return st->str;
|
||||
st = st->next;
|
||||
}
|
||||
|
||||
/* Not found. Add the string to the hash table */
|
||||
st = (stringtype *) wad_malloc(sizeof(stringtype));
|
||||
st->str = wad_strdup(s);
|
||||
st->next = strings[h];
|
||||
strings[h] = st;
|
||||
return st->str;
|
||||
}
|
||||
|
||||
void wad_string_debug() {
|
||||
if (wad_debug_mode & DEBUG_STRING) {
|
||||
int maxdepth = 0;
|
||||
int total = 0;
|
||||
int stringlen = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < STRING_HASH_SIZE; i++) {
|
||||
stringtype *s;
|
||||
int c = 0;
|
||||
s = strings[i];
|
||||
while (s) {
|
||||
c++;
|
||||
stringlen += strlen(s->str);
|
||||
s = s->next;
|
||||
}
|
||||
/* wad_printf("WAD: stringhash[%d] = %d\n", i, c);*/
|
||||
if (c > maxdepth) maxdepth = c;
|
||||
total += c;
|
||||
}
|
||||
wad_printf("WAD: nstrings = %d (%d bytes)\n", total, stringlen + total*sizeof(stringtype));
|
||||
wad_printf("WAD: maxdepth = %d\n", maxdepth);
|
||||
}
|
||||
}
|
||||
|
||||
/* Our own string copy */
|
||||
char *wad_strcpy(char *t, const char *s) {
|
||||
if (s)
|
||||
for (; *s; s++, t++) *t = *s;
|
||||
*t = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
wad_strcat(char *t, const char *s) {
|
||||
while (*t) t++;
|
||||
return wad_strcpy(t,s);
|
||||
}
|
||||
|
||||
int
|
||||
wad_strlen(const char *s) {
|
||||
int count = 0;
|
||||
while (*(s++)) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* vars.c
|
||||
*
|
||||
* This file examines the stack trace and tries to make some sense out of
|
||||
* collected debugging information. This includes locating the data on
|
||||
* the stack and/or registers.
|
||||
*
|
||||
* This feature is detached from the debugging info collector to make
|
||||
* it independent of debugging formats.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* See the file COPYING for a complete copy of the LGPL.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "wad.h"
|
||||
|
||||
static char cvs[] = "$Id$";
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* wad_build_vars()
|
||||
*
|
||||
* Build variable information for a single stack frame
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void wad_build_vars(WadFrame *f) {
|
||||
char *stack = 0;
|
||||
char *nstack = 0;
|
||||
char *pstack = 0;
|
||||
WadLocal *loc;
|
||||
int n;
|
||||
|
||||
stack = (char *) f->stack;
|
||||
if (f->next) {
|
||||
nstack = (char *) f->next->stack;
|
||||
}
|
||||
if (f->prev) {
|
||||
pstack = (char *) f->prev->stack;
|
||||
}
|
||||
|
||||
for (n = 0; n < 2; n++) {
|
||||
if (n == 0) loc = f->debug_args;
|
||||
else loc = f->debug_locals;
|
||||
|
||||
while (loc) {
|
||||
loc->ptr = 0;
|
||||
if (loc->loc == PARM_STACK) {
|
||||
if ((loc->stack >= 0) && (nstack)) {
|
||||
loc->ptr = (void *) (nstack + loc->stack);
|
||||
} else if (loc->stack < 0) {
|
||||
loc->ptr = (void *) (stack + f->stack_size + loc->stack);
|
||||
}
|
||||
loc->size = sizeof(long);
|
||||
}
|
||||
if (loc->loc == PARM_REGISTER) {
|
||||
/* Parameter is located in a register */
|
||||
#ifdef WAD_SOLARIS
|
||||
if ((loc->reg >= 24) && (loc->reg < 32)) {
|
||||
/* Value is located in the %in registers. */
|
||||
loc->ptr = (void *) (stack + (loc->reg - 16)*sizeof(int));
|
||||
loc->size = sizeof(int);
|
||||
} else if ((loc->reg >= 8) && (loc->reg < 16)) {
|
||||
|
||||
/* Value is located in the %on registers */
|
||||
if (nstack) {
|
||||
loc->ptr = (void *) (stack + (loc->reg)*sizeof(int));
|
||||
loc->size = sizeof(int);
|
||||
}
|
||||
} else if ((loc->reg >= 16) && (loc->reg < 24)) {
|
||||
/* Value has been placed in the %ln registers */
|
||||
loc->ptr = (void *) (stack + (loc->reg - 16)*sizeof(int));
|
||||
loc->size = sizeof(int);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
loc = loc->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function creates a formatted integer given a pointer, size, and sign flag */
|
||||
static
|
||||
char *wad_format_int(char *ptr, int nbytes, int sgn) {
|
||||
static char fmt[128];
|
||||
unsigned char *s;
|
||||
int incr;
|
||||
unsigned long value = 0;
|
||||
int i;
|
||||
|
||||
#ifdef WAD_LITTLE_ENDIAN
|
||||
s = (unsigned char *) (ptr + nbytes - 1);
|
||||
incr = -1;
|
||||
#else
|
||||
s = (unsigned char *) (ptr);
|
||||
incr = +1;
|
||||
#endif
|
||||
for (i = 0; i < nbytes; i++, s += incr) {
|
||||
value = (value << 8) + *s;
|
||||
}
|
||||
if (sgn) {
|
||||
return wad_format_signed((long) value,-1);
|
||||
} else {
|
||||
return wad_format_unsigned((unsigned long) value, -1);
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
/* Try to make a formatted version of a local */
|
||||
char *wad_format_var(WadLocal *l) {
|
||||
static char hexdigits[] = "0123456789abcdef";
|
||||
static char buffer[1024];
|
||||
double dval;
|
||||
float fval;
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
switch(l->type) {
|
||||
case WAD_TYPE_INT32:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,4,1));
|
||||
break;
|
||||
case WAD_TYPE_UINT32:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,4,0));
|
||||
break;
|
||||
case WAD_TYPE_INT16:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,2,1));
|
||||
break;
|
||||
case WAD_TYPE_UINT16:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,2,0));
|
||||
break;
|
||||
case WAD_TYPE_INT8:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,1,1));
|
||||
break;
|
||||
case WAD_TYPE_UINT8:
|
||||
wad_strcpy(buffer,wad_format_int(l->ptr,1,0));
|
||||
break;
|
||||
case WAD_TYPE_CHAR:
|
||||
buffer[0] = '\'';
|
||||
buffer[1] = *((char *) l->ptr);
|
||||
buffer[2] = '\'';
|
||||
buffer[3] = 0;
|
||||
break;
|
||||
case WAD_TYPE_FLOAT:
|
||||
wad_memcpy(&fval,l->ptr,sizeof(float));
|
||||
sprintf(buffer,"%g",fval);
|
||||
break;
|
||||
case WAD_TYPE_DOUBLE:
|
||||
wad_memcpy(&dval,l->ptr,sizeof(double));
|
||||
sprintf(buffer,"%g",dval);
|
||||
break;
|
||||
case WAD_TYPE_UNKNOWN:
|
||||
case WAD_TYPE_POINTER:
|
||||
default:
|
||||
/* Hmmm. Unknown data type. We'll just treat it as a word */
|
||||
if (l->ptr) {
|
||||
int incr,i;
|
||||
int b;
|
||||
int leading = 1;
|
||||
char *c;
|
||||
char *ptr;
|
||||
|
||||
#ifdef WAD_LITTLE_ENDIAN
|
||||
ptr = ((char *) l->ptr) + 3;
|
||||
incr = -1;
|
||||
#else
|
||||
ptr = (char *) l->ptr;
|
||||
incr =1 ;
|
||||
#endif
|
||||
wad_strcat(buffer,"0x");
|
||||
c = buffer+2;
|
||||
for (i = 0; i < sizeof(void *); i++) {
|
||||
b = (int) *ptr;
|
||||
if (!leading || (b)) {
|
||||
if (!leading || (b & 0xf0))
|
||||
*(c++) = hexdigits[(b & 0xf0) >> 4];
|
||||
*(c++) = hexdigits[(b & 0xf)];
|
||||
leading = 0;
|
||||
}
|
||||
ptr += incr;
|
||||
}
|
||||
if (leading)
|
||||
*(c++) = '0';
|
||||
|
||||
*c = 0;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Convert a wad local variable to a long */
|
||||
long wad_local_as_long(WadLocal *loc) {
|
||||
long value = 0;
|
||||
int32 i32;
|
||||
int16 i16;
|
||||
int8 i8;
|
||||
uint32 u32;
|
||||
uint16 u16;
|
||||
uint8 u8;
|
||||
|
||||
switch(loc->type) {
|
||||
case WAD_TYPE_INT32:
|
||||
wad_memcpy(&i32,loc->ptr,4);
|
||||
value = (long) i32;
|
||||
break;
|
||||
case WAD_TYPE_UINT32:
|
||||
wad_memcpy(&u32,loc->ptr,4);
|
||||
value = (long) u32;
|
||||
break;
|
||||
case WAD_TYPE_INT16:
|
||||
wad_memcpy(&i16,loc->ptr,2);
|
||||
value = (long) i16;
|
||||
break;
|
||||
case WAD_TYPE_UINT16:
|
||||
wad_memcpy(&u16,loc->ptr,2);
|
||||
value = (long) u16;
|
||||
break;
|
||||
case WAD_TYPE_INT8:
|
||||
case WAD_TYPE_CHAR:
|
||||
wad_memcpy(&i8, loc->ptr,1);
|
||||
value = (long) i8;
|
||||
break;
|
||||
case WAD_TYPE_UINT8:
|
||||
wad_memcpy(&u8, loc->ptr,1);
|
||||
value = (long) u8;
|
||||
break;
|
||||
default:
|
||||
wad_memcpy(&u32,loc->ptr,4);
|
||||
value = (long) u32;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Convert a wad local variable to a long */
|
||||
double wad_local_as_double(WadLocal *loc) {
|
||||
double value = 0;
|
||||
float fval;
|
||||
|
||||
switch(loc->type) {
|
||||
case WAD_TYPE_DOUBLE:
|
||||
wad_memcpy(&value,loc->ptr,8);
|
||||
break;
|
||||
case WAD_TYPE_FLOAT:
|
||||
wad_memcpy(&fval,loc->ptr,4);
|
||||
value = (double) fval;
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
package libwadpl;
|
||||
sub wad_handler_traceback {
|
||||
package DB;
|
||||
my $es = "";
|
||||
($pack,$file,$line) = caller(1);
|
||||
|
||||
for ($i = 2; ($p,$f,$l,$s,$h,$w,$e,$r) = caller($i); $i++) {
|
||||
@a = ();
|
||||
for $arg (@args) {
|
||||
$_ = "$arg";
|
||||
s/([\'\\])/\\$1/g;
|
||||
s/([^\0]*)/'$1'/
|
||||
unless /^(?: -?[\d.]+ | \*[\w:]* )$/x;
|
||||
s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
|
||||
s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
|
||||
push(@a, $_);
|
||||
}
|
||||
$w = $w ? '@ = ' : '$ = ';
|
||||
$a = $h ? '(' . join(', ', @a) . ')' : '';
|
||||
$e =~ s/\n\s*\;\s*\Z// if $e;
|
||||
$e =~ s/[\\\']/\\$1/g if $e;
|
||||
if ($r) {
|
||||
$s = "require '$e'";
|
||||
} elsif (defined $r) {
|
||||
$s = "eval '$e'";
|
||||
} elsif ($s eq '(eval)') {
|
||||
$s = "eval {...}";
|
||||
}
|
||||
$f = "file `$f'" unless $f eq '-e';
|
||||
$mess = "$w$s$a called from $f line $l\n";
|
||||
$es = $mess . $es;
|
||||
|
||||
}
|
||||
$es = "Signal at $file line $line\n" . $es;
|
||||
return $es;
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* wadpl.cxx
|
||||
*
|
||||
* Dynamically loadable module for Perl.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
|
||||
#include "wad.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "wad_perl_handler.c"
|
||||
|
||||
/* Error message returned to perl */
|
||||
|
||||
static char message[65536];
|
||||
static int global_signo = 0;
|
||||
|
||||
static void returnfunc(void) {
|
||||
SV *s;
|
||||
s = perl_eval_pv((char*)"libwadpl::wad_handler_traceback(0)", 0);
|
||||
croak("%s\n%s",SvPV(s,PL_na),message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handler function */
|
||||
static void handler(int signo, WadFrame *frame, char *ret) {
|
||||
|
||||
static char temp[1024];
|
||||
int len = 0;
|
||||
char *name;
|
||||
char *fd;
|
||||
WadFrame *f;
|
||||
WadFrame *fline = 0;
|
||||
int err;
|
||||
char *type;
|
||||
|
||||
if (!ret) {
|
||||
wad_default_callback(signo, frame, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch(signo) {
|
||||
case SIGSEGV:
|
||||
type = (char*)"Segmentation fault.";
|
||||
break;
|
||||
case SIGBUS:
|
||||
type = (char*)"Bus error.";
|
||||
break;
|
||||
case SIGABRT:
|
||||
type = (char*)"Abort.";
|
||||
break;
|
||||
case SIGFPE:
|
||||
type = (char*)"Math.";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
strcpy(message,type);
|
||||
strcat(message,"\n[ C stack trace ]\n\n");
|
||||
fd = (char *) frame;
|
||||
f = (WadFrame *) fd;
|
||||
|
||||
/* Find the last exception frame */
|
||||
while (!f->last) {
|
||||
fd = fd + f->size;
|
||||
f = (WadFrame *) fd;
|
||||
}
|
||||
/* Now work backwards */
|
||||
fd = fd - f->lastsize;
|
||||
f = (WadFrame *) fd;
|
||||
while (1) {
|
||||
sprintf(temp,"#%-3d 0x%08x in ", f->frameno, f->pc);
|
||||
strcat(message,temp);
|
||||
strcat(message,*(fd + f->sym_off) ? fd+f->sym_off : "?");
|
||||
strcat(message,"()");
|
||||
if (strlen(SRCFILE(f))) {
|
||||
strcat(message," in '");
|
||||
strcat(message, wad_strip_dir(SRCFILE(f)));
|
||||
strcat(message,"'");
|
||||
if (f->line_number > 0) {
|
||||
sprintf(temp,", line %d", f->line_number);
|
||||
strcat(message,temp);
|
||||
fline = f;
|
||||
}
|
||||
} else {
|
||||
if (strlen(fd+f->obj_off)) {
|
||||
strcat(message," from '");
|
||||
strcat(message, wad_strip_dir(OBJFILE(f)));
|
||||
strcat(message,"'");
|
||||
}
|
||||
}
|
||||
strcat(message,"\n");
|
||||
if (!f->lastsize) break;
|
||||
fd = fd - f->lastsize;
|
||||
f = (WadFrame *) fd;
|
||||
}
|
||||
if (fline) {
|
||||
int first;
|
||||
int last;
|
||||
char *line, *c;
|
||||
int i;
|
||||
first = fline->line_number - 2;
|
||||
last = fline->line_number + 2;
|
||||
if (first < 1) first = 1;
|
||||
|
||||
line = wad_load_source(SRCFILE(fline),first);
|
||||
if (line) {
|
||||
strcat(message,"\n");
|
||||
strcat(message, SRCFILE(fline));
|
||||
sprintf(temp,", line %d\n\n", fline->line_number);
|
||||
strcat(message, temp);
|
||||
for (i = first; i <= last; i++) {
|
||||
if (i == fline->line_number) strcat(message," => ");
|
||||
else strcat(message," ");
|
||||
c = strchr(line,'\n');
|
||||
if (c) {
|
||||
*c = 0;
|
||||
strcat(message,line);
|
||||
strcat(message,"\n");
|
||||
*c = '\n';
|
||||
} else {
|
||||
strcat(message,line);
|
||||
strcat(message,"\n");
|
||||
break;
|
||||
}
|
||||
line = c+1;
|
||||
}
|
||||
wad_release_source();
|
||||
strcat(message,"\n");
|
||||
}
|
||||
}
|
||||
wad_set_return_func(returnfunc);
|
||||
wad_release_trace();
|
||||
}
|
||||
|
||||
static void perlwadinit() {
|
||||
printf("WAD Enabled\n");
|
||||
wad_init();
|
||||
wad_set_callback(handler);
|
||||
wad_set_return("Perl_pp_entersub", 0);
|
||||
perl_eval_pv(wad_perl_handler, 0);
|
||||
}
|
||||
|
||||
/* This hack is used to auto-initialize wad regardless of whether we are
|
||||
used as an imported module or as a link-library for another module */
|
||||
|
||||
class wadinitializer {
|
||||
public:
|
||||
wadinitializer() {
|
||||
perlwadinit();
|
||||
}
|
||||
};
|
||||
|
||||
static wadinitializer wi;
|
||||
|
||||
extern "C"
|
||||
XS(boot_libwadpl) {
|
||||
dXSARGS;
|
||||
ST(0) = &PL_sv_yes;
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
|
@ -1,365 +0,0 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
dnl NOTES:
|
||||
dnl * As of 1.34, we no longer use and test for "nope" to indicate
|
||||
dnl an empty variable. Instead, we use `VAR=' (set the variable
|
||||
dnl to nothing) and `test -z "$VAR"' or `test -n "$VAR"' as the
|
||||
dnl case may be. --ttn, 2000/08/04 12:11:26
|
||||
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([Include/wad.h])
|
||||
AC_PREREQ(2.53)
|
||||
|
||||
# Set name for machine-dependent library files
|
||||
AC_SUBST(MACHDEP)
|
||||
AC_MSG_CHECKING(MACHDEP)
|
||||
if test -z "$MACHDEP"
|
||||
then
|
||||
if test -f /usr/lib/NextStep/software_version; then
|
||||
set X `hostinfo | grep 'NeXT Mach.*:' | \
|
||||
sed -e 's/://' -e 's/\./_/'` && \
|
||||
ac_sys_system=next && ac_sys_release=$4
|
||||
MACHDEP="$ac_sys_system$ac_sys_release$ac_sys_cpu"
|
||||
else
|
||||
ac_sys_system=`uname -s`
|
||||
if test "$ac_sys_system" = "AIX" ; then
|
||||
ac_sys_release=`uname -v`
|
||||
else
|
||||
ac_sys_release=`uname -r`
|
||||
fi
|
||||
ac_md_system=`echo $ac_sys_system |
|
||||
tr -d '[/ ]' | tr '[[A-Z]]' '[[a-z]]'`
|
||||
ac_md_release=`echo $ac_sys_release |
|
||||
tr -d '[/ ]' | sed 's/\..*//'`
|
||||
MACHDEP="$ac_md_system$ac_md_release"
|
||||
fi
|
||||
case MACHDEP in
|
||||
'') MACHDEP=unknown;;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($MACHDEP)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl Checks for programs.
|
||||
|
||||
AC_SUBST(AR)
|
||||
AC_CHECK_PROGS(AR, ar aal, ar)
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
dnl Checks for library functions.
|
||||
|
||||
# Set info about shared libraries.
|
||||
AC_SUBST(SO)
|
||||
AC_SUBST(LDSHARED)
|
||||
AC_SUBST(CCSHARED)
|
||||
|
||||
# SO is the extension of shared libraries `(including the dot!)
|
||||
# -- usually .so, .sl on HP-UX
|
||||
AC_MSG_CHECKING(SO)
|
||||
if test -z "$SO"
|
||||
then
|
||||
case $ac_sys_system in
|
||||
hp*|HP*) SO=.sl;;
|
||||
*) SO=.so;;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($SO)
|
||||
|
||||
# WAD Options
|
||||
AC_SUBST(WADOPT)
|
||||
AC_MSG_CHECKING(WADOPT)
|
||||
if test -z "$WADOPT"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
SunOS/5*) WADOPT="-DWAD_SOLARIS";;
|
||||
Linux*) WADOPT="-DWAD_LINUX";;
|
||||
*) WADOPT="-DWAD_UNKWOWN";;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($WADOPT)
|
||||
|
||||
|
||||
# LDSHARED is the ld *command* used to create shared library
|
||||
# -- "ld" on SunOS 4.x.x, "ld -G" on SunOS 5.x, "ld -shared" on IRIX 5
|
||||
# (Shared libraries in this instance are shared modules to be loaded into
|
||||
# Python, as opposed to building Python itself as a shared library.)
|
||||
AC_MSG_CHECKING(LDSHARED)
|
||||
if test -z "$LDSHARED"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
AIX*) LDSHARED="\$(srcdir)/ld_so_aix \$(CC)";;
|
||||
IRIX/5*) LDSHARED="ld -shared";;
|
||||
IRIX*/6*) LDSHARED="ld ${SGI_ABI} -shared -all";;
|
||||
SunOS/4*) LDSHARED="ld";;
|
||||
SunOS/5*) LDSHARED="ld -G";;
|
||||
hp*|HP*) LDSHARED="ld -b";;
|
||||
OSF*) LDSHARED="ld -shared -expect_unresolved \"*\"";;
|
||||
DYNIX/ptx*) LDSHARED="ld -G";;
|
||||
next/*)
|
||||
if test "$ns_dyld"
|
||||
then LDSHARED='$(CC) $(LDFLAGS) -bundle -prebind'
|
||||
else LDSHARED='$(CC) $(CFLAGS) -nostdlib -r';
|
||||
fi
|
||||
if test "$with_next_framework" ; then
|
||||
LDSHARED="$LDSHARED \$(LDLIBRARY)"
|
||||
fi ;;
|
||||
Linux*) LDSHARED="gcc -shared";;
|
||||
dgux*) LDSHARED="ld -G";;
|
||||
FreeBSD*/3*) LDSHARED="gcc -shared";;
|
||||
FreeBSD*|OpenBSD*) LDSHARED="ld -Bshareable";;
|
||||
NetBSD*)
|
||||
if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
|
||||
then
|
||||
LDSHARED="cc -shared"
|
||||
else
|
||||
LDSHARED="ld -Bshareable"
|
||||
fi;;
|
||||
SCO_SV*) LDSHARED="cc -G -KPIC -Ki486 -belf -Wl,-Bexport";;
|
||||
*) LDSHARED="ld";;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($LDSHARED)
|
||||
|
||||
|
||||
# CXXSHARED is the C++ *command* used to create shared library
|
||||
AC_SUBST(CXXLINK)
|
||||
|
||||
AC_MSG_CHECKING(CXXLINK)
|
||||
if test -z "$CXXLINK"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
SunOS/5*) if test "$GCC" = yes;
|
||||
then CXXLINK="g++ -shared";
|
||||
else CXXLINK="CC -G";
|
||||
fi;;
|
||||
Linux*) CXXLINK="g++ -shared";;
|
||||
*) CXXLINK="g++";;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($CXXLINK)
|
||||
|
||||
# CCSHARED are the C *flags* used to create objects to go into a shared
|
||||
# library (module) -- this is only needed for a few systems
|
||||
AC_MSG_CHECKING(CCSHARED)
|
||||
if test -z "$CCSHARED"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
hp*|HP*) if test "$GCC" = yes;
|
||||
then CCSHARED="-fpic";
|
||||
else CCSHARED="+z";
|
||||
fi;;
|
||||
Linux*) CCSHARED="-fpic";;
|
||||
FreeBSD*|OpenBSD*) CCSHARED="-fpic";;
|
||||
NetBSD*) CCSHARED="-fPIC";;
|
||||
SCO_SV*) CCSHARED="-KPIC -dy -Bdynamic";;
|
||||
IRIX*/6*) case $CC in
|
||||
*gcc*) CCSHARED="-shared";;
|
||||
*) CCSHARED="";;
|
||||
esac;;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($CCSHARED)
|
||||
|
||||
AC_SUBST(CXXSHARED)
|
||||
# CCSHARED are the C *flags* used to create objects to go into a shared
|
||||
# library (module) -- this is only needed for a few systems
|
||||
AC_MSG_CHECKING(CXXSHARED)
|
||||
if test -z "$CXXSHARED"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
Linux*) CXXSHARED="-fpic";;
|
||||
SunOS/5*) if test "$GCC" = yes;
|
||||
then CXXSHARED="-fpic";
|
||||
else CXXSHARED="-Kpic";
|
||||
fi;;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($CXXSHARED)
|
||||
|
||||
# RPATH is the path used to look for shared library files.
|
||||
AC_MSG_CHECKING(RPATH)
|
||||
if test -z "$RPATH"
|
||||
then
|
||||
case $ac_sys_system/$ac_sys_release in
|
||||
SunOS/5*) RPATH="\"-R\"";;
|
||||
Linux*) RPATH="-Xlinker -rpath ";;
|
||||
*) RPATH="";;
|
||||
esac
|
||||
fi
|
||||
AC_MSG_RESULT($RPATH)
|
||||
AC_SUBST(RPATH)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Try to locate the Tcl package
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TCLINCLUDE=
|
||||
TCLLIB=
|
||||
TCLPACKAGE=
|
||||
MAKETCL=
|
||||
|
||||
AC_ARG_WITH(tcl,[ --with-tcl=path Set location of Tcl package],[
|
||||
TCLPACKAGE="$withval"], [TCLPACKAGE=])
|
||||
AC_ARG_WITH(tclincl,[ --with-tclincl=path Set location of Tcl include directory],[
|
||||
TCLINCLUDE="-I$withval"], [TCLINCLUDE=])
|
||||
AC_ARG_WITH(tcllib,[ --with-tcllib=path Set location of Tcl library directory],[
|
||||
TCLLIB="-L$withval"], [TCLLIB=])
|
||||
|
||||
if test -z "$TCLINCLUDE"; then
|
||||
if test -n "$TCLPACKAGE"; then
|
||||
TCLINCLUDE="-I$TCLPACKAGE/include"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$TCLLIB"; then
|
||||
if test -n "$TCLPACKAGE"; then
|
||||
TCLLIB="-L$TCLPACKAGE/lib"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for Tcl header files)
|
||||
if test -z "$TCLINCLUDE"; then
|
||||
AC_TRY_CPP([#include <tcl.h>], , TCLINCLUDE="")
|
||||
if test -z "$TCLINCLUDE"; then
|
||||
dirs="$prefix/include /usr/local/include /usr/include /opt/local/include /home/sci/local/include"
|
||||
for i in $dirs ; do
|
||||
if test -r $i/tcl.h; then
|
||||
AC_MSG_RESULT($i)
|
||||
TCLINCLUDE="-I$i"
|
||||
MAKETCL="tcl"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test -z "$TCLINCLUDE"; then
|
||||
TCLINCLUDE=""
|
||||
MAKETCL=""
|
||||
AC_MSG_RESULT(not found)
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT($TCLINCLUDE)
|
||||
fi
|
||||
|
||||
AC_SUBST(TCLINCLUDE)
|
||||
AC_SUBST(MAKETCL)
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Look for Python
|
||||
#----------------------------------------------------------------
|
||||
|
||||
PYINCLUDE=
|
||||
MAKEPYTHON=
|
||||
PYLIB=
|
||||
PYPACKAGE=
|
||||
|
||||
AC_ARG_WITH(py,[ --with-py=path Set location of Python],[
|
||||
PYPACKAGE="$withval"], [PYPACKAGE=])
|
||||
AC_ARG_WITH(pyincl,[ --with-pyincl=path Set location of Python include directory],[
|
||||
PYINCLUDE="$withval"], [PYINCLUDE=])
|
||||
AC_ARG_WITH(pylib,[ --with-pylib=path Set location of Python library directory],[
|
||||
PYLIB="$withval"], [PYLIB=])
|
||||
|
||||
if test -z "$PYINCLUDE"; then
|
||||
if test -n "$PYPACKAGE"; then
|
||||
PYINCLUDE="$PYPACKAGE/include"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$PYLIB"; then
|
||||
if test -n "$PYPACKAGE"; then
|
||||
PYLIB="$PYPACKAGE/lib"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING(for Python header files)
|
||||
|
||||
dirs="$PYINCLUDE $PYINCLUDE/python2.0 $PYINCLUDE/python1.6 $PYINCLUDE/python1.5 $prefix/include/python2.0 $prefix/include/python1.6 $prefix/include/python1.5 /usr/local/include/python2.0 /usr/local/include/python1.6 /usr/local/include/python1.5 /usr/include/python1.5"
|
||||
for i in $dirs ; do
|
||||
if test -r $i/Python.h; then
|
||||
AC_MSG_RESULT($i)
|
||||
PYINCLUDE="-I$i"
|
||||
MAKEPYTHON="python"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$PYINCLUDE"; then
|
||||
PYINCLUDE=""
|
||||
MAKEPYTHON=""
|
||||
AC_MSG_RESULT(not found)
|
||||
fi
|
||||
|
||||
AC_SUBST(PYINCLUDE)
|
||||
AC_SUBST(PYLINK)
|
||||
AC_SUBST(MAKEPYTHON)
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Look for Perl5
|
||||
#----------------------------------------------------------------
|
||||
|
||||
PERLBIN=
|
||||
MAKEPERL=
|
||||
|
||||
AC_ARG_WITH(perl5,[ --with-perl5=path Set location of Perl5 executable],[ PERLBIN="$withval"], [PERLBIN=])
|
||||
|
||||
# First figure out what the name of Perl5 is
|
||||
|
||||
if test -z "$PERLBIN"; then
|
||||
AC_CHECK_PROGS(PERL, perl5.004 perl5.003 perl5.002 perl5.001 perl5 perl)
|
||||
else
|
||||
PERL="$PERLBIN"
|
||||
fi
|
||||
AC_MSG_CHECKING(for Perl5 header files)
|
||||
if test -n "$PERL"; then
|
||||
PERL5DIR=`($PERL -e 'use Config; print $Config{archlib};') 2>/dev/null`
|
||||
if test "$PERL5DIR" != ""; then
|
||||
dirs="$PERL5DIR $PERL5DIR/CORE"
|
||||
PERL5EXT=none
|
||||
for i in $dirs; do
|
||||
if test -r $i/perl.h; then
|
||||
AC_MSG_RESULT($i)
|
||||
PERL5EXT="-I$i"
|
||||
MAKEPERL="perl"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test "$PERL5EXT" = none; then
|
||||
PERL5EXT=""
|
||||
MAKEPERL=""
|
||||
AC_MSG_RESULT(could not locate perl.h...using $PERL5EXT)
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(unable to determine perl5 configuration)
|
||||
PERL5EXT=""
|
||||
MAKEPERL=""
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(could not figure out how to run perl5)
|
||||
PERL5EXT=""
|
||||
MAKEPERL=""
|
||||
fi
|
||||
|
||||
AC_SUBST(PERL5EXT)
|
||||
AC_SUBST(MAKEPERL)
|
||||
|
||||
dnl We use the following in `AC_CONFIG_FILES' and "make distclean".
|
||||
configure_substituted_files=`echo \
|
||||
Wad/Makefile \
|
||||
Python/Makefile \
|
||||
Tcl/Makefile \
|
||||
Test/Makefile \
|
||||
Prebuilt/linux/Makefile \
|
||||
Prebuilt/solaris/Makefile \
|
||||
Makefile \
|
||||
`
|
||||
AC_SUBST(configure_substituted_files)
|
||||
|
||||
AC_CONFIG_FILES([$configure_substituted_files])
|
||||
AC_OUTPUT
|
||||
|
||||
dnl configure.in ends here
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
%define version 1.3.7
|
||||
%define release 1
|
||||
|
||||
# Preamble
|
||||
Summary: Simplified Wrapper and Interface Generator
|
||||
Name: swig
|
||||
Version: %{version}
|
||||
Release: %{release}
|
||||
Copyright: BSD
|
||||
URL: http://www.swig.org
|
||||
Group: System Environment/Daemons
|
||||
Source0: http://download.sourceforge.net/swig/swig-%{version}.tar.gz
|
||||
Packager: Dustin Mitchell <dustin@cs.uchicago.edu>
|
||||
BuildRoot: /var/tmp/rpm/swig-root
|
||||
Prefix: /usr
|
||||
|
||||
%description
|
||||
SWIG is an interface compiler that connects programs written in C,
|
||||
C++, and Objective-C with scripting languages including Perl, Python,
|
||||
and Tcl/Tk. It works by taking the declarations commonly found in
|
||||
C/C++ header files and using them to generate the glue code (wrappers)
|
||||
that scripting languages need to access the underlying C/C++ code
|
||||
|
||||
# PREP
|
||||
%prep
|
||||
%setup -n SWIG-%{version}
|
||||
|
||||
# BUILD
|
||||
%build
|
||||
./configure --prefix=%prefix
|
||||
make
|
||||
|
||||
# INSTALL
|
||||
%install
|
||||
rm -rf ${RPM_BUILD_ROOT}
|
||||
install -d -m 755 ${RPM_BUILD_ROOT}
|
||||
make prefix=${RPM_BUILD_ROOT}%prefix install
|
||||
|
||||
# FILES
|
||||
%files
|
||||
%prefix/lib/*
|
||||
%prefix/bin/swig
|
||||
Loading…
Add table
Add a link
Reference in a new issue