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:
William S Fulton 2010-05-29 21:35:39 +00:00
commit 5aaf531b5a
51 changed files with 0 additions and 7404 deletions

View file

@ -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.

View file

@ -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!

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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.
* ----------------------------------------------------------------------------- */

View file

@ -1,5 +0,0 @@
Papers about WAD can be obtained at:
http://systems.cs.uchicago.edu/wad

View file

@ -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

View file

@ -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

View file

@ -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 *~

View file

@ -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);
}

View file

@ -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 */
};

View file

@ -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;

View file

@ -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

View file

@ -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 *~

View file

@ -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;
}

View file

@ -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;

View file

@ -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*

View file

@ -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).

View file

@ -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()

View file

@ -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"

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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()

View file

@ -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()

View file

@ -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)

View file

@ -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 *~

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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; */
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -1,8 +0,0 @@
package libwadpl;
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
package libwadpl;
bootstrap libwadpl;
@EXPORT = qw( );
1;

View file

@ -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;

View file

@ -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()

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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

View file

@ -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