mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-12 22:24:53 +00:00
We no longer need a complete spare copy of V hanging off the Vex tree.
git-svn-id: svn://svn.valgrind.org/vex/trunk@1047
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
acinclude.m4
|
||||
aclocal.m4
|
||||
configure
|
||||
config.h*
|
||||
stamp-h*
|
||||
valgrind
|
||||
valgrind.spec
|
||||
cachegrind
|
||||
vg_annotate
|
||||
vg_cachegen
|
||||
default.supp
|
||||
bin
|
||||
lib
|
||||
include
|
||||
share
|
||||
cachegrind.out.*
|
||||
autom4te.cache
|
||||
autom4te-*.cache
|
||||
valgrind.pc
|
||||
.in_place
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
The following people contributed in some way to valgrind, during its
|
||||
long journey over the past two years or so. Here's a list. If I have
|
||||
forgotten you, I do apologise; let me know (jseward@acm.org) and I'll
|
||||
fix it.
|
||||
|
||||
Donna Robinson <donna@muraroa.demon.co.uk>
|
||||
for many reasons, including endless encouragement, and
|
||||
persuading me I wasn't crazy to try doing this
|
||||
|
||||
Rob Noble <rob.noble@antlimited.com>
|
||||
for early encouragement, support, suggestions, and asking of
|
||||
many questions
|
||||
|
||||
Reuben Thomas <rrt@sc3d.org>
|
||||
for discussions about value tag operations, and making me
|
||||
laugh
|
||||
|
||||
Various KDE folks, for suffering recent versions of valgrind,
|
||||
providing many patches, questions and helpful feedback
|
||||
Dirk Mueller <mueller@kde.org>
|
||||
Stephan Kulow <coolo@kde.org>
|
||||
Michael Matz <matz@kde.org>
|
||||
Simon Hausmann <hausmann@kde.org>
|
||||
David Faure <david@mandrakesoft.com>
|
||||
Ellis Whitehead <kde@ellisw.net>
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
Julian Seward, jseward@acm.org, was the original author, creating the
|
||||
dynamic translation framework, memcheck stuff, and the
|
||||
signal/syscall/threads support gunk.
|
||||
|
||||
Nicholas Nethercote, njn25@cam.ac.uk, did the core/tool
|
||||
generalisation, and wrote Cachegrind and some of the other tools, and
|
||||
tons of other stuff, including code generation improvments.
|
||||
|
||||
Jeremy Fitzhardinge, jeremy@goop.org, wrote Helgrind, and lots of
|
||||
syscall/signal simulation stuff, including a complete redesign of how
|
||||
syscalls and signals are handled. Also code generation improvements.
|
||||
|
||||
Tom Hughes, thh@cyberscience.com, did a vast number of bug fixes, and
|
||||
helped out with support for more recent Linux/glibc versions.
|
||||
|
||||
Robert Walsh, rjwalsh@durables.org, added file descriptor leakage
|
||||
checking, new library interception machinery, support for client
|
||||
allocation pools, and minor other tweakage.
|
||||
|
||||
readelf's dwarf2 source line reader, written by Nick Clifton, was
|
||||
modified to be used in Valgrind by Daniel Berlin.
|
||||
|
||||
Michael Matz and Simon Hausmann modified the GNU binutils
|
||||
demangler(s) for use in Valgrind.
|
||||
|
||||
Dirk Mueller contrib'd the malloc-free mismatch checking stuff,
|
||||
and other bits and pieces.
|
||||
|
||||
Lots of other people sent bug reports, patches, and very
|
||||
helpful feedback. I thank you all.
|
||||
|
||||
@@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 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.
|
||||
@@ -1,43 +0,0 @@
|
||||
/.cvsignore/1.7/Tue Mar 23 19:52:03 2004//
|
||||
/ACKNOWLEDGEMENTS/1.1.1.1/Fri Mar 22 01:29:20 2002//
|
||||
/AUTHORS/1.8/Tue Jul 20 14:18:51 2004//
|
||||
/COPYING/1.1.1.1/Fri Mar 22 01:27:57 2002//
|
||||
/FAQ.txt/1.23/Sun Jul 18 10:35:36 2004//
|
||||
/INSTALL/1.1.1.1/Fri Mar 22 01:28:00 2002//
|
||||
/Makefile.all.am/1.1/Wed Sep 1 23:20:46 2004//
|
||||
/Makefile.am/1.71/Sat Oct 9 15:59:05 2004//
|
||||
/Makefile.core-AM_CPPFLAGS.am/1.3/Fri Sep 10 14:23:58 2004//
|
||||
/Makefile.tool-flags.am/1.2/Sat Sep 11 18:27:43 2004//
|
||||
/Makefile.tool-inplace.am/1.1/Wed Sep 1 23:20:46 2004//
|
||||
/Makefile.tool.am/1.3/Sat Sep 11 16:45:24 2004//
|
||||
/NEWS/1.26/Tue Aug 31 00:14:02 2004//
|
||||
/NOTES.syscalls/1.1/Mon Oct 13 22:26:54 2003//
|
||||
/README/1.19/Wed Apr 21 09:17:19 2004//
|
||||
/README_DEVELOPERS/1.3/Sat Oct 9 15:59:05 2004//
|
||||
/README_MISSING_SYSCALL_OR_IOCTL/1.8/Fri Sep 10 14:23:58 2004//
|
||||
/README_PACKAGERS/1.5/Tue Aug 24 13:56:54 2004//
|
||||
/TODO/1.2/Tue Jun 18 16:31:21 2002//
|
||||
/autogen.sh/1.3/Tue Dec 16 02:15:21 2003//
|
||||
/configure.in/1.129/Mon Oct 18 18:07:48 2004//
|
||||
/glibc-2.1.supp/1.11/Sun Apr 25 12:02:31 2004//
|
||||
/glibc-2.2.supp/1.25/Sat Jul 17 14:16:03 2004//
|
||||
/glibc-2.3.supp/1.15/Tue Jul 20 22:42:44 2004//
|
||||
/make-uninstall-docs/1.2/Fri Nov 14 17:47:51 2003//
|
||||
/valgrind.pc.in/1.2/Thu Oct 14 10:22:19 2004//
|
||||
/valgrind.spec.in/1.16/Fri Sep 3 13:45:26 2004//
|
||||
/xfree-3.supp/1.6/Fri Nov 14 17:47:51 2003//
|
||||
/xfree-4.supp/1.9/Fri Nov 14 17:47:51 2003//
|
||||
D/addrcheck////
|
||||
D/auxprogs////
|
||||
D/cachegrind////
|
||||
D/corecheck////
|
||||
D/coregrind////
|
||||
D/docs////
|
||||
D/helgrind////
|
||||
D/include////
|
||||
D/lackey////
|
||||
D/massif////
|
||||
D/memcheck////
|
||||
D/nightly////
|
||||
D/none////
|
||||
D/tests////
|
||||
@@ -1 +0,0 @@
|
||||
valgrind
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,437 +0,0 @@
|
||||
Valgrind FAQ, version 2.1.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Last revised 18 July 2004
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. Background
|
||||
2. Compiling, installing and configuring
|
||||
3. Valgrind aborts unexpectedly
|
||||
4. Valgrind behaves unexpectedly
|
||||
5. Memcheck doesn't find my bug
|
||||
6. Miscellaneous
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
1. Background
|
||||
-----------------------------------------------------------------
|
||||
|
||||
1.1. How do you pronounce "Valgrind"?
|
||||
|
||||
The "Val" as in the world "value". The "grind" is pronounced with a
|
||||
short 'i' -- ie. "grinned" (rhymes with "tinned") rather than "grined"
|
||||
(rhymes with "find").
|
||||
|
||||
Don't feel bad: almost everyone gets it wrong at first.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
1.2. Where does the name "Valgrind" come from?
|
||||
|
||||
From Nordic mythology. Originally (before release) the project was
|
||||
named Heimdall, after the watchman of the Nordic gods. He could "see a
|
||||
hundred miles by day or night, hear the grass growing, see the wool
|
||||
growing on a sheep's back" (etc). This would have been a great name,
|
||||
but it was already taken by a security package "Heimdal".
|
||||
|
||||
Keeping with the Nordic theme, Valgrind was chosen. Valgrind is the
|
||||
name of the main entrance to Valhalla (the Hall of the Chosen Slain in
|
||||
Asgard). Over this entrance there resides a wolf and over it there is
|
||||
the head of a boar and on it perches a huge eagle, whose eyes can see to
|
||||
the far regions of the nine worlds. Only those judged worthy by the
|
||||
guardians are allowed to pass through Valgrind. All others are refused
|
||||
entrance.
|
||||
|
||||
It's not short for "value grinder", although that's not a bad guess.
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
2. Compiling, installing and configuring
|
||||
-----------------------------------------------------------------
|
||||
|
||||
2.1. When I trying building Valgrind, 'make' dies partway with an
|
||||
assertion failure, something like this: make: expand.c:489:
|
||||
|
||||
allocated_variable_append: Assertion
|
||||
`current_variable_set_list->next != 0' failed.
|
||||
|
||||
It's probably a bug in 'make'. Some, but not all, instances of version 3.79.1
|
||||
have this bug, see www.mail-archive.com/bug-make@gnu.org/msg01658.html. Try
|
||||
upgrading to a more recent version of 'make'. Alternatively, we have heard
|
||||
that unsetting the CFLAGS environment variable avoids the problem.
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
3. Valgrind aborts unexpectedly
|
||||
-----------------------------------------------------------------
|
||||
|
||||
3.1. Programs run OK on Valgrind, but at exit produce a bunch of errors a bit
|
||||
like this
|
||||
|
||||
==20755== Invalid read of size 4
|
||||
==20755== at 0x40281C8A: _nl_unload_locale (loadlocale.c:238)
|
||||
==20755== by 0x4028179D: free_mem (findlocale.c:257)
|
||||
==20755== by 0x402E0962: __libc_freeres (set-freeres.c:34)
|
||||
==20755== by 0x40048DCC: vgPlain___libc_freeres_wrapper
|
||||
(vg_clientfuncs.c:585)
|
||||
==20755== Address 0x40CC304C is 8 bytes inside a block of size 380 free'd
|
||||
==20755== at 0x400484C9: free (vg_clientfuncs.c:180)
|
||||
==20755== by 0x40281CBA: _nl_unload_locale (loadlocale.c:246)
|
||||
==20755== by 0x40281218: free_mem (setlocale.c:461)
|
||||
==20755== by 0x402E0962: __libc_freeres (set-freeres.c:34)
|
||||
|
||||
and then die with a segmentation fault.
|
||||
|
||||
When the program exits, Valgrind runs the procedure __libc_freeres() in
|
||||
glibc. This is a hook for memory debuggers, so they can ask glibc to
|
||||
free up any memory it has used. Doing that is needed to ensure that
|
||||
Valgrind doesn't incorrectly report space leaks in glibc.
|
||||
|
||||
Problem is that running __libc_freeres() in older glibc versions causes
|
||||
this crash.
|
||||
|
||||
WORKAROUND FOR 1.1.X and later versions of Valgrind: use the
|
||||
--run-libc-freeres=no flag. You may then get space leak reports for
|
||||
glibc-allocations (please _don't_ report these to the glibc people,
|
||||
since they are not real leaks), but at least the program runs.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
3.2. My (buggy) program dies like this:
|
||||
valgrind: vg_malloc2.c:442 (bszW_to_pszW):
|
||||
Assertion `pszW >= 0' failed.
|
||||
|
||||
If Memcheck (the memory checker) shows any invalid reads, invalid writes
|
||||
and invalid frees in your program, the above may happen. Reason is that
|
||||
your program may trash Valgrind's low-level memory manager, which then
|
||||
dies with the above assertion, or something like this. The cure is to
|
||||
fix your program so that it doesn't do any illegal memory accesses. The
|
||||
above failure will hopefully go away after that.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
3.3. My program dies, printing a message like this along the way:
|
||||
|
||||
disInstr: unhandled instruction bytes: 0x66 0xF 0x2E 0x5
|
||||
|
||||
Older versions did not support some x86 instructions, particularly
|
||||
SSE/SSE2 instructions. Try a newer Valgrind; we now support almost all
|
||||
instructions. If it still happens with newer versions, if the failing
|
||||
instruction is an SSE/SSE2 instruction, you might be able to recompile
|
||||
your program without it by using the flag -march to gcc. Either way,
|
||||
let us know and we'll try to fix it.
|
||||
|
||||
Another possibility is that your program has a bug and erroneously jumps
|
||||
to a non-code address, in which case you'll get a SIGILL signal.
|
||||
Memcheck/Addrcheck may issue a warning just before this happens, but they
|
||||
might not if the jump happens to land in addressable memory.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
3.4. My program dies like this:
|
||||
|
||||
error: /lib/librt.so.1: symbol __pthread_clock_settime, version
|
||||
GLIBC_PRIVATE not defined in file libpthread.so.0 with link time
|
||||
reference
|
||||
|
||||
This is a total swamp. Nevertheless there is a way out. It's a problem
|
||||
which is not easy to fix. Really the problem is that /lib/librt.so.1
|
||||
refers to some symbols __pthread_clock_settime and
|
||||
__pthread_clock_gettime in /lib/libpthread.so which are not intended to
|
||||
be exported, ie they are private.
|
||||
|
||||
Best solution is to ensure your program does not use /lib/librt.so.1.
|
||||
|
||||
However .. since you're probably not using it directly, or even
|
||||
knowingly, that's hard to do. You might instead be able to fix it by
|
||||
playing around with coregrind/vg_libpthread.vs. Things to try:
|
||||
|
||||
Remove this
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
__pthread_clock_gettime;
|
||||
__pthread_clock_settime;
|
||||
};
|
||||
|
||||
or maybe remove this
|
||||
|
||||
GLIBC_2.2.3 {
|
||||
__pthread_clock_gettime;
|
||||
__pthread_clock_settime;
|
||||
} GLIBC_2.2;
|
||||
|
||||
or maybe add this
|
||||
|
||||
GLIBC_2.2.4 {
|
||||
__pthread_clock_gettime;
|
||||
__pthread_clock_settime;
|
||||
} GLIBC_2.2;
|
||||
|
||||
GLIBC_2.2.5 {
|
||||
__pthread_clock_gettime;
|
||||
__pthread_clock_settime;
|
||||
} GLIBC_2.2;
|
||||
|
||||
or some combination of the above. After each change you need to delete
|
||||
coregrind/libpthread.so and do make && make install.
|
||||
|
||||
I just don't know if any of the above will work. If you can find a
|
||||
solution which works, I would be interested to hear it.
|
||||
|
||||
To which someone replied:
|
||||
|
||||
I deleted this:
|
||||
|
||||
GLIBC_2.2.3 {
|
||||
__pthread_clock_gettime;
|
||||
__pthread_clock_settime;
|
||||
} GLIBC_2.2;
|
||||
|
||||
and it worked.
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
4. Valgrind behaves unexpectedly
|
||||
-----------------------------------------------------------------
|
||||
|
||||
4.1. I try running "valgrind my_program", but my_program runs normally,
|
||||
and Valgrind doesn't emit any output at all.
|
||||
|
||||
For versions prior to 2.1.1:
|
||||
|
||||
Valgrind doesn't work out-of-the-box with programs that are entirely
|
||||
statically linked. It does a quick test at startup, and if it detects
|
||||
that the program is statically linked, it aborts with an explanation.
|
||||
|
||||
This test may fail in some obscure cases, eg. if you run a script under
|
||||
Valgrind and the script interpreter is statically linked.
|
||||
|
||||
If you still want static linking, you can ask gcc to link certain
|
||||
libraries statically. Try the following options:
|
||||
|
||||
-Wl,-Bstatic -lmyLibrary1 -lotherLibrary -Wl,-Bdynamic
|
||||
|
||||
Just make sure you end with -Wl,-Bdynamic so that libc is dynamically
|
||||
linked.
|
||||
|
||||
If you absolutely cannot use dynamic libraries, you can try statically
|
||||
linking together all the .o files in coregrind/, all the .o files of the
|
||||
tool of your choice (eg. those in memcheck/), and the .o files of your
|
||||
program. You'll end up with a statically linked binary that runs
|
||||
permanently under Valgrind's control. Note that we haven't tested this
|
||||
procedure thoroughly.
|
||||
|
||||
|
||||
For versions 2.1.1 and later:
|
||||
|
||||
Valgrind does now work with static binaries, although beware that some
|
||||
of the tools won't operate as well as normal, because they have access
|
||||
to less information about how the program runs. Eg. Memcheck will miss
|
||||
some errors that it would otherwise find. This is because Valgrind
|
||||
doesn't replace malloc() and friends with its own versions. It's best
|
||||
if your program is dynamically linked with glibc.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
4.2. My threaded server process runs unbelievably slowly on Valgrind.
|
||||
So slowly, in fact, that at first I thought it had completely
|
||||
locked up.
|
||||
|
||||
We are not completely sure about this, but one possibility is that
|
||||
laptops with power management fool Valgrind's timekeeping mechanism,
|
||||
which is (somewhat in error) based on the x86 RDTSC instruction. A
|
||||
"fix" which is claimed to work is to run some other cpu-intensive
|
||||
process at the same time, so that the laptop's power-management
|
||||
clock-slowing does not kick in. We would be interested in hearing more
|
||||
feedback on this.
|
||||
|
||||
Another possible cause is that versions prior to 1.9.6 did not support
|
||||
threading on glibc 2.3.X systems well. Hopefully the situation is much
|
||||
improved with 1.9.6 and later versions.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
4.3. My program uses the C++ STL and string classes. Valgrind
|
||||
reports 'still reachable' memory leaks involving these classes
|
||||
at the exit of the program, but there should be none.
|
||||
|
||||
First of all: relax, it's probably not a bug, but a feature. Many
|
||||
implementations of the C++ standard libraries use their own memory pool
|
||||
allocators. Memory for quite a number of destructed objects is not
|
||||
immediately freed and given back to the OS, but kept in the pool(s) for
|
||||
later re-use. The fact that the pools are not freed at the exit() of
|
||||
the program cause Valgrind to report this memory as still reachable.
|
||||
The behaviour not to free pools at the exit() could be called a bug of
|
||||
the library though.
|
||||
|
||||
Using gcc, you can force the STL to use malloc and to free memory as
|
||||
soon as possible by globally disabling memory caching. Beware! Doing
|
||||
so will probably slow down your program, sometimes drastically.
|
||||
|
||||
- With gcc 2.91, 2.95, 3.0 and 3.1, compile all source using the STL
|
||||
with -D__USE_MALLOC. Beware! This is removed from gcc starting with
|
||||
version 3.3.
|
||||
|
||||
- With 3.2.2 and later, you should export the environment variable
|
||||
GLIBCPP_FORCE_NEW before running your program.
|
||||
|
||||
There are other ways to disable memory pooling: using the malloc_alloc
|
||||
template with your objects (not portable, but should work for gcc) or
|
||||
even writing your own memory allocators. But all this goes beyond the
|
||||
scope of this FAQ. Start by reading
|
||||
http://gcc.gnu.org/onlinedocs/libstdc++/ext/howto.html#3 if you
|
||||
absolutely want to do that. But beware:
|
||||
|
||||
1) there are currently changes underway for gcc which are not totally
|
||||
reflected in the docs right now ("now" == 26 Apr 03)
|
||||
|
||||
2) allocators belong to the more messy parts of the STL and people went
|
||||
at great lengths to make it portable across platforms. Chances are
|
||||
good that your solution will work on your platform, but not on
|
||||
others.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
4.4. The stack traces given by Memcheck (or another tool) aren't helpful.
|
||||
How can I improve them?
|
||||
|
||||
If they're not long enough, use --num-callers to make them longer.
|
||||
|
||||
If they're not detailed enough, make sure you are compiling with -g to add
|
||||
debug information. And don't strip symbol tables (programs should be
|
||||
unstripped unless you run 'strip' on them; some libraries ship stripped).
|
||||
|
||||
Also, -fomit-frame-pointer and -fstack-check can make stack traces worse.
|
||||
|
||||
Some example sub-traces:
|
||||
|
||||
With debug information and unstripped (best):
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x80483BF: really (malloc1.c:20)
|
||||
by 0x8048370: main (malloc1.c:9)
|
||||
|
||||
With no debug information, unstripped:
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x80483BF: really (in /auto/homes/njn25/grind/head5/a.out)
|
||||
by 0x8048370: main (in /auto/homes/njn25/grind/head5/a.out)
|
||||
|
||||
With no debug information, stripped:
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x80483BF: (within /auto/homes/njn25/grind/head5/a.out)
|
||||
by 0x8048370: (within /auto/homes/njn25/grind/head5/a.out)
|
||||
by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
|
||||
by 0x80482CC: (within /auto/homes/njn25/grind/head5/a.out)
|
||||
|
||||
With debug information and -fomit-frame-pointer:
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x80483C4: really (malloc1.c:20)
|
||||
by 0x42015703: __libc_start_main (in /lib/tls/libc-2.3.2.so)
|
||||
by 0x80482CC: ??? (start.S:81)
|
||||
|
||||
-----------------------------------------------------------------
|
||||
5. Memcheck doesn't find my bug
|
||||
-----------------------------------------------------------------
|
||||
|
||||
5.1. I try running "valgrind --tool=memcheck my_program" and get
|
||||
Valgrind's startup message, but I don't get any errors and I know
|
||||
my program has errors.
|
||||
|
||||
By default, Valgrind only traces the top-level process. So if your
|
||||
program spawns children, they won't be traced by Valgrind by default.
|
||||
Also, if your program is started by a shell script, Perl script, or
|
||||
something similar, Valgrind will trace the shell, or the Perl
|
||||
interpreter, or equivalent.
|
||||
|
||||
To trace child processes, use the --trace-children=yes option.
|
||||
|
||||
If you are tracing large trees of processes, it can be less disruptive
|
||||
to have the output sent over the network. Give Valgrind the flag
|
||||
--log-socket=127.0.0.1:12345 (if you want logging output sent to port
|
||||
12345 on localhost). You can use the valgrind-listener program to
|
||||
listen on that port:
|
||||
|
||||
valgrind-listener 12345
|
||||
|
||||
Obviously you have to start the listener process first. See the
|
||||
documentation for more details.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
5.2. Why doesn't Memcheck find the array overruns in this program?
|
||||
|
||||
int static[5];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int stack[5];
|
||||
|
||||
static[5] = 0;
|
||||
stack [5] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Unfortunately, Memcheck doesn't do bounds checking on static or stack
|
||||
arrays. We'd like to, but it's just not possible to do in a reasonable
|
||||
way that fits with how Memcheck works. Sorry.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
5.3. My program dies with a segmentation fault, but Memcheck doesn't give
|
||||
any error messages before it, or none that look related.
|
||||
|
||||
One possibility is that your program accesses to memory with
|
||||
inappropriate permissions set, such as writing to read-only memory.
|
||||
Maybe your program is writing to a static string like this:
|
||||
|
||||
char* s = "hello";
|
||||
s[0] = 'j';
|
||||
|
||||
or something similar. Writing to read-only memory can also apparently
|
||||
make LinuxThreads behave strangely.
|
||||
|
||||
|
||||
-----------------------------------------------------------------
|
||||
6. Miscellaneous
|
||||
-----------------------------------------------------------------
|
||||
|
||||
6.1. I tried writing a suppression but it didn't work. Can you
|
||||
write my suppression for me?
|
||||
|
||||
Yes! Use the --gen-suppressions=yes feature to spit out suppressions
|
||||
automatically for you. You can then edit them if you like, eg.
|
||||
combining similar automatically generated suppressions using wildcards
|
||||
like '*'.
|
||||
|
||||
If you really want to write suppressions by hand, read the manual
|
||||
carefully. Note particularly that C++ function names must be _mangled_.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
6.2. With Memcheck/Addrcheck's memory leak detector, what's the
|
||||
difference between "definitely lost", "possibly lost", "still
|
||||
reachable", and "suppressed"?
|
||||
|
||||
The details are in section 3.6 of the manual.
|
||||
|
||||
In short:
|
||||
|
||||
- "definitely lost" means your program is leaking memory -- fix it!
|
||||
|
||||
- "possibly lost" means your program is probably leaking memory,
|
||||
unless you're doing funny things with pointers.
|
||||
|
||||
- "still reachable" means your program is probably ok -- it didn't
|
||||
free some memory it could have. This is quite common and often
|
||||
reasonable. Don't use --show-reachable=yes if you don't want to see
|
||||
these reports.
|
||||
|
||||
- "suppressed" means that a leak error has been suppressed. There are
|
||||
some suppressions in the default suppression files. You can ignore
|
||||
suppressed errors.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
(this is the end of the FAQ.)
|
||||
@@ -1,182 +0,0 @@
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
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, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
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 at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' 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. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. 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.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. 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.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
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 must use a version of `make' that
|
||||
supports the `VPATH' variable, such as 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 `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have 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.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' 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.
|
||||
|
||||
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'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
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.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
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 host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
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.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--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.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
## This file should be included by *every* Makefile.am, except those for docs/
|
||||
## and tests/ subdirectories.
|
||||
|
||||
valdir = $(libdir)/valgrind
|
||||
inplacedir = $(top_builddir)/.in_place
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.6 dist-bzip2
|
||||
|
||||
include $(top_srcdir)/Makefile.all.am
|
||||
|
||||
## include must be first for tool.h
|
||||
## addrcheck must come after memcheck, for mac_*.o
|
||||
SUBDIRS = include coregrind . docs tests auxprogs \
|
||||
memcheck \
|
||||
addrcheck \
|
||||
cachegrind \
|
||||
corecheck \
|
||||
helgrind \
|
||||
massif \
|
||||
lackey \
|
||||
none
|
||||
|
||||
SUPP_FILES = \
|
||||
glibc-2.1.supp glibc-2.2.supp glibc-2.3.supp \
|
||||
xfree-3.supp xfree-4.supp
|
||||
|
||||
dist_val_DATA = $(SUPP_FILES) default.supp
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = valgrind.pc
|
||||
|
||||
BUILT_SOURCES = default.supp valgrind.pc
|
||||
|
||||
DISTCLEANFILES = default.supp
|
||||
|
||||
default.supp: $(SUPP_FILES)
|
||||
|
||||
## Preprend @PERL@ because tests/vg_regtest isn't executable
|
||||
regtest: check
|
||||
@PERL@ tests/vg_regtest --all
|
||||
|
||||
EXTRA_DIST = \
|
||||
FAQ.txt \
|
||||
ACKNOWLEDGEMENTS \
|
||||
README_DEVELOPERS \
|
||||
README_PACKAGERS \
|
||||
README_MISSING_SYSCALL_OR_IOCTL TODO \
|
||||
valgrind.spec.in valgrind.pc.in \
|
||||
Makefile.all.am Makefile.tool.am Makefile.core-AM_CPPFLAGS.am \
|
||||
Makefile.tool-inplace.am
|
||||
|
||||
install-exec-hook:
|
||||
$(mkinstalldirs) $(DESTDIR)$(valdir)
|
||||
rm -f $(DESTDIR)$(valdir)/libpthread.so.0
|
||||
$(LN_S) libpthread.so $(DESTDIR)$(valdir)/libpthread.so.0
|
||||
|
||||
all-local:
|
||||
mkdir -p $(inplacedir)
|
||||
rm -f $(addprefix $(inplacedir)/,default.supp $(SUPP_FILES))
|
||||
ln -s ../default.supp $(inplacedir)
|
||||
ln -s $(addprefix ../$(top_srcdir)/,$(SUPP_FILES)) $(inplacedir)
|
||||
|
||||
distclean-local:
|
||||
rm -rf $(inplacedir)
|
||||
@@ -1,8 +0,0 @@
|
||||
add_includes = -I$(top_builddir)/coregrind -I$(top_srcdir)/coregrind \
|
||||
-I$(top_srcdir)/coregrind/$(VG_ARCH) \
|
||||
-I$(top_srcdir)/coregrind/$(VG_PLATFORM) \
|
||||
-I$(top_builddir)/include -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/include/$(VG_ARCH)
|
||||
|
||||
AM_CPPFLAGS = $(add_includes)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
## Need $(top_builddir)/include because tool.h is built from tool.h.base;
|
||||
## otherwise it will not work if builddir != srcdir.
|
||||
add_includes = -I$(top_builddir)/include -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/include/$(VG_ARCH)
|
||||
|
||||
AM_CPPFLAGS = $(add_includes)
|
||||
AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O \
|
||||
@PREFERRED_STACK_BOUNDARY@ -g
|
||||
AM_CCASFLAGS = $(add_includes)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
all-local:
|
||||
mkdir -p $(inplacedir)
|
||||
-rm -f $(addprefix $(inplacedir)/,$(val_PROGRAMS))
|
||||
ln -f -s $(addprefix ../$(subdir)/,$(val_PROGRAMS)) $(inplacedir)
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
SUBDIRS = . tests docs
|
||||
|
||||
include $(top_srcdir)/Makefile.all.am
|
||||
include $(top_srcdir)/Makefile.tool-flags.am
|
||||
include $(top_srcdir)/Makefile.tool-inplace.am
|
||||
@@ -1,739 +0,0 @@
|
||||
|
||||
Stable release 2.2.0 (31 August 2004) -- CHANGES RELATIVE TO 2.0.0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
2.2.0 brings nine months worth of improvements and bug fixes. We
|
||||
believe it to be a worthy successor to 2.0.0. There are literally
|
||||
hundreds of bug fixes and minor improvements. There are also some
|
||||
fairly major user-visible changes:
|
||||
|
||||
* A complete overhaul of handling of system calls and signals, and
|
||||
their interaction with threads. In general, the accuracy of the
|
||||
system call, thread and signal simulations is much improved:
|
||||
|
||||
- Blocking system calls behave exactly as they do when running
|
||||
natively (not on valgrind). That is, if a syscall blocks only the
|
||||
calling thread when running natively, than it behaves the same on
|
||||
valgrind. No more mysterious hangs because V doesn't know that some
|
||||
syscall or other, should block only the calling thread.
|
||||
|
||||
- Interrupted syscalls should now give more faithful results.
|
||||
|
||||
- Signal contexts in signal handlers are supported.
|
||||
|
||||
* Improvements to NPTL support to the extent that V now works
|
||||
properly on NPTL-only setups.
|
||||
|
||||
* Greater isolation between Valgrind and the program being run, so
|
||||
the program is less likely to inadvertently kill Valgrind by
|
||||
doing wild writes.
|
||||
|
||||
* Massif: a new space profiling tool. Try it! It's cool, and it'll
|
||||
tell you in detail where and when your C/C++ code is allocating heap.
|
||||
Draws pretty .ps pictures of memory use against time. A potentially
|
||||
powerful tool for making sense of your program's space use.
|
||||
|
||||
* File descriptor leakage checks. When enabled, Valgrind will print out
|
||||
a list of open file descriptors on exit.
|
||||
|
||||
* Improved SSE2/SSE3 support.
|
||||
|
||||
* Time-stamped output; use --time-stamp=yes
|
||||
|
||||
|
||||
|
||||
Stable release 2.2.0 (31 August 2004) -- CHANGES RELATIVE TO 2.1.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
2.2.0 is not much different from 2.1.2, released seven weeks ago.
|
||||
A number of bugs have been fixed, most notably #85658, which gave
|
||||
problems for quite a few people. There have been many internal
|
||||
cleanups, but those are not user visible.
|
||||
|
||||
The following bugs have been fixed since 2.1.2:
|
||||
|
||||
85658 Assert in coregrind/vg_libpthread.c:2326 (open64) !=
|
||||
(void*)0 failed
|
||||
This bug was reported multiple times, and so the following
|
||||
duplicates of it are also fixed: 87620, 85796, 85935, 86065,
|
||||
86919, 86988, 87917, 88156
|
||||
|
||||
80716 Semaphore mapping bug caused by unmap (sem_destroy)
|
||||
(Was fixed prior to 2.1.2)
|
||||
|
||||
86987 semctl and shmctl syscalls family is not handled properly
|
||||
|
||||
86696 valgrind 2.1.2 + RH AS2.1 + librt
|
||||
|
||||
86730 valgrind locks up at end of run with assertion failure
|
||||
in __pthread_unwind
|
||||
|
||||
86641 memcheck doesn't work with Mesa OpenGL/ATI on Suse 9.1
|
||||
(also fixes 74298, a duplicate of this)
|
||||
|
||||
85947 MMX/SSE unhandled instruction 'sfence'
|
||||
|
||||
84978 Wrong error "Conditional jump or move depends on
|
||||
uninitialised value" resulting from "sbbl %reg, %reg"
|
||||
|
||||
86254 ssort() fails when signed int return type from comparison is
|
||||
too small to handle result of unsigned int subtraction
|
||||
|
||||
87089 memalign( 4, xxx) makes valgrind assert
|
||||
|
||||
86407 Add support for low-level parallel port driver ioctls.
|
||||
|
||||
70587 Add timestamps to Valgrind output? (wishlist)
|
||||
|
||||
84937 vg_libpthread.c:2505 (se_remap): Assertion `res == 0'
|
||||
(fixed prior to 2.1.2)
|
||||
|
||||
86317 cannot load libSDL-1.2.so.0 using valgrind
|
||||
|
||||
86989 memcpy from mac_replace_strmem.c complains about
|
||||
uninitialized pointers passed when length to copy is zero
|
||||
|
||||
85811 gnu pascal symbol causes segmentation fault; ok in 2.0.0
|
||||
|
||||
79138 writing to sbrk()'d memory causes segfault
|
||||
|
||||
77369 sched deadlock while signal received during pthread_join
|
||||
and the joined thread exited
|
||||
|
||||
88115 In signal handler for SIGFPE, siginfo->si_addr is wrong
|
||||
under Valgrind
|
||||
|
||||
78765 Massif crashes on app exit if FP exceptions are enabled
|
||||
|
||||
Additionally there are the following changes, which are not
|
||||
connected to any bug report numbers, AFAICS:
|
||||
|
||||
* Fix scary bug causing mis-identification of SSE stores vs
|
||||
loads and so causing memcheck to sometimes give nonsense results
|
||||
on SSE code.
|
||||
|
||||
* Add support for the POSIX message queue system calls.
|
||||
|
||||
* Fix to allow 32-bit Valgrind to run on AMD64 boxes. Note: this does
|
||||
NOT allow Valgrind to work with 64-bit executables - only with 32-bit
|
||||
executables on an AMD64 box.
|
||||
|
||||
* At configure time, only check whether linux/mii.h can be processed
|
||||
so that we don't generate ugly warnings by trying to compile it.
|
||||
|
||||
* Add support for POSIX clocks and timers.
|
||||
|
||||
|
||||
|
||||
Developer (cvs head) release 2.1.2 (18 July 2004)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
2.1.2 contains four months worth of bug fixes and refinements.
|
||||
Although officially a developer release, we believe it to be stable
|
||||
enough for widespread day-to-day use. 2.1.2 is pretty good, so try it
|
||||
first, although there is a chance it won't work. If so then try 2.0.0
|
||||
and tell us what went wrong." 2.1.2 fixes a lot of problems present
|
||||
in 2.0.0 and is generally a much better product.
|
||||
|
||||
Relative to 2.1.1, a large number of minor problems with 2.1.1 have
|
||||
been fixed, and so if you use 2.1.1 you should try 2.1.2. Users of
|
||||
the last stable release, 2.0.0, might also want to try this release.
|
||||
|
||||
The following bugs, and probably many more, have been fixed. These
|
||||
are listed at http://bugs.kde.org. Reporting a bug for valgrind in
|
||||
the http://bugs.kde.org is much more likely to get you a fix than
|
||||
mailing developers directly, so please continue to keep sending bugs
|
||||
there.
|
||||
|
||||
76869 Crashes when running any tool under Fedora Core 2 test1
|
||||
This fixes the problem with returning from a signal handler
|
||||
when VDSOs are turned off in FC2.
|
||||
|
||||
69508 java 1.4.2 client fails with erroneous "stack size too small".
|
||||
This fix makes more of the pthread stack attribute related
|
||||
functions work properly. Java still doesn't work though.
|
||||
|
||||
71906 malloc alignment should be 8, not 4
|
||||
All memory returned by malloc/new etc is now at least
|
||||
8-byte aligned.
|
||||
|
||||
81970 vg_alloc_ThreadState: no free slots available
|
||||
(closed because the workaround is simple: increase
|
||||
VG_N_THREADS, rebuild and try again.)
|
||||
|
||||
78514 Conditional jump or move depends on uninitialized value(s)
|
||||
(a slight mishanding of FP code in memcheck)
|
||||
|
||||
77952 pThread Support (crash) (due to initialisation-ordering probs)
|
||||
(also 85118)
|
||||
|
||||
80942 Addrcheck wasn't doing overlap checking as it should.
|
||||
78048 return NULL on malloc/new etc failure, instead of asserting
|
||||
73655 operator new() override in user .so files often doesn't get picked up
|
||||
83060 Valgrind does not handle native kernel AIO
|
||||
69872 Create proper coredumps after fatal signals
|
||||
82026 failure with new glibc versions: __libc_* functions are not exported
|
||||
70344 UNIMPLEMENTED FUNCTION: tcdrain
|
||||
81297 Cancellation of pthread_cond_wait does not require mutex
|
||||
82872 Using debug info from additional packages (wishlist)
|
||||
83025 Support for ioctls FIGETBSZ and FIBMAP
|
||||
83340 Support for ioctl HDIO_GET_IDENTITY
|
||||
79714 Support for the semtimedop system call.
|
||||
77022 Support for ioctls FBIOGET_VSCREENINFO and FBIOGET_FSCREENINFO
|
||||
82098 hp2ps ansification (wishlist)
|
||||
83573 Valgrind SIGSEGV on execve
|
||||
82999 show which cmdline option was erroneous (wishlist)
|
||||
83040 make valgrind VPATH and distcheck-clean (wishlist)
|
||||
83998 Assertion `newfd > vgPlain_max_fd' failed (see below)
|
||||
82722 Unchecked mmap in as_pad leads to mysterious failures later
|
||||
78958 memcheck seg faults while running Mozilla
|
||||
85416 Arguments with colon (e.g. --logsocket) ignored
|
||||
|
||||
|
||||
Additionally there are the following changes, which are not
|
||||
connected to any bug report numbers, AFAICS:
|
||||
|
||||
* Rearranged address space layout relative to 2.1.1, so that
|
||||
Valgrind/tools will run out of memory later than currently in many
|
||||
circumstances. This is good news esp. for Calltree. It should
|
||||
be possible for client programs to allocate over 800MB of
|
||||
memory when using memcheck now.
|
||||
|
||||
* Improved checking when laying out memory. Should hopefully avoid
|
||||
the random segmentation faults that 2.1.1 sometimes caused.
|
||||
|
||||
* Support for Fedora Core 2 and SuSE 9.1. Improvements to NPTL
|
||||
support to the extent that V now works properly on NPTL-only setups.
|
||||
|
||||
* Renamed the following options:
|
||||
--logfile-fd --> --log-fd
|
||||
--logfile --> --log-file
|
||||
--logsocket --> --log-socket
|
||||
to be consistent with each other and other options (esp. --input-fd).
|
||||
|
||||
* Add support for SIOCGMIIPHY, SIOCGMIIREG and SIOCSMIIREG ioctls and
|
||||
improve the checking of other interface related ioctls.
|
||||
|
||||
* Fix building with gcc-3.4.1.
|
||||
|
||||
* Remove limit on number of semaphores supported.
|
||||
|
||||
* Add support for syscalls: set_tid_address (258), acct (51).
|
||||
|
||||
* Support instruction "repne movs" -- not official but seems to occur.
|
||||
|
||||
* Implement an emulated soft limit for file descriptors in addition to
|
||||
the current reserved area, which effectively acts as a hard limit. The
|
||||
setrlimit system call now simply updates the emulated limits as best
|
||||
as possible - the hard limit is not allowed to move at all and just
|
||||
returns EPERM if you try and change it. This should stop reductions
|
||||
in the soft limit causing assertions when valgrind tries to allocate
|
||||
descriptors from the reserved area.
|
||||
(This actually came from bug #83998).
|
||||
|
||||
* Major overhaul of Cachegrind implementation. First user-visible change
|
||||
is that cachegrind.out files are now typically 90% smaller than they
|
||||
used to be; code annotation times are correspondingly much smaller.
|
||||
Second user-visible change is that hit/miss counts for code that is
|
||||
unloaded at run-time is no longer dumped into a single "discard" pile,
|
||||
but accurately preserved.
|
||||
|
||||
* Client requests for telling valgrind about memory pools.
|
||||
|
||||
|
||||
|
||||
Developer (cvs head) release 2.1.1 (12 March 2004)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
2.1.1 contains some internal structural changes needed for V's
|
||||
long-term future. These don't affect end-users. Most notable
|
||||
user-visible changes are:
|
||||
|
||||
* Greater isolation between Valgrind and the program being run, so
|
||||
the program is less likely to inadvertently kill Valgrind by
|
||||
doing wild writes.
|
||||
|
||||
* Massif: a new space profiling tool. Try it! It's cool, and it'll
|
||||
tell you in detail where and when your C/C++ code is allocating heap.
|
||||
Draws pretty .ps pictures of memory use against time. A potentially
|
||||
powerful tool for making sense of your program's space use.
|
||||
|
||||
* Fixes for many bugs, including support for more SSE2/SSE3 instructions,
|
||||
various signal/syscall things, and various problems with debug
|
||||
info readers.
|
||||
|
||||
* Support for glibc-2.3.3 based systems.
|
||||
|
||||
We are now doing automatic overnight build-and-test runs on a variety
|
||||
of distros. As a result, we believe 2.1.1 builds and runs on:
|
||||
Red Hat 7.2, 7.3, 8.0, 9, Fedora Core 1, SuSE 8.2, SuSE 9.
|
||||
|
||||
|
||||
The following bugs, and probably many more, have been fixed. These
|
||||
are listed at http://bugs.kde.org. Reporting a bug for valgrind in
|
||||
the http://bugs.kde.org is much more likely to get you a fix than
|
||||
mailing developers directly, so please continue to keep sending bugs
|
||||
there.
|
||||
|
||||
69616 glibc 2.3.2 w/NPTL is massively different than what valgrind expects
|
||||
69856 I don't know how to instrument MMXish stuff (Helgrind)
|
||||
73892 valgrind segfaults starting with Objective-C debug info
|
||||
(fix for S-type stabs)
|
||||
73145 Valgrind complains too much about close(<reserved fd>)
|
||||
73902 Shadow memory allocation seems to fail on RedHat 8.0
|
||||
68633 VG_N_SEMAPHORES too low (V itself was leaking semaphores)
|
||||
75099 impossible to trace multiprocess programs
|
||||
76839 the `impossible' happened: disInstr: INT but not 0x80 !
|
||||
76762 vg_to_ucode.c:3748 (dis_push_segreg): Assertion `sz == 4' failed.
|
||||
76747 cannot include valgrind.h in c++ program
|
||||
76223 parsing B(3,10) gave NULL type => impossible happens
|
||||
75604 shmdt handling problem
|
||||
76416 Problems with gcc 3.4 snap 20040225
|
||||
75614 using -gstabs when building your programs the `impossible' happened
|
||||
75787 Patch for some CDROM ioctls CDORM_GET_MCN, CDROM_SEND_PACKET,
|
||||
75294 gcc 3.4 snapshot's libstdc++ have unsupported instructions.
|
||||
(REP RET)
|
||||
73326 vg_symtab2.c:272 (addScopeRange): Assertion `range->size > 0' failed.
|
||||
72596 not recognizing __libc_malloc
|
||||
69489 Would like to attach ddd to running program
|
||||
72781 Cachegrind crashes with kde programs
|
||||
73055 Illegal operand at DXTCV11CompressBlockSSE2 (more SSE opcodes)
|
||||
73026 Descriptor leak check reports port numbers wrongly
|
||||
71705 README_MISSING_SYSCALL_OR_IOCTL out of date
|
||||
72643 Improve support for SSE/SSE2 instructions
|
||||
72484 valgrind leaves it's own signal mask in place when execing
|
||||
72650 Signal Handling always seems to restart system calls
|
||||
72006 The mmap system call turns all errors in ENOMEM
|
||||
71781 gdb attach is pretty useless
|
||||
71180 unhandled instruction bytes: 0xF 0xAE 0x85 0xE8
|
||||
69886 writes to zero page cause valgrind to assert on exit
|
||||
71791 crash when valgrinding gimp 1.3 (stabs reader problem)
|
||||
69783 unhandled syscall: 218
|
||||
69782 unhandled instruction bytes: 0x66 0xF 0x2B 0x80
|
||||
70385 valgrind fails if the soft file descriptor limit is less
|
||||
than about 828
|
||||
69529 "rep; nop" should do a yield
|
||||
70827 programs with lots of shared libraries report "mmap failed"
|
||||
for some of them when reading symbols
|
||||
71028 glibc's strnlen is optimised enough to confuse valgrind
|
||||
|
||||
|
||||
|
||||
|
||||
Unstable (cvs head) release 2.1.0 (15 December 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
For whatever it's worth, 2.1.0 actually seems pretty darn stable to me
|
||||
(Julian). It looks eminently usable, and given that it fixes some
|
||||
significant bugs, may well be worth using on a day-to-day basis.
|
||||
2.1.0 is known to build and pass regression tests on: SuSE 9, SuSE
|
||||
8.2, RedHat 8.
|
||||
|
||||
2.1.0 most notably includes Jeremy Fitzhardinge's complete overhaul of
|
||||
handling of system calls and signals, and their interaction with
|
||||
threads. In general, the accuracy of the system call, thread and
|
||||
signal simulations is much improved. Specifically:
|
||||
|
||||
- Blocking system calls behave exactly as they do when running
|
||||
natively (not on valgrind). That is, if a syscall blocks only the
|
||||
calling thread when running natively, than it behaves the same on
|
||||
valgrind. No more mysterious hangs because V doesn't know that some
|
||||
syscall or other, should block only the calling thread.
|
||||
|
||||
- Interrupted syscalls should now give more faithful results.
|
||||
|
||||
- Finally, signal contexts in signal handlers are supported. As a
|
||||
result, konqueror on SuSE 9 no longer segfaults when notified of
|
||||
file changes in directories it is watching.
|
||||
|
||||
Other changes:
|
||||
|
||||
- Robert Walsh's file descriptor leakage checks. When enabled,
|
||||
Valgrind will print out a list of open file descriptors on
|
||||
exit. Along with each file descriptor, Valgrind prints out a stack
|
||||
backtrace of where the file was opened and any details relating to the
|
||||
file descriptor such as the file name or socket details.
|
||||
To use, give: --track-fds=yes
|
||||
|
||||
- Implemented a few more SSE/SSE2 instructions.
|
||||
|
||||
- Less crud on the stack when you do 'where' inside a GDB attach.
|
||||
|
||||
- Fixed the following bugs:
|
||||
68360: Valgrind does not compile against 2.6.0-testX kernels
|
||||
68525: CVS head doesn't compile on C90 compilers
|
||||
68566: pkgconfig support (wishlist)
|
||||
68588: Assertion `sz == 4' failed in vg_to_ucode.c (disInstr)
|
||||
69140: valgrind not able to explicitly specify a path to a binary.
|
||||
69432: helgrind asserts encountering a MutexErr when there are
|
||||
EraserErr suppressions
|
||||
|
||||
- Increase the max size of the translation cache from 200k average bbs
|
||||
to 300k average bbs. Programs on the size of OOo (680m17) are
|
||||
thrashing the cache at the smaller size, creating large numbers of
|
||||
retranslations and wasting significant time as a result.
|
||||
|
||||
|
||||
|
||||
Stable release 2.0.0 (5 Nov 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
2.0.0 improves SSE/SSE2 support, fixes some minor bugs, and
|
||||
improves support for SuSE 9 and the Red Hat "Severn" beta.
|
||||
|
||||
- Further improvements to SSE/SSE2 support. The entire test suite of
|
||||
the GNU Scientific Library (gsl-1.4) compiled with Intel Icc 7.1
|
||||
20030307Z '-g -O -xW' now works. I think this gives pretty good
|
||||
coverage of SSE/SSE2 floating point instructions, or at least the
|
||||
subset emitted by Icc.
|
||||
|
||||
- Also added support for the following instructions:
|
||||
MOVNTDQ UCOMISD UNPCKLPS UNPCKHPS SQRTSS
|
||||
PUSH/POP %{FS,GS}, and PUSH %CS (Nb: there is no POP %CS).
|
||||
|
||||
- CFI support for GDB version 6. Needed to enable newer GDBs
|
||||
to figure out where they are when using --gdb-attach=yes.
|
||||
|
||||
- Fix this:
|
||||
mc_translate.c:1091 (memcheck_instrument): Assertion
|
||||
`u_in->size == 4 || u_in->size == 16' failed.
|
||||
|
||||
- Return an error rather than panicing when given a bad socketcall.
|
||||
|
||||
- Fix checking of syscall rt_sigtimedwait().
|
||||
|
||||
- Implement __NR_clock_gettime (syscall 265). Needed on Red Hat Severn.
|
||||
|
||||
- Fixed bug in overlap check in strncpy() -- it was assuming the src was 'n'
|
||||
bytes long, when it could be shorter, which could cause false
|
||||
positives.
|
||||
|
||||
- Support use of select() for very large numbers of file descriptors.
|
||||
|
||||
- Don't fail silently if the executable is statically linked, or is
|
||||
setuid/setgid. Print an error message instead.
|
||||
|
||||
- Support for old DWARF-1 format line number info.
|
||||
|
||||
|
||||
|
||||
Snapshot 20031012 (12 October 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Three months worth of bug fixes, roughly. Most significant single
|
||||
change is improved SSE/SSE2 support, mostly thanks to Dirk Mueller.
|
||||
|
||||
20031012 builds on Red Hat Fedora ("Severn") but doesn't really work
|
||||
(curiosly, mozilla runs OK, but a modest "ls -l" bombs). I hope to
|
||||
get a working version out soon. It may or may not work ok on the
|
||||
forthcoming SuSE 9; I hear positive noises about it but haven't been
|
||||
able to verify this myself (not until I get hold of a copy of 9).
|
||||
|
||||
A detailed list of changes, in no particular order:
|
||||
|
||||
- Describe --gen-suppressions in the FAQ.
|
||||
|
||||
- Syscall __NR_waitpid supported.
|
||||
|
||||
- Minor MMX bug fix.
|
||||
|
||||
- -v prints program's argv[] at startup.
|
||||
|
||||
- More glibc-2.3 suppressions.
|
||||
|
||||
- Suppressions for stack underrun bug(s) in the c++ support library
|
||||
distributed with Intel Icc 7.0.
|
||||
|
||||
- Fix problems reading /proc/self/maps.
|
||||
|
||||
- Fix a couple of messages that should have been suppressed by -q,
|
||||
but weren't.
|
||||
|
||||
- Make Addrcheck understand "Overlap" suppressions.
|
||||
|
||||
- At startup, check if program is statically linked and bail out if so.
|
||||
|
||||
- Cachegrind: Auto-detect Intel Pentium-M, also VIA Nehemiah
|
||||
|
||||
- Memcheck/addrcheck: minor speed optimisations
|
||||
|
||||
- Handle syscall __NR_brk more correctly than before.
|
||||
|
||||
- Fixed incorrect allocate/free mismatch errors when using
|
||||
operator new(unsigned, std::nothrow_t const&)
|
||||
operator new[](unsigned, std::nothrow_t const&)
|
||||
|
||||
- Support POSIX pthread spinlocks.
|
||||
|
||||
- Fixups for clean compilation with gcc-3.3.1.
|
||||
|
||||
- Implemented more opcodes:
|
||||
- push %es
|
||||
- push %ds
|
||||
- pop %es
|
||||
- pop %ds
|
||||
- movntq
|
||||
- sfence
|
||||
- pshufw
|
||||
- pavgb
|
||||
- ucomiss
|
||||
- enter
|
||||
- mov imm32, %esp
|
||||
- all "in" and "out" opcodes
|
||||
- inc/dec %esp
|
||||
- A whole bunch of SSE/SSE2 instructions
|
||||
|
||||
- Memcheck: don't bomb on SSE/SSE2 code.
|
||||
|
||||
|
||||
Snapshot 20030725 (25 July 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Fixes some minor problems in 20030716.
|
||||
|
||||
- Fix bugs in overlap checking for strcpy/memcpy etc.
|
||||
|
||||
- Do overlap checking with Addrcheck as well as Memcheck.
|
||||
|
||||
- Fix this:
|
||||
Memcheck: the `impossible' happened:
|
||||
get_error_name: unexpected type
|
||||
|
||||
- Install headers needed to compile new skins.
|
||||
|
||||
- Remove leading spaces and colon in the LD_LIBRARY_PATH / LD_PRELOAD
|
||||
passed to non-traced children.
|
||||
|
||||
- Fix file descriptor leak in valgrind-listener.
|
||||
|
||||
- Fix longstanding bug in which the allocation point of a
|
||||
block resized by realloc was not correctly set. This may
|
||||
have caused confusing error messages.
|
||||
|
||||
|
||||
Snapshot 20030716 (16 July 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
20030716 is a snapshot of our current CVS head (development) branch.
|
||||
This is the branch which will become valgrind-2.0. It contains
|
||||
significant enhancements over the 1.9.X branch.
|
||||
|
||||
Despite this being a snapshot of the CVS head, it is believed to be
|
||||
quite stable -- at least as stable as 1.9.6 or 1.0.4, if not more so
|
||||
-- and therefore suitable for widespread use. Please let us know asap
|
||||
if it causes problems for you.
|
||||
|
||||
Two reasons for releasing a snapshot now are:
|
||||
|
||||
- It's been a while since 1.9.6, and this snapshot fixes
|
||||
various problems that 1.9.6 has with threaded programs
|
||||
on glibc-2.3.X based systems.
|
||||
|
||||
- So as to make available improvements in the 2.0 line.
|
||||
|
||||
Major changes in 20030716, as compared to 1.9.6:
|
||||
|
||||
- More fixes to threading support on glibc-2.3.1 and 2.3.2-based
|
||||
systems (SuSE 8.2, Red Hat 9). If you have had problems
|
||||
with inconsistent/illogical behaviour of errno, h_errno or the DNS
|
||||
resolver functions in threaded programs, 20030716 should improve
|
||||
matters. This snapshot seems stable enough to run OpenOffice.org
|
||||
1.1rc on Red Hat 7.3, SuSE 8.2 and Red Hat 9, and that's a big
|
||||
threaded app if ever I saw one.
|
||||
|
||||
- Automatic generation of suppression records; you no longer
|
||||
need to write them by hand. Use --gen-suppressions=yes.
|
||||
|
||||
- strcpy/memcpy/etc check their arguments for overlaps, when
|
||||
running with the Memcheck or Addrcheck skins.
|
||||
|
||||
- malloc_usable_size() is now supported.
|
||||
|
||||
- new client requests:
|
||||
- VALGRIND_COUNT_ERRORS, VALGRIND_COUNT_LEAKS:
|
||||
useful with regression testing
|
||||
- VALGRIND_NON_SIMD_CALL[0123]: for running arbitrary functions
|
||||
on real CPU (use with caution!)
|
||||
|
||||
- The GDB attach mechanism is more flexible. Allow the GDB to
|
||||
be run to be specified by --gdb-path=/path/to/gdb, and specify
|
||||
which file descriptor V will read its input from with
|
||||
--input-fd=<number>.
|
||||
|
||||
- Cachegrind gives more accurate results (wasn't tracking instructions in
|
||||
malloc() and friends previously, is now).
|
||||
|
||||
- Complete support for the MMX instruction set.
|
||||
|
||||
- Partial support for the SSE and SSE2 instruction sets. Work for this
|
||||
is ongoing. About half the SSE/SSE2 instructions are done, so
|
||||
some SSE based programs may work. Currently you need to specify
|
||||
--skin=addrcheck. Basically not suitable for real use yet.
|
||||
|
||||
- Significant speedups (10%-20%) for standard memory checking.
|
||||
|
||||
- Fix assertion failure in pthread_once().
|
||||
|
||||
- Fix this:
|
||||
valgrind: vg_intercept.c:598 (vgAllRoadsLeadToRome_select):
|
||||
Assertion `ms_end >= ms_now' failed.
|
||||
|
||||
- Implement pthread_mutexattr_setpshared.
|
||||
|
||||
- Understand Pentium 4 branch hints. Also implemented a couple more
|
||||
obscure x86 instructions.
|
||||
|
||||
- Lots of other minor bug fixes.
|
||||
|
||||
- We have a decent regression test system, for the first time.
|
||||
This doesn't help you directly, but it does make it a lot easier
|
||||
for us to track the quality of the system, especially across
|
||||
multiple linux distributions.
|
||||
|
||||
You can run the regression tests with 'make regtest' after 'make
|
||||
install' completes. On SuSE 8.2 and Red Hat 9 I get this:
|
||||
|
||||
== 84 tests, 0 stderr failures, 0 stdout failures ==
|
||||
|
||||
On Red Hat 8, I get this:
|
||||
|
||||
== 84 tests, 2 stderr failures, 1 stdout failure ==
|
||||
corecheck/tests/res_search (stdout)
|
||||
memcheck/tests/sigaltstack (stderr)
|
||||
|
||||
sigaltstack is probably harmless. res_search doesn't work
|
||||
on R H 8 even running natively, so I'm not too worried.
|
||||
|
||||
On Red Hat 7.3, a glibc-2.2.5 system, I get these harmless failures:
|
||||
|
||||
== 84 tests, 2 stderr failures, 1 stdout failure ==
|
||||
corecheck/tests/pth_atfork1 (stdout)
|
||||
corecheck/tests/pth_atfork1 (stderr)
|
||||
memcheck/tests/sigaltstack (stderr)
|
||||
|
||||
You need to run on a PII system, at least, since some tests
|
||||
contain P6-specific instructions, and the test machine needs
|
||||
access to the internet so that corecheck/tests/res_search
|
||||
(a test that the DNS resolver works) can function.
|
||||
|
||||
As ever, thanks for the vast amount of feedback :) and bug reports :(
|
||||
We may not answer all messages, but we do at least look at all of
|
||||
them, and tend to fix the most frequently reported bugs.
|
||||
|
||||
|
||||
|
||||
Version 1.9.6 (7 May 2003 or thereabouts)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Major changes in 1.9.6:
|
||||
|
||||
- Improved threading support for glibc >= 2.3.2 (SuSE 8.2,
|
||||
RedHat 9, to name but two ...) It turned out that 1.9.5
|
||||
had problems with threading support on glibc >= 2.3.2,
|
||||
usually manifested by threaded programs deadlocking in system calls,
|
||||
or running unbelievably slowly. Hopefully these are fixed now. 1.9.6
|
||||
is the first valgrind which gives reasonable support for
|
||||
glibc-2.3.2. Also fixed a 2.3.2 problem with pthread_atfork().
|
||||
|
||||
- Majorly expanded FAQ.txt. We've added workarounds for all
|
||||
common problems for which a workaround is known.
|
||||
|
||||
Minor changes in 1.9.6:
|
||||
|
||||
- Fix identification of the main thread's stack. Incorrect
|
||||
identification of it was causing some on-stack addresses to not get
|
||||
identified as such. This only affected the usefulness of some error
|
||||
messages; the correctness of the checks made is unchanged.
|
||||
|
||||
- Support for kernels >= 2.5.68.
|
||||
|
||||
- Dummy implementations of __libc_current_sigrtmin,
|
||||
__libc_current_sigrtmax and __libc_allocate_rtsig, hopefully
|
||||
good enough to keep alive programs which previously died for lack of
|
||||
them.
|
||||
|
||||
- Fix bug in the VALGRIND_DISCARD_TRANSLATIONS client request.
|
||||
|
||||
- Fix bug in the DWARF2 debug line info loader, when instructions
|
||||
following each other have source lines far from each other
|
||||
(e.g. with inlined functions).
|
||||
|
||||
- Debug info reading: read symbols from both "symtab" and "dynsym"
|
||||
sections, rather than merely from the one that comes last in the
|
||||
file.
|
||||
|
||||
- New syscall support: prctl(), creat(), lookup_dcookie().
|
||||
|
||||
- When checking calls to accept(), recvfrom(), getsocketopt(),
|
||||
don't complain if buffer values are NULL.
|
||||
|
||||
- Try and avoid assertion failures in
|
||||
mash_LD_PRELOAD_and_LD_LIBRARY_PATH.
|
||||
|
||||
- Minor bug fixes in cg_annotate.
|
||||
|
||||
|
||||
|
||||
Version 1.9.5 (7 April 2003)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It occurs to me that it would be helpful for valgrind users to record
|
||||
in the source distribution the changes in each release. So I now
|
||||
attempt to mend my errant ways :-) Changes in this and future releases
|
||||
will be documented in the NEWS file in the source distribution.
|
||||
|
||||
Major changes in 1.9.5:
|
||||
|
||||
- (Critical bug fix): Fix a bug in the FPU simulation. This was
|
||||
causing some floating point conditional tests not to work right.
|
||||
Several people reported this. If you had floating point code which
|
||||
didn't work right on 1.9.1 to 1.9.4, it's worth trying 1.9.5.
|
||||
|
||||
- Partial support for Red Hat 9. RH9 uses the new Native Posix
|
||||
Threads Library (NPTL), instead of the older LinuxThreads.
|
||||
This potentially causes problems with V which will take some
|
||||
time to correct. In the meantime we have partially worked around
|
||||
this, and so 1.9.5 works on RH9. Threaded programs still work,
|
||||
but they may deadlock, because some system calls (accept, read,
|
||||
write, etc) which should be nonblocking, in fact do block. This
|
||||
is a known bug which we are looking into.
|
||||
|
||||
If you can, your best bet (unfortunately) is to avoid using
|
||||
1.9.5 on a Red Hat 9 system, or on any NPTL-based distribution.
|
||||
If your glibc is 2.3.1 or earlier, you're almost certainly OK.
|
||||
|
||||
Minor changes in 1.9.5:
|
||||
|
||||
- Added some #errors to valgrind.h to ensure people don't include
|
||||
it accidentally in their sources. This is a change from 1.0.X
|
||||
which was never properly documented. The right thing to include
|
||||
is now memcheck.h. Some people reported problems and strange
|
||||
behaviour when (incorrectly) including valgrind.h in code with
|
||||
1.9.1 -- 1.9.4. This is no longer possible.
|
||||
|
||||
- Add some __extension__ bits and pieces so that gcc configured
|
||||
for valgrind-checking compiles even with -Werror. If you
|
||||
don't understand this, ignore it. Of interest to gcc developers
|
||||
only.
|
||||
|
||||
- Removed a pointless check which caused problems interworking
|
||||
with Clearcase. V would complain about shared objects whose
|
||||
names did not end ".so", and refuse to run. This is now fixed.
|
||||
In fact it was fixed in 1.9.4 but not documented.
|
||||
|
||||
- Fixed a bug causing an assertion failure of "waiters == 1"
|
||||
somewhere in vg_scheduler.c, when running large threaded apps,
|
||||
notably MySQL.
|
||||
|
||||
- Add support for the munlock system call (124).
|
||||
|
||||
Some comments about future releases:
|
||||
|
||||
1.9.5 is, we hope, the most stable Valgrind so far. It pretty much
|
||||
supersedes the 1.0.X branch. If you are a valgrind packager, please
|
||||
consider making 1.9.5 available to your users. You can regard the
|
||||
1.0.X branch as obsolete: 1.9.5 is stable and vastly superior. There
|
||||
are no plans at all for further releases of the 1.0.X branch.
|
||||
|
||||
If you want a leading-edge valgrind, consider building the cvs head
|
||||
(from SourceForge), or getting a snapshot of it. Current cool stuff
|
||||
going in includes MMX support (done); SSE/SSE2 support (in progress),
|
||||
a significant (10-20%) performance improvement (done), and the usual
|
||||
large collection of minor changes. Hopefully we will be able to
|
||||
improve our NPTL support, but no promises.
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
- works on stock 2.4 kernels, but the scheduler loop must poll
|
||||
- works on RH9 2.4.20-18.9 kernel, but doesn't seem quite as stable
|
||||
as 2.5/2.6
|
||||
for pending signals rather than relying on the kernel delivering them
|
||||
to the right place.
|
||||
- most tested on 2.6.0-test1 and up
|
||||
|
||||
- running job-control programs (ie, bash) under Valgrind won't work
|
||||
properly without a kernel patch (as of 2.6.0-test2-mm2). This is because
|
||||
threads in a thread group don't follow the thread group leader's changes
|
||||
in process group ID, and they can't change it for themselves.
|
||||
|
||||
- SA_NOCLDWAIT doesn't work properly if the program is actually blocked
|
||||
in wait4() when SIGCHLD arrives; the wait4() will return details for
|
||||
the exiting child. In other circumstances children should be quietly reaped.
|
||||
[ This may be fixable when running under RH2.4 and 2.6, since we can
|
||||
set NOCLDWAIT in the kernel's state without risk of losing our child
|
||||
threads. ]
|
||||
|
||||
- 2.4 has somewhat disfunctional thread/signal interactions, so many test
|
||||
do not work as well under 2.4. In general, it should be no worse than
|
||||
the old signal code. I don't intend spending a lot of time fixing this
|
||||
because 2.6 is nearly ready for widespread use.
|
||||
|
||||
TODO:
|
||||
|
||||
- support application use of clone(). Interesting question is which
|
||||
options do we support? Do we need to implement futex as well, or can
|
||||
we just use the kernel's implementation?
|
||||
|
||||
========================================
|
||||
Testing
|
||||
|
||||
I've been testing with the Posix test suite:
|
||||
http://sourceforge.net/projects/posixtest/, version 1.2.0.
|
||||
|
||||
----------------------------------------
|
||||
Expected failures:
|
||||
|
||||
conformance/interfaces/sigwaitinfo/6-1.test
|
||||
pthread_kill() calls the tkill syscall, which causes a code of
|
||||
SI_TKILL rather than the SI_USER which this test expects.
|
||||
|
||||
conformance/interfaces/sigrelse/3-*.test
|
||||
glibc bug in sigrelse(), which fails without Valgrind too.
|
||||
|
||||
conformance/interfaces/pthread_barrier_*/*
|
||||
Valgrind's libpthreads doesn't implement pthread_barrier_*.
|
||||
(There are some passes, but I don't know why.)
|
||||
|
||||
conformance/interfaces/pthread_cond_timedwait/2-3
|
||||
This test is just completely broken. It does expose a problem
|
||||
in Valgrind's mutex implementation - it is too dependent on
|
||||
the client code not doing stupid stuff. This test makes
|
||||
Valgrind have an assertion failure.
|
||||
|
||||
conformance/interfaces/pthread_condattr_getpshared/*
|
||||
pthread_condattr_getpshared not implemented
|
||||
|
||||
conformance/interfaces/pthread_condattr_setpshared/*
|
||||
pthread_condattr_setpshared not implemented
|
||||
|
||||
conformance/interfaces/pthread_key_create/speculative/5-1
|
||||
Valgrind should cope with key overload
|
||||
|
||||
conformance/interfaces/pthread_mutex_timedlock/*
|
||||
not implemented
|
||||
|
||||
conformance/interfaces/pthread_rwlock_rdlock/2-1:
|
||||
relies on pthread_setschedparam
|
||||
|
||||
conformance/interfaces/pthread_rwlock_timedrdlock/*
|
||||
valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: pthread_rwlock_timedrdlock
|
||||
|
||||
conformance/interfaces/pthread_rwlockattr_getpshared/*
|
||||
pthread_rwlockattr_getpshared not implemented
|
||||
|
||||
conformance/interfaces/pthread_rwlockattr_setpshared/*
|
||||
pthread_rwlockattr_setpshared not implemented
|
||||
|
||||
conformance/interfaces/sched_rr_get_interval/*
|
||||
syscall 161 (sched_rr_get_interval) not implemented
|
||||
|
||||
conformance/interfaces/sigaction/21-1
|
||||
Subtle problem: if app specifies SA_NOCLDWAIT on their SIGCHLD
|
||||
signal handler, Valgrind will attempt to catch the SIGCHLD and
|
||||
wait4() on all the children before returning to the app.
|
||||
However, if the app was running a wait4() at the time the
|
||||
SIGCHLD arrives, it will get the child's status. Quite what
|
||||
the app is doing running wait4() when it explicitly asked for
|
||||
it to be useless, I'm not sure...
|
||||
|
||||
conformance/interfaces/sigaction/17-{3,6,8,12}
|
||||
(2.4) These fail under 2.4 because they deal with SIGSEGV, SIGBUS
|
||||
and SIGILL. These signals can only be delivered if there's a
|
||||
thread immediately ready to handle them, but cannot be left
|
||||
pending indefinitely. These tests hang forever because the
|
||||
signal is discarded rather than delivered.
|
||||
|
||||
conformance/interfaces/sigqueue/{1,4,8}-1
|
||||
(2.4) Signals that we route manually do not have queued data
|
||||
associated with them - they are routed with tkill. Also
|
||||
pending signals are only kept in a mask, not in a queue, so
|
||||
there can only be one at a time.
|
||||
|
||||
----------------------------------------
|
||||
|
||||
Still to investigate:
|
||||
|
||||
conformance/interfaces/pthread_detach/4-1
|
||||
|
||||
+conformance/interfaces/pthread_rwlock_rdlock/4-1: execution: FAILED: Output:
|
||||
+main: attempt write lock
|
||||
+main: acquired write lock
|
||||
+sig_thread: attemp read lock
|
||||
+main: fire SIGUSR1 to sig_thread
|
||||
+SIGUSR1 was not caught by sig_thread
|
||||
|
||||
|
||||
+conformance/interfaces/pthread_rwlock_unlock/4-1: execution: FAILED: Output:
|
||||
+Test FAILED: Incorrect error code, expected 0 or EINVAL, got 1
|
||||
|
||||
+conformance/interfaces/pthread_rwlock_wrlock/2-1: execution: FAILED: Output:
|
||||
+main: attempt write lock
|
||||
+sig_thread: attempt write lock
|
||||
+main: fire SIGUSR1 to sig_thread
|
||||
+The signal handler did not get called.
|
||||
|
||||
+conformance/interfaces/pthread_rwlock_wrlock/3-1: execution: FAILED: Output:
|
||||
+
|
||||
+sched status:
|
||||
+
|
||||
+Thread 1: status = WaitCV, associated_mx = 0x40115910, associated_cv = 0x401158E0
|
||||
+==11243== at 0x40102962: pthread_cond_wait (vg_libpthread.c:1093)
|
||||
+==11243== by 0x40104976: __pthread_rwlock_wrlock (vg_libpthread.c:2619)
|
||||
+==11243== by 0x8048588: main (3-1.c:53)
|
||||
+==11243== by 0x4013DA46: __libc_start_main (in /lib/libc-2.3.2.so)
|
||||
+
|
||||
+==11243== Warning: pthread scheduler exited due to deadlock
|
||||
+
|
||||
+valgrind: vg_main.c:1619 (vgPlain_main): Assertion `vgPlain_threads[vgPlain_last_run_tid].status == VgTs_Runnable' failed.
|
||||
+
|
||||
+sched status:
|
||||
+
|
||||
+Thread 1: status = WaitCV, associated_mx = 0x40115910, associated_cv = 0x401158E0
|
||||
+==11243== at 0x40102962: pthread_cond_wait (vg_libpthread.c:1093)
|
||||
+==11243== by 0x40104976: __pthread_rwlock_wrlock (vg_libpthread.c:2619)
|
||||
+==11243== by 0x8048588: main (3-1.c:53)
|
||||
+==11243== by 0x4013DA46: __libc_start_main (in /lib/libc-2.3.2.so)
|
||||
|
||||
|
||||
+conformance/interfaces/sem_close/1-1.test:
|
||||
/home/jeremy/bk/valgrind/syscalls/coregrind/.in_place/libpthread.so.0:
|
||||
version `GLIBC_2.1.1' not found (required by
|
||||
conformance/interfaces/sem_close/1-1.test)
|
||||
|
||||
+conformance/interfaces/sem_timedwait/6-1: execution: FAILED: Output:
|
||||
+TEST FAILED
|
||||
+conformance/interfaces/sem_timedwait/6-2: execution: FAILED: Output:
|
||||
+TEST FAILED
|
||||
|
||||
+conformance/interfaces/sem_timedwait/9-1: execution: FAILED: Output:
|
||||
+In handler
|
||||
+TEST FAILED: errno != EINTR
|
||||
|
||||
|
||||
conformance/interfaces/sigaction/10-1:
|
||||
Used to work. Mysterious. Works everywhere except in the test harness...
|
||||
|
||||
|
||||
+conformance/interfaces/sigpause/1-2: execution: FAILED: Output:
|
||||
+
|
||||
+valgrind: vg_mylibc.c:1324 (vgPlain_read_millisecond_timer): Assertion `rdtsc_now > rdtsc_cal_end_raw' failed.
|
||||
+
|
||||
+sched status:
|
||||
+
|
||||
+Thread 1: status = Sleeping, associated_mx = 0x0, associated_cv = 0x0
|
||||
+==19929== at 0x401D6765: __GI___libc_nanosleep (in /lib/libc-2.3.2.so)
|
||||
+==19929== by 0x80485C1: main (1-2.c:65)
|
||||
+==19929== by 0x4013DA46: __libc_start_main (in /lib/libc-2.3.2.so)
|
||||
+==19929== by 0x8048494: ??? (start.S:81)
|
||||
+
|
||||
+Thread 2: status = WaitSys, associated_mx = 0x0, associated_cv = 0x0
|
||||
+==19929== at 0x40150796: __libc_sigsuspend (in /lib/libc-2.3.2.so)
|
||||
+==19929== by 0x401509B3: __GI___sigpause (in /lib/libc-2.3.2.so)
|
||||
+==19929== by 0x804857C: a_thread_func (1-2.c:48)
|
||||
+==19929== by 0x40102099: thread_wrapper (vg_libpthread.c:667)
|
||||
|
||||
|
||||
|
||||
----------------------------------------
|
||||
|
||||
Fixes:
|
||||
conformance/interfaces/pthread_detach/4-2
|
||||
This fails under NPTL, but passes under Valgrind
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
Release notes for Valgrind
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you are building a binary package of Valgrind for distribution,
|
||||
please read README_PACKAGERS. It contains some important information.
|
||||
|
||||
If you are developing Valgrind, please read README_DEVELOPERS. It contains
|
||||
some useful information.
|
||||
|
||||
For instructions on how to build/install, see the end of this file.
|
||||
|
||||
Valgrind works on most, reasonably recent Linux setups. If you have
|
||||
problems, consult FAQ.txt to see if there are workarounds.
|
||||
|
||||
Executive Summary
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Valgrind is a GPL'd system for debugging and profiling x86-Linux programs.
|
||||
With the tools that come with Valgrind, you can automatically detect
|
||||
many memory management and threading bugs, avoiding hours of frustrating
|
||||
bug-hunting, making your programs more stable. You can also perform
|
||||
detailed profiling to help speed up your programs.
|
||||
|
||||
The Valgrind distribution includes five tools: two memory error
|
||||
detectors, a thread error detector, a cache profiler and a heap profiler.
|
||||
Several other tools have been built with Valgrind.
|
||||
|
||||
To give you an idea of what Valgrind tools do, when a program is run
|
||||
under the supervision of the first memory error detector tool, all reads
|
||||
and writes of memory are checked, and calls to malloc/new/free/delete
|
||||
are intercepted. As a result, it can detect problems such as:
|
||||
|
||||
Use of uninitialised memory
|
||||
Reading/writing memory after it has been free'd
|
||||
Reading/writing off the end of malloc'd blocks
|
||||
Reading/writing inappropriate areas on the stack
|
||||
Memory leaks -- where pointers to malloc'd blocks are lost forever
|
||||
Passing of uninitialised and/or unaddressible memory to system calls
|
||||
Mismatched use of malloc/new/new [] vs free/delete/delete []
|
||||
Overlaps of arguments to strcpy() and related functions
|
||||
Some abuses of the POSIX pthread API
|
||||
|
||||
Problems like these can be difficult to find by other means, often
|
||||
lying undetected for long periods, then causing occasional,
|
||||
difficult-to-diagnose crashes. When one of these errors occurs, you can
|
||||
attach GDB to your program, so you can poke around and see what's going
|
||||
on.
|
||||
|
||||
Valgrind is closely tied to details of the CPU, operating system and
|
||||
to a less extent, compiler and basic C libraries. This makes it
|
||||
difficult to make it portable, so I have chosen at the outset to
|
||||
concentrate on what I believe to be a widely used platform: x86/Linux.
|
||||
|
||||
Valgrind is licensed under the GNU General Public License, version 2.
|
||||
Read the file COPYING in the source distribution for details.
|
||||
|
||||
|
||||
Documentation
|
||||
~~~~~~~~~~~~~
|
||||
A comprehensive user guide is supplied. Point your browser at
|
||||
$PREFIX/share/doc/valgrind/manual.html, where $PREFIX is whatever you
|
||||
specified with --prefix= when building.
|
||||
|
||||
|
||||
Building and installing it
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
To install from CVS :
|
||||
|
||||
0. Check out the code from CVS, following the instructions at
|
||||
http://developer.kde.org/source/anoncvs.html. The 'modulename' is
|
||||
"valgrind".
|
||||
|
||||
1. cd into the source directory.
|
||||
|
||||
2. Run ./autogen.sh to setup the environment (you need the standard
|
||||
autoconf tools to do so).
|
||||
|
||||
To install from a tar.bz2 distribution:
|
||||
|
||||
3. Run ./configure, with some options if you wish. The standard
|
||||
options are documented in the INSTALL file. The only interesting
|
||||
one is the usual --prefix=/where/you/want/it/installed.
|
||||
|
||||
4. Do "make".
|
||||
|
||||
5. Do "make install", possibly as root if the destination permissions
|
||||
require that.
|
||||
|
||||
6. See if it works. Try "valgrind --tool=memcheck ls -l". Either
|
||||
this works, or it bombs out with some complaint. In that case,
|
||||
please let us know (see valgrind.kde.org/bugs.html).
|
||||
|
||||
Important! Do not move the valgrind installation into a place
|
||||
different from that specified by --prefix at build time. This will
|
||||
cause things to break in subtle ways, mostly when Valgrind handles
|
||||
fork/exec calls.
|
||||
|
||||
|
||||
Julian Seward (jseward@acm.org)
|
||||
Nick Nethercote (njn25@cam.ac.uk)
|
||||
Jeremy Fitzhardinge (jeremy@goop.org)
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
Building and not installing it
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
To run Valgrind without having to install it, run coregrind/valgrind (prefix
|
||||
with "sh" because it's not executable) with the --in-place=<dir> option, where
|
||||
<dir> is the root of the source tree (and must be an absolute path). Eg:
|
||||
|
||||
sh ~/grind/head4/coregrind/valgrind --in-place=/homes/njn25/grind/head4
|
||||
|
||||
This allows you to compile and run with "make" instead of "make install",
|
||||
saving you time.
|
||||
|
||||
I recommend compiling with "make --quiet" to further reduce the amount of
|
||||
output spewed out during compilation, letting you actually see any errors,
|
||||
warnings, etc.
|
||||
|
||||
|
||||
Running the regression tests
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
To build and run all the regression tests, run "make [--quiet] regtest".
|
||||
|
||||
To run a subset of the regression tests, execute:
|
||||
|
||||
perl tests/vg_regtest <name>
|
||||
|
||||
where <name> is a directory (all tests within will be run) or a single
|
||||
.vgtest test file, or the name of a program which has a like-named .vgtest
|
||||
file. Eg:
|
||||
|
||||
perl tests/vg_regtest memcheck
|
||||
perl tests/vg_regtest memcheck/tests/badfree.vgtest
|
||||
perl tests/vg_regtest memcheck/tests/badfree
|
||||
|
||||
|
||||
Debugging Valgrind with GDB
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
To debug Valgrind itself with GDB, start Valgrind like this:
|
||||
|
||||
valgrind --tool=none --wait-for-gdb=yes <prog>
|
||||
|
||||
Then start gdb like this in another terminal:
|
||||
|
||||
gdb /usr/lib/valgrind/stage2 <pid>
|
||||
|
||||
Where <pid> is the pid valgrind printed. Then set whatever breakpoints
|
||||
you want and do this in gdb:
|
||||
|
||||
jump *$eip
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
|
||||
Dealing with missing system call or ioctl wrappers in Valgrind
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
You're probably reading this because Valgrind bombed out whilst
|
||||
running your program, and advised you to read this file. The good
|
||||
news is that, in general, it's easy to write the missing syscall or
|
||||
ioctl wrappers you need, so that you can continue your debugging. If
|
||||
you send the resulting patches to me, then you'll be doing a favour to
|
||||
all future Valgrind users too.
|
||||
|
||||
Note that an "ioctl" is just a special kind of system call, really; so
|
||||
there's not a lot of need to distinguish them (at least conceptually)
|
||||
in the discussion that follows.
|
||||
|
||||
All this machinery is in coregrind/vg_syscalls.c.
|
||||
|
||||
|
||||
What are syscall/ioctl wrappers? What do they do?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Valgrind does what it does, in part, by keeping track of everything your
|
||||
program does. When a system call happens, for example a request to read
|
||||
part of a file, control passes to the Linux kernel, which fulfills the
|
||||
request, and returns control to your program. The problem is that the
|
||||
kernel will often change the status of some part of your program's memory
|
||||
as a result, and tools (instrumentation plug-ins) may need to know about
|
||||
this.
|
||||
|
||||
Syscall and ioctl wrappers have two jobs:
|
||||
|
||||
1. Tell a tool what's about to happen, before the syscall takes place. A
|
||||
tool could perform checks beforehand, eg. if memory about to be written
|
||||
is actually writeable. This part is useful, but not strictly
|
||||
essential.
|
||||
|
||||
2. Tell a tool what just happened, after a syscall takes place. This is
|
||||
so it can update its view of the program's state, eg. that memory has
|
||||
just been written to. This step is essential.
|
||||
|
||||
The "happenings" mostly involve reading/writing of memory.
|
||||
|
||||
So, let's look at an example of a wrapper for a system call which
|
||||
should be familiar to many Unix programmers.
|
||||
|
||||
|
||||
The syscall wrapper for time()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Removing the debug printing clutter, it looks like this:
|
||||
|
||||
PRE(time)
|
||||
{
|
||||
/* time_t time(time_t *t); */
|
||||
MAYBE_PRINTF("time ( %p )\n",arg1);
|
||||
if (arg1 != (UInt)NULL) {
|
||||
SYSCALL_TRACK( pre_mem_write, tid, "time", arg1, sizeof(time_t) );
|
||||
}
|
||||
}
|
||||
|
||||
POST(time)
|
||||
{
|
||||
if (arg1 != (UInt)NULL) {
|
||||
VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
|
||||
}
|
||||
}
|
||||
|
||||
The first thing we do happens before the syscall occurs, in the PRE() function:
|
||||
if a non-NULL buffer is passed in as the argument, tell the tool that the
|
||||
buffer is about to be written to:
|
||||
|
||||
if (arg1 != (UInt)NULL) {
|
||||
SYSCALL_TRACK( pre_mem_write, tst, "time", arg1, sizeof(time_t) );
|
||||
}
|
||||
|
||||
Finally, the really important bit, after the syscall occurs, in the POST()
|
||||
function: if, and only if, the system call was successful, tell the tool that
|
||||
the memory was written:
|
||||
|
||||
if (arg1 != (UInt)NULL) {
|
||||
VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
|
||||
}
|
||||
|
||||
The POST() function won't be called if the syscall failed, so you
|
||||
don't need to worry about checking that in the POST() function.
|
||||
(Note: this is sometimes a bug; some syscalls do return results when
|
||||
they "fail" - for example, nanosleep returns the amount of unslept
|
||||
time if interrupted. TODO: add another per-syscall flag for this
|
||||
case.)
|
||||
|
||||
|
||||
Writing your own syscall wrappers (see below for ioctl wrappers)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If Valgrind tells you that system call NNN is unimplemented, do the
|
||||
following:
|
||||
|
||||
1. Find out the name of the system call:
|
||||
|
||||
grep NNN /usr/include/asm/unistd.h
|
||||
|
||||
This should tell you something like __NR_mysyscallname.
|
||||
Copy this entry to coregrind/$(VG_PLATFORM)/vki_unistd.h.
|
||||
|
||||
2. Do 'man 2 mysyscallname' to get some idea of what the syscall
|
||||
does. Note that the actual kernel interface can differ from this,
|
||||
so you might also want to check a version of the Linux kernel
|
||||
source.
|
||||
|
||||
NOTE: any syscall which has something to do with signals or
|
||||
threads is probably "special", and needs more careful handling.
|
||||
Post something to valgrind-developers if you aren't sure.
|
||||
|
||||
|
||||
3. Add a case to the already-huge collection of wrappers in
|
||||
coregrind/vg_syscalls.c. For each in-memory parameter which is
|
||||
read or written by the syscall, do one of
|
||||
|
||||
SYSCALL_TRACK( pre_mem_read, ... )
|
||||
SYSCALL_TRACK( pre_mem_read_asciiz, ... )
|
||||
SYSCALL_TRACK( pre_mem_write, ... )
|
||||
|
||||
for that parameter. Then do the syscall. Then, if the syscall
|
||||
succeeds, issue suitable VG_TRACK( post_mem_write, ... ) calls.
|
||||
(There's no need for post_mem_read calls.)
|
||||
|
||||
Also, add it to the sys_info[] array; use SYSBA if it requires a
|
||||
PRE() and POST() function, and SYSB_ if it only requires a PRE()
|
||||
function. The 2nd arg of these macros indicate if the syscall
|
||||
could possibly block.
|
||||
|
||||
If you find this difficult, read the wrappers for other syscalls
|
||||
for ideas. A good tip is to look for the wrapper for a syscall
|
||||
which has a similar behaviour to yours, and use it as a
|
||||
starting point.
|
||||
|
||||
If you need structure definitions for your syscall, you can copy
|
||||
structure definitions from the kernel headers into
|
||||
include/vg_kerneliface.h, with the appropriate vki_* name
|
||||
mangling. Alternatively, you can #include headers for structure
|
||||
definitions, put your #includes into vg_unsafe.h (copying
|
||||
syscall-related things into vg_kerneliface.h is preferred though).
|
||||
|
||||
Test it.
|
||||
|
||||
Note that a common error is to call VG_TRACK( post_mem_write, ... )
|
||||
with 0 (NULL) as the first (address) argument. This usually means
|
||||
your logic is slightly inadequate. It's a sufficiently common bug
|
||||
that there's a built-in check for it, and you'll get a "probably
|
||||
sanity check failure" for the syscall wrapper you just made, if this
|
||||
is the case.
|
||||
|
||||
|
||||
4. Once happy, send us the patch. Pretty please.
|
||||
|
||||
|
||||
|
||||
|
||||
Writing your own ioctl wrappers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Is pretty much the same as writing syscall wrappers, except that all
|
||||
the action happens within PRE(ioctl) and POST(ioctl).
|
||||
|
||||
There's a default case, sometimes it isn't correct and you have to write a
|
||||
more specific case to get the right behaviour.
|
||||
|
||||
As above, please create a bug report and attach the patch as described
|
||||
on http://valgrind.kde.org/bugs.html
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
|
||||
Greetings, packaging person! This information is aimed at people
|
||||
building binary distributions of Valgrind.
|
||||
|
||||
Thanks for taking the time and effort to make a binary distribution
|
||||
of Valgrind. The following notes may save you some trouble.
|
||||
|
||||
|
||||
-- (Unfortunate but true) When you configure to build with the
|
||||
--prefix=/foo/bar/xyzzy option, the prefix /foo/bar/xyzzy gets
|
||||
baked into valgrind. The consequence is that you _must_ install
|
||||
valgrind at the location specified in the prefix. If you don't,
|
||||
it may appear to work, but will break doing some obscure things,
|
||||
particularly doing fork() and exec().
|
||||
|
||||
So you can't build a relocatable RPM / whatever from Valgrind.
|
||||
|
||||
|
||||
-- Don't strip the debug info off stage2 or libpthread.so.
|
||||
Valgrind will still work if you do, but it will generate less
|
||||
helpful error messages. Here's an example:
|
||||
|
||||
Mismatched free() / delete / delete []
|
||||
at 0x40043249: free (vg_clientfuncs.c:171)
|
||||
by 0x4102BB4E: QGArray::~QGArray(void) (tools/qgarray.cpp:149)
|
||||
by 0x4C261C41: PptDoc::~PptDoc(void) (include/qmemarray.h:60)
|
||||
by 0x4C261F0E: PptXml::~PptXml(void) (pptxml.cc:44)
|
||||
Address 0x4BB292A8 is 0 bytes inside a block of size 64 alloc'd
|
||||
at 0x4004318C: __builtin_vec_new (vg_clientfuncs.c:152)
|
||||
by 0x4C21BC15: KLaola::readSBStream(int) const (klaola.cc:314)
|
||||
by 0x4C21C155: KLaola::stream(KLaola::OLENode const *) (klaola.cc:416)
|
||||
by 0x4C21788F: OLEFilter::convert(QCString const &) (olefilter.cc:272)
|
||||
|
||||
This tells you that some memory allocated with new[] was freed with
|
||||
free(). If stage2 was stripped the message would look like this:
|
||||
|
||||
Mismatched free() / delete / delete []
|
||||
at 0x40043249: (inside stage2)
|
||||
by 0x4102BB4E: QGArray::~QGArray(void) (tools/qgarray.cpp:149)
|
||||
by 0x4C261C41: PptDoc::~PptDoc(void) (include/qmemarray.h:60)
|
||||
by 0x4C261F0E: PptXml::~PptXml(void) (pptxml.cc:44)
|
||||
Address 0x4BB292A8 is 0 bytes inside a block of size 64 alloc'd
|
||||
at 0x4004318C: (inside stage2)
|
||||
by 0x4C21BC15: KLaola::readSBStream(int) const (klaola.cc:314)
|
||||
by 0x4C21C155: KLaola::stream(KLaola::OLENode const *) (klaola.cc:416)
|
||||
by 0x4C21788F: OLEFilter::convert(QCString const &) (olefilter.cc:272)
|
||||
|
||||
This isn't so helpful. Although you can tell there is a mismatch,
|
||||
the names of the allocating and deallocating functions are no longer
|
||||
visible. The same kind of thing occurs in various other messages
|
||||
from valgrind.
|
||||
|
||||
|
||||
-- Try and ensure that the /usr/include/asm/unistd.h file on the
|
||||
build machine contains an entry for all the system calls that
|
||||
the kernels on the target machines can actually support. On my
|
||||
Red Hat 7.2 (kernel 2.4.9) box the highest-numbered entry is
|
||||
#define __NR_fcntl64 221
|
||||
but I have heard of 2.2 boxes where it stops at 179 or so.
|
||||
|
||||
Reason for this is that at build time, support for syscalls
|
||||
is compiled in -- or not -- depending on which of these __NR_*
|
||||
symbols is defined. Problems arise when /usr/include/asm/unistd.h
|
||||
fails to give an entry for a system call which is actually
|
||||
available in the target kernel. In that case, valgrind will
|
||||
abort if asked to handle such a syscall. This is despite the
|
||||
fact that (usually) valgrind's sources actually contain the
|
||||
code to deal with the syscall.
|
||||
|
||||
Several people have reported having this problem. So, please
|
||||
be aware of it. If it's useful, the syscall wrappers are
|
||||
all done in vg_syscall_mem.c; you might want to have a little
|
||||
look in there.
|
||||
|
||||
|
||||
-- Please test the final installation works by running it on
|
||||
something huge. I suggest checking that it can start and
|
||||
exit successfully both Mozilla-1.0 and OpenOffice.org 1.0.
|
||||
I use these as test programs, and I know they fairly thoroughly
|
||||
exercise Valgrind. The command lines to use are:
|
||||
|
||||
valgrind -v --trace-children=yes --workaround-gcc296-bugs=yes mozilla
|
||||
|
||||
valgrind -v --trace-children=yes --workaround-gcc296-bugs=yes soffice
|
||||
|
||||
|
||||
If you find any more hints/tips for packaging, please report
|
||||
it as a bugreport. See http://valgrind.kde.org/bugs.html for details.
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
Doesn't run
|
||||
~~~~~~~~~~~
|
||||
User Mode Linux.
|
||||
Wine.
|
||||
|
||||
|
||||
Desirable
|
||||
~~~~~~~~~
|
||||
Stack: make return address into NoAccess ?
|
||||
|
||||
|
||||
Future
|
||||
~~~~~~
|
||||
Automatic invariant inference and checking.
|
||||
@@ -1,2 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
@@ -1,5 +0,0 @@
|
||||
/.cvsignore/1.1/Mon Sep 23 11:36:20 2002//
|
||||
/Makefile.am/1.52/Wed Sep 1 23:20:46 2004//
|
||||
/ac_main.c/1.66/Mon Aug 23 15:06:21 2004//
|
||||
D/docs////
|
||||
D/tests////
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/addrcheck
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,23 +0,0 @@
|
||||
include $(top_srcdir)/Makefile.tool.am
|
||||
|
||||
# include memcheck/ for mac_shared.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/memcheck -fomit-frame-pointer
|
||||
|
||||
val_PROGRAMS = vgskin_addrcheck.so vgpreload_addrcheck.so
|
||||
|
||||
vgskin_addrcheck_so_SOURCES = ac_main.c
|
||||
vgskin_addrcheck_so_LDFLAGS = -shared
|
||||
vgskin_addrcheck_so_LDADD = \
|
||||
../memcheck/mac_leakcheck.o \
|
||||
../memcheck/mac_malloc_wrappers.o \
|
||||
../memcheck/mac_needs.o
|
||||
|
||||
vgpreload_addrcheck_so_SOURCES =
|
||||
vgpreload_addrcheck_so_LDADD = \
|
||||
$(top_builddir)/coregrind/vg_replace_malloc.o \
|
||||
../memcheck/mac_replace_strmem.o
|
||||
vgpreload_addrcheck_so_DEPENDENCIES = \
|
||||
$(top_builddir)/coregrind/vg_replace_malloc.o \
|
||||
../memcheck/mac_replace_strmem.o
|
||||
vgpreload_addrcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
@@ -1,4 +0,0 @@
|
||||
/.cvsignore/1.1/Thu Oct 3 10:38:40 2002//
|
||||
/Makefile.am/1.3/Wed Aug 25 11:40:04 2004//
|
||||
/ac_main.html/1.4/Wed Dec 3 21:44:45 2003//
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/addrcheck/docs
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,3 +0,0 @@
|
||||
docdir = $(datadir)/doc/valgrind
|
||||
|
||||
dist_doc_DATA = ac_main.html
|
||||
@@ -1,103 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Addrcheck: a lightweight memory checker</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a name="ac-top"></a>
|
||||
<h2>5 <b>Addrcheck</b>: a lightweight memory checker</h2>
|
||||
|
||||
To use this tool, you must specify <code>--tool=addrcheck</code>
|
||||
on the Valgrind command line.
|
||||
|
||||
<h3>5.1 Kinds of bugs that Addrcheck can find</h3>
|
||||
|
||||
Addrcheck is a simplified version of the Memcheck tool described
|
||||
in Section 3. It is identical in every way to Memcheck, except for
|
||||
one important detail: it does not do the undefined-value checks that
|
||||
Memcheck does. This means Addrcheck is about twice as fast as
|
||||
Memcheck, and uses less memory. Addrcheck can detect the following
|
||||
errors:
|
||||
<ul>
|
||||
<li>Reading/writing memory after it has been free'd</li>
|
||||
<li>Reading/writing off the end of malloc'd blocks</li>
|
||||
<li>Reading/writing inappropriate areas on the stack</li>
|
||||
<li>Memory leaks -- where pointers to malloc'd blocks are lost
|
||||
forever</li>
|
||||
<li>Mismatched use of malloc/new/new [] vs free/delete/delete []</li>
|
||||
<li>Overlapping <code>src</code> and <code>dst</code> pointers in
|
||||
<code>memcpy()</code> and related functions</li>
|
||||
<li>Some misuses of the POSIX pthreads API</li>
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
<p>
|
||||
Rather than duplicate much of the Memcheck docs here (a.k.a. since I
|
||||
am a lazy b'stard), users of Addrcheck are advised to read
|
||||
the section on Memcheck. Some important points:
|
||||
<ul>
|
||||
<li>Addrcheck is exactly like Memcheck, except that all the
|
||||
value-definedness tracking machinery has been removed. Therefore,
|
||||
the Memcheck documentation which discusses definedess ("V-bits") is
|
||||
irrelevant. The stuff on addressibility ("A-bits") is still
|
||||
relevant.
|
||||
<p>
|
||||
<li>Addrcheck accepts the same command-line flags as Memcheck, with
|
||||
the exception of ... (to be filled in).
|
||||
<p>
|
||||
<li>Like Memcheck, Addrcheck will do memory leak checking (internally,
|
||||
the same code does leak checking for both tools). The only
|
||||
difference is how the two tools decide which memory locations
|
||||
to consider when searching for pointers to blocks. Memcheck will
|
||||
only consider 4-byte aligned locations which are validly
|
||||
addressible and which hold defined values. Addrcheck does not
|
||||
track definedness and so cannot apply the last, "defined value",
|
||||
criteria.
|
||||
<p>
|
||||
The result is that Addrcheck's leak checker may "discover"
|
||||
pointers to blocks that Memcheck would not. So it is possible
|
||||
that Memcheck could (correctly) conclude that a block is leaked,
|
||||
yet Addrcheck would not conclude that.
|
||||
<p>
|
||||
Whether or not this has any effect in practice is unknown. I
|
||||
suspect not, but that is mere speculation at this stage.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Addrcheck is, therefore, a fine-grained address checker. All it
|
||||
really does is check each memory reference to say whether or not that
|
||||
location may validly be addressed. Addrcheck has a memory overhead of
|
||||
one bit per byte of used address space. In contrast, Memcheck has an
|
||||
overhead of nine bits per byte.
|
||||
|
||||
<p>
|
||||
Due to lazyness on the part of the implementor (Julian), error
|
||||
messages from Addrcheck do not distinguish reads from writes. So it
|
||||
will say, for example, "Invalid memory access of size 4", whereas
|
||||
Memcheck would have said whether the access is a read or a write.
|
||||
This could easily be remedied, if anyone is particularly bothered.
|
||||
|
||||
<p>
|
||||
Addrcheck is quite pleasant to use. It's faster than Memcheck, and
|
||||
the lack of valid-value checks has another side effect: the errors it
|
||||
does report are relatively easy to track down, compared to the
|
||||
tedious and often confusing search sometimes needed to find the
|
||||
cause of uninitialised-value errors reported by Memcheck.
|
||||
|
||||
<p>
|
||||
Because it is faster and lighter than Memcheck, our hope is that
|
||||
Addrcheck is more suitable for less-intrusive, larger scale testing
|
||||
than is viable with Memcheck. As of mid-November 2002, we have
|
||||
experimented with running the KDE-3.1 desktop on Addrcheck (the entire
|
||||
process tree, starting from <code>startkde</code>). Running on a
|
||||
512MB, 1.7 GHz P4, the result is nearly usable. The ultimate aim is
|
||||
that is fast and unintrusive enough that (eg) KDE sessions may be
|
||||
unintrusively monitored for addressing errors whilst people do real
|
||||
work with their KDE desktop.
|
||||
|
||||
<p>
|
||||
Addrcheck is a new experiment in the Valgrind world. We'd be
|
||||
interested to hear your feedback on it.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
*.stdout.diff
|
||||
*.stderr.diff
|
||||
*.stdout.out
|
||||
*.stderr.out
|
||||
@@ -1,34 +0,0 @@
|
||||
/.cvsignore/1.3/Fri Jun 25 23:25:10 2004//
|
||||
/Makefile.am/1.9/Sat Jul 10 14:56:25 2004//
|
||||
/badrw.stderr.exp/1.4/Wed Jan 7 08:47:03 2004//
|
||||
/badrw.vgtest/1.1/Fri Sep 5 23:29:33 2003//
|
||||
/filter_stderr/1.1/Fri Oct 4 11:35:47 2002//
|
||||
/fprw.stderr.exp/1.4/Tue Apr 13 08:36:35 2004//
|
||||
/fprw.vgtest/1.1/Fri Sep 5 23:29:33 2003//
|
||||
/insn_basic.stderr.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_basic.stdout.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_basic.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_cmov.stderr.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_cmov.stdout.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_cmov.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_fpu.stderr.exp/1.1/Sat Mar 27 18:02:36 2004//
|
||||
/insn_fpu.stdout.exp/1.4/Wed Mar 31 22:47:52 2004//
|
||||
/insn_fpu.vgtest/1.1/Sat Mar 27 18:02:36 2004//
|
||||
/insn_mmx.stderr.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_mmx.stdout.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_mmx.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_mmxext.stderr.exp/1.2/Tue Mar 9 08:50:02 2004//
|
||||
/insn_mmxext.stdout.exp/1.2/Sun Jul 25 15:18:20 2004//
|
||||
/insn_mmxext.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_sse.stderr.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_sse.stdout.exp/1.2/Sun Jul 25 15:18:20 2004//
|
||||
/insn_sse.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_sse2.stderr.exp/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/insn_sse2.stdout.exp/1.2/Sun Jul 25 15:18:20 2004//
|
||||
/insn_sse2.vgtest/1.1/Tue Mar 9 01:44:11 2004//
|
||||
/overlap.stderr.exp/1.1/Wed May 5 10:46:21 2004//
|
||||
/overlap.stdout.exp/1.1/Wed May 5 10:46:21 2004//
|
||||
/overlap.vgtest/1.1/Wed May 5 10:46:22 2004//
|
||||
/toobig-allocs.stderr.exp/1.1/Sat Jul 10 14:56:25 2004//
|
||||
/toobig-allocs.vgtest/1.1/Sat Jul 10 14:56:25 2004//
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/addrcheck/tests
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,14 +0,0 @@
|
||||
noinst_SCRIPTS = filter_stderr
|
||||
|
||||
INSN_TESTS=insn_basic insn_fpu insn_cmov insn_mmx insn_mmxext insn_sse insn_sse2
|
||||
|
||||
EXTRA_DIST = $(noinst_SCRIPTS) \
|
||||
badrw.stderr.exp badrw.vgtest \
|
||||
fprw.stderr.exp fprw.vgtest \
|
||||
insn_basic.vgtest insn_cmov.vgtest insn_mmx.vgtest \
|
||||
$(addsuffix .stderr.exp,$(INSN_TESTS)) \
|
||||
$(addsuffix .stdout.exp,$(INSN_TESTS)) \
|
||||
$(addsuffix .vgtest,$(INSN_TESTS)) \
|
||||
overlap.stderr.exp overlap.stdout.exp overlap.vgtest \
|
||||
toobig-allocs.stderr.exp toobig-allocs.vgtest
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
Invalid read of size 4
|
||||
at 0x........: main (badrw.c:19)
|
||||
Address 0x........ is 4 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
|
||||
Invalid write of size 4
|
||||
at 0x........: main (badrw.c:20)
|
||||
Address 0x........ is 4 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
|
||||
Invalid read of size 2
|
||||
at 0x........: main (badrw.c:22)
|
||||
Address 0x........ is 4 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
|
||||
Invalid write of size 2
|
||||
at 0x........: main (badrw.c:23)
|
||||
Address 0x........ is 4 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
|
||||
Invalid read of size 1
|
||||
at 0x........: main (badrw.c:25)
|
||||
Address 0x........ is 1 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
|
||||
Invalid write of size 1
|
||||
at 0x........: main (badrw.c:26)
|
||||
Address 0x........ is 1 bytes before a block of size 10 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (badrw.c:5)
|
||||
@@ -1,2 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../memcheck/tests/badrw
|
||||
@@ -1,8 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Same as for MemCheck
|
||||
|
||||
dir=`dirname $0`
|
||||
|
||||
$dir/../../memcheck/tests/filter_stderr
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
Invalid read of size 8
|
||||
at 0x........: main (fprw.c:20)
|
||||
Address 0x........ is 0 bytes inside a block of size 8 free'd
|
||||
at 0x........: free (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:18)
|
||||
|
||||
Invalid write of size 8
|
||||
at 0x........: main (fprw.c:20)
|
||||
Address 0x........ is 0 bytes inside a block of size 8 free'd
|
||||
at 0x........: free (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:18)
|
||||
|
||||
Invalid read of size 4
|
||||
at 0x........: main (fprw.c:21)
|
||||
Address 0x........ is 0 bytes inside a block of size 4 free'd
|
||||
at 0x........: free (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:19)
|
||||
|
||||
Invalid write of size 4
|
||||
at 0x........: main (fprw.c:21)
|
||||
Address 0x........ is 0 bytes inside a block of size 4 free'd
|
||||
at 0x........: free (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:19)
|
||||
|
||||
Invalid free() / delete / delete[]
|
||||
at 0x........: free (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:22)
|
||||
Address 0x........ is not stack'd, malloc'd or (recently) free'd
|
||||
|
||||
Invalid write of size 8
|
||||
at 0x........: main (fprw.c:24)
|
||||
Address 0x........ is 0 bytes inside a block of size 4 alloc'd
|
||||
at 0x........: malloc (vg_replace_malloc.c:...)
|
||||
by 0x........: main (fprw.c:23)
|
||||
@@ -1,2 +0,0 @@
|
||||
vgopts: --single-step=yes -q
|
||||
prog: ../../memcheck/tests/fprw
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_basic
|
||||
@@ -1,384 +0,0 @@
|
||||
cmova_1 ... ok
|
||||
cmova_2 ... ok
|
||||
cmova_3 ... ok
|
||||
cmova_4 ... ok
|
||||
cmova_5 ... ok
|
||||
cmova_6 ... ok
|
||||
cmova_7 ... ok
|
||||
cmova_8 ... ok
|
||||
cmovae_1 ... ok
|
||||
cmovae_2 ... ok
|
||||
cmovae_3 ... ok
|
||||
cmovae_4 ... ok
|
||||
cmovb_1 ... ok
|
||||
cmovb_2 ... ok
|
||||
cmovb_3 ... ok
|
||||
cmovb_4 ... ok
|
||||
cmovbe_1 ... ok
|
||||
cmovbe_2 ... ok
|
||||
cmovbe_3 ... ok
|
||||
cmovbe_4 ... ok
|
||||
cmovbe_5 ... ok
|
||||
cmovbe_6 ... ok
|
||||
cmovbe_7 ... ok
|
||||
cmovbe_8 ... ok
|
||||
cmovc_1 ... ok
|
||||
cmovc_2 ... ok
|
||||
cmovc_3 ... ok
|
||||
cmovc_4 ... ok
|
||||
cmove_1 ... ok
|
||||
cmove_2 ... ok
|
||||
cmove_3 ... ok
|
||||
cmove_4 ... ok
|
||||
cmovg_1 ... ok
|
||||
cmovg_2 ... ok
|
||||
cmovg_3 ... ok
|
||||
cmovg_4 ... ok
|
||||
cmovg_5 ... ok
|
||||
cmovg_6 ... ok
|
||||
cmovg_7 ... ok
|
||||
cmovg_8 ... ok
|
||||
cmovg_9 ... ok
|
||||
cmovg_10 ... ok
|
||||
cmovg_11 ... ok
|
||||
cmovg_12 ... ok
|
||||
cmovg_13 ... ok
|
||||
cmovg_14 ... ok
|
||||
cmovg_15 ... ok
|
||||
cmovg_16 ... ok
|
||||
cmovge_1 ... ok
|
||||
cmovge_2 ... ok
|
||||
cmovge_3 ... ok
|
||||
cmovge_4 ... ok
|
||||
cmovge_5 ... ok
|
||||
cmovge_6 ... ok
|
||||
cmovge_7 ... ok
|
||||
cmovge_8 ... ok
|
||||
cmovl_1 ... ok
|
||||
cmovl_2 ... ok
|
||||
cmovl_3 ... ok
|
||||
cmovl_4 ... ok
|
||||
cmovl_5 ... ok
|
||||
cmovl_6 ... ok
|
||||
cmovl_7 ... ok
|
||||
cmovl_8 ... ok
|
||||
cmovle_1 ... ok
|
||||
cmovle_2 ... ok
|
||||
cmovle_3 ... ok
|
||||
cmovle_4 ... ok
|
||||
cmovle_5 ... ok
|
||||
cmovle_6 ... ok
|
||||
cmovle_7 ... ok
|
||||
cmovle_8 ... ok
|
||||
cmovle_9 ... ok
|
||||
cmovle_10 ... ok
|
||||
cmovle_11 ... ok
|
||||
cmovle_12 ... ok
|
||||
cmovle_13 ... ok
|
||||
cmovle_14 ... ok
|
||||
cmovle_15 ... ok
|
||||
cmovle_16 ... ok
|
||||
cmovna_1 ... ok
|
||||
cmovna_2 ... ok
|
||||
cmovna_3 ... ok
|
||||
cmovna_4 ... ok
|
||||
cmovna_5 ... ok
|
||||
cmovna_6 ... ok
|
||||
cmovna_7 ... ok
|
||||
cmovna_8 ... ok
|
||||
cmovnae_1 ... ok
|
||||
cmovnae_2 ... ok
|
||||
cmovnae_3 ... ok
|
||||
cmovnae_4 ... ok
|
||||
cmovnb_1 ... ok
|
||||
cmovnb_2 ... ok
|
||||
cmovnb_3 ... ok
|
||||
cmovnb_4 ... ok
|
||||
cmovnbe_1 ... ok
|
||||
cmovnbe_2 ... ok
|
||||
cmovnbe_3 ... ok
|
||||
cmovnbe_4 ... ok
|
||||
cmovnbe_5 ... ok
|
||||
cmovnbe_6 ... ok
|
||||
cmovnbe_7 ... ok
|
||||
cmovnbe_8 ... ok
|
||||
cmovnc_1 ... ok
|
||||
cmovnc_2 ... ok
|
||||
cmovnc_3 ... ok
|
||||
cmovnc_4 ... ok
|
||||
cmovne_1 ... ok
|
||||
cmovne_2 ... ok
|
||||
cmovne_3 ... ok
|
||||
cmovne_4 ... ok
|
||||
cmovng_1 ... ok
|
||||
cmovng_2 ... ok
|
||||
cmovng_3 ... ok
|
||||
cmovng_4 ... ok
|
||||
cmovng_5 ... ok
|
||||
cmovng_6 ... ok
|
||||
cmovng_7 ... ok
|
||||
cmovng_8 ... ok
|
||||
cmovng_9 ... ok
|
||||
cmovng_10 ... ok
|
||||
cmovng_11 ... ok
|
||||
cmovng_12 ... ok
|
||||
cmovng_13 ... ok
|
||||
cmovng_14 ... ok
|
||||
cmovng_15 ... ok
|
||||
cmovng_16 ... ok
|
||||
cmovnge_1 ... ok
|
||||
cmovnge_2 ... ok
|
||||
cmovnge_3 ... ok
|
||||
cmovnge_4 ... ok
|
||||
cmovnge_5 ... ok
|
||||
cmovnge_6 ... ok
|
||||
cmovnge_7 ... ok
|
||||
cmovnge_8 ... ok
|
||||
cmovnl_1 ... ok
|
||||
cmovnl_2 ... ok
|
||||
cmovnl_3 ... ok
|
||||
cmovnl_4 ... ok
|
||||
cmovnl_5 ... ok
|
||||
cmovnl_6 ... ok
|
||||
cmovnl_7 ... ok
|
||||
cmovnl_8 ... ok
|
||||
cmovnle_1 ... ok
|
||||
cmovnle_2 ... ok
|
||||
cmovnle_3 ... ok
|
||||
cmovnle_4 ... ok
|
||||
cmovnle_5 ... ok
|
||||
cmovnle_6 ... ok
|
||||
cmovnle_7 ... ok
|
||||
cmovnle_8 ... ok
|
||||
cmovnle_9 ... ok
|
||||
cmovnle_10 ... ok
|
||||
cmovnle_11 ... ok
|
||||
cmovnle_12 ... ok
|
||||
cmovnle_13 ... ok
|
||||
cmovnle_14 ... ok
|
||||
cmovnle_15 ... ok
|
||||
cmovnle_16 ... ok
|
||||
cmovno_1 ... ok
|
||||
cmovno_2 ... ok
|
||||
cmovno_3 ... ok
|
||||
cmovno_4 ... ok
|
||||
cmovnp_1 ... ok
|
||||
cmovnp_2 ... ok
|
||||
cmovnp_3 ... ok
|
||||
cmovnp_4 ... ok
|
||||
cmovns_1 ... ok
|
||||
cmovns_2 ... ok
|
||||
cmovns_3 ... ok
|
||||
cmovns_4 ... ok
|
||||
cmovnz_1 ... ok
|
||||
cmovnz_2 ... ok
|
||||
cmovnz_3 ... ok
|
||||
cmovnz_4 ... ok
|
||||
cmovo_1 ... ok
|
||||
cmovo_2 ... ok
|
||||
cmovo_3 ... ok
|
||||
cmovo_4 ... ok
|
||||
cmovp_1 ... ok
|
||||
cmovp_2 ... ok
|
||||
cmovp_3 ... ok
|
||||
cmovp_4 ... ok
|
||||
cmovs_1 ... ok
|
||||
cmovs_2 ... ok
|
||||
cmovs_3 ... ok
|
||||
cmovs_4 ... ok
|
||||
cmovz_1 ... ok
|
||||
cmovz_2 ... ok
|
||||
cmovz_3 ... ok
|
||||
cmovz_4 ... ok
|
||||
cmova_9 ... ok
|
||||
cmova_10 ... ok
|
||||
cmova_11 ... ok
|
||||
cmova_12 ... ok
|
||||
cmova_13 ... ok
|
||||
cmova_14 ... ok
|
||||
cmova_15 ... ok
|
||||
cmova_16 ... ok
|
||||
cmovae_5 ... ok
|
||||
cmovae_6 ... ok
|
||||
cmovae_7 ... ok
|
||||
cmovae_8 ... ok
|
||||
cmovb_5 ... ok
|
||||
cmovb_6 ... ok
|
||||
cmovb_7 ... ok
|
||||
cmovb_8 ... ok
|
||||
cmovbe_9 ... ok
|
||||
cmovbe_10 ... ok
|
||||
cmovbe_11 ... ok
|
||||
cmovbe_12 ... ok
|
||||
cmovbe_13 ... ok
|
||||
cmovbe_14 ... ok
|
||||
cmovbe_15 ... ok
|
||||
cmovbe_16 ... ok
|
||||
cmovc_5 ... ok
|
||||
cmovc_6 ... ok
|
||||
cmovc_7 ... ok
|
||||
cmovc_8 ... ok
|
||||
cmove_5 ... ok
|
||||
cmove_6 ... ok
|
||||
cmove_7 ... ok
|
||||
cmove_8 ... ok
|
||||
cmovg_17 ... ok
|
||||
cmovg_18 ... ok
|
||||
cmovg_19 ... ok
|
||||
cmovg_20 ... ok
|
||||
cmovg_21 ... ok
|
||||
cmovg_22 ... ok
|
||||
cmovg_23 ... ok
|
||||
cmovg_24 ... ok
|
||||
cmovg_25 ... ok
|
||||
cmovg_26 ... ok
|
||||
cmovg_27 ... ok
|
||||
cmovg_28 ... ok
|
||||
cmovg_29 ... ok
|
||||
cmovg_30 ... ok
|
||||
cmovg_31 ... ok
|
||||
cmovg_32 ... ok
|
||||
cmovge_9 ... ok
|
||||
cmovge_10 ... ok
|
||||
cmovge_11 ... ok
|
||||
cmovge_12 ... ok
|
||||
cmovge_13 ... ok
|
||||
cmovge_14 ... ok
|
||||
cmovge_15 ... ok
|
||||
cmovge_16 ... ok
|
||||
cmovl_9 ... ok
|
||||
cmovl_10 ... ok
|
||||
cmovl_11 ... ok
|
||||
cmovl_12 ... ok
|
||||
cmovl_13 ... ok
|
||||
cmovl_14 ... ok
|
||||
cmovl_15 ... ok
|
||||
cmovl_16 ... ok
|
||||
cmovle_17 ... ok
|
||||
cmovle_18 ... ok
|
||||
cmovle_19 ... ok
|
||||
cmovle_20 ... ok
|
||||
cmovle_21 ... ok
|
||||
cmovle_22 ... ok
|
||||
cmovle_23 ... ok
|
||||
cmovle_24 ... ok
|
||||
cmovle_25 ... ok
|
||||
cmovle_26 ... ok
|
||||
cmovle_27 ... ok
|
||||
cmovle_28 ... ok
|
||||
cmovle_29 ... ok
|
||||
cmovle_30 ... ok
|
||||
cmovle_31 ... ok
|
||||
cmovle_32 ... ok
|
||||
cmovna_9 ... ok
|
||||
cmovna_10 ... ok
|
||||
cmovna_11 ... ok
|
||||
cmovna_12 ... ok
|
||||
cmovna_13 ... ok
|
||||
cmovna_14 ... ok
|
||||
cmovna_15 ... ok
|
||||
cmovna_16 ... ok
|
||||
cmovnae_5 ... ok
|
||||
cmovnae_6 ... ok
|
||||
cmovnae_7 ... ok
|
||||
cmovnae_8 ... ok
|
||||
cmovnb_5 ... ok
|
||||
cmovnb_6 ... ok
|
||||
cmovnb_7 ... ok
|
||||
cmovnb_8 ... ok
|
||||
cmovnbe_9 ... ok
|
||||
cmovnbe_10 ... ok
|
||||
cmovnbe_11 ... ok
|
||||
cmovnbe_12 ... ok
|
||||
cmovnbe_13 ... ok
|
||||
cmovnbe_14 ... ok
|
||||
cmovnbe_15 ... ok
|
||||
cmovnbe_16 ... ok
|
||||
cmovnc_5 ... ok
|
||||
cmovnc_6 ... ok
|
||||
cmovnc_7 ... ok
|
||||
cmovnc_8 ... ok
|
||||
cmovne_5 ... ok
|
||||
cmovne_6 ... ok
|
||||
cmovne_7 ... ok
|
||||
cmovne_8 ... ok
|
||||
cmovng_17 ... ok
|
||||
cmovng_18 ... ok
|
||||
cmovng_19 ... ok
|
||||
cmovng_20 ... ok
|
||||
cmovng_21 ... ok
|
||||
cmovng_22 ... ok
|
||||
cmovng_23 ... ok
|
||||
cmovng_24 ... ok
|
||||
cmovng_25 ... ok
|
||||
cmovng_26 ... ok
|
||||
cmovng_27 ... ok
|
||||
cmovng_28 ... ok
|
||||
cmovng_29 ... ok
|
||||
cmovng_30 ... ok
|
||||
cmovng_31 ... ok
|
||||
cmovng_32 ... ok
|
||||
cmovnge_9 ... ok
|
||||
cmovnge_10 ... ok
|
||||
cmovnge_11 ... ok
|
||||
cmovnge_12 ... ok
|
||||
cmovnge_13 ... ok
|
||||
cmovnge_14 ... ok
|
||||
cmovnge_15 ... ok
|
||||
cmovnge_16 ... ok
|
||||
cmovnl_9 ... ok
|
||||
cmovnl_10 ... ok
|
||||
cmovnl_11 ... ok
|
||||
cmovnl_12 ... ok
|
||||
cmovnl_13 ... ok
|
||||
cmovnl_14 ... ok
|
||||
cmovnl_15 ... ok
|
||||
cmovnl_16 ... ok
|
||||
cmovnle_17 ... ok
|
||||
cmovnle_18 ... ok
|
||||
cmovnle_19 ... ok
|
||||
cmovnle_20 ... ok
|
||||
cmovnle_21 ... ok
|
||||
cmovnle_22 ... ok
|
||||
cmovnle_23 ... ok
|
||||
cmovnle_24 ... ok
|
||||
cmovnle_25 ... ok
|
||||
cmovnle_26 ... ok
|
||||
cmovnle_27 ... ok
|
||||
cmovnle_28 ... ok
|
||||
cmovnle_29 ... ok
|
||||
cmovnle_30 ... ok
|
||||
cmovnle_31 ... ok
|
||||
cmovnle_32 ... ok
|
||||
cmovno_5 ... ok
|
||||
cmovno_6 ... ok
|
||||
cmovno_7 ... ok
|
||||
cmovno_8 ... ok
|
||||
cmovnp_5 ... ok
|
||||
cmovnp_6 ... ok
|
||||
cmovnp_7 ... ok
|
||||
cmovnp_8 ... ok
|
||||
cmovns_5 ... ok
|
||||
cmovns_6 ... ok
|
||||
cmovns_7 ... ok
|
||||
cmovns_8 ... ok
|
||||
cmovnz_5 ... ok
|
||||
cmovnz_6 ... ok
|
||||
cmovnz_7 ... ok
|
||||
cmovnz_8 ... ok
|
||||
cmovo_5 ... ok
|
||||
cmovo_6 ... ok
|
||||
cmovo_7 ... ok
|
||||
cmovo_8 ... ok
|
||||
cmovp_5 ... ok
|
||||
cmovp_6 ... ok
|
||||
cmovp_7 ... ok
|
||||
cmovp_8 ... ok
|
||||
cmovs_5 ... ok
|
||||
cmovs_6 ... ok
|
||||
cmovs_7 ... ok
|
||||
cmovs_8 ... ok
|
||||
cmovz_5 ... ok
|
||||
cmovz_6 ... ok
|
||||
cmovz_7 ... ok
|
||||
cmovz_8 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_cmov
|
||||
cpu_test: cmov
|
||||
@@ -1,452 +0,0 @@
|
||||
fabs_1 ... ok
|
||||
fabs_2 ... ok
|
||||
fabs_3 ... ok
|
||||
fabs_4 ... ok
|
||||
fadds_1 ... ok
|
||||
fadds_2 ... ok
|
||||
fadds_3 ... ok
|
||||
fadds_4 ... ok
|
||||
faddl_1 ... ok
|
||||
faddl_2 ... ok
|
||||
faddl_3 ... ok
|
||||
faddl_4 ... ok
|
||||
fadd_1 ... ok
|
||||
fadd_2 ... ok
|
||||
fadd_3 ... ok
|
||||
fadd_4 ... ok
|
||||
fadd_5 ... ok
|
||||
fadd_6 ... ok
|
||||
fadd_7 ... ok
|
||||
fadd_8 ... ok
|
||||
fadd_9 ... ok
|
||||
fadd_10 ... ok
|
||||
fadd_11 ... ok
|
||||
fadd_12 ... ok
|
||||
fadd_13 ... ok
|
||||
fadd_14 ... ok
|
||||
fadd_15 ... ok
|
||||
fadd_16 ... ok
|
||||
faddp_1 ... ok
|
||||
faddp_2 ... ok
|
||||
faddp_3 ... ok
|
||||
faddp_4 ... ok
|
||||
faddp_5 ... ok
|
||||
faddp_6 ... ok
|
||||
faddp_7 ... ok
|
||||
faddp_8 ... ok
|
||||
faddp_9 ... ok
|
||||
faddp_10 ... ok
|
||||
faddp_11 ... ok
|
||||
faddp_12 ... ok
|
||||
faddp_13 ... ok
|
||||
faddp_14 ... ok
|
||||
faddp_15 ... ok
|
||||
faddp_16 ... ok
|
||||
fiadds_1 ... ok
|
||||
fiadds_2 ... ok
|
||||
fiadds_3 ... ok
|
||||
fiadds_4 ... ok
|
||||
fiadds_5 ... ok
|
||||
fiadds_6 ... ok
|
||||
fiadds_7 ... ok
|
||||
fiadds_8 ... ok
|
||||
fiaddl_1 ... ok
|
||||
fiaddl_2 ... ok
|
||||
fiaddl_3 ... ok
|
||||
fiaddl_4 ... ok
|
||||
fiaddl_5 ... ok
|
||||
fiaddl_6 ... ok
|
||||
fiaddl_7 ... ok
|
||||
fiaddl_8 ... ok
|
||||
fcomi_1 ... ok
|
||||
fcomi_2 ... ok
|
||||
fcomi_3 ... ok
|
||||
fcomi_4 ... ok
|
||||
fcomi_5 ... ok
|
||||
fcomi_6 ... ok
|
||||
fcomip_1 ... ok
|
||||
fcomip_2 ... ok
|
||||
fcomip_3 ... ok
|
||||
fcomip_4 ... ok
|
||||
fcomip_5 ... ok
|
||||
fcomip_6 ... ok
|
||||
fucomi_1 ... ok
|
||||
fucomi_2 ... ok
|
||||
fucomi_3 ... ok
|
||||
fucomi_4 ... ok
|
||||
fucomi_5 ... ok
|
||||
fucomi_6 ... ok
|
||||
fucomip_1 ... ok
|
||||
fucomip_2 ... ok
|
||||
fucomip_3 ... ok
|
||||
fucomip_4 ... ok
|
||||
fucomip_5 ... ok
|
||||
fucomip_6 ... ok
|
||||
fchs_1 ... ok
|
||||
fchs_2 ... ok
|
||||
fchs_3 ... ok
|
||||
fchs_4 ... ok
|
||||
fdivs_1 ... ok
|
||||
fdivs_2 ... ok
|
||||
fdivs_3 ... ok
|
||||
fdivs_4 ... ok
|
||||
fdivl_1 ... ok
|
||||
fdivl_2 ... ok
|
||||
fdivl_3 ... ok
|
||||
fdivl_4 ... ok
|
||||
fdiv_1 ... ok
|
||||
fdiv_2 ... ok
|
||||
fdiv_3 ... ok
|
||||
fdiv_4 ... ok
|
||||
fdiv_5 ... ok
|
||||
fdiv_6 ... ok
|
||||
fdiv_7 ... ok
|
||||
fdiv_8 ... ok
|
||||
fdiv_9 ... ok
|
||||
fdiv_10 ... ok
|
||||
fdiv_11 ... ok
|
||||
fdiv_12 ... ok
|
||||
fdiv_13 ... ok
|
||||
fdiv_14 ... ok
|
||||
fdiv_15 ... ok
|
||||
fdiv_16 ... ok
|
||||
fdivp_1 ... ok
|
||||
fdivp_2 ... ok
|
||||
fdivp_3 ... ok
|
||||
fdivp_4 ... ok
|
||||
fdivp_5 ... ok
|
||||
fdivp_6 ... ok
|
||||
fdivp_7 ... ok
|
||||
fdivp_8 ... ok
|
||||
fdivp_9 ... ok
|
||||
fdivp_10 ... ok
|
||||
fdivp_11 ... ok
|
||||
fdivp_12 ... ok
|
||||
fdivp_13 ... ok
|
||||
fdivp_14 ... ok
|
||||
fdivp_15 ... ok
|
||||
fdivp_16 ... ok
|
||||
fidivs_1 ... ok
|
||||
fidivs_2 ... ok
|
||||
fidivs_3 ... ok
|
||||
fidivs_4 ... ok
|
||||
fidivs_5 ... ok
|
||||
fidivs_6 ... ok
|
||||
fidivs_7 ... ok
|
||||
fidivs_8 ... ok
|
||||
fidivl_1 ... ok
|
||||
fidivl_2 ... ok
|
||||
fidivl_3 ... ok
|
||||
fidivl_4 ... ok
|
||||
fidivl_5 ... ok
|
||||
fidivl_6 ... ok
|
||||
fidivl_7 ... ok
|
||||
fidivl_8 ... ok
|
||||
fdivrs_1 ... ok
|
||||
fdivrs_2 ... ok
|
||||
fdivrs_3 ... ok
|
||||
fdivrs_4 ... ok
|
||||
fdivrl_1 ... ok
|
||||
fdivrl_2 ... ok
|
||||
fdivrl_3 ... ok
|
||||
fdivrl_4 ... ok
|
||||
fdivr_1 ... ok
|
||||
fdivr_2 ... ok
|
||||
fdivr_3 ... ok
|
||||
fdivr_4 ... ok
|
||||
fdivr_5 ... ok
|
||||
fdivr_6 ... ok
|
||||
fdivr_7 ... ok
|
||||
fdivr_8 ... ok
|
||||
fdivr_9 ... ok
|
||||
fdivr_10 ... ok
|
||||
fdivr_11 ... ok
|
||||
fdivr_12 ... ok
|
||||
fdivr_13 ... ok
|
||||
fdivr_14 ... ok
|
||||
fdivr_15 ... ok
|
||||
fdivr_16 ... ok
|
||||
fdivrp_1 ... ok
|
||||
fdivrp_2 ... ok
|
||||
fdivrp_3 ... ok
|
||||
fdivrp_4 ... ok
|
||||
fdivrp_5 ... ok
|
||||
fdivrp_6 ... ok
|
||||
fdivrp_7 ... ok
|
||||
fdivrp_8 ... ok
|
||||
fdivrp_9 ... ok
|
||||
fdivrp_10 ... ok
|
||||
fdivrp_11 ... ok
|
||||
fdivrp_12 ... ok
|
||||
fdivrp_13 ... ok
|
||||
fdivrp_14 ... ok
|
||||
fdivrp_15 ... ok
|
||||
fdivrp_16 ... ok
|
||||
fidivrs_1 ... ok
|
||||
fidivrs_2 ... ok
|
||||
fidivrs_3 ... ok
|
||||
fidivrs_4 ... ok
|
||||
fidivrs_5 ... ok
|
||||
fidivrs_6 ... ok
|
||||
fidivrs_7 ... ok
|
||||
fidivrs_8 ... ok
|
||||
fidivrl_1 ... ok
|
||||
fidivrl_2 ... ok
|
||||
fidivrl_3 ... ok
|
||||
fidivrl_4 ... ok
|
||||
fidivrl_5 ... ok
|
||||
fidivrl_6 ... ok
|
||||
fidivrl_7 ... ok
|
||||
fidivrl_8 ... ok
|
||||
filds_1 ... ok
|
||||
filds_2 ... ok
|
||||
filds_3 ... ok
|
||||
filds_4 ... ok
|
||||
fildl_1 ... ok
|
||||
fildl_2 ... ok
|
||||
fildl_3 ... ok
|
||||
fildl_4 ... ok
|
||||
fildq_1 ... ok
|
||||
fildq_2 ... ok
|
||||
fildq_3 ... ok
|
||||
fildq_4 ... ok
|
||||
fists_1 ... ok
|
||||
fists_2 ... ok
|
||||
fists_3 ... ok
|
||||
fists_4 ... ok
|
||||
fists_5 ... ok
|
||||
fists_6 ... ok
|
||||
fists_7 ... ok
|
||||
fists_8 ... ok
|
||||
fistl_1 ... ok
|
||||
fistl_2 ... ok
|
||||
fistl_3 ... ok
|
||||
fistl_4 ... ok
|
||||
fistl_5 ... ok
|
||||
fistl_6 ... ok
|
||||
fistl_7 ... ok
|
||||
fistl_8 ... ok
|
||||
fistps_1 ... ok
|
||||
fistps_2 ... ok
|
||||
fistps_3 ... ok
|
||||
fistps_4 ... ok
|
||||
fistps_5 ... ok
|
||||
fistps_6 ... ok
|
||||
fistps_7 ... ok
|
||||
fistps_8 ... ok
|
||||
fistpl_1 ... ok
|
||||
fistpl_2 ... ok
|
||||
fistpl_3 ... ok
|
||||
fistpl_4 ... ok
|
||||
fistpl_5 ... ok
|
||||
fistpl_6 ... ok
|
||||
fistpl_7 ... ok
|
||||
fistpl_8 ... ok
|
||||
fistpq_1 ... ok
|
||||
fistpq_2 ... ok
|
||||
fistpq_3 ... ok
|
||||
fistpq_4 ... ok
|
||||
fistpq_5 ... ok
|
||||
fistpq_6 ... ok
|
||||
fistpq_7 ... ok
|
||||
fistpq_8 ... ok
|
||||
flds_1 ... ok
|
||||
flds_2 ... ok
|
||||
fldl_1 ... ok
|
||||
fldl_2 ... ok
|
||||
fld_1 ... ok
|
||||
fld_2 ... ok
|
||||
fld_3 ... ok
|
||||
fld1_1 ... ok
|
||||
fldl2t_1 ... ok
|
||||
fldl2e_1 ... ok
|
||||
fldpi_1 ... ok
|
||||
fldlg2_1 ... ok
|
||||
fldln2_1 ... ok
|
||||
fldz_1 ... ok
|
||||
fmuls_1 ... ok
|
||||
fmuls_2 ... ok
|
||||
fmuls_3 ... ok
|
||||
fmuls_4 ... ok
|
||||
fmull_1 ... ok
|
||||
fmull_2 ... ok
|
||||
fmull_3 ... ok
|
||||
fmull_4 ... ok
|
||||
fmul_1 ... ok
|
||||
fmul_2 ... ok
|
||||
fmul_3 ... ok
|
||||
fmul_4 ... ok
|
||||
fmul_5 ... ok
|
||||
fmul_6 ... ok
|
||||
fmul_7 ... ok
|
||||
fmul_8 ... ok
|
||||
fmul_9 ... ok
|
||||
fmul_10 ... ok
|
||||
fmul_11 ... ok
|
||||
fmul_12 ... ok
|
||||
fmul_13 ... ok
|
||||
fmul_14 ... ok
|
||||
fmul_15 ... ok
|
||||
fmul_16 ... ok
|
||||
fmulp_1 ... ok
|
||||
fmulp_2 ... ok
|
||||
fmulp_3 ... ok
|
||||
fmulp_4 ... ok
|
||||
fmulp_5 ... ok
|
||||
fmulp_6 ... ok
|
||||
fmulp_7 ... ok
|
||||
fmulp_8 ... ok
|
||||
fmulp_9 ... ok
|
||||
fmulp_10 ... ok
|
||||
fmulp_11 ... ok
|
||||
fmulp_12 ... ok
|
||||
fmulp_13 ... ok
|
||||
fmulp_14 ... ok
|
||||
fmulp_15 ... ok
|
||||
fmulp_16 ... ok
|
||||
fimuls_1 ... ok
|
||||
fimuls_2 ... ok
|
||||
fimuls_3 ... ok
|
||||
fimuls_4 ... ok
|
||||
fimuls_5 ... ok
|
||||
fimuls_6 ... ok
|
||||
fimuls_7 ... ok
|
||||
fimuls_8 ... ok
|
||||
fimull_1 ... ok
|
||||
fimull_2 ... ok
|
||||
fimull_3 ... ok
|
||||
fimull_4 ... ok
|
||||
fimull_5 ... ok
|
||||
fimull_6 ... ok
|
||||
fimull_7 ... ok
|
||||
fimull_8 ... ok
|
||||
frndint_1 ... ok
|
||||
frndint_2 ... ok
|
||||
frndint_3 ... ok
|
||||
frndint_4 ... ok
|
||||
frndint_5 ... ok
|
||||
frndint_6 ... ok
|
||||
frndint_7 ... ok
|
||||
frndint_8 ... ok
|
||||
frndint_9 ... ok
|
||||
frndint_10 ... ok
|
||||
frndint_11 ... ok
|
||||
frndint_12 ... ok
|
||||
frndint_13 ... ok
|
||||
frndint_14 ... ok
|
||||
frndint_15 ... ok
|
||||
frndint_16 ... ok
|
||||
fsubs_1 ... ok
|
||||
fsubs_2 ... ok
|
||||
fsubs_3 ... ok
|
||||
fsubs_4 ... ok
|
||||
fsubl_1 ... ok
|
||||
fsubl_2 ... ok
|
||||
fsubl_3 ... ok
|
||||
fsubl_4 ... ok
|
||||
fsub_1 ... ok
|
||||
fsub_2 ... ok
|
||||
fsub_3 ... ok
|
||||
fsub_4 ... ok
|
||||
fsub_5 ... ok
|
||||
fsub_6 ... ok
|
||||
fsub_7 ... ok
|
||||
fsub_8 ... ok
|
||||
fsub_9 ... ok
|
||||
fsub_10 ... ok
|
||||
fsub_11 ... ok
|
||||
fsub_12 ... ok
|
||||
fsub_13 ... ok
|
||||
fsub_14 ... ok
|
||||
fsub_15 ... ok
|
||||
fsub_16 ... ok
|
||||
fsubp_1 ... ok
|
||||
fsubp_2 ... ok
|
||||
fsubp_3 ... ok
|
||||
fsubp_4 ... ok
|
||||
fsubp_5 ... ok
|
||||
fsubp_6 ... ok
|
||||
fsubp_7 ... ok
|
||||
fsubp_8 ... ok
|
||||
fsubp_9 ... ok
|
||||
fsubp_10 ... ok
|
||||
fsubp_11 ... ok
|
||||
fsubp_12 ... ok
|
||||
fsubp_13 ... ok
|
||||
fsubp_14 ... ok
|
||||
fsubp_15 ... ok
|
||||
fsubp_16 ... ok
|
||||
fisubs_1 ... ok
|
||||
fisubs_2 ... ok
|
||||
fisubs_3 ... ok
|
||||
fisubs_4 ... ok
|
||||
fisubs_5 ... ok
|
||||
fisubs_6 ... ok
|
||||
fisubs_7 ... ok
|
||||
fisubs_8 ... ok
|
||||
fisubl_1 ... ok
|
||||
fisubl_2 ... ok
|
||||
fisubl_3 ... ok
|
||||
fisubl_4 ... ok
|
||||
fisubl_5 ... ok
|
||||
fisubl_6 ... ok
|
||||
fisubl_7 ... ok
|
||||
fisubl_8 ... ok
|
||||
fsubrs_1 ... ok
|
||||
fsubrs_2 ... ok
|
||||
fsubrs_3 ... ok
|
||||
fsubrs_4 ... ok
|
||||
fsubrl_1 ... ok
|
||||
fsubrl_2 ... ok
|
||||
fsubrl_3 ... ok
|
||||
fsubrl_4 ... ok
|
||||
fsubr_1 ... ok
|
||||
fsubr_2 ... ok
|
||||
fsubr_3 ... ok
|
||||
fsubr_4 ... ok
|
||||
fsubr_5 ... ok
|
||||
fsubr_6 ... ok
|
||||
fsubr_7 ... ok
|
||||
fsubr_8 ... ok
|
||||
fsubr_9 ... ok
|
||||
fsubr_10 ... ok
|
||||
fsubr_11 ... ok
|
||||
fsubr_12 ... ok
|
||||
fsubr_13 ... ok
|
||||
fsubr_14 ... ok
|
||||
fsubr_15 ... ok
|
||||
fsubr_16 ... ok
|
||||
fsubrp_1 ... ok
|
||||
fsubrp_2 ... ok
|
||||
fsubrp_3 ... ok
|
||||
fsubrp_4 ... ok
|
||||
fsubrp_5 ... ok
|
||||
fsubrp_6 ... ok
|
||||
fsubrp_7 ... ok
|
||||
fsubrp_8 ... ok
|
||||
fsubrp_9 ... ok
|
||||
fsubrp_10 ... ok
|
||||
fsubrp_11 ... ok
|
||||
fsubrp_12 ... ok
|
||||
fsubrp_13 ... ok
|
||||
fsubrp_14 ... ok
|
||||
fsubrp_15 ... ok
|
||||
fsubrp_16 ... ok
|
||||
fisubrs_1 ... ok
|
||||
fisubrs_2 ... ok
|
||||
fisubrs_3 ... ok
|
||||
fisubrs_4 ... ok
|
||||
fisubrs_5 ... ok
|
||||
fisubrs_6 ... ok
|
||||
fisubrs_7 ... ok
|
||||
fisubrs_8 ... ok
|
||||
fisubrl_1 ... ok
|
||||
fisubrl_2 ... ok
|
||||
fisubrl_3 ... ok
|
||||
fisubrl_4 ... ok
|
||||
fisubrl_5 ... ok
|
||||
fisubrl_6 ... ok
|
||||
fisubrl_7 ... ok
|
||||
fisubrl_8 ... ok
|
||||
fxch_1 ... ok
|
||||
fxch_2 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_fpu
|
||||
cpu_test: fpu
|
||||
@@ -1,103 +0,0 @@
|
||||
movd_1 ... ok
|
||||
movd_2 ... ok
|
||||
movd_3 ... ok
|
||||
movd_4 ... ok
|
||||
movq_1 ... ok
|
||||
movq_2 ... ok
|
||||
movq_3 ... ok
|
||||
packssdw_1 ... ok
|
||||
packssdw_2 ... ok
|
||||
packsswb_1 ... ok
|
||||
packsswb_2 ... ok
|
||||
packuswb_1 ... ok
|
||||
packuswb_2 ... ok
|
||||
paddb_1 ... ok
|
||||
paddb_2 ... ok
|
||||
paddd_1 ... ok
|
||||
paddd_2 ... ok
|
||||
paddsb_1 ... ok
|
||||
paddsb_2 ... ok
|
||||
paddsw_1 ... ok
|
||||
paddsw_2 ... ok
|
||||
paddusb_1 ... ok
|
||||
paddusb_2 ... ok
|
||||
paddusw_1 ... ok
|
||||
paddusw_2 ... ok
|
||||
paddw_1 ... ok
|
||||
paddw_2 ... ok
|
||||
pand_1 ... ok
|
||||
pand_2 ... ok
|
||||
pandn_1 ... ok
|
||||
pandn_2 ... ok
|
||||
pcmpeqb_1 ... ok
|
||||
pcmpeqb_2 ... ok
|
||||
pcmpeqd_1 ... ok
|
||||
pcmpeqd_2 ... ok
|
||||
pcmpeqw_1 ... ok
|
||||
pcmpeqw_2 ... ok
|
||||
pcmpgtb_1 ... ok
|
||||
pcmpgtb_2 ... ok
|
||||
pcmpgtd_1 ... ok
|
||||
pcmpgtd_2 ... ok
|
||||
pcmpgtw_1 ... ok
|
||||
pcmpgtw_2 ... ok
|
||||
pmaddwd_1 ... ok
|
||||
pmaddwd_2 ... ok
|
||||
pmulhw_1 ... ok
|
||||
pmulhw_2 ... ok
|
||||
pmullw_1 ... ok
|
||||
pmullw_2 ... ok
|
||||
por_1 ... ok
|
||||
por_2 ... ok
|
||||
pslld_1 ... ok
|
||||
pslld_2 ... ok
|
||||
pslld_3 ... ok
|
||||
psllq_1 ... ok
|
||||
psllq_2 ... ok
|
||||
psllq_3 ... ok
|
||||
psllw_1 ... ok
|
||||
psllw_2 ... ok
|
||||
psllw_3 ... ok
|
||||
psrad_1 ... ok
|
||||
psrad_2 ... ok
|
||||
psrad_3 ... ok
|
||||
psraw_1 ... ok
|
||||
psraw_2 ... ok
|
||||
psraw_3 ... ok
|
||||
psrld_1 ... ok
|
||||
psrld_2 ... ok
|
||||
psrld_3 ... ok
|
||||
psrlq_1 ... ok
|
||||
psrlq_2 ... ok
|
||||
psrlq_3 ... ok
|
||||
psrlw_1 ... ok
|
||||
psrlw_2 ... ok
|
||||
psrlw_3 ... ok
|
||||
psubb_1 ... ok
|
||||
psubb_2 ... ok
|
||||
psubd_1 ... ok
|
||||
psubd_2 ... ok
|
||||
psubsb_1 ... ok
|
||||
psubsb_2 ... ok
|
||||
psubsw_1 ... ok
|
||||
psubsw_2 ... ok
|
||||
psubusb_1 ... ok
|
||||
psubusb_2 ... ok
|
||||
psubusw_1 ... ok
|
||||
psubusw_2 ... ok
|
||||
psubw_1 ... ok
|
||||
psubw_2 ... ok
|
||||
punpckhbw_1 ... ok
|
||||
punpckhbw_2 ... ok
|
||||
punpckhdq_1 ... ok
|
||||
punpckhdq_2 ... ok
|
||||
punpckhwd_1 ... ok
|
||||
punpckhwd_2 ... ok
|
||||
punpcklbw_1 ... ok
|
||||
punpcklbw_2 ... ok
|
||||
punpckldq_1 ... ok
|
||||
punpckldq_2 ... ok
|
||||
punpcklwd_1 ... ok
|
||||
punpcklwd_2 ... ok
|
||||
pxor_1 ... ok
|
||||
pxor_2 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_mmx
|
||||
cpu_test: mmx
|
||||
@@ -1,29 +0,0 @@
|
||||
movntq_1 ... ok
|
||||
pavgb_1 ... ok
|
||||
pavgb_2 ... ok
|
||||
pavgw_1 ... ok
|
||||
pavgw_2 ... ok
|
||||
pextrw_1 ... ok
|
||||
pextrw_2 ... ok
|
||||
pextrw_3 ... ok
|
||||
pextrw_4 ... ok
|
||||
pinsrw_1 ... ok
|
||||
pinsrw_2 ... ok
|
||||
pinsrw_3 ... ok
|
||||
pinsrw_4 ... ok
|
||||
pmaxsw_1 ... ok
|
||||
pmaxsw_2 ... ok
|
||||
pmaxub_1 ... ok
|
||||
pmaxub_2 ... ok
|
||||
pminsw_1 ... ok
|
||||
pminsw_2 ... ok
|
||||
pminub_1 ... ok
|
||||
pminub_2 ... ok
|
||||
pmovmskb_1 ... ok
|
||||
pmulhuw_1 ... ok
|
||||
pmulhuw_2 ... ok
|
||||
psadbw_1 ... ok
|
||||
psadbw_2 ... ok
|
||||
pshufw_1 ... ok
|
||||
pshufw_2 ... ok
|
||||
sfence_1 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_mmxext
|
||||
cpu_test: mmxext
|
||||
@@ -1,142 +0,0 @@
|
||||
addps_1 ... ok
|
||||
addps_2 ... ok
|
||||
addss_1 ... ok
|
||||
addss_2 ... ok
|
||||
andnps_1 ... ok
|
||||
andnps_2 ... ok
|
||||
andps_1 ... ok
|
||||
andps_2 ... ok
|
||||
cmpeqps_1 ... ok
|
||||
cmpeqps_2 ... ok
|
||||
cmpeqss_1 ... ok
|
||||
cmpeqss_2 ... ok
|
||||
cmpleps_1 ... ok
|
||||
cmpleps_2 ... ok
|
||||
cmpless_1 ... ok
|
||||
cmpless_2 ... ok
|
||||
cmpltps_1 ... ok
|
||||
cmpltps_2 ... ok
|
||||
cmpltss_1 ... ok
|
||||
cmpltss_2 ... ok
|
||||
cmpneqps_1 ... ok
|
||||
cmpneqps_2 ... ok
|
||||
cmpneqss_1 ... ok
|
||||
cmpneqss_2 ... ok
|
||||
cmpnleps_1 ... ok
|
||||
cmpnleps_2 ... ok
|
||||
cmpnless_1 ... ok
|
||||
cmpnless_2 ... ok
|
||||
cmpnltps_1 ... ok
|
||||
cmpnltps_2 ... ok
|
||||
cmpnltss_1 ... ok
|
||||
cmpnltss_2 ... ok
|
||||
comiss_1 ... ok
|
||||
comiss_2 ... ok
|
||||
comiss_3 ... ok
|
||||
comiss_4 ... ok
|
||||
comiss_5 ... ok
|
||||
comiss_6 ... ok
|
||||
cvtpi2ps_1 ... ok
|
||||
cvtpi2ps_2 ... ok
|
||||
cvtps2pi_1 ... ok
|
||||
cvtps2pi_2 ... ok
|
||||
cvtsi2ss_1 ... ok
|
||||
cvtsi2ss_2 ... ok
|
||||
cvtss2si_1 ... ok
|
||||
cvtss2si_2 ... ok
|
||||
cvttps2pi_1 ... ok
|
||||
cvttps2pi_2 ... ok
|
||||
cvttss2si_1 ... ok
|
||||
cvttss2si_2 ... ok
|
||||
divps_1 ... ok
|
||||
divps_2 ... ok
|
||||
divss_1 ... ok
|
||||
divss_2 ... ok
|
||||
maxps_1 ... ok
|
||||
maxps_2 ... ok
|
||||
maxss_1 ... ok
|
||||
maxss_2 ... ok
|
||||
minps_1 ... ok
|
||||
minps_2 ... ok
|
||||
minss_1 ... ok
|
||||
minss_2 ... ok
|
||||
movaps_1 ... ok
|
||||
movaps_2 ... ok
|
||||
movhlps_1 ... ok
|
||||
movhps_1 ... ok
|
||||
movhps_2 ... ok
|
||||
movlhps_1 ... ok
|
||||
movlps_1 ... ok
|
||||
movlps_2 ... ok
|
||||
movmskps_1 ... ok
|
||||
movntps_1 ... ok
|
||||
movntq_1 ... ok
|
||||
movss_1 ... ok
|
||||
movss_2 ... ok
|
||||
movss_3 ... ok
|
||||
movups_1 ... ok
|
||||
movups_2 ... ok
|
||||
mulps_1 ... ok
|
||||
mulps_2 ... ok
|
||||
mulss_1 ... ok
|
||||
mulss_2 ... ok
|
||||
orps_1 ... ok
|
||||
orps_2 ... ok
|
||||
pavgb_1 ... ok
|
||||
pavgb_2 ... ok
|
||||
pavgw_1 ... ok
|
||||
pavgw_2 ... ok
|
||||
pextrw_1 ... ok
|
||||
pextrw_2 ... ok
|
||||
pextrw_3 ... ok
|
||||
pextrw_4 ... ok
|
||||
pinsrw_1 ... ok
|
||||
pinsrw_2 ... ok
|
||||
pinsrw_3 ... ok
|
||||
pinsrw_4 ... ok
|
||||
pmaxsw_1 ... ok
|
||||
pmaxsw_2 ... ok
|
||||
pmaxub_1 ... ok
|
||||
pmaxub_2 ... ok
|
||||
pminsw_1 ... ok
|
||||
pminsw_2 ... ok
|
||||
pminub_1 ... ok
|
||||
pminub_2 ... ok
|
||||
pmovmskb_1 ... ok
|
||||
pmulhuw_1 ... ok
|
||||
pmulhuw_2 ... ok
|
||||
psadbw_1 ... ok
|
||||
psadbw_2 ... ok
|
||||
pshufw_1 ... ok
|
||||
pshufw_2 ... ok
|
||||
rcpps_1 ... ok
|
||||
rcpps_2 ... ok
|
||||
rcpss_1 ... ok
|
||||
rcpss_2 ... ok
|
||||
rsqrtps_1 ... ok
|
||||
rsqrtps_2 ... ok
|
||||
rsqrtss_1 ... ok
|
||||
rsqrtss_2 ... ok
|
||||
sfence_1 ... ok
|
||||
shufps_1 ... ok
|
||||
shufps_2 ... ok
|
||||
sqrtps_1 ... ok
|
||||
sqrtps_2 ... ok
|
||||
sqrtss_1 ... ok
|
||||
sqrtss_2 ... ok
|
||||
subps_1 ... ok
|
||||
subps_2 ... ok
|
||||
subss_1 ... ok
|
||||
subss_2 ... ok
|
||||
ucomiss_1 ... ok
|
||||
ucomiss_2 ... ok
|
||||
ucomiss_3 ... ok
|
||||
ucomiss_4 ... ok
|
||||
ucomiss_5 ... ok
|
||||
ucomiss_6 ... ok
|
||||
unpckhps_1 ... ok
|
||||
unpckhps_2 ... ok
|
||||
unpcklps_1 ... ok
|
||||
unpcklps_2 ... ok
|
||||
xorps_1 ... ok
|
||||
xorps_2 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_sse
|
||||
cpu_test: sse
|
||||
@@ -1,294 +0,0 @@
|
||||
addpd_1 ... ok
|
||||
addpd_2 ... ok
|
||||
addsd_1 ... ok
|
||||
addsd_2 ... ok
|
||||
andpd_1 ... ok
|
||||
andpd_2 ... ok
|
||||
andnpd_1 ... ok
|
||||
andnpd_2 ... ok
|
||||
cmpeqpd_1 ... ok
|
||||
cmpeqpd_2 ... ok
|
||||
cmpltpd_1 ... ok
|
||||
cmpltpd_2 ... ok
|
||||
cmplepd_1 ... ok
|
||||
cmplepd_2 ... ok
|
||||
cmpneqpd_1 ... ok
|
||||
cmpneqpd_2 ... ok
|
||||
cmpnltpd_1 ... ok
|
||||
cmpnltpd_2 ... ok
|
||||
cmpnlepd_1 ... ok
|
||||
cmpnlepd_2 ... ok
|
||||
cmpeqsd_1 ... ok
|
||||
cmpeqsd_2 ... ok
|
||||
cmpltsd_1 ... ok
|
||||
cmpltsd_2 ... ok
|
||||
cmplesd_1 ... ok
|
||||
cmplesd_2 ... ok
|
||||
cmpneqsd_1 ... ok
|
||||
cmpneqsd_2 ... ok
|
||||
cmpnltsd_1 ... ok
|
||||
cmpnltsd_2 ... ok
|
||||
cmpnlesd_1 ... ok
|
||||
cmpnlesd_2 ... ok
|
||||
comisd_1 ... ok
|
||||
comisd_2 ... ok
|
||||
comisd_3 ... ok
|
||||
comisd_4 ... ok
|
||||
comisd_5 ... ok
|
||||
comisd_6 ... ok
|
||||
cvtdq2pd_1 ... ok
|
||||
cvtdq2pd_2 ... ok
|
||||
cvtdq2ps_1 ... ok
|
||||
cvtdq2ps_2 ... ok
|
||||
cvtpd2dq_1 ... ok
|
||||
cvtpd2dq_2 ... ok
|
||||
cvtpd2pi_1 ... ok
|
||||
cvtpd2pi_2 ... ok
|
||||
cvtpd2ps_1 ... ok
|
||||
cvtpd2ps_2 ... ok
|
||||
cvtpi2pd_1 ... ok
|
||||
cvtpi2pd_2 ... ok
|
||||
cvtps2dq_1 ... ok
|
||||
cvtps2dq_2 ... ok
|
||||
cvtps2pd_1 ... ok
|
||||
cvtps2pd_2 ... ok
|
||||
cvtsd2si_1 ... ok
|
||||
cvtsd2si_2 ... ok
|
||||
cvtsd2ss_1 ... ok
|
||||
cvtsd2ss_2 ... ok
|
||||
cvtsi2sd_1 ... ok
|
||||
cvtsi2sd_2 ... ok
|
||||
cvtss2sd_1 ... ok
|
||||
cvtss2sd_2 ... ok
|
||||
cvttpd2pi_1 ... ok
|
||||
cvttpd2pi_2 ... ok
|
||||
cvttpd2dq_1 ... ok
|
||||
cvttpd2dq_2 ... ok
|
||||
cvttps2dq_1 ... ok
|
||||
cvttps2dq_2 ... ok
|
||||
cvttsd2si_1 ... ok
|
||||
cvttsd2si_2 ... ok
|
||||
divpd_1 ... ok
|
||||
divpd_2 ... ok
|
||||
divsd_1 ... ok
|
||||
divsd_2 ... ok
|
||||
lfence_1 ... ok
|
||||
maxpd_1 ... ok
|
||||
maxpd_2 ... ok
|
||||
maxsd_1 ... ok
|
||||
maxsd_2 ... ok
|
||||
mfence_1 ... ok
|
||||
minpd_1 ... ok
|
||||
minpd_2 ... ok
|
||||
minsd_1 ... ok
|
||||
minsd_2 ... ok
|
||||
movapd_1 ... ok
|
||||
movapd_2 ... ok
|
||||
movd_1 ... ok
|
||||
movd_2 ... ok
|
||||
movd_3 ... ok
|
||||
movd_4 ... ok
|
||||
movdqa_1 ... ok
|
||||
movdqa_2 ... ok
|
||||
movdqa_3 ... ok
|
||||
movdqu_1 ... ok
|
||||
movdqu_2 ... ok
|
||||
movdqu_3 ... ok
|
||||
movdq2q_1 ... ok
|
||||
movhpd_1 ... ok
|
||||
movhpd_2 ... ok
|
||||
movlpd_1 ... ok
|
||||
movlpd_2 ... ok
|
||||
movmskpd_1 ... ok
|
||||
movntdq_1 ... ok
|
||||
movnti_1 ... ok
|
||||
movntpd_1 ... ok
|
||||
movq2dq_1 ... ok
|
||||
movsd_1 ... ok
|
||||
movsd_2 ... ok
|
||||
movsd_3 ... ok
|
||||
movupd_1 ... ok
|
||||
movupd_2 ... ok
|
||||
mulpd_1 ... ok
|
||||
mulpd_2 ... ok
|
||||
mulsd_1 ... ok
|
||||
mulsd_2 ... ok
|
||||
orpd_1 ... ok
|
||||
orpd_2 ... ok
|
||||
packssdw_1 ... ok
|
||||
packssdw_2 ... ok
|
||||
packsswb_1 ... ok
|
||||
packsswb_2 ... ok
|
||||
packuswb_1 ... ok
|
||||
packuswb_2 ... ok
|
||||
paddb_1 ... ok
|
||||
paddb_2 ... ok
|
||||
paddd_1 ... ok
|
||||
paddd_2 ... ok
|
||||
paddq_1 ... ok
|
||||
paddq_2 ... ok
|
||||
paddq_3 ... ok
|
||||
paddq_4 ... ok
|
||||
paddsb_1 ... ok
|
||||
paddsb_2 ... ok
|
||||
paddsw_1 ... ok
|
||||
paddsw_2 ... ok
|
||||
paddusb_1 ... ok
|
||||
paddusb_2 ... ok
|
||||
paddusw_1 ... ok
|
||||
paddusw_2 ... ok
|
||||
paddw_1 ... ok
|
||||
paddw_2 ... ok
|
||||
pand_1 ... ok
|
||||
pand_2 ... ok
|
||||
pandn_1 ... ok
|
||||
pandn_2 ... ok
|
||||
pavgb_1 ... ok
|
||||
pavgb_2 ... ok
|
||||
pavgw_1 ... ok
|
||||
pavgw_2 ... ok
|
||||
pcmpeqb_1 ... ok
|
||||
pcmpeqb_2 ... ok
|
||||
pcmpeqd_1 ... ok
|
||||
pcmpeqd_2 ... ok
|
||||
pcmpeqw_1 ... ok
|
||||
pcmpeqw_2 ... ok
|
||||
pcmpgtb_1 ... ok
|
||||
pcmpgtb_2 ... ok
|
||||
pcmpgtd_1 ... ok
|
||||
pcmpgtd_2 ... ok
|
||||
pcmpgtw_1 ... ok
|
||||
pcmpgtw_2 ... ok
|
||||
pextrw_1 ... ok
|
||||
pextrw_2 ... ok
|
||||
pextrw_3 ... ok
|
||||
pextrw_4 ... ok
|
||||
pextrw_5 ... ok
|
||||
pextrw_6 ... ok
|
||||
pextrw_7 ... ok
|
||||
pextrw_8 ... ok
|
||||
pinsrw_1 ... ok
|
||||
pinsrw_2 ... ok
|
||||
pinsrw_3 ... ok
|
||||
pinsrw_4 ... ok
|
||||
pinsrw_5 ... ok
|
||||
pinsrw_6 ... ok
|
||||
pinsrw_7 ... ok
|
||||
pinsrw_8 ... ok
|
||||
pmaddwd_1 ... ok
|
||||
pmaddwd_2 ... ok
|
||||
pmaxsw_1 ... ok
|
||||
pmaxsw_2 ... ok
|
||||
pmaxub_1 ... ok
|
||||
pmaxub_2 ... ok
|
||||
pminsw_1 ... ok
|
||||
pminsw_2 ... ok
|
||||
pminub_1 ... ok
|
||||
pminub_2 ... ok
|
||||
pmovmskb_1 ... ok
|
||||
pmulhuw_1 ... ok
|
||||
pmulhuw_2 ... ok
|
||||
pmulhw_1 ... ok
|
||||
pmulhw_2 ... ok
|
||||
pmullw_1 ... ok
|
||||
pmullw_2 ... ok
|
||||
pmuludq_1 ... ok
|
||||
pmuludq_2 ... ok
|
||||
pmuludq_3 ... ok
|
||||
pmuludq_4 ... ok
|
||||
por_1 ... ok
|
||||
por_2 ... ok
|
||||
psadbw_1 ... ok
|
||||
psadbw_2 ... ok
|
||||
pshufd_1 ... ok
|
||||
pshufd_2 ... ok
|
||||
pshufhw_1 ... ok
|
||||
pshufhw_2 ... ok
|
||||
pshuflw_1 ... ok
|
||||
pshuflw_2 ... ok
|
||||
pslld_1 ... ok
|
||||
pslld_2 ... ok
|
||||
pslld_3 ... ok
|
||||
pslldq_1 ... ok
|
||||
pslldq_2 ... ok
|
||||
psllq_1 ... ok
|
||||
psllq_2 ... ok
|
||||
psllq_3 ... ok
|
||||
psllw_1 ... ok
|
||||
psllw_2 ... ok
|
||||
psllw_3 ... ok
|
||||
psrad_1 ... ok
|
||||
psrad_2 ... ok
|
||||
psrad_3 ... ok
|
||||
psraw_1 ... ok
|
||||
psraw_2 ... ok
|
||||
psraw_3 ... ok
|
||||
psrld_1 ... ok
|
||||
psrld_2 ... ok
|
||||
psrld_3 ... ok
|
||||
psrldq_1 ... ok
|
||||
psrldq_2 ... ok
|
||||
psrlq_1 ... ok
|
||||
psrlq_2 ... ok
|
||||
psrlq_3 ... ok
|
||||
psrlw_1 ... ok
|
||||
psrlw_2 ... ok
|
||||
psrlw_3 ... ok
|
||||
psubb_1 ... ok
|
||||
psubb_2 ... ok
|
||||
psubd_1 ... ok
|
||||
psubd_2 ... ok
|
||||
psubq_1 ... ok
|
||||
psubq_2 ... ok
|
||||
psubq_3 ... ok
|
||||
psubq_4 ... ok
|
||||
psubsb_1 ... ok
|
||||
psubsb_2 ... ok
|
||||
psubsw_1 ... ok
|
||||
psubsw_2 ... ok
|
||||
psubusb_1 ... ok
|
||||
psubusb_2 ... ok
|
||||
psubusw_1 ... ok
|
||||
psubusw_2 ... ok
|
||||
psubw_1 ... ok
|
||||
psubw_2 ... ok
|
||||
punpckhbw_1 ... ok
|
||||
punpckhbw_2 ... ok
|
||||
punpckhdq_1 ... ok
|
||||
punpckhdq_2 ... ok
|
||||
punpckhqdq_1 ... ok
|
||||
punpckhqdq_2 ... ok
|
||||
punpckhwd_1 ... ok
|
||||
punpckhwd_2 ... ok
|
||||
punpcklbw_1 ... ok
|
||||
punpcklbw_2 ... ok
|
||||
punpckldq_1 ... ok
|
||||
punpckldq_2 ... ok
|
||||
punpcklqdq_1 ... ok
|
||||
punpcklqdq_2 ... ok
|
||||
punpcklwd_1 ... ok
|
||||
punpcklwd_2 ... ok
|
||||
pxor_1 ... ok
|
||||
pxor_2 ... ok
|
||||
shufpd_1 ... ok
|
||||
shufpd_2 ... ok
|
||||
sqrtpd_1 ... ok
|
||||
sqrtpd_2 ... ok
|
||||
sqrtsd_1 ... ok
|
||||
sqrtsd_2 ... ok
|
||||
subpd_1 ... ok
|
||||
subpd_2 ... ok
|
||||
subsd_1 ... ok
|
||||
subsd_2 ... ok
|
||||
ucomisd_1 ... ok
|
||||
ucomisd_2 ... ok
|
||||
ucomisd_3 ... ok
|
||||
ucomisd_4 ... ok
|
||||
ucomisd_5 ... ok
|
||||
ucomisd_6 ... ok
|
||||
unpckhpd_1 ... ok
|
||||
unpckhpd_2 ... ok
|
||||
unpcklpd_1 ... ok
|
||||
unpcklpd_2 ... ok
|
||||
xorpd_1 ... ok
|
||||
xorpd_2 ... ok
|
||||
@@ -1,3 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../none/tests/insn_sse2
|
||||
cpu_test: sse2
|
||||
@@ -1,27 +0,0 @@
|
||||
Source and destination overlap in memcpy(0x........, 0x........, 21)
|
||||
at 0x........: memcpy (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:40)
|
||||
|
||||
Source and destination overlap in memcpy(0x........, 0x........, 21)
|
||||
at 0x........: memcpy (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:42)
|
||||
|
||||
Source and destination overlap in strncpy(0x........, 0x........, 21)
|
||||
at 0x........: strncpy (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:45)
|
||||
|
||||
Source and destination overlap in strncpy(0x........, 0x........, 21)
|
||||
at 0x........: strncpy (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:47)
|
||||
|
||||
Source and destination overlap in strcpy(0x........, 0x........)
|
||||
at 0x........: strcpy (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:54)
|
||||
|
||||
Source and destination overlap in strncat(0x........, 0x........, 21)
|
||||
at 0x........: strncat (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:112)
|
||||
|
||||
Source and destination overlap in strncat(0x........, 0x........, 21)
|
||||
at 0x........: strncat (mac_replace_strmem.c:...)
|
||||
by 0x........: main (overlap.c:113)
|
||||
@@ -1,11 +0,0 @@
|
||||
`_________________________________________________'
|
||||
`abcdefghijklmnopqrstuvwxyz'
|
||||
`abcdefghijklmnopqrstuvwxy________________________'
|
||||
`abcdefghijklmnopqrstuvwxyz_______________________'
|
||||
`abcdefghijklmnopqrstuvwxyz'
|
||||
|
||||
`ABCDEFG'
|
||||
`ABCDEFGabcdefghijklmnopqrstuvwxyz'
|
||||
`ABCDEFGabcdefghijklmnopqrstuvwxy'
|
||||
`ABCDEFGabcdefghijklmnopqrstuvwxyz'
|
||||
`ABCDEFGabcdefghijklmnopqrstuvwxyz'
|
||||
@@ -1,2 +0,0 @@
|
||||
vgopts: -q
|
||||
prog: ../../memcheck/tests/overlap
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
Attempting too-big malloc()...
|
||||
Attempting too-big mmap()...
|
||||
|
||||
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
|
||||
malloc/free: in use at exit: 0 bytes in 0 blocks.
|
||||
malloc/free: 1 allocs, 0 frees, 2145386496 bytes allocated.
|
||||
For a detailed leak analysis, rerun with: --leak-check=yes
|
||||
For counts of detected errors, rerun with: -v
|
||||
@@ -1 +0,0 @@
|
||||
prog: ../../tests/toobig-allocs
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
run ()
|
||||
{
|
||||
echo "running: $*"
|
||||
eval $*
|
||||
|
||||
if test $? != 0 ; then
|
||||
echo "error: while running '$*'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run aclocal
|
||||
run autoheader
|
||||
run automake -a
|
||||
run autoconf
|
||||
@@ -1,3 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
valgrind-listener
|
||||
@@ -1,4 +0,0 @@
|
||||
/.cvsignore/1.1/Tue Feb 25 01:48:11 2003//
|
||||
/Makefile.am/1.9/Wed Sep 1 23:20:46 2004//
|
||||
/valgrind-listener.c/1.13/Wed Sep 1 23:58:13 2004//
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/auxprogs
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,9 +0,0 @@
|
||||
include $(top_srcdir)/Makefile.all.am
|
||||
include $(top_srcdir)/Makefile.core-AM_CPPFLAGS.am
|
||||
|
||||
AM_CFLAGS = $(WERROR) -Winline -Wall -O -g
|
||||
|
||||
bin_PROGRAMS = valgrind-listener
|
||||
|
||||
valgrind_listener_SOURCES = valgrind-listener.c
|
||||
|
||||
@@ -1,400 +0,0 @@
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- A simple program to listen for valgrind logfile data. ---*/
|
||||
/*--- valgrind-listener.c ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
This file is part of Valgrind, an extensible x86 protected-mode
|
||||
emulator for monitoring program execution on x86-Unixes.
|
||||
|
||||
Copyright (C) 2000-2004 Julian Seward
|
||||
jseward@acm.org
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The GNU General Public License is contained in the file COPYING.
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
/* For VG_CLO_DEFAULT_LOGPORT and VG_BUGS_TO. */
|
||||
#include "core.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
/* The maximum allowable number concurrent connections. */
|
||||
#define M_CONNECTIONS 50
|
||||
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
__attribute__ ((noreturn))
|
||||
static void panic ( Char* str )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\nvalgrind-listener: the "
|
||||
"`impossible' happened:\n %s\n", str);
|
||||
fprintf(stderr,
|
||||
"Please report this bug at: %s\n\n", VG_BUGS_TO);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__attribute__ ((noreturn))
|
||||
static void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char* fn )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\nvalgrind-listener: %s:%d (%s): Assertion `%s' failed.\n",
|
||||
file, line, fn, expr );
|
||||
fprintf(stderr,
|
||||
"Please report this bug at: %s\n\n", VG_BUGS_TO);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#undef assert
|
||||
#undef VG__STRING
|
||||
|
||||
#define VG__STRING(__str) #__str
|
||||
#define assert(expr) \
|
||||
((void) ((expr) ? 0 : \
|
||||
(my_assert_fail (VG__STRING(expr), \
|
||||
__FILE__, __LINE__, \
|
||||
__PRETTY_FUNCTION__), 0)))
|
||||
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
/* holds the fds for connections; zero if slot not in use. */
|
||||
int conn_count = 0;
|
||||
int conn_fd[M_CONNECTIONS];
|
||||
struct pollfd conn_pollfd[M_CONNECTIONS];
|
||||
|
||||
|
||||
void set_nonblocking ( int sd )
|
||||
{
|
||||
int res;
|
||||
res = fcntl(sd, F_GETFL);
|
||||
res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
|
||||
if (res != 0) {
|
||||
perror("fcntl failed");
|
||||
panic("set_nonblocking");
|
||||
}
|
||||
}
|
||||
|
||||
void set_blocking ( int sd )
|
||||
{
|
||||
int res;
|
||||
res = fcntl(sd, F_GETFL);
|
||||
res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
|
||||
if (res != 0) {
|
||||
perror("fcntl failed");
|
||||
panic("set_blocking");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void copyout ( char* buf, int nbuf )
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
fprintf(stdout, "\n(%d) ", conn_count);
|
||||
} else {
|
||||
fwrite(&buf[i], 1, 1, stdout);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int read_from_sd ( int sd )
|
||||
{
|
||||
char buf[100];
|
||||
int n;
|
||||
|
||||
set_blocking(sd);
|
||||
n = read(sd, buf, 99);
|
||||
if (n <= 0) return 0; /* closed */
|
||||
copyout(buf, n);
|
||||
|
||||
set_nonblocking(sd);
|
||||
while (1) {
|
||||
n = read(sd, buf, 100);
|
||||
if (n <= 0) return 1; /* not closed */
|
||||
copyout(buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void snooze ( void )
|
||||
{
|
||||
struct timespec req;
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = 200 * 1000 * 1000;
|
||||
nanosleep(&req,NULL);
|
||||
}
|
||||
|
||||
|
||||
/* returns 0 if invalid, else port # */
|
||||
int atoi_portno ( char* str )
|
||||
{
|
||||
int n = 0;
|
||||
while (1) {
|
||||
if (*str == 0)
|
||||
break;
|
||||
if (*str < '0' || *str > '9')
|
||||
return 0;
|
||||
n = 10*n + (int)(*str - '0');
|
||||
str++;
|
||||
if (n >= 65536)
|
||||
return 0;
|
||||
}
|
||||
if (n < 1024)
|
||||
return 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void usage ( void )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"usage is:\n"
|
||||
"\n"
|
||||
" valgrind-listener [--exit-at-zero|-e] [port-number]\n"
|
||||
"\n"
|
||||
" where --exit-at-zero or -e causes the listener to exit\n"
|
||||
" when the number of connections falls back to zero\n"
|
||||
" (the default is to keep listening forever)\n"
|
||||
"\n"
|
||||
" port-number is the default port on which to listen for\n"
|
||||
" connections. It must be between 1024 and 65535.\n"
|
||||
" Current default is %d.\n"
|
||||
"\n"
|
||||
,
|
||||
VG_CLO_DEFAULT_LOGPORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void banner ( char* str )
|
||||
{
|
||||
time_t t;
|
||||
t = time(NULL);
|
||||
printf("valgrind-listener %s at %s", str, ctime(&t));
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
void exit_routine ( void )
|
||||
{
|
||||
banner("exited");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void sigint_handler ( int signo )
|
||||
{
|
||||
exit_routine();
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
int i, j, k, res, one;
|
||||
int main_sd, new_sd, client_len;
|
||||
struct sockaddr_in client_addr, server_addr;
|
||||
|
||||
char /*bool*/ exit_when_zero = 0;
|
||||
int port = VG_CLO_DEFAULT_LOGPORT;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (0==strcmp(argv[i], "--exit-at-zero")
|
||||
|| 0==strcmp(argv[i], "-e")) {
|
||||
exit_when_zero = 1;
|
||||
}
|
||||
else
|
||||
if (atoi_portno(argv[i]) > 0) {
|
||||
port = atoi_portno(argv[i]);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
|
||||
banner("started");
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
conn_count = 0;
|
||||
for (i = 0; i < M_CONNECTIONS; i++)
|
||||
conn_fd[i] = 0;
|
||||
|
||||
/* create socket */
|
||||
main_sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (main_sd < 0) {
|
||||
perror("cannot open socket ");
|
||||
panic("main -- create socket");
|
||||
}
|
||||
|
||||
/* allow address reuse to avoid "address already in use" errors */
|
||||
|
||||
one = 1;
|
||||
if (setsockopt(main_sd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&one, sizeof(int)) < 0) {
|
||||
perror("cannot enable address reuse ");
|
||||
panic("main -- enable address reuse");
|
||||
}
|
||||
|
||||
/* bind server port */
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
server_addr.sin_port = htons(port);
|
||||
|
||||
if (bind(main_sd, (struct sockaddr *) &server_addr,
|
||||
sizeof(server_addr) ) < 0) {
|
||||
perror("cannot bind port ");
|
||||
panic("main -- bind port");
|
||||
}
|
||||
|
||||
res = listen(main_sd,M_CONNECTIONS);
|
||||
if (res != 0) {
|
||||
perror("listen failed ");
|
||||
panic("main -- listen");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
snooze();
|
||||
|
||||
/* enquire, using poll, whether there is any activity available on
|
||||
the main socket descriptor. If so, someone is trying to
|
||||
connect; get the fd and add it to our table thereof. */
|
||||
{ struct pollfd ufd;
|
||||
while (1) {
|
||||
ufd.fd = main_sd;
|
||||
ufd.events = POLLIN;
|
||||
ufd.revents = 0;
|
||||
res = poll(&ufd, 1, 0);
|
||||
if (res == 0) break;
|
||||
|
||||
/* ok, we have someone waiting to connect. Get the sd. */
|
||||
client_len = sizeof(client_addr);
|
||||
new_sd = accept(main_sd, (struct sockaddr *) &client_addr,
|
||||
&client_len);
|
||||
if (new_sd < 0) {
|
||||
perror("cannot accept connection ");
|
||||
panic("main -- accept connection");
|
||||
}
|
||||
|
||||
/* find a place to put it. */
|
||||
assert(new_sd > 0);
|
||||
for (i = 0; i < M_CONNECTIONS; i++)
|
||||
if (conn_fd[i] == 0)
|
||||
break;
|
||||
|
||||
if (i >= M_CONNECTIONS) {
|
||||
fprintf(stderr, "Too many concurrent connections. "
|
||||
"Increase M_CONNECTIONS and recompile.\n");
|
||||
panic("main -- too many concurrent connections");
|
||||
}
|
||||
|
||||
conn_fd[i] = new_sd;
|
||||
conn_count++;
|
||||
printf("\n(%d) -------------------- CONNECT "
|
||||
"--------------------\n(%d)\n(%d) ",
|
||||
conn_count, conn_count, conn_count);
|
||||
fflush(stdout);
|
||||
} /* while (1) */
|
||||
}
|
||||
|
||||
/* We've processed all new connect requests. Listen for changes
|
||||
to the current set of fds. */
|
||||
j = 0;
|
||||
for (i = 0; i < M_CONNECTIONS; i++) {
|
||||
if (conn_fd[i] == 0)
|
||||
continue;
|
||||
conn_pollfd[j].fd = conn_fd[i];
|
||||
conn_pollfd[j].events = POLLIN /* | POLLHUP | POLLNVAL */;
|
||||
conn_pollfd[j].revents = 0;
|
||||
j++;
|
||||
}
|
||||
|
||||
res = poll(conn_pollfd, j, 0 /* return immediately. */ );
|
||||
if (res < 0) {
|
||||
perror("poll(main) failed");
|
||||
panic("poll(main) failed");
|
||||
}
|
||||
|
||||
/* nothing happened. go round again. */
|
||||
if (res == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* inspect the fds. */
|
||||
for (i = 0; i < j; i++) {
|
||||
|
||||
if (conn_pollfd[i].revents & POLLIN) {
|
||||
/* data is available on this fd */
|
||||
res = read_from_sd(conn_pollfd[i].fd);
|
||||
|
||||
if (res == 0) {
|
||||
/* the connection has been closed. */
|
||||
close(conn_pollfd[i].fd);
|
||||
/* this fd has been closed or otherwise gone bad; forget
|
||||
about it. */
|
||||
for (k = 0; k < M_CONNECTIONS; k++)
|
||||
if (conn_fd[k] == conn_pollfd[i].fd)
|
||||
break;
|
||||
assert(k < M_CONNECTIONS);
|
||||
conn_fd[k] = 0;
|
||||
conn_count--;
|
||||
printf("\n(%d) ------------------- DISCONNECT "
|
||||
"-------------------\n(%d)\n(%d) ",
|
||||
conn_count, conn_count, conn_count);
|
||||
fflush(stdout);
|
||||
if (conn_count == 0 && exit_when_zero) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
exit_routine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* for (i = 0; i < j; i++) */
|
||||
|
||||
} /* while (1) */
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- end valgrind-listener.c ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
@@ -1,3 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
cg_annotate
|
||||
@@ -1,9 +0,0 @@
|
||||
/.cvsignore/1.2/Mon Sep 23 11:37:05 2002//
|
||||
/Makefile.am/1.48/Sat Sep 11 18:27:43 2004//
|
||||
/cg_annotate.in/1.20/Tue Jul 6 21:54:20 2004//
|
||||
/cg_arch.h/1.1/Sat Sep 11 16:45:25 2004//
|
||||
/cg_main.c/1.81/Wed Oct 6 13:50:12 2004//
|
||||
/cg_sim.c/1.1/Sun Jan 4 16:56:57 2004//
|
||||
D/docs////
|
||||
D/tests////
|
||||
D/x86////
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/cachegrind
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,21 +0,0 @@
|
||||
##include $(top_srcdir)/Makefile.tool.am
|
||||
include $(top_srcdir)/Makefile.all.am
|
||||
include $(top_srcdir)/Makefile.tool-flags.am
|
||||
include $(top_srcdir)/Makefile.tool-inplace.am
|
||||
|
||||
SUBDIRS = $(VG_ARCH) . tests docs
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/cachegrind/$(VG_ARCH)
|
||||
|
||||
bin_SCRIPTS = cg_annotate
|
||||
|
||||
EXTRA_DIST = cg_sim.c
|
||||
|
||||
noinst_HEADERS = cg_arch.h
|
||||
|
||||
val_PROGRAMS = vgskin_cachegrind.so
|
||||
|
||||
vgskin_cachegrind_so_SOURCES = cg_main.c
|
||||
vgskin_cachegrind_so_LDFLAGS = -shared
|
||||
vgskin_cachegrind_so_LDADD = ${VG_ARCH}/libcgarch.a
|
||||
|
||||
@@ -1,891 +0,0 @@
|
||||
#! @PERL@ -w
|
||||
|
||||
##--------------------------------------------------------------------##
|
||||
##--- The cache simulation framework: instrumentation, recording ---##
|
||||
##--- and results printing. ---##
|
||||
##--- cg_annotate.in ---##
|
||||
##--------------------------------------------------------------------##
|
||||
|
||||
# This file is part of Cachegrind, a Valgrind tool for cache
|
||||
# profiling programs.
|
||||
#
|
||||
# Copyright (C) 2002-2004 Nicholas Nethercote
|
||||
# njn25@cam.ac.uk
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# The GNU General Public License is contained in the file COPYING.
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Annotator for cachegrind.
|
||||
#
|
||||
# File format is described in /docs/techdocs.html.
|
||||
#
|
||||
# Performance improvements record, using cachegrind.out for cacheprof, doing no
|
||||
# source annotation (irrelevant ones removed):
|
||||
# user time
|
||||
# 1. turned off warnings in add_hash_a_to_b() 3.81 --> 3.48s
|
||||
# [now add_array_a_to_b()]
|
||||
# 6. make line_to_CC() return a ref instead of a hash 3.01 --> 2.77s
|
||||
#
|
||||
#10. changed file format to avoid file/fn name repetition 2.40s
|
||||
# (not sure why higher; maybe due to new '.' entries?)
|
||||
#11. changed file format to drop unnecessary end-line "."s 2.36s
|
||||
# (shrunk file by about 37%)
|
||||
#12. switched from hash CCs to array CCs 1.61s
|
||||
#13. only adding b[i] to a[i] if b[i] defined (was doing it if
|
||||
# either a[i] or b[i] was defined, but if b[i] was undefined
|
||||
# it just added 0) 1.48s
|
||||
#14. Stopped converting "." entries to undef and then back 1.16s
|
||||
#15. Using foreach $i (x..y) instead of for ($i = 0...) in
|
||||
# add_array_a_to_b() 1.11s
|
||||
#
|
||||
# Auto-annotating primes:
|
||||
#16. Finding count lengths by int((length-1)/3), not by
|
||||
# commifying (halves the number of commify calls) 1.68s --> 1.47s
|
||||
|
||||
use strict;
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Overview: the running example in the comments is for:
|
||||
# - events = A,B,C,D
|
||||
# - --show=C,A,D
|
||||
# - --sort=D,C
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Global variables, main data structures
|
||||
#----------------------------------------------------------------------------
|
||||
# CCs are arrays, the counts corresponding to @events, with 'undef'
|
||||
# representing '.'. This makes things fast (faster than using hashes for CCs)
|
||||
# but we have to use @sort_order and @show_order below to handle the --sort and
|
||||
# --show options, which is a bit tricky.
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# Total counts for summary (an array reference).
|
||||
my $summary_CC;
|
||||
|
||||
# Totals for each function, for overall summary.
|
||||
# hash(filename:fn_name => CC array)
|
||||
my %fn_totals;
|
||||
|
||||
# Individual CCs, organised by filename and line_num for easy annotation.
|
||||
# hash(filename => hash(line_num => CC array))
|
||||
my %all_ind_CCs;
|
||||
|
||||
# Files chosen for annotation on the command line.
|
||||
# key = basename (trimmed of any directory), value = full filename
|
||||
my %user_ann_files;
|
||||
|
||||
# Generic description string.
|
||||
my $desc = "";
|
||||
|
||||
# Command line of profiled program.
|
||||
my $cmd;
|
||||
|
||||
# Events in input file, eg. (A,B,C,D)
|
||||
my @events;
|
||||
|
||||
# Events to show, from command line, eg. (C,A,D)
|
||||
my @show_events;
|
||||
|
||||
# Map from @show_events indices to @events indices, eg. (2,0,3). Gives the
|
||||
# order in which we must traverse @events in order to show the @show_events,
|
||||
# eg. (@events[$show_order[1]], @events[$show_order[2]]...) = @show_events.
|
||||
# (Might help to think of it like a hash (0 => 2, 1 => 0, 2 => 3).)
|
||||
my @show_order;
|
||||
|
||||
# Print out the function totals sorted by these events, eg. (D,C).
|
||||
my @sort_events;
|
||||
|
||||
# Map from @sort_events indices to @events indices, eg. (3,2). Same idea as
|
||||
# for @show_order.
|
||||
my @sort_order;
|
||||
|
||||
# Thresholds, one for each sort event (or default to 1 if no sort events
|
||||
# specified). We print out functions and do auto-annotations until we've
|
||||
# handled this proportion of all the events thresholded.
|
||||
my @thresholds;
|
||||
|
||||
my $default_threshold = 99;
|
||||
|
||||
my $single_threshold = $default_threshold;
|
||||
|
||||
# If on, automatically annotates all files that are involved in getting over
|
||||
# all the threshold counts.
|
||||
my $auto_annotate = 0;
|
||||
|
||||
# Number of lines to show around each annotated line.
|
||||
my $context = 8;
|
||||
|
||||
# Directories in which to look for annotation files.
|
||||
my @include_dirs = ("");
|
||||
|
||||
# Input file name
|
||||
my $input_file = undef;
|
||||
|
||||
# Version number
|
||||
my $version = "@VERSION@";
|
||||
|
||||
# Usage message.
|
||||
my $usage = <<END
|
||||
usage: cg_annotate [options] --<pid> [source-files]
|
||||
|
||||
options for the user, with defaults in [ ], are:
|
||||
-h --help show this message
|
||||
-v --version show version
|
||||
--show=A,B,C only show figures for events A,B,C [all]
|
||||
--sort=A,B,C sort columns by events A,B,C [event column order]
|
||||
--threshold=<0--100> percentage of counts (of primary sort event) we
|
||||
are interested in [$default_threshold%]
|
||||
--auto=yes|no annotate all source files containing functions
|
||||
that helped reach the event count threshold [no]
|
||||
--context=N print N lines of context before and after
|
||||
annotated lines [8]
|
||||
-I --include=<dir> add <dir> to list of directories to search for
|
||||
source files
|
||||
|
||||
Cachegrind is Copyright (C) 2002-2004 Nicholas Nethercote.
|
||||
Both are licensed under the GNU General Public License, version 2.
|
||||
Bug reports, feedback, admiration, abuse, etc, to: njn25\@cam.ac.uk.
|
||||
|
||||
END
|
||||
;
|
||||
|
||||
# Used in various places of output.
|
||||
my $fancy = '-' x 80 . "\n";
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Argument and option handling
|
||||
#-----------------------------------------------------------------------------
|
||||
sub process_cmd_line()
|
||||
{
|
||||
for my $arg (@ARGV) {
|
||||
|
||||
# Option handling
|
||||
if ($arg =~ /^-/) {
|
||||
|
||||
# --version
|
||||
if ($arg =~ /^-v$|^--version$/) {
|
||||
die("cg_annotate-$version\n");
|
||||
|
||||
# --show=A,B,C
|
||||
} elsif ($arg =~ /^--show=(.*)$/) {
|
||||
@show_events = split(/,/, $1);
|
||||
|
||||
# --sort=A,B,C
|
||||
} elsif ($arg =~ /^--sort=(.*)$/) {
|
||||
@sort_events = split(/,/, $1);
|
||||
foreach my $i (0 .. scalar @sort_events - 1) {
|
||||
if ($sort_events[$i] =~#/.*:(\d+)$/) {
|
||||
/.*:([\d\.]+)%?$/) {
|
||||
my $th = $1;
|
||||
($th >= 0 && $th <= 100) or die($usage);
|
||||
$sort_events[$i] =~ s/:.*//;
|
||||
$thresholds[$i] = $th;
|
||||
} else {
|
||||
$thresholds[$i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
# --threshold=X (tolerates a trailing '%')
|
||||
} elsif ($arg =~ /^--threshold=([\d\.]+)%?$/) {
|
||||
$single_threshold = $1;
|
||||
($1 >= 0 && $1 <= 100) or die($usage);
|
||||
|
||||
# --auto=yes|no
|
||||
} elsif ($arg =~ /^--auto=(yes|no)$/) {
|
||||
$auto_annotate = 1 if ($1 eq "yes");
|
||||
$auto_annotate = 0 if ($1 eq "no");
|
||||
|
||||
# --context=N
|
||||
} elsif ($arg =~ /^--context=([\d\.]+)$/) {
|
||||
$context = $1;
|
||||
if ($context < 0) {
|
||||
die($usage);
|
||||
}
|
||||
|
||||
# --include=A,B,C
|
||||
} elsif ($arg =~ /^(-I|--include)=(.*)$/) {
|
||||
my $inc = $2;
|
||||
$inc =~ s|/$||; # trim trailing '/'
|
||||
push(@include_dirs, "$inc/");
|
||||
|
||||
} elsif ($arg =~ /^--(\d+)$/) {
|
||||
my $pid = $1;
|
||||
if (not defined $input_file) {
|
||||
$input_file = "cachegrind.out.$pid";
|
||||
} else {
|
||||
die("One cachegrind.out.<pid> file at a time, please\n");
|
||||
}
|
||||
|
||||
} else { # -h and --help fall under this case
|
||||
die($usage);
|
||||
}
|
||||
|
||||
# Argument handling -- annotation file checking and selection.
|
||||
# Stick filenames into a hash for quick 'n easy lookup throughout.
|
||||
} else {
|
||||
my $readable = 0;
|
||||
foreach my $include_dir (@include_dirs) {
|
||||
if (-r $include_dir . $arg) {
|
||||
$readable = 1;
|
||||
}
|
||||
}
|
||||
$readable or die("File $arg not found in any of: @include_dirs\n");
|
||||
$user_ann_files{$arg} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Must have chosen an input file
|
||||
if (not defined $input_file) {
|
||||
die($usage);
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Reading of input file
|
||||
#-----------------------------------------------------------------------------
|
||||
sub max ($$)
|
||||
{
|
||||
my ($x, $y) = @_;
|
||||
return ($x > $y ? $x : $y);
|
||||
}
|
||||
|
||||
# Add the two arrays; any '.' entries are ignored. Two tricky things:
|
||||
# 1. If $a2->[$i] is undefined, it defaults to 0 which is what we want; we turn
|
||||
# off warnings to allow this. This makes things about 10% faster than
|
||||
# checking for definedness ourselves.
|
||||
# 2. We don't add an undefined count or a ".", even though it's value is 0,
|
||||
# because we don't want to make an $a2->[$i] that is undef become 0
|
||||
# unnecessarily.
|
||||
sub add_array_a_to_b ($$)
|
||||
{
|
||||
my ($a1, $a2) = @_;
|
||||
|
||||
my $n = max(scalar @$a1, scalar @$a2);
|
||||
$^W = 0;
|
||||
foreach my $i (0 .. $n-1) {
|
||||
$a2->[$i] += $a1->[$i] if (defined $a1->[$i] && "." ne $a1->[$i]);
|
||||
}
|
||||
$^W = 1;
|
||||
}
|
||||
|
||||
# Add each event count to the CC array. '.' counts become undef, as do
|
||||
# missing entries (implicitly).
|
||||
sub line_to_CC ($)
|
||||
{
|
||||
my @CC = (split /\s+/, $_[0]);
|
||||
(@CC <= @events) or die("Line $.: too many event counts\n");
|
||||
return \@CC;
|
||||
}
|
||||
|
||||
sub read_input_file()
|
||||
{
|
||||
open(INPUTFILE, "< $input_file") || die "File $input_file not opened\n";
|
||||
|
||||
# Read "desc:" lines.
|
||||
my $line;
|
||||
while ($line = <INPUTFILE>) {
|
||||
if ($line =~ s/desc:\s+//) {
|
||||
$desc .= $line;
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Read "cmd:" line (Nb: will already be in $line from "desc:" loop above).
|
||||
($line =~ s/cmd:\s+//) or die("Line $.: missing command line\n");
|
||||
$cmd = $line;
|
||||
chomp($cmd); # Remove newline
|
||||
|
||||
# Read "events:" line. We make a temporary hash in which the Nth event's
|
||||
# value is N, which is useful for handling --show/--sort options below.
|
||||
$line = <INPUTFILE>;
|
||||
(defined $line && $line =~ s/events:\s+//)
|
||||
or die("Line $.: missing events line\n");
|
||||
@events = split(/\s+/, $line);
|
||||
my %events;
|
||||
my $n = 0;
|
||||
foreach my $event (@events) {
|
||||
$events{$event} = $n;
|
||||
$n++
|
||||
}
|
||||
|
||||
# If no --show arg give, default to showing all events in the file.
|
||||
# If --show option is used, check all specified events appeared in the
|
||||
# "events:" line. Then initialise @show_order.
|
||||
if (@show_events) {
|
||||
foreach my $show_event (@show_events) {
|
||||
(defined $events{$show_event}) or
|
||||
die("--show event `$show_event' did not appear in input\n");
|
||||
}
|
||||
} else {
|
||||
@show_events = @events;
|
||||
}
|
||||
foreach my $show_event (@show_events) {
|
||||
push(@show_order, $events{$show_event});
|
||||
}
|
||||
|
||||
# Do as for --show, but if no --sort arg given, default to sorting by
|
||||
# column order (ie. first column event is primary sort key, 2nd column is
|
||||
# 2ndary key, etc).
|
||||
if (@sort_events) {
|
||||
foreach my $sort_event (@sort_events) {
|
||||
(defined $events{$sort_event}) or
|
||||
die("--sort event `$sort_event' did not appear in input\n");
|
||||
}
|
||||
} else {
|
||||
@sort_events = @events;
|
||||
}
|
||||
foreach my $sort_event (@sort_events) {
|
||||
push(@sort_order, $events{$sort_event});
|
||||
}
|
||||
|
||||
# If multiple threshold args weren't given via --sort, stick in the single
|
||||
# threshold (either from --threshold if used, or the default otherwise) for
|
||||
# the primary sort event, and 0% for the rest.
|
||||
if (not @thresholds) {
|
||||
foreach my $e (@sort_order) {
|
||||
push(@thresholds, 0);
|
||||
}
|
||||
$thresholds[0] = $single_threshold;
|
||||
}
|
||||
|
||||
my $curr_file;
|
||||
my $curr_fn;
|
||||
my $curr_name;
|
||||
|
||||
my $curr_fn_CC = [];
|
||||
my $curr_file_ind_CCs = {}; # hash(line_num => CC)
|
||||
|
||||
# Read body of input file.
|
||||
while (<INPUTFILE>) {
|
||||
s/#.*$//; # remove comments
|
||||
if (s/^(\d+)\s+//) {
|
||||
my $line_num = $1;
|
||||
my $CC = line_to_CC($_);
|
||||
add_array_a_to_b($CC, $curr_fn_CC);
|
||||
|
||||
# If curr_file is selected, add CC to curr_file list. We look for
|
||||
# full filename matches; or, if auto-annotating, we have to
|
||||
# remember everything -- we won't know until the end what's needed.
|
||||
if ($auto_annotate || defined $user_ann_files{$curr_file}) {
|
||||
my $tmp = $curr_file_ind_CCs->{$line_num};
|
||||
$tmp = [] unless defined $tmp;
|
||||
add_array_a_to_b($CC, $tmp);
|
||||
$curr_file_ind_CCs->{$line_num} = $tmp;
|
||||
}
|
||||
|
||||
} elsif (s/^fn=(.*)$//) {
|
||||
# Commit result from previous function
|
||||
$fn_totals{$curr_name} = $curr_fn_CC if (defined $curr_name);
|
||||
|
||||
# Setup new one
|
||||
$curr_fn = $1;
|
||||
$curr_name = "$curr_file:$curr_fn";
|
||||
$curr_fn_CC = $fn_totals{$curr_name};
|
||||
$curr_fn_CC = [] unless (defined $curr_fn_CC);
|
||||
|
||||
} elsif (s/^fl=(.*)$//) {
|
||||
$all_ind_CCs{$curr_file} = $curr_file_ind_CCs
|
||||
if (defined $curr_file);
|
||||
|
||||
$curr_file = $1;
|
||||
$curr_file_ind_CCs = $all_ind_CCs{$curr_file};
|
||||
$curr_file_ind_CCs = {} unless (defined $curr_file_ind_CCs);
|
||||
|
||||
} elsif (s/^\s*$//) {
|
||||
# blank, do nothing
|
||||
|
||||
} elsif (s/^summary:\s+//) {
|
||||
# Finish up handling final filename/fn_name counts
|
||||
$fn_totals{"$curr_file:$curr_fn"} = $curr_fn_CC
|
||||
if (defined $curr_file && defined $curr_fn);
|
||||
$all_ind_CCs{$curr_file} =
|
||||
$curr_file_ind_CCs if (defined $curr_file);
|
||||
|
||||
$summary_CC = line_to_CC($_);
|
||||
(scalar(@$summary_CC) == @events)
|
||||
or die("Line $.: summary event and total event mismatch\n");
|
||||
|
||||
} else {
|
||||
warn("WARNING: line $. malformed, ignoring\n");
|
||||
}
|
||||
}
|
||||
|
||||
# Check if summary line was present
|
||||
if (not defined $summary_CC) {
|
||||
die("missing final summary line, aborting\n");
|
||||
}
|
||||
|
||||
close(INPUTFILE);
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Print options used
|
||||
#-----------------------------------------------------------------------------
|
||||
sub print_options ()
|
||||
{
|
||||
print($fancy);
|
||||
print($desc);
|
||||
print("Command: $cmd\n");
|
||||
print("Events recorded: @events\n");
|
||||
print("Events shown: @show_events\n");
|
||||
print("Event sort order: @sort_events\n");
|
||||
print("Thresholds: @thresholds\n");
|
||||
|
||||
my @include_dirs2 = @include_dirs; # copy @include_dirs
|
||||
shift(@include_dirs2); # remove "" entry, which is always the first
|
||||
unshift(@include_dirs2, "") if (0 == @include_dirs2);
|
||||
my $include_dir = shift(@include_dirs2);
|
||||
print("Include dirs: $include_dir\n");
|
||||
foreach my $include_dir (@include_dirs2) {
|
||||
print(" $include_dir\n");
|
||||
}
|
||||
|
||||
my @user_ann_files = keys %user_ann_files;
|
||||
unshift(@user_ann_files, "") if (0 == @user_ann_files);
|
||||
my $user_ann_file = shift(@user_ann_files);
|
||||
print("User annotated: $user_ann_file\n");
|
||||
foreach $user_ann_file (@user_ann_files) {
|
||||
print(" $user_ann_file\n");
|
||||
}
|
||||
|
||||
my $is_on = ($auto_annotate ? "on" : "off");
|
||||
print("Auto-annotation: $is_on\n");
|
||||
print("\n");
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Print summary and sorted function totals
|
||||
#-----------------------------------------------------------------------------
|
||||
sub mycmp ($$)
|
||||
{
|
||||
my ($c, $d) = @_;
|
||||
|
||||
# Iterate through sort events (eg. 3,2); return result if two are different
|
||||
foreach my $i (@sort_order) {
|
||||
my ($x, $y);
|
||||
$x = $c->[$i];
|
||||
$y = $d->[$i];
|
||||
$x = -1 unless defined $x;
|
||||
$y = -1 unless defined $y;
|
||||
|
||||
my $cmp = $y <=> $x; # reverse sort
|
||||
if (0 != $cmp) {
|
||||
return $cmp;
|
||||
}
|
||||
}
|
||||
# Exhausted events, equal
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub commify ($) {
|
||||
my ($val) = @_;
|
||||
1 while ($val =~ s/^(\d+)(\d{3})/$1,$2/);
|
||||
return $val;
|
||||
}
|
||||
|
||||
# Because the counts can get very big, and we don't want to waste screen space
|
||||
# and make lines too long, we compute exactly how wide each column needs to be
|
||||
# by finding the widest entry for each one.
|
||||
sub compute_CC_col_widths (@)
|
||||
{
|
||||
my @CCs = @_;
|
||||
my $CC_col_widths = [];
|
||||
|
||||
# Initialise with minimum widths (from event names)
|
||||
foreach my $event (@events) {
|
||||
push(@$CC_col_widths, length($event));
|
||||
}
|
||||
|
||||
# Find maximum width count for each column. @CC_col_width positions
|
||||
# correspond to @CC positions.
|
||||
foreach my $CC (@CCs) {
|
||||
foreach my $i (0 .. scalar(@$CC)-1) {
|
||||
if (defined $CC->[$i]) {
|
||||
# Find length, accounting for commas that will be added
|
||||
my $length = length $CC->[$i];
|
||||
my $clength = $length + int(($length - 1) / 3);
|
||||
$CC_col_widths->[$i] = max($CC_col_widths->[$i], $clength);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $CC_col_widths;
|
||||
}
|
||||
|
||||
# Print the CC with each column's size dictated by $CC_col_widths.
|
||||
sub print_CC ($$)
|
||||
{
|
||||
my ($CC, $CC_col_widths) = @_;
|
||||
|
||||
foreach my $i (@show_order) {
|
||||
my $count = (defined $CC->[$i] ? commify($CC->[$i]) : ".");
|
||||
my $space = ' ' x ($CC_col_widths->[$i] - length($count));
|
||||
print("$space$count ");
|
||||
}
|
||||
}
|
||||
|
||||
sub print_events ($)
|
||||
{
|
||||
my ($CC_col_widths) = @_;
|
||||
|
||||
foreach my $i (@show_order) {
|
||||
my $event = $events[$i];
|
||||
my $event_width = length($event);
|
||||
my $col_width = $CC_col_widths->[$i];
|
||||
my $space = ' ' x ($col_width - $event_width);
|
||||
print("$space$event ");
|
||||
}
|
||||
}
|
||||
|
||||
# Prints summary and function totals (with separate column widths, so that
|
||||
# function names aren't pushed over unnecessarily by huge summary figures).
|
||||
# Also returns a hash containing all the files that are involved in getting the
|
||||
# events count above the thresholds (ie. all the interesting ones).
|
||||
sub print_summary_and_fn_totals ()
|
||||
{
|
||||
my @fn_fullnames = keys %fn_totals;
|
||||
|
||||
# Work out the size of each column for printing (summary and functions
|
||||
# separately).
|
||||
my $summary_CC_col_widths = compute_CC_col_widths($summary_CC);
|
||||
my $fn_CC_col_widths = compute_CC_col_widths(values %fn_totals);
|
||||
|
||||
# Header and counts for summary
|
||||
print($fancy);
|
||||
print_events($summary_CC_col_widths);
|
||||
print("\n");
|
||||
print($fancy);
|
||||
print_CC($summary_CC, $summary_CC_col_widths);
|
||||
print(" PROGRAM TOTALS\n");
|
||||
print("\n");
|
||||
|
||||
# Header for functions
|
||||
print($fancy);
|
||||
print_events($fn_CC_col_widths);
|
||||
print(" file:function\n");
|
||||
print($fancy);
|
||||
|
||||
# Sort function names into order dictated by --sort option.
|
||||
@fn_fullnames = sort {
|
||||
mycmp($fn_totals{$a}, $fn_totals{$b})
|
||||
} @fn_fullnames;
|
||||
|
||||
|
||||
# Assertion
|
||||
(scalar @sort_order == scalar @thresholds) or
|
||||
die("sort_order length != thresholds length:\n",
|
||||
" @sort_order\n @thresholds\n");
|
||||
|
||||
my $threshold_files = {};
|
||||
# @curr_totals has the same shape as @sort_order and @thresholds
|
||||
my @curr_totals = ();
|
||||
foreach my $e (@thresholds) {
|
||||
push(@curr_totals, 0);
|
||||
}
|
||||
|
||||
# Print functions, stopping when the threshold has been reached.
|
||||
foreach my $fn_name (@fn_fullnames) {
|
||||
|
||||
# Stop when we've reached all the thresholds
|
||||
my $reached_all_thresholds = 1;
|
||||
foreach my $i (0 .. scalar @thresholds - 1) {
|
||||
my $prop = $curr_totals[$i] * 100 / $summary_CC->[$sort_order[$i]];
|
||||
$reached_all_thresholds &&= ($prop >= $thresholds[$i]);
|
||||
}
|
||||
last if $reached_all_thresholds;
|
||||
|
||||
# Print function results
|
||||
my $fn_CC = $fn_totals{$fn_name};
|
||||
print_CC($fn_CC, $fn_CC_col_widths);
|
||||
print(" $fn_name\n");
|
||||
|
||||
# Update the threshold counts
|
||||
my $filename = $fn_name;
|
||||
$filename =~ s/:.+$//; # remove function name
|
||||
$threshold_files->{$filename} = 1;
|
||||
foreach my $i (0 .. scalar @sort_order - 1) {
|
||||
$curr_totals[$i] += $fn_CC->[$sort_order[$i]]
|
||||
if (defined $fn_CC->[$sort_order[$i]]);
|
||||
}
|
||||
}
|
||||
print("\n");
|
||||
|
||||
return $threshold_files;
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Annotate selected files
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Issue a warning that the source file is more recent than the input file.
|
||||
sub warning_on_src_more_recent_than_inputfile ($)
|
||||
{
|
||||
my $src_file = $_[0];
|
||||
|
||||
my $warning = <<END
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@ Source file '$src_file' is more recent than input file '$input_file'.
|
||||
@ Annotations may not be correct.
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
END
|
||||
;
|
||||
print($warning);
|
||||
}
|
||||
|
||||
# If there is information about lines not in the file, issue a warning
|
||||
# explaining possible causes.
|
||||
sub warning_on_nonexistent_lines ($$$)
|
||||
{
|
||||
my ($src_more_recent_than_inputfile, $src_file, $excess_line_nums) = @_;
|
||||
my $cause_and_solution;
|
||||
|
||||
if ($src_more_recent_than_inputfile) {
|
||||
$cause_and_solution = <<END
|
||||
@@ cause: '$src_file' has changed since information was gathered.
|
||||
@@ If so, a warning will have already been issued about this.
|
||||
@@ solution: Recompile program and rerun under "valgrind --cachesim=yes" to
|
||||
@@ gather new information.
|
||||
END
|
||||
# We suppress warnings about .h files
|
||||
} elsif ($src_file =~ /\.h$/) {
|
||||
$cause_and_solution = <<END
|
||||
@@ cause: bug in the Valgrind's debug info reader that screws up with .h
|
||||
@@ files sometimes
|
||||
@@ solution: none, sorry
|
||||
END
|
||||
} else {
|
||||
$cause_and_solution = <<END
|
||||
@@ cause: not sure, sorry
|
||||
END
|
||||
}
|
||||
|
||||
my $warning = <<END
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@ WARNING @@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@
|
||||
@@ Information recorded about lines past the end of '$src_file'.
|
||||
@@
|
||||
@@ Probable cause and solution:
|
||||
$cause_and_solution@@
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
END
|
||||
;
|
||||
print($warning);
|
||||
}
|
||||
|
||||
sub annotate_ann_files($)
|
||||
{
|
||||
my ($threshold_files) = @_;
|
||||
|
||||
my %all_ann_files;
|
||||
my @unfound_auto_annotate_files;
|
||||
my $printed_totals_CC = [];
|
||||
|
||||
# If auto-annotating, add interesting files (but not "???")
|
||||
if ($auto_annotate) {
|
||||
delete $threshold_files->{"???"};
|
||||
%all_ann_files = (%user_ann_files, %$threshold_files)
|
||||
} else {
|
||||
%all_ann_files = %user_ann_files;
|
||||
}
|
||||
|
||||
# Track if we did any annotations.
|
||||
my $did_annotations = 0;
|
||||
|
||||
LOOP:
|
||||
foreach my $src_file (keys %all_ann_files) {
|
||||
|
||||
my $opened_file = "";
|
||||
my $full_file_name = "";
|
||||
foreach my $include_dir (@include_dirs) {
|
||||
my $try_name = $include_dir . $src_file;
|
||||
if (open(INPUTFILE, "< $try_name")) {
|
||||
$opened_file = $try_name;
|
||||
$full_file_name = ($include_dir eq ""
|
||||
? $src_file
|
||||
: "$include_dir + $src_file");
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if (not $opened_file) {
|
||||
# Failed to open the file. If chosen on the command line, die.
|
||||
# If arose from auto-annotation, print a little message.
|
||||
if (defined $user_ann_files{$src_file}) {
|
||||
die("File $src_file not opened in any of: @include_dirs\n");
|
||||
|
||||
} else {
|
||||
push(@unfound_auto_annotate_files, $src_file);
|
||||
}
|
||||
|
||||
} else {
|
||||
# File header (distinguish between user- and auto-selected files).
|
||||
print("$fancy");
|
||||
my $ann_type =
|
||||
(defined $user_ann_files{$src_file} ? "User" : "Auto");
|
||||
print("-- $ann_type-annotated source: $full_file_name\n");
|
||||
print("$fancy");
|
||||
|
||||
# Get file's CCs
|
||||
my $src_file_CCs = $all_ind_CCs{$src_file};
|
||||
if (!defined $src_file_CCs) {
|
||||
print(" No information has been collected for $src_file\n\n");
|
||||
next LOOP;
|
||||
}
|
||||
|
||||
$did_annotations = 1;
|
||||
|
||||
# Numeric, not lexicographic sort!
|
||||
my @line_nums = sort {$a <=> $b} keys %$src_file_CCs;
|
||||
|
||||
# If $src_file more recent than cachegrind.out, issue warning
|
||||
my $src_more_recent_than_inputfile = 0;
|
||||
if ((stat $opened_file)[9] > (stat $input_file)[9]) {
|
||||
$src_more_recent_than_inputfile = 1;
|
||||
warning_on_src_more_recent_than_inputfile($src_file);
|
||||
}
|
||||
|
||||
# Work out the size of each column for printing
|
||||
my $CC_col_widths = compute_CC_col_widths(values %$src_file_CCs);
|
||||
|
||||
# Events header
|
||||
print_events($CC_col_widths);
|
||||
print("\n\n");
|
||||
|
||||
# Shift out 0 if it's in the line numbers (from unknown entries,
|
||||
# likely due to bugs in Valgrind's stabs debug info reader)
|
||||
shift(@line_nums) if (0 == $line_nums[0]);
|
||||
|
||||
# Finds interesting line ranges -- all lines with a CC, and all
|
||||
# lines within $context lines of a line with a CC.
|
||||
my $n = @line_nums;
|
||||
my @pairs;
|
||||
for (my $i = 0; $i < $n; $i++) {
|
||||
push(@pairs, $line_nums[$i] - $context); # lower marker
|
||||
while ($i < $n-1 &&
|
||||
$line_nums[$i] + 2*$context >= $line_nums[$i+1]) {
|
||||
$i++;
|
||||
}
|
||||
push(@pairs, $line_nums[$i] + $context); # upper marker
|
||||
}
|
||||
|
||||
# Annotate chosen lines, tracking total counts of lines printed
|
||||
$pairs[0] = 1 if ($pairs[0] < 1);
|
||||
while (@pairs) {
|
||||
my $low = shift @pairs;
|
||||
my $high = shift @pairs;
|
||||
while ($. < $low-1) {
|
||||
my $tmp = <INPUTFILE>;
|
||||
last unless (defined $tmp); # hack to detect EOF
|
||||
}
|
||||
my $src_line;
|
||||
# Print line number, unless start of file
|
||||
print("-- line $low " . '-' x 40 . "\n") if ($low != 1);
|
||||
while (($. < $high) && ($src_line = <INPUTFILE>)) {
|
||||
if (defined $line_nums[0] && $. == $line_nums[0]) {
|
||||
print_CC($src_file_CCs->{$.}, $CC_col_widths);
|
||||
add_array_a_to_b($src_file_CCs->{$.},
|
||||
$printed_totals_CC);
|
||||
shift(@line_nums);
|
||||
|
||||
} else {
|
||||
print_CC( [], $CC_col_widths);
|
||||
}
|
||||
|
||||
print(" $src_line");
|
||||
}
|
||||
# Print line number, unless EOF
|
||||
if ($src_line) {
|
||||
print("-- line $high " . '-' x 40 . "\n");
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# If there was info on lines past the end of the file...
|
||||
if (@line_nums) {
|
||||
foreach my $line_num (@line_nums) {
|
||||
print_CC($src_file_CCs->{$line_num}, $CC_col_widths);
|
||||
print(" <bogus line $line_num>\n");
|
||||
}
|
||||
print("\n");
|
||||
warning_on_nonexistent_lines($src_more_recent_than_inputfile,
|
||||
$src_file, \@line_nums);
|
||||
}
|
||||
print("\n");
|
||||
|
||||
# Print summary of counts attributed to file but not to any
|
||||
# particular line (due to incomplete debug info).
|
||||
if ($src_file_CCs->{0}) {
|
||||
print_CC($src_file_CCs->{0}, $CC_col_widths);
|
||||
print(" <counts for unidentified lines in $src_file>\n\n");
|
||||
}
|
||||
|
||||
close(INPUTFILE);
|
||||
}
|
||||
}
|
||||
|
||||
# Print list of unfound auto-annotate selected files.
|
||||
if (@unfound_auto_annotate_files) {
|
||||
print("$fancy");
|
||||
print("The following files chosen for auto-annotation could not be found:\n");
|
||||
print($fancy);
|
||||
foreach my $f (@unfound_auto_annotate_files) {
|
||||
print(" $f\n");
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
# If we did any annotating, print what proportion of events were covered by
|
||||
# annotated lines above.
|
||||
if ($did_annotations) {
|
||||
my $percent_printed_CC;
|
||||
foreach (my $i = 0; $i < @$summary_CC; $i++) {
|
||||
$percent_printed_CC->[$i] =
|
||||
sprintf("%.0f",
|
||||
$printed_totals_CC->[$i] / $summary_CC->[$i] * 100);
|
||||
}
|
||||
my $pp_CC_col_widths = compute_CC_col_widths($percent_printed_CC);
|
||||
print($fancy);
|
||||
print_events($pp_CC_col_widths);
|
||||
print("\n");
|
||||
print($fancy);
|
||||
print_CC($percent_printed_CC, $pp_CC_col_widths);
|
||||
print(" percentage of events annotated\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# "main()"
|
||||
#----------------------------------------------------------------------------
|
||||
process_cmd_line();
|
||||
read_input_file();
|
||||
print_options();
|
||||
my $threshold_files = print_summary_and_fn_totals();
|
||||
annotate_ann_files($threshold_files);
|
||||
|
||||
##--------------------------------------------------------------------##
|
||||
##--- end cg_annotate.in ---##
|
||||
##--------------------------------------------------------------------##
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- Arch-specific declarations. cg_arch.h ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
This file is part of Cachegrind, a Valgrind tool for cache
|
||||
profiling programs.
|
||||
|
||||
Copyright (C) 2002-2004 Nicholas Nethercote
|
||||
njn25@cam.ac.uk
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The GNU General Public License is contained in the file COPYING.
|
||||
*/
|
||||
|
||||
#ifndef __CG_ARCH_H
|
||||
#define __CG_ARCH_H
|
||||
|
||||
// For cache simulation
|
||||
typedef struct {
|
||||
int size; // bytes
|
||||
int assoc;
|
||||
int line_size; // bytes
|
||||
} cache_t;
|
||||
|
||||
void VGA_(configure_caches)(cache_t* I1c, cache_t* D1c, cache_t* L2c,
|
||||
cache_t* I1_dflt, cache_t* D1_dflt, cache_t* L2_dflt,
|
||||
Bool all_caches_clo_defined);
|
||||
|
||||
#endif // __CG_ARCH_H
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- end ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,210 +0,0 @@
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- Cache simulation cg_sim.c ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
This file is part of Cachegrind, a Valgrind tool for cache
|
||||
profiling programs.
|
||||
|
||||
Copyright (C) 2002-2004 Nicholas Nethercote
|
||||
njn25@cam.ac.uk
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The GNU General Public License is contained in the file COPYING.
|
||||
*/
|
||||
|
||||
/* Notes:
|
||||
- simulates a write-allocate cache
|
||||
- (block --> set) hash function uses simple bit selection
|
||||
- handling of references straddling two cache blocks:
|
||||
- counts as only one cache access (not two)
|
||||
- both blocks hit --> one hit
|
||||
- one block hits, the other misses --> one miss
|
||||
- both blocks miss --> one miss (not two)
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int size; /* bytes */
|
||||
int assoc;
|
||||
int line_size; /* bytes */
|
||||
int sets;
|
||||
int sets_min_1;
|
||||
int assoc_bits;
|
||||
int line_size_bits;
|
||||
int tag_shift;
|
||||
char desc_line[128];
|
||||
int* tags;
|
||||
} cache_t2;
|
||||
|
||||
/* By this point, the size/assoc/line_size has been checked. */
|
||||
static void cachesim_initcache(cache_t config, cache_t2* c)
|
||||
{
|
||||
int i;
|
||||
|
||||
c->size = config.size;
|
||||
c->assoc = config.assoc;
|
||||
c->line_size = config.line_size;
|
||||
|
||||
c->sets = (c->size / c->line_size) / c->assoc;
|
||||
c->sets_min_1 = c->sets - 1;
|
||||
c->assoc_bits = VG_(log2)(c->assoc);
|
||||
c->line_size_bits = VG_(log2)(c->line_size);
|
||||
c->tag_shift = c->line_size_bits + VG_(log2)(c->sets);
|
||||
|
||||
if (c->assoc == 1) {
|
||||
VG_(sprintf)(c->desc_line, "%d B, %d B, direct-mapped",
|
||||
c->size, c->line_size);
|
||||
} else {
|
||||
VG_(sprintf)(c->desc_line, "%d B, %d B, %d-way associative",
|
||||
c->size, c->line_size, c->assoc);
|
||||
}
|
||||
|
||||
c->tags = VG_(malloc)(sizeof(UInt) * c->sets * c->assoc);
|
||||
|
||||
for (i = 0; i < c->sets * c->assoc; i++)
|
||||
c->tags[i] = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void print_cache(cache_t2* c)
|
||||
{
|
||||
UInt set, way, i;
|
||||
|
||||
/* Note initialisation and update of 'i'. */
|
||||
for (i = 0, set = 0; set < c->sets; set++) {
|
||||
for (way = 0; way < c->assoc; way++, i++) {
|
||||
VG_(printf)("%8x ", c->tags[i]);
|
||||
}
|
||||
VG_(printf)("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is done as a macro rather than by passing in the cache_t2 as an
|
||||
* arg because it slows things down by a small amount (3-5%) due to all
|
||||
* that extra indirection. */
|
||||
|
||||
#define CACHESIM(L, MISS_TREATMENT) \
|
||||
/* The cache and associated bits and pieces. */ \
|
||||
static cache_t2 L; \
|
||||
\
|
||||
static void cachesim_##L##_initcache(cache_t config) \
|
||||
{ \
|
||||
cachesim_initcache(config, &L); \
|
||||
} \
|
||||
\
|
||||
static /* __inline__ */ \
|
||||
void cachesim_##L##_doref(Addr a, UChar size, ULong* m1, ULong *m2) \
|
||||
{ \
|
||||
register UInt set1 = ( a >> L.line_size_bits) & (L.sets_min_1); \
|
||||
register UInt set2 = ((a+size-1) >> L.line_size_bits) & (L.sets_min_1); \
|
||||
register UInt tag = a >> L.tag_shift; \
|
||||
int i, j; \
|
||||
Bool is_miss = False; \
|
||||
int* set; \
|
||||
\
|
||||
/* First case: word entirely within line. */ \
|
||||
if (set1 == set2) { \
|
||||
\
|
||||
/* Shifting is a bit faster than multiplying */ \
|
||||
set = &(L.tags[set1 << L.assoc_bits]); \
|
||||
\
|
||||
/* This loop is unrolled for just the first case, which is the most */\
|
||||
/* common. We can't unroll any further because it would screw up */\
|
||||
/* if we have a direct-mapped (1-way) cache. */\
|
||||
if (tag == set[0]) { \
|
||||
return; \
|
||||
} \
|
||||
/* If the tag is one other than the MRU, move it into the MRU spot */\
|
||||
/* and shuffle the rest down. */\
|
||||
for (i = 1; i < L.assoc; i++) { \
|
||||
if (tag == set[i]) { \
|
||||
for (j = i; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* A miss; install this tag as MRU, shuffle rest down. */ \
|
||||
for (j = L.assoc - 1; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
MISS_TREATMENT; \
|
||||
return; \
|
||||
\
|
||||
/* Second case: word straddles two lines. */ \
|
||||
/* Nb: this is a fast way of doing ((set1+1) % L.sets) */ \
|
||||
} else if (((set1 + 1) & (L.sets-1)) == set2) { \
|
||||
set = &(L.tags[set1 << L.assoc_bits]); \
|
||||
if (tag == set[0]) { \
|
||||
goto block2; \
|
||||
} \
|
||||
for (i = 1; i < L.assoc; i++) { \
|
||||
if (tag == set[i]) { \
|
||||
for (j = i; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
goto block2; \
|
||||
} \
|
||||
} \
|
||||
for (j = L.assoc - 1; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
is_miss = True; \
|
||||
block2: \
|
||||
set = &(L.tags[set2 << L.assoc_bits]); \
|
||||
if (tag == set[0]) { \
|
||||
goto miss_treatment; \
|
||||
} \
|
||||
for (i = 1; i < L.assoc; i++) { \
|
||||
if (tag == set[i]) { \
|
||||
for (j = i; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
goto miss_treatment; \
|
||||
} \
|
||||
} \
|
||||
for (j = L.assoc - 1; j > 0; j--) { \
|
||||
set[j] = set[j - 1]; \
|
||||
} \
|
||||
set[0] = tag; \
|
||||
is_miss = True; \
|
||||
miss_treatment: \
|
||||
if (is_miss) { MISS_TREATMENT; } \
|
||||
\
|
||||
} else { \
|
||||
VG_(printf)("addr: %x size: %u sets: %d %d", a, size, set1, set2); \
|
||||
VG_(skin_panic)("item straddles more than two cache sets"); \
|
||||
} \
|
||||
return; \
|
||||
}
|
||||
|
||||
CACHESIM(L2, (*m2)++ );
|
||||
CACHESIM(I1, { (*m1)++; cachesim_L2_doref(a, size, m1, m2); } );
|
||||
CACHESIM(D1, { (*m1)++; cachesim_L2_doref(a, size, m1, m2); } );
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- end cg_sim.c ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
@@ -1,5 +0,0 @@
|
||||
/.cvsignore/1.1/Mon Sep 23 11:36:22 2002//
|
||||
/Makefile.am/1.3/Wed Aug 25 11:40:04 2004//
|
||||
/cg_main.html/1.5/Fri Nov 14 17:47:52 2003//
|
||||
/cg_techdocs.html/1.4/Thu Nov 20 16:20:54 2003//
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
valgrind/cachegrind/docs
|
||||
@@ -1 +0,0 @@
|
||||
:ext:jseward@cvs.kde.org:/home/kde
|
||||
@@ -1,3 +0,0 @@
|
||||
docdir = $(datadir)/doc/valgrind
|
||||
|
||||
dist_doc_DATA = cg_main.html cg_techdocs.html
|
||||
@@ -1,714 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Cachegrind: a cache-miss profiler</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a name="cg-top"></a>
|
||||
<h2>4 <b>Cachegrind</b>: a cache-miss profiler</h2>
|
||||
|
||||
To use this tool, you must specify <code>--tool=cachegrind</code>
|
||||
on the Valgrind command line.
|
||||
|
||||
<p>
|
||||
Detailed technical documentation on how Cachegrind works is available
|
||||
<A HREF="cg_techdocs.html">here</A>. If you want to know how
|
||||
to <b>use</b> it, you only need to read this page.
|
||||
|
||||
|
||||
<a name="cache"></a>
|
||||
<h3>4.1 Cache profiling</h3>
|
||||
Cachegrind is a tool for doing cache simulations and annotating your source
|
||||
line-by-line with the number of cache misses. In particular, it records:
|
||||
<ul>
|
||||
<li>L1 instruction cache reads and misses;
|
||||
<li>L1 data cache reads and read misses, writes and write misses;
|
||||
<li>L2 unified cache reads and read misses, writes and writes misses.
|
||||
</ul>
|
||||
On a modern x86 machine, an L1 miss will typically cost around 10 cycles,
|
||||
and an L2 miss can cost as much as 200 cycles. Detailed cache profiling can be
|
||||
very useful for improving the performance of your program.<p>
|
||||
|
||||
Also, since one instruction cache read is performed per instruction executed,
|
||||
you can find out how many instructions are executed per line, which can be
|
||||
useful for traditional profiling and test coverage.<p>
|
||||
|
||||
Any feedback, bug-fixes, suggestions, etc, welcome.
|
||||
|
||||
|
||||
<h3>4.2 Overview</h3>
|
||||
First off, as for normal Valgrind use, you probably want to compile with
|
||||
debugging info (the <code>-g</code> flag). But by contrast with normal
|
||||
Valgrind use, you probably <b>do</b> want to turn optimisation on, since you
|
||||
should profile your program as it will be normally run.
|
||||
|
||||
The two steps are:
|
||||
<ol>
|
||||
<li>Run your program with <code>valgrind --tool=cachegrind</code> in front of
|
||||
the normal command line invocation. When the program finishes,
|
||||
Cachegrind will print summary cache statistics. It also collects
|
||||
line-by-line information in a file
|
||||
<code>cachegrind.out.<i>pid</i></code>, where <code><i>pid</i></code>
|
||||
is the program's process id.
|
||||
<p>
|
||||
This step should be done every time you want to collect
|
||||
information about a new program, a changed program, or about the
|
||||
same program with different input.
|
||||
</li><p>
|
||||
<li>Generate a function-by-function summary, and possibly annotate
|
||||
source files, using the supplied
|
||||
<code>cg_annotate</code> program. Source files to annotate can be
|
||||
specified manually, or manually on the command line, or
|
||||
"interesting" source files can be annotated automatically with
|
||||
the <code>--auto=yes</code> option. You can annotate C/C++
|
||||
files or assembly language files equally easily.
|
||||
<p>
|
||||
This step can be performed as many times as you like for each
|
||||
Step 2. You may want to do multiple annotations showing
|
||||
different information each time.
|
||||
</li><p>
|
||||
</ol>
|
||||
|
||||
The steps are described in detail in the following sections.
|
||||
|
||||
|
||||
<h3>4.3 Cache simulation specifics</h3>
|
||||
|
||||
Cachegrind uses a simulation for a machine with a split L1 cache and a unified
|
||||
L2 cache. This configuration is used for all (modern) x86-based machines we
|
||||
are aware of. Old Cyrix CPUs had a unified I and D L1 cache, but they are
|
||||
ancient history now.<p>
|
||||
|
||||
The more specific characteristics of the simulation are as follows.
|
||||
|
||||
<ul>
|
||||
<li>Write-allocate: when a write miss occurs, the block written to
|
||||
is brought into the D1 cache. Most modern caches have this
|
||||
property.<p>
|
||||
</li>
|
||||
<p>
|
||||
<li>Bit-selection hash function: the line(s) in the cache to which a
|
||||
memory block maps is chosen by the middle bits M--(M+N-1) of the
|
||||
byte address, where:
|
||||
<ul>
|
||||
<li> line size = 2^M bytes </li>
|
||||
<li>(cache size / line size) = 2^N bytes</li>
|
||||
</ul>
|
||||
</li>
|
||||
<p>
|
||||
<li>Inclusive L2 cache: the L2 cache replicates all the entries of
|
||||
the L1 cache. This is standard on Pentium chips, but AMD
|
||||
Athlons use an exclusive L2 cache that only holds blocks evicted
|
||||
from L1. Ditto AMD Durons and most modern VIAs.</li>
|
||||
</ul>
|
||||
|
||||
The cache configuration simulated (cache size, associativity and line size) is
|
||||
determined automagically using the CPUID instruction. If you have an old
|
||||
machine that (a) doesn't support the CPUID instruction, or (b) supports it in
|
||||
an early incarnation that doesn't give any cache information, then Cachegrind
|
||||
will fall back to using a default configuration (that of a model 3/4 Athlon).
|
||||
Cachegrind will tell you if this happens. You can manually specify one, two or
|
||||
all three levels (I1/D1/L2) of the cache from the command line using the
|
||||
<code>--I1</code>, <code>--D1</code> and <code>--L2</code> options.
|
||||
|
||||
<p>
|
||||
Other noteworthy behaviour:
|
||||
|
||||
<ul>
|
||||
<li>References that straddle two cache lines are treated as follows:
|
||||
<ul>
|
||||
<li>If both blocks hit --> counted as one hit</li>
|
||||
<li>If one block hits, the other misses --> counted as one miss</li>
|
||||
<li>If both blocks miss --> counted as one miss (not two)</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>Instructions that modify a memory location (eg. <code>inc</code> and
|
||||
<code>dec</code>) are counted as doing just a read, ie. a single data
|
||||
reference. This may seem strange, but since the write can never cause a
|
||||
miss (the read guarantees the block is in the cache) it's not very
|
||||
interesting.
|
||||
<p>
|
||||
Thus it measures not the number of times the data cache is accessed, but
|
||||
the number of times a data cache miss could occur.<p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
If you are interested in simulating a cache with different properties, it is
|
||||
not particularly hard to write your own cache simulator, or to modify the
|
||||
existing ones in <code>vg_cachesim_I1.c</code>, <code>vg_cachesim_D1.c</code>,
|
||||
<code>vg_cachesim_L2.c</code> and <code>vg_cachesim_gen.c</code>. We'd be
|
||||
interested to hear from anyone who does.
|
||||
|
||||
|
||||
<a name="profile"></a>
|
||||
<h3>4.4 Profiling programs</h3>
|
||||
|
||||
To gather cache profiling information about the program <code>ls -l</code>,
|
||||
invoke Cachegrind like this:
|
||||
|
||||
<blockquote><code>valgrind --tool=cachegrind ls -l</code></blockquote>
|
||||
|
||||
The program will execute (slowly). Upon completion, summary statistics
|
||||
that look like this will be printed:
|
||||
|
||||
<pre>
|
||||
==31751== I refs: 27,742,716
|
||||
==31751== I1 misses: 276
|
||||
==31751== L2 misses: 275
|
||||
==31751== I1 miss rate: 0.0%
|
||||
==31751== L2i miss rate: 0.0%
|
||||
==31751==
|
||||
==31751== D refs: 15,430,290 (10,955,517 rd + 4,474,773 wr)
|
||||
==31751== D1 misses: 41,185 ( 21,905 rd + 19,280 wr)
|
||||
==31751== L2 misses: 23,085 ( 3,987 rd + 19,098 wr)
|
||||
==31751== D1 miss rate: 0.2% ( 0.1% + 0.4%)
|
||||
==31751== L2d miss rate: 0.1% ( 0.0% + 0.4%)
|
||||
==31751==
|
||||
==31751== L2 misses: 23,360 ( 4,262 rd + 19,098 wr)
|
||||
==31751== L2 miss rate: 0.0% ( 0.0% + 0.4%)
|
||||
</pre>
|
||||
|
||||
Cache accesses for instruction fetches are summarised first, giving the
|
||||
number of fetches made (this is the number of instructions executed, which
|
||||
can be useful to know in its own right), the number of I1 misses, and the
|
||||
number of L2 instruction (<code>L2i</code>) misses.
|
||||
<p>
|
||||
Cache accesses for data follow. The information is similar to that of the
|
||||
instruction fetches, except that the values are also shown split between reads
|
||||
and writes (note each row's <code>rd</code> and <code>wr</code> values add up
|
||||
to the row's total).
|
||||
<p>
|
||||
Combined instruction and data figures for the L2 cache follow that.
|
||||
|
||||
|
||||
<h3>4.5 Output file</h3>
|
||||
|
||||
As well as printing summary information, Cachegrind also writes
|
||||
line-by-line cache profiling information to a file named
|
||||
<code>cachegrind.out.<i>pid</i></code>. This file is human-readable, but is
|
||||
best interpreted by the accompanying program <code>cg_annotate</code>,
|
||||
described in the next section.
|
||||
<p>
|
||||
Things to note about the <code>cachegrind.out.<i>pid</i></code> file:
|
||||
<ul>
|
||||
<li>It is written every time Cachegrind
|
||||
is run, and will overwrite any existing
|
||||
<code>cachegrind.out.<i>pid</i></code> in the current directory (but
|
||||
that won't happen very often because it takes some time for process ids
|
||||
to be recycled).</li><p>
|
||||
<li>It can be huge: <code>ls -l</code> generates a file of about
|
||||
350KB. Browsing a few files and web pages with a Konqueror
|
||||
built with full debugging information generates a file
|
||||
of around 15 MB.</li>
|
||||
</ul>
|
||||
|
||||
Note that older versions of Cachegrind used a log file named
|
||||
<code>cachegrind.out</code> (i.e. no <code><i>.pid</i></code> suffix).
|
||||
The suffix serves two purposes. Firstly, it means you don't have to
|
||||
rename old log files that you don't want to overwrite. Secondly, and
|
||||
more importantly, it allows correct profiling with the
|
||||
<code>--trace-children=yes</code> option of programs that spawn child
|
||||
processes.
|
||||
|
||||
|
||||
<a name="profileflags"></a>
|
||||
<h3>4.6 Cachegrind options</h3>
|
||||
|
||||
Cache-simulation specific options are:
|
||||
|
||||
<ul>
|
||||
<li><code>--I1=<size>,<associativity>,<line_size></code><br>
|
||||
<code>--D1=<size>,<associativity>,<line_size></code><br>
|
||||
<code>--L2=<size>,<associativity>,<line_size></code><p>
|
||||
[default: uses CPUID for automagic cache configuration]<p>
|
||||
|
||||
Manually specifies the I1/D1/L2 cache configuration, where
|
||||
<code>size</code> and <code>line_size</code> are measured in bytes. The
|
||||
three items must be comma-separated, but with no spaces, eg:
|
||||
|
||||
<blockquote>
|
||||
<code>valgrind --tool=cachegrind --I1=65535,2,64</code>
|
||||
</blockquote>
|
||||
|
||||
You can specify one, two or three of the I1/D1/L2 caches. Any level not
|
||||
manually specified will be simulated using the configuration found in the
|
||||
normal way (via the CPUID instruction, or failing that, via defaults).
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="annotate"></a>
|
||||
<h3>4.7 Annotating C/C++ programs</h3>
|
||||
|
||||
Before using <code>cg_annotate</code>, it is worth widening your
|
||||
window to be at least 120-characters wide if possible, as the output
|
||||
lines can be quite long.
|
||||
<p>
|
||||
To get a function-by-function summary, run <code>cg_annotate
|
||||
--<i>pid</i></code> in a directory containing a
|
||||
<code>cachegrind.out.<i>pid</i></code> file. The <code>--<i>pid</i></code>
|
||||
is required so that <code>cg_annotate</code> knows which log file to use when
|
||||
several are present.
|
||||
<p>
|
||||
The output looks like this:
|
||||
|
||||
<pre>
|
||||
--------------------------------------------------------------------------------
|
||||
I1 cache: 65536 B, 64 B, 2-way associative
|
||||
D1 cache: 65536 B, 64 B, 2-way associative
|
||||
L2 cache: 262144 B, 64 B, 8-way associative
|
||||
Command: concord vg_to_ucode.c
|
||||
Events recorded: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
|
||||
Events shown: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
|
||||
Event sort order: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
|
||||
Threshold: 99%
|
||||
Chosen for annotation:
|
||||
Auto-annotation: on
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
|
||||
--------------------------------------------------------------------------------
|
||||
27,742,716 276 275 10,955,517 21,905 3,987 4,474,773 19,280 19,098 PROGRAM TOTALS
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw file:function
|
||||
--------------------------------------------------------------------------------
|
||||
8,821,482 5 5 2,242,702 1,621 73 1,794,230 0 0 getc.c:_IO_getc
|
||||
5,222,023 4 4 2,276,334 16 12 875,959 1 1 concord.c:get_word
|
||||
2,649,248 2 2 1,344,810 7,326 1,385 . . . vg_main.c:strcmp
|
||||
2,521,927 2 2 591,215 0 0 179,398 0 0 concord.c:hash
|
||||
2,242,740 2 2 1,046,612 568 22 448,548 0 0 ctype.c:tolower
|
||||
1,496,937 4 4 630,874 9,000 1,400 279,388 0 0 concord.c:insert
|
||||
897,991 51 51 897,831 95 30 62 1 1 ???:???
|
||||
598,068 1 1 299,034 0 0 149,517 0 0 ../sysdeps/generic/lockfile.c:__flockfile
|
||||
598,068 0 0 299,034 0 0 149,517 0 0 ../sysdeps/generic/lockfile.c:__funlockfile
|
||||
598,024 4 4 213,580 35 16 149,506 0 0 vg_clientmalloc.c:malloc
|
||||
446,587 1 1 215,973 2,167 430 129,948 14,057 13,957 concord.c:add_existing
|
||||
341,760 2 2 128,160 0 0 128,160 0 0 vg_clientmalloc.c:vg_trap_here_WRAPPER
|
||||
320,782 4 4 150,711 276 0 56,027 53 53 concord.c:init_hash_table
|
||||
298,998 1 1 106,785 0 0 64,071 1 1 concord.c:create
|
||||
149,518 0 0 149,516 0 0 1 0 0 ???:tolower@@GLIBC_2.0
|
||||
149,518 0 0 149,516 0 0 1 0 0 ???:fgetc@@GLIBC_2.0
|
||||
95,983 4 4 38,031 0 0 34,409 3,152 3,150 concord.c:new_word_node
|
||||
85,440 0 0 42,720 0 0 21,360 0 0 vg_clientmalloc.c:vg_bogus_epilogue
|
||||
</pre>
|
||||
|
||||
First up is a summary of the annotation options:
|
||||
|
||||
<ul>
|
||||
<li>I1 cache, D1 cache, L2 cache: cache configuration. So you know the
|
||||
configuration with which these results were obtained.</li><p>
|
||||
|
||||
<li>Command: the command line invocation of the program under
|
||||
examination.</li><p>
|
||||
|
||||
<li>Events recorded: event abbreviations are:<p>
|
||||
<ul>
|
||||
<li><code>Ir </code>: I cache reads (ie. instructions executed)</li>
|
||||
<li><code>I1mr</code>: I1 cache read misses</li>
|
||||
<li><code>I2mr</code>: L2 cache instruction read misses</li>
|
||||
<li><code>Dr </code>: D cache reads (ie. memory reads)</li>
|
||||
<li><code>D1mr</code>: D1 cache read misses</li>
|
||||
<li><code>D2mr</code>: L2 cache data read misses</li>
|
||||
<li><code>Dw </code>: D cache writes (ie. memory writes)</li>
|
||||
<li><code>D1mw</code>: D1 cache write misses</li>
|
||||
<li><code>D2mw</code>: L2 cache data write misses</li>
|
||||
</ul><p>
|
||||
Note that D1 total accesses is given by <code>D1mr</code> +
|
||||
<code>D1mw</code>, and that L2 total accesses is given by
|
||||
<code>I2mr</code> + <code>D2mr</code> + <code>D2mw</code>.</li><p>
|
||||
|
||||
<li>Events shown: the events shown (a subset of events gathered). This can
|
||||
be adjusted with the <code>--show</code> option.</li><p>
|
||||
|
||||
<li>Event sort order: the sort order in which functions are shown. For
|
||||
example, in this case the functions are sorted from highest
|
||||
<code>Ir</code> counts to lowest. If two functions have identical
|
||||
<code>Ir</code> counts, they will then be sorted by <code>I1mr</code>
|
||||
counts, and so on. This order can be adjusted with the
|
||||
<code>--sort</code> option.<p>
|
||||
|
||||
Note that this dictates the order the functions appear. It is <b>not</b>
|
||||
the order in which the columns appear; that is dictated by the "events
|
||||
shown" line (and can be changed with the <code>--show</code> option).
|
||||
</li><p>
|
||||
|
||||
<li>Threshold: <code>cg_annotate</code> by default omits functions
|
||||
that cause very low numbers of misses to avoid drowning you in
|
||||
information. In this case, cg_annotate shows summaries the
|
||||
functions that account for 99% of the <code>Ir</code> counts;
|
||||
<code>Ir</code> is chosen as the threshold event since it is the
|
||||
primary sort event. The threshold can be adjusted with the
|
||||
<code>--threshold</code> option.</li><p>
|
||||
|
||||
<li>Chosen for annotation: names of files specified manually for annotation;
|
||||
in this case none.</li><p>
|
||||
|
||||
<li>Auto-annotation: whether auto-annotation was requested via the
|
||||
<code>--auto=yes</code> option. In this case no.</li><p>
|
||||
</ul>
|
||||
|
||||
Then follows summary statistics for the whole program. These are similar
|
||||
to the summary provided when running <code>valgrind --tool=cachegrind</code>.<p>
|
||||
|
||||
Then follows function-by-function statistics. Each function is
|
||||
identified by a <code>file_name:function_name</code> pair. If a column
|
||||
contains only a dot it means the function never performs
|
||||
that event (eg. the third row shows that <code>strcmp()</code>
|
||||
contains no instructions that write to memory). The name
|
||||
<code>???</code> is used if the the file name and/or function name
|
||||
could not be determined from debugging information. If most of the
|
||||
entries have the form <code>???:???</code> the program probably wasn't
|
||||
compiled with <code>-g</code>. If any code was invalidated (either due to
|
||||
self-modifying code or unloading of shared objects) its counts are aggregated
|
||||
into a single cost centre written as <code>(discarded):(discarded)</code>.<p>
|
||||
|
||||
It is worth noting that functions will come from three types of source files:
|
||||
<ol>
|
||||
<li> From the profiled program (<code>concord.c</code> in this example).</li>
|
||||
<li>From libraries (eg. <code>getc.c</code>)</li>
|
||||
<li>From Valgrind's implementation of some libc functions (eg.
|
||||
<code>vg_clientmalloc.c:malloc</code>). These are recognisable because
|
||||
the filename begins with <code>vg_</code>, and is probably one of
|
||||
<code>vg_main.c</code>, <code>vg_clientmalloc.c</code> or
|
||||
<code>vg_mylibc.c</code>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
There are two ways to annotate source files -- by choosing them
|
||||
manually, or with the <code>--auto=yes</code> option. To do it
|
||||
manually, just specify the filenames as arguments to
|
||||
<code>cg_annotate</code>. For example, the output from running
|
||||
<code>cg_annotate concord.c</code> for our example produces the same
|
||||
output as above followed by an annotated version of
|
||||
<code>concord.c</code>, a section of which looks like:
|
||||
|
||||
<pre>
|
||||
--------------------------------------------------------------------------------
|
||||
-- User-annotated source: concord.c
|
||||
--------------------------------------------------------------------------------
|
||||
Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw
|
||||
|
||||
[snip]
|
||||
|
||||
. . . . . . . . . void init_hash_table(char *file_name, Word_Node *table[])
|
||||
3 1 1 . . . 1 0 0 {
|
||||
. . . . . . . . . FILE *file_ptr;
|
||||
. . . . . . . . . Word_Info *data;
|
||||
1 0 0 . . . 1 1 1 int line = 1, i;
|
||||
. . . . . . . . .
|
||||
5 0 0 . . . 3 0 0 data = (Word_Info *) create(sizeof(Word_Info));
|
||||
. . . . . . . . .
|
||||
4,991 0 0 1,995 0 0 998 0 0 for (i = 0; i < TABLE_SIZE; i++)
|
||||
3,988 1 1 1,994 0 0 997 53 52 table[i] = NULL;
|
||||
. . . . . . . . .
|
||||
. . . . . . . . . /* Open file, check it. */
|
||||
6 0 0 1 0 0 4 0 0 file_ptr = fopen(file_name, "r");
|
||||
2 0 0 1 0 0 . . . if (!(file_ptr)) {
|
||||
. . . . . . . . . fprintf(stderr, "Couldn't open '%s'.\n", file_name);
|
||||
1 1 1 . . . . . . exit(EXIT_FAILURE);
|
||||
. . . . . . . . . }
|
||||
. . . . . . . . .
|
||||
165,062 1 1 73,360 0 0 91,700 0 0 while ((line = get_word(data, line, file_ptr)) != EOF)
|
||||
146,712 0 0 73,356 0 0 73,356 0 0 insert(data->;word, data->line, table);
|
||||
. . . . . . . . .
|
||||
4 0 0 1 0 0 2 0 0 free(data);
|
||||
4 0 0 1 0 0 2 0 0 fclose(file_ptr);
|
||||
3 0 0 2 0 0 . . . }
|
||||
</pre>
|
||||
|
||||
(Although column widths are automatically minimised, a wide terminal is clearly
|
||||
useful.)<p>
|
||||
|
||||
Each source file is clearly marked (<code>User-annotated source</code>) as
|
||||
having been chosen manually for annotation. If the file was found in one of
|
||||
the directories specified with the <code>-I</code>/<code>--include</code>
|
||||
option, the directory and file are both given.<p>
|
||||
|
||||
Each line is annotated with its event counts. Events not applicable for a line
|
||||
are represented by a `.'; this is useful for distinguishing between an event
|
||||
which cannot happen, and one which can but did not.<p>
|
||||
|
||||
Sometimes only a small section of a source file is executed. To minimise
|
||||
uninteresting output, Valgrind only shows annotated lines and lines within a
|
||||
small distance of annotated lines. Gaps are marked with the line numbers so
|
||||
you know which part of a file the shown code comes from, eg:
|
||||
|
||||
<pre>
|
||||
(figures and code for line 704)
|
||||
-- line 704 ----------------------------------------
|
||||
-- line 878 ----------------------------------------
|
||||
(figures and code for line 878)
|
||||
</pre>
|
||||
|
||||
The amount of context to show around annotated lines is controlled by the
|
||||
<code>--context</code> option.<p>
|
||||
|
||||
To get automatic annotation, run <code>cg_annotate --auto=yes</code>.
|
||||
cg_annotate will automatically annotate every source file it can find that is
|
||||
mentioned in the function-by-function summary. Therefore, the files chosen for
|
||||
auto-annotation are affected by the <code>--sort</code> and
|
||||
<code>--threshold</code> options. Each source file is clearly marked
|
||||
(<code>Auto-annotated source</code>) as being chosen automatically. Any files
|
||||
that could not be found are mentioned at the end of the output, eg:
|
||||
|
||||
<pre>
|
||||
--------------------------------------------------------------------------------
|
||||
The following files chosen for auto-annotation could not be found:
|
||||
--------------------------------------------------------------------------------
|
||||
getc.c
|
||||
ctype.c
|
||||
../sysdeps/generic/lockfile.c
|
||||
</pre>
|
||||
|
||||
This is quite common for library files, since libraries are usually compiled
|
||||
with debugging information, but the source files are often not present on a
|
||||
system. If a file is chosen for annotation <b>both</b> manually and
|
||||
automatically, it is marked as <code>User-annotated source</code>.
|
||||
|
||||
Use the <code>-I/--include</code> option to tell Valgrind where to look for
|
||||
source files if the filenames found from the debugging information aren't
|
||||
specific enough.
|
||||
|
||||
Beware that cg_annotate can take some time to digest large
|
||||
<code>cachegrind.out.<i>pid</i></code> files, e.g. 30 seconds or more. Also
|
||||
beware that auto-annotation can produce a lot of output if your program is
|
||||
large!
|
||||
|
||||
|
||||
<h3>4.8 Annotating assembler programs</h3>
|
||||
|
||||
Valgrind can annotate assembler programs too, or annotate the
|
||||
assembler generated for your C program. Sometimes this is useful for
|
||||
understanding what is really happening when an interesting line of C
|
||||
code is translated into multiple instructions.<p>
|
||||
|
||||
To do this, you just need to assemble your <code>.s</code> files with
|
||||
assembler-level debug information. gcc doesn't do this, but you can
|
||||
use the GNU assembler with the <code>--gstabs</code> option to
|
||||
generate object files with this information, eg:
|
||||
|
||||
<blockquote><code>as --gstabs foo.s</code></blockquote>
|
||||
|
||||
You can then profile and annotate source files in the same way as for C/C++
|
||||
programs.
|
||||
|
||||
|
||||
<h3>4.9 <code>cg_annotate</code> options</h3>
|
||||
<ul>
|
||||
<li><code>--<i>pid</i></code></li><p>
|
||||
|
||||
Indicates which <code>cachegrind.out.<i>pid</i></code> file to read.
|
||||
Not actually an option -- it is required.
|
||||
|
||||
<li><code>-h, --help</code></li><p>
|
||||
<li><code>-v, --version</code><p>
|
||||
|
||||
Help and version, as usual.</li>
|
||||
|
||||
<li><code>--sort=A,B,C</code> [default: order in
|
||||
<code>cachegrind.out.<i>pid</i></code>]<p>
|
||||
Specifies the events upon which the sorting of the function-by-function
|
||||
entries will be based. Useful if you want to concentrate on eg. I cache
|
||||
misses (<code>--sort=I1mr,I2mr</code>), or D cache misses
|
||||
(<code>--sort=D1mr,D2mr</code>), or L2 misses
|
||||
(<code>--sort=D2mr,I2mr</code>).</li><p>
|
||||
|
||||
<li><code>--show=A,B,C</code> [default: all, using order in
|
||||
<code>cachegrind.out.<i>pid</i></code>]<p>
|
||||
Specifies which events to show (and the column order). Default is to use
|
||||
all present in the <code>cachegrind.out.<i>pid</i></code> file (and use
|
||||
the order in the file).</li><p>
|
||||
|
||||
<li><code>--threshold=X</code> [default: 99%] <p>
|
||||
Sets the threshold for the function-by-function summary. Functions are
|
||||
shown that account for more than X% of the primary sort event. If
|
||||
auto-annotating, also affects which files are annotated.
|
||||
|
||||
Note: thresholds can be set for more than one of the events by appending
|
||||
any events for the <code>--sort</code> option with a colon and a number
|
||||
(no spaces, though). E.g. if you want to see the functions that cover
|
||||
99% of L2 read misses and 99% of L2 write misses, use this option:
|
||||
|
||||
<blockquote><code>--sort=D2mr:99,D2mw:99</code></blockquote>
|
||||
</li><p>
|
||||
|
||||
<li><code>--auto=no</code> [default]<br>
|
||||
<code>--auto=yes</code> <p>
|
||||
When enabled, automatically annotates every file that is mentioned in the
|
||||
function-by-function summary that can be found. Also gives a list of
|
||||
those that couldn't be found.
|
||||
|
||||
<li><code>--context=N</code> [default: 8]<p>
|
||||
Print N lines of context before and after each annotated line. Avoids
|
||||
printing large sections of source files that were not executed. Use a
|
||||
large number (eg. 10,000) to show all source lines.
|
||||
</li><p>
|
||||
|
||||
<li><code>-I=<dir>, --include=<dir></code>
|
||||
[default: empty string]<p>
|
||||
Adds a directory to the list in which to search for files. Multiple
|
||||
-I/--include options can be given to add multiple directories.
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>4.10 Warnings</h3>
|
||||
There are a couple of situations in which cg_annotate issues warnings.
|
||||
|
||||
<ul>
|
||||
<li>If a source file is more recent than the
|
||||
<code>cachegrind.out.<i>pid</i></code> file. This is because the
|
||||
information in <code>cachegrind.out.<i>pid</i></code> is only recorded
|
||||
with line numbers, so if the line numbers change at all in the source
|
||||
(eg. lines added, deleted, swapped), any annotations will be
|
||||
incorrect.<p>
|
||||
|
||||
<li>If information is recorded about line numbers past the end of a file.
|
||||
This can be caused by the above problem, ie. shortening the source file
|
||||
while using an old <code>cachegrind.out.<i>pid</i></code> file. If this
|
||||
happens, the figures for the bogus lines are printed anyway (clearly
|
||||
marked as bogus) in case they are important.</li><p>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>4.11 Things to watch out for</h3>
|
||||
Some odd things that can occur during annotation:
|
||||
|
||||
<ul>
|
||||
<li>If annotating at the assembler level, you might see something like this:
|
||||
|
||||
<pre>
|
||||
1 0 0 . . . . . . leal -12(%ebp),%eax
|
||||
1 0 0 . . . 1 0 0 movl %eax,84(%ebx)
|
||||
2 0 0 0 0 0 1 0 0 movl $1,-20(%ebp)
|
||||
. . . . . . . . . .align 4,0x90
|
||||
1 0 0 . . . . . . movl $.LnrB,%eax
|
||||
1 0 0 . . . 1 0 0 movl %eax,-16(%ebp)
|
||||
</pre>
|
||||
|
||||
How can the third instruction be executed twice when the others are
|
||||
executed only once? As it turns out, it isn't. Here's a dump of the
|
||||
executable, using <code>objdump -d</code>:
|
||||
|
||||
<pre>
|
||||
8048f25: 8d 45 f4 lea 0xfffffff4(%ebp),%eax
|
||||
8048f28: 89 43 54 mov %eax,0x54(%ebx)
|
||||
8048f2b: c7 45 ec 01 00 00 00 movl $0x1,0xffffffec(%ebp)
|
||||
8048f32: 89 f6 mov %esi,%esi
|
||||
8048f34: b8 08 8b 07 08 mov $0x8078b08,%eax
|
||||
8048f39: 89 45 f0 mov %eax,0xfffffff0(%ebp)
|
||||
</pre>
|
||||
|
||||
Notice the extra <code>mov %esi,%esi</code> instruction. Where did this
|
||||
come from? The GNU assembler inserted it to serve as the two bytes of
|
||||
padding needed to align the <code>movl $.LnrB,%eax</code> instruction on
|
||||
a four-byte boundary, but pretended it didn't exist when adding debug
|
||||
information. Thus when Valgrind reads the debug info it thinks that the
|
||||
<code>movl $0x1,0xffffffec(%ebp)</code> instruction covers the address
|
||||
range 0x8048f2b--0x804833 by itself, and attributes the counts for the
|
||||
<code>mov %esi,%esi</code> to it.<p>
|
||||
</li>
|
||||
|
||||
<li>Inlined functions can cause strange results in the function-by-function
|
||||
summary. If a function <code>inline_me()</code> is defined in
|
||||
<code>foo.h</code> and inlined in the functions <code>f1()</code>,
|
||||
<code>f2()</code> and <code>f3()</code> in <code>bar.c</code>, there will
|
||||
not be a <code>foo.h:inline_me()</code> function entry. Instead, there
|
||||
will be separate function entries for each inlining site, ie.
|
||||
<code>foo.h:f1()</code>, <code>foo.h:f2()</code> and
|
||||
<code>foo.h:f3()</code>. To find the total counts for
|
||||
<code>foo.h:inline_me()</code>, add up the counts from each entry.<p>
|
||||
|
||||
The reason for this is that although the debug info output by gcc
|
||||
indicates the switch from <code>bar.c</code> to <code>foo.h</code>, it
|
||||
doesn't indicate the name of the function in <code>foo.h</code>, so
|
||||
Valgrind keeps using the old one.<p>
|
||||
|
||||
<li>Sometimes, the same filename might be represented with a relative name
|
||||
and with an absolute name in different parts of the debug info, eg:
|
||||
<code>/home/user/proj/proj.h</code> and <code>../proj.h</code>. In this
|
||||
case, if you use auto-annotation, the file will be annotated twice with
|
||||
the counts split between the two.<p>
|
||||
</li>
|
||||
|
||||
<li>Files with more than 65,535 lines cause difficulties for the stabs debug
|
||||
info reader. This is because the line number in the <code>struct
|
||||
nlist</code> defined in <code>a.out.h</code> under Linux is only a 16-bit
|
||||
value. Valgrind can handle some files with more than 65,535 lines
|
||||
correctly by making some guesses to identify line number overflows. But
|
||||
some cases are beyond it, in which case you'll get a warning message
|
||||
explaining that annotations for the file might be incorrect.<p>
|
||||
</li>
|
||||
|
||||
<li>If you compile some files with <code>-g</code> and some without, some
|
||||
events that take place in a file without debug info could be attributed
|
||||
to the last line of a file with debug info (whichever one gets placed
|
||||
before the non-debug-info file in the executable).<p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
This list looks long, but these cases should be fairly rare.<p>
|
||||
|
||||
Note: stabs is not an easy format to read. If you come across bizarre
|
||||
annotations that look like might be caused by a bug in the stabs reader,
|
||||
please let us know.<p>
|
||||
|
||||
|
||||
<h3>4.12 Accuracy</h3>
|
||||
Valgrind's cache profiling has a number of shortcomings:
|
||||
|
||||
<ul>
|
||||
<li>It doesn't account for kernel activity -- the effect of system calls on
|
||||
the cache contents is ignored.</li><p>
|
||||
|
||||
<li>It doesn't account for other process activity (although this is probably
|
||||
desirable when considering a single program).</li><p>
|
||||
|
||||
<li>It doesn't account for virtual-to-physical address mappings; hence the
|
||||
entire simulation is not a true representation of what's happening in the
|
||||
cache.</li><p>
|
||||
|
||||
<li>It doesn't account for cache misses not visible at the instruction level,
|
||||
eg. those arising from TLB misses, or speculative execution.</li><p>
|
||||
|
||||
<li>Valgrind's custom threads implementation will schedule threads
|
||||
differently to the standard one. This could warp the results for
|
||||
threaded programs.
|
||||
</li><p>
|
||||
|
||||
<li>The instructions <code>bts</code>, <code>btr</code> and <code>btc</code>
|
||||
will incorrectly be counted as doing a data read if both the arguments
|
||||
are registers, eg:
|
||||
|
||||
<blockquote><code>btsl %eax, %edx</code></blockquote>
|
||||
|
||||
This should only happen rarely.
|
||||
</li><p>
|
||||
|
||||
<li>FPU instructions with data sizes of 28 and 108 bytes (e.g.
|
||||
<code>fsave</code>) are treated as though they only access 16 bytes.
|
||||
These instructions seem to be rare so hopefully this won't affect
|
||||
accuracy much.
|
||||
</li><p>
|
||||
</ul>
|
||||
|
||||
Another thing worth nothing is that results are very sensitive. Changing the
|
||||
size of the <code>valgrind.so</code> file, the size of the program being
|
||||
profiled, or even the length of its name can perturb the results. Variations
|
||||
will be small, but don't expect perfectly repeatable results if your program
|
||||
changes at all.<p>
|
||||
|
||||
While these factors mean you shouldn't trust the results to be super-accurate,
|
||||
hopefully they should be close enough to be useful.<p>
|
||||
|
||||
|
||||
<h3>4.13 Todo</h3>
|
||||
<ul>
|
||||
<li>Program start-up/shut-down calls a lot of functions that aren't
|
||||
interesting and just complicate the output. Would be nice to exclude
|
||||
these somehow.</li>
|
||||
<p>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,458 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
body { background-color: #ffffff;
|
||||
color: #000000;
|
||||
font-family: Times, Helvetica, Arial;
|
||||
font-size: 14pt}
|
||||
h4 { margin-bottom: 0.3em}
|
||||
code { color: #000000;
|
||||
font-family: Courier;
|
||||
font-size: 13pt }
|
||||
pre { color: #000000;
|
||||
font-family: Courier;
|
||||
font-size: 13pt }
|
||||
a:link { color: #0000C0;
|
||||
text-decoration: none; }
|
||||
a:visited { color: #0000C0;
|
||||
text-decoration: none; }
|
||||
a:active { color: #0000C0;
|
||||
text-decoration: none; }
|
||||
</style>
|
||||
<title>How Cachegrind works</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<a name="cg-techdocs"> </a>
|
||||
<h1 align=center>How Cachegrind works</h1>
|
||||
|
||||
<center>
|
||||
Detailed technical notes for hackers, maintainers and the
|
||||
overly-curious<br>
|
||||
<p>
|
||||
<a href="mailto:njn25@cam.ac.uk">njn25@cam.ac.uk</a><br>
|
||||
<a
|
||||
href="http://valgrind.kde.org">http://valgrind.kde.org</a><br>
|
||||
<p>
|
||||
Copyright © 2001-2003 Nick Nethercote
|
||||
<p>
|
||||
</center>
|
||||
|
||||
<p>
|
||||
|
||||
|
||||
|
||||
|
||||
<hr width="100%">
|
||||
|
||||
<h2>Cache profiling</h2>
|
||||
Valgrind is a very nice platform for doing cache profiling and other kinds of
|
||||
simulation, because it converts horrible x86 instructions into nice clean
|
||||
RISC-like UCode. For example, for cache profiling we are interested in
|
||||
instructions that read and write memory; in UCode there are only four
|
||||
instructions that do this: <code>LOAD</code>, <code>STORE</code>,
|
||||
<code>FPU_R</code> and <code>FPU_W</code>. By contrast, because of the x86
|
||||
addressing modes, almost every instruction can read or write memory.<p>
|
||||
|
||||
Most of the cache profiling machinery is in the file
|
||||
<code>vg_cachesim.c</code>.<p>
|
||||
|
||||
These notes are a somewhat haphazard guide to how Valgrind's cache profiling
|
||||
works.<p>
|
||||
|
||||
<h3>Cost centres</h3>
|
||||
Valgrind gathers cache profiling about every instruction executed,
|
||||
individually. Each instruction has a <b>cost centre</b> associated with it.
|
||||
There are two kinds of cost centre: one for instructions that don't reference
|
||||
memory (<code>iCC</code>), and one for instructions that do
|
||||
(<code>idCC</code>):
|
||||
|
||||
<pre>
|
||||
typedef struct _CC {
|
||||
ULong a;
|
||||
ULong m1;
|
||||
ULong m2;
|
||||
} CC;
|
||||
|
||||
typedef struct _iCC {
|
||||
/* word 1 */
|
||||
UChar tag;
|
||||
UChar instr_size;
|
||||
|
||||
/* words 2+ */
|
||||
Addr instr_addr;
|
||||
CC I;
|
||||
} iCC;
|
||||
|
||||
typedef struct _idCC {
|
||||
/* word 1 */
|
||||
UChar tag;
|
||||
UChar instr_size;
|
||||
UChar data_size;
|
||||
|
||||
/* words 2+ */
|
||||
Addr instr_addr;
|
||||
CC I;
|
||||
CC D;
|
||||
} idCC;
|
||||
</pre>
|
||||
|
||||
Each <code>CC</code> has three fields <code>a</code>, <code>m1</code>,
|
||||
<code>m2</code> for recording references, level 1 misses and level 2 misses.
|
||||
Each of these is a 64-bit <code>ULong</code> -- the numbers can get very large,
|
||||
ie. greater than 4.2 billion allowed by a 32-bit unsigned int.<p>
|
||||
|
||||
A <code>iCC</code> has one <code>CC</code> for instruction cache accesses. A
|
||||
<code>idCC</code> has two, one for instruction cache accesses, and one for data
|
||||
cache accesses.<p>
|
||||
|
||||
The <code>iCC</code> and <code>dCC</code> structs also store unchanging
|
||||
information about the instruction:
|
||||
<ul>
|
||||
<li>An instruction-type identification tag (explained below)</li><p>
|
||||
<li>Instruction size</li><p>
|
||||
<li>Data reference size (<code>idCC</code> only)</li><p>
|
||||
<li>Instruction address</li><p>
|
||||
</ul>
|
||||
|
||||
Note that data address is not one of the fields for <code>idCC</code>. This is
|
||||
because for many memory-referencing instructions the data address can change
|
||||
each time it's executed (eg. if it uses register-offset addressing). We have
|
||||
to give this item to the cache simulation in a different way (see
|
||||
Instrumentation section below). Some memory-referencing instructions do always
|
||||
reference the same address, but we don't try to treat them specialy in order to
|
||||
keep things simple.<p>
|
||||
|
||||
Also note that there is only room for recording info about one data cache
|
||||
access in an <code>idCC</code>. So what about instructions that do a read then
|
||||
a write, such as:
|
||||
|
||||
<blockquote><code>inc %(esi)</code></blockquote>
|
||||
|
||||
In a write-allocate cache, as simulated by Valgrind, the write cannot miss,
|
||||
since it immediately follows the read which will drag the block into the cache
|
||||
if it's not already there. So the write access isn't really interesting, and
|
||||
Valgrind doesn't record it. This means that Valgrind doesn't measure
|
||||
memory references, but rather memory references that could miss in the cache.
|
||||
This behaviour is the same as that used by the AMD Athlon hardware counters.
|
||||
It also has the benefit of simplifying the implementation -- instructions that
|
||||
read and write memory can be treated like instructions that read memory.<p>
|
||||
|
||||
<h3>Storing cost-centres</h3>
|
||||
Cost centres are stored in a way that makes them very cheap to lookup, which is
|
||||
important since one is looked up for every original x86 instruction
|
||||
executed.<p>
|
||||
|
||||
Valgrind does JIT translations at the basic block level, and cost centres are
|
||||
also setup and stored at the basic block level. By doing things carefully, we
|
||||
store all the cost centres for a basic block in a contiguous array, and lookup
|
||||
comes almost for free.<p>
|
||||
|
||||
Consider this part of a basic block (for exposition purposes, pretend it's an
|
||||
entire basic block):
|
||||
|
||||
<pre>
|
||||
movl $0x0,%eax
|
||||
movl $0x99, -4(%ebp)
|
||||
</pre>
|
||||
|
||||
The translation to UCode looks like this:
|
||||
|
||||
<pre>
|
||||
MOVL $0x0, t20
|
||||
PUTL t20, %EAX
|
||||
INCEIPo $5
|
||||
|
||||
LEA1L -4(t4), t14
|
||||
MOVL $0x99, t18
|
||||
STL t18, (t14)
|
||||
INCEIPo $7
|
||||
</pre>
|
||||
|
||||
The first step is to allocate the cost centres. This requires a preliminary
|
||||
pass to count how many x86 instructions were in the basic block, and their
|
||||
types (and thus sizes). UCode translations for single x86 instructions are
|
||||
delimited by the <code>INCEIPo</code> instruction, the argument of which gives
|
||||
the byte size of the instruction (note that lazy INCEIP updating is turned off
|
||||
to allow this).<p>
|
||||
|
||||
We can tell if an x86 instruction references memory by looking for
|
||||
<code>LDL</code> and <code>STL</code> UCode instructions, and thus what kind of
|
||||
cost centre is required. From this we can determine how many cost centres we
|
||||
need for the basic block, and their sizes. We can then allocate them in a
|
||||
single array.<p>
|
||||
|
||||
Consider the example code above. After the preliminary pass, we know we need
|
||||
two cost centres, one <code>iCC</code> and one <code>dCC</code>. So we
|
||||
allocate an array to store these which looks like this:
|
||||
|
||||
<pre>
|
||||
|(uninit)| tag (1 byte)
|
||||
|(uninit)| instr_size (1 bytes)
|
||||
|(uninit)| (padding) (2 bytes)
|
||||
|(uninit)| instr_addr (4 bytes)
|
||||
|(uninit)| I.a (8 bytes)
|
||||
|(uninit)| I.m1 (8 bytes)
|
||||
|(uninit)| I.m2 (8 bytes)
|
||||
|
||||
|(uninit)| tag (1 byte)
|
||||
|(uninit)| instr_size (1 byte)
|
||||
|(uninit)| data_size (1 byte)
|
||||
|(uninit)| (padding) (1 byte)
|
||||
|(uninit)| instr_addr (4 bytes)
|
||||
|(uninit)| I.a (8 bytes)
|
||||
|(uninit)| I.m1 (8 bytes)
|
||||
|(uninit)| I.m2 (8 bytes)
|
||||
|(uninit)| D.a (8 bytes)
|
||||
|(uninit)| D.m1 (8 bytes)
|
||||
|(uninit)| D.m2 (8 bytes)
|
||||
</pre>
|
||||
|
||||
(We can see now why we need tags to distinguish between the two types of cost
|
||||
centres.)<p>
|
||||
|
||||
We also record the size of the array. We look up the debug info of the first
|
||||
instruction in the basic block, and then stick the array into a table indexed
|
||||
by filename and function name. This makes it easy to dump the information
|
||||
quickly to file at the end.<p>
|
||||
|
||||
<h3>Instrumentation</h3>
|
||||
The instrumentation pass has two main jobs:
|
||||
|
||||
<ol>
|
||||
<li>Fill in the gaps in the allocated cost centres.</li><p>
|
||||
<li>Add UCode to call the cache simulator for each instruction.</li><p>
|
||||
</ol>
|
||||
|
||||
The instrumentation pass steps through the UCode and the cost centres in
|
||||
tandem. As each original x86 instruction's UCode is processed, the appropriate
|
||||
gaps in the instructions cost centre are filled in, for example:
|
||||
|
||||
<pre>
|
||||
|INSTR_CC| tag (1 byte)
|
||||
|5 | instr_size (1 bytes)
|
||||
|(uninit)| (padding) (2 bytes)
|
||||
|i_addr1 | instr_addr (4 bytes)
|
||||
|0 | I.a (8 bytes)
|
||||
|0 | I.m1 (8 bytes)
|
||||
|0 | I.m2 (8 bytes)
|
||||
|
||||
|WRITE_CC| tag (1 byte)
|
||||
|7 | instr_size (1 byte)
|
||||
|4 | data_size (1 byte)
|
||||
|(uninit)| (padding) (1 byte)
|
||||
|i_addr2 | instr_addr (4 bytes)
|
||||
|0 | I.a (8 bytes)
|
||||
|0 | I.m1 (8 bytes)
|
||||
|0 | I.m2 (8 bytes)
|
||||
|0 | D.a (8 bytes)
|
||||
|0 | D.m1 (8 bytes)
|
||||
|0 | D.m2 (8 bytes)
|
||||
</pre>
|
||||
|
||||
(Note that this step is not performed if a basic block is re-translated; see
|
||||
<a href="#retranslations">here</a> for more information.)<p>
|
||||
|
||||
GCC inserts padding before the <code>instr_size</code> field so that it is word
|
||||
aligned.<p>
|
||||
|
||||
The instrumentation added to call the cache simulation function looks like this
|
||||
(instrumentation is indented to distinguish it from the original UCode):
|
||||
|
||||
<pre>
|
||||
MOVL $0x0, t20
|
||||
PUTL t20, %EAX
|
||||
PUSHL %eax
|
||||
PUSHL %ecx
|
||||
PUSHL %edx
|
||||
MOVL $0x4091F8A4, t46 # address of 1st CC
|
||||
PUSHL t46
|
||||
CALLMo $0x12 # second cachesim function
|
||||
CLEARo $0x4
|
||||
POPL %edx
|
||||
POPL %ecx
|
||||
POPL %eax
|
||||
INCEIPo $5
|
||||
|
||||
LEA1L -4(t4), t14
|
||||
MOVL $0x99, t18
|
||||
MOVL t14, t42
|
||||
STL t18, (t14)
|
||||
PUSHL %eax
|
||||
PUSHL %ecx
|
||||
PUSHL %edx
|
||||
PUSHL t42
|
||||
MOVL $0x4091F8C4, t44 # address of 2nd CC
|
||||
PUSHL t44
|
||||
CALLMo $0x13 # second cachesim function
|
||||
CLEARo $0x8
|
||||
POPL %edx
|
||||
POPL %ecx
|
||||
POPL %eax
|
||||
INCEIPo $7
|
||||
</pre>
|
||||
|
||||
Consider the first instruction's UCode. Each call is surrounded by three
|
||||
<code>PUSHL</code> and <code>POPL</code> instructions to save and restore the
|
||||
caller-save registers. Then the address of the instruction's cost centre is
|
||||
pushed onto the stack, to be the first argument to the cache simulation
|
||||
function. The address is known at this point because we are doing a
|
||||
simultaneous pass through the cost centre array. This means the cost centre
|
||||
lookup for each instruction is almost free (just the cost of pushing an
|
||||
argument for a function call). Then the call to the cache simulation function
|
||||
for non-memory-reference instructions is made (note that the
|
||||
<code>CALLMo</code> UInstruction takes an offset into a table of predefined
|
||||
functions; it is not an absolute address), and the single argument is
|
||||
<code>CLEAR</code>ed from the stack.<p>
|
||||
|
||||
The second instruction's UCode is similar. The only difference is that, as
|
||||
mentioned before, we have to pass the address of the data item referenced to
|
||||
the cache simulation function too. This explains the <code>MOVL t14,
|
||||
t42</code> and <code>PUSHL t42</code> UInstructions. (Note that the seemingly
|
||||
redundant <code>MOV</code>ing will probably be optimised away during register
|
||||
allocation.)<p>
|
||||
|
||||
Note that instead of storing unchanging information about each instruction
|
||||
(instruction size, data size, etc) in its cost centre, we could have passed in
|
||||
these arguments to the simulation function. But this would slow the calls down
|
||||
(two or three extra arguments pushed onto the stack). Also it would bloat the
|
||||
UCode instrumentation by amounts similar to the space required for them in the
|
||||
cost centre; bloated UCode would also fill the translation cache more quickly,
|
||||
requiring more translations for large programs and slowing them down more.<p>
|
||||
|
||||
<a name="retranslations"></a>
|
||||
<h3>Handling basic block retranslations</h3>
|
||||
The above description ignores one complication. Valgrind has a limited size
|
||||
cache for basic block translations; if it fills up, old translations are
|
||||
discarded. If a discarded basic block is executed again, it must be
|
||||
re-translated.<p>
|
||||
|
||||
However, we can't use this approach for profiling -- we can't throw away cost
|
||||
centres for instructions in the middle of execution! So when a basic block is
|
||||
translated, we first look for its cost centre array in the hash table. If
|
||||
there is no cost centre array, it must be the first translation, so we proceed
|
||||
as described above. But if there is a cost centre array already, it must be a
|
||||
retranslation. In this case, we skip the cost centre allocation and
|
||||
initialisation steps, but still do the UCode instrumentation step.<p>
|
||||
|
||||
<h3>The cache simulation</h3>
|
||||
The cache simulation is fairly straightforward. It just tracks which memory
|
||||
blocks are in the cache at the moment (it doesn't track the contents, since
|
||||
that is irrelevant).<p>
|
||||
|
||||
The interface to the simulation is quite clean. The functions called from the
|
||||
UCode contain calls to the simulation functions in the files
|
||||
<Code>vg_cachesim_{I1,D1,L2}.c</code>; these calls are inlined so that only
|
||||
one function call is done per simulated x86 instruction. The file
|
||||
<code>vg_cachesim.c</code> simply <code>#include</code>s the three files
|
||||
containing the simulation, which makes plugging in new cache simulations is
|
||||
very easy -- you just replace the three files and recompile.<p>
|
||||
|
||||
<h3>Output</h3>
|
||||
Output is fairly straightforward, basically printing the cost centre for every
|
||||
instruction, grouped by files and functions. Total counts (eg. total cache
|
||||
accesses, total L1 misses) are calculated when traversing this structure rather
|
||||
than during execution, to save time; the cache simulation functions are called
|
||||
so often that even one or two extra adds can make a sizeable difference.<p>
|
||||
|
||||
Input file has the following format:
|
||||
|
||||
<pre>
|
||||
file ::= desc_line* cmd_line events_line data_line+ summary_line
|
||||
desc_line ::= "desc:" ws? non_nl_string
|
||||
cmd_line ::= "cmd:" ws? cmd
|
||||
events_line ::= "events:" ws? (event ws)+
|
||||
data_line ::= file_line | fn_line | count_line
|
||||
file_line ::= ("fl=" | "fi=" | "fe=") filename
|
||||
fn_line ::= "fn=" fn_name
|
||||
count_line ::= line_num ws? (count ws)+
|
||||
summary_line ::= "summary:" ws? (count ws)+
|
||||
count ::= num | "."
|
||||
</pre>
|
||||
|
||||
Where:
|
||||
|
||||
<ul>
|
||||
<li><code>non_nl_string</code> is any string not containing a newline.</li><p>
|
||||
<li><code>cmd</code> is a command line invocation.</li><p>
|
||||
<li><code>filename</code> and <code>fn_name</code> can be anything.</li><p>
|
||||
<li><code>num</code> and <code>line_num</code> are decimal numbers.</li><p>
|
||||
<li><code>ws</code> is whitespace.</li><p>
|
||||
<li><code>nl</code> is a newline.</li><p>
|
||||
</ul>
|
||||
|
||||
The contents of the "desc:" lines is printed out at the top of the summary.
|
||||
This is a generic way of providing simulation specific information, eg. for
|
||||
giving the cache configuration for cache simulation.<p>
|
||||
|
||||
Counts can be "." to represent "N/A", eg. the number of write misses for an
|
||||
instruction that doesn't write to memory.<p>
|
||||
|
||||
The number of counts in each <code>line</code> and the
|
||||
<code>summary_line</code> should not exceed the number of events in the
|
||||
<code>event_line</code>. If the number in each <code>line</code> is less,
|
||||
cg_annotate treats those missing as though they were a "." entry. <p>
|
||||
|
||||
A <code>file_line</code> changes the current file name. A <code>fn_line</code>
|
||||
changes the current function name. A <code>count_line</code> contains counts
|
||||
that pertain to the current filename/fn_name. A "fn=" <code>file_line</code>
|
||||
and a <code>fn_line</code> must appear before any <code>count_line</code>s to
|
||||
give the context of the first <code>count_line</code>s.<p>
|
||||
|
||||
Each <code>file_line</code> should be immediately followed by a
|
||||
<code>fn_line</code>. "fi=" <code>file_lines</code> are used to switch
|
||||
filenames for inlined functions; "fe=" <code>file_lines</code> are similar, but
|
||||
are put at the end of a basic block in which the file name hasn't been switched
|
||||
back to the original file name. (fi and fe lines behave the same, they are
|
||||
only distinguished to help debugging.)<p>
|
||||
|
||||
|
||||
<h3>Summary of performance features</h3>
|
||||
Quite a lot of work has gone into making the profiling as fast as possible.
|
||||
This is a summary of the important features:
|
||||
|
||||
<ul>
|
||||
<li>The basic block-level cost centre storage allows almost free cost centre
|
||||
lookup.</li><p>
|
||||
|
||||
<li>Only one function call is made per instruction simulated; even this
|
||||
accounts for a sizeable percentage of execution time, but it seems
|
||||
unavoidable if we want flexibility in the cache simulator.</li><p>
|
||||
|
||||
<li>Unchanging information about an instruction is stored in its cost centre,
|
||||
avoiding unnecessary argument pushing, and minimising UCode
|
||||
instrumentation bloat.</li><p>
|
||||
|
||||
<li>Summary counts are calculated at the end, rather than during
|
||||
execution.</li><p>
|
||||
|
||||
<li>The <code>cachegrind.out</code> output files can contain huge amounts of
|
||||
information; file format was carefully chosen to minimise file
|
||||
sizes.</li><p>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Annotation</h3>
|
||||
Annotation is done by cg_annotate. It is a fairly straightforward Perl script
|
||||
that slurps up all the cost centres, and then runs through all the chosen
|
||||
source files, printing out cost centres with them. It too has been carefully
|
||||
optimised.
|
||||
|
||||
|
||||
<h3>Similar work, extensions</h3>
|
||||
It would be relatively straightforward to do other simulations and obtain
|
||||
line-by-line information about interesting events. A good example would be
|
||||
branch prediction -- all branches could be instrumented to interact with a
|
||||
branch prediction simulator, using very similar techniques to those described
|
||||
above.<p>
|
||||
|
||||
In particular, cg_annotate would not need to change -- the file format is such
|
||||
that it is not specific to the cache simulation, but could be used for any kind
|
||||
of line-by-line information. The only part of cg_annotate that is specific to
|
||||
the cache simulation is the name of the input file
|
||||
(<code>cachegrind.out</code>), although it would be very simple to add an
|
||||
option to control this.<p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user