initial commit

This is the first public release of the ptrace based mtrace utility, a dynamic
memory allocation debuger and analyzer.
This commit is contained in:
Stefani Seibold 2015-04-20 09:08:14 +02:00
commit 0a26d61e70
117 changed files with 119597 additions and 0 deletions

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

0
CREDITS Normal file
View File

365
INSTALL Normal file
View File

@ -0,0 +1,365 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

109
Makefile.am Normal file
View File

@ -0,0 +1,109 @@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
ACLOCAL_AMFLAGS = -I config/m4
SUBDIRS = \
client \
sysdeps \
.
AM_CPPFLAGS += \
$(libelf_CFLAGS) \
-DSYSCONFDIR=\"$(sysconfdir)\"
AM_LDFLAGS += \
-Wl,--no-as-needed
mtrace_SOURCES = \
breakpoint.c \
common.c \
debug.c \
dict.c \
dwarf.c \
event.c \
library.c \
main.c \
mtelf.c \
options.c \
rbtree.c \
report.c \
server.c \
task.c \
trace.c
mtrace_LDADD = \
$(libelf_LIBS) \
libclient.la \
sysdeps/libos.la
bin_PROGRAMS = \
mtrace
noinst_HEADERS = \
backend.h \
backtrace.h \
breakpoint.h \
common.h \
debug.h \
dict.h \
dwarf.h \
event.h \
forward.h \
library.h \
list.h \
main.h \
mtelf.h \
mtrace.h \
options.h \
rbtree.h \
report.h \
task.h \
thread.h \
trace.h
dist_doc_DATA = COPYING CREDITS INSTALL README TODO
EXTRA_DIST =
MAINTAINERCLEANFILES = \
configure \
Makefile.in \
aclocal.m4 \
config.h.in \
config.h.in~ \
config/autoconf/compile \
config/autoconf/config.guess \
config/autoconf/config.sub \
config/autoconf/depcomp \
config/autoconf/install-sh \
config/autoconf/ltmain.sh \
config/autoconf/mdate-sh \
config/autoconf/missing \
config/autoconf/texinfo.tex \
libtool.m4 \
ltoptions.m4 \
ltsugar.m4 \
ltversion.m4 \
lt~obsolete.m4 \
$(DIST_ARCHIVES)
maintainer-clean-local:
-chmod -R a+rw $(distdir)
-rm -fr $(distdir)

1120
Makefile.in Normal file

File diff suppressed because it is too large Load Diff

0
NEWS Normal file
View File

31
README.md Normal file
View File

@ -0,0 +1,31 @@
mtrace is an interactive dynamic memory tracer/debugger for C and C++ using GLIBC, which intercepts and reports all kinds of dynamic memory allocations using a preloaded library.
It supports the developer to get statistics about the memory usage and finding memory leaks in an arbitrate application. There is no need of modification of the source code nor any recompilation.
Unlike other dynamic memory tracer, mtrace is able to find no longer referenced memory allocation by scanning all writable memory mappings of the program against the addresses of the allocation. If the memory address will be not found during a scan there is a high change for a missing reference and therefore for a memory leak.
The mtrace utility was designed to run in a very constrained environment, like small embedded systems. This is one of the reasons for a client/server architecture. The server runs on the target side and the interactive client runs on the host side, the communication is done via TCP. If server and client are on the same machine then the communication can be done via UNIX Domain Socket. Both sides can run on different architectures, address sizes and endianness, but for tracing 64 bit programs the client must be compiled as a 64 bit program. On the host side all binaries (including debug information) must be accessible, there is no need for debug information on the target side.
The mtrace utility intercepts the following GLIBC calls:
malloc()
memalign()
realloc()
free()
posix_memalign()
aligned_alloc()
valloc()
pvalloc()
mmap()
munmap()
clone()
system()
execve()
exit()
The operator new() method is using malloc(), so memory allocations of a C++ application can also be traced.
There is currently support for X86 (32 udn 64 Bit), PowerPC (32 Bit) and ARM (32 Bit). Only Linux is now supported, but there are plans to support different operating systems and CPU's.
Stay tuned...

10
TODO Normal file
View File

@ -0,0 +1,10 @@
ppc single step
arm thumb support
dwarf debug support
arm & ppc hw bp support
dwarf caching
regex
invalid stack trace cache for unmapped libraries
restore REALLOC_TRY when realloc fails
manual page
documentation

1193
aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

15558
autom4te.cache/output.0 Normal file

File diff suppressed because it is too large Load Diff

15558
autom4te.cache/output.1 Normal file

File diff suppressed because it is too large Load Diff

15558
autom4te.cache/output.2 Normal file

File diff suppressed because it is too large Load Diff

522
autom4te.cache/requests Normal file
View File

@ -0,0 +1,522 @@
# This file was generated.
# It contains the lists of macros which have been traced.
# It can be safely removed.
@request = (
bless( [
'0',
1,
[
'/usr/share/autoconf-2.69'
],
[
'/usr/share/autoconf-2.69/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.15/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/libtool.m4',
'/usr/share/aclocal/ltargz.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal/ltoptions.m4',
'/usr/share/aclocal/ltsugar.m4',
'/usr/share/aclocal/ltversion.m4',
'/usr/share/aclocal/lt~obsolete.m4',
'/usr/share/aclocal-1.15/amversion.m4',
'/usr/share/aclocal-1.15/auxdir.m4',
'/usr/share/aclocal-1.15/cond.m4',
'/usr/share/aclocal-1.15/depend.m4',
'/usr/share/aclocal-1.15/depout.m4',
'/usr/share/aclocal-1.15/init.m4',
'/usr/share/aclocal-1.15/install-sh.m4',
'/usr/share/aclocal-1.15/lead-dot.m4',
'/usr/share/aclocal-1.15/maintainer.m4',
'/usr/share/aclocal-1.15/make.m4',
'/usr/share/aclocal-1.15/missing.m4',
'/usr/share/aclocal-1.15/options.m4',
'/usr/share/aclocal-1.15/prog-cc-c-o.m4',
'/usr/share/aclocal-1.15/runlog.m4',
'/usr/share/aclocal-1.15/sanity.m4',
'/usr/share/aclocal-1.15/silent.m4',
'/usr/share/aclocal-1.15/strip.m4',
'/usr/share/aclocal-1.15/substnot.m4',
'/usr/share/aclocal-1.15/tar.m4',
'configure.ac'
],
{
'AC_ENABLE_FAST_INSTALL' => 1,
'_AM_PROG_CC_C_O' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'_LT_CC_BASENAME' => 1,
'AC_LTDL_OBJDIR' => 1,
'AC_LIB_LTDL' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'AM_SET_LEADING_DOT' => 1,
'AM_SILENT_RULES' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'_LT_PROG_CXX' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'AC_LTDL_PREOPEN' => 1,
'AC_ENABLE_STATIC' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'_LT_PROG_LTMAIN' => 1,
'_m4_warn' => 1,
'AM_RUN_LOG' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'_AM_MANGLE_OPTION' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'AC_LTDL_DLLIB' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'LT_INIT' => 1,
'AM_DEP_TRACK' => 1,
'_LT_COMPILER_OPTION' => 1,
'AC_PROG_EGREP' => 1,
'_LT_LIBOBJ' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'_AM_PROG_TAR' => 1,
'LT_AC_PROG_GCJ' => 1,
'_AM_IF_OPTION' => 1,
'LTDL_INIT' => 1,
'LT_FUNC_ARGZ' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'AC_PROG_LD' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'_AC_PROG_LIBTOOL' => 1,
'_AM_SET_OPTION' => 1,
'AC_LIBTOOL_GCJ' => 1,
'AC_PROG_LD_GNU' => 1,
'AC_PROG_LIBTOOL' => 1,
'_LT_LINKER_OPTION' => 1,
'LT_PROG_GCJ' => 1,
'LT_AC_PROG_RC' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'AM_CONDITIONAL' => 1,
'_AM_SET_OPTIONS' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AC_DEFUN' => 1,
'm4_pattern_forbid' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'AC_LIBTOOL_FC' => 1,
'AC_DISABLE_STATIC' => 1,
'LT_CMD_MAX_LEN' => 1,
'LT_PROG_RC' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'_LTDL_SETUP' => 1,
'_AM_DEPENDENCIES' => 1,
'AM_SUBST_NOTMAKE' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'm4_pattern_allow' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'AM_PROG_CC_C_O' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'LT_OUTPUT' => 1,
'AC_ENABLE_SHARED' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'AC_LIBTOOL_RC' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'AM_DISABLE_STATIC' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'LT_PROG_GO' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'AM_PROG_NM' => 1,
'AC_DEFUN_ONCE' => 1,
'_LT_AC_TAGVAR' => 1,
'AC_LIBTOOL_SETUP' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'LT_PATH_LD' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AC_DISABLE_SHARED' => 1,
'_LT_AC_LANG_GCJ' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'AM_MISSING_HAS_RUN' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'LT_WITH_LTDL' => 1,
'AC_CHECK_LIBM' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'_LT_AC_LANG_CXX' => 1,
'LT_SUPPORTED_TAG' => 1,
'_LT_DLL_DEF_P' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'LTSUGAR_VERSION' => 1,
'LT_PATH_NM' => 1,
'LTOPTIONS_VERSION' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_LIBTOOL_CXX' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'_LT_AC_LANG_F77' => 1,
'LTOBSOLETE_VERSION' => 1,
'LTDL_INSTALLABLE' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'AM_SET_DEPDIR' => 1,
'LT_AC_PROG_EGREP' => 1,
'LT_LIB_DLLOAD' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'LT_AC_PROG_SED' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'LTDL_CONVENIENCE' => 1,
'AM_MAKE_INCLUDE' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'LT_LANG' => 1,
'_LT_AC_SHELL_INIT' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'AC_LIBTOOL_F77' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'AM_PROG_LD' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'm4_include' => 1,
'AM_PROG_LIBTOOL' => 1,
'LT_SYS_MODULE_PATH' => 1,
'_LT_PROG_FC' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'AM_ENABLE_SHARED' => 1,
'AM_ENABLE_STATIC' => 1,
'AC_PATH_MAGIC' => 1,
'LTVERSION_VERSION' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AM_DISABLE_SHARED' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'AC_WITH_LTDL' => 1,
'_LT_AC_LOCK' => 1,
'LT_LIB_M' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AM_MISSING_PROG' => 1,
'AC_PROG_NM' => 1,
'AM_SANITY_CHECK' => 1,
'include' => 1,
'_LT_WITH_SYSROOT' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AU_DEFUN' => 1,
'_LT_PROG_F77' => 1
}
], 'Autom4te::Request' ),
bless( [
'1',
1,
[
'/usr/share/autoconf-2.69'
],
[
'/usr/share/autoconf-2.69/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.15/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/ltargz.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal-1.15/amversion.m4',
'/usr/share/aclocal-1.15/auxdir.m4',
'/usr/share/aclocal-1.15/cond.m4',
'/usr/share/aclocal-1.15/depend.m4',
'/usr/share/aclocal-1.15/depout.m4',
'/usr/share/aclocal-1.15/init.m4',
'/usr/share/aclocal-1.15/install-sh.m4',
'/usr/share/aclocal-1.15/lead-dot.m4',
'/usr/share/aclocal-1.15/maintainer.m4',
'/usr/share/aclocal-1.15/make.m4',
'/usr/share/aclocal-1.15/missing.m4',
'/usr/share/aclocal-1.15/options.m4',
'/usr/share/aclocal-1.15/prog-cc-c-o.m4',
'/usr/share/aclocal-1.15/runlog.m4',
'/usr/share/aclocal-1.15/sanity.m4',
'/usr/share/aclocal-1.15/silent.m4',
'/usr/share/aclocal-1.15/strip.m4',
'/usr/share/aclocal-1.15/substnot.m4',
'/usr/share/aclocal-1.15/tar.m4',
'config/m4/libtool.m4',
'config/m4/ltoptions.m4',
'config/m4/ltsugar.m4',
'config/m4/ltversion.m4',
'config/m4/lt~obsolete.m4',
'configure.ac'
],
{
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AM_MISSING_PROG' => 1,
'AC_WITH_LTDL' => 1,
'LT_LIB_M' => 1,
'_LT_AC_LOCK' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'AU_DEFUN' => 1,
'_LT_PROG_F77' => 1,
'AM_SANITY_CHECK' => 1,
'include' => 1,
'AM_PROG_INSTALL_SH' => 1,
'_LT_WITH_SYSROOT' => 1,
'AC_PROG_NM' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'AM_ENABLE_SHARED' => 1,
'AM_ENABLE_STATIC' => 1,
'AC_PATH_MAGIC' => 1,
'LTVERSION_VERSION' => 1,
'LT_SYS_MODULE_PATH' => 1,
'_LT_PROG_FC' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'm4_include' => 1,
'AM_PROG_LD' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'AM_PROG_LIBTOOL' => 1,
'AC_LIBTOOL_F77' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'AM_DISABLE_SHARED' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'LT_AC_PROG_EGREP' => 1,
'LT_LIB_DLLOAD' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'_LT_AC_LANG_F77' => 1,
'LTOBSOLETE_VERSION' => 1,
'LTDL_INSTALLABLE' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'AM_SET_DEPDIR' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AM_MAKE_INCLUDE' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'LT_LANG' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'_LT_AC_SHELL_INIT' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'LT_AC_PROG_SED' => 1,
'LTDL_CONVENIENCE' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'AC_CHECK_LIBM' => 1,
'LT_WITH_LTDL' => 1,
'AM_MISSING_HAS_RUN' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'LTOPTIONS_VERSION' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_LIBTOOL_CXX' => 1,
'LT_PATH_NM' => 1,
'LTSUGAR_VERSION' => 1,
'_LT_DLL_DEF_P' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'_LT_AC_LANG_CXX' => 1,
'LT_SUPPORTED_TAG' => 1,
'LT_PROG_GO' => 1,
'AC_LIBTOOL_RC' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'AM_DISABLE_STATIC' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'LT_OUTPUT' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'AC_ENABLE_SHARED' => 1,
'AM_PROG_CC_C_O' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'LT_PATH_LD' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AC_DISABLE_SHARED' => 1,
'_LT_AC_LANG_GCJ' => 1,
'_LT_AC_TAGVAR' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AM_PROG_NM' => 1,
'AC_DEFUN_ONCE' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AC_DEFUN' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'AM_CONDITIONAL' => 1,
'_AM_SET_OPTIONS' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'm4_pattern_allow' => 1,
'_AM_DEPENDENCIES' => 1,
'AM_SUBST_NOTMAKE' => 1,
'LT_CMD_MAX_LEN' => 1,
'LT_PROG_RC' => 1,
'AC_DISABLE_STATIC' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'_LTDL_SETUP' => 1,
'm4_pattern_forbid' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'AC_LIBTOOL_FC' => 1,
'_AM_PROG_TAR' => 1,
'LT_AC_PROG_GCJ' => 1,
'_AM_IF_OPTION' => 1,
'LTDL_INIT' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'_LT_LIBOBJ' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AM_DEP_TRACK' => 1,
'_LT_COMPILER_OPTION' => 1,
'AC_PROG_EGREP' => 1,
'AM_RUN_LOG' => 1,
'_AM_MANGLE_OPTION' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'AC_LTDL_DLLIB' => 1,
'LT_INIT' => 1,
'AC_LIBTOOL_GCJ' => 1,
'AC_PROG_LD_GNU' => 1,
'AC_PROG_LIBTOOL' => 1,
'LT_PROG_GCJ' => 1,
'_LT_LINKER_OPTION' => 1,
'LT_AC_PROG_RC' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'_AC_PROG_LIBTOOL' => 1,
'_AM_SET_OPTION' => 1,
'AC_PROG_LD' => 1,
'LT_FUNC_ARGZ' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'_LT_PROG_CXX' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AM_SET_LEADING_DOT' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'AM_SILENT_RULES' => 1,
'AC_LIB_LTDL' => 1,
'_AM_PROG_CC_C_O' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'_LT_CC_BASENAME' => 1,
'AC_LTDL_OBJDIR' => 1,
'_LT_PROG_LTMAIN' => 1,
'_m4_warn' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'AC_LTDL_PREOPEN' => 1,
'AC_ENABLE_STATIC' => 1
}
], 'Autom4te::Request' ),
bless( [
'2',
1,
[
'/usr/share/autoconf-2.69'
],
[
'/usr/share/autoconf-2.69/autoconf/autoconf.m4f',
'aclocal.m4',
'configure.ac'
],
{
'AC_LIBSOURCE' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'include' => 1,
'AM_XGETTEXT_OPTION' => 1,
'sinclude' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_PP_SRCEXT' => 1,
'AC_PROG_LIBTOOL' => 1,
'm4_sinclude' => 1,
'AM_PATH_GUILE' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AC_CANONICAL_TARGET' => 1,
'AM_PROG_MKDIR_P' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_NLS' => 1,
'AC_CANONICAL_HOST' => 1,
'_AM_COND_ENDIF' => 1,
'AC_SUBST_TRACE' => 1,
'AM_GNU_GETTEXT' => 1,
'_AM_COND_IF' => 1,
'AM_POT_TOOLS' => 1,
'AM_PROG_F77_C_O' => 1,
'AM_PROG_FC_C_O' => 1,
'_AM_MAKEFILE_INCLUDE' => 1,
'LT_INIT' => 1,
'AC_CONFIG_FILES' => 1,
'AC_CANONICAL_BUILD' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AM_PROG_CXX_C_O' => 1,
'AM_PROG_MOC' => 1,
'_m4_warn' => 1,
'm4_pattern_allow' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AM_MAKEFILE_INCLUDE' => 1,
'LT_SUPPORTED_TAG' => 1,
'm4_pattern_forbid' => 1,
'_AM_COND_ELSE' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AM_ENABLE_MULTILIB' => 1,
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'AM_SILENT_RULES' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
'AC_CONFIG_LINKS' => 1,
'AM_PROG_AR' => 1,
'AC_FC_SRCEXT' => 1,
'AC_SUBST' => 1,
'AC_FC_FREEFORM' => 1,
'AC_INIT' => 1,
'AC_FC_PP_DEFINE' => 1,
'AH_OUTPUT' => 1,
'm4_include' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_CONDITIONAL' => 1
}
], 'Autom4te::Request' )
);

2757
autom4te.cache/traces.0 Normal file

File diff suppressed because it is too large Load Diff

2757
autom4te.cache/traces.1 Normal file

File diff suppressed because it is too large Load Diff

712
autom4te.cache/traces.2 Normal file
View File

@ -0,0 +1,712 @@
m4trace:aclocal.m4:1189: -1- m4_include([config/m4/libtool.m4])
m4trace:aclocal.m4:1190: -1- m4_include([config/m4/ltoptions.m4])
m4trace:aclocal.m4:1191: -1- m4_include([config/m4/ltsugar.m4])
m4trace:aclocal.m4:1192: -1- m4_include([config/m4/ltversion.m4])
m4trace:aclocal.m4:1193: -1- m4_include([config/m4/lt~obsolete.m4])
m4trace:configure.ac:27: -1- AC_INIT([mtrace], [0.1], [stefani@seibold.net])
m4trace:configure.ac:27: -1- m4_pattern_forbid([^_?A[CHUM]_])
m4trace:configure.ac:27: -1- m4_pattern_forbid([_AC_])
m4trace:configure.ac:27: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
m4trace:configure.ac:27: -1- m4_pattern_allow([^AS_FLAGS$])
m4trace:configure.ac:27: -1- m4_pattern_forbid([^_?m4_])
m4trace:configure.ac:27: -1- m4_pattern_forbid([^dnl$])
m4trace:configure.ac:27: -1- m4_pattern_forbid([^_?AS_])
m4trace:configure.ac:27: -1- AC_SUBST([SHELL])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([SHELL])
m4trace:configure.ac:27: -1- m4_pattern_allow([^SHELL$])
m4trace:configure.ac:27: -1- AC_SUBST([PATH_SEPARATOR])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PATH_SEPARATOR])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PATH_SEPARATOR$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME], ['AC_PACKAGE_NAME'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_NAME])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_NAME$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME], ['AC_PACKAGE_TARNAME'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_TARNAME])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION], ['AC_PACKAGE_VERSION'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_VERSION])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_VERSION$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING], ['AC_PACKAGE_STRING'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_STRING])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_STRING$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
m4trace:configure.ac:27: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL], ['AC_PACKAGE_URL'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([PACKAGE_URL])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_URL$])
m4trace:configure.ac:27: -1- AC_SUBST([exec_prefix], [NONE])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([exec_prefix])
m4trace:configure.ac:27: -1- m4_pattern_allow([^exec_prefix$])
m4trace:configure.ac:27: -1- AC_SUBST([prefix], [NONE])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([prefix])
m4trace:configure.ac:27: -1- m4_pattern_allow([^prefix$])
m4trace:configure.ac:27: -1- AC_SUBST([program_transform_name], [s,x,x,])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([program_transform_name])
m4trace:configure.ac:27: -1- m4_pattern_allow([^program_transform_name$])
m4trace:configure.ac:27: -1- AC_SUBST([bindir], ['${exec_prefix}/bin'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([bindir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^bindir$])
m4trace:configure.ac:27: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([sbindir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^sbindir$])
m4trace:configure.ac:27: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([libexecdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^libexecdir$])
m4trace:configure.ac:27: -1- AC_SUBST([datarootdir], ['${prefix}/share'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([datarootdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^datarootdir$])
m4trace:configure.ac:27: -1- AC_SUBST([datadir], ['${datarootdir}'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([datadir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^datadir$])
m4trace:configure.ac:27: -1- AC_SUBST([sysconfdir], ['${prefix}/etc'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([sysconfdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^sysconfdir$])
m4trace:configure.ac:27: -1- AC_SUBST([sharedstatedir], ['${prefix}/com'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([sharedstatedir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^sharedstatedir$])
m4trace:configure.ac:27: -1- AC_SUBST([localstatedir], ['${prefix}/var'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([localstatedir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^localstatedir$])
m4trace:configure.ac:27: -1- AC_SUBST([includedir], ['${prefix}/include'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([includedir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^includedir$])
m4trace:configure.ac:27: -1- AC_SUBST([oldincludedir], ['/usr/include'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([oldincludedir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^oldincludedir$])
m4trace:configure.ac:27: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME],
['${datarootdir}/doc/${PACKAGE_TARNAME}'],
['${datarootdir}/doc/${PACKAGE}'])])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([docdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^docdir$])
m4trace:configure.ac:27: -1- AC_SUBST([infodir], ['${datarootdir}/info'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([infodir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^infodir$])
m4trace:configure.ac:27: -1- AC_SUBST([htmldir], ['${docdir}'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([htmldir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^htmldir$])
m4trace:configure.ac:27: -1- AC_SUBST([dvidir], ['${docdir}'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([dvidir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^dvidir$])
m4trace:configure.ac:27: -1- AC_SUBST([pdfdir], ['${docdir}'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([pdfdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^pdfdir$])
m4trace:configure.ac:27: -1- AC_SUBST([psdir], ['${docdir}'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([psdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^psdir$])
m4trace:configure.ac:27: -1- AC_SUBST([libdir], ['${exec_prefix}/lib'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([libdir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^libdir$])
m4trace:configure.ac:27: -1- AC_SUBST([localedir], ['${datarootdir}/locale'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([localedir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^localedir$])
m4trace:configure.ac:27: -1- AC_SUBST([mandir], ['${datarootdir}/man'])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([mandir])
m4trace:configure.ac:27: -1- m4_pattern_allow([^mandir$])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_NAME$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */
@%:@undef PACKAGE_NAME])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */
@%:@undef PACKAGE_TARNAME])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_VERSION$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */
@%:@undef PACKAGE_VERSION])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_STRING$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */
@%:@undef PACKAGE_STRING])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */
@%:@undef PACKAGE_BUGREPORT])
m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL])
m4trace:configure.ac:27: -1- m4_pattern_allow([^PACKAGE_URL$])
m4trace:configure.ac:27: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */
@%:@undef PACKAGE_URL])
m4trace:configure.ac:27: -1- AC_SUBST([DEFS])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([DEFS])
m4trace:configure.ac:27: -1- m4_pattern_allow([^DEFS$])
m4trace:configure.ac:27: -1- AC_SUBST([ECHO_C])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([ECHO_C])
m4trace:configure.ac:27: -1- m4_pattern_allow([^ECHO_C$])
m4trace:configure.ac:27: -1- AC_SUBST([ECHO_N])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([ECHO_N])
m4trace:configure.ac:27: -1- m4_pattern_allow([^ECHO_N$])
m4trace:configure.ac:27: -1- AC_SUBST([ECHO_T])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([ECHO_T])
m4trace:configure.ac:27: -1- m4_pattern_allow([^ECHO_T$])
m4trace:configure.ac:27: -1- AC_SUBST([LIBS])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([LIBS])
m4trace:configure.ac:27: -1- m4_pattern_allow([^LIBS$])
m4trace:configure.ac:27: -1- AC_SUBST([build_alias])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([build_alias])
m4trace:configure.ac:27: -1- m4_pattern_allow([^build_alias$])
m4trace:configure.ac:27: -1- AC_SUBST([host_alias])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([host_alias])
m4trace:configure.ac:27: -1- m4_pattern_allow([^host_alias$])
m4trace:configure.ac:27: -1- AC_SUBST([target_alias])
m4trace:configure.ac:27: -1- AC_SUBST_TRACE([target_alias])
m4trace:configure.ac:27: -1- m4_pattern_allow([^target_alias$])
m4trace:configure.ac:28: -1- AC_CONFIG_HEADERS([config.h])
m4trace:configure.ac:31: -1- AC_CONFIG_AUX_DIR([config/autoconf])
m4trace:configure.ac:32: -1- AC_CANONICAL_BUILD
m4trace:configure.ac:32: -1- AC_REQUIRE_AUX_FILE([config.sub])
m4trace:configure.ac:32: -1- AC_REQUIRE_AUX_FILE([config.guess])
m4trace:configure.ac:32: -1- AC_SUBST([build], [$ac_cv_build])
m4trace:configure.ac:32: -1- AC_SUBST_TRACE([build])
m4trace:configure.ac:32: -1- m4_pattern_allow([^build$])
m4trace:configure.ac:32: -1- AC_SUBST([build_cpu], [$[1]])
m4trace:configure.ac:32: -1- AC_SUBST_TRACE([build_cpu])
m4trace:configure.ac:32: -1- m4_pattern_allow([^build_cpu$])
m4trace:configure.ac:32: -1- AC_SUBST([build_vendor], [$[2]])
m4trace:configure.ac:32: -1- AC_SUBST_TRACE([build_vendor])
m4trace:configure.ac:32: -1- m4_pattern_allow([^build_vendor$])
m4trace:configure.ac:32: -1- AC_SUBST([build_os])
m4trace:configure.ac:32: -1- AC_SUBST_TRACE([build_os])
m4trace:configure.ac:32: -1- m4_pattern_allow([^build_os$])
m4trace:configure.ac:33: -1- AC_CANONICAL_HOST
m4trace:configure.ac:33: -1- AC_SUBST([host], [$ac_cv_host])
m4trace:configure.ac:33: -1- AC_SUBST_TRACE([host])
m4trace:configure.ac:33: -1- m4_pattern_allow([^host$])
m4trace:configure.ac:33: -1- AC_SUBST([host_cpu], [$[1]])
m4trace:configure.ac:33: -1- AC_SUBST_TRACE([host_cpu])
m4trace:configure.ac:33: -1- m4_pattern_allow([^host_cpu$])
m4trace:configure.ac:33: -1- AC_SUBST([host_vendor], [$[2]])
m4trace:configure.ac:33: -1- AC_SUBST_TRACE([host_vendor])
m4trace:configure.ac:33: -1- m4_pattern_allow([^host_vendor$])
m4trace:configure.ac:33: -1- AC_SUBST([host_os])
m4trace:configure.ac:33: -1- AC_SUBST_TRACE([host_os])
m4trace:configure.ac:33: -1- m4_pattern_allow([^host_os$])
m4trace:configure.ac:40: -1- AC_SUBST([HOST_OS])
m4trace:configure.ac:40: -1- AC_SUBST_TRACE([HOST_OS])
m4trace:configure.ac:40: -1- m4_pattern_allow([^HOST_OS$])
m4trace:configure.ac:52: -1- AC_SUBST([HOST_CPU])
m4trace:configure.ac:52: -1- AC_SUBST_TRACE([HOST_CPU])
m4trace:configure.ac:52: -1- m4_pattern_allow([^HOST_CPU$])
m4trace:configure.ac:55: -1- AC_SUBST([CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:55: -1- AC_SUBST([CFLAGS])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CFLAGS])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CFLAGS$])
m4trace:configure.ac:55: -1- AC_SUBST([LDFLAGS])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([LDFLAGS])
m4trace:configure.ac:55: -1- m4_pattern_allow([^LDFLAGS$])
m4trace:configure.ac:55: -1- AC_SUBST([LIBS])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([LIBS])
m4trace:configure.ac:55: -1- m4_pattern_allow([^LIBS$])
m4trace:configure.ac:55: -1- AC_SUBST([CPPFLAGS])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CPPFLAGS])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CPPFLAGS$])
m4trace:configure.ac:55: -1- AC_SUBST([CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:55: -1- AC_SUBST([CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:55: -1- AC_SUBST([CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:55: -1- AC_SUBST([CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^CC$])
m4trace:configure.ac:55: -1- AC_SUBST([ac_ct_CC])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([ac_ct_CC])
m4trace:configure.ac:55: -1- m4_pattern_allow([^ac_ct_CC$])
m4trace:configure.ac:55: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([EXEEXT])
m4trace:configure.ac:55: -1- m4_pattern_allow([^EXEEXT$])
m4trace:configure.ac:55: -1- AC_SUBST([OBJEXT], [$ac_cv_objext])
m4trace:configure.ac:55: -1- AC_SUBST_TRACE([OBJEXT])
m4trace:configure.ac:55: -1- m4_pattern_allow([^OBJEXT$])
m4trace:configure.ac:55: -1- AC_REQUIRE_AUX_FILE([compile])
m4trace:configure.ac:56: -1- LT_INIT
m4trace:configure.ac:56: -1- m4_pattern_forbid([^_?LT_[A-Z_]+$])
m4trace:configure.ac:56: -1- m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])
m4trace:configure.ac:56: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
m4trace:configure.ac:56: -1- AC_SUBST([LIBTOOL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([LIBTOOL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LIBTOOL$])
m4trace:configure.ac:56: -1- AC_SUBST([SED])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([SED])
m4trace:configure.ac:56: -1- m4_pattern_allow([^SED$])
m4trace:configure.ac:56: -1- AC_SUBST([GREP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([GREP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^GREP$])
m4trace:configure.ac:56: -1- AC_SUBST([EGREP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([EGREP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^EGREP$])
m4trace:configure.ac:56: -1- AC_SUBST([FGREP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([FGREP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^FGREP$])
m4trace:configure.ac:56: -1- AC_SUBST([GREP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([GREP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^GREP$])
m4trace:configure.ac:56: -1- AC_SUBST([LD])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([LD])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LD$])
m4trace:configure.ac:56: -1- AC_SUBST([DUMPBIN])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([DUMPBIN])
m4trace:configure.ac:56: -1- m4_pattern_allow([^DUMPBIN$])
m4trace:configure.ac:56: -1- AC_SUBST([ac_ct_DUMPBIN])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([ac_ct_DUMPBIN])
m4trace:configure.ac:56: -1- m4_pattern_allow([^ac_ct_DUMPBIN$])
m4trace:configure.ac:56: -1- AC_SUBST([DUMPBIN])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([DUMPBIN])
m4trace:configure.ac:56: -1- m4_pattern_allow([^DUMPBIN$])
m4trace:configure.ac:56: -1- AC_SUBST([NM])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([NM])
m4trace:configure.ac:56: -1- m4_pattern_allow([^NM$])
m4trace:configure.ac:56: -1- AC_SUBST([LN_S], [$as_ln_s])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([LN_S])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LN_S$])
m4trace:configure.ac:56: -1- AC_SUBST([OBJDUMP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([OBJDUMP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^OBJDUMP$])
m4trace:configure.ac:56: -1- AC_SUBST([OBJDUMP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([OBJDUMP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^OBJDUMP$])
m4trace:configure.ac:56: -1- AC_SUBST([DLLTOOL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([DLLTOOL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^DLLTOOL$])
m4trace:configure.ac:56: -1- AC_SUBST([DLLTOOL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([DLLTOOL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^DLLTOOL$])
m4trace:configure.ac:56: -1- AC_SUBST([AR])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([AR])
m4trace:configure.ac:56: -1- m4_pattern_allow([^AR$])
m4trace:configure.ac:56: -1- AC_SUBST([ac_ct_AR])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([ac_ct_AR])
m4trace:configure.ac:56: -1- m4_pattern_allow([^ac_ct_AR$])
m4trace:configure.ac:56: -1- AC_SUBST([STRIP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([STRIP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^STRIP$])
m4trace:configure.ac:56: -1- AC_SUBST([RANLIB])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([RANLIB])
m4trace:configure.ac:56: -1- m4_pattern_allow([^RANLIB$])
m4trace:configure.ac:56: -1- AC_SUBST([AWK])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([AWK])
m4trace:configure.ac:56: -1- m4_pattern_allow([^AWK$])
m4trace:configure.ac:56: -1- m4_pattern_allow([LT_OBJDIR])
m4trace:configure.ac:56: -1- AC_DEFINE_TRACE_LITERAL([LT_OBJDIR])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LT_OBJDIR$])
m4trace:configure.ac:56: -1- AH_OUTPUT([LT_OBJDIR], [/* Define to the sub-directory where libtool stores uninstalled libraries. */
@%:@undef LT_OBJDIR])
m4trace:configure.ac:56: -1- LT_SUPPORTED_TAG([CC])
m4trace:configure.ac:56: -1- AC_SUBST([MANIFEST_TOOL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([MANIFEST_TOOL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^MANIFEST_TOOL$])
m4trace:configure.ac:56: -1- AC_SUBST([DSYMUTIL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([DSYMUTIL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^DSYMUTIL$])
m4trace:configure.ac:56: -1- AC_SUBST([NMEDIT])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([NMEDIT])
m4trace:configure.ac:56: -1- m4_pattern_allow([^NMEDIT$])
m4trace:configure.ac:56: -1- AC_SUBST([LIPO])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([LIPO])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LIPO$])
m4trace:configure.ac:56: -1- AC_SUBST([OTOOL])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([OTOOL])
m4trace:configure.ac:56: -1- m4_pattern_allow([^OTOOL$])
m4trace:configure.ac:56: -1- AC_SUBST([OTOOL64])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([OTOOL64])
m4trace:configure.ac:56: -1- m4_pattern_allow([^OTOOL64$])
m4trace:configure.ac:56: -1- AC_SUBST([LT_SYS_LIBRARY_PATH])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([LT_SYS_LIBRARY_PATH])
m4trace:configure.ac:56: -1- m4_pattern_allow([^LT_SYS_LIBRARY_PATH$])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_DLFCN_H], [/* Define to 1 if you have the <dlfcn.h> header file. */
@%:@undef HAVE_DLFCN_H])
m4trace:configure.ac:56: -1- AC_SUBST([CPP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([CPP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^CPP$])
m4trace:configure.ac:56: -1- AC_SUBST([CPPFLAGS])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([CPPFLAGS])
m4trace:configure.ac:56: -1- m4_pattern_allow([^CPPFLAGS$])
m4trace:configure.ac:56: -1- AC_SUBST([CPP])
m4trace:configure.ac:56: -1- AC_SUBST_TRACE([CPP])
m4trace:configure.ac:56: -1- m4_pattern_allow([^CPP$])
m4trace:configure.ac:56: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS])
m4trace:configure.ac:56: -1- m4_pattern_allow([^STDC_HEADERS$])
m4trace:configure.ac:56: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */
@%:@undef STDC_HEADERS])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
@%:@undef HAVE_SYS_TYPES_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
@%:@undef HAVE_SYS_STAT_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
@%:@undef HAVE_STDLIB_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
@%:@undef HAVE_STRING_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
@%:@undef HAVE_MEMORY_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
@%:@undef HAVE_STRINGS_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
@%:@undef HAVE_INTTYPES_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
@%:@undef HAVE_STDINT_H])
m4trace:configure.ac:56: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
@%:@undef HAVE_UNISTD_H])
m4trace:configure.ac:56: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DLFCN_H])
m4trace:configure.ac:56: -1- m4_pattern_allow([^HAVE_DLFCN_H$])
m4trace:configure.ac:58: -1- AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AM_[A-Z]+FLAGS$])
m4trace:configure.ac:58: -1- AM_AUTOMAKE_VERSION([1.15])
m4trace:configure.ac:58: -1- AC_REQUIRE_AUX_FILE([install-sh])
m4trace:configure.ac:58: -1- AC_SUBST([INSTALL_PROGRAM])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([INSTALL_PROGRAM])
m4trace:configure.ac:58: -1- m4_pattern_allow([^INSTALL_PROGRAM$])
m4trace:configure.ac:58: -1- AC_SUBST([INSTALL_SCRIPT])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([INSTALL_SCRIPT])
m4trace:configure.ac:58: -1- m4_pattern_allow([^INSTALL_SCRIPT$])
m4trace:configure.ac:58: -1- AC_SUBST([INSTALL_DATA])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([INSTALL_DATA])
m4trace:configure.ac:58: -1- m4_pattern_allow([^INSTALL_DATA$])
m4trace:configure.ac:58: -1- AC_SUBST([am__isrc], [' -I$(srcdir)'])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__isrc])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__isrc$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([am__isrc])
m4trace:configure.ac:58: -1- AC_SUBST([CYGPATH_W])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([CYGPATH_W])
m4trace:configure.ac:58: -1- m4_pattern_allow([^CYGPATH_W$])
m4trace:configure.ac:58: -1- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([PACKAGE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^PACKAGE$])
m4trace:configure.ac:58: -1- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([VERSION])
m4trace:configure.ac:58: -1- m4_pattern_allow([^VERSION$])
m4trace:configure.ac:58: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^PACKAGE$])
m4trace:configure.ac:58: -1- AH_OUTPUT([PACKAGE], [/* Name of package */
@%:@undef PACKAGE])
m4trace:configure.ac:58: -1- AC_DEFINE_TRACE_LITERAL([VERSION])
m4trace:configure.ac:58: -1- m4_pattern_allow([^VERSION$])
m4trace:configure.ac:58: -1- AH_OUTPUT([VERSION], [/* Version number of package */
@%:@undef VERSION])
m4trace:configure.ac:58: -1- AC_REQUIRE_AUX_FILE([missing])
m4trace:configure.ac:58: -1- AC_SUBST([ACLOCAL])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([ACLOCAL])
m4trace:configure.ac:58: -1- m4_pattern_allow([^ACLOCAL$])
m4trace:configure.ac:58: -1- AC_SUBST([AUTOCONF])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AUTOCONF])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AUTOCONF$])
m4trace:configure.ac:58: -1- AC_SUBST([AUTOMAKE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AUTOMAKE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AUTOMAKE$])
m4trace:configure.ac:58: -1- AC_SUBST([AUTOHEADER])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AUTOHEADER])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AUTOHEADER$])
m4trace:configure.ac:58: -1- AC_SUBST([MAKEINFO])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([MAKEINFO])
m4trace:configure.ac:58: -1- m4_pattern_allow([^MAKEINFO$])
m4trace:configure.ac:58: -1- AC_SUBST([install_sh])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([install_sh])
m4trace:configure.ac:58: -1- m4_pattern_allow([^install_sh$])
m4trace:configure.ac:58: -1- AC_SUBST([STRIP])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([STRIP])
m4trace:configure.ac:58: -1- m4_pattern_allow([^STRIP$])
m4trace:configure.ac:58: -1- AC_SUBST([INSTALL_STRIP_PROGRAM])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([INSTALL_STRIP_PROGRAM])
m4trace:configure.ac:58: -1- m4_pattern_allow([^INSTALL_STRIP_PROGRAM$])
m4trace:configure.ac:58: -1- AC_REQUIRE_AUX_FILE([install-sh])
m4trace:configure.ac:58: -1- AC_SUBST([MKDIR_P])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([MKDIR_P])
m4trace:configure.ac:58: -1- m4_pattern_allow([^MKDIR_P$])
m4trace:configure.ac:58: -1- AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([mkdir_p])
m4trace:configure.ac:58: -1- m4_pattern_allow([^mkdir_p$])
m4trace:configure.ac:58: -1- AC_SUBST([SET_MAKE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([SET_MAKE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^SET_MAKE$])
m4trace:configure.ac:58: -1- AC_SUBST([am__leading_dot])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__leading_dot])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__leading_dot$])
m4trace:configure.ac:58: -1- AC_SUBST([AMTAR], ['$${TAR-tar}'])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AMTAR])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AMTAR$])
m4trace:configure.ac:58: -1- AC_SUBST([am__tar])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__tar])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__tar$])
m4trace:configure.ac:58: -1- AC_SUBST([am__untar])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__untar])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__untar$])
m4trace:configure.ac:58: -1- AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([DEPDIR])
m4trace:configure.ac:58: -1- m4_pattern_allow([^DEPDIR$])
m4trace:configure.ac:58: -1- AC_SUBST([am__include])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__include])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__include$])
m4trace:configure.ac:58: -1- AC_SUBST([am__quote])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__quote])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__quote$])
m4trace:configure.ac:58: -1- AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
m4trace:configure.ac:58: -1- AC_SUBST([AMDEP_TRUE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AMDEP_TRUE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AMDEP_TRUE$])
m4trace:configure.ac:58: -1- AC_SUBST([AMDEP_FALSE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AMDEP_FALSE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AMDEP_FALSE$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AMDEP_TRUE])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AMDEP_FALSE])
m4trace:configure.ac:58: -1- AC_SUBST([AMDEPBACKSLASH])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AMDEPBACKSLASH])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AMDEPBACKSLASH$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])
m4trace:configure.ac:58: -1- AC_SUBST([am__nodep])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__nodep])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__nodep$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([am__nodep])
m4trace:configure.ac:58: -1- AC_SUBST([CCDEPMODE], [depmode=$am_cv_CC_dependencies_compiler_type])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([CCDEPMODE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^CCDEPMODE$])
m4trace:configure.ac:58: -1- AM_CONDITIONAL([am__fastdepCC], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_CC_dependencies_compiler_type" = gcc3])
m4trace:configure.ac:58: -1- AC_SUBST([am__fastdepCC_TRUE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__fastdepCC_TRUE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__fastdepCC_TRUE$])
m4trace:configure.ac:58: -1- AC_SUBST([am__fastdepCC_FALSE])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([am__fastdepCC_FALSE])
m4trace:configure.ac:58: -1- m4_pattern_allow([^am__fastdepCC_FALSE$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([am__fastdepCC_TRUE])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([am__fastdepCC_FALSE])
m4trace:configure.ac:58: -1- AM_SILENT_RULES
m4trace:configure.ac:58: -1- AC_SUBST([AM_V])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AM_V])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AM_V$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AM_V])
m4trace:configure.ac:58: -1- AC_SUBST([AM_DEFAULT_V])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AM_DEFAULT_V])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AM_DEFAULT_V$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AM_DEFAULT_V])
m4trace:configure.ac:58: -1- AC_SUBST([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AM_DEFAULT_VERBOSITY])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AM_DEFAULT_VERBOSITY$])
m4trace:configure.ac:58: -1- AC_SUBST([AM_BACKSLASH])
m4trace:configure.ac:58: -1- AC_SUBST_TRACE([AM_BACKSLASH])
m4trace:configure.ac:58: -1- m4_pattern_allow([^AM_BACKSLASH$])
m4trace:configure.ac:58: -1- _AM_SUBST_NOTMAKE([AM_BACKSLASH])
m4trace:configure.ac:59: -1- AM_MAINTAINER_MODE
m4trace:configure.ac:59: -1- AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
m4trace:configure.ac:59: -1- AC_SUBST([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:59: -1- AC_SUBST_TRACE([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:59: -1- m4_pattern_allow([^MAINTAINER_MODE_TRUE$])
m4trace:configure.ac:59: -1- AC_SUBST([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:59: -1- AC_SUBST_TRACE([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:59: -1- m4_pattern_allow([^MAINTAINER_MODE_FALSE$])
m4trace:configure.ac:59: -1- _AM_SUBST_NOTMAKE([MAINTAINER_MODE_TRUE])
m4trace:configure.ac:59: -1- _AM_SUBST_NOTMAKE([MAINTAINER_MODE_FALSE])
m4trace:configure.ac:59: -1- AC_SUBST([MAINT])
m4trace:configure.ac:59: -1- AC_SUBST_TRACE([MAINT])
m4trace:configure.ac:59: -1- m4_pattern_allow([^MAINT$])
m4trace:configure.ac:85: -1- AH_OUTPUT([HAVE_ELF_H], [/* Define to 1 if you have the <elf.h> header file. */
@%:@undef HAVE_ELF_H])
m4trace:configure.ac:85: -1- AH_OUTPUT([HAVE_GELF_H], [/* Define to 1 if you have the <gelf.h> header file. */
@%:@undef HAVE_GELF_H])
m4trace:configure.ac:88: -1- AH_OUTPUT([HAVE_LIBELF], [/* Define to 1 if you have the `elf\' library (-lelf). */
@%:@undef HAVE_LIBELF])
m4trace:configure.ac:88: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBELF])
m4trace:configure.ac:88: -1- m4_pattern_allow([^HAVE_LIBELF$])
m4trace:configure.ac:96: -1- AH_OUTPUT([HAVE_BFD_H], [/* Define to 1 if you have the <bfd.h> header file. */
@%:@undef HAVE_BFD_H])
m4trace:configure.ac:96: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BFD_H])
m4trace:configure.ac:96: -1- m4_pattern_allow([^HAVE_BFD_H$])
m4trace:configure.ac:99: -1- AH_OUTPUT([HAVE_LIBBFD], [/* Define to 1 if you have the `bfd\' library (-lbfd). */
@%:@undef HAVE_LIBBFD])
m4trace:configure.ac:99: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBBFD])
m4trace:configure.ac:99: -1- m4_pattern_allow([^HAVE_LIBBFD$])
m4trace:configure.ac:104: -1- AH_OUTPUT([HAVE_PTHREAD_H], [/* Define to 1 if you have the <pthread.h> header file. */
@%:@undef HAVE_PTHREAD_H])
m4trace:configure.ac:104: -1- AC_DEFINE_TRACE_LITERAL([HAVE_PTHREAD_H])
m4trace:configure.ac:104: -1- m4_pattern_allow([^HAVE_PTHREAD_H$])
m4trace:configure.ac:107: -1- AH_OUTPUT([HAVE_LIBPTHREAD], [/* Define to 1 if you have the `pthread\' library (-lpthread). */
@%:@undef HAVE_LIBPTHREAD])
m4trace:configure.ac:107: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBPTHREAD])
m4trace:configure.ac:107: -1- m4_pattern_allow([^HAVE_LIBPTHREAD$])
m4trace:configure.ac:112: -1- AH_OUTPUT([HAVE_DLFCN_H], [/* Define to 1 if you have the <dlfcn.h> header file. */
@%:@undef HAVE_DLFCN_H])
m4trace:configure.ac:112: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DLFCN_H])
m4trace:configure.ac:112: -1- m4_pattern_allow([^HAVE_DLFCN_H$])
m4trace:configure.ac:115: -1- AH_OUTPUT([HAVE_LIBDL], [/* Define to 1 if you have the `dl\' library (-ldl). */
@%:@undef HAVE_LIBDL])
m4trace:configure.ac:115: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBDL])
m4trace:configure.ac:115: -1- m4_pattern_allow([^HAVE_LIBDL$])
m4trace:configure.ac:123: -1- AH_OUTPUT([HAVE_LIBTERMCAP], [/* Define to 1 if you have the `termcap\' library (-ltermcap). */
@%:@undef HAVE_LIBTERMCAP])
m4trace:configure.ac:123: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBTERMCAP])
m4trace:configure.ac:123: -1- m4_pattern_allow([^HAVE_LIBTERMCAP$])
m4trace:configure.ac:127: -1- AH_OUTPUT([HAVE_READLINE_READLINE_H], [/* Define to 1 if you have the <readline/readline.h> header file. */
@%:@undef HAVE_READLINE_READLINE_H])
m4trace:configure.ac:127: -1- AC_DEFINE_TRACE_LITERAL([HAVE_READLINE_READLINE_H])
m4trace:configure.ac:127: -1- m4_pattern_allow([^HAVE_READLINE_READLINE_H$])
m4trace:configure.ac:130: -1- AH_OUTPUT([HAVE_LIBREADLINE], [/* Define to 1 if you have the `readline\' library (-lreadline). */
@%:@undef HAVE_LIBREADLINE])
m4trace:configure.ac:130: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBREADLINE])
m4trace:configure.ac:130: -1- m4_pattern_allow([^HAVE_LIBREADLINE$])
m4trace:configure.ac:136: -1- AH_OUTPUT([HAVE_SELINUX_SELINUX_H], [/* Define to 1 if you have the <selinux/selinux.h> header file. */
@%:@undef HAVE_SELINUX_SELINUX_H])
m4trace:configure.ac:136: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SELINUX_SELINUX_H])
m4trace:configure.ac:136: -1- m4_pattern_allow([^HAVE_SELINUX_SELINUX_H$])
m4trace:configure.ac:137: -1- AH_OUTPUT([HAVE_LIBSELINUX], [/* Define to 1 if you have the `selinux\' library (-lselinux). */
@%:@undef HAVE_LIBSELINUX])
m4trace:configure.ac:137: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSELINUX])
m4trace:configure.ac:137: -1- m4_pattern_allow([^HAVE_LIBSELINUX$])
m4trace:configure.ac:146: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ELF_C_READ_MMAP])
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
m4trace:configure.ac:146: -1- AH_OUTPUT([HAVE_ELF_C_READ_MMAP], [/* we have read mmap support */
@%:@undef HAVE_ELF_C_READ_MMAP])
m4trace:configure.ac:159: -1- AC_DEFINE_TRACE_LITERAL([ELF_HASH_TAKES_CHARP])
m4trace:configure.ac:159: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
m4trace:configure.ac:159: -1- AH_OUTPUT([ELF_HASH_TAKES_CHARP], [/* elf_hash() takes char* (as opposed to unsigned char *) */
@%:@undef ELF_HASH_TAKES_CHARP])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
@%:@undef HAVE_FCNTL_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
@%:@undef HAVE_LIMITS_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
@%:@undef HAVE_STDDEF_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
@%:@undef HAVE_STDINT_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
@%:@undef HAVE_STDLIB_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
@%:@undef HAVE_STRING_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_IOCTL_H], [/* Define to 1 if you have the <sys/ioctl.h> header file. */
@%:@undef HAVE_SYS_IOCTL_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
@%:@undef HAVE_SYS_PARAM_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
@%:@undef HAVE_SYS_TIME_H])
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
@%:@undef HAVE_UNISTD_H])
m4trace:configure.ac:194: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
m4trace:configure.ac:194: -1- m4_pattern_allow([^uid_t$])
m4trace:configure.ac:194: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
@%:@undef uid_t])
m4trace:configure.ac:194: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
m4trace:configure.ac:194: -1- m4_pattern_allow([^gid_t$])
m4trace:configure.ac:194: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
@%:@undef gid_t])
m4trace:configure.ac:195: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
calls it, or to nothing if \'inline\' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif])
m4trace:configure.ac:196: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
m4trace:configure.ac:196: -1- m4_pattern_allow([^pid_t$])
m4trace:configure.ac:196: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
@%:@undef pid_t])
m4trace:configure.ac:197: -1- AC_DEFINE_TRACE_LITERAL([size_t])
m4trace:configure.ac:197: -1- m4_pattern_allow([^size_t$])
m4trace:configure.ac:197: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
@%:@undef size_t])
m4trace:configure.ac:198: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG])
m4trace:configure.ac:198: -1- m4_pattern_allow([^SIZEOF_LONG$])
m4trace:configure.ac:198: -1- AH_OUTPUT([SIZEOF_LONG], [/* The size of `long\', as computed by sizeof. */
@%:@undef SIZEOF_LONG])
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.h])
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.c])
m4trace:configure.ac:202: -1- AC_SUBST([LIB@&t@OBJS], ["$LIB@&t@OBJS error.$ac_objext"])
m4trace:configure.ac:202: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
m4trace:configure.ac:202: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.c])
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_VFORK_H], [/* Define to 1 if you have the <vfork.h> header file. */
@%:@undef HAVE_VFORK_H])
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VFORK_H])
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_VFORK_H$])
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_FORK], [/* Define to 1 if you have the `fork\' function. */
@%:@undef HAVE_FORK])
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_VFORK], [/* Define to 1 if you have the `vfork\' function. */
@%:@undef HAVE_VFORK])
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_VFORK])
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_WORKING_VFORK], [/* Define to 1 if `vfork\' works. */
@%:@undef HAVE_WORKING_VFORK])
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([vfork])
m4trace:configure.ac:203: -1- m4_pattern_allow([^vfork$])
m4trace:configure.ac:203: -1- AH_OUTPUT([vfork], [/* Define as `fork\' if `vfork\' does not work. */
@%:@undef vfork])
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_FORK])
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_WORKING_FORK], [/* Define to 1 if `fork\' works. */
@%:@undef HAVE_WORKING_FORK])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_ALARM], [/* Define to 1 if you have the `alarm\' function. */
@%:@undef HAVE_ALARM])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_ATEXIT], [/* Define to 1 if you have the `atexit\' function. */
@%:@undef HAVE_ATEXIT])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
@%:@undef HAVE_GETCWD])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
@%:@undef HAVE_GETTIMEOFDAY])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
@%:@undef HAVE_MEMSET])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_MKDIR], [/* Define to 1 if you have the `mkdir\' function. */
@%:@undef HAVE_MKDIR])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_RMDIR], [/* Define to 1 if you have the `rmdir\' function. */
@%:@undef HAVE_RMDIR])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRCHR], [/* Define to 1 if you have the `strchr\' function. */
@%:@undef HAVE_STRCHR])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
@%:@undef HAVE_STRDUP])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRERROR], [/* Define to 1 if you have the `strerror\' function. */
@%:@undef HAVE_STRERROR])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRTOL], [/* Define to 1 if you have the `strtol\' function. */
@%:@undef HAVE_STRTOL])
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
@%:@undef HAVE_STRTOUL])
m4trace:configure.ac:233: -1- AC_DEFINE_TRACE_LITERAL([DEBUG])
m4trace:configure.ac:233: -1- m4_pattern_allow([^DEBUG$])
m4trace:configure.ac:233: -1- AH_OUTPUT([DEBUG], [/* debugging */
@%:@undef DEBUG])
m4trace:configure.ac:247: -1- AC_SUBST([AM_CPPFLAGS])
m4trace:configure.ac:247: -1- AC_SUBST_TRACE([AM_CPPFLAGS])
m4trace:configure.ac:247: -1- m4_pattern_allow([^AM_CPPFLAGS$])
m4trace:configure.ac:248: -1- AC_SUBST([AM_CFLAGS])
m4trace:configure.ac:248: -1- AC_SUBST_TRACE([AM_CFLAGS])
m4trace:configure.ac:248: -1- m4_pattern_allow([^AM_CFLAGS$])
m4trace:configure.ac:249: -1- AC_SUBST([AM_LDFLAGS])
m4trace:configure.ac:249: -1- AC_SUBST_TRACE([AM_LDFLAGS])
m4trace:configure.ac:249: -1- m4_pattern_allow([^AM_LDFLAGS$])
m4trace:configure.ac:250: -1- AC_SUBST([libelf_LD_LIBRARY_PATH])
m4trace:configure.ac:250: -1- AC_SUBST_TRACE([libelf_LD_LIBRARY_PATH])
m4trace:configure.ac:250: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
m4trace:configure.ac:252: -1- AC_CONFIG_FILES([
Makefile
client/Makefile
sysdeps/Makefile
sysdeps/linux-gnu/Makefile
sysdeps/linux-gnu/x86/Makefile
sysdeps/linux-gnu/ppc/Makefile
sysdeps/linux-gnu/arm/Makefile
])
m4trace:configure.ac:261: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
m4trace:configure.ac:261: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.ac:261: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([LTLIBOBJS])
m4trace:configure.ac:261: -1- m4_pattern_allow([^LTLIBOBJS$])
m4trace:configure.ac:261: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
m4trace:configure.ac:261: -1- AC_SUBST([am__EXEEXT_TRUE])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
m4trace:configure.ac:261: -1- AC_SUBST([am__EXEEXT_FALSE])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_builddir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_build_prefix])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([srcdir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_srcdir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_srcdir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_top_srcdir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([builddir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_builddir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_top_builddir])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([INSTALL])
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([MKDIR_P])
m4trace:configure.ac:261: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])

169
backend.h Normal file
View File

@ -0,0 +1,169 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata, Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_BACKEND_H
#define _INC_BACKEND_H
#include "config.h"
#include "arch.h"
#include "os.h"
#include "forward.h"
#include "mtrace.h"
#include <stddef.h>
#include <sys/types.h>
/* Convert a PID to a path to the corresponding binary. */
char *pid2name(pid_t pid);
/* Given a PID, find a leader of thread group. */
pid_t process_leader(pid_t pid);
/* Given a PID of leader thread, fill in PIDs of all the tasks. The
* function will initialize the pointer *RET_TASKS to a
* newly-allocated array, and will store number of elements in that
* array to *RET_N. You have to free that buffer when you don't need
* it anymore. */
int process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n);
/* set tracing options, the task must be in state traced */
int trace_set_options(struct task *task);
/* make the forked process traceable */
void trace_me(void);
/* stop tracing a task. */
int untrace_task(struct task *task, int signum);
/* Called when mtrace needs to attach to task, such as when it attaches
* to a running process, whose PID is given on the command line. */
int trace_attach(struct task *task);
/* wait for a task ready for tracing */
int trace_wait(struct task *task);
/* continue process */
int continue_task(struct task *task, int signum);
/* Return current instruction pointer */
arch_addr_t get_instruction_pointer(struct task *task);
/* Set instruction pointer of task to addr */
void set_instruction_pointer(struct task *task, arch_addr_t addr);
/* do a single step */
int do_singlestep(struct task *task);
/* handle a single step event */
int handle_singlestep(struct task *task, int (*singlestep)(struct task *task));
/* Find and return caller address, i.e. the address where the current
* function returns. */
arch_addr_t get_return_addr(struct task *task);
/* set instruction hw breakpoint */
int set_hw_bp(struct task *task, unsigned int slot, arch_addr_t addr);
/* remove instruction hw breakpoint */
int reset_hw_bp(struct task *task, unsigned int slot, arch_addr_t addr);
/* save the process context (state, registers, stack pointer) */
int fetch_context(struct task *task);
/* save the process context for parameter fetching */
void save_param_context(struct task *task);
/* get return value of a remote function */
unsigned long fetch_retval(struct task *task);
/* get parameter value of a remote function */
unsigned long fetch_param(struct task *task, unsigned int param);
/* get register value of a remote function */
unsigned long fetch_reg(struct task *task, unsigned int reg);
/* Should copy len bytes from address addr of task to local buffer dst */
ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t len);
/* Should copy len bytes from local buffer src to address addr of the remote task */
ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_t len);
/* Should copy len bytes from address addr of remote task to local
* buffer dst and overwrite the task data with src */
ssize_t copy_from_to_proc(struct task *task, arch_addr_t addr, const void *src, void *dst, size_t len);
/* Should copy max. len of a string from address addr from the remote task
* to local buffer dst */
ssize_t copy_str_from_proc(struct task *task, arch_addr_t addr, char *dst, size_t len);
/* Called at some point after we have attached to PROC. This callback
* should insert an introspection breakpoint for handling dynamic
* linker library loads. */
int linkmap_init(struct task *task, arch_addr_t dyn_addr);
/* This should extract entry point address and interpreter (dynamic
* linker) bias if possible. Returns 0 if there were no errors, -1
* otherwise. Sets *ENTRYP and *INTERP_BIASP to non-zero values if
* the corresponding value is known, or zero otherwise; this is not
* done for pointers that are NULL. */
int process_get_entry(struct task *task, unsigned long *entryp, unsigned long *interp_biasp);
/* The following callbacks have to be implemented in OS backend if
* os.h defines OS_HAVE_PROCESS_DATA. */
#ifdef OS_HAVE_PROCESS_DATA
int os_task_init(struct task *task);
void os_task_destroy(struct task *task);
int os_task_clone(struct task *retp, struct task *task);
#endif
/* The following callbacks have to be implemented in OS backend if
* os.h defines ARCH_HAVE_PROCESS_DATA. */
#ifdef ARCH_HAVE_PROCESS_DATA
int arch_task_init(struct task *task);
void arch_task_destroy(struct task *task);
int arch_task_clone(struct task *retp, struct task *task);
#endif
/* stop all thread of a given task */
void stop_threads(struct task *task);
/* scan writeable memory segments */
void *mem_scan(struct task *task, struct mt_msg *cmd, void *payload, unsigned long *data_len);
/* os specific init */
int os_init(void);
/* wait for the next unqueued trace event */
struct task *wait_event();
/* wakeup a wait_event() call */
void wait_event_wakeup(void);
/* return true the elf file is 64 bit */
int is_64bit(struct mt_elf *mte);
/* change user id of a running process */
void change_uid(const char *command);
#endif

42
backtrace.h Normal file
View File

@ -0,0 +1,42 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_BACKTRACE_H
#define _INC_BACKTRACE_H
#include "task.h"
/* init backtrace for given task */
int backtrace_init(struct task *task);
/* destroy backtrace for given task */
void backtrace_destroy(struct task *task);
/* start backtrace for given task */
int backtrace_init_unwind(struct task *task);
/* get backtrace IP address for given task */
unsigned long backtrace_get_ip(struct task *task);
/* step to next backtrace given task */
int backtrace_step(struct task *task);
#endif

9
bootstrap Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
make clean
make maintainer-clean
rm -rf config autom4te.cache
libtoolize -c
aclocal
autoheader
automake --add-missing -c
autoconf

518
breakpoint.c Normal file
View File

@ -0,0 +1,518 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2006,2007,2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2009 Juan Cespedes
* Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "backend.h"
#include "breakpoint.h"
#include "debug.h"
#include "library.h"
#include "mtelf.h"
#include "report.h"
#include "task.h"
#include "trace.h"
#define HW_BP_SCRATCH_SLOT 0
static unsigned int target_address_hash(unsigned long key)
{
unsigned int i;
unsigned int h = 4713;
union {
arch_addr_t addr;
uint8_t v[sizeof(arch_addr_t) / sizeof(uint8_t)];
} u = { .addr = ARCH_ADDR_T(key) };
for (i = 0; i < ARRAY_SIZE(u.v); ++i)
h = (h >> 1) ^ u.v[i];
return h;
}
static int target_address_cmp(unsigned long key1, unsigned long key2)
{
arch_addr_t addr1 = ARCH_ADDR_T(key1);
arch_addr_t addr2 = ARCH_ADDR_T(key2);
return addr1 < addr2 ? 1 : addr1 > addr2 ? -1 : 0;
}
static void enable_sw_breakpoint(struct task *task, struct breakpoint *bp)
{
static unsigned char break_insn[] = BREAKPOINT_VALUE;
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
copy_from_to_proc(task, bp->addr, break_insn, bp->orig_value, BREAKPOINT_LENGTH);
}
static void disable_sw_breakpoint(struct task *task, const struct breakpoint *bp)
{
debug(DEBUG_PROCESS, "pid=%d, addr=%lx", task->pid, bp->addr);
copy_to_proc(task, bp->addr, bp->orig_value, BREAKPOINT_LENGTH);
}
int breakpoint_on_hit(struct task *task, struct breakpoint *bp)
{
if (bp->on_hit)
return (bp->on_hit)(task, bp);
return 0;
}
struct breakpoint *breakpoint_find(struct task *task, arch_addr_t addr)
{
struct task *leader = task->leader;
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", leader->pid, addr);
return (struct breakpoint *)dict_find_entry(leader->breakpoints, (unsigned long)addr);
}
#if HW_BREAKPOINTS > 0
#if HW_BREAKPOINTS > 1
static int find_hw_bp_slot(struct task *leader)
{
int i;
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i)
if ((leader->hw_bp_mask & (1 << i)) == 0)
return i;
return -1;
}
#endif
static void enable_hw_bp(struct task *task, struct breakpoint *bp)
{
int slot = bp->hw_bp_slot;
if (bp->hw_bp_slot != HW_BP_SCRATCH_SLOT)
assert(task->hw_bp[slot] == NULL);
task->hw_bp[slot] = bp;
if (set_hw_bp(task, slot, bp->addr) == -1)
fatal("set_hw_bp");
}
void breakpoint_hw_clone(struct task *task)
{
int i;
struct task *leader = task->leader;
if (leader == task)
return;
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i) {
if ((leader->hw_bp_mask & (1 << i)) == 0) {
assert(task->hw_bp[i] == NULL);
continue;
}
assert(leader->hw_bp[i]->hw_bp_slot == i);
enable_hw_bp(task, leader->hw_bp[i]);
}
}
static void disable_hw_bp(struct task *task, struct breakpoint *bp)
{
int slot = bp->hw_bp_slot;
assert(task->hw_bp[slot] == bp);
task->hw_bp[slot] = NULL;
if (reset_hw_bp(task, slot, bp->addr) == -1)
fatal("reset_hw_bp");
}
void breakpoint_hw_destroy(struct task *task)
{
int i;
for(i = 0; i < HW_BREAKPOINTS; ++i) {
if (task->hw_bp[i]) {
assert(task->hw_bp[i]->hw_bp_slot == i);
disable_hw_bp(task, task->hw_bp[i]);
}
}
}
void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
{
if (bp->type == SW_BP)
return;
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
if (task->hw_bp[bp->hw_bp_slot] != bp)
enable_hw_bp(task, bp);
}
static void enable_hw_bp_cb(struct task *task, void *data)
{
enable_hw_bp(task, data);
}
void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
{
if (bp->type == SW_BP)
return;
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
disable_hw_bp(task, bp);
}
static void disable_hw_bp_cb(struct task *task, void *data)
{
disable_hw_bp(task, data);
}
static void remove_hw_scratch_bp_cb(struct task *task, void *data)
{
if (task->hw_bp[HW_BP_SCRATCH_SLOT] == data) {
assert(task->hw_bp[HW_BP_SCRATCH_SLOT]->hw_bp_slot == HW_BP_SCRATCH_SLOT);
disable_hw_bp(task, data);
}
}
#endif
struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int bp_type, size_t ext)
{
struct task *leader = task->leader;
struct breakpoint *bp = malloc(sizeof(*bp) + ext);
if (bp == NULL)
goto fail1;
bp->on_hit = NULL;
bp->libsym = libsym;
bp->addr = addr;
bp->enabled = 0;
bp->locked = 0;
bp->ext = ext;
switch(bp_type) {
case HW_BP_SCRATCH:
#if HW_BREAKPOINTS > 0
bp->type = HW_BP_SCRATCH;
bp->hw_bp_slot = HW_BP_SCRATCH_SLOT;
break;
#endif
case HW_BP:
#if HW_BREAKPOINTS > 1
{
int slot = find_hw_bp_slot(leader);
if (slot > 0) {
leader->hw_bp_mask |= (1 << slot);
bp->type = HW_BP;
bp->hw_bp_slot = slot;
break;
}
}
#endif
case SW_BP:
bp->type = SW_BP;
memset(bp->orig_value, 0, sizeof(bp->orig_value));
}
if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) {
fprintf(stderr, "couldn't enter breakpoint %lx to dictionary\n", addr);
goto fail2;
}
return bp;
fail2:
free(bp);
fail1:
return NULL;
}
struct breakpoint *breakpoint_new(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int type)
{
return breakpoint_new_ext(task, addr, libsym, type, 0);
}
void breakpoint_enable(struct task *task, struct breakpoint *bp)
{
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
if (!bp->enabled) {
#if HW_BREAKPOINTS > 0
if (bp->type != SW_BP) {
if (bp->type == HW_BP)
each_task(task->leader, enable_hw_bp_cb, bp);
}
else
#endif
{
stop_threads(task);
enable_sw_breakpoint(task, bp);
}
bp->enabled = 1;
}
}
void breakpoint_disable(struct task *task, struct breakpoint *bp)
{
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
if (bp->enabled) {
#if HW_BREAKPOINTS > 0
if (bp->type != SW_BP) {
if (bp->type == HW_BP)
each_task(task->leader, disable_hw_bp_cb, bp);
else
each_task(task->leader, remove_hw_scratch_bp_cb, bp);
}
else
#endif
{
stop_threads(task);
disable_sw_breakpoint(task, bp);
}
bp->enabled = 0;
}
}
struct breakpoint *breakpoint_insert(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int type)
{
debug(DEBUG_FUNCTION, "pid=%d, addr=%lx, symbol=%s", task->pid, addr, libsym ? libsym->func->name : "NULL");
if (!addr)
return NULL;
struct breakpoint *bp = breakpoint_find(task, addr);
if (!bp) {
bp = breakpoint_new(task, addr, libsym, type);
if (!bp)
return NULL;
}
breakpoint_enable(task, bp);
return bp;
}
void breakpoint_delete(struct task *task, struct breakpoint *bp)
{
struct task *leader = task->leader;
debug(DEBUG_FUNCTION, "pid=%d, addr=%lx", task->pid, bp->addr);
breakpoint_disable(task, bp);
#if HW_BREAKPOINTS > 0
if (bp->type != SW_BP) {
int slot = bp->hw_bp_slot;
if (bp->type == HW_BP) {
assert(slot != HW_BP_SCRATCH_SLOT);
leader->hw_bp_mask &= ~(1 << slot);
}
else
assert(slot == HW_BP_SCRATCH_SLOT);
}
#endif
dict_remove_entry(leader->breakpoints, (unsigned long)bp->addr);
free(bp);
}
static int enable_nonlocked_bp_cb(unsigned long key, const void *value, void *data)
{
struct breakpoint *bp = (struct breakpoint *)value;
struct task *leader = (struct task *)data;
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (!bp->locked)
breakpoint_enable(leader, bp);
return 0;
}
void breakpoint_enable_all_nonlocked(struct task *leader)
{
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (leader->breakpoints)
dict_apply_to_all(leader->breakpoints, enable_nonlocked_bp_cb, leader);
}
static int disable_nonlocked_bp_cb(unsigned long key, const void *value, void *data)
{
struct breakpoint *bp = (struct breakpoint *)value;
struct task *leader = (struct task *)data;
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (!bp->locked)
breakpoint_disable(leader, bp);
return 0;
}
void breakpoint_disable_all_nonlocked(struct task *leader)
{
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (leader->breakpoints)
dict_apply_to_all(leader->breakpoints, disable_nonlocked_bp_cb, leader);
}
static int enable_bp_cb(unsigned long key, const void *value, void *data)
{
struct breakpoint *bp = (struct breakpoint *)value;
struct task *leader = (struct task *)data;
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
breakpoint_enable(leader, bp);
return 0;
}
void breakpoint_enable_all(struct task *leader)
{
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (leader->breakpoints)
dict_apply_to_all(leader->breakpoints, enable_bp_cb, leader);
}
static int disable_bp_cb(unsigned long key, const void *value, void *data)
{
struct breakpoint *bp = (struct breakpoint *)value;
struct task *leader = (struct task *)data;
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
breakpoint_disable(leader, bp);
return 0;
}
void breakpoint_disable_all(struct task *leader)
{
debug(DEBUG_FUNCTION, "pid=%d", leader->pid);
if (leader->breakpoints)
dict_apply_to_all(leader->breakpoints, disable_bp_cb, leader);
}
static int destroy_breakpoint_cb(unsigned long key, const void *value, void *data)
{
free((struct breakpoint *)value);
return 0;
}
void breakpoint_clear_all(struct task *leader)
{
if (leader->breakpoints) {
dict_apply_to_all(leader->breakpoints, &destroy_breakpoint_cb, leader);
dict_clear(leader->breakpoints);
leader->breakpoints = NULL;
}
}
void breakpoint_setup(struct task *leader)
{
leader->breakpoints = dict_init(12401, target_address_hash, target_address_cmp);
}
static int clone_single_cb(unsigned long key, const void *value, void *data)
{
struct breakpoint *bp = (struct breakpoint *)value;
struct task *new_task = (struct task *)data;
struct library_symbol *libsym = bp->libsym ? find_symbol(new_task, bp->libsym->addr) : NULL;
size_t ext = bp->ext;
struct breakpoint *new_bp = malloc(sizeof(*new_bp) + ext);
if (!new_bp)
goto fail1;
new_bp->libsym = libsym;
new_bp->addr = bp->addr;
new_bp->on_hit = bp->on_hit;
new_bp->enabled = bp->enabled;
new_bp->locked = bp->locked;
new_bp->type = bp->type;
new_bp->ext = ext;
#if HW_BREAKPOINT > 0
if (new_bp->type != SW_BP) {
new_bp->hw_bp_slot = bp->hw_bp_slot;
if (bp->type == HW_BP) {
assert(new_bp->hw_bp_slot != HW_BP_SCRATCH_SLOT);
new_task->hw_bp[new_bp->hw_bp_slot] = new_bp;
if (new_bp->enabled) {
if (set_hw_bp(new_task, new_bp->hw_bp_slot, new_bp->addr) == -1)
fatal("set_hw_bp");
}
}
else
assert(new_bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
}
else
#endif
memcpy(new_bp->orig_value, bp->orig_value, sizeof(bp->orig_value));
if (ext)
memcpy((void *)new_bp + ext, (void *)bp + ext, ext);
if (dict_add(new_task->leader->breakpoints, (unsigned long)new_bp->addr, new_bp) < 0) {
fprintf(stderr, "couldn't enter breakpoint %lx to dictionary\n", new_bp->addr);
goto fail2;
}
return 0;
fail2:
free(new_bp);
fail1:
return -1;
}
int breakpoint_clone_all(struct task *clone, struct task *leader)
{
return dict_apply_to_all(leader->breakpoints, &clone_single_cb, clone);
}

108
breakpoint.h Normal file
View File

@ -0,0 +1,108 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_BREAKPOINT_H
#define _INC_BREAKPOINT_H
#include "sysdep.h"
#include "forward.h"
#define SW_BP 0
#define HW_BP 1
#define HW_BP_SCRATCH 2
struct breakpoint {
int (*on_hit)(struct task *task, struct breakpoint *bp);
struct library_symbol *libsym;
arch_addr_t addr;
unsigned int enabled:1;
unsigned int locked:1;
unsigned int type:2;
unsigned int ext:8;
union {
unsigned char orig_value[BREAKPOINT_LENGTH];
#if HW_BREAKPOINTS > 0
int hw_bp_slot;
#endif
};
};
/* setup the basic breakpoint support for a given leader */
void breakpoint_setup(struct task *leader);
/* Call on-hit handler of BP, if any is set. */
int breakpoint_on_hit(struct task *task, struct breakpoint *bp);
/* get a new breakpoint structure. */
struct breakpoint *breakpoint_new(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int type);
/* get a new extended breakpoint structure . */
struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int type, size_t ext);
/* insert a new breakpoint structure if necessary and turn the breakpoint on */
struct breakpoint *breakpoint_insert(struct task *task, arch_addr_t addr, struct library_symbol *libsym, int type);
/* delete a breakpoint in task */
void breakpoint_delete(struct task *task, struct breakpoint *bp);
/* Enable breakpoint in task */
void breakpoint_enable(struct task *task, struct breakpoint *bp);
/* Disable task breakpoint task */
void breakpoint_disable(struct task *task, struct breakpoint *bp);
void breakpoint_enable_all(struct task *leader);
void breakpoint_disable_all(struct task *leader);
void breakpoint_enable_all_nonlocked(struct task *leader);
void breakpoint_disable_all_nonlocked(struct task *leader);
void breakpoint_clear_all(struct task *leader);
int breakpoint_clone_all(struct task *clone, struct task *leader);
struct breakpoint *breakpoint_find(struct task *leader, arch_addr_t addr);
#if HW_BREAKPOINTS > 0
void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp);
void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp);
void breakpoint_hw_clone(struct task *task);
void breakpoint_hw_destroy(struct task *task);
#else
static inline void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
{
}
static inline void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
{
}
static inline void breakpoint_hw_clone(struct task *task)
{
}
static inline void breakpoint_hw_destroy(struct task *task)
{
}
#endif
#endif

33
client/Makefile.am Normal file
View File

@ -0,0 +1,33 @@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
noinst_LTLIBRARIES = \
../libclient.la
___libclient_la_SOURCES = \
binfile.c \
client.c \
dump.c \
job.c \
process.c \
readline.c
noinst_HEADERS = bfdinc.h binfile.h client.h dump.h job.h process.h
MAINTAINERCLEANFILES = \
Makefile.in

639
client/Makefile.in Normal file
View File

@ -0,0 +1,639 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = client
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
$(top_srcdir)/config/m4/ltoptions.m4 \
$(top_srcdir)/config/m4/ltsugar.m4 \
$(top_srcdir)/config/m4/ltversion.m4 \
$(top_srcdir)/config/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
___libclient_la_LIBADD =
am____libclient_la_OBJECTS = binfile.lo client.lo dump.lo job.lo \
process.lo readline.lo
___libclient_la_OBJECTS = $(am____libclient_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
am__dirstamp = $(am__leading_dot)dirstamp
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(___libclient_la_SOURCES)
DIST_SOURCES = $(___libclient_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/config/autoconf/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HOST_CPU = @HOST_CPU@
HOST_OS = @HOST_OS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = \
../libclient.la
___libclient_la_SOURCES = \
binfile.c \
client.c \
dump.c \
job.c \
process.c \
readline.c
noinst_HEADERS = bfdinc.h binfile.h client.h dump.h job.h process.h
MAINTAINERCLEANFILES = \
Makefile.in
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign client/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign client/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
../$(am__dirstamp):
@$(MKDIR_P) ..
@: > ../$(am__dirstamp)
../libclient.la: $(___libclient_la_OBJECTS) $(___libclient_la_DEPENDENCIES) $(EXTRA____libclient_la_DEPENDENCIES) ../$(am__dirstamp)
$(AM_V_CCLD)$(LINK) $(___libclient_la_OBJECTS) $(___libclient_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf ../.libs ../_libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f ../$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

39
client/bfdinc.h Normal file
View File

@ -0,0 +1,39 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_BININC_H
#define _INC_CLIENT_BININC_H
#include "config.h"
#ifndef PACKAGE
#define PACKAGE "binfile"
#endif
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "1.0"
#endif
#include <bfd.h>
#undef PACKAGE
#undef PACKAGE_VERSION
#endif

229
client/binfile.c Normal file
View File

@ -0,0 +1,229 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <execinfo.h>
#include <link.h>
#include <stdio.h>
#include "binfile.h"
#include "process.h"
/* These variables are used to pass information between
translate_addresses and find_address_in_section. */
struct sym_info {
bfd_vma pc;
asymbol **syms;
const char *filename;
const char *functionname;
unsigned int line;
bfd_boolean found;
};
static long slurp_symtab(struct bin_file *binfile)
{
long storage;
long symcount;
bfd_boolean dynamic = FALSE;
if ((bfd_get_file_flags(binfile->abfd) & HAS_SYMS) == 0)
return 0;
storage = bfd_get_symtab_upper_bound(binfile->abfd);
if (storage == 0) {
storage = bfd_get_dynamic_symtab_upper_bound(binfile->abfd);
dynamic = TRUE;
}
if (storage < 0)
return 0;
binfile->syms = (asymbol **)malloc(storage);
if (dynamic)
symcount = bfd_canonicalize_dynamic_symtab(binfile->abfd, binfile->syms);
else
symcount = bfd_canonicalize_symtab(binfile->abfd, binfile->syms);
if (symcount < 0)
return 0;
/* If there are no symbols left after canonicalization and
we have not tried the dynamic symbols then give them a go. */
if (symcount == 0 && ! dynamic && (storage = bfd_get_dynamic_symtab_upper_bound(binfile->abfd)) > 0) {
free(binfile->syms);
binfile->syms = malloc(storage);
symcount = bfd_canonicalize_dynamic_symtab(binfile->abfd, binfile->syms);
}
return symcount;
}
static void find_address_in_section(bfd *abfd, asection *section, void *data __attribute__ ((__unused__)))
{
bfd_vma vma;
bfd_size_type size;
struct sym_info *psi = (struct sym_info *) data;
if (psi->found)
return;
if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
return;
vma = bfd_get_section_vma(abfd, section);
if (psi->pc < vma)
return;
size = bfd_section_size(abfd, section);
if (psi->pc >= vma + size)
return;
psi->found = bfd_find_nearest_line(abfd, section, psi->syms, psi->pc - vma, &psi->filename, &psi->functionname, &psi->line);
}
char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off)
{
struct sym_info si = { 0 };
char *ret_buf = NULL;
if (!binfile)
return NULL;
if (!binfile->abfd)
return NULL;
if (!binfile->syms)
return NULL;
si.pc = (binfile->abfd->flags & EXEC_P) ? addr : addr - off;
si.syms = binfile->syms;
si.found = FALSE;
si.line = 0;
bfd_map_over_sections(binfile->abfd, find_address_in_section, &si);
if (!si.found) {
if (asprintf(&ret_buf, "%s", bfd_get_filename(binfile->abfd)) == -1)
ret_buf = NULL;
} else {
const char *name;
do {
char *alloc = NULL;
name = si.functionname;
if (name == NULL || *name == '\0') {
if (asprintf(&alloc, "[0x%lx]", (unsigned long)addr) == -1)
name = "?";
else
name = alloc;
}
else {
alloc = bfd_demangle(binfile->abfd, name, 27);
if (alloc != NULL)
name = alloc;
}
if (ret_buf)
free(ret_buf);
if (si.line) {
if (asprintf(&ret_buf, "%s:%u %s", si.filename ? si.filename : bfd_get_filename(binfile->abfd), si.line, name) == -1)
ret_buf = NULL;
}
else {
if (asprintf(&ret_buf, "%s %s", si.filename ? si.filename : bfd_get_filename(binfile->abfd), name) == -1)
ret_buf = NULL;
}
if (alloc)
free(alloc);
si.found = bfd_find_inliner_info(binfile->abfd, &si.filename, &si.functionname, &si.line);
} while (si.found);
}
return ret_buf;
}
struct bin_file *bin_file_new(const char *filename)
{
bfd *abfd;
char **matching;
struct bin_file *binfile;
if (!filename)
return NULL;
binfile = malloc(sizeof(struct bin_file));
if (!binfile)
return NULL;
abfd = bfd_openr(filename, NULL);
if (!abfd)
goto error;
/* Decompress sections. */
// abfd->flags |= BFD_DECOMPRESS;
if (bfd_check_format(abfd, bfd_archive))
goto error;
if (!bfd_check_format_matches(abfd, bfd_object, &matching))
goto error;
binfile->abfd = abfd;
if (slurp_symtab(binfile) <= 0)
goto error;
binfile->refcnt = 1;
return binfile;
error:
if (abfd)
bfd_close(abfd);
free(binfile);
return NULL;
}
struct bin_file *bin_file_clone(struct bin_file *binfile)
{
if (!binfile)
return NULL;
binfile->refcnt++;
return binfile;
}
void bin_file_free(struct bin_file *binfile)
{
if (!binfile)
return;
if (--binfile->refcnt > 0)
return;
if (binfile->syms)
free(binfile->syms);
if (binfile->abfd)
bfd_close(binfile->abfd);
}

37
client/binfile.h Normal file
View File

@ -0,0 +1,37 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_BINFILE_H
#define _INC_CLIENT_BINFILE_H
#include "bfdinc.h"
struct bin_file {
bfd *abfd;
asymbol **syms;
unsigned int refcnt;
};
struct bin_file *bin_file_new(const char *filename);
struct bin_file *bin_file_clone(struct bin_file *binfile);
void bin_file_free(struct bin_file *binfile);
char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off);
#endif

470
client/client.c Normal file
View File

@ -0,0 +1,470 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <byteswap.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "binfile.h"
#include "common.h"
#include "client.h"
#include "dump.h"
#include "ioevent.h"
#include "options.h"
#include "process.h"
#include "readline.h"
#include "rbtree.h"
#include "socket.h"
#include "thread.h"
struct rb_process {
struct rb_node node;
struct process *process;
};
static int client_fd;
static struct rb_root pid_table;
static int first_pid;
static struct memtrace_info mt_info;
static struct thread *thread;
static struct rb_process *pid_rb_search(struct rb_root *root, pid_t pid)
{
struct rb_node *node = root->rb_node;
while (node) {
struct rb_process *data = (struct rb_process *) node;
if (pid < data->process->pid)
node = node->rb_left;
else if (pid > data->process->pid)
node = node->rb_right;
else
return data;
}
return NULL;
}
static struct process *pid_rb_delete(struct rb_root *root, pid_t pid)
{
struct rb_process *data = pid_rb_search(root, pid);
struct process *process;
if (data) {
process = data->process;
rb_erase(&data->node, root);
free(data);
return process;
}
return NULL;
}
static int process_rb_insert(struct rb_root *root, struct process *process)
{
struct rb_node **new = &(root->rb_node), *parent = NULL;
struct rb_process *data;
/* Figure out where to put new node */
while (*new) {
struct rb_process *this = (struct rb_process *) *new;
parent = *new;
if (process->pid < this->process->pid)
new = &((*new)->rb_left);
else if (process->pid > this->process->pid)
new = &((*new)->rb_right);
else
return FALSE;
}
data = malloc(sizeof(*data));
data->process = process;
/* Add new node and rebalance tree. */
rb_link_node(&data->node, parent, new);
rb_insert_color(&data->node, root);
return TRUE;
}
static void swap_msg(struct mt_msg *mt_msg)
{
mt_msg->operation = bswap_16(mt_msg->operation);
mt_msg->payload_len = bswap_32(mt_msg->payload_len);
mt_msg->pid = bswap_32(mt_msg->pid);
mt_msg->tid = bswap_32(mt_msg->tid);
}
static int socket_read_msg(struct mt_msg *mt_msg, void **payload, int *swap_endian)
{
if (TEMP_FAILURE_RETRY(safe_read(client_fd, mt_msg, sizeof(*mt_msg))) <= 0)
return FALSE;
if (mt_msg->operation > 0xff) {
swap_msg(mt_msg);
*swap_endian = 1;
}
else
*swap_endian = 0;
if (mt_msg->payload_len) {
*payload = malloc(mt_msg->payload_len);
if (TEMP_FAILURE_RETRY(safe_read(client_fd, *payload, mt_msg->payload_len)) <= 0)
return FALSE;
}
return TRUE;
}
static pid_t pid_payload(struct process *process, void *payload)
{
struct mt_pid_payload *mt_pid = payload;
return process->val32(mt_pid->pid);
}
void client_close(void)
{
if (client_fd != -1) {
ioevent_del_input(client_fd);
shutdown(client_fd, SHUT_RDWR);
close(client_fd);
client_fd = -1;
}
}
static void client_broken(void)
{
if (client_fd != -1) {
fprintf(stderr, "connection lost\n");
client_close();
}
}
static int client_func(void)
{
struct mt_msg mt_msg;
struct process *process;
void *payload = NULL;
int swap_endian;
if (socket_read_msg(&mt_msg, &payload, &swap_endian) == FALSE) {
client_broken();
return -1;
}
if (!mt_msg.pid) {
process = NULL;
switch(mt_msg.operation) {
case MT_DISCONNECT:
sock_send_msg(client_fd, MT_DISCONNECT, 0, 0, NULL, 0);
client_close();
break;
case MT_INFO:
memcpy(&mt_info, payload, sizeof(mt_info));
break;
default:
fatal("protocol violation 0x%08x", mt_msg.operation);
}
}
else {
process = client_find_process(mt_msg.pid);
if (!process) {
process = process_new(mt_msg.pid, swap_endian, 0, mt_info.do_trace);
client_add_process(process);
}
else {
if (process->swap_endian != swap_endian)
process = NULL;
else
if (process->status == MT_PROCESS_IGNORE)
process = NULL;
}
}
if (process) {
switch(mt_msg.operation) {
case MT_MALLOC:
case MT_REALLOC:
case MT_REALLOC_FAILED:
case MT_MEMALIGN:
case MT_POSIX_MEMALIGN:
case MT_ALIGNED_ALLOC:
case MT_VALLOC:
case MT_PVALLOC:
case MT_MMAP:
case MT_MMAP64:
process_alloc(process, &mt_msg, payload);
break;
case MT_REALLOC_ENTER:
case MT_FREE:
process_free(process, &mt_msg, payload);
break;
case MT_MUNMAP:
process_munmap(process, &mt_msg, payload);
break;
case MT_FORK:
process_duplicate(process, client_find_process(pid_payload(process, payload)));
break;
case MT_ATTACH:
process_reinit(process, swap_endian, 0);
break;
case MT_ATTACH64:
if (!IS64BIT) {
fprintf(stderr, "64 bit processes with pid %d not supported on 32 bit hosts\n", mt_msg.pid);
process_set_status(process, MT_PROCESS_IGNORE);
break;
}
process_reinit(process, swap_endian, 1);
break;
case MT_ABOUT_EXIT:
process_about_exit(process);
break;
case MT_EXIT:
process_exit(process);
break;
case MT_NOFOLLOW:
process_delete(process);
break;
case MT_SCAN:
process_scan(process, payload, mt_msg.payload_len);
break;
case MT_ADD_MAP:
process_add_map(process, payload, mt_msg.payload_len);
break;
case MT_DEL_MAP:
process_del_map(process, payload, mt_msg.payload_len);
break;
case MT_DETACH:
process_detach(process);
break;
default:
fatal("protocol violation 0x%08x", mt_msg.operation);
}
}
if (payload)
free(payload);
return mt_msg.operation;
}
void client_show_info(void)
{
printf("memtrace info:\n");
printf(" follow fork: %s\n", mt_info.mode & MEMTRACE_SI_FORK ? "yes" : "no");
printf(" follow exec: %s\n", mt_info.mode & MEMTRACE_SI_EXEC ? "yes" : "no");
printf(" verbose: %s\n", mt_info.mode & MEMTRACE_SI_VERBOSE ? "yes" : "no");
printf(" do trace: %s\n", mt_info.do_trace ? "yes" : "no");
printf(" stack depth: %u\n", mt_info.stack_depth);
}
int client_wait_op(enum mt_operation op)
{
for(;;) {
if (client_fd == -1)
return -1;
if (ioevent_wait_input(client_fd, -1) <= 0)
break;
if (client_func() == (int)op)
break;
}
return 0;
}
static int client_release_process(struct rb_node *node, void *user)
{
struct rb_process *data = (struct rb_process *)node;
process_delete(data->process);
free(data);
return 0;
}
void client_finalize()
{
client_close();
rb_iterate(&pid_table, client_release_process, NULL);
}
static int client_iterate_process(struct rb_node *node, void *user)
{
struct rb_process *data = (struct rb_process *)node;
int (*func)(struct process *process) = user;
return func(data->process);
}
void client_iterate_processes(int (*func)(struct process *process))
{
rb_iterate(&pid_table, client_iterate_process, func);
}
struct process *client_find_process(pid_t pid)
{
struct rb_process *data;
data = pid_rb_search(&pid_table, pid);
if (data)
return data->process;
return NULL;
}
struct process *client_first_process(void)
{
if (!first_pid)
return NULL;
return client_find_process(first_pid);
}
void client_add_process(struct process *process)
{
if (!first_pid)
first_pid = process->pid;
process_rb_insert(&pid_table, process);
}
void client_remove_process(struct process *process)
{
process = pid_rb_delete(&pid_table, process->pid);
if (process)
free(process);
}
void _client_init(int do_trace)
{
pid_table = RB_ROOT;
first_pid = 0;
mt_info.version = MEMTRACE_SI_VERSION;
mt_info.mode = 0;
mt_info.do_trace = do_trace;
mt_info.stack_depth = 0;
}
int client_start(void)
{
_client_init(0);
client_fd = connect_to(options.client, options.port);
if (client_fd == -1) {
fprintf(stderr, "could not connect: %s:%s", options.client, options.port);
return -1;
}
client_wait_op(MT_INFO);
if (mt_info.version != MEMTRACE_SI_VERSION) {
fprintf(stderr,
"client version v%u does not match client version v%u\n",
mt_info.version,
MEMTRACE_SI_VERSION
);
return -1;
}
client_show_info();
ioevent_add_input(client_fd, client_func);
readline_init();
while(ioevent_watch(-1) != -1)
;
return 0;
}
void *client_thread(void *unused)
{
while(client_fd != -1)
client_func();
return NULL;
}
int client_start_pair(int handle)
{
thread = thread_new();
if (!thread)
return -1;
client_fd = handle;
_client_init(1);
if (thread_start(thread, client_thread, NULL))
fatal("could not start thread (%s)", strerror(errno));
return 0;
}
int client_send_msg(struct process *process, enum mt_operation op, void *payload, unsigned int payload_len)
{
int ret = sock_send_msg(client_fd, process->val16(op), process->pid, 0, payload, payload_len);
if (ret < 0)
client_broken();
return ret;
}
int client_connected(void)
{
if (client_fd != -1)
return 1;
printf("connection lost\n");
return 0;
}
int client_stop(void)
{
if (thread)
thread_join(thread);
client_close();
return 0;
}

45
client/client.h Normal file
View File

@ -0,0 +1,45 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_CLIENT_H
#define _INC_CLIENT_CLIENT_H
#include "memtrace.h"
struct process;
void client_finalize();
struct process *client_first_process(void);
struct process *client_find_process(pid_t pid);
void client_iterate_processes(int (*func)(struct process *process));
void client_add_process(struct process *process);
void client_remove_process(struct process *process);
void client_show_info(void);
int client_wait_op(enum mt_operation op);
void client_close(void);
int client_send_msg(struct process *process, enum mt_operation op, void *payload, unsigned int payload_len);
int client_connected(void);
int client_start(void);
int client_start_pair(int handle);
int client_stop(void);
#endif

232
client/dump.c Normal file
View File

@ -0,0 +1,232 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <termios.h>
#include <stdarg.h>
#include <ncurses.h>
#include "dump.h"
#include "ioevent.h"
static int dump_term;
static FILE *dump_outfile;
static int rows, cols;
static int row, col;
static int get_term_size(void)
{
#ifdef TIOCGSIZE
struct ttysize ttys;
#endif
#ifdef TIOCGWINSZ
struct winsize wins;
#endif
const char *s;
#ifdef TIOCGSIZE
if (ioctl(0, TIOCGSIZE, &ttys) != -1) {
rows = ttys.ts_lines;
cols = ttys.ts_cols;
return 0;
}
#endif
#ifdef TIOCGWINSZ
if (ioctl(0, TIOCGWINSZ, &wins) != -1) {
rows = wins.ws_row;
cols = wins.ws_col;
return 0;
}
#endif
if (rows) {
s = getenv("LINES");
if (s)
rows = strtol(s, NULL, 10);
else
rows = 25;
}
if (cols) {
s=getenv("COLUMNS");
if (s)
cols = strtol(s, NULL, 10);
else
cols = 80;
}
return 0;
}
int dump_init(FILE *file)
{
dump_outfile = file;
if (!dump_outfile) {
dump_term = 0;
row = 0;
col = 0;
get_term_size();
}
return 0;
}
static int dump_pager(void)
{
struct termios termios;
struct termios termios_old;
int c;
int len;
len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1;
fflush(stdout);
tcgetattr(0, &termios_old);
termios = termios_old;
cfmakeraw(&termios);
tcsetattr(0, TCSADRAIN, &termios);
ioevent_wait_input(0, -1);
c = getchar();
tcsetattr(0, TCSANOW, &termios_old);
printf("%*s\r", len, "");
fflush(stdout);
switch(c) {
case '\03':
case 'q':
if (col)
fputc('\n', stdout);
dump_term = 1;
return -1;
case ' ':
get_term_size();
row = rows - 1;
break;
default:
get_term_size();
row = 0;
break;
}
return 0;
}
static int next_nl(char *str, int l)
{
int n;
for(n = 0; *str; ++n) {
if (!l--)
break;
if (*str++ == '\n')
break;
}
return n;
}
static int dump_line(char *s, int n)
{
if (dump_term)
return -1;
col += fwrite(s, sizeof(char), n, stdout);
if (s[n] == '\n') {
if (col < cols)
fputc('\n', stdout);
row++;
col = 0;
}
else {
if (col >= cols) {
row++;
col = 0;
}
}
if (row >= rows) {
if (dump_pager())
return -1;
}
return 0;
}
int dump_printf(const char *fmt, ...)
{
char *str;
char *s;
int n;
va_list args;
int ret = 0;
if (dump_outfile) {
va_start(args, fmt);
vfprintf(dump_outfile, fmt, args);
va_end(args);
return 0;
}
va_start(args, fmt);
n = vasprintf(&str, fmt, args);
va_end(args);
if (n == -1)
return -1;
for(s = str; *s; ) {
n = next_nl(s, cols - col);
ret = dump_line(s, n);
if (ret)
break;
s += n;
if (*s == '\n') {
++s;
++n;
}
}
free(str);
return ret;
}
int dump_flush(void)
{
if (dump_outfile)
fflush(dump_outfile);
else
fflush(stdout);
return 0;
}

31
client/dump.h Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_DUMP_H
#define _INC_CLIENT_DUMP_H
#include <stdio.h>
int dump_init(FILE *file);
int dump_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int dump_flush(void);
#endif

52
client/job.c Normal file
View File

@ -0,0 +1,52 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include "client.h"
#include "common.h"
#include "job.h"
#include "process.h"
void leaks_scan(struct process *process, int mode)
{
process_leaks_scan(process, mode);
client_wait_op(MT_SCAN);
}
void dump_stacks(struct process *process, void (*dump)(struct process *process, const char *outfile), const char *outfile)
{
if (!process->n_allocations)
return;
dump(process, outfile);
}

29
client/job.h Normal file
View File

@ -0,0 +1,29 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_JOB_H
#define _INC_CLIENT_JOB_H
struct process;
void leaks_scan(struct process *process, int mode);
void dump_stacks(struct process *process, void (*dump)(struct process *process, const char *outfile), const char *outfile);
#endif

1462
client/process.c Normal file

File diff suppressed because it is too large Load Diff

109
client/process.h Normal file
View File

@ -0,0 +1,109 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_PROCESS_H
#define _INC_CLIENT_PROCESS_H
#include "list.h"
#include "memtrace.h"
#include "rbtree.h"
#define SCAN_ALL 0
#define SCAN_LEAK 1
#define SCAN_NEW 2
struct alloc_block;
enum process_status {
MT_PROCESS_RUNNING, /* process is running */
MT_PROCESS_EXIT, /* _exit() has been called in process */
MT_PROCESS_EXITING, /* process is about exiting */
MT_PROCESS_IGNORE, /* ignore the process */
MT_PROCESS_DETACH, /* trace will be detached */
};
struct lib {
struct list_head list;
const char *pathname;
unsigned long offset;
unsigned long addr;
unsigned long size;
};
struct process {
enum process_status status;
pid_t pid;
int tracing;
char *filename;
unsigned long bytes_used;
unsigned long n_allocations;
unsigned long total_allocations;
unsigned long leaks;
unsigned long long leaked_bytes;
unsigned long stack_trees;
struct rb_root block_table;
struct rb_root stack_table;
struct list_head map_list;
unsigned long long tsc;
int swap_endian;
int is_64bit;
unsigned long (*get_ulong)(void *);
void (*put_ulong)(void *, unsigned long);
uint16_t (*val16)(uint16_t val);
uint32_t (*val32)(uint32_t val);
uint64_t (*val64)(uint64_t val);
uint8_t ptr_size;
};
struct process *process_new(pid_t pid, int swap_endian, int is_64bit, int tracing);
void process_reset_allocations(struct process *process);
void process_reinit(struct process *process, int swap_endian, int is_64bit);
void process_set_clone(struct process *process, struct process *clone);
struct process *process_clone_of(struct process *process);
void process_delete(struct process *process);
void process_duplicate(struct process *process, struct process *copy);
void process_run(struct process *process, const char *libpath, const char *path, char **args);
void process_set_status(struct process *process, enum process_status status);
void process_start_input(struct process *process);
void process_stop_input(struct process *process);
void process_about_exit(struct process *process);
void process_exit(struct process *process);
void process_status(struct process *process);
void *process_scan(struct process *curr, void *leaks, uint32_t payload_len);
void process_alloc(struct process *process, struct mt_msg *msg, void *payload);
void process_free(struct process *process, struct mt_msg *msg, void *payload);
void process_munmap(struct process *process, struct mt_msg *msg, void *payload);
void process_add_map(struct process *process, void *payload, uint32_t payload_len);
void process_del_map(struct process *process, void *payload, uint32_t payload_len);
void process_detach(struct process *process);
unsigned long process_leaks_scan(struct process *process, int mode);
void process_dump_sort_average(struct process *process, const char *outfile);
void process_dump_sort_usage(struct process *process, const char *outfile);
void process_dump_sort_leaks(struct process *process, const char *outfile);
void process_dump_sort_bytes_leaked(struct process *process, const char *outfile);
void process_dump_sort_allocations(struct process *process, const char *outfile);
void process_dump_sort_total(struct process *process, const char *outfile);
void process_dump_sort_tsc(struct process *process, const char *outfile);
void process_dump_stacks(struct process *process, const char *outfile);
#endif

854
client/readline.c Normal file
View File

@ -0,0 +1,854 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "binfile.h"
#include "client.h"
#include "common.h"
#include "dump.h"
#include "ioevent.h"
#include "job.h"
#include "options.h"
#include "process.h"
#define PROGNAME "memtrace"
struct cmd_opt {
const char *name;
unsigned int match_len;
void *data;
const char *info;
const char *usage;
struct cmd_opt *options;
};
typedef int (*opt_call)(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]);
typedef int (*cmd_call)(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_dump(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_help(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_proclist(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_quit(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_reset(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_scan(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_set(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_show(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_status(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_start(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_stop(struct cmd_opt *cmd, int argc, const char *argv[]);
static int do_set_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]);
static int do_show_info(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]);
static int do_show_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[]);
const char dump_str[] = "dump";
const char help_str[] = "help";
const char proclist_str[] = "proclist";
const char quit_str[] = "quit";
const char reset_str[] = "reset";
const char scan_str[] = "scan";
const char set_str[] = "set";
const char show_str[] = "show";
const char start_str[] = "start";
const char status_str[] = "status";
const char stop_str[] = "stop";
static const char *outfile;
static struct cmd_opt dump_opts[] = {
{ "allocations", 2, process_dump_sort_allocations, "sort by number of open allocations" },
{ "average", 2, process_dump_sort_average, "sort by average allocation of bytes (usage / allocations)" },
{ "bytes-leaked", 1, process_dump_sort_bytes_leaked, "sort by number of leaked bytes" },
{ "leaks", 1, process_dump_sort_leaks, "sort by number of detected leaks" },
{ "stacks", 1, process_dump_stacks, "dump all stack sort by number of total allocations" },
{ "total", 2, process_dump_sort_total, "sort by number of total allocations" },
{ "tsc", 2, process_dump_sort_tsc, "sort by time stamp counter" },
{ "usage", 1, process_dump_sort_usage, "sort by number of bytes" },
{ NULL, 0, NULL, "\n use > to dump the output into a file" },
};
static struct cmd_opt set_opts[] = {
{ "searchpath", 1, do_set_searchpath, "set searchpath for binaries and libraries" },
{ },
};
static struct cmd_opt show_opts[] = {
{ "info", 1, do_show_info, "show client settings" },
{ "searchpath", 1, do_show_searchpath, "show searchpath for binaries and libraries" },
{ },
};
static struct cmd_opt scan_opts[] = {
{ "all", 1, (void *)SCAN_ALL, "scan all memory blocks" },
{ "leak", 1, (void *)SCAN_LEAK, "scan only leaked allocations" },
{ "new", 1, (void *)SCAN_NEW, "scan only allocations since last scan" },
{ },
};
static struct cmd_opt cmds[] = {
{
dump_str,
1,
do_dump,
"dump stack trees",
"[sort-by] [<pid>] [>filename]",
dump_opts
},
{
help_str,
1,
do_help,
"this help",
"[<command>]",
cmds
},
{
proclist_str,
1,
do_proclist,
"list processes",
""
},
{
quit_str,
1,
do_quit,
"exit the program",
""
},
{
reset_str,
1,
do_reset,
"reset all current memory allocation",
"[<pid>]"
},
{
scan_str,
2,
do_scan,
"scan new memory leaks",
"[<pid>]",
scan_opts
},
{
set_str,
2,
do_set,
"change settings",
"<option> [arg]",
set_opts
},
{
show_str,
2,
do_show,
"show settings",
"<option> [arg]",
show_opts
},
{
start_str,
4,
do_start,
"start allocation tracing",
""
},
{
status_str,
4,
do_status,
"show allocation status",
"[<pid>]"
},
{
stop_str,
3,
do_stop,
"stop allocation tracing",
""
},
{ },
};
static void _quit(void)
{
rl_callback_handler_remove();
_exit(1);
}
static inline char *skip_spaces(const char *s)
{
while(isspace(*s))
++s;
return (char *)s;
}
static inline unsigned int match_chr(const char *s, char c)
{
unsigned int i;
for(i = 0; *s != c; ++i) {
if (!*s++)
break;
}
return i;
}
static inline unsigned int get_string(const char *s)
{
char c = *s++;
return match_chr(s, c) + 1;
}
static char *readline_cmd_generator(const char *text, int state)
{
static unsigned int list_index, len;
if (!state) {
list_index = 0;
len = strlen(text);
}
text = skip_spaces(text);
while(list_index < ARRAY_SIZE(cmds) -1) {
const char *name = cmds[list_index++].name;
if (strncmp(name, text, len) == 0)
return strdup(name);
}
return NULL;
}
static char **readline_option_complete(const char *text, struct cmd_opt *options)
{
char **match_list;
unsigned int len = strlen(text);
unsigned int i = 1;
unsigned int match_list_size = 8;
if (!options)
return NULL;
match_list = malloc(match_list_size * sizeof(*match_list));
if (!match_list)
return match_list;
while(options->name) {
if (!strncmp(options->name, text, len)) {
if (i + 2 > match_list_size) {
char **new;
match_list_size += 8;
new = realloc(match_list, match_list_size * sizeof(*match_list));
if (!new)
break;
match_list = new;
}
match_list[i++] = strdup(options->name);
}
++options;
}
if (i < 2) {
free(match_list);
return NULL;
}
if (i == 2) {
match_list[0] = match_list[1];
match_list[1] = NULL;
}
else {
match_list[0] = strndup(match_list[1], len);
match_list[i] = NULL;
}
return match_list;
}
static char **readline_completor(const char *text, int start, int end)
{
char *p;
unsigned int i, n;
rl_attempted_completion_over = 1;
if (start) {
if (rl_line_buffer[start - 1] == '>')
return rl_completion_matches(text, rl_filename_completion_function);
}
if (rl_line_buffer[end])
return NULL;
p = skip_spaces(rl_line_buffer);
for(n = 0; p[n]; ++n) {
if (isspace(p[n]))
break;
}
if (isspace(p[n])) {
for(i = 0; i < ARRAY_SIZE(cmds) - 1; ++i) {
if (n >= cmds[i].match_len && !strncmp(cmds[i].name, p, n))
return readline_option_complete(text, cmds[i].options);
}
return NULL;
}
return rl_completion_matches(text, readline_cmd_generator);
}
static void readline_handler(char *line)
{
unsigned int i;
unsigned int n;
const char **argv = NULL;
unsigned int argv_size = 8;
unsigned int argc;
char *linedup;
char *s;
linedup = strdup(line);
if (!linedup)
goto finish;
argv = malloc(argv_size * sizeof(*argv));
if (!argv)
goto finish;
s = linedup;
i = 0;
for(;;) {
s = skip_spaces(s);
if (!*s)
break;
if (i + 2 > argv_size) {
const char **new;
argv_size += 8;
new = realloc(argv, argv_size * sizeof(*argv));
if (!new)
break;
argv = new;
}
if (*s == '\"') {
argv[i] = s + 1;
n = get_string(s);
}
else
if (*s == '\'') {
argv[i] = s + 1;
n = get_string(s);
}
else {
argv[i] = s;
for(n = 1; !isspace(s[n]); ++n) {
if (!s[n])
break;
}
}
++i;
if (!s[n])
break;
s[n] = 0;
s += n + 1;
}
if (!i)
return;
argc = i;
argv[i++] = NULL;
outfile = NULL;
for(i = 0; i < argc; ++i) {
if (argv[i][0] == '>') {
unsigned int j;
outfile = argv[i] + 1;
for(j = i; j < argc; ++j)
argv[j] = argv[j + 1];
--argc;
}
}
if (argc) {
n = strlen(argv[0]);
for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i) {
if (n >= cmds[i].match_len && !strncmp(argv[0], cmds[i].name, n)) {
if (((cmd_call)cmds[i].data)(&cmds[i], argc, argv) >= 0) {
HIST_ENTRY *entry = history_get(history_base + history_length - 1);
if (!entry || strcmp(entry->line, line))
add_history(line);
}
goto finish;
}
}
}
printf("unknown command '%s'\n", argv[0]);
finish:
free(argv);
free(linedup);
return;
}
static void split_search_patch(const char *str)
{
struct opt_b_t *opt_b_last = NULL;
while(options.opt_b) {
struct opt_b_t *p = options.opt_b;
options.opt_b = p->next;
free(p->pathname);
free(p);
}
while(*str) {
unsigned int n = match_chr(str, ':');
struct opt_b_t *tmp = malloc(n + 1);
if (!tmp) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
tmp->pathname = strndup(str, n);
tmp->pathname[n] = 0;
tmp->next = NULL;
if (opt_b_last)
opt_b_last->next = tmp;
opt_b_last = tmp;
if (!options.opt_b)
options.opt_b = tmp;
str += n;
if (!*str++)
break;
}
}
static int do_set_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[])
{
if (argc < 3) {
fprintf(stderr, "%s: missing search path argument for '%s'\n", cmd->name, opt->name);
return -1;
}
split_search_patch(argv[2]);
return 0;
}
static int do_show_info(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[])
{
if (argc > 2) {
fprintf(stderr, "%s: too many option argument for '%s'\n", cmd->name, opt->name);
return -1;
}
client_show_info();
return 0;
}
static int do_show_searchpath(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, const char *argv[])
{
struct opt_b_t *p = options.opt_b;
if (argc > 3) {
fprintf(stderr, "%s: too many option argument for '%s'\n", cmd->name, opt->name);
return -1;
}
printf("%s=", opt->name);
if (p) {
for(;;) {
printf("%s", p->pathname);
p = p->next;
if (!p)
break;
printf(":");
}
}
printf("\n");
return 0;
}
static struct process *get_process(const char *arg)
{
struct process *process;
if (!arg) {
process = client_first_process();
if (!process)
fprintf(stderr, "no process available\n");
}
else {
process = client_find_process(atoi(arg));
if (!process)
fprintf(stderr, "process %s not found\n", arg);
}
return process;
}
static int do_dump(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
size_t len;
struct cmd_opt *options = cmd->options;;
unsigned int i;
void *data;
if (!argv[1]) {
process = client_first_process();
if (!process) {
fprintf(stderr, "no process available\n");
return -1;
}
data = process_dump_sort_allocations;
}
else {
data = NULL;
len = strlen(argv[1]);
for(i = 0; options[i].name; ++i) {
if (options[i].match_len <= len && !strncmp(options[i].name, argv[1], len)) {
data = options[i].data;
break;
}
}
if (!data) {
process = client_find_process(atoi(argv[1]));
if (!process) {
fprintf(stderr, "%s: unknown sort criteria\n", cmd->name);
return -1;
}
data = process_dump_sort_allocations;
}
else {
process = get_process(argv[2]);
if (!process)
return -1;
}
}
dump_stacks(process, data, outfile);
return 0;
}
static int do_help(struct cmd_opt *cmd, int argc, const char *argv[])
{
int i;
unsigned int len;
if (argc <= 1) {
for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i)
printf(" %s - %s\n", cmds[i].name, cmds[i].info);
return 0;
}
len = strlen(argv[1]);
for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i) {
if (cmds[i].match_len <= len && !strncmp(cmds[i].name, argv[1], len)) {
struct cmd_opt *options = cmds[i].options;;
printf("usage: %s %s\n", cmds[i].name, cmds[i].usage);
if (options) {
while(options->name) {
printf(" %s - %s\n", options->name, options->info);
++options;
}
if (options->info)
printf(" %s\n", options->info);
}
return 0;
}
}
printf("%s: no help for '%s'\n", cmd->name, argv[1]);
return -1;
}
static int show_process(struct process *process)
{
printf(" %d %c", process->pid, process->tracing ? '+' : '-');
if (process->filename)
printf(" %s", process->filename);
printf("\n");
return 0;
}
static int do_proclist(struct cmd_opt *cmd, int argc, const char *argv[])
{
if (argc > 1) {
fprintf(stderr, "%s: expect no arguments\n", proclist_str);
return -1;
}
printf("available processes:\n");
client_iterate_processes(show_process);
return 0;
}
static int do_quit(struct cmd_opt *cmd, int argc, const char *argv[])
{
_quit();
return 0;
}
static int do_reset(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
process = get_process(argv[1]);
if (!process)
return -1;
process_reset_allocations(process);
return 0;
}
static int do_scan(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
struct cmd_opt *options = cmd->options;;
size_t len;
unsigned int i;
int mode;
if (!client_connected())
return -1;
process = get_process(argv[1]);
if (!process)
return -1;
if (!process->tracing) {
fprintf(stderr, "scan can only performed in tracing state!\n");
return -1;
}
if (argc == 1)
mode = SCAN_ALL;
else {
mode = -1;
len = strlen(argv[1]);
for(i = 0; options[i].name; ++i) {
if (options[i].match_len <= len && !strncmp(options[i].name, argv[1], len)) {
mode = (unsigned long)options[i].data;
break;
}
}
if (mode < 0) {
fprintf(stderr, "%s: unknown scan mode\n", cmd->name);
return -1;
}
}
leaks_scan(process, mode);
return 0;
}
static int do_set(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct cmd_opt *opt = cmd->options;
unsigned int len;
if (argc < 2) {
fprintf(stderr, "%s: missing option argument\n", cmd->name);
return -1;
}
len = strlen(argv[1]);
while(opt->name) {
if (opt->match_len <= len && !strncmp(opt->name, argv[1], len))
return ((opt_call)opt->data)(cmd, opt, argc, argv);
++opt;
}
fprintf(stderr, "%s: unknown option '%s'\n", cmd->name, argv[1]);
return -1;
}
static int do_show(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct cmd_opt *opt = cmd->options;
unsigned int len;
if (argc < 2) {
fprintf(stderr, "%s: missing option argument\n", cmd->name);
return -1;
}
len = strlen(argv[1]);
while(opt->name) {
if (opt->match_len <= len && !strncmp(opt->name, argv[1], len))
return ((opt_call)opt->data)(cmd, opt, argc, argv);
++opt;
}
fprintf(stderr, "%s: unknown option '%s'\n", cmd->name, argv[1]);
return -1;
}
static int do_start(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
if (!client_connected())
return -1;
process = get_process(argv[1]);
if (!process)
return -1;
process_reset_allocations(process);
process->tracing = 1;
client_send_msg(process, MT_START, NULL, 0);
return 0;
}
static int do_status(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
process = get_process(argv[1]);
if (!process)
return -1;
process_status(process);
return 0;
}
static int do_stop(struct cmd_opt *cmd, int argc, const char *argv[])
{
struct process *process;
if (!client_connected())
return -1;
process = get_process(argv[1]);
if (!process)
return -1;
process->tracing = 0;
client_send_msg(process, MT_STOP, NULL, 0);
return 0;
}
static int readline_func(void)
{
rl_callback_read_char();
return 0;
}
void readline_init(void)
{
rl_terminal_name = getenv("TERM");
rl_instream = stdin;
rl_outstream = stderr;
rl_readline_name = PROGNAME;
rl_callback_handler_install(PROGNAME "> ", readline_handler);
rl_attempted_completion_function = readline_completor;
/* characters that need to be quoted when appearing in filenames. */
rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{"; /*}*/
#if 0
rl_filename_quoting_function = NULL;
rl_filename_dequoting_function = NULL;
rl_char_is_quoted_p = NULL;
#endif
rl_completer_quote_characters = "'\"";
#if (RL_VERSION_MAJOR>=5)
rl_catch_signals = 1 ;
rl_catch_sigwinch = 1 ;
rl_set_signals () ;
#endif
ioevent_add_input(0, readline_func);
}

27
client/readline.h Normal file
View File

@ -0,0 +1,27 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_CLIENT_READLINE_H
#define _INC_CLIENT_READLINE_H
void readline_init(void);
#endif

93
common.c Normal file
View File

@ -0,0 +1,93 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include "common.h"
void _fatal(const char *file, const char *func, int line, const char *format, ...)
{
va_list args;
char *message = NULL;
va_start(args, format);
if (vasprintf(&message, format, args) == -1)
abort();
va_end(args);
fprintf(stderr,"%s(%s:%d):\n %s\n", file, func, line, message);
free(message);
}
char *safe_strncpy(char *dst, const char *src, size_t size)
{
if (!size)
return dst;
dst[--size] = '\0';
return strncpy(dst, src, size);
}
unsigned long get_val32(void *data, unsigned long index)
{
return (unsigned long)*(uint32_t *)(data + index * sizeof(uint32_t));
}
unsigned long get_val64(void *data, unsigned long index)
{
return (unsigned long)*(uint64_t *)(data + index * sizeof(uint64_t));
}
unsigned long find_block(unsigned long (*get_val)(void *data, unsigned long index), void *arr, unsigned long n, unsigned long addr)
{
unsigned long first, middle, last, val;
first = 0;
last = n;
if (addr < get_val(arr,first))
return n;
if (addr > get_val(arr, last - 1))
return n;
do {
middle = (first + last) >> 1;
val = get_val(arr, middle);
if (addr < val)
last = middle;
else if (addr > val)
first = middle + 1;
else
return middle;
} while (first < last);
return n;
}

76
common.h Normal file
View File

@ -0,0 +1,76 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2010 Joe Damato
* Copyright (C) 2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_COMMON_H
#define _INC_COMMON_H
#include <config.h>
#include <sys/types.h>
#include <sys/time.h>
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof (x) / sizeof *(x))
#endif
/**
* Macro to convert a constant number value into a string constant
*/
#define XSTR(x) #x
#define STR(x) XSTR(x)
#ifndef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define fatal(fmt...) _fatal(__FILE__,__PRETTY_FUNCTION__,__LINE__ , ##fmt),abort()
void _fatal(const char *file, const char *func, int line, const char *format, ...) __attribute__ ((format (printf, 4, 5)));;
char *safe_strncpy(char *dst, const char *src, size_t size);
unsigned long get_val32(void *data, unsigned long index);
unsigned long get_val64(void *data, unsigned long index);
unsigned long find_block(unsigned long (*get_val)(void *data, unsigned long index), void *arr, unsigned long n, unsigned long addr);
#endif

202
config.h.in Normal file
View File

@ -0,0 +1,202 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* debugging */
#undef DEBUG
/* elf_hash() takes char* (as opposed to unsigned char *) */
#undef ELF_HASH_TAKES_CHARP
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
/* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT
/* Define to 1 if you have the <bfd.h> header file. */
#undef HAVE_BFD_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* we have read mmap support */
#undef HAVE_ELF_C_READ_MMAP
/* Define to 1 if you have the <elf.h> header file. */
#undef HAVE_ELF_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the <gelf.h> header file. */
#undef HAVE_GELF_H
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `bfd' library (-lbfd). */
#undef HAVE_LIBBFD
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `elf' library (-lelf). */
#undef HAVE_LIBELF
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the `readline' library (-lreadline). */
#undef HAVE_LIBREADLINE
/* Define to 1 if you have the `selinux' library (-lselinux). */
#undef HAVE_LIBSELINUX
/* Define to 1 if you have the `termcap' library (-ltermcap). */
#undef HAVE_LIBTERMCAP
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the `mkdir' function. */
#undef HAVE_MKDIR
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if you have the <readline/readline.h> header file. */
#undef HAVE_READLINE_READLINE_H
/* Define to 1 if you have the `rmdir' function. */
#undef HAVE_RMDIR
/* Define to 1 if you have the <selinux/selinux.h> header file. */
#undef HAVE_SELINUX_SELINUX_H
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define as `fork' if `vfork' does not work. */
#undef vfork

347
config/autoconf/compile Executable file
View File

@ -0,0 +1,347 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

1449
config/autoconf/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1828
config/autoconf/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

791
config/autoconf/depcomp Executable file
View File

@ -0,0 +1,791 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

501
config/autoconf/install-sh Executable file
View File

@ -0,0 +1,501 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

11149
config/autoconf/ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

215
config/autoconf/missing Executable file
View File

@ -0,0 +1,215 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

8382
config/m4/libtool.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

437
config/m4/ltoptions.m4 vendored Normal file
View File

@ -0,0 +1,437 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 8 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option '$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
_LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
[_LT_WITH_AIX_SONAME([aix])])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the 'shared' and
# 'disable-shared' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the 'static' and
# 'disable-static' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the 'fast-install'
# and 'disable-fast-install' LT_INIT options.
# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for pkg in $enableval; do
IFS=$lt_save_ifs
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the 'disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_AIX_SONAME([DEFAULT])
# ----------------------------------
# implement the --with-aix-soname flag, and support the `aix-soname=aix'
# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
m4_define([_LT_WITH_AIX_SONAME],
[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
shared_archive_member_spec=
case $host,$enable_shared in
power*-*-aix[[5-9]]*,yes)
AC_MSG_CHECKING([which variant of shared library versioning to provide])
AC_ARG_WITH([aix-soname],
[AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
[shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
[case $withval in
aix|svr4|both)
;;
*)
AC_MSG_ERROR([Unknown argument to --with-aix-soname])
;;
esac
lt_cv_with_aix_soname=$with_aix_soname],
[AC_CACHE_VAL([lt_cv_with_aix_soname],
[lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
with_aix_soname=$lt_cv_with_aix_soname])
AC_MSG_RESULT([$with_aix_soname])
if test aix != "$with_aix_soname"; then
# For the AIX way of multilib, we name the shared archive member
# based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
# and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
# Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
# the AIX toolchain works better with OBJECT_MODE set (default 32).
if test 64 = "${OBJECT_MODE-32}"; then
shared_archive_member_spec=shr_64
else
shared_archive_member_spec=shr
fi
fi
;;
*)
with_aix_soname=aix
;;
esac
_LT_DECL([], [shared_archive_member_spec], [0],
[Shared archive member basename, for filename based shared library versioning on AIX])dnl
])# _LT_WITH_AIX_SONAME
LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
# LT_INIT options.
# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
for lt_pkg in $withval; do
IFS=$lt_save_ifs
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS=$lt_save_ifs
;;
esac],
[pic_mode=m4_default([$1], [default])])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the 'pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])

124
config/m4/ltsugar.m4 vendored Normal file
View File

@ -0,0 +1,124 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59, which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])

23
config/m4/ltversion.m4 vendored Normal file
View File

@ -0,0 +1,23 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 4179 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])

99
config/m4/lt~obsolete.m4 vendored Normal file
View File

@ -0,0 +1,99 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])

15558
configure vendored Executable file

File diff suppressed because it is too large Load Diff

261
configure.ac Normal file
View File

@ -0,0 +1,261 @@
# -*- Autoconf -*-
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
# Copyright (C) 2010,2013 Petr Machata, Red Hat Inc.
# Copyright (C) 2010,2011 Joe Damato
# Copyright (C) 2010 Marc Kleine-Budde
# Copyright (C) 2010 Zachary T Welch
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.65)
AC_INIT([mtrace],[0.1],[stefani@seibold.net])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR(main.c)
AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_AUX_DIR([config/autoconf])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
case "${host_os}" in
linux-gnu*) HOST_OS="linux-gnu" ;;
linux-uclibc*) HOST_OS="linux-gnu" ;;
*) AC_MSG_ERROR([unkown host-os ${host_os}]) ;;
esac
AC_SUBST(HOST_OS)
case "${host_cpu}" in
arm*|sa110) HOST_CPU="arm" ;;
cris*) HOST_CPU="cris" ;;
mips*) HOST_CPU="mips" ;;
powerpc|powerpc64) HOST_CPU="ppc" ;;
sun4u|sparc64) HOST_CPU="sparc" ;;
s390x) HOST_CPU="s390" ;;
i?86|x86_64) HOST_CPU="x86" ;;
*) HOST_CPU="${host_cpu}" ;;
esac
AC_SUBST(HOST_CPU)
# Checks for programs.
AC_PROG_CC
LT_INIT
# libtool-2: LT_INIT()
AM_INIT_AUTOMAKE([foreign no-exeext dist-bzip2])
AM_MAINTAINER_MODE
AC_ARG_WITH([libelf],
AS_HELP_STRING([--with-libelf], [Prefix of libelf headers/library]),
[case "${withval}" in
(no)
AC_MSG_ERROR([*** libelf is a required dependency])
;;
(yes)
AC_MSG_ERROR([*** --with-libelf requires you to specify a path])
;;
(*)
AM_CPPFLAGS="${AM_CPPFLAGS} -I${withval}/include"
AM_LDFLAGS="${AM_LDFLAGS} -L${withval}/lib"
libelf_LD_LIBRARY_PATH="${withval}/lib"
;;
esac],[])
# Checks for libraries.
saved_CPPFLAGS="${CPPFLAGS}"
saved_LDFLAGS="${LDFLAGS}"
CPPFLAGS="${CPPFLAGS} ${AM_CPPFLAGS}"
LDFLAGS="${LDFLAGS} ${AM_LDFLAGS}"
# libelf
AC_CHECK_HEADERS([elf.h gelf.h],,
[AC_MSG_ERROR([*** elf.h or gelf.h not found on your system])]
)
AC_CHECK_LIB([elf], [elf_begin],,
[AC_MSG_ERROR([*** libelf not found on your system])]
)
CPPFLAGS="${saved_CPPFLAGS}"
LDFLAGS="${saved_LDFLAGS}"
# libbfd
AC_CHECK_HEADERS([bfd.h],,
[AC_MSG_ERROR([*** bfd.h not found on your system])]
)
AC_CHECK_LIB([bfd], [bfd_openr],,
[AC_MSG_ERROR([*** libbfd not found on your system])]
)
# libpthread
AC_CHECK_HEADERS([pthread.h],,
[AC_MSG_ERROR([*** pthread.h not found on your system])]
)
AC_CHECK_LIB([pthread], [pthread_create],,
[AC_MSG_ERROR([*** libpthread not found on your system])]
)
# libdl
AC_CHECK_HEADERS([dlfcn.h],,
[AC_MSG_ERROR([*** dlfcn.h not found on your system])]
)
AC_CHECK_LIB([dl], [dladdr],,
[AC_MSG_ERROR([*** libdl not found on your system])]
)
# libtermcap
#AC_CHECK_HEADERS([termcap.h],,
# [AC_MSG_ERROR([*** termcap.h not found on your system])]
#)
AC_CHECK_LIB([termcap], [tgetflag],,
)
# libreadline
AC_CHECK_HEADERS([readline/readline.h],,
[AC_MSG_ERROR([*** readline.h not found on your system])]
)
AC_CHECK_LIB([readline], [rl_callback_read_char],,
[AC_MSG_ERROR([*** libreadline not found on your system])]
)
dnl Check security_get_boolean_active availability.
AC_CHECK_HEADERS(selinux/selinux.h)
AC_CHECK_LIB(selinux, security_get_boolean_active)
saved_CPPFLAGS="${CPPFLAGS}"
saved_LDFLAGS="${LDFLAGS}"
CPPFLAGS="${CPPFLAGS} ${AM_CPPFLAGS}"
LDFLAGS="${LDFLAGS} ${AM_LDFLAGS}"
# HAVE_ELF_C_READ_MMAP
AC_MSG_CHECKING([whether elf_begin accepts ELF_C_READ_MMAP])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <gelf.h>]], [[
int main () {
Elf *elf = elf_begin(4, ELF_C_READ_MMAP, 0);
return 0;
}
]])],[
AC_DEFINE([HAVE_ELF_C_READ_MMAP], [1], [we have read mmap support])
AC_MSG_RESULT([yes])],[
AC_MSG_RESULT([no])])
saved_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} -Wall -Werror"
AC_MSG_CHECKING([whether elf_hash takes a char* argument])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libelf.h>]], [[
(void) elf_hash("name");
]])],
[AC_DEFINE([ELF_HASH_TAKES_CHARP], [1],
[elf_hash() takes char* (as opposed to unsigned char *)])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
CFLAGS="${saved_CFLAGS}"
CPPFLAGS="${saved_CPPFLAGS}"
LDFLAGS="${saved_LDFLAGS}"
AM_CPPFLAGS=" \
${AM_CPPFLAGS} \
-I\$(top_srcdir)/client \
-I\$(top_srcdir)/sysdeps/${HOST_OS}/${HOST_CPU} \
-I\$(top_srcdir)/sysdeps/${HOST_OS} \
-I\$(top_srcdir)/sysdeps \
-I\$(top_srcdir) \
"
# Checks for header files.
AC_CHECK_HEADERS([ \
fcntl.h \
limits.h \
stddef.h \
stdint.h \
stdlib.h \
string.h \
sys/ioctl.h \
sys/param.h \
sys/time.h \
unistd.h \
])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
AC_C_INLINE
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_CHECK_SIZEOF([long])
# Checks for library functions.
AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
AC_CHECK_FUNCS([ \
alarm \
atexit \
getcwd \
gettimeofday \
memset \
mkdir \
rmdir \
strchr \
strdup \
strerror \
strtol \
strtoul \
])
#
# Debugging
#
AC_MSG_CHECKING([whether to enable debugging])
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug], [enable debugging @<:@default=no@:>@]),
[case "$enableval" in
y | yes) CONFIG_DEBUG=yes ;;
*) CONFIG_DEBUG=no ;;
esac],
[CONFIG_DEBUG=no])
AC_MSG_RESULT([${CONFIG_DEBUG}])
if test "${CONFIG_DEBUG}" = "yes"; then
AC_DEFINE(DEBUG, 1, [debugging])
else
AM_CFLAGS="${AM_CFLAGS} -DNDEBUG"
fi
# Ignore the compiler's warnings at your own risk.
AM_CFLAGS="${AM_CFLAGS} -Wall -Wsign-compare -Wfloat-equal -Wformat-security -rdynamic"
AC_ARG_ENABLE([werror],
AS_HELP_STRING([--disable-werror], [disable use of -Werror]),
[enable_werror=$enableval], [enable_werror=yes])
if test x$enable_werror = xyes; then
AM_CFLAGS="${AM_CFLAGS} -Werror"
fi
AC_SUBST(AM_CPPFLAGS)
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_LDFLAGS)
AC_SUBST(libelf_LD_LIBRARY_PATH)
AC_CONFIG_FILES([
Makefile
client/Makefile
sysdeps/Makefile
sysdeps/linux-gnu/Makefile
sysdeps/linux-gnu/x86/Makefile
sysdeps/linux-gnu/ppc/Makefile
sysdeps/linux-gnu/arm/Makefile
])
AC_OUTPUT

55
debug.c Normal file
View File

@ -0,0 +1,55 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2003,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "common.h"
#include "options.h"
#include "debug.h"
#ifdef DEBUG
void _debug(int level, const char *file, const char *function, int line, const char *fmt, ...)
{
char *buf = NULL;
va_list args;
if (!(options.debug & level))
return;
va_start(args, fmt);
if (vasprintf(&buf, fmt, args) == -1)
abort();
va_end(args);
fprintf(options.output, "DEBUG: %s():%s@%d - %s\n", function, file, line, buf);
fflush(options.output);
}
#endif

49
debug.h Normal file
View File

@ -0,0 +1,49 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2003,2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_DEBUG_H
#define _INC_DEBUG_H
#include "config.h"
/* debug levels:
*/
enum {
DEBUG_EVENT_HANDLER = 01,
DEBUG_DWARF = 02,
DEBUG_EVENT = 010,
DEBUG_PROCESS = 020,
DEBUG_FUNCTION = 040
};
#ifdef DEBUG
void _debug(int level, const char *file, const char *function, int line, const char *fmt, ...) __attribute__ ((format(printf, 5, 6)));
#else
static inline void _debug(int level, const char *file, const char *function, int line, const char *fmt, ...)
{
}
#endif
#define debug(level, expr...) _debug(level, __FILE__, __FUNCTION__, __LINE__, expr)
#endif

152
dict.c Normal file
View File

@ -0,0 +1,152 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata
* Copyright (C) 2003,2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "common.h"
#include "dict.h"
#include "list.h"
struct dict_entry {
struct list_head list;
unsigned long key;
const void *value;
};
struct dict {
unsigned int size;
unsigned int (*key2hash)(unsigned long);
int (*key_cmp)(unsigned long, unsigned long);
struct list_head buckets[0];
};
struct dict *dict_init(unsigned int size, unsigned int (*key2hash)(unsigned long), int (*key_cmp)(unsigned long, unsigned long))
{
struct dict *d;
unsigned int i;
d = malloc(sizeof(*d) + sizeof(d->buckets[0]) * size);
d->size = size;
d->key2hash = key2hash;
d->key_cmp = key_cmp;
for (i = 0; i < d->size; i++)
INIT_LIST_HEAD(&d->buckets[i]);
return d;
}
void dict_clear(struct dict *d)
{
unsigned int i;
struct list_head *it, *next;
for (i = 0; i < d->size; i++) {
list_for_each_safe(it, next, &d->buckets[i]) {
struct dict_entry *entry = container_of(it, struct dict_entry, list);
free(entry);
}
}
free(d);
}
static struct dict_entry *_dict_find_entry(struct dict *d, unsigned long key, unsigned int hash)
{
struct list_head *it;
list_for_each(it, &d->buckets[hash]) {
struct dict_entry *entry = container_of(it, struct dict_entry, list);
if (!d->key_cmp(key, entry->key))
return entry;
}
return NULL;
}
int dict_add(struct dict *d, unsigned long key, const void *value)
{
struct dict_entry *newentry;
unsigned int hash = d->key2hash(key) % d->size;
if (_dict_find_entry(d, key, hash))
return -1;
newentry = malloc(sizeof(*newentry));
newentry->key = key;
newentry->value = value;
INIT_LIST_HEAD(&newentry->list);
list_add(&newentry->list, &d->buckets[hash]);
return 0;
}
const void *dict_remove_entry(struct dict *d, unsigned long key)
{
unsigned int hash = d->key2hash(key) % d->size;
struct dict_entry *entry = _dict_find_entry(d, key, hash);
if (entry) {
const void *value = entry->value;
list_del(&entry->list);
free(entry);
return value;
}
return NULL;
}
const void *dict_find_entry(struct dict *d, unsigned long key)
{
unsigned int hash = d->key2hash(key) % d->size;
struct dict_entry *entry = _dict_find_entry(d, key, hash);
return entry ? entry->value : NULL;
}
int dict_apply_to_all(struct dict *d, int (*func)(unsigned long key, const void *value, void *data), void *data)
{
unsigned int i;
for (i = 0; i < d->size; i++) {
struct list_head *it, *next;
list_for_each_safe(it, next, &d->buckets[i]) {
struct dict_entry *entry = container_of(it, struct dict_entry, list);
if (func(entry->key, entry->value, data))
return -1;
}
}
return 0;
}

39
dict.h Normal file
View File

@ -0,0 +1,39 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata
* Copyright (C) 2003,2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
* Copyright (C) ???? Morten Eriksen <mortene@sim.no>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_DICT_H
#define _INC_DICT_H
struct dict;
struct dict *dict_init(unsigned int size, unsigned int (*key2hash)(unsigned long), int (*key_cmp)(unsigned long, unsigned long));
void dict_clear(struct dict *d);
int dict_add(struct dict *d, unsigned long key, const void *value);
const void *dict_remove_entry(struct dict *d, unsigned long key);
const void *dict_find_entry(struct dict *d, unsigned long key);
int dict_apply_to_all(struct dict *d, int (*func) (unsigned long key, const void *value, void *data), void *data);
#endif

1982
dwarf.c Normal file

File diff suppressed because it is too large Load Diff

136
dwarf.h Normal file
View File

@ -0,0 +1,136 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the libunwind source
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_DWARF_H
#define _INC_DWARF_H
#include <stdint.h>
#include "arch.h"
#include "forward.h"
#include "mtelf.h"
#define DWARF_LOC(r, t) ((struct dwarf_loc){ .val = (r), .type = (t) })
#define DWARF_GET_LOC(l) ((l).val)
#define DWARF_LOC_TYPE_MEM 0
#define DWARF_LOC_TYPE_REG 1
#define DWARF_LOC_TYPE_VAL 2
#define DWARF_NULL_LOC DWARF_LOC(0, 0)
#define DWARF_MEM_LOC(m) DWARF_LOC((m), DWARF_LOC_TYPE_MEM)
#define DWARF_REG_LOC(r) DWARF_LOC((r), DWARF_LOC_TYPE_REG)
#define DWARF_VAL_LOC(v) DWARF_LOC((v), DWARF_LOC_TYPE_VAL)
#define DWARF_IS_NULL_LOC(l) ({ struct dwarf_loc _l = (l); _l.val == 0 && _l.type == 0; })
#define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM)
#define DWARF_IS_REG_LOC(l) ((l).type == DWARF_LOC_TYPE_REG)
#define DWARF_IS_VAL_LOC(l) ((l).type == DWARF_LOC_TYPE_VAL)
#define DWARF_ADDR_SIZE(as) ((as)->task->is_64bit ? 8 : 4)
#define DWARF_ENOMEM 1 /* out of memory */
#define DWARF_EBADREG 2 /* bad register number */
#define DWARF_EBADFRAME 3 /* bad frame */
#define DWARF_EINVAL 4 /* unsupported operation or bad value */
#define DWARF_EBADVERSION 5 /* unwind info has unsupported version */
#define DWARF_ENOINFO 6 /* no unwind info found */
#define DWARF_STOPUNWIND 7 /* no unwind info found */
struct dwarf_cie_info {
arch_addr_t start_ip; /* first IP covered by this procedure */
arch_addr_t ip_range; /* ip range covered by this procedure */
arch_addr_t cie_instr_start; /* start addr. of CIE "initial_instructions" */
arch_addr_t cie_instr_end; /* end addr. of CIE "initial_instructions" */
arch_addr_t fde_instr_start; /* start addr. of FDE "instructions" */
arch_addr_t fde_instr_end; /* end addr. of FDE "instructions" */
arch_addr_t code_align; /* code-alignment factor */
arch_addr_t data_align; /* data-alignment factor */
arch_addr_t ret_addr_column; /* column of return-address register */
uint16_t abi;
uint16_t tag;
uint8_t fde_encoding;
uint8_t lsda_encoding;
unsigned int sized_augmentation:1;
unsigned int have_abi_marker:1;
unsigned int signal_frame:1;
};
struct dwarf_loc {
unsigned long val;
unsigned int type;
};
struct dwarf_cursor {
arch_addr_t cfa; /* canonical frame address; aka frame-/stack-pointer */
arch_addr_t ip; /* instruction pointer */
arch_addr_t ret_addr_column; /* column for return-address */
unsigned int use_prev_instr:1; /* use previous (= call) or current (= signal) instruction? */
unsigned int valid:1;
struct library *lib;
struct dwarf_cie_info dci;
struct dwarf_loc *loc;
};
struct dwarf_addr_space {
struct task *task;
arch_addr_t addr;
union {
long val;
unsigned char val_bytes[sizeof(long)];
};
struct dwarf_cursor cursor;
unsigned int ip_reg;
unsigned int ret_reg;
unsigned int num_regs;
};
struct dwarf_eh_frame_hdr;
void *dwarf_init(struct task *task);
void dwarf_destroy(struct dwarf_addr_space *as);
int dwarf_init_unwind(struct dwarf_addr_space *as);
int dwarf_step(struct dwarf_addr_space *as);
arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as);
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
int dwarf_get_unwind_table(struct task *task, struct library *lib, struct dwarf_eh_frame_hdr *hdr);
int dwarf_arch_init(struct dwarf_addr_space *as);
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
int dwarf_arch_step(struct dwarf_addr_space *as);
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg);
#ifdef DWARF_TO_REGNUM
unsigned int dwarf_to_regnum(unsigned int reg);
#else
static inline unsigned int dwarf_to_regnum(unsigned int reg)
{
return reg;
}
#endif
#endif

343
event.c Normal file
View File

@ -0,0 +1,343 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2007,2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 1998,2001,2004,2007,2008,2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#define _GNU_SOURCE
#include <assert.h>
#include <sys/ptrace.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h>
#include "backend.h"
#include "breakpoint.h"
#include "common.h"
#include "debug.h"
#include "event.h"
#include "library.h"
#include "mtrace.h"
#include "options.h"
#include "report.h"
#include "task.h"
#include "trace.h"
static LIST_HEAD(event_head);
void queue_event(struct task *task)
{
if (task) {
if (task->event.type != EVENT_NONE)
list_add_tail(&task->event.list, &event_head);
}
}
void wait_for_event(struct task *task)
{
while(task->event.type == EVENT_NONE)
queue_event(wait_event());
}
struct task *next_event(void)
{
if (!list_empty(&event_head)) {
struct task *task = container_of(event_head.next, struct task, event.list);
list_del(&task->event.list);
return task;
}
return wait_event();
}
void remove_event(struct task *task)
{
task->event.type = EVENT_NONE;
list_del(&task->event.list);
}
void init_event(struct task *task)
{
task->event.type = EVENT_NONE;
INIT_LIST_HEAD(&task->event.list);
}
static void show_clone(struct task *task, enum event_type type)
{
const char *str;
switch(type) {
case EVENT_FORK:
str = "fork";
break;
case EVENT_VFORK:
str = "vfork";
break;
case EVENT_CLONE:
str = "clone";
break;
default:
str = "?";
break;
}
fprintf(options.output, "+++ process pid=%d %s (newpid=%d) +++\n", task->pid, str, task->event.e_un.newpid);
}
static struct task *handle_clone(struct task *task, enum event_type type)
{
struct task *newproc;
int newpid = task->event.e_un.newpid;
debug(DEBUG_FUNCTION, "pid=%d, newpid=%d", task->pid, newpid);
if (options.verbose)
show_clone(task, type);
continue_task(task, 0);
newproc = task_clone(task, newpid);
if (!newproc)
goto fail;
if (newproc->leader == newproc) {
if (!options.follow) {
remove_proc(newproc);
return task;
}
report_fork(newproc, task->pid);
}
continue_task(newproc, newproc->event.e_un.signum);
return task;
fail:
fprintf(stderr,
"Error during init of tracing process %d\n"
"This process won't be traced.\n",
newpid
);
return task;
}
static struct task *handle_signal(struct task *task)
{
continue_task(task, task->event.e_un.signum);
return task;
}
static void show_exit(struct task *task)
{
if (options.verbose)
fprintf(options.output, "+++ process pid=%d exited (status=%d) +++\n", task->pid, task->event.e_un.ret_val);
}
static struct task *handle_about_exit(struct task *task)
{
show_exit(task);
if (task->leader == task) {
if (report_about_exit(task) != -1)
return task;
remove_proc(task);
}
else
remove_task(task);
return NULL;
}
static struct task *handle_exit(struct task *task)
{
show_exit(task);
if (task->leader == task) {
report_exit(task);
remove_proc(task);
}
else
remove_task(task);
return NULL;
}
static struct task *handle_exit_signal(struct task *task)
{
if (options.verbose)
fprintf(options.output, "+++ process pid=%d killed by signal %s (%d) +++\n", task->pid, strsignal(task->event.e_un.signum), task->event.e_un.signum);
if (task->leader == task) {
report_exit(task);
remove_proc(task);
}
else
remove_task(task);
return NULL;
}
static struct task *handle_exec(struct task *task)
{
debug(DEBUG_FUNCTION, "pid=%d", task->pid);
if (!options.follow_exec)
goto nofollow;
if (process_exec(task) < 0) {
fprintf(stderr, "couldn't reinitialize process %d after exec\n", task->pid);
goto untrace;
}
if (options.verbose)
fprintf(options.output, "+++ process pid=%d exec (%s) +++\n", task->pid, library_execname(task));
continue_task(task, 0);
return task;
nofollow:
report_nofollow(task);
untrace:
remove_proc(task);
return NULL;
}
static int handle_call_after(struct task *task, struct breakpoint *bp)
{
if (!task->breakpoint)
return 0;
task->libsym->func->report_out(task, task->libsym);
task->breakpoint = NULL;
task->libsym = NULL;
return 0;
}
static struct task *handle_breakpoint(struct task *task)
{
struct breakpoint *bp = task->event.e_un.breakpoint;
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
if (task->skip_bp == bp) {
task->skip_bp = NULL;
skip_breakpoint(task, bp);
return task;
}
if (breakpoint_on_hit(task, bp)) {
set_instruction_pointer(task, bp->addr);
continue_task(task, 0);
return task;
}
if (bp->libsym && !task->breakpoint) {
struct library_symbol *libsym = bp->libsym;
save_param_context(task);
if (libsym->func->report_out) {
task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, HW_BP_SCRATCH);
if (task->breakpoint) {
task->libsym = libsym;
task->breakpoint->on_hit = handle_call_after;
}
enable_scratch_hw_bp(task, task->breakpoint);
}
if (libsym->func->report_in)
libsym->func->report_in(task, libsym);
}
if (task->stopped)
skip_breakpoint(task, bp);
return task;
}
int handle_event(void)
{
struct task *task = next_event();
if (!task)
return 0;
struct event *event = &task->event;
enum event_type type = event->type;
event->type = EVENT_NONE;
debug(DEBUG_FUNCTION, "pid=%d, type=%d", task->pid, event->type);
switch (type) {
case EVENT_NONE:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event none", task->pid);
break;
case EVENT_SIGNAL:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event signal %d", task->pid, event->e_un.signum);
task = handle_signal(task);
break;
case EVENT_ABOUT_EXIT:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
task = handle_about_exit(task);
break;
case EVENT_EXIT:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
task = handle_exit(task);
break;
case EVENT_EXIT_SIGNAL:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit signal %d", task->pid, event->e_un.signum);
task = handle_exit_signal(task);
break;
case EVENT_FORK:
case EVENT_VFORK:
case EVENT_CLONE:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event clone (%u)", task->pid, event->e_un.newpid);
task = handle_clone(task, type);
break;
case EVENT_EXEC:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exec()", task->pid);
task = handle_exec(task);
break;
case EVENT_BREAKPOINT:
debug(DEBUG_EVENT_HANDLER, "pid=%d, event breakpoint %#lx", task->pid, event->e_un.breakpoint->addr);
task = handle_breakpoint(task);
break;
default:
fprintf(stderr, "Error! unknown event?\n");
return -1;
}
return 1;
}

62
event.h Normal file
View File

@ -0,0 +1,62 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_EVENT_H
#define _INC_EVENT_H
#include "forward.h"
#include "list.h"
enum event_type {
EVENT_NONE = 0,
EVENT_SIGNAL,
EVENT_ABOUT_EXIT,
EVENT_EXIT,
EVENT_EXIT_SIGNAL,
EVENT_FORK,
EVENT_CLONE,
EVENT_VFORK,
EVENT_EXEC,
EVENT_BREAKPOINT,
EVENT_MAX
};
struct event {
struct list_head list;
enum event_type type;
union {
int ret_val; /* EVENT_EXIT */
int signum; /* EVENT_SIGNAL, EVENT_EXIT_SIGNAL */
struct breakpoint *breakpoint; /* EVENT_BREAKPOINT */
int newpid; /* EVENT_CLONE, EVENT_FORK, EVENT_VFORK */
} e_un;
};
void init_event(struct task *task);
void remove_event(struct task *task);
struct task *next_event(void);
void wait_for_event(struct task *task);
void queue_event(struct task *task);
int handle_event(void);
#endif

35
forward.h Normal file
View File

@ -0,0 +1,35 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/* Important types defined in other header files are declared here. */
#ifndef _INC_FORWARD_H
#define _INC_FORWARD_H
struct event;
struct task;
struct breakpoint;
struct library;
struct library_symbol;
struct mt_elf;
struct mt_msg;
#endif

298
library.c Normal file
View File

@ -0,0 +1,298 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2001,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <sys/mman.h>
#include "backend.h"
#include "breakpoint.h"
#include "debug.h"
#include "dict.h"
#include "library.h"
#include "report.h"
#include "server.h"
#include "task.h"
struct library_symbol *library_symbol_new(struct library *lib, arch_addr_t addr, const struct function *func)
{
struct library_symbol *libsym = malloc(sizeof(*libsym));
if (!libsym)
return NULL;
INIT_LIST_HEAD(&libsym->list);
libsym->lib = NULL;
libsym->func = func;
libsym->addr = addr;
list_add_tail(&libsym->list, &lib->sym_list);
return libsym;
}
static void library_symbol_destroy(struct task *task, struct library_symbol *libsym)
{
struct breakpoint *bp = breakpoint_find(task, libsym->addr);
if (bp)
breakpoint_delete(task, bp);
list_del(&libsym->list);
free(libsym);
}
static struct library_symbol *library_symbol_clone(struct library *lib, struct library_symbol *libsym)
{
struct library_symbol *retp = library_symbol_new(lib, libsym->addr, libsym->func);
if (!retp)
return NULL;
return retp;
}
struct library *library_new(void)
{
struct library *lib = malloc(sizeof(*lib));
if (lib == NULL)
return NULL;
memset(lib, 0, sizeof(*lib));
INIT_LIST_HEAD(&lib->list);
INIT_LIST_HEAD(&lib->sym_list);
return lib;
}
void library_destroy(struct task *task, struct library *lib)
{
if (lib == NULL)
return;
struct list_head *it, *next;
list_for_each_safe(it, next, &lib->sym_list) {
struct library_symbol *sym = container_of(it, struct library_symbol, list);
library_symbol_destroy(task, sym);
}
list_del(&lib->list);
if (lib->image_addr)
munmap(lib->image_addr, lib->load_size);
free(lib);
}
void library_set_filename(struct library *lib, const char *new_name)
{
free((void *)lib->filename);
lib->filename = new_name ? strdup(new_name) : NULL;
}
static struct library *library_clone(struct task *clone, struct library *lib)
{
struct list_head *it;
struct library *retp = library_new();
if (!retp)
return NULL;
library_set_filename(retp, lib->filename);
retp->key = lib->key;
/* Clone symbols. */
list_for_each(it, &lib->sym_list) {
if (!library_symbol_clone(retp, container_of(it, struct library_symbol, list)))
goto fail;
}
return retp;
fail:
/* Release what we managed to allocate. */
library_destroy(clone, retp);
return NULL;
}
static void library_each_symbol(struct library *lib, void (*cb)(struct library_symbol *, void *), void *data)
{
struct list_head *it, *next;
list_for_each_safe(it, next, &lib->sym_list) {
struct library_symbol *sym = container_of(it, struct library_symbol, list);
(*cb) (sym, data);
}
}
struct library_symbol *library_find_symbol(struct library *lib, arch_addr_t addr)
{
struct list_head *it;
list_for_each(it, &lib->sym_list) {
struct library_symbol *sym = container_of(it, struct library_symbol, list);
if (sym->addr == addr)
return sym;
}
return NULL;
}
struct library_symbol *find_symbol(struct task *leader, arch_addr_t addr)
{
/* Clone symbols first so that we can clone and relink breakpoints. */
struct list_head *it;
list_for_each(it, &leader->libraries_list) {
struct library *lib = container_of(it, struct library, list);
struct library_symbol *libsym = library_find_symbol(lib, addr);
if (libsym)
return libsym;
}
return NULL;
}
struct library *library_find_with_key(struct list_head *list, arch_addr_t key)
{
struct list_head *it;
list_for_each(it, list) {
struct library *lib = container_of(it, struct library, list);
if (lib->key == key)
return lib;
}
return NULL;
}
void library_delete_list(struct task *leader, struct list_head *list)
{
struct list_head *it, *next;
list_for_each_safe(it, next, list) {
struct library *lib = container_of(it, struct library, list);
debug(DEBUG_FUNCTION, "%s@%#lx", lib->filename, lib->base);
library_destroy(leader, lib);
}
}
static void cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
{
struct task *task = data;
arch_addr_t addr = libsym->addr;
struct breakpoint *bp = breakpoint_find(task, addr);
if (bp) {
assert(bp->libsym == NULL);
bp->libsym = libsym;
return;
}
bp = breakpoint_new(task, addr, libsym, libsym->func->hw_bp_min <= HW_BREAKPOINTS ? HW_BP : SW_BP);
if (!bp)
fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s.", libsym->func->name, task->pid, strerror(errno));
if (server_connected())
breakpoint_enable(task, bp);
}
void library_add(struct task *leader, struct library *lib)
{
assert(leader->leader == leader);
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", lib->filename, lib->base, leader->pid);
/* Insert breakpoints for all active symbols. */
library_each_symbol(lib, cb_breakpoint_for_symbol, leader);
list_add_tail(&lib->list, &leader->libraries_list);
report_add_map(leader, lib);
}
void cb_remove_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
{
struct task *task = data;
arch_addr_t addr = libsym->addr;
struct breakpoint *bp = breakpoint_find(task, addr);
if (bp)
breakpoint_delete(task, bp);
}
void library_remove(struct task *leader, struct library *lib)
{
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", lib->filename, lib->base, leader->pid);
library_each_symbol(lib, cb_remove_breakpoint_for_symbol, leader);
list_del(&lib->list);
report_del_map(leader, lib);
}
void library_clear_all(struct task *leader)
{
library_delete_list(leader, &leader->libraries_list);
}
int library_clone_all(struct task *clone, struct task *leader)
{
struct list_head *it;
list_for_each(it, &leader->libraries_list) {
struct library *lib = container_of(it, struct library, list);
struct library *nlibp = library_clone(clone, lib);
if (!nlibp)
return -1;
list_add_tail(&nlibp->list, &clone->libraries_list);
}
return 0;
}
void library_setup(struct task *leader)
{
INIT_LIST_HEAD(&leader->libraries_list);
}
const char *library_execname(struct task *leader)
{
if (list_empty(&leader->libraries_list))
return NULL;
return container_of(leader->libraries_list.next, struct library, list)->filename;
}

121
library.h Normal file
View File

@ -0,0 +1,121 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2006 Paul Gilliam, IBM Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_LIBRARY_H
#define _INC_LIBRARY_H
#include <stdint.h>
#include "forward.h"
#include "sysdep.h"
#include "list.h"
#include "mtelf.h"
struct library_symbol {
struct list_head list;
struct library *lib;
const struct function *func;
arch_addr_t addr;
};
struct library_symbol *library_symbol_new(struct library *lib, arch_addr_t addr, const struct function *func);
struct library {
struct list_head list;
/* Symbols associated with the library. This includes a
* symbols that don't have a breakpoint attached (yet). */
struct list_head sym_list;
/* Unique key. Two library objects are considered equal, if
* they have the same key. */
arch_addr_t key;
/* Address where the library is mapped. */
arch_addr_t base;
/* Absolute address of the entry point. Useful for main
* binary, though I suppose the value might be useful for the
* dynamic linker, too (in case we ever want to do early
* process tracing). */
arch_addr_t entry;
const char *filename;
/* executable segment */
unsigned long load_offset;
unsigned long load_addr;
unsigned long load_size;
/* mapped image */
void *image_addr;
/* global-pointer */
arch_addr_t gp;
unsigned long seg_offset;
void *table_data;
unsigned long table_len;
#ifdef __arm__
void *exidx_data;
unsigned long exidx_len;
#endif
};
/* Init LIB. */
struct library *library_new(void);
/* Destroy library. Doesn't free LIB itself. Symbols are destroyed
* and freed. */
void library_destroy(struct task *leader, struct library *lib);
/* Set library filename. Frees the old name if necessary. */
void library_set_filename(struct library *lib, const char *new_name);
/* Add a library to the list of the thread leader libraries. */
void library_add(struct task *leader, struct library *lib);
/* delete a given list of libraries */
void library_delete_list(struct task *leader, struct list_head *list);
/* delete all libraries of a given leader */
void library_clear_all(struct task *leader);
/* cline all libraries of a given leader to a new task leader*/
int library_clone_all(struct task *clone, struct task *leader);
/* setup library list of a given leader */
void library_setup(struct task *leader);
/* get the pathname of the executable */
const char *library_execname(struct task *leader);
/* Iterate through list of symbols of library. */
struct library_symbol *library_find_symbol(struct library *lib, arch_addr_t addr);
/* find a library with a given key */
struct library *library_find_with_key(struct list_head *list, arch_addr_t key);
/* Iterate through list all symbols of leader task. */
struct library_symbol *find_symbol(struct task *leader, arch_addr_t addr);
#endif

228
list.h Normal file
View File

@ -0,0 +1,228 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on linux kernel list.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_LIST_H
#define _INC_LIST_H
#define prefetch(x) __builtin_prefetch(x)
struct list_head {
struct list_head *next, *prev;
};
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = entry;
entry->prev = entry;
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del_entry(list);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del_entry(list);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#endif

172
main.c Normal file
View File

@ -0,0 +1,172 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#define _GNU_SOURCE
#include <sys/param.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "backend.h"
#include "breakpoint.h"
#include "common.h"
#include "client.h"
#include "debug.h"
#include "options.h"
#include "library.h"
#include "main.h"
#include "mtelf.h"
#include "mtrace.h"
#include "server.h"
#include "task.h"
#include "trace.h"
static int do_exit;
void mtrace_request_exit(void)
{
if (do_exit)
return;
if (options.verbose)
fprintf(options.output, "+++ request exit +++\n");
do_exit = 1;
wait_event_wakeup();
}
static void dump_process(struct task *leader)
{
if (!leader)
return;
pid_t pid = leader->pid;
report_detach(leader);
while(server_handle_command() != -1) {
struct task *task = pid2task(pid);
if (!task)
break;
if (!task->stopped)
break;
}
}
static void mtrace_exit(void)
{
each_process(stop_threads);
while(server_connected()) {
if (task_list_empty())
break;
dump_process(get_first_process());
}
each_process(remove_proc);
each_pid(remove_task);
}
static void mtrace_init(char **cmd)
{
struct opt_p_t *opt_p_tmp;
if (os_init())
exit(EXIT_FAILURE);
if (options.command) {
struct task *task = task_create(options.command, cmd);
if (!task)
exit(EXIT_FAILURE);
if (options.verbose)
fprintf(options.output, "+++ process pid=%d created (%s) +++\n", task->pid, library_execname(task));
}
for(opt_p_tmp = options.opt_p; opt_p_tmp; opt_p_tmp = opt_p_tmp->next)
open_pid(opt_p_tmp->pid);
}
static void mtrace_main(void)
{
while(!do_exit) {
if (task_list_empty())
break;
if (handle_event() == -1)
break;
if (server_poll() == -1)
break;
}
}
int main(int argc, char *argv[])
{
char **cmd = process_options(argc, argv);
if (options.client) {
if (client_start() == -1)
exit(EXIT_FAILURE);
return 0;
}
if (options.server) {
if (server_start() == -1)
exit(EXIT_FAILURE);
}
else {
int ret = server_start_pair();
if (ret == -1)
exit(EXIT_FAILURE);
if (client_start_pair(ret))
exit(EXIT_FAILURE);
}
mtrace_init(cmd);
mtrace_main();
mtrace_exit();
report_disconnect();
client_stop();
server_stop();
return 0;
}

27
main.h Normal file
View File

@ -0,0 +1,27 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_MAIN_H
#define _INC_MAIN_H
void mtrace_request_exit(void);
#endif

92
memtrace.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef _INC_MEMTRACE_H
#define _INC_MEMTRACE_H
#include <stdint.h>
#if __LP64__
#define IS64BIT 1
#else
#define IS64BIT 0
#endif
#define MEMTRACE_SI_VERSION 5
#define MEMTRACE_SI_FORK 1
#define MEMTRACE_SI_EXEC 2
#define MEMTRACE_SI_VERBOSE 4
enum mt_operation {
MT_DISCONNECT,
MT_INFO,
MT_ADD_MAP,
MT_DEL_MAP,
MT_ATTACH,
MT_ATTACH64,
MT_FORK,
MT_ABOUT_EXIT,
MT_EXIT,
MT_NOFOLLOW,
MT_MALLOC,
MT_REALLOC_ENTER,
MT_REALLOC_FAILED,
MT_REALLOC,
MT_FREE,
MT_MMAP,
MT_MMAP64,
MT_MUNMAP,
MT_MEMALIGN,
MT_POSIX_MEMALIGN,
MT_ALIGNED_ALLOC,
MT_VALLOC,
MT_PVALLOC,
MT_SCAN,
MT_STOP,
MT_START,
MT_DETACH,
};
struct mt_msg {
uint16_t operation;
uint32_t pid;
uint32_t tid;
uint32_t payload_len;
};
struct mt_alloc_payload_64 {
uint64_t ptr;
uint64_t size;
uint64_t data[0];
};
struct mt_alloc_payload_32 {
uint32_t ptr;
uint32_t size;
uint32_t data[0];
};
struct mt_pid_payload {
uint32_t pid;
};
struct mt_scan_payload {
uint32_t ptr_size;
uint64_t mask;
char data[0];
};
struct memtrace_info {
uint8_t version;
uint8_t mode;
uint8_t do_trace;
uint8_t stack_depth;
};
struct mt_map_payload {
uint64_t addr;
uint64_t offset;
uint64_t size;
char filename[0];
};
#endif

529
mtelf.c Normal file
View File

@ -0,0 +1,529 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2006,2010,2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2010 Zachary T Welch, CodeSourcery
* Copyright (C) 2010 Joe Damato
* Copyright (C) 1997,1998,2001,2004,2007,2008,2009 Juan Cespedes
* Copyright (C) 2006 Olaf Hering, SUSE Linux GmbH
* Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
* Copyright (C) 2006 Paul Gilliam, IBM Corporation
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <gelf.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "backend.h"
#include "breakpoint.h"
#include "dwarf.h"
#include "library.h"
#include "mtelf.h"
#include "task.h"
#include "debug.h"
#include "options.h"
#include "common.h"
#include "report.h"
static int open_elf(struct mt_elf *mte, const char *filename)
{
mte->filename = filename;
mte->fd = open(filename, O_RDONLY);
if (mte->fd == -1)
return 1;
elf_version(EV_CURRENT);
#ifdef HAVE_ELF_C_READ_MMAP
mte->elf = elf_begin(mte->fd, ELF_C_READ_MMAP, NULL);
#else
mte->elf = elf_begin(mte->fd, ELF_C_READ, NULL);
#endif
if (mte->elf == NULL || elf_kind(mte->elf) != ELF_K_ELF) {
fprintf(stderr, "\"%s\" is not an ELF file\n", filename);
exit(EXIT_FAILURE);
}
if (gelf_getehdr(mte->elf, &mte->ehdr) == NULL) {
fprintf(stderr, "can't read ELF header of \"%s\": %s\n", filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
if (mte->ehdr.e_type != ET_EXEC && mte->ehdr.e_type != ET_DYN) {
fprintf(stderr, "\"%s\" is neither an ELF executable" " nor a shared library\n", filename);
exit(EXIT_FAILURE);
}
if (1
#ifdef MT_ELF_MACHINE
&& (mte->ehdr.e_ident[EI_CLASS] != MT_ELFCLASS || mte->ehdr.e_machine != MT_ELF_MACHINE)
#endif
#ifdef MT_ELF_MACHINE2
&& (mte->ehdr.e_ident[EI_CLASS] != MT_ELFCLASS2 || mte->ehdr.e_machine != MT_ELF_MACHINE2)
#endif
#ifdef MT_ELF_MACHINE3
&& (mte->ehdr.e_ident[EI_CLASS] != MT_ELFCLASS3 || mte->ehdr.e_machine != MT_ELF_MACHINE3)
#endif
) {
fprintf(stderr, "\"%s\" is ELF from incompatible architecture\n", filename);
exit(EXIT_FAILURE);
}
return 0;
}
static void read_symbol_table(struct mt_elf *mte, const char *filename, Elf_Scn *scn, GElf_Shdr *shdr, const char *name, Elf_Data ** datap, size_t *countp, const char **strsp)
{
*datap = elf_getdata(scn, NULL);
*countp = shdr->sh_size / shdr->sh_entsize;
if ((*datap == NULL || elf_getdata(scn, *datap) != NULL)) {
fprintf(stderr, "Couldn't get data of section" " %s from \"%s\": %s\n", name, filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
scn = elf_getscn(mte->elf, shdr->sh_link);
GElf_Shdr shdr2;
if (scn == NULL || gelf_getshdr(scn, &shdr2) == NULL) {
fprintf(stderr, "Couldn't get header of section" " #%d from \"%s\": %s\n", shdr2.sh_link, filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
Elf_Data *data = elf_getdata(scn, NULL);
if (data == NULL || elf_getdata(scn, data) != NULL || shdr2.sh_size != data->d_size || data->d_off) {
fprintf(stderr, "Couldn't get data of section" " #%d from \"%s\": %s\n", shdr2.sh_link, filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
*strsp = data->d_buf;
}
static int populate_this_symtab(struct mt_elf *mte, struct library *lib, Elf_Data *symtab, const char *strtab, size_t size)
{
size_t i;
for (i = 0; i < size; ++i) {
GElf_Sym sym;
if (gelf_getsym(symtab, i, &sym) == NULL) {
fprintf(stderr, "couldn't get symbol #%zd from %s: %s\n", i, mte->filename, elf_errmsg(-1));
continue;
}
if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_value == 0 || sym.st_shndx == STN_UNDEF)
continue;
/* Find symbol name and snip version. */
const char *orig_name = strtab + sym.st_name;
const char *version = strchr(orig_name, '@');
size_t len = version ? (size_t)(version - orig_name) : strlen(orig_name);
char name[len + 1];
memcpy(name, orig_name, len);
name[len] = 0;
/* If the symbol is not matched, skip it. */
const struct function *func = flist_matches_symbol(name);
if (!func)
continue;
arch_addr_t addr = ARCH_ADDR_T(sym.st_value + mte->bias);
if (!library_find_symbol(lib, addr)) {
struct library_symbol *libsym = library_symbol_new(lib, addr, func);
if (!libsym) {
fprintf(stderr, "couldn't init symbol: %s%s\n", name, func->name);
continue;
}
}
}
return 0;
}
static int populate_symtab(struct mt_elf *mte, struct library *lib)
{
if (mte->symtab != NULL && mte->strtab != NULL) {
int status = populate_this_symtab(mte, lib, mte->symtab, mte->strtab, mte->symtab_count);
if (status < 0)
return status;
}
return populate_this_symtab(mte, lib, mte->dynsym, mte->dynstr, mte->dynsym_count);
}
static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
{
void *addr;
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
if (addr == MAP_FAILED) {
fprintf(stderr, "mmap failed\n");
return -1;
}
*image_addr = addr;
return 0;
}
static int elf_lib_init(struct mt_elf *mte, struct task *task, struct library *lib)
{
if (elf_map_image(mte, &lib->image_addr))
return -1;
lib->base = ARCH_ADDR_T(mte->base_addr);
lib->entry = ARCH_ADDR_T(mte->entry_addr);
lib->load_offset = mte->txt_hdr.p_offset;
lib->load_addr = mte->txt_hdr.p_vaddr + mte->bias;
lib->load_size = mte->txt_hdr.p_filesz;
lib->seg_offset = mte->eh_hdr.p_offset;
lib->gp = mte->pltgot;
#ifdef __arm__
if (mte->exidx_hdr.p_filesz) {
lib->exidx_data = lib->image_addr + mte->exidx_hdr.p_offset;
lib->exidx_len = mte->exidx_hdr.p_memsz;
}
#endif
if (mte->eh_hdr.p_filesz && mte->dyn_addr) {
if (dwarf_get_unwind_table(task, lib, (struct dwarf_eh_frame_hdr *)(lib->image_addr - lib->load_offset + mte->eh_hdr.p_offset)) < 0)
return -1;
}
if (populate_symtab(mte, lib) < 0)
return -1;
return 0;
}
static void close_elf(struct mt_elf *mte)
{
if (mte->fd != -1) {
elf_end(mte->elf);
close(mte->fd);
}
}
static int elf_read(struct mt_elf *mte, const char *filename, GElf_Addr bias)
{
debug(DEBUG_FUNCTION, "filename=%s", filename);
if (open_elf(mte, filename) < 0)
return -1;
GElf_Phdr phdr;
int i;
memset(&mte->txt_hdr, 0, sizeof(mte->txt_hdr));
memset(&mte->eh_hdr, 0, sizeof(mte->eh_hdr));
memset(&mte->dyn_hdr, 0, sizeof(mte->dyn_hdr));
memset(&mte->exidx_hdr, 0, sizeof(mte->exidx_hdr));
for (i = 0; gelf_getphdr(mte->elf, i, &phdr) != NULL; ++i) {
switch (phdr.p_type) {
case PT_LOAD:
if (!mte->base_addr || mte->base_addr > phdr.p_vaddr + bias)
mte->base_addr = phdr.p_vaddr + bias;
if ((phdr.p_flags & (PF_X | PF_W)) == PF_X)
mte->txt_hdr = phdr;
break;
case PT_GNU_EH_FRAME:
mte->eh_hdr = phdr;
break;
#ifdef __arm__
case PT_ARM_EXIDX:
mte->exidx_hdr = phdr;
break;
#endif
case PT_INTERP:
mte->interp = phdr.p_vaddr + bias;
break;
default:
break;
}
}
if (!mte->base_addr) {
fprintf(stderr, "Couldn't determine base address of %s\n", filename);
return -1;
}
debug(DEBUG_FUNCTION, "filename=`%s' load_offset=%#llx addr=%#llx size=%#llx",
filename,
(unsigned long long)mte->txt_hdr.p_offset,
(unsigned long long)mte->txt_hdr.p_vaddr + bias,
(unsigned long long)mte->txt_hdr.p_filesz);
for (i = 1; i < mte->ehdr.e_shnum; ++i) {
Elf_Scn *scn;
GElf_Shdr shdr;
const char *name;
scn = elf_getscn(mte->elf, i);
if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
fprintf(stderr, "Couldn't get section #%d from" " \"%s\": %s\n", i, filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
name = elf_strptr(mte->elf, mte->ehdr.e_shstrndx, shdr.sh_name);
if (name == NULL) {
fprintf(stderr, "Couldn't get name of section #%d from \"%s\": %s\n", i, filename, elf_errmsg(-1));
exit(EXIT_FAILURE);
}
if (shdr.sh_type == SHT_SYMTAB) {
read_symbol_table(mte, filename, scn, &shdr, name, &mte->symtab, &mte->symtab_count, &mte->strtab);
} else if (shdr.sh_type == SHT_DYNSYM) {
read_symbol_table(mte, filename, scn, &shdr, name, &mte->dynsym, &mte->dynsym_count, &mte->dynstr);
} else if (shdr.sh_type == SHT_DYNAMIC) {
Elf_Data *data;
GElf_Dyn dyn;
int idx;
data = elf_getdata(scn, NULL);
if (data == NULL) {
fprintf(stderr, "Couldn't get .dynamic data from \"%s\": %s\n", filename, strerror(errno));
exit(EXIT_FAILURE);
}
for(idx = 0; gelf_getdyn(data, idx, &dyn); ++idx) {
if (dyn.d_tag == DT_PLTGOT) {
mte->pltgot = dyn.d_un.d_ptr;
break;
}
}
mte->dyn_addr = shdr.sh_addr + bias;
}
}
if (!mte->dyn_addr) {
fprintf(stderr, "Couldn't find .dynamic section \"%s\"\n", filename);
exit(EXIT_FAILURE);
}
if (!mte->dynsym || !mte->dynstr) {
fprintf(stderr, "Couldn't find .dynsym or .dynstr in \"%s\"\n", filename);
exit(EXIT_FAILURE);
}
return 0;
}
int elf_read_library(struct task *task, struct library *lib, const char *filename, GElf_Addr bias)
{
struct mt_elf mte = { };
int ret;
library_set_filename(lib, filename);
if (elf_read(&mte, filename, bias) == -1)
return -1;
mte.bias = bias;
mte.entry_addr = mte.ehdr.e_entry + bias;
ret = elf_lib_init(&mte, task, lib);
close_elf(&mte);
return ret;
}
static arch_addr_t _find_solib_break(struct mt_elf *mte, Elf_Data *symtab, const char *strtab, size_t size)
{
size_t i;
unsigned int j;
static const char * const solib_break_names[] =
{
"r_debug_state",
"_r_debug_state",
"_dl_debug_state",
"rtld_db_dlactivity",
"__dl_rtld_db_dlactivity",
"_rtld_debug_state"
};
for (i = 0; i < size; ++i) {
GElf_Sym sym;
if (gelf_getsym(symtab, i, &sym) == NULL) {
fprintf(stderr, "couldn't get symbol #%zd from %s: %s\n", i, mte->filename, elf_errmsg(-1));
continue;
}
if (GELF_ST_TYPE(sym.st_info) != STT_FUNC || sym.st_value == 0 || sym.st_shndx == STN_UNDEF)
continue;
const char *name = strtab + sym.st_name;
for(j = 0; j < ARRAY_SIZE(solib_break_names); j++) {
if (!strcmp(name, solib_break_names[j]))
return ARCH_ADDR_T(sym.st_value + mte->bias);
}
}
return ARCH_ADDR_T(0);
}
static arch_addr_t find_solib_break(struct mt_elf *mte)
{
if (mte->symtab && mte->strtab) {
arch_addr_t addr = _find_solib_break(mte, mte->symtab, mte->strtab, mte->symtab_count);
if (addr)
return addr;
}
return _find_solib_break(mte, mte->dynsym, mte->dynstr, mte->dynsym_count);
}
struct entry_breakpoint {
struct breakpoint breakpoint; /* must the first element in the structure */
arch_addr_t dyn_addr;
};
static int entry_breakpoint_on_hit(struct task *task, struct breakpoint *a)
{
struct entry_breakpoint *entry_bp = (void *)a;
if (!task)
return 0;
breakpoint_delete(task, &entry_bp->breakpoint);
linkmap_init(task, entry_bp->dyn_addr);
return 1;
}
struct library *elf_read_main_binary(struct task *task)
{
char fname[PATH_MAX];
int ret;
char *filename;
struct mt_elf mte = { };
unsigned long entry;
unsigned long base;
struct library *lib;
filename = pid2name(task->pid);
if (!filename)
return NULL;
lib = library_new();
if (lib == NULL)
goto fail1;
ret = readlink(filename, fname, sizeof(fname) - 1);
if (ret == -1)
goto fail2;
fname[ret] = 0;
library_set_filename(lib, strdup(fname));
if (elf_read(&mte, filename, 0) == -1)
goto fail3;
task->is_64bit = is_64bit(&mte);
if (process_get_entry(task, &entry, &base) < 0) {
fprintf(stderr, "Couldn't find process entry of %s\n", filename);
goto fail3;
}
free(filename);
mte.bias = (GElf_Addr) (uintptr_t) entry - mte.ehdr.e_entry;
mte.entry_addr = (GElf_Addr) (uintptr_t) entry;
if (elf_lib_init(&mte, task, lib))
goto fail3;
close_elf(&mte);
report_attach(task);
library_add(task, lib);
if (!linkmap_init(task, ARCH_ADDR_T(mte.dyn_addr)))
return lib;
if (!mte.interp)
return lib;
struct mt_elf mte_ld = { };
copy_str_from_proc(task, ARCH_ADDR_T(mte.interp), fname, sizeof(fname));
if (!elf_read(&mte_ld, fname, (GElf_Addr)base)) {
mte_ld.bias = (GElf_Addr)base;
mte_ld.entry_addr = mte_ld.ehdr.e_entry + (GElf_Addr)base;
arch_addr_t addr = find_solib_break(&mte_ld);
if (!addr)
addr = ARCH_ADDR_T(entry);
struct entry_breakpoint *entry_bp = (void *)breakpoint_new_ext(task, addr, NULL, 0, sizeof(*entry_bp) - sizeof(entry_bp->breakpoint));
if (!entry_bp)
fprintf(stderr,
"Couldn't initialize entry breakpoint for PID %d.\n"
"Some tracing events may be missed.\n",
task->pid
);
else {
entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit;
entry_bp->breakpoint.locked = 1;
entry_bp->dyn_addr = ARCH_ADDR_T(mte.dyn_addr);
breakpoint_enable(task, &entry_bp->breakpoint);
}
}
close_elf(&mte_ld);
return lib;
fail3:
close_elf(&mte);
fail2:
library_destroy(task, lib);
fail1:
free(filename);
return lib;
}

72
mtelf.h Normal file
View File

@ -0,0 +1,72 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2006,2010,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2010 Zachary T Welch
* Copyright (C) 2001,2004,2007,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_MTRACE_ELF_H
#define _INC_MTRACE_ELF_H
#include <gelf.h>
#include <stdlib.h>
#include "forward.h"
#include "sysdep.h"
struct mt_elf {
int fd;
const char *filename;
Elf *elf;
GElf_Ehdr ehdr;
Elf_Data *dynsym;
size_t dynsym_count;
const char *dynstr;
Elf_Data *symtab;
const char *strtab;
size_t symtab_count;
GElf_Addr dyn_addr;
GElf_Addr bias;
GElf_Addr entry_addr;
GElf_Addr base_addr;
GElf_Addr interp;
GElf_Phdr txt_hdr;
GElf_Phdr eh_hdr;
GElf_Phdr dyn_hdr;
GElf_Phdr exidx_hdr;
GElf_Addr pltgot;
};
struct elf_image {
void *addr; /* pointer to mmap'd image */
size_t size; /* (file-) size of the image */
};
/* For now we assume that all libraries can be
* opened via a filesystem. BASE is ignored for ET_EXEC files. */
int elf_read_library(struct task *task, struct library *lib, const char *filename, GElf_Addr bias);
/* Create a library object representing the main binary. The entry
* point address is stored to *ENTRYP. */
struct library *elf_read_main_binary(struct task *task);
#endif

31
mtrace.h Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_MTRACE_H
#define _INC_MTRACE_H
typedef unsigned long arch_addr_t;
#define ARCH_ADDR_T(x) ((arch_addr_t)(x))
#endif

470
options.c Normal file
View File

@ -0,0 +1,470 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2009,2010 Joe Damato
* Copyright (C) 1998,1999,2002,2003,2004,2007,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
* Copyright (C) 2006 Steve Fink
* Copyright (C) 2006 Paul Gilliam, IBM Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <sys/ioctl.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "options.h"
#ifndef SYSCONFDIR
#define SYSCONFDIR "/etc"
#endif
#define SYSTEM_CONFIG_FILE SYSCONFDIR "/mtrace.conf"
#define USER_CONFIG_FILE "~/.mtrace.conf"
#define MIN_STACK 4
#define MAX_STACK 128
#define DEFAULT_STACK 6
#define DEFAULT_PORT 4576
struct options_t options;
static char *progname; /* Program name (`mtrace') */
static void err_usage(void)
{
fprintf(stderr, "Try `%s --help' for more information.\n", progname);
exit(1);
}
static void usage(void)
{
fprintf(stdout,
"Usage: %s [option ...] [command [arg ...]]\n"
"\n"
"Trace memory allocation library calls of a given program.\n"
"\n"
" -a, --autoscan scan memory on exit of a traced program\n"
" -b, --binpath=path binary search path (may be repeated)\n"
" -c, --client connect to socket (path or address)\n"
#ifdef DEBUG
" -D, --debug=MASK enable debugging (see -Dh or --debug=help)\n"
" -Dh, --debug=help show help on debugging\n"
#endif
" -d, --depth=NR backtrace stack depth (default: " STR(DEFAULT_STACK) ")\n"
" -e, --follow-exec follow exec() system calls\n"
" -F, --config=FILE load alternate configuration file (may be repeated)\n"
" -f, --follow-child trace forked children\n"
" -h, --help display this help and exit\n"
" -i, --interactive interactive client mode\n"
" -l, --listen listen on socket path or address in server mode\n"
" -o, --output=FILE write the trace output to file with given name\n"
" -p, --pid=PID attach to the process with the process ID pid (may be repeated)\n"
" -P, --port=PORT socket port (default: " STR(DEFAULT_PORT) ")\n"
" -s, --server server mode\n"
" -S, --sort-by=type sort dump by type:\n"
" allocations, average, bytes-leaked, leaks, stacks, total, tsc, usage\n"
" -u, --user=USERNAME run command with the userid, groupid of username\n"
" -V, --version output version information and exit\n"
" -v, --verbose verbose mode (repeat for higher verbosity)\n"
" -w, --wait wait for client connection\n"
"\n"
"Report bugs to stefani@seibold.net\n", progname);
}
#ifdef DEBUG
static void usage_debug(void)
{
fprintf(stdout, "%s debugging option, --debug=<octal> or -D<octal>:\n", progname);
fprintf(stdout,
"\n"
" number ref. in source description\n"
" 1 general Generally helpful progress information\n"
" 10 event Shows every event received by a traced process\n"
" 20 process Shows actions carried upon a traced processes\n"
" 40 function Shows every entry to internal functions\n"
"\n"
"Debugging options are mixed using bitwise-or.\n"
"Note that the meanings and values are subject to change.\n"
);
}
#endif
static char *search_for_command(char *filename)
{
static char pathname[PATH_MAX];
char *path;
int m, n;
if (strchr(filename, '/')) {
return filename;
}
for (path = getenv("PATH"); path && *path; path += m) {
if (strchr(path, ':')) {
n = strchr(path, ':') - path;
m = n + 1;
} else {
m = n = strlen(path);
}
if (n + strlen(filename) + 1 >= PATH_MAX) {
fprintf(stderr, "Error: filename too long.\n");
exit(1);
}
strncpy(pathname, path, n);
if (n && pathname[n - 1] != '/') {
pathname[n++] = '/';
}
strcpy(pathname + n, filename);
if (!access(pathname, X_OK)) {
return pathname;
}
}
return filename;
}
static int parse_int(const char *optarg, char opt, int min, int max)
{
char *endptr;
long int l = strtol(optarg, &endptr, 0);
if (l < min || (max != 0 && l > max)
|| *optarg == 0 || *endptr != 0) {
const char *fmt = max != 0 ? "Invalid argument to -%c: '%s'. Use integer %d..%d.\n" : "Invalid argument to -%c: '%s'. Use integer >=%d.\n";
fprintf(stderr, fmt, opt, optarg, min, max);
exit(1);
}
return (int)l;
}
char **process_options(int argc, char **argv)
{
struct opt_F_t *opt_F_last = NULL;
struct opt_p_t *opt_p_last = NULL;
struct opt_b_t *opt_b_last = NULL;
progname = argv[0];
options.auto_scan = 0;
options.output = stderr;
options.bt_depth = DEFAULT_STACK;
options.port = NULL;
options.follow = 0;
options.follow_exec = 0;
options.interactive = 0;
options.verbose = 0;
options.wait = 0;
options.client = NULL;
options.server = 0;
options.listen = NULL;
options.user = NULL;
options.command = NULL;
options.opt_p = NULL;
options.opt_F = NULL;
options.opt_b = NULL;
options.sort_by = -1;
options.debug = 0;
for(;;) {
int c;
int option_index = 0;
static const struct option long_options[] = {
{ "auto_scan", 0, 0, 'a' },
{ "binpath", 1, 0, 'b' },
{ "client", 1, 0, 'c' },
{ "config", 1, 0, 'F' },
{ "debug", 1, 0, 'D' },
{ "depth", 1, 0, 'd' },
{ "help", 0, 0, 'h' },
{ "follow-child", 0, 0, 'f'},
{ "follow-exec", 0, 0, 'e' },
{ "interactive", 0, 0, 'i' },
{ "listen", 1, 0, 'l' },
{ "output", 1, 0, 'o' },
{ "pid", 1, 0, 'p' },
{ "port", 1, 0, 'P' },
{ "server", 0, 0, 's' },
{ "sort-by", 1, 0, 'S' },
{ "user", 1, 0, 'u' },
{ "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' },
{ "wait", 0, 0, 'w' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv,
"+aefhisVvw"
"b:c:D:F:l:o:p:P:u:d:S:",
long_options,
&option_index);
if (c == -1)
break;
switch (c) {
case 'a':
options.auto_scan = 1;
break;
case 'b':
{
struct opt_b_t *tmp = malloc(sizeof(*tmp));
if (!tmp) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
tmp->pathname = strdup(optarg);
tmp->next = NULL;
if (opt_b_last)
opt_b_last->next = tmp;
opt_b_last = tmp;
if (!options.opt_b)
options.opt_b = tmp;
break;
}
case 'c':
options.client = optarg;
break;
case 'D':
{
#ifdef DEBUG
char *p;
if (optarg[0] == 'h') {
usage_debug();
exit(0);
}
options.debug = strtoul(optarg, &p, 8);
if (*p) {
fprintf(stderr, "%s: --debug requires an octal argument\n", progname);
err_usage();
}
#endif
break;
}
case 'f':
options.follow = 1;
break;
case 'F':
{
struct opt_F_t *tmp = malloc(sizeof(*tmp));
if (!tmp) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
tmp->filename = optarg;
tmp->next = NULL;
if (opt_F_last)
opt_F_last->next = tmp;
opt_F_last = tmp;
if (!options.opt_F)
options.opt_F = tmp;
break;
}
case 'h':
usage();
exit(0);
case 'i':
options.interactive = 1;
break;
case 'l':
options.listen = optarg;
break;
case 'o':
options.output = fopen(optarg, "w");
if (!options.output) {
fprintf(stderr, "can't open %s for writing: %s\n", optarg, strerror(errno));
exit(1);
}
setvbuf(options.output, (char *)NULL, _IOLBF, 0);
fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
break;
case 'p':
{
struct opt_p_t *tmp = malloc(sizeof(*tmp));
if (!tmp) {
fprintf(stderr, "%s\n", strerror(errno));
exit(1);
}
tmp->pid = parse_int(optarg, 'p', 1, 0);
tmp->next = NULL;
if (opt_p_last)
opt_p_last->next = tmp;
opt_p_last = tmp;
if (!options.opt_p)
options.opt_p = tmp;
break;
}
case 'P':
options.port = optarg;
break;
case 'u':
options.user = optarg;
break;
case 'V':
printf("mtrace version " PACKAGE_VERSION ".\n"
"Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>.\n"
"\n"
"This software was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich.\n"
"\n"
"This is free software; see the GNU General Public Licence\n"
"version 2 or later for copying conditions. There is NO warranty.\n");
exit(0);
case 'd':
options.bt_depth = parse_int(optarg, 'd', 1, 0);
break;
case 'e':
options.follow_exec = 1;
break;
case 'v':
options.verbose++;
break;
case 'w':
options.wait = 1;
break;
case 's':
options.server = 1;
break;
case 'S':
if (!strncmp(optarg, "allocations", 2))
options.sort_by = OPT_SORT_ALLOCATIONS;
else
if (!strncmp(optarg, "average", 2))
options.sort_by = OPT_SORT_AVERAGE;
else
if (!strncmp(optarg, "bytes-leaked", 1))
options.sort_by = OPT_SORT_BYTES_LEAKED;
else
if (!strncmp(optarg, "leaks", 1))
options.sort_by = OPT_SORT_LEAKS;
else
if (!strncmp(optarg, "stacks", 1))
options.sort_by = OPT_SORT_STACKS;
else
if (!strncmp(optarg, "total", 2))
options.sort_by = OPT_SORT_TOTAL;
else
if (!strncmp(optarg, "tsc", 2))
options.sort_by = OPT_SORT_TSC;
else
if (!strncmp(optarg, "usage", 1))
options.sort_by = OPT_SORT_USAGE;
else {
fprintf(stderr, "invalid sort paramter: %s\n", optarg);
exit(1);
}
break;
default:
err_usage();
}
}
argc -= optind;
argv += optind;
if (options.sort_by == OPT_SORT_LEAKS || options.sort_by == OPT_SORT_BYTES_LEAKED)
options.auto_scan = 1;
if (!options.client && !options.opt_p && argc < 1) {
fprintf(stderr, "%s: too few arguments\n", progname);
err_usage();
}
if (!options.server && options.listen) {
fprintf(stderr, "%s: listen mode can only valid in server mode\n", progname);
err_usage();
}
if (options.client && (options.opt_p || argc > 0)) {
fprintf(stderr, "%s: client mode does not require -p nor executable\n", progname);
err_usage();
}
else
if (options.client && options.server) {
fprintf(stderr, "%s: choose between client and server mode\n", progname);
err_usage();
}
if (options.opt_b && !options.client) {
fprintf(stderr, "%s: binpath can only used in client mode\n", progname);
err_usage();
}
if (options.interactive && (!options.client && !options.opt_p)) {
fprintf(stderr, "%s: interactive mode can only invoked in -p or -c mode\n", progname);
err_usage();
}
if (options.auto_scan && options.server) {
fprintf(stderr, "%s: scan option can not passed in -s mode\n", progname);
err_usage();
}
if (options.port) {
if (!options.client && !options.server) {
fprintf(stderr, "%s: Port only valid in client or server mode \n", progname);
err_usage();
}
}
else
options.port = STR(DEFAULT_PORT);
if (options.sort_by != -1 && options.server) {
fprintf(stderr, "%s: sort-by can not passed in -s mode\n", progname);
err_usage();
}
if (options.bt_depth < MIN_STACK)
options.bt_depth = MIN_STACK;
else
if (options.bt_depth > MAX_STACK)
options.bt_depth = MAX_STACK;
if (!options.opt_F) {
options.opt_F = malloc(sizeof(struct opt_F_t));
options.opt_F->filename = USER_CONFIG_FILE;
options.opt_F->next = malloc(sizeof(struct opt_F_t));
options.opt_F->next->filename = SYSTEM_CONFIG_FILE;
options.opt_F->next->next = NULL;
}
if (argc > 0)
options.command = search_for_command(argv[0]);
return &argv[0];
}

85
options.h Normal file
View File

@ -0,0 +1,85 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2009,2010 Joe Damato
* Copyright (C) 1998,2002,2008 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
* Copyright (C) 2006 Steve Fink
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_OPTIONS_H
#define _INC_OPTIONS_H
#include <sys/types.h>
#include "config.h"
#include "forward.h"
#define OPT_SORT_ALLOCATIONS 0
#define OPT_SORT_AVERAGE 1
#define OPT_SORT_BYTES_LEAKED 2
#define OPT_SORT_LEAKS 3
#define OPT_SORT_STACKS 4
#define OPT_SORT_TOTAL 5
#define OPT_SORT_TSC 6
#define OPT_SORT_USAGE 7
struct options_t options;
struct opt_p_t {
pid_t pid;
struct opt_p_t *next;
};
struct opt_F_t {
const char *filename;
struct opt_F_t *next;
};
struct opt_b_t {
char *pathname;
struct opt_b_t *next;
};
struct options_t {
int auto_scan; /* scan memory on every exit of a trace program */
int bt_depth; /* how may levels of stack frames to show */
int follow; /* trace child processes */
int follow_exec; /* follow exec system calls */
int interactive; /* interactive mode */
FILE *output; /* output to a specific file */
int server; /* server mode flag */
char *listen; /* server listen on socket path or address */
char *client; /* connect to socket path or address */
char *user; /* -u: username to run command as */
int verbose; /* verbose mode */
int wait; /* wait for client connection */
char *port; /* socket port */
char *command; /* command string */
struct opt_p_t *opt_p; /* attach to process with a given pid */
struct opt_F_t *opt_F; /* alternate configuration file(s) */
struct opt_b_t *opt_b; /* binary search path(s) */
int sort_by; /* sort dump in non interative and non server mode */
int debug; /* debug */
};
char **process_options(int argc, char **argv);
#endif

448
rbtree.c Normal file
View File

@ -0,0 +1,448 @@
/*
* Red Black Trees
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the linux kernel source
* Copyright (C) 1999 Andrea Arcangeli <andrea@suse.de>
* Copyright (C) 2002 David Woodhouse <dwmw2@infradead.org>
* Copyright (C) 2012 Michel Lespinasse <walken@google.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "rbtree.h"
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
/*
* This function returns the first node (in sort order) of the tree.
*/
struct rb_node *rb_first(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_left)
n = n->rb_left;
return n;
}
struct rb_node *rb_last(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_right)
n = n->rb_right;
return n;
}
struct rb_node *rb_next(const struct rb_node *node)
{
struct rb_node *parent;
if (rb_parent(node) == node)
return NULL;
/* If we have a right-hand child, go down and then left as far
as we can. */
if (node->rb_right) {
node = node->rb_right;
while (node->rb_left)
node=node->rb_left;
return (struct rb_node *)node;
}
/* No right-hand children. Everything down and left is
smaller than us, so any 'next' node must be in the general
direction of our parent. Go up the tree; any time the
ancestor is a right-hand child of its parent, keep going
up. First time it's a left-hand child of its parent, said
parent is our 'next' node. */
while ((parent = rb_parent(node)) && node == parent->rb_right)
node = parent;
return parent;
}
struct rb_node *rb_prev(const struct rb_node *node)
{
struct rb_node *parent;
if (rb_parent(node) == node)
return NULL;
/* If we have a left-hand child, go down and then right as far
as we can. */
if (node->rb_left) {
node = node->rb_left;
while (node->rb_right)
node=node->rb_right;
return (struct rb_node *)node;
}
/* No left-hand children. Go up till we find an ancestor which
is a right-hand child of its parent */
while ((parent = rb_parent(node)) && node == parent->rb_left)
node = parent;
return parent;
}
int rb_iterate(const struct rb_root *root, int (*func)(struct rb_node *,void *user), void *user)
{
struct rb_node *parent;
struct rb_node *node;
int ret = 0;
node = rb_first(root);
while(node) {
if (rb_parent(node) == node)
break;
if (node->rb_right) {
node = node->rb_right;
while (node->rb_left)
node=node->rb_left;
}
else {
struct rb_node *last;
do {
parent = rb_parent(node);
ret = func(node, user);
if (ret)
break;
last = node;
node = parent;
} while(parent && last == parent->rb_right);
}
}
return ret;
}
static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
{
for (;;) {
if (node->rb_left)
node = node->rb_left;
else if (node->rb_right)
node = node->rb_right;
else
return (struct rb_node *)node;
}
}
struct rb_node *rb_next_postorder(const struct rb_node *node)
{
const struct rb_node *parent;
if (!node)
return NULL;
parent = rb_parent(node);
if (parent && node == parent->rb_left && parent->rb_right)
return rb_left_deepest_node(parent->rb_right);
return (struct rb_node *)parent;
}
struct rb_node *rb_first_postorder(const struct rb_root *root)
{
if (!root->rb_node)
return NULL;
return rb_left_deepest_node(root->rb_node);
}

94
rbtree.h Normal file
View File

@ -0,0 +1,94 @@
/*
* Red Black Trees
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the linux kernel source
* Copyright (C) 1999 Andrea Arcangeli <andrea@suse.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_RBTREE_H
#define _INC_RBTREE_H
#include <stdlib.h>
#include "common.h"
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
struct rb_root
{
struct rb_node *rb_node;
};
#define RB_ROOT (struct rb_root) { NULL, }
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
/* Postorder iteration - always visit the parent after its children */
struct rb_node *rb_first_postorder(const struct rb_root *);
struct rb_node *rb_next_postorder(const struct rb_node *);
/* Find logical next and previous nodes in a tree */
struct rb_node *rb_next(const struct rb_node *);
struct rb_node *rb_prev(const struct rb_node *);
struct rb_node *rb_first(const struct rb_root *);
struct rb_node *rb_last(const struct rb_root *);
static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,
struct rb_node **rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
int rb_iterate(const struct rb_root *root, int (*func)(struct rb_node *,void *data), void *user);
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define rb_entry_safe(ptr, type, member) \
({ typeof(ptr) ____ptr = (ptr); \
____ptr ? rb_entry(____ptr, type, member) : NULL; \
})
/**
* rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of
* given type safe against removal of rb_node entry
*
* @pos: the 'type *' to use as a loop cursor.
* @n: another 'type *' to use as temporary storage
* @root: 'rb_root *' of the rbtree.
* @field: the name of the rb_node field within 'type'.
*/
#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
typeof(*pos), field); 1; }); \
pos = n)
#endif

498
report.c Normal file
View File

@ -0,0 +1,498 @@
/*
* report events to client
*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include "backend.h"
#include "backtrace.h"
#include "common.h"
#include "debug.h"
#include "library.h"
#include "memtrace.h"
#include "options.h"
#include "report.h"
#include "server.h"
#include "task.h"
#include "trace.h"
static int report_alloc64(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth)
{
int i = 0;
struct mt_alloc_payload_64 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint64_t));
alloc->ptr = (uint64_t)ptr;
alloc->size = (uint64_t)size;
if (depth && backtrace_init_unwind(task) >= 0) {
do {
alloc->data[i] = (uint64_t)backtrace_get_ip(task);
if (!alloc->data[i])
break;
++i;
if (backtrace_step(task) < 0)
break;
} while(i < depth);
}
skip_breakpoint(task, task->event.e_un.breakpoint);
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint64_t));
}
static int report_alloc32(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth)
{
int i = 0;
struct mt_alloc_payload_32 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint32_t));
alloc->ptr = (uint32_t)ptr;
alloc->size = (uint32_t)size;
if (depth && backtrace_init_unwind(task) >= 0) {
do {
alloc->data[i] = (uint32_t)backtrace_get_ip(task);
if (!alloc->data[i])
break;
++i;
if (backtrace_step(task) < 0)
break;
} while(i < depth);
}
skip_breakpoint(task, task->event.e_un.breakpoint);
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint32_t));
}
static int report_alloc(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth)
{
if (!ptr)
return 0;
if (!server_connected())
return -1;
debug(DEBUG_FUNCTION, "%d [%d]: %#lx %lu", op, task->pid, ptr, size);
if (task->is_64bit)
return report_alloc64(task, op, ptr, size, depth);
else
return report_alloc32(task, op, ptr, size, depth);
}
static int _null(struct task *task, struct library_symbol *libsym)
{
return 0;
}
static int _report_malloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 0);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_MALLOC, ret, len, options.bt_depth);
}
static int report_free(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long addr = fetch_param(task, 0);
return report_alloc(task, MT_FREE, addr, 0, 0);
}
static int _report_realloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long addr = fetch_param(task, 0);
unsigned long len = fetch_param(task, 1);
unsigned long ret = fetch_retval(task);
if (ret)
return report_alloc(task, MT_REALLOC, ret, len, options.bt_depth);
else
return report_alloc(task, MT_REALLOC_FAILED, addr, 1, options.bt_depth);
}
static int report_realloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long addr = fetch_param(task, 0);
unsigned long len = fetch_param(task, 1);
return report_alloc(task, MT_REALLOC_ENTER, addr, len, options.bt_depth);
}
static int _report_calloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 0) * fetch_param(task, 1);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_MALLOC, ret, len, options.bt_depth);
}
static inline unsigned long roundup_mask(unsigned long val, unsigned long mask)
{
return (val + mask) & ~mask;
}
static int _report_mmap(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long ret = fetch_retval(task);
if ((void *)ret == MAP_FAILED)
return 0;
unsigned long len = fetch_param(task, 1);
len = roundup_mask(len, PAGE_SIZE -1);
return report_alloc(task, MT_MMAP, ret, len, options.bt_depth);
}
static int _report_mmap64(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long ret = fetch_retval(task);
if ((void *)ret == MAP_FAILED)
return 0;
union {
uint64_t l;
struct {
uint32_t v1;
uint32_t v2;
} v;
} len;
len.l = fetch_param(task, 1);
if (!task->is_64bit) {
len.v.v1 = fetch_param(task, 1);
len.v.v2 = fetch_param(task, 2);
}
else
len.l = fetch_param(task, 1);
ret &= ~(PAGE_SIZE -1);
len.l = roundup_mask(len.l, PAGE_SIZE -1);
return report_alloc(task, MT_MMAP64, ret, len.l, options.bt_depth);
}
static int report_munmap(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long addr = fetch_param(task, 0);
unsigned long len = fetch_param(task, 1);
addr &= ~(PAGE_SIZE -1);
len = roundup_mask(len, PAGE_SIZE -1);
return report_alloc(task, MT_MUNMAP, addr, len, 0);
}
static int _report_memalign(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 1);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_MEMALIGN, ret, len, options.bt_depth);
}
static int _report_posix_memalign(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long ret = fetch_retval(task);
if (ret)
return 0;
unsigned long len = fetch_param(task, 2);
unsigned long ptr = fetch_param(task, 0);
unsigned long new_ptr;
if (task->is_64bit)
copy_from_proc(task, ARCH_ADDR_T(ptr), &new_ptr, sizeof(new_ptr));
else {
uint32_t tmp;
copy_from_proc(task, ARCH_ADDR_T(ptr), &tmp, sizeof(tmp));
new_ptr = tmp;
}
return report_alloc(task, MT_POSIX_MEMALIGN, new_ptr, len, options.bt_depth);
}
static int _report_aligned_alloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 1);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_ALIGNED_ALLOC, ret, len, options.bt_depth);
}
static int _report_valloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 0);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_VALLOC, ret, len, options.bt_depth);
}
static int _report_pvalloc(struct task *task, struct library_symbol *libsym)
{
if (!server_connected())
return -1;
unsigned long len = fetch_param(task, 0);
unsigned long ret = fetch_retval(task);
return report_alloc(task, MT_PVALLOC, ret, len, options.bt_depth);
}
#if 1
static int mt_test(struct task *task, struct library_symbol *libsym)
{
unsigned int i;
for(i = 0; i < 13; ++i) {
unsigned long val = fetch_param(task, i);
fprintf(stderr, "%s:%d %d\n", __FUNCTION__, __LINE__, (int32_t)val);
}
return 0;
}
#endif
static const struct function flist[] = {
{ "malloc", 2, NULL, _report_malloc },
{ "free", 3, report_free, NULL },
{ "realloc", 4, report_realloc, _report_realloc },
{ "calloc", 5, NULL, _report_calloc },
{ "posix_memalign", 6, NULL, _report_posix_memalign },
{ "mmap", 7, NULL, _report_mmap },
{ "mmap64", 8, NULL, _report_mmap64 },
{ "munmap", 9, report_munmap, _null },
{ "memalign", 10, NULL, _report_memalign },
{ "aligned_alloc", 11, NULL, _report_aligned_alloc },
{ "valloc", 12, NULL, _report_valloc },
{ "pvalloc", 13, NULL, _report_pvalloc },
#if 0
{ "cfree", 14, report_free, NULL },
#endif
#if 1
{ "mt_test", 15, mt_test, NULL },
#endif
};
const struct function *flist_matches_symbol(const char *sym_name)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(flist); ++i) {
if (!strcmp(sym_name, flist[i].name))
return &flist[i];
}
return 0;
}
int _report_map(struct task *task, struct library *lib, enum mt_operation op)
{
size_t len = strlen(lib->filename) + 1;
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
payload->addr = lib->load_addr;
payload->offset = lib->load_offset;
payload->size = lib->load_size;
memcpy(payload->filename, lib->filename, len);
return server_send_msg(op, task->pid, 0, payload, sizeof(struct mt_map_payload) + len);
}
int report_add_map(struct task *task, struct library *lib)
{
if (!server_connected())
return -1;
return _report_map(task, lib, MT_ADD_MAP);
}
int report_del_map(struct task *task, struct library *lib)
{
if (!server_connected())
return -1;
return _report_map(task, lib, MT_DEL_MAP);
}
int report_info(int do_trace)
{
struct memtrace_info mt_info;
if (!server_connected())
return -1;
mt_info.version = MEMTRACE_SI_VERSION;
mt_info.mode = 0;
mt_info.do_trace = do_trace ? 1 : 0;
mt_info.stack_depth = options.bt_depth;
if (options.verbose)
mt_info.mode |= MEMTRACE_SI_VERBOSE;
if (options.follow_exec)
mt_info.mode |= MEMTRACE_SI_EXEC;
if (options.follow)
mt_info.mode |= MEMTRACE_SI_FORK;
return server_send_msg(MT_INFO, 0, 0, &mt_info, sizeof(mt_info));
}
int report_scan(pid_t pid, const void *data, unsigned int data_len)
{
if (!server_connected())
return -1;
return server_send_msg(MT_SCAN, pid, 0, data, data_len);
}
int report_attach(struct task *task)
{
if (!server_connected())
return -1;
return server_send_msg(task->is_64bit ? MT_ATTACH64 : MT_ATTACH, task->pid, 0, NULL, 0);
}
int report_fork(struct task *task, pid_t ppid)
{
struct mt_pid_payload fork_pid = { .pid = ppid };
if (!server_connected())
return -1;
return server_send_msg(MT_FORK, task->pid, 0, &fork_pid, sizeof(fork_pid));
}
int report_exit(struct task *task)
{
if (!server_connected())
return -1;
return server_send_msg(MT_EXIT, task->pid, 0, NULL, 0);
}
int report_about_exit(struct task *task)
{
if (!server_connected())
return -1;
return server_send_msg(MT_ABOUT_EXIT, task->pid, 0, NULL, 0);
}
int report_nofollow(struct task *task)
{
if (!server_connected())
return -1;
return server_send_msg(MT_NOFOLLOW, task->pid, 0, NULL, 0);
}
int report_detach(struct task *task)
{
if (!server_connected())
return -1;
return server_send_msg(MT_DETACH, task->pid, 0, NULL, 0);
}
int report_disconnect(void)
{
if (!server_connected())
return -1;
return server_send_msg(MT_DISCONNECT, 0, 0, NULL, 0);
}
static void report_process(struct task *leader)
{
struct list_head *it;
report_attach(leader);
list_for_each(it, &leader->libraries_list) {
struct library *lib = container_of(it, struct library, list);
report_add_map(leader, lib);
}
}
int report_processes(void)
{
if (!server_connected())
return -1;
each_process(&report_process);
return 0;
}

52
report.h Normal file
View File

@ -0,0 +1,52 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_REPORT_H
#define _INC_REPORT_H
#include "forward.h"
#define REPORT_ENTER 1
#define REPORT_LEAVE 2
struct function {
const char *name;
unsigned int hw_bp_min;
int (*report_in)(struct task *task, struct library_symbol *libsym);
int (*report_out)(struct task *task, struct library_symbol *libsym);
};
const struct function *flist_matches_symbol(const char *sym_name);
int report_add_map(struct task *task, struct library *lib);
int report_del_map(struct task *task, struct library *lib);
int report_info(int do_trace);
int report_scan(pid_t pid, const void *data, unsigned int data_len);
int report_attach(struct task *task);
int report_fork(struct task *task, pid_t pid);
int report_exit(struct task *task);
int report_about_exit(struct task *task);
int report_nofollow(struct task *task);
int report_disconnect(void);
int report_processes(void);
int report_detach(struct task *task);
#endif

353
server.c Normal file
View File

@ -0,0 +1,353 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <semaphore.h>
#include "backend.h"
#include "breakpoint.h"
#include "common.h"
#include "ioevent.h"
#include "main.h"
#include "memtrace.h"
#include "options.h"
#include "server.h"
#include "task.h"
#include "thread.h"
#include "trace.h"
#define MODE_NONE 0
#define MODE_COMMAND 1
#define MODE_ACCEPTED 2
#define MODE_DISCONNECT 3
static unsigned int server_mode = MODE_NONE;
static int listen_fd = -1;
static int server_fd = -1;
static struct thread *thread;
static int command_pending;
static sem_t sem;
static void stop_trace(struct task *leader)
{
struct list_head *it;
breakpoint_disable_all_nonlocked(leader);
list_for_each(it, &leader->task_list) {
struct task *task = container_of(it, struct task, task_list);
task->breakpoint = NULL;
}
leader->breakpoint = NULL;
}
static void start_trace(struct task *leader)
{
breakpoint_enable_all_nonlocked(leader);
}
int server_connected(void)
{
return server_fd != -1;
}
static void server_close(void)
{
if (server_connected()) {
shutdown(server_fd, SHUT_RDWR);
close(server_fd);
server_fd = -1;
each_process(&stop_trace);
}
}
int server_poll(void)
{
int ret = 0;
if (command_pending) {
ret = server_handle_command();
if (options.server)
ret = 0;
command_pending = 0;
sem_post(&sem);
}
return ret;
}
static void request_server(void)
{
command_pending = 1;
wait_event_wakeup();
thread_enable_cancel();
TEMP_FAILURE_RETRY(sem_wait(&sem));
thread_disable_cancel();
}
int server_handle_command(void)
{
int ret;
struct mt_msg cmd;
void *payload = NULL;
struct task *task;
unsigned int mode = server_mode;
server_mode = MODE_NONE;
switch(mode) {
case MODE_ACCEPTED:
report_info(1);
report_processes();
each_process(&start_trace);
return 0;
case MODE_DISCONNECT:
server_close();
return -1;
case MODE_COMMAND:
break;
default:
break;
}
if (!server_connected())
return -1;
ret = safe_read(server_fd, &cmd, sizeof(cmd));
if (ret != sizeof(cmd)) {
if (ret > 0) {
if (!options.verbose)
fprintf(stderr, "cmd read wrong size %d\n", ret);
}
server_close();
return options.server ? 0: -1;
}
if (cmd.payload_len) {
payload = malloc(cmd.payload_len);
if (safe_read(server_fd, payload, cmd.payload_len) != (ssize_t)cmd.payload_len) {
fprintf(stderr, "can't read payload_len (%u)\n", cmd.payload_len);
goto finish;
}
}
if (!cmd.pid) {
server_close();
goto finish;
}
task = pid2task(cmd.pid);
if (!task)
goto finish;
if (task != task->leader)
goto finish;
switch(cmd.operation) {
case MT_SCAN:
{
unsigned long data_len = 0;
void *data = NULL;
stop_threads(task);
data = mem_scan(task, &cmd, payload, &data_len);
report_scan(cmd.pid, data, data_len);
break;
}
case MT_START:
start_trace(task);
break;
case MT_STOP:
stop_trace(task);
break;
case MT_DETACH:
detach_proc(task);
break;
case MT_EXIT:
remove_proc(task);
break;
default:
break;
}
finish:
if (payload)
free(payload);
return cmd.operation;
}
static void *server_listen_thread(void *ptr)
{
int ret;
for(;;) {
if (!server_connected()) {
thread_enable_cancel();
server_fd = TEMP_FAILURE_RETRY(accept(listen_fd, NULL, 0));
thread_disable_cancel();
if (server_fd < 0)
fatal("accept (%s)", strerror(errno));
server_mode = MODE_ACCEPTED;
}
else {
thread_enable_cancel();
ret = ioevent_wait_input(server_fd, -1);
thread_disable_cancel();
if (ret != 1)
server_mode = MODE_DISCONNECT;
else
server_mode = MODE_COMMAND;
}
request_server();
}
return NULL;
}
int server_start(void)
{
thread = thread_new();
if (!thread)
return -1;
listen_fd = bind_to(options.listen, options.port);
if (listen_fd < 0)
fatal("colud not bind socket: %s:%s", options.listen, options.port);
if (listen(listen_fd, 1) < 0)
fatal("listen (%s)", strerror(errno));
if (options.wait) {
fprintf(stderr, "waiting for client connection...\n");
server_fd = TEMP_FAILURE_RETRY(accept(listen_fd, NULL, 0));
if (server_fd < 0)
fatal("accept (%s)", strerror(errno));
report_info(1);
report_processes();
each_process(&start_trace);
}
else {
each_process(&stop_trace);
}
sem_init(&sem, 0, 1);
if (thread_start(thread, server_listen_thread, NULL))
fatal("could not start thread (%s)", strerror(errno));
return 0;
}
static void *server_pair_thread(void *ptr)
{
int ret;
for(;;) {
if (!server_connected())
break;
thread_enable_cancel();
ret = ioevent_wait_input(server_fd, -1);
thread_disable_cancel();
if (ret != 1)
server_mode = MODE_DISCONNECT;
else
server_mode = MODE_COMMAND;
request_server();
}
return NULL;
}
int server_start_pair(void)
{
int sv[2];
thread = thread_new();
if (!thread)
return -1;
if (create_socket_pair(sv) == -1)
return -1;
server_fd = sv[0];
sem_init(&sem, 0, 1);
if (thread_start(thread, server_pair_thread, NULL)) {
thread_remove(thread);
server_close();
return -1;
}
report_processes();
return sv[1];
}
int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len)
{
return sock_send_msg(server_fd, op, pid, tid, payload, payload_len);
}
int server_stop(void)
{
thread_cancel(thread);
if (thread)
thread_join(thread);
server_close();
if (listen_fd != -1) {
if (is_named(options.listen))
unlink(options.listen);
close(listen_fd);
listen_fd = -1;
}
return 0;
}

37
server.h Normal file
View File

@ -0,0 +1,37 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_SERVER_H
#define _INC_SERVER_H
#include "forward.h"
#include "socket.h"
int server_start(void);
int server_start_pair(void);
int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len);
int server_handle_command(void);
int server_connected(void);
int server_stop(void);
int server_poll(void);
#endif

29
sysdeps/Makefile.am Normal file
View File

@ -0,0 +1,29 @@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
DIST_SUBDIRS = \
linux-gnu
SUBDIRS = \
$(HOST_OS)
noinst_HEADERS = \
sysdep.h
MAINTAINERCLEANFILES = \
Makefile.in

656
sysdeps/Makefile.in Normal file
View File

@ -0,0 +1,656 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = sysdeps
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
$(top_srcdir)/config/m4/ltoptions.m4 \
$(top_srcdir)/config/m4/ltsugar.m4 \
$(top_srcdir)/config/m4/ltversion.m4 \
$(top_srcdir)/config/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HOST_CPU = @HOST_CPU@
HOST_OS = @HOST_OS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
DIST_SUBDIRS = \
linux-gnu
SUBDIRS = \
$(HOST_OS)
noinst_HEADERS = \
sysdep.h
MAINTAINERCLEANFILES = \
Makefile.in
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign sysdeps/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile $(HEADERS)
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-libtool cscopelist-am ctags \
ctags-am distclean distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,44 @@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
DIST_SUBDIRS = x86 ppc arm
SUBDIRS = \
$(HOST_CPU)
noinst_LTLIBRARIES = \
../libos.la
___libos_la_SOURCES = \
backtrace.c \
ioevent.c \
trace.c \
os.c \
proc.c \
socket.c \
thread.c
___libos_la_LIBADD = \
libcpu.la
noinst_HEADERS = ioevent.h os.h socket.h
EXTRA_DIST =
MAINTAINERCLEANFILES = \
Makefile.in

View File

@ -0,0 +1,764 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# This file is part of mtrace.
# Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = sysdeps/linux-gnu
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
$(top_srcdir)/config/m4/ltoptions.m4 \
$(top_srcdir)/config/m4/ltsugar.m4 \
$(top_srcdir)/config/m4/ltversion.m4 \
$(top_srcdir)/config/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
___libos_la_DEPENDENCIES = libcpu.la
am____libos_la_OBJECTS = backtrace.lo ioevent.lo trace.lo os.lo \
proc.lo socket.lo thread.lo
___libos_la_OBJECTS = $(am____libos_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
am__dirstamp = $(am__leading_dot)dirstamp
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(___libos_la_SOURCES)
DIST_SOURCES = $(___libos_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/config/autoconf/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HOST_CPU = @HOST_CPU@
HOST_OS = @HOST_OS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
DIST_SUBDIRS = x86 ppc arm
SUBDIRS = \
$(HOST_CPU)
noinst_LTLIBRARIES = \
../libos.la
___libos_la_SOURCES = \
backtrace.c \
ioevent.c \
trace.c \
os.c \
proc.c \
socket.c \
thread.c
___libos_la_LIBADD = \
libcpu.la
noinst_HEADERS = ioevent.h os.h socket.h
EXTRA_DIST =
MAINTAINERCLEANFILES = \
Makefile.in
all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign sysdeps/linux-gnu/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
../$(am__dirstamp):
@$(MKDIR_P) ..
@: > ../$(am__dirstamp)
../libos.la: $(___libos_la_OBJECTS) $(___libos_la_DEPENDENCIES) $(EXTRA____libos_la_DEPENDENCIES) ../$(am__dirstamp)
$(AM_V_CCLD)$(LINK) $(___libos_la_OBJECTS) $(___libos_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioevent.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf ../.libs ../_libs
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f ../$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-recursive
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic clean-libtool \
clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,31 @@
# This file is part of mtrace.
# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
noinst_LTLIBRARIES = \
../libcpu.la
___libcpu_la_SOURCES = \
dwarf-arm.c \
regs.c \
arch.c
noinst_HEADERS = \
arch.h
MAINTAINERCLEANFILES = \
Makefile.in

View File

@ -0,0 +1,634 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# This file is part of mtrace.
# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = sysdeps/linux-gnu/arm
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
$(top_srcdir)/config/m4/ltoptions.m4 \
$(top_srcdir)/config/m4/ltsugar.m4 \
$(top_srcdir)/config/m4/ltversion.m4 \
$(top_srcdir)/config/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
___libcpu_la_LIBADD =
am____libcpu_la_OBJECTS = dwarf-arm.lo regs.lo arch.lo
___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
am__dirstamp = $(am__leading_dot)dirstamp
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(___libcpu_la_SOURCES)
DIST_SOURCES = $(___libcpu_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/config/autoconf/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HOST_CPU = @HOST_CPU@
HOST_OS = @HOST_OS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = \
../libcpu.la
___libcpu_la_SOURCES = \
dwarf-arm.c \
regs.c \
arch.c
noinst_HEADERS = \
arch.h
MAINTAINERCLEANFILES = \
Makefile.in
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/arm/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign sysdeps/linux-gnu/arm/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
../$(am__dirstamp):
@$(MKDIR_P) ..
@: > ../$(am__dirstamp)
../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) $(EXTRA____libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
$(AM_V_CCLD)$(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf-arm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf ../.libs ../_libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f ../$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,731 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2010,2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "arch.h"
#include "backend.h"
#include "breakpoint.h"
#include "common.h"
#include "mtelf.h"
#include "task.h"
#define COND_ALWAYS 0xe
#define COND_NV 0xf
#define FLAG_C 0x20000000
#define SUBMASK(x) ((1 << ((x) + 1)) - 1)
#define BIT(obj, st) (((obj) >> (st)) & 1)
#define BITS(obj, st, fn) (((obj) >> (st)) & SUBMASK((fn) - (st)))
#define SBITS(obj, st, fn) (BITS(obj, st, fn) | (BIT(obj, fn) * ~ SUBMASK((fn) - (st))))
#define ARM_REG_SP 13
#define ARM_REG_LR 14
#define ARM_REG_PC 15
#define ARM_REG_CPSR 16
int is_64bit(struct mt_elf *mte)
{
return 0;
}
static inline int bitcount(unsigned int n)
{
return __builtin_popcount(n);
}
static inline int proc_read_8(struct task *task, uint32_t addr, uint8_t *dst)
{
return copy_from_proc(task, addr, dst, sizeof(*dst));
}
static inline int proc_read_16(struct task *task, uint32_t addr, uint16_t *dst)
{
return copy_from_proc(task, addr, dst, sizeof(*dst));
}
static inline int proc_read_32(struct task *task, uint32_t addr, uint32_t *dst)
{
return copy_from_proc(task, addr, dst, sizeof(*dst));
}
static int arm_get_register(struct task *task, unsigned int reg, uint32_t *lp)
{
if (ARRAY_SIZE(task->context.regs.uregs) >= reg) {
long l;
errno = 0;
l = ptrace(PTRACE_PEEKUSER, task->pid, (void *)(reg * 4), 0);
if (l == -1 && errno != 0)
return -1;
*lp = (uint32_t)l;
}
else
*lp = fetch_reg(task, reg * 4);
return 0;
}
static int arm_get_register_offpc(struct task *task, unsigned int reg, uint32_t *lp)
{
if (arm_get_register(task, reg, lp) < 0)
return -1;
if (reg == ARM_REG_PC)
*lp += 8;
return 0;
}
static int arm_get_shifted_register(struct task *task, uint32_t inst, unsigned int carry, uint32_t pc, uint32_t *lp)
{
unsigned int rm = BITS(inst, 0, 3);
unsigned int shifttype = BITS(inst, 5, 6);
uint32_t shift;
uint32_t res;
if (BIT(inst, 4)) {
if (arm_get_register_offpc(task, BITS(inst, 8, 11), &shift) < 0)
return -1;
shift &= 0xff;
} else
shift = BITS(inst, 7, 11);
if (rm == ARM_REG_PC)
res = pc + (BIT(inst, 4) ? 12 : 8);
else {
if (arm_get_register(task, rm, &res) < 0)
return -1;
}
switch(shifttype) {
case 0: /* LSL */
res = shift >= 32 ? 0 : res << shift;
break;
case 1: /* LSR */
res = shift >= 32 ? 0 : res >> shift;
break;
case 2: /* ASR */
if (shift >= 32)
shift = 31;
res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift);
break;
case 3: /* ROR/RRX */
shift &= 31;
if (shift == 0)
res = (res >> 1) | (carry ? 0x80000000L : 0);
else
res = (res >> shift) | (res << (32 - shift));
break;
}
*lp = res & 0xffffffff;
return 0;
}
static uint32_t arm_branch_dest(uint32_t pc, const uint32_t insn)
{
/* Bits 0-23 are signed immediate value. */
return pc + ((((insn & 0xffffff) ^ 0x800000) - 0x800000) << 2) + 8;
}
static int arm_get_next_pcs(struct task *task, const uint32_t pc, uint32_t next_pcs[2])
{
uint32_t this_instr;
uint32_t next;
next_pcs[0] = 0;
next_pcs[1] = 0;
if (proc_read_32(task, pc, &this_instr) < 0)
return -1;
/* In theory, we sometimes don't even need to add any
* breakpoints at all. If the conditional bits of the
* instruction indicate that it should not be taken, then we
* can just skip it altogether without bothering. We could
* also emulate the instruction under the breakpoint.
*
* Here, we make it as simple as possible (though We Accept
* Patches). */
int nr = 0;
/* ARM can branch either relatively by using a branch
* instruction, or absolutely, by doing arbitrary arithmetic
* with PC as the destination. */
const unsigned int cond = BITS(this_instr, 28, 31);
const unsigned int opcode = BITS(this_instr, 24, 27);
if (cond == COND_NV) {
if (opcode == 0x0a || opcode == 0x0b) {
uint32_t addr;
/* Branch with Link and change to Thumb. */
addr = arm_branch_dest(pc, this_instr) | (((this_instr >> 24) & 0x1) << 1);
next_pcs[nr++] = addr | 1; /* thumb addr */
}
}
else {
uint32_t status;
if (arm_get_register(task, ARM_REG_CPSR, &status) < 0)
return -1;
unsigned int c = status & FLAG_C ? 1 : 0;
switch(opcode) {
uint32_t operand1, operand2;
case 0x0:
case 0x1: /* data processing */
case 0x2:
case 0x3:
if (BITS(this_instr, 12, 15) != ARM_REG_PC)
break;
if (BITS(this_instr, 22, 25) == 0 && BITS(this_instr, 4, 7) == 9) /* multiply */
goto invalid;
/* BX <reg>, BLX <reg> */
if (BITS(this_instr, 4, 27) == 0x12fff1 || BITS(this_instr, 4, 27) == 0x12fff3) {
uint32_t tmp;
if (arm_get_register_offpc(task, BITS(this_instr, 0, 3), &tmp) < 0)
return -1;
next_pcs[nr++] = tmp;
return 0;
}
/* Multiply into PC. */
if (arm_get_register_offpc(task, BITS(this_instr, 16, 19), &operand1) < 0)
return -1;
if (BIT(this_instr, 25)) {
uint32_t immval = BITS(this_instr, 0, 7);
uint32_t rotate = 2 * BITS(this_instr, 8, 11);
operand2 = ((immval >> rotate) | (immval << (32 - rotate))) & 0xffffffff;
} else {
/* operand 2 is a shifted register. */
if (arm_get_shifted_register(task, this_instr, c, pc, &operand2) < 0)
return -1;
}
uint32_t result;
switch(BITS(this_instr, 21, 24)) {
case 0x0: /*and */
result = operand1 & operand2;
break;
case 0x1: /*eor */
result = operand1 ^ operand2;
break;
case 0x2: /*sub */
result = operand1 - operand2;
break;
case 0x3: /*rsb */
result = operand2 - operand1;
break;
case 0x4: /*add */
result = operand1 + operand2;
break;
case 0x5: /*adc */
result = operand1 + operand2 + c;
break;
case 0x6: /*sbc */
result = operand1 - operand2 + c;
break;
case 0x7: /*rsc */
result = operand2 - operand1 + c;
break;
case 0x8:
case 0x9:
case 0xa:
case 0xb: /* tst, teq, cmp, cmn */
/* Only take the default branch. */
result = 0;
break;
case 0xc: /*orr */
result = operand1 | operand2;
break;
case 0xd: /*mov */
/* Always step into a function. */
result = operand2;
break;
case 0xe: /*bic */
result = operand1 & ~operand2;
break;
case 0xf: /*mvn */
result = ~operand2;
break;
default:
result = 0;
break;
}
next_pcs[nr++] = result;
break;
case 0x4:
case 0x5: /* data transfer */
case 0x6:
case 0x7:
/* Ignore if insn isn't load or Rn not PC. */
if (!BIT(this_instr, 20) || BITS(this_instr, 12, 15) != ARM_REG_PC)
break;
if (BIT(this_instr, 22))
goto invalid;
/* byte write to PC */
uint32_t base;
if (arm_get_register_offpc(task, BITS(this_instr, 16, 19), &base) < 0)
return -1;
if (BIT(this_instr, 24)) {
/* pre-indexed */
uint32_t offset;
if (BIT(this_instr, 25)) {
if (arm_get_shifted_register(task, this_instr, c, pc, &offset) < 0)
return -1;
} else {
offset = BITS(this_instr, 0, 11);
}
if (BIT(this_instr, 23))
base += offset;
else
base -= offset;
}
if (proc_read_32(task, base, &next) < 0)
return -1;
next_pcs[nr++] = next;
break;
case 0x8:
case 0x9: /* block transfer */
if (!BIT(this_instr, 20))
break;
/* LDM */
if (BIT(this_instr, 15)) {
/* Loading pc. */
uint32_t rn_val;
int offset = 0;
if (arm_get_register(task, BITS(this_instr, 16, 19), &rn_val) < 0)
return -1;
int pre = BIT(this_instr, 24);
if (BIT(this_instr, 23)) {
/* Bit U = up. */
offset = bitcount(BITS(this_instr, 0, 14)) * 4;
if (pre)
offset += 4;
}
else {
if (pre)
offset = -4;
}
if (proc_read_32(task, rn_val + offset, &next) < 0)
return -1;
next_pcs[nr++] = next;
}
break;
case 0xb: /* branch & link */
case 0xa: /* branch */
next_pcs[nr++] = arm_branch_dest(pc, this_instr);
break;
case 0xc:
case 0xd:
case 0xe: /* coproc ops */
case 0xf: /* SWI */
break;
}
}
finish:
/* Otherwise take the next instruction. */
if (!nr || cond != COND_ALWAYS)
next_pcs[nr++] = pc + 4;
return 0;
invalid:
fprintf(stderr, "Invalid update to pc in instruction.\n");
goto finish;
}
/* Return the size in bytes of the complete Thumb instruction whose
* first halfword is INST1. */
static int thumb_insn_size (unsigned short inst1)
{
if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
return 4;
else
return 2;
}
static int thumb_get_next_pcs(struct task *task, const uint32_t pc, uint32_t next_pcs[2])
{
uint16_t inst1;
uint32_t next;
next_pcs[0] = 0;
next_pcs[1] = 0;
if (proc_read_16(task, pc, &inst1) < 0)
return -1;
int nr = 0;
/* We currently ignore Thumb-2 conditional execution support
* (the IT instruction). No branches are allowed in IT block,
* and it's not legal to jump in the middle of it, so unless
* we need to singlestep through large swaths of code, which
* we currently don't, we can ignore them. */
if ((inst1 & 0xff00) == 0xbd00) { /* pop {rlist, pc} */
/* Fetch the saved PC from the stack. It's stored above all of the other registers. */
uint32_t sp;
if (arm_get_register(task, ARM_REG_SP, &sp) < 0 || proc_read_32(task, sp + bitcount(BITS(inst1, 0, 7)) * 4, &next) < 0)
return -1;
next_pcs[nr++] = next;
}
else
if ((inst1 & 0xf000) == 0xd000) { /* conditional branch */
const unsigned int cond = BITS(inst1, 8, 11);
if (cond != 0x0f) { /* SWI */
next_pcs[nr++] = pc + (SBITS(inst1, 0, 7) << 1);
if (cond == COND_ALWAYS)
return 0;
}
}
else
if ((inst1 & 0xf800) == 0xe000) { /* unconditional branch */
next_pcs[nr++] = pc + (SBITS(inst1, 0, 10) << 1);
}
else
if (thumb_insn_size(inst1) == 4) { /* 32-bit instruction */
unsigned short inst2;
if (proc_read_16(task, pc + 2, &inst2) < 0)
return -1;
if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000) {
/* Branches and miscellaneous control instructions. */
if ((inst2 & 0x1000) != 0 || (inst2 & 0xd001) == 0xc000) {
/* B, BL, BLX. */
const int imm1 = SBITS(inst1, 0, 10);
const unsigned int imm2 = BITS(inst2, 0, 10);
const unsigned int j1 = BIT(inst2, 13);
const unsigned int j2 = BIT(inst2, 11);
int32_t offset = (imm1 << 12) + (imm2 << 1);
offset ^= ((!j2) << 22) | ((!j1) << 23);
next = pc + offset;
/* For BLX make sure to clear the low bits. */
if (BIT(inst2, 12) == 0)
next = next & 0xfffffffc;
next_pcs[nr++] = next;
return 0;
}
else
if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00) {
/* SUBS PC, LR, #imm8. */
if (arm_get_register(task, ARM_REG_LR, &next) < 0)
return -1;
next -= inst2 & 0x00ff;
next_pcs[nr++] = next;
return 0;
}
else
if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380) {
/* Conditional branch. */
const int sign = SBITS(inst1, 10, 10);
const unsigned int imm1 = BITS(inst1, 0, 5);
const unsigned int imm2 = BITS(inst2, 0, 10);
const unsigned int j1 = BIT(inst2, 13);
const unsigned int j2 = BIT(inst2, 11);
int32_t offset = (sign << 20) + (j2 << 19) + (j1 << 18);
offset += (imm1 << 12) + (imm2 << 1);
next_pcs[nr++] = pc + offset;
if (BITS(inst1, 6, 9) == COND_ALWAYS)
return 0;
}
}
else
if ((inst1 & 0xfe50) == 0xe810) {
int load_pc = 1;
int offset;
if (BIT(inst1, 7) && !BIT(inst1, 8)) {
/* LDMIA or POP */
if (!BIT(inst2, 15))
load_pc = 0;
offset = bitcount(inst2) * 4 - 4;
}
else
if (!BIT(inst1, 7) && BIT(inst1, 8)) {
/* LDMDB */
if (!BIT(inst2, 15))
load_pc = 0;
offset = -4;
}
else
if (BIT(inst1, 7) && BIT(inst1, 8)) {
/* RFEIA */
offset = 0;
}
else
if (!BIT(inst1, 7) && !BIT(inst1, 8)) {
/* RFEDB */
offset = -8;
} else {
load_pc = 0;
}
if (load_pc) {
uint32_t addr;
if (arm_get_register(task, BITS(inst1, 0, 3), &addr) < 0)
return -1;
addr = addr + offset;
if (proc_read_32(task, addr, &next) < 0)
return -1;
next_pcs[nr++] = next;
}
}
else
if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00) {
/* MOV PC or MOVS PC. */
if (arm_get_register(task, BITS(inst2, 0, 3), &next) < 0)
return -1;
next_pcs[nr++] = next;
}
else
if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000) {
/* LDR PC. */
const unsigned int rn = BITS(inst1, 0, 3);
uint32_t base;
if (arm_get_register(task, rn, &base) < 0)
return -1;
int load_pc = 1;
if (rn == ARM_REG_PC) {
base = (base + 4) & ~0x3;
if (BIT(inst1, 7))
base += BITS(inst2, 0, 11);
else
base -= BITS(inst2, 0, 11);
}
else
if (BIT(inst1, 7)) {
base += BITS(inst2, 0, 11);
}
else
if (BIT(inst2, 11)) {
if (BIT(inst2, 10)) {
if (BIT(inst2, 9))
base += BITS(inst2, 0, 7);
else
base -= BITS(inst2, 0, 7);
}
}
else
if ((inst2 & 0x0fc0) == 0x0000) {
uint32_t v;
if (arm_get_register(task, BITS(inst2, 0, 3), &v) < 0)
return -1;
base += v << BITS(inst2, 4, 5);
} else {
/* Reserved. */
load_pc = 0;
}
if (load_pc) {
if (proc_read_32(task, base, &next) < 0)
return -1;
next_pcs[nr++] = next;
}
}
else
if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000) {
/* TBB. */
uint32_t table;
uint32_t offset;
uint8_t length;
const unsigned int tbl_reg = BITS(inst1, 0, 3);
if (tbl_reg == ARM_REG_PC)
/* Regcache copy of PC isn't right yet. */
table = pc + 4;
else {
if (arm_get_register(task, tbl_reg, &table) < 0)
return -1;
}
if (arm_get_register(task, BITS(inst2, 0, 3), &offset) < 0)
return -1;
table += offset;
if (proc_read_8(task, table, &length) < 0)
return -1;
next_pcs[nr++] = pc + 2 * length;
}
else
if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010) {
/* TBH. */
uint32_t table;
uint32_t offset;
uint16_t length;
const unsigned int tbl_reg = BITS(inst1, 0, 3);
if (tbl_reg == ARM_REG_PC)
/* Regcache copy of PC isn't right yet. */
table = pc + 4;
else {
if (arm_get_register(task, tbl_reg, &table) < 0)
return -1;
}
if (arm_get_register(task, BITS(inst2, 0, 3), &offset) < 0)
return -1;
table += 2 * offset;
if (proc_read_16(task, table, &length) < 0)
return -1;
next_pcs[nr++] = pc + 2 * length;
}
}
/* Otherwise take the next instruction. */
if (!nr)
next_pcs[nr++] = pc + thumb_insn_size(inst1);
return 0;
}
static int ptrace_cont(struct task *task)
{
if (ptrace(PTRACE_CONT, task->pid, 0, 0) == -1) {
if (errno != ESRCH)
fprintf(stderr, "%s PTRACE_CONT pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
return -1;
}
return 0;
}
int do_singlestep(struct task *task)
{
const uint32_t pc = get_instruction_pointer(task);
uint32_t cpsr;
struct breakpoint *bp1, *bp2;
int ret;
uint32_t next_pcs[2];
if (arm_get_register(task, ARM_REG_CPSR, &cpsr) < 0)
return -1;
if (BIT(cpsr, 5))
ret = thumb_get_next_pcs(task, pc, next_pcs);
else
ret = arm_get_next_pcs(task, pc, next_pcs);
if (ret < 0)
return -1;
bp1 = breakpoint_find(task, next_pcs[0]);
if (!bp1) {
bp1 = breakpoint_new(task, next_pcs[0], NULL, SW_BP);
if (!bp1)
return -1;
}
if (!bp1->enabled)
breakpoint_enable(task, bp1);
else
bp1 = NULL;
if (next_pcs[1]) {
bp2 = breakpoint_find(task, next_pcs[1]);
if (!bp2) {
bp2 = breakpoint_new(task, next_pcs[1], NULL, SW_BP);
if (!bp2)
return -1;
}
if (!bp2->enabled)
breakpoint_enable(task, bp2);
else
bp2 = NULL;
}
else
bp2 = NULL;
ret = handle_singlestep(task, ptrace_cont);
if (bp1)
breakpoint_disable(task, bp1);
if (bp2)
breakpoint_disable(task, bp2);
if (ret)
return ret;
return 0;
}

View File

@ -0,0 +1,59 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011, 2012 Petr Machata
* Copyright (C) 2006 Ian Wienand
* Copyright (C) 2004 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_SYSDEPS_LINUX_GNU_ARM_ARCH_H
#define _INC_SYSDEPS_LINUX_GNU_ARM_ARCH_H
#include <elf.h>
#include <stddef.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#define BREAKPOINT_VALUE { 0xf0, 0x01, 0xf0, 0xe7 }
#define BREAKPOINT_LENGTH 4
#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
#define THUMB_BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 0
#define ARCH_HAVE_FETCH_ARG
#define ARCH_HAVE_SIZEOF
#define ARCH_HAVE_ALIGNOF
#define ARCH_ENDIAN_LITTLE
#define ARCH_HAVE_ATOMIC_SINGLESTEP
#define MT_ELFCLASS ELFCLASS32
#define MT_ELF_MACHINE EM_ARM
#define ARCH_SINGLESTEP
#define DWARF_TO_REGNUM
#define HW_BREAKPOINTS 0
struct context {
struct pt_regs regs;
};
#endif

View File

@ -0,0 +1,625 @@
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include "config.h"
#include "common.h"
#include "backend.h"
#include "debug.h"
#include "dwarf.h"
#include "library.h"
#include "task.h"
#define R_15 15
#define R_SPSR 128
#define ARM_EXTABLE_ENTRY_SIZE 8
#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
#define ARM_EXIDX_CANT_UNWIND 0x00000001
#define ARM_EXIDX_COMPACT 0x80000000
#define ARM_EXTBL_OP_FINISH 0xb0
typedef enum arm_exbuf_cmd {
ARM_EXIDX_CMD_FINISH,
ARM_EXIDX_CMD_DATA_PUSH,
ARM_EXIDX_CMD_DATA_POP,
ARM_EXIDX_CMD_REG_POP,
ARM_EXIDX_CMD_REG_TO_SP,
ARM_EXIDX_CMD_VFP_POP,
ARM_EXIDX_CMD_WREG_POP,
ARM_EXIDX_CMD_WCGR_POP,
ARM_EXIDX_CMD_RESERVED,
ARM_EXIDX_CMD_REFUSED,
} arm_exbuf_cmd_t;
struct arm_exbuf_data {
arm_exbuf_cmd_t cmd;
uint32_t data;
};
enum arm_exbuf_cmd_flags {
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
ARM_EXIDX_VFP_DOUBLE = 1 << 17,
};
enum dwarf_ppc_regnum {
DWARF_ARM_R0,
DWARF_ARM_R1,
DWARF_ARM_R2,
DWARF_ARM_R3,
DWARF_ARM_R4,
DWARF_ARM_R5,
DWARF_ARM_R6,
DWARF_ARM_R7,
DWARF_ARM_R8,
DWARF_ARM_R9,
DWARF_ARM_R10,
DWARF_ARM_FP,
DWARF_ARM_IP,
DWARF_ARM_SP,
DWARF_ARM_LR,
DWARF_ARM_PC,
DWARF_ARM_CPSR,
};
static const uint8_t dwarf_to_regnum_map[] = {
[DWARF_ARM_R0] = offsetof(struct pt_regs, ARM_r0),
[DWARF_ARM_R1] = offsetof(struct pt_regs, ARM_r1),
[DWARF_ARM_R2] = offsetof(struct pt_regs, ARM_r2),
[DWARF_ARM_R3] = offsetof(struct pt_regs, ARM_r3),
[DWARF_ARM_R4] = offsetof(struct pt_regs, ARM_r4),
[DWARF_ARM_R5] = offsetof(struct pt_regs, ARM_r5),
[DWARF_ARM_R6] = offsetof(struct pt_regs, ARM_r6),
[DWARF_ARM_R7] = offsetof(struct pt_regs, ARM_r7),
[DWARF_ARM_R8] = offsetof(struct pt_regs, ARM_r8),
[DWARF_ARM_R9] = offsetof(struct pt_regs, ARM_r9),
[DWARF_ARM_R10] = offsetof(struct pt_regs, ARM_r10),
[DWARF_ARM_FP] = offsetof(struct pt_regs, ARM_fp),
[DWARF_ARM_IP] = offsetof(struct pt_regs, ARM_ip),
[DWARF_ARM_SP] = offsetof(struct pt_regs, ARM_sp),
[DWARF_ARM_LR] = offsetof(struct pt_regs, ARM_lr),
[DWARF_ARM_PC] = offsetof(struct pt_regs, ARM_pc),
[DWARF_ARM_CPSR] = offsetof(struct pt_regs, ARM_cpsr),
};
int dwarf_arch_init(struct dwarf_addr_space *as)
{
as->num_regs = ARRAY_SIZE(dwarf_to_regnum_map);
as->ip_reg = DWARF_ARM_PC;
as->ret_reg = DWARF_ARM_SP;
return 0;
}
int dwarf_arch_init_unwind(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
unsigned int i;
for(i = DWARF_ARM_R0; i <= DWARF_ARM_R10; ++i)
c->loc[i] = DWARF_REG_LOC(i);
c->loc[DWARF_ARM_FP] = DWARF_REG_LOC(DWARF_ARM_FP);
c->loc[DWARF_ARM_IP] = DWARF_REG_LOC(DWARF_ARM_IP);
c->loc[DWARF_ARM_SP] = DWARF_REG_LOC(DWARF_ARM_SP);
c->loc[DWARF_ARM_LR] = DWARF_REG_LOC(DWARF_ARM_LR);
c->loc[DWARF_ARM_PC] = DWARF_REG_LOC(DWARF_ARM_PC);
c->loc[DWARF_ARM_CPSR] = DWARF_REG_LOC(DWARF_ARM_CPSR);
c->ip = fetch_reg(as->task, offsetof(struct pt_regs, ARM_pc));
c->cfa = fetch_reg(as->task, offsetof(struct pt_regs, ARM_sp));
c->use_prev_instr = 0;
return 0;
}
static int is_signal_frame(struct dwarf_cursor *c)
{
return c->dci.signal_frame;
}
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg)
{
if (reg >= ARRAY_SIZE(dwarf_to_regnum_map))
return -DWARF_EBADREG;
return dwarf_to_regnum_map[reg];
}
unsigned int dwarf_to_regnum(unsigned int num)
{
if (num == R_SPSR)
return DWARF_ARM_CPSR;
if (num <= R_15)
return num;
return ~0;
}
static inline int access_mem(struct dwarf_addr_space *as, arch_addr_t addr, void *valp, size_t size)
{
#ifdef DEBUG
if (as) {
struct dwarf_cursor *c = &as->cursor;
struct library *lib = c->lib;
if (addr < ARCH_ADDR_T(lib->image_addr))
fatal("invalid access mem: addr %#lx < %p", addr, lib->image_addr);
if (addr >= ARCH_ADDR_T(lib->image_addr + lib->load_size))
fatal("invalid access mem: addr %#lx >= %p", addr, lib->image_addr + lib->load_size);
}
#endif
memcpy(valp, (void *)addr, size);
return 0;
}
static int prel31_to_addr(struct dwarf_addr_space *as, arch_addr_t prel31, arch_addr_t *val)
{
int32_t offset;
if (access_mem(as, prel31, &offset, sizeof(offset)) < 0)
return -DWARF_EINVAL;
offset = (offset << 1) >> 1;
*val = prel31 + offset;
return 0;
}
static int arm_exidx_apply_cmd(struct dwarf_addr_space *as, struct arm_exbuf_data *edata)
{
struct dwarf_cursor *c = &as->cursor;
arch_addr_t ip;
unsigned int i;
switch(edata->cmd) {
case ARM_EXIDX_CMD_FINISH:
/* Set LR to PC if not set already. */
if (DWARF_IS_NULL_LOC(c->loc[DWARF_ARM_PC]))
c->loc[DWARF_ARM_PC] = c->loc[DWARF_ARM_LR];
/* Set IP. */
if (dwarf_get(as, c->loc[DWARF_ARM_PC], &ip) < 0)
return -DWARF_EINVAL;
c->ip = ip;
break;
case ARM_EXIDX_CMD_DATA_PUSH:
debug(DEBUG_DWARF, "vsp = vsp - %d", edata->data);
c->cfa -= edata->data;
break;
case ARM_EXIDX_CMD_DATA_POP:
debug(DEBUG_DWARF, "vsp = vsp + %d", edata->data);
c->cfa += edata->data;
break;
case ARM_EXIDX_CMD_REG_POP:
for (i = 0; i < 16; i++) {
if (edata->data & (1 << i)) {
debug(DEBUG_DWARF, "pop {r%d}", i);
c->loc[DWARF_ARM_R0 + i] = DWARF_MEM_LOC(c->cfa);
c->cfa += 4;
}
}
/* Set cfa in case the SP got popped. */
if (edata->data & (1 << 13)) {
if (dwarf_get(as, c->loc[DWARF_ARM_SP], &c->cfa) < 0)
return -DWARF_EINVAL;
}
break;
case ARM_EXIDX_CMD_REG_TO_SP:
assert (edata->data < 16);
debug(DEBUG_DWARF, "vsp = r%d", edata->data);
c->loc[DWARF_ARM_SP] = c->loc[DWARF_ARM_R0 + edata->data];
if (dwarf_get(as, c->loc[DWARF_ARM_SP], &c->cfa) < 0)
return -DWARF_EINVAL;
break;
case ARM_EXIDX_CMD_VFP_POP:
/* Skip VFP registers, but be sure to adjust stack */
for (i = ARM_EXBUF_START(edata->data); i <= ARM_EXBUF_END(edata->data); i++)
c->cfa += 8;
if (!(edata->data & ARM_EXIDX_VFP_DOUBLE))
c->cfa += 4;
break;
case ARM_EXIDX_CMD_WREG_POP:
for (i = ARM_EXBUF_START(edata->data); i <= ARM_EXBUF_END(edata->data); i++)
c->cfa += 8;
break;
case ARM_EXIDX_CMD_WCGR_POP:
for (i = 0; i < 4; i++) {
if (edata->data & (1 << i))
c->cfa += 4;
}
break;
case ARM_EXIDX_CMD_REFUSED:
case ARM_EXIDX_CMD_RESERVED:
return -DWARF_EINVAL;
}
return 0;
}
static int arm_exidx_decode(struct dwarf_addr_space *as, const uint8_t *buf, uint8_t len)
{
const uint8_t *end = buf + len;
int ret;
struct arm_exbuf_data edata;
assert(buf != NULL);
assert(len > 0);
while(buf < end) {
uint8_t op = *buf++;
if ((op & 0xc0) == 0x00) {
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
edata.data = (((int)op & 0x3f) << 2) + 4;
}
else
if ((op & 0xc0) == 0x40) {
edata.cmd = ARM_EXIDX_CMD_DATA_PUSH;
edata.data = (((int)op & 0x3f) << 2) + 4;
}
else
if ((op & 0xf0) == 0x80) {
uint8_t op2 = *buf++;
if (op == 0x80 && op2 == 0x00)
edata.cmd = ARM_EXIDX_CMD_REFUSED;
else {
edata.cmd = ARM_EXIDX_CMD_REG_POP;
edata.data = ((op & 0xf) << 8) | op2;
edata.data = edata.data << 4;
}
}
else
if ((op & 0xf0) == 0x90) {
if (op == 0x9d || op == 0x9f)
edata.cmd = ARM_EXIDX_CMD_RESERVED;
else {
edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
edata.data = op & 0x0f;
}
}
else
if ((op & 0xf0) == 0xa0) {
unsigned end = (op & 0x07);
edata.data = (1 << (end + 1)) - 1;
edata.data = edata.data << 4;
if (op & 0x08)
edata.data |= 1 << 14;
edata.cmd = ARM_EXIDX_CMD_REG_POP;
}
else
if (op == ARM_EXTBL_OP_FINISH) {
edata.cmd = ARM_EXIDX_CMD_FINISH;
buf = end;
}
else
if (op == 0xb1) {
uint8_t op2 = *buf++;
if (op2 == 0 || (op2 & 0xf0))
edata.cmd = ARM_EXIDX_CMD_RESERVED;
else {
edata.cmd = ARM_EXIDX_CMD_REG_POP;
edata.data = op2 & 0x0f;
}
}
else
if (op == 0xb2) {
uint32_t offset = 0;
uint8_t byte, shift = 0;
do {
byte = *buf++;
offset |= (byte & 0x7f) << shift;
shift += 7;
} while(byte & 0x80);
edata.data = offset * 4 + 0x204;
edata.cmd = ARM_EXIDX_CMD_DATA_POP;
}
else
if (op == 0xb3 || op == 0xc8 || op == 0xc9) {
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
edata.data = *buf++;
if (op == 0xc8)
edata.data |= ARM_EXIDX_VFP_SHIFT_16;
if (op != 0xb3)
edata.data |= ARM_EXIDX_VFP_DOUBLE;
}
else
if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) {
edata.cmd = ARM_EXIDX_CMD_VFP_POP;
edata.data = 0x80 | (op & 0x07);
if ((op & 0xf8) == 0xd0)
edata.data |= ARM_EXIDX_VFP_DOUBLE;
}
else
if (op >= 0xc0 && op <= 0xc5) {
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
edata.data = 0xa0 | (op & 0x07);
}
else
if (op == 0xc6) {
edata.cmd = ARM_EXIDX_CMD_WREG_POP;
edata.data = *buf++;
}
else
if (op == 0xc7) {
uint8_t op2 = *buf++;
if (op2 == 0 || (op2 & 0xf0))
edata.cmd = ARM_EXIDX_CMD_RESERVED;
else {
edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
edata.data = op2 & 0x0f;
}
}
else
edata.cmd = ARM_EXIDX_CMD_RESERVED;
ret = arm_exidx_apply_cmd(as, &edata);
if (ret < 0)
return ret;
}
return 0;
}
static int arm_exidx_extract(struct dwarf_addr_space *as, arch_addr_t entry, uint8_t *buf)
{
int nbuf = 0;
arch_addr_t addr;
uint32_t data;
#ifdef DEBUG
if (prel31_to_addr(NULL, entry, &addr) < 0)
return -DWARF_EINVAL;
#else
addr = 0;
#endif
/* An ARM unwind entry consists of a prel31 offset to the start of a
function followed by 31bits of data:
* if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND)
* if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT)
* if bit 31 is zero: this is a prel31 offset of the start of the
table entry for this function */
if (access_mem(as, entry + 4, &data, sizeof(data)) < 0)
return -DWARF_EINVAL;
if (data == ARM_EXIDX_CANT_UNWIND) {
debug(DEBUG_DWARF, "can't unwind");
return -DWARF_STOPUNWIND;
}
else
if (data & ARM_EXIDX_COMPACT) {
debug(DEBUG_DWARF, "%#lx compact model %d [%8.8x]", addr, (data >> 24) & 0x7f, data);
buf[nbuf++] = data >> 16;
buf[nbuf++] = data >> 8;
buf[nbuf++] = data;
}
else {
arch_addr_t extbl_data;
unsigned int n_table_words;
if (prel31_to_addr(as, entry + 4, &extbl_data) < 0)
return -DWARF_EINVAL;
if (access_mem(as, extbl_data, &data, sizeof(data)) < 0)
return -DWARF_EINVAL;
if (data & ARM_EXIDX_COMPACT) {
unsigned int pers = (data >> 24) & 0x0f;
debug(DEBUG_DWARF, "%#lx compact model %d [%8.8x]", addr, pers, data);
if (pers == 1 || pers == 2) {
n_table_words = (data >> 16) & 0xff;
extbl_data += 4;
}
else {
n_table_words = 0;
buf[nbuf++] = data >> 16;
}
buf[nbuf++] = data >> 8;
buf[nbuf++] = data;
}
else {
arch_addr_t pers;
if (prel31_to_addr(as, extbl_data, &pers) < 0)
return -DWARF_EINVAL;
debug(DEBUG_DWARF, "%#lx Personality routine: %#lx", addr, pers);
if (access_mem(as, extbl_data + 4, &data, sizeof(data)) < 0)
return -DWARF_EINVAL;
n_table_words = data >> 24;
buf[nbuf++] = data >> 16;
buf[nbuf++] = data >> 8;
buf[nbuf++] = data;
extbl_data += 8;
}
assert(n_table_words <= 5);
unsigned j;
for(j = 0; j < n_table_words; j++) {
if (access_mem(as, extbl_data, &data, sizeof(data)) < 0)
return -DWARF_EINVAL;
extbl_data += 4;
buf[nbuf++] = data >> 24;
buf[nbuf++] = data >> 16;
buf[nbuf++] = data >> 8;
buf[nbuf++] = data >> 0;
}
}
if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH)
buf[nbuf++] = ARM_EXTBL_OP_FINISH;
return nbuf;
}
static unsigned long arm_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip, void *exidx_data, unsigned long exidx_len)
{
struct dwarf_cursor *c = &as->cursor;
struct library *lib = c->lib;
unsigned long map_offset = (unsigned long)lib->image_addr + lib->load_offset - lib->load_addr;
unsigned long lo, hi, e, f;
arch_addr_t val;
hi = exidx_len / ARM_EXTABLE_ENTRY_SIZE;
if (!hi)
return 0;
lo = 0;
f = 0;
do {
unsigned long mid = (lo + hi) / 2;
e = (unsigned long)exidx_data + mid * ARM_EXTABLE_ENTRY_SIZE;
if (prel31_to_addr(NULL, e, &val) < 0)
return -DWARF_EINVAL;
val -= map_offset;
if (ip < val)
hi = mid;
else {
f = e;
lo = mid + 1;
}
} while(lo < hi);
return f;
}
static int arm_exidx_step(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
struct library *lib = c->lib;
arch_addr_t old_ip, old_cfa, entry;
uint8_t buf[32];
int ret;
if (!lib)
return -DWARF_ENOINFO;
old_ip = c->ip;
old_cfa = c->cfa;
/* mark PC unsaved */
c->loc[DWARF_ARM_PC] = DWARF_NULL_LOC;
entry = arm_search_unwind_table(as, c->ip, lib->exidx_data, lib->exidx_len);
if (!entry)
return -DWARF_ENOINFO;
ret = arm_exidx_extract(as, entry, buf);
if (ret <= 0)
return ret;
ret = arm_exidx_decode(as, buf, ret);
if (ret)
return ret;
if (c->ip == old_ip && c->cfa == old_cfa) {
debug(DEBUG_DWARF, "ip and cfa unchanged; stopping here (ip=0x%lx)\n", c->ip);
return -DWARF_EBADFRAME;
}
if (!c->ip)
return -DWARF_EINVAL;
return 0;
}
static int arm_frame_step(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
struct dwarf_loc ip_loc, fp_loc;
arch_addr_t instr, ip, fp, nframe;
int ret;
if (dwarf_get(as, c->loc[DWARF_ARM_FP], &fp) < 0)
return -DWARF_EBADFRAME;
if (fp <= c->cfa || fp - c->cfa > 128 * 1024)
return -DWARF_EBADFRAME;
if (dwarf_get(as, DWARF_MEM_LOC(fp), &nframe) < 0)
return -DWARF_EBADFRAME;
ret = dwarf_locate_map(as, nframe - 8);
if (ret)
return -DWARF_ENOINFO;
if (dwarf_get(as, DWARF_MEM_LOC(nframe - 8), &instr) < 0)
return -DWARF_ENOINFO;
if ((instr & 0xFFFFD800) == 0xE92DD800) {
/* Standard APCS fp. */
ip_loc = DWARF_MEM_LOC(fp - 4);
fp_loc = DWARF_MEM_LOC(fp - 12);
}
else {
/* Codesourcery optimized normal frame. */
ip_loc = DWARF_MEM_LOC(fp);
fp_loc = DWARF_MEM_LOC(fp - 4);
}
if (dwarf_get(as, ip_loc, &ip) < 0)
return -DWARF_EBADFRAME;
c->loc[DWARF_ARM_IP] = ip_loc;
c->loc[DWARF_ARM_FP] = fp_loc;
c->ip = ip;
c->cfa = fp;
debug(DEBUG_DWARF, "ip=%lx", c->ip);
return 0;
}
int dwarf_arch_step(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
int ret;
if (is_signal_frame(c))
return -DWARF_EBADFRAME;
ret = arm_exidx_step(as);
if (ret) {
if (ret == -DWARF_STOPUNWIND)
return ret;
}
if (arm_frame_step(as) == 0)
return 0;
return -DWARF_EBADFRAME;
}

View File

@ -0,0 +1,169 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata, Red Hat Inc.
* Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ptrace.h>
//#include <sys/reg.h>
#include "backend.h"
#include "task.h"
#include "arch.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
#define PTRACE_PEEKUSER PTRACE_PEEKUSR
#endif
#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
#define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
arch_addr_t get_instruction_pointer(struct task *task)
{
return ARCH_ADDR_T(task->context.regs.ARM_pc);
}
void set_instruction_pointer(struct task *task, arch_addr_t addr)
{
unsigned long val = (unsigned long)addr;
task->context.regs.ARM_pc = val;
if (ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct pt_regs, ARM_pc), val) == -1)
fprintf(stderr, "pid=%d Couldn't set instruction pointer: %s\n", task->pid, strerror(errno));
}
arch_addr_t get_return_addr(struct task *task)
{
return ARCH_ADDR_T(task->context.regs.ARM_lr);
}
int fetch_context(struct task *task)
{
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1)
fprintf(stderr, "pid=%d Couldn't fetch register context: %s\n", task->pid, strerror(errno));
return 0;
}
void save_param_context(struct task *task)
{
task->saved_context = task->context;
}
unsigned long fetch_param(struct task *task, unsigned int param)
{
unsigned long val;
switch (param) {
case 0:
val = task->saved_context.regs.ARM_r0;
break;
case 1:
val = task->saved_context.regs.ARM_r1;
break;
case 2:
val = task->saved_context.regs.ARM_r2;
break;
case 3:
val = task->saved_context.regs.ARM_r3;
break;
default:
copy_from_proc(task, task->saved_context.regs.ARM_sp + (param - 4) * sizeof(val), &val, sizeof(val));
}
return val;
}
unsigned long fetch_retval(struct task *task)
{
return task->context.regs.ARM_r0;
}
unsigned long fetch_reg(struct task *task, unsigned int reg)
{
unsigned long val;
switch(reg) {
case offsetof(struct pt_regs, ARM_cpsr):
val = task->context.regs.ARM_cpsr;
break;
case offsetof(struct pt_regs, ARM_pc):
val = task->context.regs.ARM_pc;
break;
case offsetof(struct pt_regs, ARM_lr):
val = task->context.regs.ARM_lr;
break;
case offsetof(struct pt_regs, ARM_sp):
val = task->context.regs.ARM_sp;
break;
case offsetof(struct pt_regs, ARM_ip):
val = task->context.regs.ARM_ip;
break;
case offsetof(struct pt_regs, ARM_fp):
val = task->context.regs.ARM_fp;
break;
case offsetof(struct pt_regs, ARM_r10):
val = task->context.regs.ARM_r10;
break;
case offsetof(struct pt_regs, ARM_r9):
val = task->context.regs.ARM_r9;
break;
case offsetof(struct pt_regs, ARM_r8):
val = task->context.regs.ARM_r8;
break;
case offsetof(struct pt_regs, ARM_r7):
val = task->context.regs.ARM_r7;
break;
case offsetof(struct pt_regs, ARM_r6):
val = task->context.regs.ARM_r6;
break;
case offsetof(struct pt_regs, ARM_r5):
val = task->context.regs.ARM_r5;
break;
case offsetof(struct pt_regs, ARM_r4):
val = task->context.regs.ARM_r4;
break;
case offsetof(struct pt_regs, ARM_r3):
val = task->context.regs.ARM_r3;
break;
case offsetof(struct pt_regs, ARM_r2):
val = task->context.regs.ARM_r2;
break;
case offsetof(struct pt_regs, ARM_r1):
val = task->context.regs.ARM_r1;
break;
case offsetof(struct pt_regs, ARM_r0):
val = task->context.regs.ARM_r0;
break;
case offsetof(struct pt_regs, ARM_ORIG_r0):
val = task->context.regs.ARM_ORIG_r0;
break;
default:
abort();
}
return val;
}

View File

@ -0,0 +1,60 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "backtrace.h"
#include "dwarf.h"
#include "task.h"
#include <stdio.h>
int backtrace_init(struct task *task)
{
task->backtrace = dwarf_init(task);
return task->backtrace != NULL;
}
void backtrace_destroy(struct task *task)
{
if (task->backtrace)
dwarf_destroy(task->backtrace);
}
int backtrace_init_unwind(struct task *task)
{
if (task->backtrace)
return dwarf_init_unwind(task->backtrace);
return -1;
}
unsigned long backtrace_get_ip(struct task *task)
{
if (task->backtrace)
return dwarf_get_ip(task->backtrace);
return 0;
}
int backtrace_step(struct task *task)
{
if (task->backtrace)
return dwarf_step(task->backtrace);
return -1;
}

123
sysdeps/linux-gnu/ioevent.c Normal file
View File

@ -0,0 +1,123 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define _GNU_SOURCE
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include "ioevent.h"
struct io_watch_event {
int (*func)(void);
};
struct pollfd *io_watch_poll;
struct io_watch_event *io_watch_event;
static unsigned int io_watch_size;
static unsigned int io_watch_elems;
static inline void io_watch_set(unsigned int idx, int fd, int (*func)(void))
{
io_watch_event[idx].func = func;
io_watch_poll[idx].fd = fd;
io_watch_poll[idx].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
}
int ioevent_add_input(int fd, int (*func)(void))
{
unsigned int i;
for(i = 0; i < io_watch_elems; ++i) {
if (io_watch_poll[i].fd == fd) {
io_watch_set(i, fd, func);
return 1;
}
}
if (io_watch_size == io_watch_elems) {
io_watch_size += 16;
io_watch_poll = realloc(io_watch_poll, sizeof(struct pollfd) * io_watch_size);
io_watch_event = realloc(io_watch_event, sizeof(struct io_watch_event) * io_watch_size);
}
io_watch_set(io_watch_elems, fd, func);
++io_watch_elems;
return 0;
}
int ioevent_del_input(int fd)
{
unsigned int i;
for(i = 0; i < io_watch_elems; ++i) {
if (io_watch_poll[i].fd == fd) {
--io_watch_elems;
if (i != io_watch_elems) {
io_watch_set(i,
io_watch_poll[io_watch_elems].fd,
io_watch_event[io_watch_elems].func
);
}
return 0;
}
}
return -1;
}
int ioevent_watch(int timeout)
{
unsigned int i;
int ret;
ret = TEMP_FAILURE_RETRY(poll(io_watch_poll, io_watch_elems, timeout));
if (ret < 0)
return ret;
ret = 0;
for(i = 0; i < io_watch_elems; ++i) {
if (io_watch_poll[i].revents) {
if (io_watch_event[i].func() == -1)
ret = -1;
}
}
return ret;
}
int ioevent_wait_input(int fd, int timeout)
{
struct pollfd pfd[1];
pfd[0].fd = fd;
pfd[0].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
return TEMP_FAILURE_RETRY(poll(pfd, ARRAY_SIZE(pfd), timeout));
}

View File

@ -0,0 +1,30 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
#define _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
int ioevent_add_input(int fd, int (*func)(void));
int ioevent_del_input(int fd);
int ioevent_watch(int timeout);
int ioevent_wait_input(int fd, int timeout);
#endif

426
sysdeps/linux-gnu/os.c Normal file
View File

@ -0,0 +1,426 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <bfd.h>
#include <pwd.h>
#include <grp.h>
#include "backend.h"
#include "breakpoint.h"
#include "common.h"
#include "debug.h"
#include "main.h"
#include "options.h"
#include "os.h"
#include "socket.h"
#include "task.h"
struct map {
unsigned long long start;
unsigned long long end;
};
static void report_fault(int signo, siginfo_t* siginf, void* arg)
{
int nptrs;
int i;
void *trace[48];
char **strings;
Dl_info info;
char linkname[PATH_MAX];
bfd* abfd = 0;
asymbol **syms = 0;
asection *text = 0;
int l;
fprintf(stderr, "fault signal %d (%s)\n", signo, strsignal(signo));
l = readlink("/proc/self/exe", linkname, sizeof(linkname));
if (l == -1) {
perror("failed to find executable\n");
return;
}
linkname[l] = 0;
bfd_init();
abfd = bfd_openr(linkname, 0);
if (!abfd) {
perror("bfd_openr failed: ");
return;
}
/* oddly, this is required for it to work... */
bfd_check_format(abfd,bfd_object);
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
syms = (asymbol **) malloc(storage_needed);
bfd_canonicalize_symtab(abfd, syms);
text = bfd_get_section_by_name(abfd, ".text");
nptrs = backtrace(trace, ARRAY_SIZE(trace));
strings = backtrace_symbols(trace, nptrs);
if (!strings) {
perror("backtrace_symbols");
_exit(EXIT_FAILURE);
}
for (i = 0; i < nptrs; ++i) {
unsigned long offset;
fprintf(stderr, "%d:%s", i, strings[i]);
offset = ((long)trace[i]) - text->vma;
if (offset < text->size) {
const char *file;
const char *func;
unsigned line;
if (bfd_find_nearest_line(abfd, text, syms, offset, &file, &func, &line) && file) {
fprintf(stderr, ": %s()", func);
if (*file)
fprintf(stderr, ":%s@%u", file, line);
goto skip;
}
}
if (dladdr(trace[i], &info)) {
if (info.dli_sname)
fprintf(stderr, ": %s", info.dli_sname);
}
skip:
fprintf(stderr, "\n");
}
free(strings);
fflush(stderr);
_exit(EXIT_FAILURE);
}
static void signal_exit(int sig)
{
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
mtrace_request_exit();
}
static void sigchld_handler(int signum)
{
}
static int open_mem(pid_t pid)
{
int h;
char *proc_name;
if (asprintf(&proc_name, "/proc/%u/mem", pid) == -1)
fatal("asprintf (%s)", strerror(errno));
h = open(proc_name, O_RDONLY);
if (h == -1)
fatal("open: '%s'(%s)", proc_name, strerror(errno));
free(proc_name);
return h;
}
static struct map *get_writeable_mappings(struct task *task)
{
unsigned long long start;
unsigned long long end;
char permr;
char permw;
char filename[PATH_MAX + 2];
char nl;
FILE *in;
unsigned int maps_size = 0;
struct map *maps = NULL;
unsigned int map = 0;
snprintf(filename, sizeof(filename)-1, "/proc/%d/maps", task->pid);
maps_size = 16;
maps = malloc(maps_size * sizeof(*maps));
in = fopen(filename, "r");
if (!in)
goto skip;
while(fscanf(in, "%llx-%llx %c%c%*c%*c %*x %*x:%*x %*u%*64[ ]%c", &start, &end, &permr, &permw, filename) == 5) {
if (*filename != '\n') {
if (fscanf(in, "%" STR(PATH_MAX) "[^\n]%c", filename + 1, &nl) != 2)
break;
if (nl != '\n')
break;
}
else
*filename = 0;
if (*filename != '[' && *filename != 0) {
struct stat statbuf;
if (stat(filename, &statbuf) < 0)
continue;
if (S_ISCHR(statbuf.st_mode)) {
if (statbuf.st_rdev != makedev(1, 5))
continue;
}
}
if (permw != 'w' || permr != 'r')
continue;
if (map >= maps_size - 1) {
maps_size += 16;
maps = realloc(maps, maps_size * sizeof(*maps));
}
maps[map].start = start;
maps[map].end = end;
map++;
}
fclose(in);
skip:
maps[map].start = 0;
maps[map].end = 0;
return maps;
}
void *mem_scan(struct task *task, struct mt_msg *cmd, void *payload, unsigned long *data_len)
{
struct mt_scan_payload *mt_scan = payload;
unsigned long mask = (unsigned long)mt_scan->mask;
uint32_t ptr_size = mt_scan->ptr_size;
void *blocks = mt_scan->data;
unsigned long n = (cmd->payload_len - (blocks - payload)) / ptr_size;
unsigned long map;
struct map *maps;
int h;
unsigned long (*get_val)(void *data, unsigned long index);
unsigned long start;
unsigned long end;
if (!n)
return NULL;
if (ptr_size == sizeof(uint32_t))
get_val = get_val32;
else
get_val = get_val64;
h = open_mem(task->pid);
if (h == -1)
return NULL;
maps = get_writeable_mappings(task);
for(map = 0; (start = maps[map].start) && (end = maps[map].end); ++map) {
int do_peek = 0;
while(start < end) {
unsigned long i;
char page_buf[PAGE_SIZE];
if (!do_peek) {
if (lseek(h, start, SEEK_SET) != (off_t)start || read(h, page_buf, sizeof(page_buf)) == -1)
do_peek = 1;
}
if (do_peek) {
if (copy_from_proc(task, ARCH_ADDR_T(start), page_buf, sizeof(page_buf)) != sizeof(page_buf)) {
fprintf(stderr, "ptrace (%s)\n", strerror(errno));
break;
}
}
for(i = 0; i < sizeof(page_buf) / ptr_size; ++i) {
unsigned long found, addr;
addr = get_val(page_buf, i);
if (addr & mask)
continue;
found = find_block(get_val, blocks, n, addr);
if (found != n) {
if (!--n)
goto finish;
if (found != n)
memmove(blocks + found * ptr_size, blocks + (found + 1) * ptr_size, (n - found) * ptr_size);
}
}
start += sizeof(page_buf);
}
}
finish:
close(h);
*data_len = n * ptr_size;
free(maps);
return blocks;
}
void change_uid(const char *command)
{
uid_t run_uid, run_euid;
gid_t run_gid, run_egid;
if (options.user) {
struct passwd *pent;
if (getuid() != 0 || geteuid() != 0) {
fprintf(stderr, "you must be root to use the -u option\n");
exit(1);
}
if ((pent = getpwnam(options.user)) == NULL) {
fprintf(stderr, "cannot find user `%s'\n", options.user);
exit(1);
}
run_uid = pent->pw_uid;
run_gid = pent->pw_gid;
if (initgroups(options.user, run_gid) < 0) {
perror("mtrace: initgroups");
exit(1);
}
} else {
run_uid = getuid();
run_gid = getgid();
}
if (options.user || !geteuid()) {
struct stat statbuf;
run_euid = run_uid;
run_egid = run_gid;
if (!stat(options.command, &statbuf)) {
if (statbuf.st_mode & S_ISUID) {
run_euid = statbuf.st_uid;
}
if (statbuf.st_mode & S_ISGID) {
run_egid = statbuf.st_gid;
}
}
if (setregid(run_gid, run_egid) < 0) {
perror("mtrace: setregid");
exit(1);
}
if (setreuid(run_uid, run_euid) < 0) {
perror("mtrace: setreuid");
exit(1);
}
}
}
ssize_t sock_fd_write(int sock, void *buf, ssize_t buflen, int fd)
{
ssize_t size;
struct msghdr msg;
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = buflen;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
size = sendmsg(sock, &msg, MSG_DONTWAIT);
return size;
}
int os_init(void)
{
sigset_t block_sigset;
struct sigaction act;
const int siglist[] = { SIGSEGV, SIGABRT, SIGTRAP, SIGILL, SIGFPE };
unsigned int i;
int ret;
for(i = 0; i < ARRAY_SIZE(siglist); i++) {
act.sa_flags = SA_ONESHOT | SA_SIGINFO;
act.sa_sigaction = report_fault;
sigfillset(&act.sa_mask);
sigaction(siglist[i], &act, NULL);
}
signal(SIGINT, signal_exit); /* Detach task_es when interrupted */
signal(SIGTERM, signal_exit); /* ... or killed */
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
act.sa_handler = sigchld_handler;
if (sigaction(SIGCHLD, &act, NULL)) {
perror("sigaction(SIGCHLD)");
return -1;
}
sigemptyset(&block_sigset);
sigaddset(&block_sigset, SIGCHLD);
ret = pthread_sigmask(SIG_BLOCK, &block_sigset, NULL);
if (ret) {
fprintf(stderr, "pthread_sigmask %d (%s)\n", ret, strerror(ret));
return -1;
}
return 0;
}

41
sysdeps/linux-gnu/os.h Normal file
View File

@ -0,0 +1,41 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_SYSDEPS_LINUX_GNU_OS_H
#define _INC_SYSDEPS_LINUX_GNU_OS_H
#include <sys/user.h>
#include "mtrace.h"
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define OS_HAVE_PROCESS_DATA
struct os_task_data {
arch_addr_t debug_addr;
int debug_state;
};
#endif

View File

@ -0,0 +1,31 @@
# This file is part of mtrace.
# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
noinst_LTLIBRARIES = \
../libcpu.la
___libcpu_la_SOURCES = \
dwarf-ppc.c \
regs.c \
arch.c
noinst_HEADERS = \
arch.h
MAINTAINERCLEANFILES = \
Makefile.in

View File

@ -0,0 +1,634 @@
# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# This file is part of mtrace.
# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = sysdeps/linux-gnu/ppc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
$(top_srcdir)/config/m4/ltoptions.m4 \
$(top_srcdir)/config/m4/ltsugar.m4 \
$(top_srcdir)/config/m4/ltversion.m4 \
$(top_srcdir)/config/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
$(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
___libcpu_la_LIBADD =
am____libcpu_la_OBJECTS = dwarf-ppc.lo regs.lo arch.lo
___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
am__dirstamp = $(am__leading_dot)dirstamp
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(___libcpu_la_SOURCES)
DIST_SOURCES = $(___libcpu_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/config/autoconf/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CPPFLAGS = @AM_CPPFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
HOST_CPU = @HOST_CPU@
HOST_OS = @HOST_OS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LTLIBRARIES = \
../libcpu.la
___libcpu_la_SOURCES = \
dwarf-ppc.c \
regs.c \
arch.c
noinst_HEADERS = \
arch.h
MAINTAINERCLEANFILES = \
Makefile.in
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/ppc/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign sysdeps/linux-gnu/ppc/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
../$(am__dirstamp):
@$(MKDIR_P) ..
@: > ../$(am__dirstamp)
../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) $(EXTRA____libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
$(AM_V_CCLD)$(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf-ppc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf ../.libs ../_libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f ../$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -0,0 +1,32 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2010,2011,2012 Petr Machata, Red Hat Inc.
* Copyright (C) 2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "arch.h"
#include "mtelf.h"
int is_64bit(struct mt_elf *mte)
{
return mte->ehdr.e_machine != EM_PPC;
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2011, 2012 Petr Machata
* Copyright (C) 2006 Ian Wienand
* Copyright (C) 2004 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _INC_SYSDEPS_LINUX_GNU_PPC_ARCH_H
#define _INC_SYSDEPS_LINUX_GNU_PPC_ARCH_H
#include <elf.h>
#include <stddef.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 0
#define ARCH_ENDIAN_BIG
#define ARCH_HAVE_ATOMIC_SINGLESTEP
#define MT_ELFCLASS ELFCLASS32
#define MT_ELF_MACHINE EM_PPC
#ifdef __powerpc64__
#define MT_ELFCLASS2 ELFCLASS64
#define MT_ELF_MACHINE2 EM_PPC64
#endif
#define DWARF_TO_REGNUM
#define HW_BREAKPOINTS 0
struct context {
struct pt_regs regs;
};
#endif

View File

@ -0,0 +1,248 @@
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <inttypes.h>
#include "common.h"
#include "backend.h"
#include "debug.h"
#include "dwarf.h"
#include "task.h"
#define R_LR 65
#define R_CTR 66
#define R_CR0 68
#define R_CR1 69
#define R_CR2 70
#define R_CR3 71
#define R_CR4 72
#define R_XER 76
#define R_VR0 77
#define R_VRSAVE 109
#define R_VSCR 110
#define R_SPEFSCR 112
#define R_FRAME_POINTER 113
enum dwarf_ppc_regnum {
DWARF_PPC_R0,
DWARF_PPC_R1, /* called STACK_POINTER in gcc */
DWARF_PPC_R2,
DWARF_PPC_R3,
DWARF_PPC_R4,
DWARF_PPC_R5,
DWARF_PPC_R6,
DWARF_PPC_R7,
DWARF_PPC_R8,
DWARF_PPC_R9,
DWARF_PPC_R10,
DWARF_PPC_R11, /* called STATIC_CHAIN in gcc */
DWARF_PPC_R12,
DWARF_PPC_R13,
DWARF_PPC_R14,
DWARF_PPC_R15,
DWARF_PPC_R16,
DWARF_PPC_R17,
DWARF_PPC_R18,
DWARF_PPC_R19,
DWARF_PPC_R20,
DWARF_PPC_R21,
DWARF_PPC_R22,
DWARF_PPC_R23,
DWARF_PPC_R24,
DWARF_PPC_R25,
DWARF_PPC_R26,
DWARF_PPC_R27,
DWARF_PPC_R28,
DWARF_PPC_R29,
DWARF_PPC_R30,
DWARF_PPC_R31, /* called HARD_FRAME_POINTER in gcc */
DWARF_PPC_LR, /* Link Register */
DWARF_PPC_CTR, /* Count Register */
DWARF_PPC_CR0, /* Condition Register */
DWARF_PPC_CR1,
DWARF_PPC_CR2,
DWARF_PPC_CR3,
DWARF_PPC_CR4,
DWARF_PPC_XER, /* Fixed-Point Status and Control Register */
DWARF_PPC_VR0,
DWARF_PPC_VRSAVE,
DWARF_PPC_VSCR,
DWARF_PPC_FPSCR,
DWARF_PPC_FRAME_POINTER,
};
static const uint8_t dwarf_to_regnum_map[] = {
[DWARF_PPC_R0] = PT_R0 + 1,
[DWARF_PPC_R1] = PT_R1 + 1,
[DWARF_PPC_R2] = PT_R2 + 1,
[DWARF_PPC_R3] = PT_R3 + 1,
[DWARF_PPC_R4] = PT_R4 + 1,
[DWARF_PPC_R5] = PT_R5 + 1,
[DWARF_PPC_R6] = PT_R6 + 1,
[DWARF_PPC_R7] = PT_R7 + 1,
[DWARF_PPC_R8] = PT_R8 + 1,
[DWARF_PPC_R9] = PT_R9 + 1,
[DWARF_PPC_R10] = PT_R10 + 1,
[DWARF_PPC_R11] = PT_R11 + 1,
[DWARF_PPC_R12] = PT_R12 + 1,
[DWARF_PPC_R13] = PT_R13 + 1,
[DWARF_PPC_R14] = PT_R14 + 1,
[DWARF_PPC_R15] = PT_R15 + 1,
[DWARF_PPC_R16] = PT_R16 + 1,
[DWARF_PPC_R17] = PT_R17 + 1,
[DWARF_PPC_R18] = PT_R18 + 1,
[DWARF_PPC_R19] = PT_R19 + 1,
[DWARF_PPC_R20] = PT_R20 + 1,
[DWARF_PPC_R21] = PT_R21 + 1,
[DWARF_PPC_R22] = PT_R22 + 1,
[DWARF_PPC_R23] = PT_R23 + 1,
[DWARF_PPC_R24] = PT_R24 + 1,
[DWARF_PPC_R25] = PT_R25 + 1,
[DWARF_PPC_R26] = PT_R26 + 1,
[DWARF_PPC_R27] = PT_R27 + 1,
[DWARF_PPC_R28] = PT_R28 + 1,
[DWARF_PPC_R29] = PT_R29 + 1,
[DWARF_PPC_R30] = PT_R30 + 1,
[DWARF_PPC_R31] = PT_R31 + 1,
[DWARF_PPC_LR] = PT_LNK + 1,
[DWARF_PPC_CTR] = PT_CTR + 1,
[DWARF_PPC_CR0] = PT_CCR + 1,
[DWARF_PPC_CR1] = 0,
[DWARF_PPC_CR2] = 0,
[DWARF_PPC_CR3] = 0,
[DWARF_PPC_CR4] = 0,
[DWARF_PPC_XER] = PT_XER + 1,
[DWARF_PPC_VR0] = 0,
[DWARF_PPC_VRSAVE] = 0,
[DWARF_PPC_VSCR] = 0,
[DWARF_PPC_FPSCR] = 0,
[DWARF_PPC_FRAME_POINTER] = 0,
};
int dwarf_arch_init(struct dwarf_addr_space *as)
{
as->num_regs = ARRAY_SIZE(dwarf_to_regnum_map);
as->ip_reg = as->num_regs; /* not in dwarf, invalid register */
as->ret_reg = DWARF_PPC_R1;
return 0;
}
int dwarf_arch_init_unwind(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
unsigned int i;
for(i = DWARF_PPC_R0; i <= DWARF_PPC_R31; ++i)
c->loc[i] = DWARF_REG_LOC(i);
c->loc[DWARF_PPC_LR] = DWARF_REG_LOC(DWARF_PPC_LR);
c->loc[DWARF_PPC_CTR] = DWARF_REG_LOC(DWARF_PPC_CTR);
c->loc[DWARF_PPC_CR0] = DWARF_REG_LOC(DWARF_PPC_CR0);
c->loc[DWARF_PPC_CR1] = DWARF_REG_LOC(DWARF_PPC_CR1);
c->loc[DWARF_PPC_CR2] = DWARF_REG_LOC(DWARF_PPC_CR2);
c->loc[DWARF_PPC_CR3] = DWARF_REG_LOC(DWARF_PPC_CR3);
c->loc[DWARF_PPC_CR4] = DWARF_REG_LOC(DWARF_PPC_CR4);
c->loc[DWARF_PPC_XER] = DWARF_REG_LOC(DWARF_PPC_XER);
c->loc[DWARF_PPC_VR0] = DWARF_REG_LOC(DWARF_PPC_VR0);
c->loc[DWARF_PPC_VRSAVE] = DWARF_REG_LOC(DWARF_PPC_VRSAVE);
c->loc[DWARF_PPC_VSCR] = DWARF_REG_LOC(DWARF_PPC_VSCR);
c->loc[DWARF_PPC_FPSCR] = DWARF_REG_LOC(DWARF_PPC_FPSCR);
c->loc[DWARF_PPC_FRAME_POINTER] = DWARF_REG_LOC(DWARF_PPC_FRAME_POINTER);
c->ip = fetch_reg(as->task, PT_LNK);
c->cfa = fetch_reg(as->task, PT_R1);
c->use_prev_instr = 0;
return 0;
}
static int is_signal_frame(struct dwarf_cursor *c)
{
return c->dci.signal_frame;
}
#define BACK_CHAIN 0
#define LR_SAVE 1
int dwarf_arch_step(struct dwarf_addr_space *as)
{
struct dwarf_cursor *c = &as->cursor;
arch_addr_t cfa;
int ret;
if (is_signal_frame(c))
return -DWARF_EBADFRAME;
if ((ret = dwarf_get(as, DWARF_MEM_LOC(c->cfa + BACK_CHAIN * DWARF_ADDR_SIZE(as)), &cfa)) < 0) {
debug(DEBUG_DWARF, "Unable to retrieve CFA from back chain in stack frame - %d", ret);
return ret;
}
if (cfa <= c->cfa || cfa - c->cfa > 128 * 1024)
return -DWARF_EBADFRAME;
c->cfa = cfa;
if ((ret = dwarf_get(as, DWARF_MEM_LOC(c->cfa + LR_SAVE * DWARF_ADDR_SIZE(as)), &c->ip)) < 0) {
debug(DEBUG_DWARF, "Unable to retrieve IP from lr save in stack frame - %d", ret);
return ret;
}
return 0;
}
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg)
{
int regnum;
if (reg >= ARRAY_SIZE(dwarf_to_regnum_map))
return -DWARF_EBADREG;
regnum = dwarf_to_regnum_map[reg];
if (!regnum)
return -DWARF_EBADREG;
return regnum -1;
}
unsigned int dwarf_to_regnum(unsigned int num)
{
if (num < 32)
return DWARF_PPC_R0 + num;
switch(num) {
case R_LR:
return DWARF_PPC_LR;
case R_CTR:
return DWARF_PPC_CTR;
case R_CR0:
return DWARF_PPC_CR0;
case R_CR1:
return DWARF_PPC_CR1;
case R_CR2:
return DWARF_PPC_CR2;
case R_CR3:
return DWARF_PPC_CR3;
case R_CR4:
return DWARF_PPC_CR4;
case R_XER:
return DWARF_PPC_XER;
case R_VR0:
return DWARF_PPC_VR0;
case R_VRSAVE:
return DWARF_PPC_VRSAVE;
case R_VSCR:
return DWARF_PPC_VSCR;
case R_SPEFSCR:
return DWARF_PPC_FPSCR;
case R_FRAME_POINTER:
return DWARF_PPC_FRAME_POINTER;
default:
break;
}
return ~0;
}

View File

@ -0,0 +1,317 @@
/*
* This file is part of mtrace.
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
* This file is based on the ltrace source
* Copyright (C) 2012 Petr Machata, Red Hat Inc.
* Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include "backend.h"
#include "task.h"
#include "arch.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
#define PTRACE_PEEKUSER PTRACE_PEEKUSR
#endif
#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
#define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
static inline unsigned long fix_machine(struct task *task, unsigned long val)
{
if (!task->is_64bit)
val &= 0xffffffff;
return val;
}
arch_addr_t get_instruction_pointer(struct task *task)
{
#ifdef __powerpc64__
return ARCH_ADDR_T(fix_machine(task, task->context.regs.nip));
#else
return ARCH_ADDR_T(task->context.regs.nip);
#endif
}
void set_instruction_pointer(struct task *task, arch_addr_t addr)
{
unsigned long val = (unsigned long)addr;
#ifdef __powerpc64__
val = fix_machine(task, val);
#endif
task->context.regs.nip = val;
if (ptrace(PTRACE_POKEUSER, task->pid, (sizeof(unsigned long) * PT_NIP), val) == -1)
fprintf(stderr, "pid=%d Couldn't set instruction pointer: %s\n", task->pid, strerror(errno));
}
arch_addr_t get_return_addr(struct task *task)
{
#ifdef __powerpc64__
return ARCH_ADDR_T(fix_machine(task, task->context.regs.link));
#endif
return ARCH_ADDR_T(task->context.regs.link);
}
int fetch_context(struct task *task)
{
if (ptrace(PTRACE_GETREGS, task->pid, 0, &task->context.regs) == -1)
fprintf(stderr, "pid=%d Couldn't fetch register context: %s\n", task->pid, strerror(errno));
return 0;
}
void save_param_context(struct task *task)
{
task->saved_context = task->context;
}
#ifdef __powerpc64__
static unsigned long fetch_stack_64(struct task *task, unsigned int param)
{
uint64_t val;
copy_from_proc(task, (void *)task->saved_context.regs.gpr[PT_R1] + (param - 8 + 14) * sizeof(val), &val, sizeof(val));
return val;
}
#endif
static unsigned long fetch_stack_32(struct task *task, unsigned int param)
{
uint32_t val;
copy_from_proc(task, task->saved_context.regs.gpr[PT_R1] + (param - 8 + 2) * sizeof(val), &val, sizeof(val));
return val;
}
unsigned long fetch_param(struct task *task, unsigned int param)
{
unsigned long val;
switch (param) {
case 0:
val = task->saved_context.regs.gpr[PT_R3];
break;
case 1:
val = task->saved_context.regs.gpr[PT_R4];
break;
case 2:
val = task->saved_context.regs.gpr[PT_R5];
break;
case 3:
val = task->saved_context.regs.gpr[PT_R6];
break;
case 4:
val = task->saved_context.regs.gpr[PT_R7];
break;
case 5:
val = task->saved_context.regs.gpr[PT_R8];
break;
case 6:
val = task->saved_context.regs.gpr[PT_R9];
break;
case 7:
val = task->saved_context.regs.gpr[PT_R10];
break;
default:
#ifdef __powerpc64__
if (task->is_64bit) {
val = fetch_stack_64(task, param);
break;
}
#endif
val = fetch_stack_32(task, param);
break;
}
#ifdef __powerpc64__
val = fix_machine(task, val);
#endif
return val;
}
unsigned long fetch_retval(struct task *task)
{
#ifdef __powerpc64__
return fix_machine(task, task->context.regs.gpr[PT_R3]);
#else
return task->context.regs.gpr[PT_R3];
#endif
}
unsigned long fetch_reg(struct task *task, unsigned int reg)
{
unsigned long val;
switch(reg) {
case PT_R0:
val = task->context.regs.gpr[PT_R0];
break;
case PT_R1:
val = task->context.regs.gpr[PT_R1];
break;
case PT_R2:
val = task->context.regs.gpr[PT_R2];
break;
case PT_R3:
val = task->context.regs.gpr[PT_R3];
break;
case PT_R4:
val = task->context.regs.gpr[PT_R4];
break;
case PT_R5:
val = task->context.regs.gpr[PT_R5];
break;
case PT_R6:
val = task->context.regs.gpr[PT_R6];
break;
case PT_R7:
val = task->context.regs.gpr[PT_R7];
break;
case PT_R8:
val = task->context.regs.gpr[PT_R8];
break;
case PT_R9:
val = task->context.regs.gpr[PT_R9];
break;
case PT_R10:
val = task->context.regs.gpr[PT_R10];
break;
case PT_R11:
val = task->context.regs.gpr[PT_R11];
break;
case PT_R12:
val = task->context.regs.gpr[PT_R12];
break;
case PT_R13:
val = task->context.regs.gpr[PT_R13];
break;
case PT_R14:
val = task->context.regs.gpr[PT_R14];
break;
case PT_R15:
val = task->context.regs.gpr[PT_R15];
break;
case PT_R16:
val = task->context.regs.gpr[PT_R16];
break;
case PT_R17:
val = task->context.regs.gpr[PT_R17];
break;
case PT_R18:
val = task->context.regs.gpr[PT_R18];
break;
case PT_R19:
val = task->context.regs.gpr[PT_R19];
break;
case PT_R20:
val = task->context.regs.gpr[PT_R20];
break;
case PT_R21:
val = task->context.regs.gpr[PT_R21];
break;
case PT_R22:
val = task->context.regs.gpr[PT_R22];
break;
case PT_R23:
val = task->context.regs.gpr[PT_R23];
break;
case PT_R24:
val = task->context.regs.gpr[PT_R24];
break;
case PT_R25:
val = task->context.regs.gpr[PT_R25];
break;
case PT_R26:
val = task->context.regs.gpr[PT_R26];
break;
case PT_R27:
val = task->context.regs.gpr[PT_R27];
break;
case PT_R28:
val = task->context.regs.gpr[PT_R28];
break;
case PT_R29:
val = task->context.regs.gpr[PT_R29];
break;
case PT_R30:
val = task->context.regs.gpr[PT_R30];
break;
case PT_R31:
val = task->context.regs.gpr[PT_R31];
break;
case PT_NIP:
val = task->context.regs.nip;
break;
case PT_MSR:
val = task->context.regs.msr;
break;
case PT_ORIG_R3:
val = task->context.regs.orig_gpr3;
break;
case PT_CTR:
val = task->context.regs.ctr;
break;
case PT_LNK:
val = task->context.regs.link;
break;
case PT_XER:
val = task->context.regs.xer;
break;
case PT_CCR:
val = task->context.regs.ccr;
break;
#ifndef __powerpc64__
case PT_MQ:
val = task->context.regs.mq;
break;
#else
case PT_SOFTE:
val = task->context.regs.softe;
break;
#endif
case PT_TRAP:
val = task->context.regs.trap;
break;
case PT_DAR:
val = task->context.regs.dar;
break;
case PT_DSISR:
val = task->context.regs.dsisr;
break;
case PT_RESULT:
val = task->context.regs.result;
break;
default:
abort();
}
return fix_machine(task, val);
}

Some files were not shown because too many files have changed in this diff Show More