You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
1
(20) |
2
(19) |
3
(7) |
|
4
(13) |
5
(24) |
6
(9) |
7
(12) |
8
(8) |
9
(34) |
10
(28) |
|
11
(20) |
12
(23) |
13
(12) |
14
(10) |
15
(15) |
16
(24) |
17
(26) |
|
18
(17) |
19
(14) |
20
(14) |
21
(8) |
22
(12) |
23
(22) |
24
(10) |
|
25
(21) |
26
(21) |
27
(18) |
28
(8) |
29
(13) |
30
(15) |
|
|
From: <sv...@va...> - 2007-11-09 23:59:49
|
Author: sewardj
Date: 2007-11-09 23:59:49 +0000 (Fri, 09 Nov 2007)
New Revision: 7130
Log:
Rename in the manual.
Modified:
trunk/helgrind/docs/hg-manual.xml
Modified: trunk/helgrind/docs/hg-manual.xml
===================================================================
--- trunk/helgrind/docs/hg-manual.xml 2007-11-09 23:59:14 UTC (rev 7129)
+++ trunk/helgrind/docs/hg-manual.xml 2007-11-09 23:59:49 UTC (rev 7130)
@@ -3,20 +3,20 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-<chapter id="tc-manual" xreflabel="Thrcheck: thread error detector">
- <title>Thrcheck: a thread error detector</title>
+<chapter id="hg-manual" xreflabel="Helgrind: thread error detector">
+ <title>Helgrind: a thread error detector</title>
<para>To use this tool, you must specify
-<computeroutput>--tool=thrcheck</computeroutput> on the Valgrind
+<computeroutput>--tool=helgrind</computeroutput> on the Valgrind
command line.</para>
-<sect1 id="tc-manual.overview" xreflabel="Overview">
+<sect1 id="hg-manual.overview" xreflabel="Overview">
<title>Overview</title>
-<para>Thrcheck is a Valgrind tool for detecting synchronisation errors
+<para>Helgrind is a Valgrind tool for detecting synchronisation errors
in C, C++ and Fortran programs that use the POSIX pthreads
threading primitives.</para>
@@ -25,7 +25,7 @@
thread exit, mutexes (locks), condition variables (inter-thread event
notifications), reader-writer locks, and semaphores.</para>
-<para>Thrcheck is aware of all these abstractions and tracks their
+<para>Helgrind is aware of all these abstractions and tracks their
effects as accurately as it can. Currently it does not correctly
handle pthread barriers and pthread spinlocks, although it will not
object if you use them. On x86 and amd64 platforms, it understands
@@ -33,38 +33,38 @@
LOCK instruction prefix.
</para>
-<para>Thrcheck can detect three classes of errors, which are discussed
+<para>Helgrind can detect three classes of errors, which are discussed
in detail in the next three sections:</para>
<orderedlist>
<listitem>
- <para><link linkend="tc-manual.api-checks">
+ <para><link linkend="hg-manual.api-checks">
Misuses of the POSIX pthreads API.</link></para>
</listitem>
<listitem>
- <para><link linkend="tc-manual.lock-orders">
+ <para><link linkend="hg-manual.lock-orders">
Potential deadlocks arising from lock
ordering problems.</link></para>
</listitem>
<listitem>
- <para><link linkend="tc-manual.data-races">
+ <para><link linkend="hg-manual.data-races">
Data races -- accessing memory without adequate locking.
</link></para>
</listitem>
</orderedlist>
<para>Following those is a section containing
-<link linkend="tc-manual.effective-use">
-hints and tips on how to get the best out of Thrcheck.</link>
+<link linkend="hg-manual.effective-use">
+hints and tips on how to get the best out of Helgrind.</link>
</para>
<para>Then there is a
-<link linkend="tc-manual.options">summary of command-line
+<link linkend="hg-manual.options">summary of command-line
options.</link>
</para>
<para>Finally, there is
-<link linkend="tc-manual.todolist">a brief summary of areas in which Thrcheck
+<link linkend="hg-manual.todolist">a brief summary of areas in which Helgrind
could be improved.</link>
</para>
@@ -73,10 +73,10 @@
-<sect1 id="tc-manual.api-checks" xreflabel="API Checks">
+<sect1 id="hg-manual.api-checks" xreflabel="API Checks">
<title>Detected errors: Misuses of the POSIX pthreads API</title>
-<para>Thrcheck intercepts calls to many POSIX pthreads functions, and
+<para>Helgrind intercepts calls to many POSIX pthreads functions, and
is therefore able to report on various common problems. Although
these are unglamourous errors, their presence can lead to undefined
program behaviour and hard-to-find bugs later in execution. The
@@ -114,26 +114,26 @@
where the error was detected. They may also contain auxiliary stack
traces giving additional information. In particular, most errors
relating to mutexes will also tell you where that mutex first came to
-Thrcheck's attention (the "<computeroutput>was first observed
+Helgrind's attention (the "<computeroutput>was first observed
at</computeroutput>" part), so you have a chance of figuring out which
mutex it is referring to. For example:</para>
<programlisting><![CDATA[
Thread #1 unlocked a not-locked lock at 0x7FEFFFA90
- at 0x4C2408D: pthread_mutex_unlock (tc_intercepts.c:492)
+ at 0x4C2408D: pthread_mutex_unlock (hg_intercepts.c:492)
by 0x40073A: nearly_main (tc09_bad_unlock.c:27)
by 0x40079B: main (tc09_bad_unlock.c:50)
Lock at 0x7FEFFFA90 was first observed
- at 0x4C25D01: pthread_mutex_init (tc_intercepts.c:326)
+ at 0x4C25D01: pthread_mutex_init (hg_intercepts.c:326)
by 0x40071F: nearly_main (tc09_bad_unlock.c:23)
by 0x40079B: main (tc09_bad_unlock.c:50)
]]></programlisting>
-<para>Thrcheck has a way of summarising thread identities, as
+<para>Helgrind has a way of summarising thread identities, as
evidenced here by the text "<computeroutput>Thread
#1</computeroutput>". This is so that it can speak about threads and
sets of threads without overwhelming you with details. See
-<link linkend="tc-manual.data-races.errmsgs">below</link>
+<link linkend="hg-manual.data-races.errmsgs">below</link>
for more information on interpreting error messages.</para>
</sect1>
@@ -141,14 +141,14 @@
-<sect1 id="tc-manual.lock-orders" xreflabel="Lock Orders">
+<sect1 id="hg-manual.lock-orders" xreflabel="Lock Orders">
<title>Detected errors: Inconsistent Lock Orderings</title>
<para>In this section, and in general, to "acquire" a lock simply
means to lock that lock, and to "release" a lock means to unlock
it.</para>
-<para>Thrcheck monitors the order in which threads acquire locks.
+<para>Helgrind monitors the order in which threads acquire locks.
This allows it to detect potential deadlocks which could arise from
the formation of cycles of locks. Detecting such inconsistencies is
useful because, whilst actual deadlocks are fairly obvious, potential
@@ -176,43 +176,43 @@
</listitem>
</itemizedlist>
-<para>Thrcheck builds a directed graph indicating the order in which
+<para>Helgrind builds a directed graph indicating the order in which
locks have been acquired in the past. When a thread acquires a new
lock, the graph is updated, and then checked to see if it now contains
a cycle. The presence of a cycle indicates a potential deadlock involving
the locks in the cycle.</para>
<para>In simple situations, where the cycle only contains two locks,
-Thrcheck will show where the required order was established:</para>
+Helgrind will show where the required order was established:</para>
<programlisting><![CDATA[
Thread #1: lock order "0x7FEFFFAB0 before 0x7FEFFFA80" violated
- at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388)
by 0x40081F: main (tc13_laog1.c:24)
Required order was established by acquisition of lock at 0x7FEFFFAB0
- at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388)
by 0x400748: main (tc13_laog1.c:17)
followed by a later acquisition of lock at 0x7FEFFFA80
- at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388)
by 0x400773: main (tc13_laog1.c:18)
]]></programlisting>
<para>When there are more than two locks in the cycle, the error is
-equally serious. However, at present Thrcheck does not show the locks
+equally serious. However, at present Helgrind does not show the locks
involved, so as to avoid flooding you with information. That could be
fixed in future. For example, here is a an example involving a cycle
of five locks from a naive implementation the famous Dining
Philosophers problem
-(see <computeroutput>thrcheck/tests/tc14_laog_dinphils.c</computeroutput>).
-In this case Thrcheck has detected that all 5 philosophers could
+(see <computeroutput>helgrind/tests/tc14_laog_dinphils.c</computeroutput>).
+In this case Helgrind has detected that all 5 philosophers could
simultaneously pick up their left fork and then deadlock whilst
waiting to pick up their right forks.</para>
<programlisting><![CDATA[
Thread #6: lock order "0x6010C0 before 0x601160" violated
- at 0x4C23C91: pthread_mutex_lock (tc_intercepts.c:388)
+ at 0x4C23C91: pthread_mutex_lock (hg_intercepts.c:388)
by 0x4007C0: dine (tc14_laog_dinphils.c:19)
- by 0x4C25DF7: mythread_wrapper (tc_intercepts.c:178)
+ by 0x4C25DF7: mythread_wrapper (hg_intercepts.c:178)
by 0x4E2F09D: start_thread (in /lib64/libpthread-2.5.so)
by 0x51054CC: clone (in /lib64/libc-2.5.so)
]]></programlisting>
@@ -222,7 +222,7 @@
-<sect1 id="tc-manual.data-races" xreflabel="Data Races">
+<sect1 id="hg-manual.data-races" xreflabel="Data Races">
<title>Detected errors: Data Races</title>
<para>A data race happens, or could happen, when two threads
@@ -232,12 +232,12 @@
one of the central difficulties of threaded programming.</para>
<para>Reliably detecting races is a difficult problem, and most
-of Thrcheck's internals are devoted to do dealing with it.
+of Helgrind's internals are devoted to do dealing with it.
As a consequence this section is somewhat long and involved.
We begin with a simple example.</para>
-<sect2 id="tc-manual.data-races.example" xreflabel="Simple Race">
+<sect2 id="hg-manual.data-races.example" xreflabel="Simple Race">
<title>A Simple Data Race</title>
<para>About the simplest possible example of a race is as follows. In
@@ -269,7 +269,7 @@
by both threads. A correct program would
protect <computeroutput>var</computeroutput> with a lock of type
<computeroutput>pthread_mutex_t</computeroutput>, which is acquired
-before each access and released afterwards. Thrcheck's output for
+before each access and released afterwards. Helgrind's output for
this program is:</para>
<programlisting><![CDATA[
@@ -279,7 +279,7 @@
at 0x510548E: clone (in /lib64/libc-2.5.so)
by 0x4E2F305: do_clone (in /lib64/libpthread-2.5.so)
by 0x4E2F7C5: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.5.so)
- by 0x4C23870: pthread_create@* (tc_intercepts.c:198)
+ by 0x4C23870: pthread_create@* (hg_intercepts.c:198)
by 0x4005F1: main (simple_race.c:12)
Possible data race during write of size 4 at 0x601034
@@ -309,34 +309,34 @@
sections below explain them. Here we merely note their presence:</para>
<itemizedlist>
- <listitem><para>Thrcheck maintains some kind of state machine for the
+ <listitem><para>Helgrind maintains some kind of state machine for the
memory location in question, hence the "<computeroutput>Old
state:</computeroutput>" and "<computeroutput>New
state:</computeroutput>" lines.</para>
</listitem>
- <listitem><para>Thrcheck keeps track of which threads have accessed
+ <listitem><para>Helgrind keeps track of which threads have accessed
the location: "<computeroutput>threads #1, #2</computeroutput>".
Before printing the main error message, it prints the creation
points of these two threads, so you can see which threads it is
referring to.</para>
</listitem>
- <listitem><para>Thrcheck tries to provide an explaination of why the
+ <listitem><para>Helgrind tries to provide an explaination of why the
race exists: "<computeroutput>Location 0x601034 has never been
protected by any lock</computeroutput>".</para>
</listitem>
</itemizedlist>
<para>Understanding the memory state machine is central to
-understanding Thrcheck's race-detection algorithm. The next three
+understanding Helgrind's race-detection algorithm. The next three
subsections explain this.</para>
</sect2>
-<sect2 id="tc-manual.data-races.memstates" xreflabel="Memory States">
-<title>Thrcheck's Memory State Machine</title>
+<sect2 id="hg-manual.data-races.memstates" xreflabel="Memory States">
+<title>Helgrind's Memory State Machine</title>
-<para>Thrcheck tracks the state of every byte of memory used by your
+<para>Helgrind tracks the state of every byte of memory used by your
program. There are a number of states, but only three are
interesting:</para>
@@ -355,7 +355,7 @@
<listitem><para>Shared-Modified: memory in this state is regarded as
shared by multiple threads, at least one of which has written to it.
All participating threads must hold at least one lock in common when
- accessing the memory. If no such lock exists, Thrcheck reports a
+ accessing the memory. If no such lock exists, Helgrind reports a
race error.</para>
</listitem>
</itemizedlist>
@@ -375,14 +375,14 @@
<para>This same thread adds one to the value it has and stores it back
in <computeroutput>var</computeroutput>. This causes another state
-change, this time to the shared-modified state. Because Thrcheck has
+change, this time to the shared-modified state. Because Helgrind has
also been tracking which threads hold which locks, it can see that
<computeroutput>var</computeroutput> is in shared-modified state but
no lock has been used to consistently protect it. Hence a race is
reported exactly at the transition from shared-readonly to
shared-modified.</para>
-<para>The essence of the algorithm is this. Thrcheck keeps track of
+<para>The essence of the algorithm is this. Helgrind keeps track of
each memory location that has been accessed by more than one thread.
For each such location it incrementally infers the set of locks which
have consistently been used to protect that location. If the
@@ -396,11 +396,11 @@
15(4):391-411, November 1997).</para>
<para>Lockset inference has since been widely implemented, studied and
-extended. Thrcheck incorporates several refinements aimed at avoiding
+extended. Helgrind incorporates several refinements aimed at avoiding
the high false error rate that naive versions of the algorithm suffer
from. A
-<link linkend="tc-manual.data-races.summary">summary of the complete
-algorithm used by Thrcheck</link> is presented below. First, however,
+<link linkend="hg-manual.data-races.summary">summary of the complete
+algorithm used by Helgrind</link> is presented below. First, however,
it is important to understand details of transitions pertaining to the
Exclusive-ownership state.</para>
@@ -408,7 +408,7 @@
-<sect2 id="tc-manual.data-races.exclusive" xreflabel="Excl Transfers">
+<sect2 id="hg-manual.data-races.exclusive" xreflabel="Excl Transfers">
<title>Transfers of Exclusive Ownership Between Threads</title>
<para>As presented, the algorithm is far too strict. It reports many
@@ -460,7 +460,7 @@
before the parent reads the results
from <computeroutput>buf</computeroutput>.</para>
-<para>To model this, Thrcheck allows the child to steal, from the
+<para>To model this, Helgrind allows the child to steal, from the
parent, exclusive ownership of any memory exclusively owned by the
parent before the pthread_create call. Similarly, once the parent's
pthread_join call returns, it can steal back ownership of memory
@@ -479,8 +479,8 @@
segments" in "Runtime Checking of Multithreaded Applications with
Visual Threads" (Jerry J. Harrow, Jr, Proceedings of the 7th
International SPIN Workshop on Model Checking of Software Stanford,
-California, USA, August 2000, LNCS 1885, pp331--342). Thrcheck
-implements an extended version of it. Specifically, Thrcheck allows
+California, USA, August 2000, LNCS 1885, pp331--342). Helgrind
+implements an extended version of it. Specifically, Helgrind allows
transfer of exclusive ownership in the following situations:</para>
<itemizedlist>
@@ -511,7 +511,7 @@
-<sect2 id="tc-manual.data-races.re-excl" xreflabel="Re-Excl Transfers">
+<sect2 id="hg-manual.data-races.re-excl" xreflabel="Re-Excl Transfers">
<title>Restoration of Exclusive Ownership</title>
<para>Another common idiom is to partition the lifetime of the program
@@ -543,7 +543,7 @@
]]></programlisting>
<para>This program is correct, but using only the mechanisms described
-so far, Thrcheck would report an error at
+so far, Helgrind would report an error at
<computeroutput>var += 4</computeroutput>. This is because, by that
point, <computeroutput>var</computeroutput> is marked as being in the
state "shared-modified and protected by the
@@ -552,10 +552,10 @@
for <computeroutput>var</computeroutput> to return to the parent
thread's exclusive ownership after the child thread has exited.</para>
-<para>To make this possible, for every memory location Thrcheck also keeps
+<para>To make this possible, for every memory location Helgrind also keeps
track of all the threads that have accessed that location
-- its threadset. When a thread Tquitter joins back to Tstayer,
-Thrcheck examines the locksets of all memory in shared-modified or
+Helgrind examines the locksets of all memory in shared-modified or
shared-readable state. In each such lockset, if Tquitter is
mentioned, it is removed and replaced by Tstayer. If, as a result, a
lockset becomes a singleton set containing Tstayer, then the
@@ -568,7 +568,7 @@
<para>More generally, when a group of threads merges back to a single
thread via a cascade of pthread_join calls, any memory shared by the
group (or a subset of it) ends up being owned exclusively by the sole
-surviving thread. This significantly enhances Thrcheck's flexibility,
+surviving thread. This significantly enhances Helgrind's flexibility,
since it means that each memory location may make arbitrarily many
transitions between exclusive and shared ownership. Furthermore, a
different lock may protect the location during each period of shared
@@ -578,22 +578,22 @@
-<sect2 id="tc-manual.data-races.summary" xreflabel="Race Det Summary">
+<sect2 id="hg-manual.data-races.summary" xreflabel="Race Det Summary">
<title>A Summary of the Race Detection Algorithm</title>
-<para>Thrcheck looks for memory locations which are accessed by more
-than one thread. For each such location, Thrcheck records which of
+<para>Helgrind looks for memory locations which are accessed by more
+than one thread. For each such location, Helgrind records which of
the program's locks were held by the accessing thread at the time of
each access. The hope is to discover that there is indeed at least
one lock which is consistently used by all threads to protect that
location. If no such lock can be found, then there is apparently no
consistent locking strategy being applied for that location, and so a
-possible data race might result. Thrcheck accordingly reports an
+possible data race might result. Helgrind accordingly reports an
error.</para>
<para>In practice this discipline is far too simplistic, and is
unusable since it reports many races in some widely used and
-known-correct programming disciplines. Thrcheck's checking therefore
+known-correct programming disciplines. Helgrind's checking therefore
incorporates many refinements to this basic idea, and can be
summarised as follows:</para>
@@ -630,7 +630,7 @@
<para>All memory accesses are intercepted and monitored.</para>
-<para>By observing the above events, Thrcheck can infer certain
+<para>By observing the above events, Helgrind can infer certain
aspects of the program's locking discipline. Programs which adhere to
the following rules are considered to be acceptable:
</para>
@@ -677,7 +677,7 @@
on that same semaphore</para></listitem>
</itemizedlist>
<para>
- This refinement allows Thrcheck to correctly track the ownership
+ This refinement allows Helgrind to correctly track the ownership
state of inter-thread buffers used in the worker-thread and
worker-thread-pool concurrent programming idioms (styles).</para>
</listitem>
@@ -704,23 +704,23 @@
the algorithm is precise even for 16- and 8-bit memory
accesses.</para>
-<para>Thrcheck correctly handles reader-writer locks in this
+<para>Helgrind correctly handles reader-writer locks in this
framework. Locations shared between multiple threads can be protected
during reads by locks held in either read-mode or write-mode, but can
only be protected during writes by locks held in write-mode. Normal
POSIX mutexes are treated as if they are reader-writer locks which are
only ever held in write-mode.</para>
-<para>Thrcheck correctly handles POSIX mutexes for which recursive
+<para>Helgrind correctly handles POSIX mutexes for which recursive
locking is allowed.</para>
-<para>Thrcheck partially correctly handles x86 and amd64 memory access
+<para>Helgrind partially correctly handles x86 and amd64 memory access
instructions preceded by a LOCK prefix. Writes are correctly handled,
by pretending that the LOCK prefix implies acquisition and release of
a magic "bus hardware lock" mutex before and after the instruction.
This unfortunately requires subsequent reads from such locations to
also use a LOCK prefix, which is not required by the real hardware.
-Thrcheck does not offer any equivalent handling for atomic sequences
+Helgrind does not offer any equivalent handling for atomic sequences
on PowerPC/POWER platforms created by the use of lwarx/stwcx
instructions.</para>
@@ -728,10 +728,10 @@
-<sect2 id="tc-manual.data-races.errmsgs" xreflabel="Race Error Messages">
+<sect2 id="hg-manual.data-races.errmsgs" xreflabel="Race Error Messages">
<title>Interpreting Race Error Messages</title>
-<para>Thrcheck's race detection algorithm collects a lot of
+<para>Helgrind's race detection algorithm collects a lot of
information, and tries to present it in a helpful way when a race is
detected. Here's an example:</para>
@@ -740,7 +740,7 @@
at 0x510548E: clone (in /lib64/libc-2.5.so)
by 0x4E2F305: do_clone (in /lib64/libpthread-2.5.so)
by 0x4E2F7C5: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.5.so)
- by 0x4C23870: pthread_create@* (tc_intercepts.c:198)
+ by 0x4C23870: pthread_create@* (hg_intercepts.c:198)
by 0x400CEF: main (tc17_sembar.c:195)
// And the same for threads #3, #4 and #5 -- omitted for conciseness
@@ -748,23 +748,23 @@
Possible data race during read of size 4 at 0x602174
at 0x400BE5: gomp_barrier_wait (tc17_sembar.c:122)
by 0x400C44: child (tc17_sembar.c:161)
- by 0x4C25DF7: mythread_wrapper (tc_intercepts.c:178)
+ by 0x4C25DF7: mythread_wrapper (hg_intercepts.c:178)
by 0x4E2F09D: start_thread (in /lib64/libpthread-2.5.so)
by 0x51054CC: clone (in /lib64/libc-2.5.so)
Old state: shared-modified by threads #2, #3, #4, #5
New state: shared-modified by threads #2, #3, #4, #5
Reason: this thread, #2, holds no consistent locks
Last consistently used lock for 0x602174 was first observed
- at 0x4C25D01: pthread_mutex_init (tc_intercepts.c:326)
+ at 0x4C25D01: pthread_mutex_init (hg_intercepts.c:326)
by 0x4009E4: gomp_barrier_init (tc17_sembar.c:46)
by 0x400CBC: main (tc17_sembar.c:192)
]]></programlisting>
-<para>Thrcheck first announces the creation points of any threads
+<para>Helgrind first announces the creation points of any threads
referenced in the error message. This is so it can speak concisely
about threads and sets of threads without repeatedly printing their
creation point call stacks. Each thread is only ever announced once,
-the first time it appears in any Thrcheck error message.</para>
+the first time it appears in any Helgrind error message.</para>
<para>The main error message begins at the text
"<computeroutput>Possible data race during read</computeroutput>".
@@ -779,7 +779,7 @@
locks in common with those held during all previous accesses to the
location -- "no consistent locks", in other words.</para>
-<para>Finally, Thrcheck shows the lock which has protected this
+<para>Finally, Helgrind shows the lock which has protected this
location in all previous accesses. (If there is more than one, only
one is shown). This can be a useful hint, because it typically shows
the lock that the programmers intended to use to protect the location,
@@ -814,7 +814,7 @@
<para>The location is shared by 3 threads, all of which have been
reading and writing it while (as required) holding at least one lock
in common. Now it is being read without that lock being held. In the
-"Last consistently used lock" part, Thrcheck offers its best guess as
+"Last consistently used lock" part, Helgrind offers its best guess as
to the identity of the lock that should have been used.</para>
<programlisting><![CDATA[
@@ -837,10 +837,10 @@
to make it available to other threads, one of which is thread #5 --
and thread #5 has forgotten to use the lock.</para>
-<para>Also, this message implies that Thrcheck did not see any
+<para>Also, this message implies that Helgrind did not see any
synchronisation event between threads #4 and #5 that would have
allowed #5 to acquire exclusive ownership from #4. See
-<link linkend="tc-manual.data-races.exclusive">above</link>
+<link linkend="hg-manual.data-races.exclusive">above</link>
for a discussion of transfers of exclusive ownership states between
threads.</para>
@@ -849,20 +849,20 @@
</sect1>
-<sect1 id="tc-manual.effective-use" xreflabel="Thrcheck Effective Use">
-<title>Hints and Tips for Effective Use of Thrcheck</title>
+<sect1 id="hg-manual.effective-use" xreflabel="Helgrind Effective Use">
+<title>Hints and Tips for Effective Use of Helgrind</title>
-<para>Thrcheck can be very helpful in finding and resolving
+<para>Helgrind can be very helpful in finding and resolving
threading-related problems. Like all sophisticated tools, it is most
effective when you understand how to play to its strengths.</para>
-<para>Thrcheck will be less effective when you merely throw an
+<para>Helgrind will be less effective when you merely throw an
existing threaded program at it and try to make sense of any reported
errors. It will be more effective if you design threaded programs
-from the start in a way that helps Thrcheck verify correctness. The
+from the start in a way that helps Helgrind verify correctness. The
same is true for finding memory errors with Memcheck, but applies more
here, because thread checking is a harder problem. Consequently it is
-much easier to write a correct program for which Thrcheck falsely
+much easier to write a correct program for which Helgrind falsely
reports (threading) errors than it is to write a correct program for
which Memcheck falsely reports (memory) errors.</para>
@@ -876,23 +876,23 @@
<listitem>
<para>Make sure your application, and all the libraries it uses,
- use the POSIX threading primitives. Thrcheck needs to be able to
+ use the POSIX threading primitives. Helgrind needs to be able to
see all events pertaining to thread creation, exit, locking and
other syncronisation events. To do so it intercepts many POSIX
pthread_ functions.</para>
<para>Do not roll your own threading primitives (mutexes, etc)
from combinations of the Linux futex syscall, counters and wotnot.
- These throw Thrcheck's internal what's-going-on models way off
+ These throw Helgrind's internal what's-going-on models way off
course and will give bogus results.</para>
<para>Also, do not reimplement existing POSIX abstractions using
other POSIX abstractions. For example, don't build your own
semaphore routines or reader-writer locks from POSIX mutexes and
condition variables. Instead use POSIX reader-writer locks and
- semaphores directly, since Thrcheck supports them directly.</para>
+ semaphores directly, since Helgrind supports them directly.</para>
- <para>Thrcheck directly supports the following POSIX threading
+ <para>Helgrind directly supports the following POSIX threading
abstractions: mutexes, reader-writer locks, condition variables
(but see below), and semaphores. Currently spinlocks and barriers
are not supported, although they could be in future. A prototype
@@ -904,7 +904,7 @@
<itemizedlist>
<listitem><para>Qt version 4.X. Qt 3.X is fine, but not 4.X.
- Thrcheck contains partial direct support for Qt 4.X threading,
+ Helgrind contains partial direct support for Qt 4.X threading,
but this is not yet in a usable state. Assistance from folks
knowledgeable in Qt 4 threading internals would be
appreciated.</para></listitem>
@@ -912,28 +912,28 @@
<listitem><para>Runtime support library for GNU OpenMP (part of
GCC), at least GCC versions 4.2 and 4.3. With some minor effort
of modifying the GNU OpenMP runtime support sources, it is
- possible to use Thrcheck on GNU OpenMP compiled codes. Please
+ possible to use Helgrind on GNU OpenMP compiled codes. Please
contact the Valgrind authors for details.</para></listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Avoid memory recycling. If you can't avoid it, you must use
- tell Thrcheck what is going on via the VALGRIND_HG_CLEAN_MEMORY
+ tell Helgrind what is going on via the VALGRIND_HG_CLEAN_MEMORY
client request
- (in <computeroutput>thrcheck.h</computeroutput>).</para>
+ (in <computeroutput>helgrind.h</computeroutput>).</para>
- <para>Thrcheck is aware of standard memory allocation and
+ <para>Helgrind is aware of standard memory allocation and
deallocation that occurs via malloc/free/new/delete and from entry
and exit of stack frames. In particular, when memory is
- deallocated via free, delete, or function exit, Thrcheck considers
+ deallocated via free, delete, or function exit, Helgrind considers
that memory clean, so when it is eventually reallocated, its
history is irrelevant.</para>
<para>However, it is common practice to implement memory recycling
schemes. In these, memory to be freed is not handed to
malloc/delete, but instead put into a pool of free buffers to be
- handed out again as required. The problem is that Thrcheck has no
+ handed out again as required. The problem is that Helgrind has no
way to know that such memory is logically no longer in use, and
its history is irrelevant. Hence you must make that explicit,
using the VALGRIND_HG_CLEAN_MEMORY client request to specify the
@@ -948,8 +948,8 @@
signalling. Semaphores with an initial value of zero are
particularly useful for this.</para>
- <para>Thrcheck only partially correctly handles POSIX condition
- variables. This is because Thrcheck can see inter-thread
+ <para>Helgrind only partially correctly handles POSIX condition
+ variables. This is because Helgrind can see inter-thread
dependencies between a pthread_cond_wait call and a
pthread_cond_signal/broadcast call only if the waiting thread
actually gets to the rendezvous first (so that it actually calls
@@ -957,9 +957,9 @@
if the signaller arrives first. In the latter case, POSIX
guidelines imply that the associated boolean condition still
provides an inter-thread synchronisation event, but one which is
- invisible to Thrcheck.</para>
+ invisible to Helgrind.</para>
- <para>The result of Thrcheck missing some inter-thread
+ <para>The result of Helgrind missing some inter-thread
synchronisation events is to cause it to report false positives.
That's because missing such events reduces the extent to which it
can transfer exclusive memory ownership between threads. So
@@ -989,7 +989,7 @@
<para>Assume <computeroutput>b</computeroutput> is False most of
the time. If the waiter arrives at the rendezvous first, it
enters its while-loop, waits for the signaller to signal, and
- eventually proceeds. Thrcheck sees the signal, notes the
+ eventually proceeds. Helgrind sees the signal, notes the
dependency, and all is well.</para>
<para>If the signaller arrives
@@ -1000,9 +1000,9 @@
until the signaller sets <computeroutput>b</computeroutput> to
True. Hence there is still the same inter-thread dependency, but
this time it is through an arbitrary in-memory condition, and
- Thrcheck cannot see it.</para>
+ Helgrind cannot see it.</para>
- <para>By comparison, Thrcheck's detection of inter-thread
+ <para>By comparison, Helgrind's detection of inter-thread
dependencies caused by semaphore operations is believed to be
exactly correct.</para>
@@ -1013,14 +1013,14 @@
<listitem>
<para>Make sure you are using a supported Linux distribution. At
- present, Thrcheck only properly supports x86-linux and amd64-linux
+ present, Helgrind only properly supports x86-linux and amd64-linux
with glibc-2.3 or later. The latter restriction means we only
support glibc's NPTL threading implementation. The old
LinuxThreads implementation is not supported.</para>
<para>Unsupported targets may work to varying degrees. In
particular ppc32-linux and ppc64-linux running NTPL should work,
- but you will get false race errors because Thrcheck does not know
+ but you will get false race errors because Helgrind does not know
how to properly handle atomic instruction sequences created using
the lwarx/stwcx instructions.</para>
</listitem>
@@ -1031,14 +1031,14 @@
don't call pthread_detach on existing threads.</para>
<para>Using pthread_join to round up finished threads provides a
- clear synchronisation point that both Thrcheck and programmers can
- see. This synchronisation point allows Thrcheck to adjust its
+ clear synchronisation point that both Helgrind and programmers can
+ see. This synchronisation point allows Helgrind to adjust its
memory ownership
- models <link linkend="tc-manual.data-races.exclusive">as described
- extensively above</link>, which helps Thrcheck produce more
+ models <link linkend="hg-manual.data-races.exclusive">as described
+ extensively above</link>, which helps Helgrind produce more
accurate error reports.</para>
- <para>If you don't call pthread_join on a thread, Thrcheck has no
+ <para>If you don't call pthread_join on a thread, Helgrind has no
way to know when it finishes, relative to any significant
synchronisation points for other threads in the program. So it
assumes that the thread lingers indefinitely and can potentially
@@ -1049,25 +1049,25 @@
</listitem>
<listitem>
- <para>Perform thread debugging (with Thrcheck) and memory
+ <para>Perform thread debugging (with Helgrind) and memory
debugging (with Memcheck) together.</para>
- <para>Thrcheck tracks the state of memory in detail, and memory
+ <para>Helgrind tracks the state of memory in detail, and memory
management bugs in the application are liable to cause confusion.
In extreme cases, applications which do many invalid reads and
writes (particularly to freed memory) have been known to crash
- Thrcheck. So, ideally, you should make your application
- Memcheck-clean before using Thrcheck.</para>
+ Helgrind. So, ideally, you should make your application
+ Memcheck-clean before using Helgrind.</para>
<para>It may be impossible to make your application Memcheck-clean
unless you first remove threading bugs. In particular, it may be
difficult to remove all reads and writes to freed memory in
multithreaded C++ destructor sequences at program termination.
- So, ideally, you should make your application Thrcheck-clean
+ So, ideally, you should make your application Helgrind-clean
before using Memcheck.</para>
<para>Since this circularity is obviously unresolvable, at least
- bear in mind that Memcheck and Thrcheck are to some extent
+ bear in mind that Memcheck and Helgrind are to some extent
complementary, and you may need to use them together.</para>
</listitem>
@@ -1075,17 +1075,17 @@
<para>POSIX requires that implementations of standard I/O (printf,
fprintf, fwrite, fread, etc) are thread safe. Unfortunately GNU
libc implements this by using internal locking primitives that
- Thrcheck is unable to intercept. Consequently Thrcheck generates
+ Helgrind is unable to intercept. Consequently Helgrind generates
many false race reports when you use these functions.</para>
- <para>Thrcheck attempts to hide these errors using the standard
+ <para>Helgrind attempts to hide these errors using the standard
Valgrind error-suppression mechanism. So, at least for simple
test cases, you don't see any. Nevertheless, some may slip
through. Just something to be aware of.</para>
</listitem>
<listitem>
- <para>Thrcheck's error checks do not work properly inside the
+ <para>Helgrind's error checks do not work properly inside the
system threading library itself
(<computeroutput>libpthread.so</computeroutput>), and it usually
observes large numbers of (false) errors in there. Valgrind's
@@ -1106,13 +1106,13 @@
-<sect1 id="tc-manual.options" xreflabel="Thrcheck Options">
-<title>Thrcheck Options</title>
+<sect1 id="hg-manual.options" xreflabel="Helgrind Options">
+<title>Helgrind Options</title>
<para>The following end-user options are available:</para>
<!-- start of xi:include in the manpage -->
-<variablelist id="tc.opts.list">
+<variablelist id="hg.opts.list">
<varlistentry id="opt.happens-before" xreflabel="--happens-before">
<term>
@@ -1120,13 +1120,13 @@
[default: all] ]]></option>
</term>
<listitem>
- <para>Thrcheck always regards locks as the basis for
+ <para>Helgrind always regards locks as the basis for
inter-thread synchronisation. However, by default, before
- reporting a race error, Thrcheck will also check whether
+ reporting a race error, Helgrind will also check whether
certain other kinds of inter-thread synchronisation events
happened. It may be that if such events took place, then no
race really occurred, and so no error needs to be reported.
- See <link linkend="tc-manual.data-races.exclusive">above</link>
+ See <link linkend="hg-manual.data-races.exclusive">above</link>
for a discussion of transfers of exclusive ownership states
between threads.
</para>
@@ -1146,7 +1146,7 @@
<para>Changing this setting from the default will increase your
false-error rate but give little or no gain. The only advantage
is that <option>--happens-before=threads</option> and
- <option>--happens-before=none</option> should make Thrcheck
+ <option>--happens-before=none</option> should make Helgrind
less and less sensitive to the scheduling of threads, and hence
the output more and more repeatable across runs.
</para>
@@ -1161,7 +1161,7 @@
]]></option>
</term>
<listitem>
- <para>Requests that Thrcheck produces a log of all state changes
+ <para>Requests that Helgrind produces a log of all state changes
to location 0xXXYYZZ. This can be helpful in tracking down
tricky races. <varname>--trace-level</varname> controls the
verbosity of the log. At the default setting (1), a one-line
@@ -1175,9 +1175,9 @@
<!-- start of xi:include in the manpage -->
<para>In addition, the following debugging options are available for
-Thrcheck:</para>
+Helgrind:</para>
-<variablelist id="tc.debugopts.list">
+<variablelist id="hg.debugopts.list">
<varlistentry id="opt.trace-malloc" xreflabel="--trace-malloc">
<term>
@@ -1196,9 +1196,9 @@
</term>
<listitem>
<para>At exit, write to stderr a dump of the happens-before
- graph computed by Thrcheck, in a format suitable for the VCG
+ graph computed by Helgrind, in a format suitable for the VCG
graph visualisation tool. A suitable command line is:</para>
- <para><computeroutput>valgrind --tool=thrcheck
+ <para><computeroutput>valgrind --tool=helgrind
--gen-vcg=yes my_app 2>&1
| grep xxxxxx | sed "s/xxxxxx//g"
| xvcg -</computeroutput></para>
@@ -1233,7 +1233,7 @@
]]></option>
</term>
<listitem>
- <para>Run extensive sanity checks on Thrcheck's internal
+ <para>Run extensive sanity checks on Helgrind's internal
data structures at events defined by the bitstring, as
follows:</para>
<para><computeroutput>10000 </computeroutput>after changes to
@@ -1246,7 +1246,7 @@
lock or unlock event</para>
<para><computeroutput>00001 </computeroutput>after every client
thread creation or joinage event</para>
- <para>Note these will make Thrcheck run very slowly, often to
+ <para>Note these will make Helgrind run very slowly, often to
the point of being completely unusable.</para>
</listitem>
</varlistentry>
@@ -1257,8 +1257,8 @@
</sect1>
-<sect1 id="tc-manual.todolist" xreflabel="To Do List">
-<title>A To-Do List for Thrcheck</title>
+<sect1 id="hg-manual.todolist" xreflabel="To Do List">
+<title>A To-Do List for Helgrind</title>
<para>The following is a list of loose ends which should be tidied up
some time.</para>
|
|
From: <sv...@va...> - 2007-11-09 23:59:14
|
Author: sewardj
Date: 2007-11-09 23:59:14 +0000 (Fri, 09 Nov 2007)
New Revision: 7129
Log:
Stop xsltproc barfing on un-escaped '&'.
Modified:
trunk/massif/docs/ms-manual.xml
Modified: trunk/massif/docs/ms-manual.xml
===================================================================
--- trunk/massif/docs/ms-manual.xml 2007-11-09 23:30:51 UTC (rev 7128)
+++ trunk/massif/docs/ms-manual.xml 2007-11-09 23:59:14 UTC (rev 7129)
@@ -10,7 +10,7 @@
Docs:
- Mention that complex functions names are best protected with single
quotes, eg:
- --alloc-fn='operator new(unsigned, std::nothrow_t const&)'
+ --alloc-fn='operator new(unsigned, std::nothrow_t const&)'
[XXX: that doesn't work if the option is in a .valgrindrc file or in
$VALGRIND_OPTS. In m_commandline.c:add_args_from_string() need to
respect single quotes...]
|
|
From: Julian S. <js...@ac...> - 2007-11-09 23:36:52
|
> > Added: > > trunk/old-helgrind/ > > Removed: > > trunk/helgrind/ > > Will you delete this eventually? Yes, providing that's OK with you & Jeremy. Or can leave it around for reference purposes. J |
|
From: Julian S. <js...@ac...> - 2007-11-09 23:34:43
|
> > track_pre_thread_ll_exit, which is notified just before the new thread > > exits, that is, after it has made its last memory reference. > > What's the "ll_" mean -- low-level? Could it be removed? Yes, low-level. These events mark the extreme boundaries of a thread's lifespan, from the kernel's point of view: ll_create is before it has executed its first instruction and ll_exit after it has executed it's last. Reason I'd like to keep the ll_ part is that it makes it clear these events are not to do with pthread_create or pthread_exit/pthread_join, which are a higher level abstraction synthesised by libpthread. J |
|
From: <sv...@va...> - 2007-11-09 23:30:48
|
Author: sewardj
Date: 2007-11-09 23:30:51 +0000 (Fri, 09 Nov 2007)
New Revision: 7128
Log:
Merge (from branches/THRCHECK) misc build-system changes. Nothing
significant.
Modified:
trunk/Makefile.am
trunk/configure.in
trunk/docs/xml/manual.xml
trunk/none/tests/amd64/Makefile.am
Modified: trunk/Makefile.am
===================================================================
--- trunk/Makefile.am 2007-11-09 23:29:46 UTC (rev 7127)
+++ trunk/Makefile.am 2007-11-09 23:30:51 UTC (rev 7128)
@@ -9,17 +9,18 @@
massif \
lackey \
none \
+ helgrind \
exp-omega
-# Temporary: we want to compile Helgrind, but not regtest it.
# Put docs last because building the HTML is slow and we want to get
# everything else working before we try it.
-SUBDIRS = include coregrind . tests perf auxprogs $(TOOLS) helgrind docs
+SUBDIRS = include coregrind . tests perf auxprogs $(TOOLS) docs
DIST_SUBDIRS = $(SUBDIRS)
SUPP_FILES = \
glibc-2.2.supp glibc-2.3.supp glibc-2.4.supp glibc-2.5.supp \
- glibc-2.6.supp aix5libc.supp xfree-3.supp xfree-4.supp
+ glibc-2.6.supp aix5libc.supp xfree-3.supp xfree-4.supp \
+ glibc-2.X-helgrind.supp
dist_val_DATA = $(SUPP_FILES) default.supp
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2007-11-09 23:29:46 UTC (rev 7127)
+++ trunk/configure.in 2007-11-09 23:30:51 UTC (rev 7128)
@@ -473,30 +473,30 @@
2.2)
AC_MSG_RESULT(2.2 family)
AC_DEFINE([GLIBC_2_2], 1, [Define to 1 if you're using glibc 2.2.x])
- DEFAULT_SUPP="glibc-2.2.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.2.supp glibc-2.X-helgrind.supp ${DEFAULT_SUPP}"
;;
2.3)
AC_MSG_RESULT(2.3 family)
AC_DEFINE([GLIBC_2_3], 1, [Define to 1 if you're using glibc 2.3.x])
- DEFAULT_SUPP="glibc-2.3.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.3.supp glibc-2.X-helgrind.supp ${DEFAULT_SUPP}"
;;
2.4)
AC_MSG_RESULT(2.4 family)
AC_DEFINE([GLIBC_2_4], 1, [Define to 1 if you're using glibc 2.4.x])
- DEFAULT_SUPP="glibc-2.4.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.4.supp glibc-2.X-helgrind.supp ${DEFAULT_SUPP}"
;;
2.5)
AC_MSG_RESULT(2.5 family)
AC_DEFINE([GLIBC_2_5], 1, [Define to 1 if you're using glibc 2.5.x])
- DEFAULT_SUPP="glibc-2.5.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.5.supp glibc-2.X-helgrind.supp ${DEFAULT_SUPP}"
;;
2.6)
AC_MSG_RESULT(2.6 family)
AC_DEFINE([GLIBC_2_6], 1, [Define to 1 if you're using glibc 2.6.x])
- DEFAULT_SUPP="glibc-2.6.supp ${DEFAULT_SUPP}"
+ DEFAULT_SUPP="glibc-2.6.supp glibc-2.X-helgrind.supp ${DEFAULT_SUPP}"
;;
aix5)
AC_MSG_RESULT(AIX 5.1 or 5.2 or 5.3)
Modified: trunk/docs/xml/manual.xml
===================================================================
--- trunk/docs/xml/manual.xml 2007-11-09 23:29:46 UTC (rev 7127)
+++ trunk/docs/xml/manual.xml 2007-11-09 23:30:51 UTC (rev 7128)
@@ -28,12 +28,10 @@
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="../../callgrind/docs/cl-manual.xml" parse="xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="../../massif/docs/ms-manual.xml" parse="xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-<!--
<xi:include href="../../helgrind/docs/hg-manual.xml" parse="xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
--->
+ <xi:include href="../../massif/docs/ms-manual.xml" parse="xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="../../none/docs/nl-manual.xml" parse="xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="../../lackey/docs/lk-manual.xml" parse="xml"
Modified: trunk/none/tests/amd64/Makefile.am
===================================================================
--- trunk/none/tests/amd64/Makefile.am 2007-11-09 23:29:46 UTC (rev 7127)
+++ trunk/none/tests/amd64/Makefile.am 2007-11-09 23:30:51 UTC (rev 7128)
@@ -36,7 +36,7 @@
smc1.stderr.exp smc1.stdout.exp smc1.vgtest \
shrld.stderr.exp shrld.stdout.exp shrld.vgtest \
slahf-amd64.stderr.exp slahf-amd64.stdout.exp \
- slahf-amd64.stderr.vgtest
+ slahf-amd64.vgtest
check_PROGRAMS = \
|
|
From: <sv...@va...> - 2007-11-09 23:29:43
|
Author: sewardj
Date: 2007-11-09 23:29:46 +0000 (Fri, 09 Nov 2007)
New Revision: 7127
Log:
Merge (from branches/THRCHECK) r7043:
Allow a test to have any number of .stderr.exp* files, so long as at
least one is found. In fact the comments in the code that claimed
that .stderr.exp[0-9] are the only ones allowed were misleading;
.stderr.exp* has always been allowed. The only functional change here
is to mandate that at least one such file exists; prior to the change
the script mandated that at least a .stderr.exp (with no other suffix)
file existed.
Purpose is to allow collections of .stderr.exp files with suffixes
arranged in some meaningful way, eg, foo.stderr.exp-glibc25-amd64.
This might help in making testsuites more maintainable when there
have to be multiple .stderr.exp files. Naming them merely as
.stderr.exp1, .stderr.exp2, etc, makes it impossible to remember
what the differences between the files actually is.
Modified:
trunk/tests/vg_regtest.in
Modified: trunk/tests/vg_regtest.in
===================================================================
--- trunk/tests/vg_regtest.in 2007-11-09 23:26:54 UTC (rev 7126)
+++ trunk/tests/vg_regtest.in 2007-11-09 23:29:46 UTC (rev 7127)
@@ -63,7 +63,8 @@
#
# Expected stdout (filtered) is kept in <test>.stdout.exp[0-9]* (can be more
# than one expected output). It can be missing if it would be empty. Expected
-# stderr (filtered) is kept in <test>.stderr.exp[0-9]*.
+# stderr (filtered) is kept in <test>.stderr.exp*. There must be at least
+# one stderr.exp* file.
#
# The prerequisite command, if present, must return 0 otherwise the test is
# skipped. The post-test command, if present, must return 0 and its stdout
@@ -328,9 +329,9 @@
# Filter stderr
mysystem("$stderr_filter < $name.stderr.out > $tmp");
rename($tmp, "$name.stderr.out");
- # Find all the .stderr.exp files. $name.stderr.exp must exist.
+ # Find all the .stderr.exp files. At least one must exist.
my @stderr_exps = <$name.stderr.exp*>;
- (-r "$name.stderr.exp") or die "Could not read `$name.stderr.exp'\n";
+ (0 != scalar @stderr_exps) or die "Could not find `$name.stderr.exp*'\n";
do_diffs($fullname, $name, "stderr", \@stderr_exps);
# Maybe do post-test check
|
|
From: <sv...@va...> - 2007-11-09 23:26:54
|
Author: sewardj
Date: 2007-11-09 23:26:54 +0000 (Fri, 09 Nov 2007)
New Revision: 7126
Log:
I got a bit confused with glibc-2.6.X suppressions whilst merging from
branches/THRCHECK (sorry Dirk). I'll fix them shortly.
Modified:
trunk/glibc-2.6.supp
Modified: trunk/glibc-2.6.supp
===================================================================
--- trunk/glibc-2.6.supp 2007-11-09 23:25:46 UTC (rev 7125)
+++ trunk/glibc-2.6.supp 2007-11-09 23:26:54 UTC (rev 7126)
@@ -1,7 +1,7 @@
##----------------------------------------------------------------------##
-# Errors to suppress by default with glibc 2.4.x
+# Errors to suppress by default with glibc 2.6.x
# Format of this file is:
# {
@@ -40,23 +40,44 @@
}
{
- dl-hack3
+ dl-hack3-1
Memcheck:Cond
obj:/lib*/ld-2.6*.so*
obj:/lib*/ld-2.6*.so*
obj:/lib*/ld-2.6*.so*
}
-
{
- dl-hack3
+ dl-hack3-2
Memcheck:Cond
- obj:/lib*/ld-2.6*.so
- obj:/lib*/ld-2.6*.so
- obj:/lib*/libc-2.6*.so
- obj:/lib*/libdl-2.6*.so
- obj:/lib*/ld-2.6*.so
+ obj:/lib*/ld-2.6*.so*
+ obj:/lib*/ld-2.6*.so*
+ obj:/lib*/libc-2.6*.so*
}
+{
+ dl-hack4-64bit-1
+ Memcheck:Addr8
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/ld-2.6*.so*
+}
+{
+ dl-hack4-64bit-2
+ Memcheck:Addr8
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/libc-2.6*.so*
+}
+{
+ dl-hack4-64bit-3
+ Memcheck:Addr8
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/ld-2.6*.so*
+ obj:/lib64/libdl-2.6*.so*
+}
+
+
+
##----------------------------------------------------------------------##
{
glibc-2.5.x-on-SUSE-10.2-(PPC)-1
@@ -94,19 +115,11 @@
{
glibc-2.6-on-SUSE-10.3-(x86)
Memcheck:Addr4
- obj:/lib*/ld-2.6*.so*
- obj:/lib*/ld-2.6*.so*
- obj:/lib*/ld-2.6*.so*
+ obj:/lib/ld-2.6*.so
+ obj:/lib/ld-2.6*.so
+ obj:/lib/ld-2.6*.so
}
-{
- glibc-2.6-on-SUSE-10.3-(x86_64)
- Memcheck:Addr8
- obj:/lib*/ld-2.6*.so
- obj:/lib*/ld-2.6*.so
- obj:/lib*/ld-2.6*.so
-}
-
##----------------------------------------------------------------------##
## Various structure padding things on SUSE 10.2
##
|
|
From: <sv...@va...> - 2007-11-09 23:25:55
|
Author: sewardj
Date: 2007-11-09 23:25:46 +0000 (Fri, 09 Nov 2007)
New Revision: 7125
Log:
Allow VG_(atoll16) to accept a leading "0x".
Modified:
trunk/coregrind/m_libcbase.c
trunk/include/pub_tool_libcbase.h
Modified: trunk/coregrind/m_libcbase.c
===================================================================
--- trunk/coregrind/m_libcbase.c 2007-11-09 23:24:09 UTC (rev 7124)
+++ trunk/coregrind/m_libcbase.c 2007-11-09 23:25:46 UTC (rev 7125)
@@ -68,6 +68,9 @@
Bool neg = False;
Long n = 0;
if (*str == '-') { str++; neg = True; };
+ if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')) {
+ str += 2;
+ }
while (True) {
Char c = *str;
if (c >= '0' && c <= (Char)'9') {
Modified: trunk/include/pub_tool_libcbase.h
===================================================================
--- trunk/include/pub_tool_libcbase.h 2007-11-09 23:24:09 UTC (rev 7124)
+++ trunk/include/pub_tool_libcbase.h 2007-11-09 23:25:46 UTC (rev 7125)
@@ -42,10 +42,9 @@
Converting strings to numbers
------------------------------------------------------------------ */
- // Nb: atoll16 doesn't handle a "0x" prefix.
-extern Long VG_(atoll) ( Char* str ); // base 10
-extern Long VG_(atoll16) ( Char* str ); // base 16
-extern Long VG_(atoll36) ( Char* str ); // base 36
+extern Long VG_(atoll) ( Char* str ); // base 10
+extern Long VG_(atoll16) ( Char* str ); // base 16; leading 0x accepted
+extern Long VG_(atoll36) ( Char* str ); // base 36
/* ---------------------------------------------------------------------
String functions and macros
|
|
From: Nicholas N. <nj...@cs...> - 2007-11-09 23:25:32
|
On Fri, 9 Nov 2007 sv...@va... wrote: > r6805: Modify two thread-notification events in the core-tool > interface. This removes track_post_thread_create and > track_post_thread_join. The core can only see low level thread > creation and exiting, and has no idea about pthread-level concepts > like "pthread_create" and "pthread_join", so these are a bit > ambiguous. > > Replace them with track_pre_thread_ll_create, which is notified before > a new thread makes any memory references, and > track_pre_thread_ll_exit, which is notified just before the new thread > exits, that is, after it has made its last memory reference. What's the "ll_" mean -- low-level? Could it be removed? N |
|
From: <sv...@va...> - 2007-11-09 23:24:07
|
Author: sewardj
Date: 2007-11-09 23:24:09 +0000 (Fri, 09 Nov 2007)
New Revision: 7124
Log:
Oops (a second time), this was missed out of r7118 (Merge (from
branches/THRCHECK) the following amd64-linux stack unwind kludges)
Modified:
trunk/coregrind/m_syswrap/syswrap-generic.c
Modified: trunk/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-generic.c 2007-11-09 23:21:44 UTC (rev 7123)
+++ trunk/coregrind/m_syswrap/syswrap-generic.c 2007-11-09 23:24:09 UTC (rev 7124)
@@ -522,7 +522,7 @@
i->fd = fd;
i->pathname = VG_(arena_strdup)(VG_AR_CORE, pathname);
- i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid);
+ i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
}
// Record opening of an fd, and find its name.
|
|
From: <sv...@va...> - 2007-11-09 23:21:44
|
Author: sewardj
Date: 2007-11-09 23:21:44 +0000 (Fri, 09 Nov 2007)
New Revision: 7123
Log:
Merge (from branches/THRCHECK) the following two changes to the core-tool
interface:
r6805: Modify two thread-notification events in the core-tool
interface. This removes track_post_thread_create and
track_post_thread_join. The core can only see low level thread
creation and exiting, and has no idea about pthread-level concepts
like "pthread_create" and "pthread_join", so these are a bit
ambiguous.
Replace them with track_pre_thread_ll_create, which is notified before
a new thread makes any memory references, and
track_pre_thread_ll_exit, which is notified just before the new thread
exits, that is, after it has made its last memory reference.
r6823: Core-tool interface: give 'needs_tool_errors' an extra Boolean
indicating whether or not the core should print thread id's on error
messages.
Modified:
trunk/coregrind/m_errormgr.c
trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
trunk/coregrind/m_syswrap/syswrap-linux.c
trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c
trunk/coregrind/m_syswrap/syswrap-x86-linux.c
trunk/coregrind/m_tooliface.c
trunk/coregrind/pub_core_tooliface.h
trunk/include/pub_tool_tooliface.h
Modified: trunk/coregrind/m_errormgr.c
===================================================================
--- trunk/coregrind/m_errormgr.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_errormgr.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -293,7 +293,8 @@
}
if (!VG_(clo_xml)) {
- if (err->tid > 0 && err->tid != last_tid_printed) {
+ if (VG_(tdict).tool_show_ThreadIDs_for_errors
+ && err->tid > 0 && err->tid != last_tid_printed) {
VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
last_tid_printed = err->tid;
}
@@ -380,7 +381,7 @@
err->count = 1;
err->tid = tid;
if (NULL == where)
- err->where = VG_(record_ExeContext)( tid );
+ err->where = VG_(record_ExeContext)( tid, 0 );
else
err->where = where;
Modified: trunk/coregrind/m_syswrap/syswrap-amd64-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-amd64-linux.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_syswrap/syswrap-amd64-linux.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -267,6 +267,12 @@
ctst->client_stack_szB = 0;
}
+ /* Assume the clone will succeed, and tell any tool that wants to
+ know that this thread has come into existence. If the clone
+ fails, we'll send out a ll_exit notification for it at the out:
+ label below, to clean up. */
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
if (flags & VKI_CLONE_SETTLS) {
if (debug)
VG_(printf)("clone child has SETTLS: tls at %p\n", tlsaddr);
@@ -292,6 +298,8 @@
/* clone failed */
VG_(cleanup_thread)(&ctst->arch);
ctst->status = VgTs_Empty;
+ /* oops. Better tell the tool the thread exited in a hurry :-) */
+ VG_TRACK( pre_thread_ll_exit, ctid );
}
return res;
Modified: trunk/coregrind/m_syswrap/syswrap-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-linux.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_syswrap/syswrap-linux.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -78,8 +78,6 @@
VG_(printf)("thread tid %d started: stack = %p\n",
tid, &tid);
- VG_TRACK ( post_thread_create, tst->os_state.parent, tid );
-
tst->os_state.lwpid = VG_(gettid)();
tst->os_state.threadgroup = VG_(getpid)();
@@ -128,6 +126,9 @@
c = VG_(count_living_threads)();
vg_assert(c >= 1); /* stay sane */
+ // Tell the tool this thread is exiting
+ VG_TRACK( pre_thread_ll_exit, tid );
+
if (c == 1) {
VG_(debugLog)(1, "syswrap-linux",
Modified: trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_syswrap/syswrap-ppc32-linux.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -313,6 +313,12 @@
ctst->client_stack_szB = 0;
}
+ /* Assume the clone will succeed, and tell any tool that wants to
+ know that this thread has come into existence. If the clone
+ fails, we'll send out a ll_exit notification for it at the out:
+ label below, to clean up. */
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
if (flags & VKI_CLONE_SETTLS) {
if (debug)
VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls);
@@ -344,6 +350,8 @@
/* clone failed */
VG_(cleanup_thread)(&ctst->arch);
ctst->status = VgTs_Empty;
+ /* oops. Better tell the tool the thread exited in a hurry :-) */
+ VG_TRACK( pre_thread_ll_exit, ctid );
}
return res;
Modified: trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_syswrap/syswrap-ppc64-linux.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -341,6 +341,12 @@
ctst->client_stack_szB = 0;
}
+ /* Assume the clone will succeed, and tell any tool that wants to
+ know that this thread has come into existence. If the clone
+ fails, we'll send out a ll_exit notification for it at the out:
+ label below, to clean up. */
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
if (flags & VKI_CLONE_SETTLS) {
if (debug)
VG_(printf)("clone child has SETTLS: tls at %p\n", child_tls);
@@ -374,6 +380,8 @@
/* clone failed */
VG_(cleanup_thread)(&ctst->arch);
ctst->status = VgTs_Empty;
+ /* oops. Better tell the tool the thread exited in a hurry :-) */
+ VG_TRACK( pre_thread_ll_exit, ctid );
}
return res;
Modified: trunk/coregrind/m_syswrap/syswrap-x86-linux.c
===================================================================
--- trunk/coregrind/m_syswrap/syswrap-x86-linux.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_syswrap/syswrap-x86-linux.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -279,6 +279,15 @@
ctst->client_stack_szB = 0;
}
+ /* Assume the clone will succeed, and tell any tool that wants to
+ know that this thread has come into existence. We cannot defer
+ it beyond this point because sys_set_thread_area, just below,
+ causes tCheck to assert by making references to the new ThreadId
+ if we don't state the new thread exists prior to that point.
+ If the clone fails, we'll send out a ll_exit notification for it
+ at the out: label below, to clean up. */
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
if (flags & VKI_CLONE_SETTLS) {
if (debug)
VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
@@ -311,6 +320,8 @@
/* clone failed */
VG_(cleanup_thread)(&ctst->arch);
ctst->status = VgTs_Empty;
+ /* oops. Better tell the tool the thread exited in a hurry :-) */
+ VG_TRACK( pre_thread_ll_exit, ctid );
}
return res;
Modified: trunk/coregrind/m_tooliface.c
===================================================================
--- trunk/coregrind/m_tooliface.c 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/m_tooliface.c 2007-11-09 23:21:44 UTC (rev 7123)
@@ -176,6 +176,7 @@
void VG_(needs_tool_errors)(
Bool (*eq) (VgRes, Error*, Error*),
void (*pp) (Error*),
+ Bool show_TIDs,
UInt (*update) (Error*),
Bool (*recog) (Char*, Supp*),
Bool (*read_extra) (Int, Char*, Int, Supp*),
@@ -187,6 +188,7 @@
VG_(needs).tool_errors = True;
VG_(tdict).tool_eq_Error = eq;
VG_(tdict).tool_pp_Error = pp;
+ VG_(tdict).tool_show_ThreadIDs_for_errors = show_TIDs;
VG_(tdict).tool_update_extra = update;
VG_(tdict).tool_recognised_suppression = recog;
VG_(tdict).tool_read_extra_suppression_info = read_extra;
@@ -332,8 +334,8 @@
DEF(track_start_client_code, ThreadId, ULong)
DEF(track_stop_client_code, ThreadId, ULong)
-DEF(track_post_thread_create, ThreadId, ThreadId)
-DEF(track_post_thread_join, ThreadId, ThreadId)
+DEF(track_pre_thread_ll_create, ThreadId, ThreadId)
+DEF(track_pre_thread_ll_exit, ThreadId)
DEF(track_pre_deliver_signal, ThreadId, Int sigNo, Bool)
DEF(track_post_deliver_signal, ThreadId, Int sigNo)
Modified: trunk/coregrind/pub_core_tooliface.h
===================================================================
--- trunk/coregrind/pub_core_tooliface.h 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/coregrind/pub_core_tooliface.h 2007-11-09 23:21:44 UTC (rev 7123)
@@ -118,6 +118,7 @@
// VG_(needs).tool_errors
Bool (*tool_eq_Error) (VgRes, Error*, Error*);
void (*tool_pp_Error) (Error*);
+ Bool tool_show_ThreadIDs_for_errors;
UInt (*tool_update_extra) (Error*);
Bool (*tool_recognised_suppression) (Char*, Supp*);
Bool (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*);
@@ -207,8 +208,8 @@
void (*track_start_client_code)(ThreadId, ULong);
void (*track_stop_client_code) (ThreadId, ULong);
- void (*track_post_thread_create)(ThreadId, ThreadId);
- void (*track_post_thread_join) (ThreadId, ThreadId);
+ void (*track_pre_thread_ll_create)(ThreadId, ThreadId);
+ void (*track_pre_thread_ll_exit) (ThreadId);
void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool);
void (*track_post_deliver_signal)(ThreadId, Int sigNo);
Modified: trunk/include/pub_tool_tooliface.h
===================================================================
--- trunk/include/pub_tool_tooliface.h 2007-11-09 23:16:11 UTC (rev 7122)
+++ trunk/include/pub_tool_tooliface.h 2007-11-09 23:21:44 UTC (rev 7123)
@@ -303,6 +303,9 @@
// Print error context.
void (*pp_Error)(Error* err),
+ // Should the core indicate which ThreadId each error comes from?
+ Bool show_ThreadIDs_for_errors,
+
// Should fill in any details that could be postponed until after the
// decision whether to ignore the error (ie. details not affecting the
// result of VG_(tdict).tool_eq_Error()). This saves time when errors
@@ -544,13 +547,14 @@
/* Scheduler events (not exhaustive) */
/* Called when 'tid' starts or stops running client code blocks.
- Gives the total dispatched block count at that event. Note, this is
- not the same as 'tid' holding the BigLock (the lock that ensures that
- only one thread runs at a time): a thread can hold the lock for other
- purposes (making translations, etc) yet not be running client blocks.
- Obviously though, a thread must hold the lock in order to run client
- code blocks, so the times bracketed by 'thread_run'..'thread_runstate'
- are a subset of the times when thread 'tid' holds the cpu lock.
+ Gives the total dispatched block count at that event. Note, this
+ is not the same as 'tid' holding the BigLock (the lock that ensures
+ that only one thread runs at a time): a thread can hold the lock
+ for other purposes (making translations, etc) yet not be running
+ client blocks. Obviously though, a thread must hold the lock in
+ order to run client code blocks, so the times bracketed by
+ 'start_client_code'..'stop_client_code' are a subset of the times
+ when thread 'tid' holds the cpu lock.
*/
void VG_(track_start_client_code)(
void(*f)(ThreadId tid, ULong blocks_dispatched)
@@ -562,13 +566,18 @@
/* Thread events (not exhaustive)
- Called during thread create, before the new thread has run any
- instructions (or touched any memory).
- */
-void VG_(track_post_thread_create)(void(*f)(ThreadId tid, ThreadId child));
-void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee));
+ ll_create: low level thread creation. Called before the new thread
+ has run any instructions (or touched any memory). In fact, called
+ immediately before the new thread has come into existence; the new
+ thread can be assumed to exist when notified by this call.
+ ll_exit: low level thread exit. Called after the exiting thread
+ has run its last instruction.
+*/
+void VG_(track_pre_thread_ll_create)(void(*f)(ThreadId tid, ThreadId child));
+void VG_(track_pre_thread_ll_exit) (void(*f)(ThreadId tid));
+
/* Signal events (not exhaustive)
... pre_send_signal, post_send_signal ...
|
|
From: <sv...@va...> - 2007-11-09 23:16:09
|
Author: sewardj Date: 2007-11-09 23:16:11 +0000 (Fri, 09 Nov 2007) New Revision: 7122 Log: Oops, this was missed out of r7118 (Merge (from branches/THRCHECK) the following amd64-linux stack unwind kludges) Modified: trunk/include/pub_tool_stacktrace.h Modified: trunk/include/pub_tool_stacktrace.h =================================================================== --- trunk/include/pub_tool_stacktrace.h 2007-11-09 23:13:22 UTC (rev 7121) +++ trunk/include/pub_tool_stacktrace.h 2007-11-09 23:16:11 UTC (rev 7122) @@ -37,8 +37,11 @@ // Walks the stack to get instruction pointers from the top stack frames for // thread 'tid'. Maximum of 'n_ips' addresses put into 'ips'; 0 is the top // of the stack, 1 is its caller, etc. Everything from ips[n_ips] onwards -// is undefined and should not be read. -extern UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips ); +// is undefined and should not be read. The initial IP value to +// use is adjusted by first_ip_delta before the stack is unwound. +// A safe value to pass is zero. +extern UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips, + Word first_ip_delta ); // Apply a function to every element in the StackTrace. The parameter 'n' // gives the index of the passed ip. Doesn't go below main() unless |
|
From: <sv...@va...> - 2007-11-09 23:13:20
|
Author: sewardj
Date: 2007-11-09 23:13:22 +0000 (Fri, 09 Nov 2007)
New Revision: 7121
Log:
Merge (from branches/THRCHECK) r6804:
Split the scheduler initialisation into two phases, for reasons I
can't exactly remember. But I think it was so that the tool can be
told of the initial thread's TID before it is notified of any initial
address range permissions. Or something like that.
Modified:
trunk/coregrind/m_main.c
trunk/coregrind/m_scheduler/scheduler.c
trunk/coregrind/pub_core_scheduler.h
Modified: trunk/coregrind/m_main.c
===================================================================
--- trunk/coregrind/m_main.c 2007-11-09 23:09:50 UTC (rev 7120)
+++ trunk/coregrind/m_main.c 2007-11-09 23:13:22 UTC (rev 7121)
@@ -1174,6 +1174,7 @@
HChar* toolname = "memcheck"; // default to Memcheck
Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
UInt* client_auxv = NULL;
+ ThreadId tid_main = VG_INVALID_THREADID;
Int loglevel, i;
Bool logging_to_fd;
struct vki_rlimit zero = { 0, 0 };
@@ -1766,6 +1767,17 @@
}
//--------------------------------------------------------------
+ // Initialise the scheduler (phase 1) [generates tid_main]
+ // p: none, afaics
+ //--------------------------------------------------------------
+ VG_(debugLog)(1, "main", "Initialise scheduler (phase 1)\n");
+ tid_main = VG_(scheduler_init_phase1)();
+ vg_assert(tid_main >= 0 && tid_main < VG_N_THREADS
+ && tid_main != VG_INVALID_THREADID);
+ /* Tell the tool about tid_main */
+ VG_TRACK( pre_thread_ll_create, VG_INVALID_THREADID, tid_main );
+
+ //--------------------------------------------------------------
// Tell the tool about the initial client memory permissions
// p: aspacem
// p: mallocfree
@@ -1837,18 +1849,20 @@
}
//--------------------------------------------------------------
- // Initialise the scheduler
+ // Initialise the scheduler (phase 2)
+ // p: Initialise the scheduler (phase 1) [for tid_main]
// p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
// p: setup_client_stack
//--------------------------------------------------------------
- VG_(debugLog)(1, "main", "Initialise scheduler\n");
+ VG_(debugLog)(1, "main", "Initialise scheduler (phase 2)\n");
{ NSegment const* seg
= VG_(am_find_nsegment)( the_iifii.initial_client_SP );
vg_assert(seg);
vg_assert(seg->kind == SkAnonC);
vg_assert(the_iifii.initial_client_SP >= seg->start);
vg_assert(the_iifii.initial_client_SP <= seg->end);
- VG_(scheduler_init)( seg->end, the_iifii.clstack_max_size );
+ VG_(scheduler_init_phase2)( tid_main,
+ seg->end, the_iifii.clstack_max_size );
}
//--------------------------------------------------------------
Modified: trunk/coregrind/m_scheduler/scheduler.c
===================================================================
--- trunk/coregrind/m_scheduler/scheduler.c 2007-11-09 23:09:50 UTC (rev 7120)
+++ trunk/coregrind/m_scheduler/scheduler.c 2007-11-09 23:13:22 UTC (rev 7121)
@@ -437,22 +437,17 @@
}
-/* Initialise the scheduler. Create a single "main" thread ready to
- run, with special ThreadId of one. This is called at startup. The
- caller subsequently initialises the guest state components of this
- main thread, thread 1.
+/* First phase of initialisation of the scheduler. Initialise the
+ bigLock, zeroise the VG_(threads) structure and decide on the
+ ThreadId of the root thread.
*/
-void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size )
+ThreadId VG_(scheduler_init_phase1) ( void )
{
Int i;
ThreadId tid_main;
- VG_(debugLog)(1,"sched","sched_init: cls_end=0x%lx, cls_sz=%ld\n",
- clstack_end, clstack_size);
+ VG_(debugLog)(1,"sched","sched_init_phase1\n");
- vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
- vg_assert(VG_IS_PAGE_ALIGNED(clstack_size));
-
ML_(sema_init)(&the_BigLock);
for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) {
@@ -470,8 +465,28 @@
}
tid_main = VG_(alloc_ThreadState)();
- vg_assert(tid_main == 1);
+ return tid_main;
+}
+
+
+/* Second phase of initialisation of the scheduler. Given the root
+ ThreadId computed by first phase of initialisation, fill in stack
+ details and acquire bigLock. Initialise the scheduler. This is
+ called at startup. The caller subsequently initialises the guest
+ state components of this main thread.
+*/
+void VG_(scheduler_init_phase2) ( ThreadId tid_main,
+ Addr clstack_end,
+ SizeT clstack_size )
+{
+ VG_(debugLog)(1,"sched","sched_init_phase2: tid_main=%d, "
+ "cls_end=0x%lx, cls_sz=%ld\n",
+ tid_main, clstack_end, clstack_size);
+
+ vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
+ vg_assert(VG_IS_PAGE_ALIGNED(clstack_size));
+
VG_(threads)[tid_main].client_stack_highest_word
= clstack_end + 1 - sizeof(UWord);
VG_(threads)[tid_main].client_stack_szB
@@ -625,6 +640,7 @@
VG_(clo_profile_flags) > 0 ? 1 : 0 )
);
+ vg_assert(VG_(in_generated_code) == True);
VG_(in_generated_code) = False;
if (jumped) {
Modified: trunk/coregrind/pub_core_scheduler.h
===================================================================
--- trunk/coregrind/pub_core_scheduler.h 2007-11-09 23:09:50 UTC (rev 7120)
+++ trunk/coregrind/pub_core_scheduler.h 2007-11-09 23:13:22 UTC (rev 7121)
@@ -75,9 +75,16 @@
// The scheduler.
extern VgSchedReturnCode VG_(scheduler) ( ThreadId tid );
-// Initialise. Is passed the extent of the root thread's client stack.
-extern void VG_(scheduler_init) ( Addr clstack_end, SizeT clstack_size );
+// Initialise, phase 1. Zero out VG_(threads), decide on the root
+// ThreadId and initialise the bigLock.
+extern ThreadId VG_(scheduler_init_phase1) ( void );
+// Initialise, phase 2. Is passed the extent of the root thread's
+// client stack and the root ThreadId decided on by phase 1.
+extern void VG_(scheduler_init_phase2) ( ThreadId main_tid,
+ Addr clstack_end,
+ SizeT clstack_size );
+
/* Stats ... */
extern void VG_(print_scheduler_stats) ( void );
|
|
From: <sv...@va...> - 2007-11-09 23:09:49
|
Author: sewardj
Date: 2007-11-09 23:09:50 +0000 (Fri, 09 Nov 2007)
New Revision: 7120
Log:
Merge r6806 from branches/THRCHECK:
Fix longstanding error in the amd64-linux function-wrapping macros:
protect the caller's red zone across the hidden call. All rather
nasty as explained in big comment.
Modified:
trunk/include/valgrind.h
Modified: trunk/include/valgrind.h
===================================================================
--- trunk/include/valgrind.h 2007-11-09 23:06:35 UTC (rev 7119)
+++ trunk/include/valgrind.h 2007-11-09 23:09:50 UTC (rev 7120)
@@ -1022,6 +1022,27 @@
/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
long) == 8. */
+/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
+ macros. In order not to trash the stack redzone, we need to drop
+ %rsp by 128 before the hidden call, and restore afterwards. The
+ nastyness is that it is only by luck that the stack still appears
+ to be unwindable during the hidden call - since then the behaviour
+ of any routine using this macro does not match what the CFI data
+ says. Sigh.
+
+ Why is this important? Imagine that a wrapper has a stack
+ allocated local, and passes to the hidden call, a pointer to it.
+ Because gcc does not know about the hidden call, it may allocate
+ that local in the redzone. Unfortunately the hidden call may then
+ trash it before it comes to use it. So we must step clear of the
+ redzone, for the duration of the hidden call, to make it safe.
+
+ Probably the same problem afflicts the other redzone-style ABIs too
+ (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
+ self describing (none of this CFI nonsense) so at least messing
+ with the stack pointer doesn't give a danger of non-unwindable
+ stack. */
+
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
@@ -1029,8 +1050,10 @@
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1046,9 +1069,11 @@
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1065,10 +1090,12 @@
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1086,11 +1113,13 @@
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1109,12 +1138,14 @@
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1134,6 +1165,7 @@
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
"movq 24(%%rax), %%rdx\n\t" \
@@ -1141,6 +1173,7 @@
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1161,6 +1194,7 @@
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
"movq 32(%%rax), %%rcx\n\t" \
@@ -1168,6 +1202,7 @@
"movq 16(%%rax), %%rsi\n\t" \
"movq 8(%%rax), %%rdi\n\t" \
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ "addq $128,%%rsp\n\t" \
VALGRIND_CALL_NOREDIR_RAX \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
@@ -1191,6 +1226,7 @@
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
"movq 40(%%rax), %%r8\n\t" \
@@ -1201,6 +1237,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $8, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1224,6 +1261,7 @@
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
"movq 48(%%rax), %%r9\n\t" \
@@ -1235,6 +1273,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $16, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1259,6 +1298,7 @@
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
"pushq 56(%%rax)\n\t" \
@@ -1271,6 +1311,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $24, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1296,6 +1337,7 @@
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 80(%%rax)\n\t" \
"pushq 72(%%rax)\n\t" \
"pushq 64(%%rax)\n\t" \
@@ -1309,6 +1351,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $32, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1335,6 +1378,7 @@
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 88(%%rax)\n\t" \
"pushq 80(%%rax)\n\t" \
"pushq 72(%%rax)\n\t" \
@@ -1349,6 +1393,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $40, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
@@ -1376,6 +1421,7 @@
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
"pushq 96(%%rax)\n\t" \
"pushq 88(%%rax)\n\t" \
"pushq 80(%%rax)\n\t" \
@@ -1391,6 +1437,7 @@
"movq (%%rax), %%rax\n\t" /* target->%rax */ \
VALGRIND_CALL_NOREDIR_RAX \
"addq $48, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
: /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
|
|
From: <sv...@va...> - 2007-11-09 23:06:35
|
Author: sewardj
Date: 2007-11-09 23:06:35 +0000 (Fri, 09 Nov 2007)
New Revision: 7119
Log:
Track vex r1793: make all tools able to handle the new IR memory bus
event statement (Ist_MBE).
Modified:
trunk/cachegrind/cg_main.c
trunk/callgrind/main.c
trunk/lackey/lk_main.c
trunk/memcheck/mc_translate.c
Modified: trunk/cachegrind/cg_main.c
===================================================================
--- trunk/cachegrind/cg_main.c 2007-11-09 23:02:28 UTC (rev 7118)
+++ trunk/cachegrind/cg_main.c 2007-11-09 23:06:35 UTC (rev 7119)
@@ -963,7 +963,7 @@
case Ist_AbiHint:
case Ist_Put:
case Ist_PutI:
- case Ist_MFence:
+ case Ist_MBE:
break;
case Ist_IMark:
Modified: trunk/callgrind/main.c
===================================================================
--- trunk/callgrind/main.c 2007-11-09 23:02:28 UTC (rev 7118)
+++ trunk/callgrind/main.c 2007-11-09 23:06:35 UTC (rev 7119)
@@ -468,7 +468,7 @@
case Ist_Put:
case Ist_PutI:
- case Ist_MFence:
+ case Ist_MBE:
case Ist_Exit:
break;
Modified: trunk/lackey/lk_main.c
===================================================================
--- trunk/lackey/lk_main.c 2007-11-09 23:02:28 UTC (rev 7118)
+++ trunk/lackey/lk_main.c 2007-11-09 23:06:35 UTC (rev 7119)
@@ -670,7 +670,7 @@
case Ist_AbiHint:
case Ist_Put:
case Ist_PutI:
- case Ist_MFence:
+ case Ist_MBE:
addStmtToIRSB( sbOut, st );
break;
Modified: trunk/memcheck/mc_translate.c
===================================================================
--- trunk/memcheck/mc_translate.c 2007-11-09 23:02:28 UTC (rev 7118)
+++ trunk/memcheck/mc_translate.c 2007-11-09 23:06:35 UTC (rev 7119)
@@ -3290,7 +3290,7 @@
return isBogusAtom(st->Ist.AbiHint.base);
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
return False;
default:
unhandled:
@@ -3470,7 +3470,7 @@
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
break;
case Ist_Dirty:
|
|
From: <sv...@va...> - 2007-11-09 23:02:26
|
Author: sewardj
Date: 2007-11-09 23:02:28 +0000 (Fri, 09 Nov 2007)
New Revision: 7118
Log:
Merge (from branches/THRCHECK) the following amd64-linux stack unwind
kludges^H^H^H^H^H^H^Henhancements:
r6802: For VG_(record_ExeContext) et al, add a new parameter
(first_ip_delta) which is added to the initial IP value before the
stack is unwound. A safe value to pass is zero, which causes the
existing behaviour to be unchanged. This is a kludge needed to work
around the incomplete amd64 stack unwind info in glibc-2.5's clone()
routine.
r7059: Add a last-ditch heuristic-hack to the amd64-linux stack
unwinder, which is used when all other methods fail. Seems like GDB
has something similar.
Modified:
trunk/coregrind/m_execontext.c
trunk/coregrind/m_stacktrace.c
trunk/exp-omega/o_main.c
trunk/include/pub_tool_execontext.h
trunk/massif/ms_main.c
trunk/memcheck/mc_main.c
trunk/memcheck/mc_malloc_wrappers.c
Modified: trunk/coregrind/m_execontext.c
===================================================================
--- trunk/coregrind/m_execontext.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/coregrind/m_execontext.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -277,7 +277,7 @@
ec_htab_size_idx++;
}
-ExeContext* VG_(record_ExeContext) ( ThreadId tid )
+ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta )
{
Int i;
Addr ips[VG_DEEPEST_BACKTRACE];
@@ -297,7 +297,8 @@
vg_assert(VG_(clo_backtrace_size) >= 1 &&
VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
- n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size) );
+ n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
+ first_ip_delta );
tl_assert(n_ips >= 1 && n_ips <= VG_(clo_backtrace_size));
/* Now figure out if we've seen this one before. First hash it so
Modified: trunk/coregrind/m_stacktrace.c
===================================================================
--- trunk/coregrind/m_stacktrace.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/coregrind/m_stacktrace.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -240,7 +240,29 @@
continue;
}
- /* No luck there. We have to give up. */
+ /* Last-ditch hack (evidently GDB does something similar). We
+ are in the middle of nowhere and we have a nonsense value for
+ the frame pointer. If the stack pointer is still valid,
+ assume that what it points at is a return address. Yes,
+ desperate measures. Could do better here:
+ - check that the supposed return address is in
+ an executable page
+ - check that the supposed return address is just after a call insn
+ - given those two checks, don't just consider *sp as the return
+ address; instead scan a likely section of stack (eg sp .. sp+256)
+ and use suitable values found there.
+ */
+ if (fp_min <= sp && sp < fp_max) {
+ ip = ((UWord*)sp)[0];
+ ips[i++] = ip;
+ if (debug)
+ VG_(printf)(" ipsH[%d]=%08p\n", i-1, ips[i-1]);
+ ip = ip - 1;
+ sp += 8;
+ continue;
+ }
+
+ /* No luck at all. We have to give up. */
break;
}
@@ -369,7 +391,8 @@
return n_found;
}
-UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips )
+UInt VG_(get_StackTrace) ( ThreadId tid, StackTrace ips, UInt n_ips,
+ Word first_ip_delta )
{
/* thread in thread table */
Addr ip = VG_(get_IP)(tid);
@@ -405,6 +428,10 @@
}
# endif
+ /* Take into account the first_ip_delta. */
+ vg_assert( sizeof(Addr) == sizeof(Word) );
+ ip += first_ip_delta;
+
if (0)
VG_(printf)("tid %d: stack_highest=0x%08lx ip=0x%08lx sp=0x%08lx fp=0x%08lx\n",
tid, stack_highest_word, ip, sp, fp);
@@ -446,7 +473,8 @@
void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips )
{
Addr ips[n_ips];
- UInt n_ips_obtained = VG_(get_StackTrace)(tid, ips, n_ips);
+ UInt n_ips_obtained = VG_(get_StackTrace)(tid, ips, n_ips,
+ 0/*first_ip_delta*/);
VG_(pp_StackTrace)(ips, n_ips_obtained);
}
Modified: trunk/exp-omega/o_main.c
===================================================================
--- trunk/exp-omega/o_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/exp-omega/o_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -15,7 +15,7 @@
providing moral support.)
Partly based upon other Valgrind tools
- Copyright (C) 2000-2006 Julian Seward, Nicholas Nethercote et al.
+ Copyright (C) 2000-2007 Julian Seward, Nicholas Nethercote et al.
js...@ac...
nj...@va...
@@ -1582,7 +1582,8 @@
{
O_MDEBUG("creating new context maybeLast=0");
// Get the current stacktrace
- mb->leaked = VG_(record_ExeContext)(VG_(get_running_tid)());
+ mb->leaked = VG_(record_ExeContext)(VG_(get_running_tid)(),
+ 0/*first_ip_delta*/);
}
doReport = o_addLeakedBlock(mb->where, mb->leaked, mb->length);
@@ -1945,7 +1946,7 @@
*/
mb->hdr.key = start;
mb->length = size;
- mb->where = VG_(record_ExeContext)(tid);
+ mb->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
/*
O_DEBUG("Creating new MemBlock (%p) key = %p, length %d",
@@ -2036,7 +2037,8 @@
if(!tp->memBlock->maybeLast)
{
tp->memBlock->maybeLast = tp;
- tp->memBlock->funcEnd = VG_(record_ExeContext)(VG_(get_running_tid)());
+ tp->memBlock->funcEnd = VG_(record_ExeContext)(VG_(get_running_tid)(),
+ 0/*first_ip_delta*/);
O_MDEBUG("setting maybeLast to %p in block at %p",
FROM_TRACKED_KEY(tp->hdr.key), tp->block);
}
Modified: trunk/include/pub_tool_execontext.h
===================================================================
--- trunk/include/pub_tool_execontext.h 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/include/pub_tool_execontext.h 2007-11-09 23:02:28 UTC (rev 7118)
@@ -51,8 +51,11 @@
//
// If called from generated code, use VG_(get_running_tid)() to get the
// current ThreadId. If called from non-generated code, the current
-// ThreadId should be passed in by the core.
-extern ExeContext* VG_(record_ExeContext) ( ThreadId tid );
+// ThreadId should be passed in by the core. The initial IP value to
+// use is adjusted by first_ip_delta before the stack is unwound.
+// A safe value to pass is zero.
+extern
+ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta );
// Apply a function to every element in the ExeContext. The parameter 'n'
// gives the index of the passed ip. Doesn't go below main() unless
Modified: trunk/massif/ms_main.c
===================================================================
--- trunk/massif/ms_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/massif/ms_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -875,7 +875,8 @@
VG_(tool_panic)("get_IPs: ips[] too small, inc. MAX_OVERESTIMATE?");
// Ask for more IPs than clo_depth suggests we need.
- n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate );
+ n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate,
+ 0/*first_ip_delta*/ );
tl_assert(n_ips > 0);
// If the original stack trace is smaller than asked-for, redo=False.
Modified: trunk/memcheck/mc_main.c
===================================================================
--- trunk/memcheck/mc_main.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/memcheck/mc_main.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -4659,7 +4659,7 @@
cgbs[i].start = arg[1];
cgbs[i].size = arg[2];
cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
- cgbs[i].where = VG_(record_ExeContext) ( tid );
+ cgbs[i].where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
*ret = i;
} else
@@ -4975,6 +4975,7 @@
VG_(needs_core_errors) ();
VG_(needs_tool_errors) (mc_eq_Error,
mc_pp_Error,
+ True,/*show TIDs for errors*/
mc_update_extra,
mc_recognised_suppression,
mc_read_extra_suppression_info,
Modified: trunk/memcheck/mc_malloc_wrappers.c
===================================================================
--- trunk/memcheck/mc_malloc_wrappers.c 2007-11-09 22:50:55 UTC (rev 7117)
+++ trunk/memcheck/mc_malloc_wrappers.c 2007-11-09 23:02:28 UTC (rev 7118)
@@ -131,7 +131,7 @@
mc->data = p;
mc->szB = szB;
mc->allockind = kind;
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
/* Paranoia ... ensure the MC_Chunk is off-limits to the client, so
the mc->data field isn't visible to the leak checker. If memory
@@ -271,7 +271,7 @@
/* Put it out of harm's way for a while, if not from a client request */
if (MC_AllocCustom != mc->allockind) {
/* Record where freed */
- mc->where = VG_(record_ExeContext) ( tid );
+ mc->where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
add_to_freed_queue ( mc );
} else {
VG_(free) ( mc );
@@ -349,14 +349,14 @@
if (old_szB == new_szB) {
/* size unchanged */
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
p_new = p_old;
} else if (old_szB > new_szB) {
/* new size is smaller */
MC_(make_mem_noaccess)( mc->data+new_szB, mc->szB-new_szB );
mc->szB = new_szB;
- mc->where = VG_(record_ExeContext)(tid);
+ mc->where = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
p_new = p_old;
} else {
|
|
From: Nicholas N. <nj...@cs...> - 2007-11-09 22:52:28
|
On Sat, 3 Nov 2007, Josef Weidendorfer wrote: > I do not understand the benefit of QUAL above. Do I understand correctly, > and you specify the name of an environment variable here that is substituted > in the file name? Why can you not just say --cg-out-file=X.$QUAL (ie. the > substitution is done by the shell at exec time)? It's somehow important for MPI programs, where you want every different process's output to go to a different file. I don't know the details. > With %T, we could generalize the options among the tools, e.g. by > just using "--out-file=<pattern>". > However. This does not really work for callgrind :-( > To get the current behavior of callgrind, there is the need for > four (!) such patterns for different contexts: > 1) termination without separate counters per thread: %T.out.%p > 2) termination with separate counters per thread: %T.out.%p-%t > 3) dumping in the middle without seperate c.p.t. : %T.out.%p.%c > 4) " with " : %T.out.%p.%c-%t > > I am open for any suggestions to unify this mess into just one pattern. A format string seems like a good way to do it. But it's not obvious how to do it for Callgrind. Hmm. Nick |
|
From: <sv...@va...> - 2007-11-09 22:50:56
|
Author: sewardj
Date: 2007-11-09 22:50:55 +0000 (Fri, 09 Nov 2007)
New Revision: 7117
Log:
Suppressions for (new) Helgrind.
Added:
trunk/glibc-2.X-helgrind.supp
Added: trunk/glibc-2.X-helgrind.supp
===================================================================
--- trunk/glibc-2.X-helgrind.supp (rev 0)
+++ trunk/glibc-2.X-helgrind.supp 2007-11-09 22:50:55 UTC (rev 7117)
@@ -0,0 +1,336 @@
+
+##----------------------------------------------------------------------##
+# Suppressions for the Helgrind tool when using
+# a glibc-2.{2,3,4,5,6} system
+
+######------------ glibc-2.5 specific ------------######
+#
+## NB. This is the "reference set". Derived sets for
+## glibc 2.4, 2.3 and 2.6 follow below.
+{
+ helgrind-glibc25-001
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/ld-2.5.so
+}
+{
+ helgrind-glibc25-002
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/libc-2.5.so
+ obj:/lib*/ld-2.5.so
+}
+{
+ helgrind-glibc25-003
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/libc-2.5.so
+ obj:/lib*/libc-2.5.so
+}
+{
+ helgrind-glibc25-004
+ Helgrind:Race
+ obj:/lib*/libc-2.5.so
+ obj:/lib*/libc-2.5.so
+}
+{
+ helgrind-glibc25-005
+ Helgrind:Race
+ obj:/lib*/libpthread-2.5.so
+ obj:/lib*/libpthread-2.5.so
+ obj:/lib*/libpthread-2.5.so
+}
+{
+ helgrind-glibc25-006
+ Helgrind:Race
+ obj:/lib*/libpthread-2.5.so
+ obj:/lib*/libpthread-2.5.so
+ obj:/lib*/libc-2.5.so
+}
+{
+ helgrind-glibc25-007
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/libc-2.5.so
+ obj:/lib*/libdl-2.5.so
+}
+{
+ helgrind-glibc25-008
+ Helgrind:Race
+ obj:/lib*/libpthread-2.5.so
+ obj:/lib*/libc-2.5.so
+}
+{
+ helgrind-glibc25-009
+ Helgrind:Race
+ obj:/lib*/libc-2.5.so
+ fun:*
+ obj:/lib*/libc-2.5.so
+}
+{
+ helgrind-glibc25-010
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/libpthread-2.5.so
+}
+{
+ helgrind-glibc25-011
+ Helgrind:Race
+ obj:/lib*/libc-2.5.so
+ obj:/lib*/libpthread-2.5.so
+}
+{
+ helgrind-glibc25-013
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ fun:*
+ obj:/lib*/ld-2.5.so
+}
+{
+ helgrind-glibc25-014
+ Helgrind:Race
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/ld-2.5.so
+ obj:/lib*/libpthread-2.5.so
+}
+
+# These are very ugly. They are needed to suppress errors inside (eg)
+# NPTL's pthread_cond_signal. Why only one stack frame -- at least we
+# should see the wrapper calling the real functions, right?
+# Unfortunately, no: the real functions are handwritten assembly (in
+# the glibc-2.5 sources) and does not create a proper stack frame.
+# Therefore it's only one level of unwinding before we're back out in
+# user code rather than the 2 levels you'd expect.
+{
+ helgrind-glibc25-101
+ Helgrind:Race
+ obj:/lib*/libpthread-2.5.so
+ fun:pthread_*
+}
+{
+ helgrind-glibc25-102
+ Helgrind:Race
+ fun:mythread_wrapper
+ obj:/lib*/libpthread-2.5.so
+}
+{
+ helgrind-glibc25-103
+ Helgrind:Race
+ fun:pthread_cond_*@@GLIBC_2.3.2
+}
+{
+ helgrind-glibc25-104
+ Helgrind:Race
+ fun:__lll_mutex_*
+}
+{
+ helgrind-glibc25-105
+ Helgrind:Race
+ fun:pthread_rwlock_*lock*
+}
+
+######------------ glibc-2.4 specific ------------######
+#
+{
+ helgrind-glibc24-001
+ Helgrind:Race
+ obj:/lib*/ld-2.4.so
+ obj:/lib*/ld-2.4.so
+ obj:/lib*/ld-2.4.so
+}
+{
+ helgrind-glibc24-003
+ Helgrind:Race
+ obj:/lib*/ld-2.4.so
+ obj:/lib*/libc-2.4.so
+ obj:/lib*/libc-2.4.so
+}
+{
+ helgrind-glibc24-004
+ Helgrind:Race
+ obj:/lib*/libc-2.4.so
+ obj:/lib*/libc-2.4.so
+}
+{
+ helgrind-glibc24-005
+ Helgrind:Race
+ obj:/lib*/libpthread-2.4.so
+ obj:/lib*/libpthread-2.4.so
+ obj:/lib*/libpthread-2.4.so
+}
+{
+ helgrind-glibc24-006
+ Helgrind:Race
+ obj:/lib*/libpthread-2.4.so
+ obj:/lib*/libpthread-2.4.so
+ obj:/lib*/libc-2.4.so
+}
+{
+ helgrind-glibc24-008
+ Helgrind:Race
+ obj:/lib*/libpthread-2.4.so
+ obj:/lib*/libc-2.4.so
+}
+{
+ helgrind-glibc24-010
+ Helgrind:Race
+ obj:/lib*/ld-2.4.so
+ obj:/lib*/libpthread-2.4.so
+}
+{
+ helgrind-glibc24-011
+ Helgrind:Race
+ obj:/lib*/libc-2.4.so
+ obj:/lib*/libpthread-2.4.so
+}
+
+{
+ helgrind-glibc24-101
+ Helgrind:Race
+ obj:/lib*/libpthread-2.4.so
+ fun:pthread_*
+}
+{
+ helgrind-glibc24-102
+ Helgrind:Race
+ fun:mythread_wrapper
+ obj:/lib*/libpthread-2.4.so
+}
+
+######------------ glibc-2.6 specific ---------######
+#
+{
+ helgrind-glibc26-001
+ Helgrind:Race
+ obj:/lib*/ld-2.6.*so
+ obj:/lib*/ld-2.6.*so
+ obj:/lib*/ld-2.6.*so
+}
+{
+ helgrind-glibc26-003
+ Helgrind:Race
+ obj:/lib*/ld-2.6.*so
+ obj:/lib*/libc-2.6.*so
+ obj:/lib*/libc-2.6.*so
+}
+{
+ helgrind-glibc26-004
+ Helgrind:Race
+ obj:/lib*/libc-2.6.*so
+ obj:/lib*/libc-2.6.*so
+}
+{
+ helgrind-glibc26-006
+ Helgrind:Race
+ obj:/lib*/libpthread-2.6.*so
+ obj:/lib*/libpthread-2.6.*so
+ obj:/lib*/libc-2.6.*so
+}
+{
+ helgrind-glibc26-008
+ Helgrind:Race
+ obj:/lib*/libpthread-2.6.*so
+ obj:/lib*/libc-2.6.*so
+}
+
+{
+ helgrind-glibc26-101
+ Helgrind:Race
+ obj:/lib*/libpthread-2.6.*so
+ fun:pthread_*
+}
+{
+ helgrind-glibc26-102
+ Helgrind:Race
+ fun:mythread_wrapper
+ obj:/lib*/libpthread-2.6.*so
+}
+{
+ helgrind-glibc26-106
+ Helgrind:Race
+ fun:__lll_lock_wait
+}
+
+######--------- glibc-2.3 specific ---------######
+{
+ helgrind-glibc23-001
+ Helgrind:Race
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/ld-2.3.*so
+}
+{
+ helgrind-glibc23-002
+ Helgrind:Race
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/libc-2.3.*so
+ obj:/lib*/ld-2.3.*so
+}
+{
+ helgrind-glibc23-004
+ Helgrind:Race
+ obj:/lib*/libc-2.3.*so
+ obj:/lib*/libc-2.3.*so
+}
+{
+ helgrind-glibc23-006
+ Helgrind:Race
+ obj:/lib*/libpthread-2.3.*so
+ obj:/lib*/libpthread-2.3.*so
+ obj:/lib*/libc-2.3.*so
+}
+{
+ helgrind-glibc23-008
+ Helgrind:Race
+ obj:/lib*/libpthread-2.3.*so
+ obj:/lib*/libc-2.3.*so
+}
+{
+ helgrind-glibc23-009
+ Helgrind:Race
+ obj:/lib*/libc-2.3.*so
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/libc-2.3.*so
+}
+{
+ helgrind-glibc23-011
+ Helgrind:Race
+ obj:/lib*/libc-2.3.*so
+ obj:/lib*/libpthread-2.3.*so
+}
+{
+ helgrind-glibc23-012
+ Helgrind:Race
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/libc-2.3.*so
+}
+{
+ helgrind-glibc23-014
+ Helgrind:Race
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/ld-2.3.*so
+ obj:/lib*/libpthread-2.3.*so
+}
+
+{
+ helgrind-glibc23-100
+ Helgrind:Race
+ obj:/lib*/libpthread-2.3.*so
+ fun:pthread_*
+}
+{
+ helgrind-glibc23-101
+ Helgrind:Race
+ fun:mythread_wrapper
+ obj:/lib*/libpthread-2.3.*so
+}
+
+######------ qt4 specific (GNU mangling) ------######
+{
+ helgrind-qt4-QMutex::lock()-twice
+ Helgrind:Race
+ fun:_ZN6QMutex4lockEv
+ fun:_ZN6QMutex4lockEv
+}
|
|
From: <sv...@va...> - 2007-11-09 22:49:34
|
Author: sewardj Date: 2007-11-09 22:49:28 +0000 (Fri, 09 Nov 2007) New Revision: 7116 Log: Import thrcheck from the THRCHECK branch, and rename it Helgrind (with permission of the existing Helgrind authors). Added: trunk/helgrind/ trunk/helgrind/Makefile.am trunk/helgrind/docs/ trunk/helgrind/docs/Makefile.am trunk/helgrind/docs/hg-manual.xml trunk/helgrind/helgrind.h trunk/helgrind/hg_intercepts.c trunk/helgrind/hg_main.c trunk/helgrind/hg_wordfm.c trunk/helgrind/hg_wordfm.h trunk/helgrind/hg_wordset.c trunk/helgrind/hg_wordset.h trunk/helgrind/tests/ trunk/helgrind/tests/Makefile.am trunk/helgrind/tests/filter_stderr trunk/helgrind/tests/hg01_all_ok.c trunk/helgrind/tests/hg01_all_ok.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg01_all_ok.stdout.exp trunk/helgrind/tests/hg01_all_ok.vgtest trunk/helgrind/tests/hg02_deadlock.c trunk/helgrind/tests/hg02_deadlock.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg02_deadlock.stderr.exp-glibc25-x86 trunk/helgrind/tests/hg02_deadlock.stdout.exp trunk/helgrind/tests/hg02_deadlock.vgtest trunk/helgrind/tests/hg03_inherit.c trunk/helgrind/tests/hg03_inherit.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg03_inherit.stderr.exp-glibc25-x86 trunk/helgrind/tests/hg03_inherit.stdout.exp trunk/helgrind/tests/hg03_inherit.vgtest trunk/helgrind/tests/hg04_race.c trunk/helgrind/tests/hg04_race.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg04_race.stderr.exp-glibc25-x86 trunk/helgrind/tests/hg04_race.stdout.exp trunk/helgrind/tests/hg04_race.vgtest trunk/helgrind/tests/hg05_race2.c trunk/helgrind/tests/hg05_race2.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg05_race2.stderr.exp-glibc25-x86 trunk/helgrind/tests/hg05_race2.stdout.exp trunk/helgrind/tests/hg05_race2.vgtest trunk/helgrind/tests/hg06_readshared.c trunk/helgrind/tests/hg06_readshared.stderr.exp-glibc25-amd64 trunk/helgrind/tests/hg06_readshared.stdout.exp trunk/helgrind/tests/hg06_readshared.vgtest trunk/helgrind/tests/tc01_simple_race.c trunk/helgrind/tests/tc01_simple_race.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc01_simple_race.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc01_simple_race.stdout.exp trunk/helgrind/tests/tc01_simple_race.vgtest trunk/helgrind/tests/tc02_simple_tls.c trunk/helgrind/tests/tc02_simple_tls.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc02_simple_tls.stdout.exp trunk/helgrind/tests/tc02_simple_tls.vgtest trunk/helgrind/tests/tc03_re_excl.c trunk/helgrind/tests/tc03_re_excl.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc03_re_excl.stdout.exp trunk/helgrind/tests/tc03_re_excl.vgtest trunk/helgrind/tests/tc04_free_lock.c trunk/helgrind/tests/tc04_free_lock.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc04_free_lock.stdout.exp trunk/helgrind/tests/tc04_free_lock.vgtest trunk/helgrind/tests/tc05_simple_race.c trunk/helgrind/tests/tc05_simple_race.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc05_simple_race.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc05_simple_race.stdout.exp trunk/helgrind/tests/tc05_simple_race.vgtest trunk/helgrind/tests/tc06_two_races.c trunk/helgrind/tests/tc06_two_races.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc06_two_races.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc06_two_races.stdout.exp trunk/helgrind/tests/tc06_two_races.vgtest trunk/helgrind/tests/tc07_hbl1.c trunk/helgrind/tests/tc07_hbl1.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc07_hbl1.stdout.exp trunk/helgrind/tests/tc07_hbl1.vgtest trunk/helgrind/tests/tc08_hbl2.c trunk/helgrind/tests/tc08_hbl2.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc08_hbl2.stdout.exp trunk/helgrind/tests/tc08_hbl2.vgtest trunk/helgrind/tests/tc09_bad_unlock.c trunk/helgrind/tests/tc09_bad_unlock.stderr.exp-glibc23-amd64 trunk/helgrind/tests/tc09_bad_unlock.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc09_bad_unlock.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc09_bad_unlock.stdout.exp trunk/helgrind/tests/tc09_bad_unlock.vgtest trunk/helgrind/tests/tc10_rec_lock.c trunk/helgrind/tests/tc10_rec_lock.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc10_rec_lock.stdout.exp trunk/helgrind/tests/tc10_rec_lock.vgtest trunk/helgrind/tests/tc11_XCHG.c trunk/helgrind/tests/tc11_XCHG.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc11_XCHG.stdout.exp trunk/helgrind/tests/tc11_XCHG.vgtest trunk/helgrind/tests/tc12_rwl_trivial.c trunk/helgrind/tests/tc12_rwl_trivial.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc12_rwl_trivial.stdout.exp trunk/helgrind/tests/tc12_rwl_trivial.vgtest trunk/helgrind/tests/tc13_laog1.c trunk/helgrind/tests/tc13_laog1.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc13_laog1.stdout.exp trunk/helgrind/tests/tc13_laog1.vgtest trunk/helgrind/tests/tc14_laog_dinphils.c trunk/helgrind/tests/tc14_laog_dinphils.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc14_laog_dinphils.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc14_laog_dinphils.stdout.exp trunk/helgrind/tests/tc14_laog_dinphils.vgtest trunk/helgrind/tests/tc15_laog_lockdel.c trunk/helgrind/tests/tc15_laog_lockdel.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc15_laog_lockdel.stdout.exp trunk/helgrind/tests/tc15_laog_lockdel.vgtest trunk/helgrind/tests/tc16_byterace.c trunk/helgrind/tests/tc16_byterace.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc16_byterace.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc16_byterace.stdout.exp trunk/helgrind/tests/tc16_byterace.vgtest trunk/helgrind/tests/tc17_sembar.c trunk/helgrind/tests/tc17_sembar.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc17_sembar.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc17_sembar.stdout.exp trunk/helgrind/tests/tc17_sembar.vgtest trunk/helgrind/tests/tc18_semabuse.c trunk/helgrind/tests/tc18_semabuse.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc18_semabuse.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc18_semabuse.stdout.exp trunk/helgrind/tests/tc18_semabuse.vgtest trunk/helgrind/tests/tc19_shadowmem.c trunk/helgrind/tests/tc19_shadowmem.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc19_shadowmem.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc19_shadowmem.stdout.exp trunk/helgrind/tests/tc19_shadowmem.vgtest trunk/helgrind/tests/tc20_verifywrap.c trunk/helgrind/tests/tc20_verifywrap.stderr.exp-glibc23-amd64 trunk/helgrind/tests/tc20_verifywrap.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc20_verifywrap.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc20_verifywrap.stdout.exp trunk/helgrind/tests/tc20_verifywrap.vgtest trunk/helgrind/tests/tc21_pthonce.c trunk/helgrind/tests/tc21_pthonce.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc21_pthonce.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc21_pthonce.stdout.exp trunk/helgrind/tests/tc21_pthonce.vgtest trunk/helgrind/tests/tc22_exit_w_lock.c trunk/helgrind/tests/tc22_exit_w_lock.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc22_exit_w_lock.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc22_exit_w_lock.stdout.exp trunk/helgrind/tests/tc22_exit_w_lock.vgtest trunk/helgrind/tests/tc23_bogus_condwait.c trunk/helgrind/tests/tc23_bogus_condwait.stderr.exp-glibc25-amd64 trunk/helgrind/tests/tc23_bogus_condwait.stderr.exp-glibc25-x86 trunk/helgrind/tests/tc23_bogus_condwait.stdout.exp trunk/helgrind/tests/tc23_bogus_condwait.vgtest [... diff too large to include ...] |
|
From: Nicholas N. <nj...@cs...> - 2007-11-09 22:39:27
|
On Fri, 9 Nov 2007 sv...@va... wrote: > Author: sewardj > Date: 2007-11-09 15:44:15 +0000 (Fri, 09 Nov 2007) > New Revision: 7113 > > Log: > Rename this directory. > > Added: > trunk/old-helgrind/ > Removed: > trunk/helgrind/ Will you delete this eventually? Nick |
|
From: Nicholas N. <nj...@cs...> - 2007-11-09 22:37:30
|
On Fri, 9 Nov 2007, Julian Seward wrote: >> - How to show file names with full path in thrcheck's output? > > I think Nick and/or Josef know about this. I remember that a change > was committed to trunk, which makes this work. When Thrcheck is merged > to trunk (soon), then it will get that same functionality. Yes, you have to use VG_(get_filename_linenum). (Strangely enough, VG_(get_filename) doesn't get the directory name.) N |
|
From: <sv...@va...> - 2007-11-09 21:15:07
|
Author: sewardj
Date: 2007-11-09 21:15:04 +0000 (Fri, 09 Nov 2007)
New Revision: 1793
Log:
Merge changes from THRCHECK branch r1787. These changes are all to do
with making x86/amd64 LOCK prefixes properly visible in the IR, since
threading tools need to see them. Probably would be no bad thing for
cachegrind/callgrind to notice them too, since asserting a bus lock on
a multiprocessor is an expensive event that programmers might like to
know about.
* amd64 front end: handle LOCK prefixes a lot more accurately
* x86 front end: ditto, and also a significant cleanup of prefix
handling, which was a mess
* To represent prefixes, remove the IR 'Ist_MFence' construction
and replace it with something more general: an IR Memory Bus
Event statement (Ist_MBE), which can represent lock
acquisition, lock release, and memory fences.
* Fix up all front ends and back ends to respectively generate
and handle Ist_MBE. Fix up the middle end (iropt) to deal with
them.
Modified:
trunk/priv/guest-amd64/toIR.c
trunk/priv/guest-ppc/toIR.c
trunk/priv/guest-x86/toIR.c
trunk/priv/host-amd64/isel.c
trunk/priv/host-ppc/isel.c
trunk/priv/host-x86/isel.c
trunk/priv/ir/irdefs.c
trunk/priv/ir/iropt.c
trunk/pub/libvex_ir.h
trunk/test_main.c
Modified: trunk/priv/guest-amd64/toIR.c
===================================================================
--- trunk/priv/guest-amd64/toIR.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/guest-amd64/toIR.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -1963,7 +1963,7 @@
/*------------------------------------------------------------*/
static
-HChar* sorbTxt ( Prefix pfx )
+HChar* segRegTxt ( Prefix pfx )
{
if (pfx & PFX_CS) return "%cs:";
if (pfx & PFX_DS) return "%ds:";
@@ -2115,7 +2115,7 @@
case 0x00: case 0x01: case 0x02: case 0x03:
/* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
{ UChar rm = toUChar(mod_reg_rm & 7);
- DIS(buf, "%s(%s)", sorbTxt(pfx), nameIRegRexB(8,pfx,rm));
+ DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
*len = 1;
return disAMode_copy2tmp(
handleAddrOverrides(pfx, getIRegRexB(8,pfx,rm)));
@@ -2129,9 +2129,9 @@
{ UChar rm = toUChar(mod_reg_rm & 7);
Long d = getSDisp8(delta);
if (d == 0) {
- DIS(buf, "%s(%s)", sorbTxt(pfx), nameIRegRexB(8,pfx,rm));
+ DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,rm));
} else {
- DIS(buf, "%s%lld(%s)", sorbTxt(pfx), d, nameIRegRexB(8,pfx,rm));
+ DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
}
*len = 2;
return disAMode_copy2tmp(
@@ -2146,7 +2146,7 @@
/* ! 14 */ case 0x15: case 0x16: case 0x17:
{ UChar rm = toUChar(mod_reg_rm & 7);
Long d = getSDisp32(delta);
- DIS(buf, "%s%lld(%s)", sorbTxt(pfx), d, nameIRegRexB(8,pfx,rm));
+ DIS(buf, "%s%lld(%s)", segRegTxt(pfx), d, nameIRegRexB(8,pfx,rm));
*len = 5;
return disAMode_copy2tmp(
handleAddrOverrides(pfx,
@@ -2164,7 +2164,7 @@
case 0x05:
{ Long d = getSDisp32(delta);
*len = 5;
- DIS(buf, "%s%lld(%%rip)", sorbTxt(pfx), d);
+ DIS(buf, "%s%lld(%%rip)", segRegTxt(pfx), d);
/* We need to know the next instruction's start address.
Try and figure out what it is, record the guess, and ask
the top-level driver logic (bbToIR_AMD64) to check we
@@ -2207,11 +2207,11 @@
if ((!index_is_SP) && (!base_is_BPor13)) {
if (scale == 0) {
- DIS(buf, "%s(%s,%s)", sorbTxt(pfx),
+ DIS(buf, "%s(%s,%s)", segRegTxt(pfx),
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r));
} else {
- DIS(buf, "%s(%s,%s,%d)", sorbTxt(pfx),
+ DIS(buf, "%s(%s,%s,%d)", segRegTxt(pfx),
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r), 1<<scale);
}
@@ -2227,7 +2227,7 @@
if ((!index_is_SP) && base_is_BPor13) {
Long d = getSDisp32(delta);
- DIS(buf, "%s%lld(,%s,%d)", sorbTxt(pfx), d,
+ DIS(buf, "%s%lld(,%s,%d)", segRegTxt(pfx), d,
nameIReg64rexX(pfx,index_r), 1<<scale);
*len = 6;
return
@@ -2240,7 +2240,7 @@
}
if (index_is_SP && (!base_is_BPor13)) {
- DIS(buf, "%s(%s)", sorbTxt(pfx), nameIRegRexB(8,pfx,base_r));
+ DIS(buf, "%s(%s)", segRegTxt(pfx), nameIRegRexB(8,pfx,base_r));
*len = 2;
return disAMode_copy2tmp(
handleAddrOverrides(pfx, getIRegRexB(8,pfx,base_r)));
@@ -2248,7 +2248,7 @@
if (index_is_SP && base_is_BPor13) {
Long d = getSDisp32(delta);
- DIS(buf, "%s%lld", sorbTxt(pfx), d);
+ DIS(buf, "%s%lld", segRegTxt(pfx), d);
*len = 6;
return disAMode_copy2tmp(
handleAddrOverrides(pfx, mkU64(d)));
@@ -2274,7 +2274,7 @@
Long d = getSDisp8(delta+1);
if (index_r == R_RSP && 0==getRexX(pfx)) {
- DIS(buf, "%s%lld(%s)", sorbTxt(pfx),
+ DIS(buf, "%s%lld(%s)", segRegTxt(pfx),
d, nameIRegRexB(8,pfx,base_r));
*len = 3;
return disAMode_copy2tmp(
@@ -2282,11 +2282,11 @@
binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
} else {
if (scale == 0) {
- DIS(buf, "%s%lld(%s,%s)", sorbTxt(pfx), d,
+ DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d,
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r));
} else {
- DIS(buf, "%s%lld(%s,%s,%d)", sorbTxt(pfx), d,
+ DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d,
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r), 1<<scale);
}
@@ -2321,7 +2321,7 @@
Long d = getSDisp32(delta+1);
if (index_r == R_RSP && 0==getRexX(pfx)) {
- DIS(buf, "%s%lld(%s)", sorbTxt(pfx),
+ DIS(buf, "%s%lld(%s)", segRegTxt(pfx),
d, nameIRegRexB(8,pfx,base_r));
*len = 6;
return disAMode_copy2tmp(
@@ -2329,11 +2329,11 @@
binop(Iop_Add64, getIRegRexB(8,pfx,base_r), mkU64(d)) ));
} else {
if (scale == 0) {
- DIS(buf, "%s%lld(%s,%s)", sorbTxt(pfx), d,
+ DIS(buf, "%s%lld(%s,%s)", segRegTxt(pfx), d,
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r));
} else {
- DIS(buf, "%s%lld(%s,%s,%d)", sorbTxt(pfx), d,
+ DIS(buf, "%s%lld(%s,%s,%d)", segRegTxt(pfx), d,
nameIRegRexB(8,pfx,base_r),
nameIReg64rexX(pfx,index_r), 1<<scale);
}
@@ -8299,6 +8299,96 @@
}
+/* Helper for deciding whether a given insn (starting at the opcode
+ byte) may validly be used with a LOCK prefix. The following insns
+ may be used with LOCK when their destination operand is in memory.
+ Note, this is slightly too permissive. Oh well. Note also, AFAICS
+ this is exactly the same for both 32-bit and 64-bit mode.
+
+ ADD 80 /0, 81 /0, 83 /0, 00, 01, 02, 03
+ OR 80 /1, 81 /1, 83 /1, 08, 09, 0A, 0B
+ ADC 80 /2, 81 /2, 83 /2, 10, 11, 12, 13
+ SBB 81 /3, 81 /3, 83 /3, 18, 19, 1A, 1B
+ AND 80 /4, 81 /4, 83 /4, 20, 21, 22, 23
+ SUB 80 /5, 81 /5, 83 /5, 28, 29, 2A, 2B
+ XOR 80 /6, 81 /6, 83 /6, 30, 31, 32, 33
+
+ DEC FE /1, FF /1
+ INC FE /0, FF /0
+
+ NEG F6 /3, F7 /3
+ NOT F6 /2, F7 /2
+
+ XCHG 86, 87
+
+ BTC 0F BB, 0F BA /7
+ BTR 0F B3, 0F BA /6
+ BTS 0F AB, 0F BA /5
+
+ CMPXCHG 0F B0, 0F B1
+ CMPXCHG8B 0F C7 /1
+
+ XADD 0F C0, 0F C1
+*/
+static Bool can_be_used_with_LOCK_prefix ( UChar* opc )
+{
+ switch (opc[0]) {
+ case 0x00: case 0x01: case 0x02: case 0x03: return True;
+ case 0x08: case 0x09: case 0x0A: case 0x0B: return True;
+ case 0x10: case 0x11: case 0x12: case 0x13: return True;
+ case 0x18: case 0x19: case 0x1A: case 0x1B: return True;
+ case 0x20: case 0x21: case 0x22: case 0x23: return True;
+ case 0x28: case 0x29: case 0x2A: case 0x2B: return True;
+ case 0x30: case 0x31: case 0x32: case 0x33: return True;
+
+ case 0x80: case 0x81: case 0x83:
+ if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 6)
+ return True;
+ break;
+
+ case 0xFE: case 0xFF:
+ if (gregLO3ofRM(opc[1]) >= 0 && gregLO3ofRM(opc[1]) <= 1)
+ return True;
+ break;
+
+ case 0xF6: case 0xF7:
+ if (gregLO3ofRM(opc[1]) >= 2 && gregLO3ofRM(opc[1]) <= 3)
+ return True;
+ break;
+
+ case 0x86: case 0x87:
+ return True;
+
+ case 0x0F: {
+ switch (opc[1]) {
+ case 0xBB: case 0xB3: case 0xAB:
+ return True;
+ case 0xBA:
+ if (gregLO3ofRM(opc[2]) >= 5 && gregLO3ofRM(opc[2]) <= 7)
+ return True;
+ break;
+ case 0xB0: case 0xB1:
+ return True;
+ case 0xC7:
+ if (gregLO3ofRM(opc[2]) == 1)
+ return True;
+ break;
+ case 0xC0: case 0xC1:
+ return True;
+ default:
+ break;
+ } /* switch (opc[1]) */
+ break;
+ }
+
+ default:
+ break;
+ } /* switch (opc[0]) */
+
+ return False;
+}
+
+
/*------------------------------------------------------------*/
/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
@@ -8341,6 +8431,9 @@
/* pfx holds the summary of prefixes. */
Prefix pfx = PFX_EMPTY;
+ /* do we need follow the insn with MBusEvent(BusUnlock) ? */
+ Bool unlock_bus_after_insn = False;
+
/* Set result defaults. */
dres.whatNext = Dis_Continue;
dres.len = 0;
@@ -8477,17 +8570,40 @@
/* Kludge re LOCK prefixes. We assume here that all code generated
by Vex is going to be run in a single-threaded context, in other
words that concurrent executions of Vex-generated translations
- will not happen. That is certainly the case for how the
- Valgrind-3.0 code line uses Vex. Given that assumption, it
- seems safe to ignore LOCK prefixes since there will never be any
- other thread running at the same time as this one. However, at
- least emit a memory fence on the basis that it would at least be
- prudent to flush any memory transactions from this thread as far
- as possible down the memory hierarchy. */
+ will not happen. So we don't need to worry too much about
+ preserving atomicity. However, mark the fact that the notional
+ hardware bus lock is being acquired (and, after the insn,
+ released), so that thread checking tools know this is a locked
+ insn.
+
+ We check for, and immediately reject, (most) inappropriate uses
+ of the LOCK prefix. Later (at decode_failure: and
+ decode_success:), if we've added a BusLock event, then we will
+ follow up with a BusUnlock event. How do we know execution will
+ actually ever get to the BusUnlock event? Because
+ can_be_used_with_LOCK_prefix rejects all control-flow changing
+ instructions.
+
+ One loophole, though: if a LOCK prefix insn (seg)faults, then
+ the BusUnlock event will never be reached. This could cause
+ tools which track bus hardware lock to lose track. Really, we
+ should explicitly release the lock after every insn, but that's
+ obviously way too expensive. Really, any tool which tracks the
+ state of the bus lock needs to ask V's core/tool interface to
+ notify it of signal deliveries. On delivery of SIGSEGV to the
+ guest, the tool will be notified, in which case it should
+ release the bus hardware lock if it is held.
+
+ Note, guest-x86/toIR.c contains identical logic.
+ */
if (pfx & PFX_LOCK) {
- /* vex_printf("vex amd64->IR: ignoring LOCK prefix on: ");
- insn_verbose = True; */
- stmt( IRStmt_MFence() );
+ if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
+ stmt( IRStmt_MBE(Imbe_BusLock) );
+ unlock_bus_after_insn = True;
+ DIP("lock ");
+ } else {
+ goto decode_failure;
+ }
}
@@ -9557,7 +9673,7 @@
delta += 3;
/* Insert a memory fence. It's sometimes important that these
are carried through to the generated code. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("sfence\n");
goto decode_success;
}
@@ -10336,7 +10452,7 @@
delta += 3;
/* Insert a memory fence. It's sometimes important that these
are carried through to the generated code. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("%sfence\n", gregLO3ofRM(insn[2])==5 ? "l" : "m");
goto decode_success;
}
@@ -12796,7 +12912,7 @@
assign( addr, handleAddrOverrides(pfx, mkU64(d64)) );
putIRegRAX(sz, loadLE( ty, mkexpr(addr) ));
DIP("mov%c %s0x%llx, %s\n", nameISize(sz),
- sorbTxt(pfx), d64,
+ segRegTxt(pfx), d64,
nameIRegRAX(sz));
break;
@@ -12814,7 +12930,7 @@
assign( addr, handleAddrOverrides(pfx, mkU64(d64)) );
storeLE( mkexpr(addr), getIRegRAX(sz) );
DIP("mov%c %s, %s0x%llx\n", nameISize(sz), nameIRegRAX(sz),
- sorbTxt(pfx), d64);
+ segRegTxt(pfx), d64);
break;
/* XXXX be careful here with moves to AH/BH/CH/DH */
@@ -13644,6 +13760,12 @@
/* ------------------------ XCHG ----------------------- */
+ /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
+ prefix. Therefore, surround it with a IRStmt_MBE(Imbe_BusLock)
+ and IRStmt_MBE(Imbe_BusUnlock) pair. But be careful; if it is
+ used with an explicit LOCK prefix, we don't want to end up with
+ two IRStmt_MBE(Imbe_BusLock)s -- one made here and one made by
+ the generic LOCK logic at the top of disInstr. */
case 0x86: /* XCHG Gb,Eb */
sz = 1;
/* Fall through ... */
@@ -13662,6 +13784,18 @@
nameISize(sz), nameIRegG(sz, pfx, modrm),
nameIRegE(sz, pfx, modrm));
} else {
+ /* Need to add IRStmt_MBE(Imbe_BusLock). */
+ if (pfx & PFX_LOCK) {
+ /* check it's already been taken care of */
+ vassert(unlock_bus_after_insn);
+ } else {
+ vassert(!unlock_bus_after_insn);
+ stmt( IRStmt_MBE(Imbe_BusLock) );
+ unlock_bus_after_insn = True;
+ }
+ /* Because unlock_bus_after_insn is now True, generic logic
+ at the bottom of disInstr will add the
+ IRStmt_MBE(Imbe_BusUnlock). */
addr = disAMode ( &alen, pfx, delta, dis_buf, 0 );
assign( t1, loadLE(ty, mkexpr(addr)) );
assign( t2, getIRegG(sz, pfx, modrm) );
@@ -14169,7 +14303,7 @@
stmt( IRStmt_Dirty(d) );
/* CPUID is a serialising insn. So, just in case someone is
using it as a memory fence ... */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("cpuid\n");
break;
}
@@ -14533,6 +14667,8 @@
insn, but nevertheless be paranoid and update it again right
now. */
stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr) ) );
+ if (unlock_bus_after_insn)
+ stmt( IRStmt_MBE(Imbe_BusUnlock) );
jmp_lit(Ijk_NoDecode, guest_RIP_curr_instr);
dres.whatNext = Dis_StopHere;
dres.len = 0;
@@ -14543,6 +14679,8 @@
decode_success:
/* All decode successes end up here. */
DIP("\n");
+ if (unlock_bus_after_insn)
+ stmt( IRStmt_MBE(Imbe_BusUnlock) );
dres.len = (Int)toUInt(delta - delta_start);
return dres;
}
Modified: trunk/priv/guest-ppc/toIR.c
===================================================================
--- trunk/priv/guest-ppc/toIR.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/guest-ppc/toIR.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -4816,7 +4816,7 @@
return False;
}
DIP("isync\n");
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
break;
/* X-Form */
@@ -4829,7 +4829,7 @@
}
DIP("eieio\n");
/* Insert a memory fence, just to be on the safe side. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
break;
case 0x014: // lwarx (Load Word and Reserve Indexed, PPC32 p458)
@@ -4918,7 +4918,7 @@
DIP("%ssync\n", flag_L == 1 ? "lw" : "");
/* Insert a memory fence. It's sometimes important that these
are carried through to the generated code. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
break;
/* 64bit Memsync */
@@ -5662,7 +5662,7 @@
putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
/* be paranoid ... */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
irsb->jumpkind = Ijk_TInval;
irsb->next = mkSzImm(ty, nextInsnAddr());
Modified: trunk/priv/guest-x86/toIR.c
===================================================================
--- trunk/priv/guest-x86/toIR.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/guest-x86/toIR.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -7136,6 +7136,96 @@
}
+/* Helper for deciding whether a given insn (starting at the opcode
+ byte) may validly be used with a LOCK prefix. The following insns
+ may be used with LOCK when their destination operand is in memory.
+ Note, this is slightly too permissive. Oh well. Note also, AFAICS
+ this is exactly the same for both 32-bit and 64-bit mode.
+
+ ADD 80 /0, 81 /0, 83 /0, 00, 01, 02, 03
+ OR 80 /1, 81 /1, 83 /1, 08, 09, 0A, 0B
+ ADC 80 /2, 81 /2, 83 /2, 10, 11, 12, 13
+ SBB 81 /3, 81 /3, 83 /3, 18, 19, 1A, 1B
+ AND 80 /4, 81 /4, 83 /4, 20, 21, 22, 23
+ SUB 80 /5, 81 /5, 83 /5, 28, 29, 2A, 2B
+ XOR 80 /6, 81 /6, 83 /6, 30, 31, 32, 33
+
+ DEC FE /1, FF /1
+ INC FE /0, FF /0
+
+ NEG F6 /3, F7 /3
+ NOT F6 /2, F7 /2
+
+ XCHG 86, 87
+
+ BTC 0F BB, 0F BA /7
+ BTR 0F B3, 0F BA /6
+ BTS 0F AB, 0F BA /5
+
+ CMPXCHG 0F B0, 0F B1
+ CMPXCHG8B 0F C7 /1
+
+ XADD 0F C0, 0F C1
+*/
+static Bool can_be_used_with_LOCK_prefix ( UChar* opc )
+{
+ switch (opc[0]) {
+ case 0x00: case 0x01: case 0x02: case 0x03: return True;
+ case 0x08: case 0x09: case 0x0A: case 0x0B: return True;
+ case 0x10: case 0x11: case 0x12: case 0x13: return True;
+ case 0x18: case 0x19: case 0x1A: case 0x1B: return True;
+ case 0x20: case 0x21: case 0x22: case 0x23: return True;
+ case 0x28: case 0x29: case 0x2A: case 0x2B: return True;
+ case 0x30: case 0x31: case 0x32: case 0x33: return True;
+
+ case 0x80: case 0x81: case 0x83:
+ if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 6)
+ return True;
+ break;
+
+ case 0xFE: case 0xFF:
+ if (gregOfRM(opc[1]) >= 0 && gregOfRM(opc[1]) <= 1)
+ return True;
+ break;
+
+ case 0xF6: case 0xF7:
+ if (gregOfRM(opc[1]) >= 2 && gregOfRM(opc[1]) <= 3)
+ return True;
+ break;
+
+ case 0x86: case 0x87:
+ return True;
+
+ case 0x0F: {
+ switch (opc[1]) {
+ case 0xBB: case 0xB3: case 0xAB:
+ return True;
+ case 0xBA:
+ if (gregOfRM(opc[2]) >= 5 && gregOfRM(opc[2]) <= 7)
+ return True;
+ break;
+ case 0xB0: case 0xB1:
+ return True;
+ case 0xC7:
+ if (gregOfRM(opc[2]) == 1)
+ return True;
+ break;
+ case 0xC0: case 0xC1:
+ return True;
+ default:
+ break;
+ } /* switch (opc[1]) */
+ break;
+ }
+
+ default:
+ break;
+ } /* switch (opc[0]) */
+
+ return False;
+}
+
+
/*------------------------------------------------------------*/
/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
@@ -7155,10 +7245,10 @@
IRType ty;
IRTemp addr, t0, t1, t2, t3, t4, t5, t6;
Int alen;
- UChar opc, modrm, abyte;
+ UChar opc, modrm, abyte, pre;
UInt d32;
HChar dis_buf[50];
- Int am_sz, d_sz;
+ Int am_sz, d_sz, n_prefixes;
DisResult dres;
UChar* insn; /* used in SSE decoders */
@@ -7178,6 +7268,12 @@
indicating the prefix. */
UChar sorb = 0;
+ /* Gets set to True if a LOCK prefix is seen. */
+ Bool pfx_lock = False;
+
+ /* do we need follow the insn with MBusEvent(BusUnlock) ? */
+ Bool unlock_bus_after_insn = False;
+
/* Set result defaults. */
dres.whatNext = Dis_Continue;
dres.len = 0;
@@ -7242,103 +7338,129 @@
}
}
- /* Deal with prefixes. */
- /* Skip a LOCK prefix. */
- /* 2005 Jan 06: the following insns are observed to sometimes
- have a LOCK prefix:
- cmpxchgl %ecx,(%edx)
- cmpxchgl %edx,0x278(%ebx) etc
- xchgl %eax, (%ecx)
- xaddl %eax, (%ecx)
- We need to catch any such which appear to be being used as
- a memory barrier, for example lock addl $0,0(%esp)
- and emit an IR MFence construct.
- */
- if (getIByte(delta) == 0xF0) {
-
+ /* Handle a couple of weird-ass NOPs that have been observed in the
+ wild. */
+ {
UChar* code = (UChar*)(guest_code + delta);
-
- /* Various bits of kernel headers use the following as a memory
- barrier. Hence, first emit an MFence and then let the insn
- go through as usual. */
- /* F08344240000: lock addl $0, 0(%esp) */
- if (code[0] == 0xF0 && code[1] == 0x83 && code[2] == 0x44 &&
- code[3] == 0x24 && code[4] == 0x00 && code[5] == 0x00) {
- stmt( IRStmt_MFence() );
+ /* Sun's JVM 1.5.0 uses the following as a NOP:
+ 26 2E 64 65 90 %es:%cs:%fs:%gs:nop */
+ if (code[0] == 0x26 && code[1] == 0x2E && code[2] == 0x64
+ && code[3] == 0x65 && code[4] == 0x90) {
+ DIP("%%es:%%cs:%%fs:%%gs:nop\n");
+ delta += 5;
+ goto decode_success;
}
- else
- if (0) {
- vex_printf("vex x86->IR: ignoring LOCK prefix on: ");
- /* insn_verbose = True; */
+ /* don't barf on recent binutils padding
+ 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%eax,%eax,1) */
+ if (code[0] == 0x66
+ && code[1] == 0x2E && code[2] == 0x0F && code[3] == 0x1F
+ && code[4] == 0x84 && code[5] == 0x00 && code[6] == 0x00
+ && code[7] == 0x00 && code[8] == 0x00 && code[9] == 0x00 ) {
+ DIP("nopw %%cs:0x0(%%eax,%%eax,1)\n");
+ delta += 10;
+ goto decode_success;
}
+ }
- /* In any case, skip the prefix. */
- delta++;
- }
+ /* Normal instruction handling starts here. */
- /* Detect operand-size overrides. It is possible for more than one
- 0x66 to appear. */
- while (getIByte(delta) == 0x66) { sz = 2; delta++; };
-
- /* segment override prefixes come after the operand-size override,
- it seems */
- switch (getIByte(delta)) {
- case 0x3E: /* %DS: */
- case 0x26: /* %ES: */
- /* Sun's JVM 1.5.0 uses the following as a NOP:
- 26 2E 64 65 90 %es:%cs:%fs:%gs:nop */
- {
- UChar* code = (UChar*)(guest_code + delta);
- if (code[0] == 0x26 && code[1] == 0x2E && code[2] == 0x64
- && code[3] == 0x65 && code[4] == 0x90) {
- DIP("%%es:%%cs:%%fs:%%gs:nop\n");
- delta += 5;
- goto decode_success;
- }
- /* else fall through */
- }
- case 0x64: /* %FS: */
- case 0x65: /* %GS: */
- sorb = getIByte(delta); delta++;
- break;
- case 0x2E: /* %CS: */
- /* 2E prefix on a conditional branch instruction is a
- branch-prediction hint, which can safely be ignored. */
- {
+ /* Deal with some but not all prefixes:
+ 66(oso)
+ F0(lock)
+ 2E(cs:) 3E(ds:) 26(es:) 64(fs:) 65(gs:) 36(ss:)
+ Not dealt with (left in place):
+ F2 F3
+ */
+ n_prefixes = 0;
+ while (True) {
+ if (n_prefixes > 7) goto decode_failure;
+ pre = getUChar(delta);
+ switch (pre) {
+ case 0x66:
+ sz = 2;
+ break;
+ case 0xF0:
+ pfx_lock = True;
+ break;
+ case 0x3E: /* %DS: */
+ case 0x26: /* %ES: */
+ case 0x64: /* %FS: */
+ case 0x65: /* %GS: */
+ if (sorb != 0)
+ goto decode_failure; /* only one seg override allowed */
+ sorb = pre;
+ break;
+ case 0x2E: { /* %CS: */
+ /* 2E prefix on a conditional branch instruction is a
+ branch-prediction hint, which can safely be ignored. */
UChar op1 = getIByte(delta+1);
UChar op2 = getIByte(delta+2);
if ((op1 >= 0x70 && op1 <= 0x7F)
|| (op1 == 0xE3)
|| (op1 == 0x0F && op2 >= 0x80 && op2 <= 0x8F)) {
if (0) vex_printf("vex x86->IR: ignoring branch hint\n");
- sorb = getIByte(delta); delta++;
- break;
+ } else {
+ /* All other CS override cases are not handled */
+ goto decode_failure;
}
+ break;
}
- /* don't barf on recent binutils padding
- 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%eax,%eax,1)
- */
- {
- UChar* code = (UChar*)(guest_code + delta);
- if (sz == 2
- && code[-1] == 0x66
- && code[0] == 0x2E && code[1] == 0x0F && code[2] == 0x1F
- && code[3] == 0x84 && code[4] == 0x00 && code[5] == 0x00
- && code[6] == 0x00 && code[7] == 0x00 && code[8] == 0x00 ) {
- DIP("nopw %%cs:0x0(%%eax,%%eax,1)\n");
- delta += 9;
- goto decode_success;
- }
- }
- /* All other CS override cases are not handled */
+ case 0x36: /* %SS: */
+ /* SS override cases are not handled */
+ goto decode_failure;
+ default:
+ goto not_a_prefix;
+ }
+ n_prefixes++;
+ delta++;
+ }
+
+ not_a_prefix:
+
+ /* Now we should be looking at the primary opcode byte or the
+ leading F2 or F3. Check that any LOCK prefix is actually
+ allowed. */
+
+ /* Kludge re LOCK prefixes. We assume here that all code generated
+ by Vex is going to be run in a single-threaded context, in other
+ words that concurrent executions of Vex-generated translations
+ will not happen. So we don't need to worry too much about
+ preserving atomicity. However, mark the fact that the notional
+ hardware bus lock is being acquired (and, after the insn,
+ released), so that thread checking tools know this is a locked
+ insn.
+
+ We check for, and immediately reject, (most) inappropriate uses
+ of the LOCK prefix. Later (at decode_failure: and
+ decode_success:), if we've added a BusLock event, then we will
+ follow up with a BusUnlock event. How do we know execution will
+ actually ever get to the BusUnlock event? Because
+ can_be_used_with_LOCK_prefix rejects all control-flow changing
+ instructions.
+
+ One loophole, though: if a LOCK prefix insn (seg)faults, then
+ the BusUnlock event will never be reached. This could cause
+ tools which track bus hardware lock to lose track. Really, we
+ should explicitly release the lock after every insn, but that's
+ obviously way too expensive. Really, any tool which tracks the
+ state of the bus lock needs to ask V's core/tool interface to
+ notify it of signal deliveries. On delivery of SIGSEGV to the
+ guest, the tool will be notified, in which case it should
+ release the bus hardware lock if it is held.
+
+ Note, guest-amd64/toIR.c contains identical logic.
+ */
+ if (pfx_lock) {
+ if (can_be_used_with_LOCK_prefix( (UChar*)&guest_code[delta] )) {
+ stmt( IRStmt_MBE(Imbe_BusLock) );
+ unlock_bus_after_insn = True;
+ DIP("lock ");
+ } else {
goto decode_failure;
- case 0x36: /* %SS: */
- /* SS override cases are not handled */
- goto decode_failure;
- default:
- break;
+ }
}
+
/* ---------------------------------------------------- */
/* --- The SSE decoder. --- */
/* ---------------------------------------------------- */
@@ -8324,7 +8446,7 @@
delta += 3;
/* Insert a memory fence. It's sometimes important that these
are carried through to the generated code. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("sfence\n");
goto decode_success;
}
@@ -9104,7 +9226,7 @@
delta += 3;
/* Insert a memory fence. It's sometimes important that these
are carried through to the generated code. */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("%sfence\n", gregOfRM(insn[2])==5 ? "l" : "m");
goto decode_success;
}
@@ -12184,6 +12306,12 @@
/* ------------------------ XCHG ----------------------- */
+ /* XCHG reg,mem automatically asserts LOCK# even without a LOCK
+ prefix. Therefore, surround it with a IRStmt_MBE(Imbe_BusLock)
+ and IRStmt_MBE(Imbe_BusUnlock) pair. But be careful; if it is
+ used with an explicit LOCK prefix, we don't want to end up with
+ two IRStmt_MBE(Imbe_BusLock)s -- one made here and one made by
+ the generic LOCK logic at the top of disInstr. */
case 0x86: /* XCHG Gb,Eb */
sz = 1;
/* Fall through ... */
@@ -12201,6 +12329,18 @@
nameISize(sz), nameIReg(sz,gregOfRM(modrm)),
nameIReg(sz,eregOfRM(modrm)));
} else {
+ /* Need to add IRStmt_MBE(Imbe_BusLock). */
+ if (pfx_lock) {
+ /* check it's already been taken care of */
+ vassert(unlock_bus_after_insn);
+ } else {
+ vassert(!unlock_bus_after_insn);
+ stmt( IRStmt_MBE(Imbe_BusLock) );
+ unlock_bus_after_insn = True;
+ }
+ /* Because unlock_bus_after_insn is now True, generic logic
+ at the bottom of disInstr will add the
+ IRStmt_MBE(Imbe_BusUnlock). */
addr = disAMode ( &alen, sorb, delta, dis_buf );
assign( t1, loadLE(ty,mkexpr(addr)) );
assign( t2, getIReg(sz,gregOfRM(modrm)) );
@@ -12699,7 +12839,7 @@
stmt( IRStmt_Dirty(d) );
/* CPUID is a serialising insn. So, just in case someone is
using it as a memory fence ... */
- stmt( IRStmt_MFence() );
+ stmt( IRStmt_MBE(Imbe_Fence) );
DIP("cpuid\n");
break;
}
@@ -13086,6 +13226,8 @@
insn, but nevertheless be paranoid and update it again right
now. */
stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr) ) );
+ if (unlock_bus_after_insn)
+ stmt( IRStmt_MBE(Imbe_BusUnlock) );
jmp_lit(Ijk_NoDecode, guest_EIP_curr_instr);
dres.whatNext = Dis_StopHere;
dres.len = 0;
@@ -13096,7 +13238,8 @@
decode_success:
/* All decode successes end up here. */
DIP("\n");
-
+ if (unlock_bus_after_insn)
+ stmt( IRStmt_MBE(Imbe_BusUnlock) );
dres.len = delta - delta_start;
return dres;
}
Modified: trunk/priv/host-amd64/isel.c
===================================================================
--- trunk/priv/host-amd64/isel.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/host-amd64/isel.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -3763,9 +3763,18 @@
}
/* --------- MEM FENCE --------- */
- case Ist_MFence:
- addInstr(env, AMD64Instr_MFence());
- return;
+ case Ist_MBE:
+ switch (stmt->Ist.MBE.event) {
+ case Imbe_Fence:
+ addInstr(env, AMD64Instr_MFence());
+ return;
+ case Imbe_BusLock:
+ case Imbe_BusUnlock:
+ return;
+ default:
+ break;
+ }
+ break;
/* --------- INSTR MARK --------- */
/* Doesn't generate any executable code ... */
Modified: trunk/priv/host-ppc/isel.c
===================================================================
--- trunk/priv/host-ppc/isel.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/host-ppc/isel.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -3866,9 +3866,18 @@
}
/* --------- MEM FENCE --------- */
- case Ist_MFence:
- addInstr(env, PPCInstr_MFence());
- return;
+ case Ist_MBE:
+ switch (stmt->Ist.MBE.event) {
+ case Imbe_Fence:
+ addInstr(env, PPCInstr_MFence());
+ return;
+ case Imbe_BusLock:
+ case Imbe_BusUnlock:
+ return;
+ default:
+ break;
+ }
+ break;
/* --------- INSTR MARK --------- */
/* Doesn't generate any executable code ... */
Modified: trunk/priv/host-x86/isel.c
===================================================================
--- trunk/priv/host-x86/isel.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/host-x86/isel.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -3802,9 +3802,18 @@
}
/* --------- MEM FENCE --------- */
- case Ist_MFence:
- addInstr(env, X86Instr_MFence(env->hwcaps));
- return;
+ case Ist_MBE:
+ switch (stmt->Ist.MBE.event) {
+ case Imbe_Fence:
+ addInstr(env, X86Instr_MFence(env->hwcaps));
+ return;
+ case Imbe_BusLock:
+ case Imbe_BusUnlock:
+ return;
+ default:
+ break;
+ }
+ break;
/* --------- INSTR MARK --------- */
/* Doesn't generate any executable code ... */
Modified: trunk/priv/ir/irdefs.c
===================================================================
--- trunk/priv/ir/irdefs.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/ir/irdefs.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -736,6 +736,16 @@
}
}
+void ppIRMBusEvent ( IRMBusEvent event )
+{
+ switch (event) {
+ case Imbe_Fence: vex_printf("Fence"); break;
+ case Imbe_BusLock: vex_printf("BusLock"); break;
+ case Imbe_BusUnlock: vex_printf("BusUnlock"); break;
+ default: vpanic("ppIRMBusEvent");
+ }
+}
+
void ppIRStmt ( IRStmt* s )
{
if (!s) {
@@ -781,8 +791,9 @@
case Ist_Dirty:
ppIRDirty(s->Ist.Dirty.details);
break;
- case Ist_MFence:
- vex_printf("IR-MFence");
+ case Ist_MBE:
+ vex_printf("IR-");
+ ppIRMBusEvent(s->Ist.MBE.event);
break;
case Ist_Exit:
vex_printf( "if (" );
@@ -1186,12 +1197,12 @@
s->Ist.Dirty.details = d;
return s;
}
-IRStmt* IRStmt_MFence ( void )
+IRStmt* IRStmt_MBE ( IRMBusEvent event )
{
- /* Just use a single static closure. */
- static IRStmt static_closure;
- static_closure.tag = Ist_MFence;
- return &static_closure;
+ IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
+ s->tag = Ist_MBE;
+ s->Ist.MBE.event = event;
+ return s;
}
IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst ) {
IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
@@ -1387,8 +1398,8 @@
deepCopyIRExpr(s->Ist.Store.data));
case Ist_Dirty:
return IRStmt_Dirty(deepCopyIRDirty(s->Ist.Dirty.details));
- case Ist_MFence:
- return IRStmt_MFence();
+ case Ist_MBE:
+ return IRStmt_MBE(s->Ist.MBE.event);
case Ist_Exit:
return IRStmt_Exit(deepCopyIRExpr(s->Ist.Exit.guard),
s->Ist.Exit.jk,
@@ -2021,7 +2032,7 @@
return True;
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
return True;
case Ist_Exit:
return isIRAtom(st->Ist.Exit.guard);
@@ -2196,7 +2207,7 @@
useBeforeDef_Expr(bb,stmt,d->mAddr,def_counts);
break;
case Ist_NoOp:
- case Ist_MFence:
+ case Ist_MBE:
break;
case Ist_Exit:
useBeforeDef_Expr(bb,stmt,stmt->Ist.Exit.guard,def_counts);
@@ -2500,8 +2511,15 @@
bad_dirty:
sanityCheckFail(bb,stmt,"IRStmt.Dirty: ill-formed");
case Ist_NoOp:
- case Ist_MFence:
break;
+ case Ist_MBE:
+ switch (stmt->Ist.MBE.event) {
+ case Imbe_Fence: case Imbe_BusLock: case Imbe_BusUnlock:
+ break;
+ default: sanityCheckFail(bb,stmt,"IRStmt.MBE.event: unknown");
+ break;
+ }
+ break;
case Ist_Exit:
tcExpr( bb, stmt, stmt->Ist.Exit.guard, gWordTy );
if (typeOfIRExpr(tyenv,stmt->Ist.Exit.guard) != Ity_I1)
Modified: trunk/priv/ir/iropt.c
===================================================================
--- trunk/priv/ir/iropt.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/priv/ir/iropt.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -442,7 +442,7 @@
addStmtToIRSB(bb, IRStmt_Dirty(d2));
break;
case Ist_NoOp:
- case Ist_MFence:
+ case Ist_MBE:
case Ist_IMark:
addStmtToIRSB(bb, st);
break;
@@ -708,11 +708,12 @@
crude solution is just to flush everything; we could easily
enough do a lot better if needed. */
/* Probably also overly-conservative, but also dump everything
- if we hit a memory fence. Ditto AbiHints.*/
+ if we hit a memory bus event (fence, lock, unlock). Ditto
+ AbiHints.*/
case Ist_AbiHint:
vassert(isIRAtom(st->Ist.AbiHint.base));
/* fall through */
- case Ist_MFence:
+ case Ist_MBE:
case Ist_Dirty:
for (j = 0; j < env->used; j++)
env->inuse[j] = False;
@@ -1760,8 +1761,8 @@
case Ist_NoOp:
return IRStmt_NoOp();
- case Ist_MFence:
- return IRStmt_MFence();
+ case Ist_MBE:
+ return IRStmt_MBE(st->Ist.MBE.event);
case Ist_Exit: {
IRExpr* fcond;
@@ -1967,7 +1968,7 @@
return;
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
return;
case Ist_Exit:
addUses_Expr(set, st->Ist.Exit.guard);
@@ -2535,7 +2536,7 @@
/* ------ BEGIN invalidate aenv bindings ------ */
/* This is critical: remove from aenv any E' -> .. bindings
which might be invalidated by this statement. The only
- vulnerable kind of bindings are the GetIt kind.
+ vulnerable kind of bindings are the GetI kind.
Dirty call - dump (paranoia level -> 2)
Store - dump (ditto)
Put, PutI - dump unless no-overlap is proven (.. -> 1)
@@ -2543,12 +2544,12 @@
to do the no-overlap assessments needed for Put/PutI.
*/
switch (st->tag) {
- case Ist_Dirty: case Ist_Store:
+ case Ist_Dirty: case Ist_Store: case Ist_MBE:
paranoia = 2; break;
case Ist_Put: case Ist_PutI:
paranoia = 1; break;
case Ist_NoOp: case Ist_IMark: case Ist_AbiHint:
- case Ist_WrTmp: case Ist_MFence: case Ist_Exit:
+ case Ist_WrTmp: case Ist_Exit:
paranoia = 0; break;
default:
vpanic("do_cse_BB(1)");
@@ -2963,7 +2964,7 @@
case Ist_IMark:
return False;
- case Ist_MFence:
+ case Ist_MBE:
case Ist_AbiHint:
/* just be paranoid ... these should be rare. */
return True;
@@ -3206,7 +3207,7 @@
switch (st->tag) {
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
break;
case Ist_AbiHint:
deltaIRExpr(st->Ist.AbiHint.base, delta);
@@ -3691,7 +3692,7 @@
return;
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
return;
case Ist_Exit:
aoccCount_Expr(uses, st->Ist.Exit.guard);
@@ -3933,8 +3934,8 @@
return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
case Ist_NoOp:
return IRStmt_NoOp();
- case Ist_MFence:
- return IRStmt_MFence();
+ case Ist_MBE:
+ return IRStmt_MBE(st->Ist.MBE.event);
case Ist_Dirty:
d = st->Ist.Dirty.details;
d2 = emptyIRDirty();
@@ -4093,11 +4094,11 @@
question is marked as requiring precise
exceptions. */
|| (env[k].doesLoad && stmtPuts)
- /* probably overly conservative: a memory fence
+ /* probably overly conservative: a memory bus event
invalidates absolutely everything, so that all
computation prior to it is forced to complete before
- proceeding with the fence. */
- || st->tag == Ist_MFence
+ proceeding with the event (fence,lock,unlock). */
+ || st->tag == Ist_MBE
/* also be (probably overly) paranoid re AbiHints */
|| st->tag == Ist_AbiHint
);
@@ -4265,7 +4266,7 @@
break;
case Ist_NoOp:
case Ist_IMark:
- case Ist_MFence:
+ case Ist_MBE:
break;
case Ist_Exit:
vassert(isIRAtom(st->Ist.Exit.guard));
Modified: trunk/pub/libvex_ir.h
===================================================================
--- trunk/pub/libvex_ir.h 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/pub/libvex_ir.h 2007-11-09 21:15:04 UTC (rev 1793)
@@ -229,8 +229,8 @@
float, or a vector (SIMD) value. */
typedef
enum {
- Ity_INVALID=0x10FFF,
- Ity_I1=0x11000,
+ Ity_INVALID=0x11000,
+ Ity_I1,
Ity_I8,
Ity_I16,
Ity_I32,
@@ -254,8 +254,8 @@
/* IREndness is used in load IRExprs and store IRStmts. */
typedef
enum {
- Iend_LE=22, /* little endian */
- Iend_BE=33 /* big endian */
+ Iend_LE=0x12000, /* little endian */
+ Iend_BE /* big endian */
}
IREndness;
@@ -267,7 +267,7 @@
/* The various kinds of constant. */
typedef
enum {
- Ico_U1=0x12000,
+ Ico_U1=0x13000,
Ico_U8,
Ico_U16,
Ico_U32,
@@ -406,7 +406,7 @@
/* -- Do not change this ordering. The IR generators rely on
(eg) Iop_Add64 == IopAdd8 + 3. -- */
- Iop_INVALID=0x13000,
+ Iop_INVALID=0x14000,
Iop_Add8, Iop_Add16, Iop_Add32, Iop_Add64,
Iop_Sub8, Iop_Sub16, Iop_Sub32, Iop_Sub64,
/* Signless mul. MullS/MullU is elsewhere. */
@@ -884,7 +884,7 @@
in the comments for IRExpr. */
typedef
enum {
- Iex_Binder,
+ Iex_Binder=0x15000,
Iex_Get,
Iex_GetI,
Iex_RdTmp,
@@ -1181,7 +1181,7 @@
*/
typedef
enum {
- Ijk_Boring=0x14000, /* not interesting; just goto next */
+ Ijk_Boring=0x16000, /* not interesting; just goto next */
Ijk_Call, /* guest is doing a call */
Ijk_Ret, /* guest is doing a return */
Ijk_ClientReq, /* do guest client req before continuing */
@@ -1254,7 +1254,7 @@
/* Effects on resources (eg. registers, memory locations) */
typedef
enum {
- Ifx_None = 0x15000, /* no effect */
+ Ifx_None = 0x17000, /* no effect */
Ifx_Read, /* reads the resource */
Ifx_Write, /* writes the resource */
Ifx_Modify, /* modifies the resource */
@@ -1316,6 +1316,19 @@
IRExpr** args );
+/* --------------- Memory Bus Events --------------- */
+
+typedef
+ enum {
+ Imbe_Fence=0x18000,
+ Imbe_BusLock,
+ Imbe_BusUnlock
+ }
+ IRMBusEvent;
+
+extern void ppIRMBusEvent ( IRMBusEvent );
+
+
/* ------------------ Statements ------------------ */
/* The different kinds of statements. Their meaning is explained
@@ -1327,9 +1340,10 @@
they are required by some IR consumers such as tools that
instrument the code.
*/
+
typedef
enum {
- Ist_NoOp,
+ Ist_NoOp=0x19000,
Ist_IMark, /* META */
Ist_AbiHint, /* META */
Ist_Put,
@@ -1337,7 +1351,7 @@
Ist_WrTmp,
Ist_Store,
Ist_Dirty,
- Ist_MFence,
+ Ist_MBE, /* META (maybe) */
Ist_Exit
}
IRStmtTag;
@@ -1452,11 +1466,15 @@
IRDirty* details;
} Dirty;
- /* A memory fence.
- ppIRExpr output: IR-MFence
+ /* A memory bus event - a fence, or acquisition/release of the
+ hardware bus lock. IR optimisation treats all these as fences
+ across which no memory references may be moved.
+ ppIRExpr output: MBusEvent-Fence,
+ MBusEvent-BusLock, MBusEvent-BusUnlock.
*/
struct {
- } MFence;
+ IRMBusEvent event;
+ } MBE;
/* Conditional exit from the middle of an IRSB.
ppIRExpr output: if (<guard>) goto {<jk>} <dst>
@@ -1481,7 +1499,7 @@
extern IRStmt* IRStmt_WrTmp ( IRTemp tmp, IRExpr* data );
extern IRStmt* IRStmt_Store ( IREndness end, IRExpr* addr, IRExpr* data );
extern IRStmt* IRStmt_Dirty ( IRDirty* details );
-extern IRStmt* IRStmt_MFence ( void );
+extern IRStmt* IRStmt_MBE ( IRMBusEvent event );
extern IRStmt* IRStmt_Exit ( IRExpr* guard, IRJumpKind jk, IRConst* dst );
/* Deep-copy an IRStmt. */
Modified: trunk/test_main.c
===================================================================
--- trunk/test_main.c 2007-11-06 20:39:17 UTC (rev 1792)
+++ trunk/test_main.c 2007-11-09 21:15:04 UTC (rev 1793)
@@ -127,7 +127,8 @@
/* FIXME: put sensible values into the .hwcaps fields */
LibVEX_default_VexArchInfo(&vai_x86);
- vai_x86.hwcaps = 0;
+ vai_x86.hwcaps = VEX_HWCAPS_X86_SSE1
+ | VEX_HWCAPS_X86_SSE2 | VEX_HWCAPS_X86_SSE3;
LibVEX_default_VexArchInfo(&vai_amd64);
vai_amd64.hwcaps = 0;
@@ -139,7 +140,7 @@
LibVEX_default_VexAbiInfo(&vbi);
/* ----- Set up args for LibVEX_Translate ----- */
-#if 1 /* ppc32 -> ppc32 */
+#if 0 /* ppc32 -> ppc32 */
vta.arch_guest = VexArchPPC32;
vta.archinfo_guest = vai_ppc32;
vta.arch_host = VexArchPPC32;
@@ -151,7 +152,7 @@
vta.arch_host = VexArchAMD64;
vta.archinfo_host = vai_amd64;
#endif
-#if 0 /* x86 -> x86 */
+#if 1 /* x86 -> x86 */
vta.arch_guest = VexArchX86;
vta.archinfo_guest = vai_x86;
vta.arch_host = VexArchX86;
@@ -187,6 +188,8 @@
vta.dispatch = NULL;
#endif
+ vta.finaltidy = NULL;
+
for (i = 0; i < TEST_N_ITERS; i++)
tres = LibVEX_Translate ( &vta );
|
|
From: <sv...@va...> - 2007-11-09 21:07:32
|
Author: sewardj
Date: 2007-11-09 21:07:31 +0000 (Fri, 09 Nov 2007)
New Revision: 7115
Log:
Fix tag.
Modified:
trunk/massif/docs/ms-manual.xml
Modified: trunk/massif/docs/ms-manual.xml
===================================================================
--- trunk/massif/docs/ms-manual.xml 2007-11-09 15:46:37 UTC (rev 7114)
+++ trunk/massif/docs/ms-manual.xml 2007-11-09 21:07:31 UTC (rev 7115)
@@ -6,7 +6,7 @@
<chapter id="ms-manual" xreflabel="Massif: a heap profiler">
<title>Massif: a heap profiler</title>
-</pre>
+<pre>
Docs:
- Mention that complex functions names are best protected with single
quotes, eg:
|
|
From: <sv...@va...> - 2007-11-09 15:46:34
|
Author: sewardj
Date: 2007-11-09 15:46:37 +0000 (Fri, 09 Nov 2007)
New Revision: 7114
Log:
Minor changes.
Modified:
branches/THRCHECK/thrcheck/docs/tc-manual.xml
Modified: branches/THRCHECK/thrcheck/docs/tc-manual.xml
===================================================================
--- branches/THRCHECK/thrcheck/docs/tc-manual.xml 2007-11-09 15:44:15 UTC (rev 7113)
+++ branches/THRCHECK/thrcheck/docs/tc-manual.xml 2007-11-09 15:46:37 UTC (rev 7114)
@@ -179,7 +179,7 @@
<para>Thrcheck builds a directed graph indicating the order in which
locks have been acquired in the past. When a thread acquires a new
lock, the graph is updated, and then checked to see if it now contains
-a cycle. Presence of a cycle indicates a potential deadlock involving
+a cycle. The presence of a cycle indicates a potential deadlock involving
the locks in the cycle.</para>
<para>In simple situations, where the cycle only contains two locks,
@@ -544,11 +544,12 @@
<para>This program is correct, but using only the mechanisms described
so far, Thrcheck would report an error at
-<computeroutput>var += 4;</computeroutput>. This is because, by that
+<computeroutput>var += 4</computeroutput>. This is because, by that
point, <computeroutput>var</computeroutput> is marked as being in the
-state "shared-modified with a singleton
-lockset <computeroutput>{mx}</computeroutput>". Really, what we want
-is for <computeroutput>var</computeroutput> to return to the parent
+state "shared-modified and protected by the
+lock <computeroutput>mx</computeroutput>", but is being accessed
+without locking. Really, what we want is
+for <computeroutput>var</computeroutput> to return to the parent
thread's exclusive ownership after the child thread has exited.</para>
<para>To make this possible, for every memory location Thrcheck also keeps
|
|
From: <sv...@va...> - 2007-11-09 15:44:27
|
Author: sewardj Date: 2007-11-09 15:44:15 +0000 (Fri, 09 Nov 2007) New Revision: 7113 Log: Rename this directory. Added: trunk/old-helgrind/ Removed: trunk/helgrind/ Copied: trunk/old-helgrind (from rev 7110, trunk/helgrind) |