1f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
2f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
3f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- Error management for Helgrind.                               ---*/
4f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*---                                                  hg_errors.c ---*/
5f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
6f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
7f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*
8f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This file is part of Helgrind, a Valgrind tool for detecting errors
9f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   in threaded programs.
10f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
11ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2007-2017 OpenWorks Ltd
12f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      info@open-works.co.uk
13f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
14f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This program is free software; you can redistribute it and/or
15f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   modify it under the terms of the GNU General Public License as
16f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   published by the Free Software Foundation; either version 2 of the
17f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   License, or (at your option) any later version.
18f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
19f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   This program is distributed in the hope that it will be useful, but
20f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   General Public License for more details.
23f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
24f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   You should have received a copy of the GNU General Public License
25f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   along with this program; if not, write to the Free Software
26f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   02111-1307, USA.
28f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
29f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   The GNU General Public License is contained in the file COPYING.
30f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
31f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
32f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_basics.h"
33f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_libcbase.h"
34f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_libcassert.h"
35f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_libcprint.h"
36328d6627c26471332610da3f5a0b9cc3cdd410c7philippe#include "pub_tool_stacktrace.h"
37f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_execontext.h"
38f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_errormgr.h"
39f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_wordfm.h"
40f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_xarray.h"
41f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_debuginfo.h"
42f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "pub_tool_threadstate.h"
4324118491f347852bc311069a273fce13608dd531sewardj#include "pub_tool_options.h"     // VG_(clo_xml)
44f7ec77f53fd09a5682dbe6db049efe0746df7948philippe#include "pub_tool_aspacemgr.h"
4507c08527f05caeb0062b42ca9a58ee774ec5fba1philippe#include "pub_tool_addrinfo.h"
46f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
47f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_basics.h"
48f57743408d27fedf60a7b48d25339d51b1f8a055philippe#include "hg_addrdescr.h"
49f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_wordset.h"
50f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_lock_n_thread.h"
51c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj#include "libhb.h"
52f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#include "hg_errors.h"            /* self */
53f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
54f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
55f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*----------------------------------------------------------------*/
5624118491f347852bc311069a273fce13608dd531sewardj/*--- Error management -- storage                              ---*/
57f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*----------------------------------------------------------------*/
58f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
59f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* maps (by value) strings to a copy of them in ARENA_TOOL */
60f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
61f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic WordFM* string_table = NULL;
62f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
63f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjULong HG_(stats__string_table_queries) = 0;
64f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
65f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjULong HG_(stats__string_table_get_map_size) ( void ) {
66f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return string_table ? (ULong)VG_(sizeFM)(string_table) : 0;
67f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
68f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
69f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Word string_table_cmp ( UWord s1, UWord s2 ) {
70f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
71f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
72f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
7319f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic HChar* string_table_strdup ( const HChar* str ) {
74f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   HChar* copy = NULL;
75f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   HG_(stats__string_table_queries)++;
76f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (!str)
77f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      str = "(null)";
78f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (!string_table) {
79f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1",
80f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                 HG_(free), string_table_cmp );
81f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
82f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (VG_(lookupFM)( string_table,
836bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian                      NULL, (UWord*)&copy, (UWord)str )) {
84f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert(copy);
85f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy );
86f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return copy;
87f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } else {
88f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      copy = HG_(strdup)("hg.sts.2", str);
8919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      VG_(addToFM)( string_table, (UWord)copy, (UWord)copy );
90f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      return copy;
91f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
92f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
93f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
94f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* maps from Lock .unique fields to LockP*s */
95f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
96f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic WordFM* map_LockN_to_P = NULL;
97f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
98f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjULong HG_(stats__LockN_to_P_queries) = 0;
99f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
100f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjULong HG_(stats__LockN_to_P_get_map_size) ( void ) {
101f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0;
102f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
103f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
104f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic Word lock_unique_cmp ( UWord lk1W, UWord lk2W )
105f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
106f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Lock* lk1 = (Lock*)lk1W;
107f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Lock* lk2 = (Lock*)lk2W;
108f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockNorP)(lk1) );
109f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockNorP)(lk2) );
110f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (lk1->unique < lk2->unique) return -1;
111f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (lk1->unique > lk2->unique) return 1;
112f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return 0;
113f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
114f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
115ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Given a normal Lock (LockN), convert it to a persistent Lock
116ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   (LockP).  In some cases the LockN could be invalid (if it's been
117ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   freed), so we enquire, in hg_main.c's admin_locks list, whether it
118ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   is in fact valid.  If allowed_to_be_invalid is True, then it's OK
119ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   for the LockN to be invalid, in which case Lock_INVALID is
120ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   returned.  In all other cases, we insist that the LockN is a valid
121ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   lock, and return its corresponding LockP.
122ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
123ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   Why can LockNs sometimes be invalid?  Because they are harvested
124ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   from locksets that are attached to the OldRef info for conflicting
125ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   threads.  By the time we detect a race, the some of the elements of
126ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   the lockset may have been destroyed by the client, in which case
127ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   the corresponding Lock structures we maintain will have been freed.
128ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
129ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   So we check that each LockN is a member of the admin_locks double
130ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   linked list of all Lock structures.  That stops us prodding around
131ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   in potentially freed-up Lock structures.  However, it's not quite a
132ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   proper check: if a new Lock has been reallocated at the same
133ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   address as one which was previously freed, we'll wind up copying
134ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   the new one as the basis for the LockP, which is completely bogus
135ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   because it is unrelated to the previous Lock that lived there.
136ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   Let's hope that doesn't happen too often.
137ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj*/
138ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic Lock* mk_LockP_from_LockN ( Lock* lkn,
139ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                   Bool allowed_to_be_invalid )
140f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
141f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   Lock* lkp = NULL;
142f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   HG_(stats__LockN_to_P_queries)++;
143ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
144ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   /* First off, let's do some sanity checks.  If
145ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      allowed_to_be_invalid is False, we _must_ be able to find 'lkn'
146ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      in admin_locks; else we must assert.  If it is True, it's OK for
147ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      it not to be findable, but in that case we must return
148ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      Lock_INVALID right away. */
149ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   Lock* lock_list = HG_(get_admin_locks)();
150ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   while (lock_list) {
151ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      if (lock_list == lkn)
152ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         break;
153ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      lock_list = lock_list->admin_next;
154ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
155ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (lock_list == NULL) {
156ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      /* We didn't find it.  That possibility has to be OK'd by the
157ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         caller. */
158ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      tl_assert(allowed_to_be_invalid);
159ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      return Lock_INVALID;
160ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
161ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
162ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   /* So we must be looking at a valid LockN. */
163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockN)(lkn) );
164ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (!map_LockN_to_P) {
166f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1",
167f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                   HG_(free), lock_unique_cmp );
168f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1696bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian   if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) {
170f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) );
171f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      *lkp = *lkn;
1721d7c3322207f80d9a962a402a171a14e4d628a77sewardj      lkp->admin_next = NULL;
1731d7c3322207f80d9a962a402a171a14e4d628a77sewardj      lkp->admin_prev = NULL;
174f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp->magic = LockP_MAGIC;
175f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* Forget about the bag of lock holders - don't copy that.
176f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         Also, acquired_at should be NULL whenever heldBy is, and vice
177f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         versa.  Also forget about the associated libhb synch object. */
178f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp->heldW  = False;
179f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp->heldBy = NULL;
180f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp->acquired_at = NULL;
181f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      lkp->hbso = NULL;
1826bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian      VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp );
183f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
184f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockP)(lkp) );
185f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return lkp;
186f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
187f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
188f631b021ceaf3a2fd3908a413255c3d82b88dea5florianstatic Int sort_by_guestaddr(const void* n1, const void* n2)
189f631b021ceaf3a2fd3908a413255c3d82b88dea5florian{
190f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   const Lock* l1 = *(const Lock *const *)n1;
191f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   const Lock* l2 = *(const Lock *const *)n2;
192f631b021ceaf3a2fd3908a413255c3d82b88dea5florian
193f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   Addr a1 = l1 == Lock_INVALID ? 0 : l1->guestaddr;
194f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   Addr a2 = l2 == Lock_INVALID ? 0 : l2->guestaddr;
195f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   if (a1 < a2) return -1;
196f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   if (a1 > a2) return 1;
197f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   return 0;
198f631b021ceaf3a2fd3908a413255c3d82b88dea5florian}
199f631b021ceaf3a2fd3908a413255c3d82b88dea5florian
200ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Expand a WordSet of LockN*'s into a NULL-terminated vector of
201ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   LockP*'s.  Any LockN's that can't be converted into a LockP
202ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   (because they have been freed, see comment on mk_LockP_from_LockN)
203ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   are converted instead into the value Lock_INVALID.  Hence the
204ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   returned vector is a sequence: zero or more (valid LockP* or
205ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   LockN_INVALID), terminated by a NULL. */
206ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic
207ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjLock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets,
208ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                            WordSetID lockset,
209ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                            Bool allowed_to_be_invalid )
210ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
211ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(univ_lsets);
212ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert( HG_(plausibleWS)(univ_lsets, lockset) );
213ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord  nLocks = HG_(cardinalityWS)(univ_lsets, lockset);
214ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa",
215ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                (nLocks+1) * sizeof(Lock*) );
216ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */
217ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord* lockNs  = NULL;
218ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord  nLockNs = 0;
219ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (nLocks > 0)  {
220ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the
221ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         lockset is empty; hence the guarding "if".  Sigh. */
222ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset );
223ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      tl_assert(lockNs);
224ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
225ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord i;
226ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   /* Convert to LockPs. */
227ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   for (i = 0; i < nLockNs; i++) {
228ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i],
229ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                       allowed_to_be_invalid );
230ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
231f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   /* Sort the locks by increasing Lock::guestaddr to avoid jitters
232f631b021ceaf3a2fd3908a413255c3d82b88dea5florian      in the output. */
233f631b021ceaf3a2fd3908a413255c3d82b88dea5florian   VG_(ssort)(lockPs, nLockNs, sizeof lockPs[0], sort_by_guestaddr);
234f631b021ceaf3a2fd3908a413255c3d82b88dea5florian
235ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   return lockPs;
236ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
237ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
238ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Get the number of useful elements in a vector created by
239ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   enumerate_WordSet_into_LockP_vector.  Returns both the total number
240ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   of elements (not including the terminating NULL) and the number of
241ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   non-Lock_INVALID elements. */
242ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic void count_LockP_vector ( /*OUT*/UWord* nLocks,
243ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                 /*OUT*/UWord* nLocksValid,
244ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                 Lock** vec )
245ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
246ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(vec);
247ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   *nLocks = *nLocksValid = 0;
248ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord n = 0;
249ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   while (vec[n]) {
250ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      (*nLocks)++;
251ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      if (vec[n] != Lock_INVALID)
252ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         (*nLocksValid)++;
253ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      n++;
254ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
255ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
256ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
257ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Find out whether 'lk' is in 'vec'. */
258ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic Bool elem_LockP_vector ( Lock** vec, Lock* lk )
259ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
260ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(vec);
261ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(lk);
262ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord n = 0;
263ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   while (vec[n]) {
264ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      if (vec[n] == lk)
265ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         return True;
266ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      n++;
267ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
268ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   return False;
269ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
270ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
271ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
272f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Errors:
273f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
274f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      race: program counter
275f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            read or write
276f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            data size
277f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            previous state
278f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            current state
279f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
280f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      FIXME: how does state printing interact with lockset gc?
281f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Are the locksets in prev/curr state always valid?
282f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Ditto question for the threadsets
283f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          ThreadSets - probably are always valid if Threads
284f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          are never thrown away.
285f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          LockSets - could at least print the lockset elements that
286f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj          correspond to actual locks at the time of printing.  Hmm.
287f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj*/
288f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
289f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Error kinds */
290f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
291f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   enum {
292f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_Race=1101,      // race
293f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_UnlockUnlocked, // unlocking a not-locked lock
294f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_UnlockForeign,  // unlocking a lock held by some other thread
295f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_UnlockBogus,    // unlocking an address not known to be a lock
296f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_PthAPIerror,    // error from the POSIX pthreads API
297f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_LockOrder,      // lock order error
298f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XE_Misc            // misc other error (w/ string to describe it)
299f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
300f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XErrorTag;
301f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
302f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Extra contexts for kinds */
303f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
304f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   struct  {
305f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XErrorTag tag;
306f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      union {
307f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
30823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Addr        data_addr;
30923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Int         szB;
31007c08527f05caeb0062b42ca9a58ee774ec5fba1philippe            AddrInfo    data_addrinfo;
31123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Bool        isWrite;
31223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Thread*     thr;
313ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            Lock**      locksHeldW;
314095d61eef541731e77e2c648983aee9ea2bf5e59sewardj            /* h1_* and h2_* provide some description of a previously
315095d61eef541731e77e2c648983aee9ea2bf5e59sewardj               observed access with which we are conflicting. */
31623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Thread*     h1_ct; /* non-NULL means h1 info present */
31723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            ExeContext* h1_ct_mbsegstartEC;
31823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            ExeContext* h1_ct_mbsegendEC;
31923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Thread*     h2_ct; /* non-NULL means h2 info present */
32023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            ExeContext* h2_ct_accEC;
32123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Int         h2_ct_accSzB;
32223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Bool        h2_ct_accIsW;
323ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            Lock**      h2_ct_locksHeldW;
324f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } Race;
325f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
326f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread* thr;  /* doing the unlocking */
327f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Lock*   lock; /* lock (that is already unlocked) */
328f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } UnlockUnlocked;
329f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
330f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread* thr;    /* doing the unlocking */
331f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread* owner;  /* thread that actually holds the lock */
332f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Lock*   lock;   /* lock (that is held by 'owner') */
333f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } UnlockForeign;
334f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
335f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread* thr;     /* doing the unlocking */
336f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Addr    lock_ga; /* purported address of the lock */
337f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } UnlockBogus;
338f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
339f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread* thr;
340f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            HChar*  fnname; /* persistent, in tool-arena */
341f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Word    err;    /* pth error code */
342f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            HChar*  errstr; /* persistent, in tool-arena */
343f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } PthAPIerror;
344f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
345f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj            Thread*     thr;
346ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            /* The first 4 fields describe the previously observed
347ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               (should-be) ordering. */
34846daf0d598c38c9251964712d894f0fcd3cc4143philippe            Lock*       shouldbe_earlier_lk;
34946daf0d598c38c9251964712d894f0fcd3cc4143philippe            Lock*       shouldbe_later_lk;
350ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            ExeContext* shouldbe_earlier_ec;
351ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            ExeContext* shouldbe_later_ec;
352ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            /* In principle we need to record two more stacks, from
353ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               this thread, when acquiring the locks in the "wrong"
354ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               order.  In fact the wallclock-later acquisition by this
355ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               thread is recorded in the main stack for this error.
356ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               So we only need a stack for the earlier acquisition by
357ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               this thread. */
358ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            ExeContext* actual_earlier_ec;
359f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } LockOrder;
360f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         struct {
3618fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            Thread*     thr;
3628fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            HChar*      errstr; /* persistent, in tool-arena */
3638fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            HChar*      auxstr; /* optional, persistent, in tool-arena */
3648fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            ExeContext* auxctx; /* optional */
365f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         } Misc;
366f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      } XE;
367f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
368f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError;
369f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
370f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjstatic void init_XError ( XError* xe ) {
371f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(memset)(xe, 0, sizeof(*xe) );
372f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe->tag = XE_Race-1; /* bogus */
373f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
374f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
375f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
376f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Extensions of suppressions */
377f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjtypedef
378f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   enum {
379f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_Race=1201, /* race */
380f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_FreeMemLock,
381f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_UnlockUnlocked,
382f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_UnlockForeign,
383f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_UnlockBogus,
384f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_PthAPIerror,
385f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_LockOrder,
386f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      XS_Misc
387f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
388f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XSuppTag;
389f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
390f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
391f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Updates the copy with address info if necessary. */
3928e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianUInt HG_(update_extra) ( const Error* err )
393f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
394f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError* xe = (XError*)VG_(get_error_extra)(err);
395f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(xe);
396f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   //if (extra != NULL && Undescribed == extra->addrinfo.akind) {
397f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   //   describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
398f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   //}
399f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
400f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   if (xe->tag == XE_Race) {
40124118491f347852bc311069a273fce13608dd531sewardj
402ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      /* Note the set of locks that the thread is (w-)holding.
403ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Convert the WordSetID of LockN*'s into a NULL-terminated
404ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         vector of LockP*'s.  We don't expect to encounter any invalid
405ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         LockNs in this conversion. */
406ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      tl_assert(xe->XE.Race.thr);
407ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      xe->XE.Race.locksHeldW
408ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         = enumerate_WordSet_into_LockP_vector(
409ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj              HG_(get_univ_lsets)(),
410ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj              xe->XE.Race.thr->locksetW,
411ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj              False/*!allowed_to_be_invalid*/
412ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj           );
413ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
414f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      /* See if we can come up with a source level description of the
415f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         raced-upon address.  This is potentially expensive, which is
416f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         why it's only done at the update_extra point, not when the
417f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         error is initially created. */
418c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj      static Int xxx = 0;
419c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj      xxx++;
420c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj      if (0)
421c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj         VG_(printf)("HG_(update_extra): "
422c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj                     "%d conflicting-event queries\n", xxx);
423095d61eef541731e77e2c648983aee9ea2bf5e59sewardj
42407c08527f05caeb0062b42ca9a58ee774ec5fba1philippe      HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo);
42524118491f347852bc311069a273fce13608dd531sewardj
42624118491f347852bc311069a273fce13608dd531sewardj      /* And poke around in the conflicting-event map, to see if we
42724118491f347852bc311069a273fce13608dd531sewardj         can rustle up a plausible-looking conflicting memory access
42824118491f347852bc311069a273fce13608dd531sewardj         to show. */
42923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj      if (HG_(clo_history_level) >= 2) {
430ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Thr*        thrp            = NULL;
431ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         ExeContext* wherep          = NULL;
432ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Addr        acc_addr        = xe->XE.Race.data_addr;
433ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Int         acc_szB         = xe->XE.Race.szB;
434ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Thr*        acc_thr         = xe->XE.Race.thr->hbthr;
435ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Bool        acc_isW         = xe->XE.Race.isWrite;
436ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         SizeT       conf_szB        = 0;
437ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Bool        conf_isW        = False;
438ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         WordSetID   conf_locksHeldW = 0;
43923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         tl_assert(!xe->XE.Race.h2_ct_accEC);
44023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         tl_assert(!xe->XE.Race.h2_ct);
44123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (libhb_event_map_lookup(
442ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW,
44323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                acc_thr, acc_addr, acc_szB, acc_isW )) {
44423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            Thread* threadp;
44523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            tl_assert(wherep);
44623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            tl_assert(thrp);
44760626649e5fa6cd21af377fde5e83803fc136f61sewardj            threadp = libhb_get_Thr_hgthread( thrp );
44823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            tl_assert(threadp);
44923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            xe->XE.Race.h2_ct_accEC  = wherep;
45023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            xe->XE.Race.h2_ct        = threadp;
45123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            xe->XE.Race.h2_ct_accSzB = (Int)conf_szB;
45223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            xe->XE.Race.h2_ct_accIsW = conf_isW;
453ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            xe->XE.Race.h2_ct_locksHeldW
454ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               = enumerate_WordSet_into_LockP_vector(
455ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                    HG_(get_univ_lsets)(),
456ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                    conf_locksHeldW,
457ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                    True/*allowed_to_be_invalid*/
458ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                 );
459c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj        }
460c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj      }
46123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
46223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj      // both NULL or both non-NULL
46323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj      tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) );
464f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
465f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
466f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return sizeof(XError);
467f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
468f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
469f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid HG_(record_error_Race) ( Thread* thr,
470a781be6728a28c94aec57f793f4d084456e93684sewardj                              Addr data_addr, Int szB, Bool isWrite,
47123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                              Thread* h1_ct,
47223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                              ExeContext* h1_ct_segstart,
47323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                              ExeContext* h1_ct_mbsegendEC )
474f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
475f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
476f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
477f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
478f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#  if defined(VGO_linux)
479f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* Skip any races on locations apparently in GOTPLT sections.  This
480f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      is said to be caused by ld.so poking PLT table entries (or
481f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      whatever) when it writes the resolved address of a dynamically
482f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      linked routine, into the table (or whatever) when it is called
483f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      for the first time. */
484f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   {
485e08950b4ce5a3f5d75a7279548f975cd6207dc74florian     VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, data_addr );
486f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n",
487f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                        data_addr, VG_(pp_SectKind)(sect));
4885210413b79e93b660f5fd16dfb319237858835f5sewardj     /* SectPLT is required on ???-linux */
489f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     if (sect == Vg_SectGOTPLT) return;
4905210413b79e93b660f5fd16dfb319237858835f5sewardj     /* SectPLT is required on ppc32/64-linux */
4915210413b79e93b660f5fd16dfb319237858835f5sewardj     if (sect == Vg_SectPLT) return;
4924fa71081858358c26ad182b82d2ddc305b2e72f1mjw     /* SectGOT is required on arm-linux */
4934fa71081858358c26ad182b82d2ddc305b2e72f1mjw     if (sect == Vg_SectGOT) return;
494f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
495f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#  endif
496f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
497f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
498f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_Race;
499f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Race.data_addr   = data_addr;
500f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Race.szB         = szB;
501f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Race.isWrite     = isWrite;
502f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Race.thr         = thr;
503f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(isWrite == False || isWrite == True);
504a781be6728a28c94aec57f793f4d084456e93684sewardj   tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
50524118491f347852bc311069a273fce13608dd531sewardj   /* Skip on the detailed description of the raced-on address at this
50624118491f347852bc311069a273fce13608dd531sewardj      point; it's expensive.  Leave it for the update_extra function
50724118491f347852bc311069a273fce13608dd531sewardj      if we ever make it that far. */
50807c08527f05caeb0062b42ca9a58ee774ec5fba1philippe   xe.XE.Race.data_addrinfo.tag = Addr_Undescribed;
509f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
510c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj   // Skip on any of the conflicting-access info at this point.
511c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj   // It's expensive to obtain, and this error is more likely than
512c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj   // not to be discarded.  We'll fill these fields in in
513c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj   // HG_(update_extra) just above, assuming the error ever makes
514c5ea9961f9705b956742ae8c553c76caa2da8c29sewardj   // it that far (unlikely).
51523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h2_ct_accSzB = 0;
51623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h2_ct_accIsW = False;
51723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h2_ct_accEC  = NULL;
51823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h2_ct        = NULL;
519f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
520f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
52123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
52223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h1_ct              = h1_ct;
52323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart;
52423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj   xe.XE.Race.h1_ct_mbsegendEC   = h1_ct_mbsegendEC;
52523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
526f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
527f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_Race, data_addr, NULL, &xe );
528f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
529f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
530f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk )
531f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
532f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
533f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
534f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockN)(lk) );
535f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
536f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_UnlockUnlocked;
537ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.UnlockUnlocked.thr
538ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      = thr;
539ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.UnlockUnlocked.lock
540ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
541f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
542f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
543f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
544f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
545f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_UnlockUnlocked, 0, NULL, &xe );
546f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
547f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
548f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid HG_(record_error_UnlockForeign) ( Thread* thr,
549f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                       Thread* owner, Lock* lk )
550f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
551f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
552f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
553f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(owner) );
554f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_LockN)(lk) );
555f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
556f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_UnlockForeign;
557f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.UnlockForeign.thr   = thr;
558f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.UnlockForeign.owner = owner;
559ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.UnlockForeign.lock
560ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/);
561f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
562f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
563f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
564f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
565f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_UnlockForeign, 0, NULL, &xe );
566f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
567f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
568f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga )
569f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
570f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
571f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
572f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
573f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_UnlockBogus;
574f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.UnlockBogus.thr     = thr;
575f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.UnlockBogus.lock_ga = lock_ga;
576f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
577f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
578f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
579f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
580f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_UnlockBogus, 0, NULL, &xe );
581f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
582f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
583f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardjvoid HG_(record_error_LockOrder)(
584ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj        Thread*     thr,
58546daf0d598c38c9251964712d894f0fcd3cc4143philippe        Lock*       shouldbe_earlier_lk,
58646daf0d598c38c9251964712d894f0fcd3cc4143philippe        Lock*       shouldbe_later_lk,
587ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj        ExeContext* shouldbe_earlier_ec,
588ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj        ExeContext* shouldbe_later_ec,
589ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj        ExeContext* actual_earlier_ec
590f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj     )
591f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
592f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
593f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
594c1fb9d265a0d64216d387684a425125af4aca557sewardj   tl_assert(HG_(clo_track_lockorders));
595f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
596f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_LockOrder;
597f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.LockOrder.thr       = thr;
59846daf0d598c38c9251964712d894f0fcd3cc4143philippe   xe.XE.LockOrder.shouldbe_earlier_lk
59946daf0d598c38c9251964712d894f0fcd3cc4143philippe      = mk_LockP_from_LockN(shouldbe_earlier_lk,
60046daf0d598c38c9251964712d894f0fcd3cc4143philippe                            False/*!allowed_to_be_invalid*/);
601ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec;
60246daf0d598c38c9251964712d894f0fcd3cc4143philippe   xe.XE.LockOrder.shouldbe_later_lk
60346daf0d598c38c9251964712d894f0fcd3cc4143philippe      = mk_LockP_from_LockN(shouldbe_later_lk,
60446daf0d598c38c9251964712d894f0fcd3cc4143philippe                            False/*!allowed_to_be_invalid*/);
605ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.LockOrder.shouldbe_later_ec   = shouldbe_later_ec;
606ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   xe.XE.LockOrder.actual_earlier_ec   = actual_earlier_ec;
607f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
608f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
609f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
610f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
611f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_LockOrder, 0, NULL, &xe );
612f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
613f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
6146bd9dc18c043927c1196caba20a327238a179c42florianvoid HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname,
6156bd9dc18c043927c1196caba20a327238a179c42florian                                     Word err, const HChar* errstr )
616f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
617f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
618f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
619f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(fnname);
620f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(errstr);
621f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
622f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_PthAPIerror;
623f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.PthAPIerror.thr    = thr;
624f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.PthAPIerror.fnname = string_table_strdup(fnname);
625f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.PthAPIerror.err    = err;
626f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.PthAPIerror.errstr = string_table_strdup(errstr);
627f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
628f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
629f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
630f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
631f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_PthAPIerror, 0, NULL, &xe );
632f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
633f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
6346bd9dc18c043927c1196caba20a327238a179c42florianvoid HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr,
6356bd9dc18c043927c1196caba20a327238a179c42florian                                    const HChar* auxstr, ExeContext* auxctx )
636f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
637f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError xe;
638f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_Thread)(thr) );
639f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(errstr);
640f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   init_XError(&xe);
641f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.tag = XE_Misc;
642f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Misc.thr    = thr;
643f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe.XE.Misc.errstr = string_table_strdup(errstr);
6448fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj   xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL;
6458fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj   xe.XE.Misc.auxctx = auxctx;
646f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   // FIXME: tid vs thr
647f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( HG_(is_sane_ThreadId)(thr->coretid) );
648f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert( thr->coretid != VG_INVALID_THREADID );
649f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   VG_(maybe_record_error)( thr->coretid,
650f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                            XE_Misc, 0, NULL, &xe );
651f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
652f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
6536bd9dc18c043927c1196caba20a327238a179c42florianvoid HG_(record_error_Misc) ( Thread* thr, const HChar* errstr )
6548fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj{
6558fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj   HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL);
6568fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj}
6578fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj
6588e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianBool HG_(eq_Error) ( VgRes not_used, const Error* e1, const Error* e2 )
659f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
660f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError *xe1, *xe2;
661f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
662f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
663f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
664f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe1 = (XError*)VG_(get_error_extra)(e1);
665f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   xe2 = (XError*)VG_(get_error_extra)(e2);
666f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(xe1);
667f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(xe2);
668f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
669f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   switch (VG_(get_error_kind)(e1)) {
670f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_Race:
671f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.Race.szB == xe2->XE.Race.szB
672f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite
673f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && (HG_(clo_cmp_race_err_addrs)
674f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                       ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr
675f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                       : True);
676f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockUnlocked:
677f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr
678f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock;
679f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockForeign:
680f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr
681f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner
682f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock;
683f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockBogus:
684f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr
685f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga;
686f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_PthAPIerror:
687f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr
688f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname,
689f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                  xe2->XE.PthAPIerror.fnname)
690f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err;
691f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_LockOrder:
692f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr;
693f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_Misc:
694f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return xe1->XE.Misc.thr == xe2->XE.Misc.thr
695f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr);
696f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      default:
697f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         tl_assert(0);
698f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
699f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
700f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /*NOTREACHED*/
701f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(0);
702f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
703f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
704f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
70524118491f347852bc311069a273fce13608dd531sewardj/*----------------------------------------------------------------*/
70624118491f347852bc311069a273fce13608dd531sewardj/*--- Error management -- printing                             ---*/
70724118491f347852bc311069a273fce13608dd531sewardj/*----------------------------------------------------------------*/
70824118491f347852bc311069a273fce13608dd531sewardj
70924118491f347852bc311069a273fce13608dd531sewardj/* Do a printf-style operation on either the XML or normal output
71024118491f347852bc311069a273fce13608dd531sewardj   channel, depending on the setting of VG_(clo_xml).
71124118491f347852bc311069a273fce13608dd531sewardj*/
7126bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorianstatic void emit_WRK ( const HChar* format, va_list vargs )
71324118491f347852bc311069a273fce13608dd531sewardj{
71424118491f347852bc311069a273fce13608dd531sewardj   if (VG_(clo_xml)) {
71524118491f347852bc311069a273fce13608dd531sewardj      VG_(vprintf_xml)(format, vargs);
71624118491f347852bc311069a273fce13608dd531sewardj   } else {
71724118491f347852bc311069a273fce13608dd531sewardj      VG_(vmessage)(Vg_UserMsg, format, vargs);
71824118491f347852bc311069a273fce13608dd531sewardj   }
71924118491f347852bc311069a273fce13608dd531sewardj}
7206bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorianstatic void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
7216bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorianstatic void emit ( const HChar* format, ... )
72224118491f347852bc311069a273fce13608dd531sewardj{
72324118491f347852bc311069a273fce13608dd531sewardj   va_list vargs;
72424118491f347852bc311069a273fce13608dd531sewardj   va_start(vargs, format);
72524118491f347852bc311069a273fce13608dd531sewardj   emit_WRK(format, vargs);
72624118491f347852bc311069a273fce13608dd531sewardj   va_end(vargs);
72724118491f347852bc311069a273fce13608dd531sewardj}
72824118491f347852bc311069a273fce13608dd531sewardj
72924118491f347852bc311069a273fce13608dd531sewardj
730f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/* Announce (that is, print the point-of-creation) of 'thr'.  Only do
731f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   this once, as we only want to see these announcements once per
73224118491f347852bc311069a273fce13608dd531sewardj   thread.  Returned Bool indicates whether or not an announcement was
73324118491f347852bc311069a273fce13608dd531sewardj   made.
73424118491f347852bc311069a273fce13608dd531sewardj*/
73524118491f347852bc311069a273fce13608dd531sewardjstatic Bool announce_one_thread ( Thread* thr )
736f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
737f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(HG_(is_sane_Thread)(thr));
738f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   tl_assert(thr->errmsg_index >= 1);
73924118491f347852bc311069a273fce13608dd531sewardj   if (thr->announced)
74024118491f347852bc311069a273fce13608dd531sewardj      return False;
74124118491f347852bc311069a273fce13608dd531sewardj
74224118491f347852bc311069a273fce13608dd531sewardj   if (VG_(clo_xml)) {
74324118491f347852bc311069a273fce13608dd531sewardj
74424118491f347852bc311069a273fce13608dd531sewardj      VG_(printf_xml)("<announcethread>\n");
74511b5c6d24609d9b75aa15f0a6dfb2b207136de60sewardj      VG_(printf_xml)("  <hthreadid>%d</hthreadid>\n", thr->errmsg_index);
746f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (thr->errmsg_index == 1) {
747f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         tl_assert(thr->created_at == NULL);
74824118491f347852bc311069a273fce13608dd531sewardj         VG_(printf_xml)("  <isrootthread></isrootthread>\n");
74924118491f347852bc311069a273fce13608dd531sewardj      } else {
75024118491f347852bc311069a273fce13608dd531sewardj         tl_assert(thr->created_at != NULL);
75124118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( thr->created_at );
75224118491f347852bc311069a273fce13608dd531sewardj      }
75324118491f347852bc311069a273fce13608dd531sewardj      VG_(printf_xml)("</announcethread>\n\n");
75424118491f347852bc311069a273fce13608dd531sewardj
75524118491f347852bc311069a273fce13608dd531sewardj   } else {
75624118491f347852bc311069a273fce13608dd531sewardj
757ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)("---Thread-Announcement----------"
758ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                "--------------------------------" "\n");
759ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)("\n");
760ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
76124118491f347852bc311069a273fce13608dd531sewardj      if (thr->errmsg_index == 1) {
76224118491f347852bc311069a273fce13608dd531sewardj         tl_assert(thr->created_at == NULL);
76324118491f347852bc311069a273fce13608dd531sewardj         VG_(message)(Vg_UserMsg,
76424118491f347852bc311069a273fce13608dd531sewardj                      "Thread #%d is the program's root thread\n",
76524118491f347852bc311069a273fce13608dd531sewardj                       thr->errmsg_index);
766f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      } else {
767f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         tl_assert(thr->created_at != NULL);
76824118491f347852bc311069a273fce13608dd531sewardj         VG_(message)(Vg_UserMsg, "Thread #%d was created\n",
769f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj                                  thr->errmsg_index);
770f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(pp_ExeContext)( thr->created_at );
771f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
77224118491f347852bc311069a273fce13608dd531sewardj      VG_(message)(Vg_UserMsg, "\n");
77324118491f347852bc311069a273fce13608dd531sewardj
77424118491f347852bc311069a273fce13608dd531sewardj   }
77524118491f347852bc311069a273fce13608dd531sewardj
77624118491f347852bc311069a273fce13608dd531sewardj   thr->announced = True;
77724118491f347852bc311069a273fce13608dd531sewardj   return True;
77824118491f347852bc311069a273fce13608dd531sewardj}
77924118491f347852bc311069a273fce13608dd531sewardj
780ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Announce 'lk'. */
781ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic void announce_LockP ( Lock* lk )
782ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
783ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(lk);
784ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (lk == Lock_INVALID)
785ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      return; /* Can't be announced -- we know nothing about it. */
786ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(lk->magic == LockP_MAGIC);
787ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
788ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (VG_(clo_xml)) {
78946daf0d598c38c9251964712d894f0fcd3cc4143philippe      if (lk->appeared_at) {
79046daf0d598c38c9251964712d894f0fcd3cc4143philippe         emit( "  <auxwhat>Lock at %p was first observed</auxwhat>\n",
79146daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)lk );
79246daf0d598c38c9251964712d894f0fcd3cc4143philippe         VG_(pp_ExeContext)( lk->appeared_at );
79346daf0d598c38c9251964712d894f0fcd3cc4143philippe      }
79446daf0d598c38c9251964712d894f0fcd3cc4143philippe
795ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   } else {
7968061201f9eaaf2fc6a672f631310662749a6527fphilippe      if (lk->appeared_at) {
79746daf0d598c38c9251964712d894f0fcd3cc4143philippe         VG_(umsg)( " Lock at %p was first observed\n",
7988061201f9eaaf2fc6a672f631310662749a6527fphilippe                    (void*)lk->guestaddr );
7998061201f9eaaf2fc6a672f631310662749a6527fphilippe         VG_(pp_ExeContext)( lk->appeared_at );
8008061201f9eaaf2fc6a672f631310662749a6527fphilippe      } else {
80146daf0d598c38c9251964712d894f0fcd3cc4143philippe         VG_(umsg)( " Lock at %p : no stacktrace for first observation\n",
8028061201f9eaaf2fc6a672f631310662749a6527fphilippe                    (void*)lk->guestaddr );
8038061201f9eaaf2fc6a672f631310662749a6527fphilippe      }
8048061201f9eaaf2fc6a672f631310662749a6527fphilippe      HG_(get_and_pp_addrdescr) (lk->guestaddr);
805ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)("\n");
806ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
807ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
808ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
809ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj/* Announce (that is, print point-of-first-observation) for the
810ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   locks in 'lockvec' and, if non-NULL, 'lockvec2'. */
811ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardjstatic void announce_combined_LockP_vecs ( Lock** lockvec,
812ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                           Lock** lockvec2 )
813ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
814ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord i;
815ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(lockvec);
816ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   for (i = 0; lockvec[i]; i++) {
817ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      announce_LockP(lockvec[i]);
818ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
819ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (lockvec2) {
820ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      for (i = 0; lockvec2[i]; i++) {
821ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         Lock* lk = lockvec2[i];
822ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (!elem_LockP_vector(lockvec, lk))
823ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            announce_LockP(lk);
824ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      }
825ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
826ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
827ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
828ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
8296bd9dc18c043927c1196caba20a327238a179c42florianstatic void show_LockP_summary_textmode ( Lock** locks, const HChar* pre )
830ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj{
831ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(locks);
832ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord i;
833ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   UWord nLocks = 0, nLocksValid = 0;
834ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   count_LockP_vector(&nLocks, &nLocksValid, locks);
835ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   tl_assert(nLocksValid <= nLocks);
836ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
837ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (nLocks == 0) {
838ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)( "%sLocks held: none", pre );
839ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   } else {
840ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)( "%sLocks held: %lu, at address%s ",
841ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                 pre, nLocks, nLocksValid == 1 ? "" : "es" );
842ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
843ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
844ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (nLocks > 0) {
845ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      for (i = 0; i < nLocks; i++) {
846ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (locks[i] == Lock_INVALID)
847ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            continue;
848ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         VG_(umsg)( "%p", (void*)locks[i]->guestaddr);
849ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (locks[i+1] != NULL)
850ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            VG_(umsg)(" ");
851ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      }
852ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      if (nLocksValid < nLocks)
853ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid);
854ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
855ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   VG_(umsg)("\n");
856ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj}
857ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
858ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
85924118491f347852bc311069a273fce13608dd531sewardj/* This is the "this error is due to be printed shortly; so have a
86024118491f347852bc311069a273fce13608dd531sewardj   look at it any print any preamble you want" function.  We use it to
86124118491f347852bc311069a273fce13608dd531sewardj   announce any previously un-announced threads in the upcoming error
86224118491f347852bc311069a273fce13608dd531sewardj   message.
86324118491f347852bc311069a273fce13608dd531sewardj*/
8648e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianvoid HG_(before_pp_Error) ( const Error* err )
86524118491f347852bc311069a273fce13608dd531sewardj{
86624118491f347852bc311069a273fce13608dd531sewardj   XError* xe;
86724118491f347852bc311069a273fce13608dd531sewardj   tl_assert(err);
86824118491f347852bc311069a273fce13608dd531sewardj   xe = (XError*)VG_(get_error_extra)(err);
86924118491f347852bc311069a273fce13608dd531sewardj   tl_assert(xe);
87024118491f347852bc311069a273fce13608dd531sewardj
87124118491f347852bc311069a273fce13608dd531sewardj   switch (VG_(get_error_kind)(err)) {
87224118491f347852bc311069a273fce13608dd531sewardj      case XE_Misc:
87324118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.Misc.thr );
87424118491f347852bc311069a273fce13608dd531sewardj         break;
87524118491f347852bc311069a273fce13608dd531sewardj      case XE_LockOrder:
87624118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.LockOrder.thr );
87724118491f347852bc311069a273fce13608dd531sewardj         break;
87824118491f347852bc311069a273fce13608dd531sewardj      case XE_PthAPIerror:
87924118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.PthAPIerror.thr );
88024118491f347852bc311069a273fce13608dd531sewardj         break;
88124118491f347852bc311069a273fce13608dd531sewardj      case XE_UnlockBogus:
88224118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.UnlockBogus.thr );
88324118491f347852bc311069a273fce13608dd531sewardj         break;
88424118491f347852bc311069a273fce13608dd531sewardj      case XE_UnlockForeign:
88524118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.UnlockForeign.thr );
88624118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.UnlockForeign.owner );
88724118491f347852bc311069a273fce13608dd531sewardj         break;
88824118491f347852bc311069a273fce13608dd531sewardj      case XE_UnlockUnlocked:
88924118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.UnlockUnlocked.thr );
89024118491f347852bc311069a273fce13608dd531sewardj         break;
89124118491f347852bc311069a273fce13608dd531sewardj      case XE_Race:
89224118491f347852bc311069a273fce13608dd531sewardj         announce_one_thread( xe->XE.Race.thr );
89323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h2_ct)
89423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            announce_one_thread( xe->XE.Race.h2_ct );
89523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h1_ct)
89623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            announce_one_thread( xe->XE.Race.h1_ct );
8970c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe         if (xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
8980c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe            Thread* thr = get_admin_threads();
8990c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe            while (thr) {
9000c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe               if (thr->errmsg_index
9010c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe                   == xe->XE.Race.data_addrinfo.Addr.Block.alloc_tinfo.tnr) {
9020c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe                  announce_one_thread (thr);
9030c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe                  break;
9040c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe               }
9050c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe               thr = thr->admin;
9060c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe            }
9070c9ac8d0deca2f2a552fb2b0cab24efe6191bac7philippe         }
90824118491f347852bc311069a273fce13608dd531sewardj         break;
90924118491f347852bc311069a273fce13608dd531sewardj      default:
91024118491f347852bc311069a273fce13608dd531sewardj         tl_assert(0);
911f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
912f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
913f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
9148e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianvoid HG_(pp_Error) ( const Error* err )
915f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
91624118491f347852bc311069a273fce13608dd531sewardj   const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
91724118491f347852bc311069a273fce13608dd531sewardj
918ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   if (!xml) {
919ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)("--------------------------------"
920ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                "--------------------------------" "\n");
921ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj      VG_(umsg)("\n");
922ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj   }
923ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
924f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   XError *xe = (XError*)VG_(get_error_extra)(err);
92524118491f347852bc311069a273fce13608dd531sewardj   tl_assert(xe);
926f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
9272fa18d9ea5474392ec055e8e553a409ae36719cebart   if (xml)
9282fa18d9ea5474392ec055e8e553a409ae36719cebart      emit( "  <kind>%s</kind>\n", HG_(get_error_name)(err));
9292fa18d9ea5474392ec055e8e553a409ae36719cebart
930f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   switch (VG_(get_error_kind)(err)) {
931f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
932f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_Misc: {
933f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) );
93424118491f347852bc311069a273fce13608dd531sewardj
93524118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
93624118491f347852bc311069a273fce13608dd531sewardj
93724118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
93824118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Thread #%d: %s</text>\n",
93924118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.Misc.thr->errmsg_index,
94024118491f347852bc311069a273fce13608dd531sewardj               xe->XE.Misc.errstr );
94124118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
94224118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.Misc.thr->errmsg_index );
94324118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
94424118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
9458fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj         if (xe->XE.Misc.auxstr) {
9468fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            emit("  <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr);
9478fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            if (xe->XE.Misc.auxctx)
9488fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj               VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
9498fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj         }
95024118491f347852bc311069a273fce13608dd531sewardj
95124118491f347852bc311069a273fce13608dd531sewardj      } else {
95224118491f347852bc311069a273fce13608dd531sewardj
95324118491f347852bc311069a273fce13608dd531sewardj         emit( "Thread #%d: %s\n",
95424118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.Misc.thr->errmsg_index,
95524118491f347852bc311069a273fce13608dd531sewardj               xe->XE.Misc.errstr );
95624118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
9578fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj         if (xe->XE.Misc.auxstr) {
9588fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            emit(" %s\n", xe->XE.Misc.auxstr);
9598fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj            if (xe->XE.Misc.auxctx)
9608fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj               VG_(pp_ExeContext)( xe->XE.Misc.auxctx );
9618fef62537fc0bcc0903d5be3080152f0e0b3979dsewardj         }
96224118491f347852bc311069a273fce13608dd531sewardj
96324118491f347852bc311069a273fce13608dd531sewardj      }
964f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
965f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
966f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
967f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_LockOrder: {
968f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) );
96924118491f347852bc311069a273fce13608dd531sewardj
97024118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
97124118491f347852bc311069a273fce13608dd531sewardj
97224118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
97324118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Thread #%d: lock order \"%p before %p\" "
97424118491f347852bc311069a273fce13608dd531sewardj                    "violated</text>\n",
97524118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.LockOrder.thr->errmsg_index,
97646daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
97746daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
97824118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
97924118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.LockOrder.thr->errmsg_index );
98024118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
98124118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
982ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (xe->XE.LockOrder.shouldbe_earlier_ec
983ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj             && xe->XE.LockOrder.shouldbe_later_ec) {
98424118491f347852bc311069a273fce13608dd531sewardj            emit( "  <auxwhat>Required order was established by "
98524118491f347852bc311069a273fce13608dd531sewardj                  "acquisition of lock at %p</auxwhat>\n",
98646daf0d598c38c9251964712d894f0fcd3cc4143philippe                  (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
987ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
98824118491f347852bc311069a273fce13608dd531sewardj            emit( "  <auxwhat>followed by a later acquisition "
98924118491f347852bc311069a273fce13608dd531sewardj                  "of lock at %p</auxwhat>\n",
99046daf0d598c38c9251964712d894f0fcd3cc4143philippe                  (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
991ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
99224118491f347852bc311069a273fce13608dd531sewardj         }
99346daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
99446daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
99524118491f347852bc311069a273fce13608dd531sewardj
99624118491f347852bc311069a273fce13608dd531sewardj      } else {
99724118491f347852bc311069a273fce13608dd531sewardj
99824118491f347852bc311069a273fce13608dd531sewardj         emit( "Thread #%d: lock order \"%p before %p\" violated\n",
99924118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.LockOrder.thr->errmsg_index,
100046daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr,
100146daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
1002ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         emit( "\n" );
1003ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         emit( "Observed (incorrect) order is: "
1004ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               "acquisition of lock at %p\n",
100546daf0d598c38c9251964712d894f0fcd3cc4143philippe               (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr);
1006ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (xe->XE.LockOrder.actual_earlier_ec) {
1007ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj             VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec);
1008ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         } else {
1009ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit("   (stack unavailable)\n");
1010ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         }
1011ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         emit( "\n" );
1012ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         emit(" followed by a later acquisition of lock at %p\n",
101346daf0d598c38c9251964712d894f0fcd3cc4143philippe              (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr);
101424118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1015ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         if (xe->XE.LockOrder.shouldbe_earlier_ec
1016ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj             && xe->XE.LockOrder.shouldbe_later_ec) {
1017ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit("\n");
1018ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit( "Required order was established by "
101924118491f347852bc311069a273fce13608dd531sewardj                  "acquisition of lock at %p\n",
102046daf0d598c38c9251964712d894f0fcd3cc4143philippe                  (void*)xe->XE.LockOrder.shouldbe_earlier_lk->guestaddr );
1021ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec );
1022ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit( "\n" );
1023ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit( " followed by a later acquisition of lock at %p\n",
102446daf0d598c38c9251964712d894f0fcd3cc4143philippe                  (void*)xe->XE.LockOrder.shouldbe_later_lk->guestaddr );
1025ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec );
102624118491f347852bc311069a273fce13608dd531sewardj         }
102746daf0d598c38c9251964712d894f0fcd3cc4143philippe         emit("\n");
102846daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.LockOrder.shouldbe_earlier_lk );
102946daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.LockOrder.shouldbe_later_lk );
103024118491f347852bc311069a273fce13608dd531sewardj
1031f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
103224118491f347852bc311069a273fce13608dd531sewardj
1033f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
1034f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1035f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1036f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_PthAPIerror: {
1037f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) );
103824118491f347852bc311069a273fce13608dd531sewardj
103924118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
104024118491f347852bc311069a273fce13608dd531sewardj
104124118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
1042b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart         emit(
1043b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart            "    <text>Thread #%d's call to %pS failed</text>\n",
104424118491f347852bc311069a273fce13608dd531sewardj            (Int)xe->XE.PthAPIerror.thr->errmsg_index,
104524118491f347852bc311069a273fce13608dd531sewardj            xe->XE.PthAPIerror.fnname );
104624118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
104724118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.PthAPIerror.thr->errmsg_index );
104824118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
104924118491f347852bc311069a273fce13608dd531sewardj         emit( "  <what>with error code %ld (%s)</what>\n",
105024118491f347852bc311069a273fce13608dd531sewardj               xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
105124118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
105224118491f347852bc311069a273fce13608dd531sewardj
105324118491f347852bc311069a273fce13608dd531sewardj      } else {
105424118491f347852bc311069a273fce13608dd531sewardj
1055b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart         emit( "Thread #%d's call to %pS failed\n",
105624118491f347852bc311069a273fce13608dd531sewardj                      (Int)xe->XE.PthAPIerror.thr->errmsg_index,
105724118491f347852bc311069a273fce13608dd531sewardj                      xe->XE.PthAPIerror.fnname );
105824118491f347852bc311069a273fce13608dd531sewardj         emit( "   with error code %ld (%s)\n",
105924118491f347852bc311069a273fce13608dd531sewardj               xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr );
106024118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
106124118491f347852bc311069a273fce13608dd531sewardj
106224118491f347852bc311069a273fce13608dd531sewardj      }
106324118491f347852bc311069a273fce13608dd531sewardj
1064f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
1065f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1066f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1067f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_UnlockBogus: {
1068f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) );
106924118491f347852bc311069a273fce13608dd531sewardj
107024118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
107124118491f347852bc311069a273fce13608dd531sewardj
107224118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
107324118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Thread #%d unlocked an invalid "
107424118491f347852bc311069a273fce13608dd531sewardj                    "lock at %p</text>\n",
107524118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockBogus.thr->errmsg_index,
107624118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockBogus.lock_ga );
107724118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
107824118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockBogus.thr->errmsg_index );
107924118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
108024118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
108124118491f347852bc311069a273fce13608dd531sewardj
108224118491f347852bc311069a273fce13608dd531sewardj      } else {
108324118491f347852bc311069a273fce13608dd531sewardj
108424118491f347852bc311069a273fce13608dd531sewardj         emit( "Thread #%d unlocked an invalid lock at %p\n",
108524118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockBogus.thr->errmsg_index,
108624118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockBogus.lock_ga );
108724118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
108824118491f347852bc311069a273fce13608dd531sewardj
108924118491f347852bc311069a273fce13608dd531sewardj      }
109024118491f347852bc311069a273fce13608dd531sewardj
1091f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
1092f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1093f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1094f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_UnlockForeign: {
1095f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) );
1096f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) );
1097f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) );
109824118491f347852bc311069a273fce13608dd531sewardj
109924118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
110024118491f347852bc311069a273fce13608dd531sewardj
110124118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
110224118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Thread #%d unlocked lock at %p "
110324118491f347852bc311069a273fce13608dd531sewardj                    "currently held by thread #%d</text>\n",
110424118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.thr->errmsg_index,
110524118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockForeign.lock->guestaddr,
110624118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.owner->errmsg_index );
110724118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
110824118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.thr->errmsg_index );
110924118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
111024118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.owner->errmsg_index );
111124118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
111224118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
111346daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.UnlockForeign.lock );
111424118491f347852bc311069a273fce13608dd531sewardj
111524118491f347852bc311069a273fce13608dd531sewardj      } else {
111624118491f347852bc311069a273fce13608dd531sewardj
111724118491f347852bc311069a273fce13608dd531sewardj         emit( "Thread #%d unlocked lock at %p "
111824118491f347852bc311069a273fce13608dd531sewardj               "currently held by thread #%d\n",
111924118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.thr->errmsg_index,
112024118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockForeign.lock->guestaddr,
112124118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockForeign.owner->errmsg_index );
112224118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
112346daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.UnlockForeign.lock );
112424118491f347852bc311069a273fce13608dd531sewardj
1125f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
112624118491f347852bc311069a273fce13608dd531sewardj
1127f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
1128f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1129f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1130f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_UnlockUnlocked: {
1131f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) );
1132f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) );
1133f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
113424118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
113524118491f347852bc311069a273fce13608dd531sewardj
113624118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
113724118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Thread #%d unlocked a "
113824118491f347852bc311069a273fce13608dd531sewardj                    "not-locked lock at %p</text>\n",
113924118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
114024118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
114124118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
114224118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockUnlocked.thr->errmsg_index );
114324118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
114424118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
114546daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.UnlockUnlocked.lock);
114624118491f347852bc311069a273fce13608dd531sewardj
114724118491f347852bc311069a273fce13608dd531sewardj      } else {
114824118491f347852bc311069a273fce13608dd531sewardj
114924118491f347852bc311069a273fce13608dd531sewardj         emit( "Thread #%d unlocked a not-locked lock at %p\n",
115024118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.UnlockUnlocked.thr->errmsg_index,
115124118491f347852bc311069a273fce13608dd531sewardj               (void*)xe->XE.UnlockUnlocked.lock->guestaddr );
115224118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
115346daf0d598c38c9251964712d894f0fcd3cc4143philippe         announce_LockP ( xe->XE.UnlockUnlocked.lock);
115424118491f347852bc311069a273fce13608dd531sewardj
1155f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
115624118491f347852bc311069a273fce13608dd531sewardj
1157f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break;
1158f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1159f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1160f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XE_Race: {
1161f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Addr      err_ga;
11626bf3726ebf7a04ca48a5e6cb1ad7a3065054e54eflorian      const HChar* what;
1163f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      Int       szB;
1164f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      what      = xe->XE.Race.isWrite ? "write" : "read";
1165f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      szB       = xe->XE.Race.szB;
1166f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      err_ga = VG_(get_error_address)(err);
1167f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
116824118491f347852bc311069a273fce13608dd531sewardj      tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr ));
116923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj      if (xe->XE.Race.h2_ct)
117023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct ));
117124118491f347852bc311069a273fce13608dd531sewardj
117224118491f347852bc311069a273fce13608dd531sewardj      if (xml) {
117324118491f347852bc311069a273fce13608dd531sewardj
117424118491f347852bc311069a273fce13608dd531sewardj         /* ------ XML ------ */
117524118491f347852bc311069a273fce13608dd531sewardj         emit( "  <xwhat>\n" );
117624118491f347852bc311069a273fce13608dd531sewardj         emit( "    <text>Possible data race during %s of size %d "
1177ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                    "at %p by thread #%d</text>\n",
1178ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
117924118491f347852bc311069a273fce13608dd531sewardj         emit( "    <hthreadid>%d</hthreadid>\n",
118024118491f347852bc311069a273fce13608dd531sewardj               (Int)xe->XE.Race.thr->errmsg_index );
118124118491f347852bc311069a273fce13608dd531sewardj         emit( "  </xwhat>\n" );
118224118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
118324118491f347852bc311069a273fce13608dd531sewardj
118423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h2_ct) {
118523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
118623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "  <xauxwhat>\n");
118723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "    <text>This conflicts with a previous %s of size %d "
118823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                            "by thread #%d</text>\n",
118923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct_accIsW ? "write" : "read",
119023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct_accSzB,
119123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct->errmsg_index );
119223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "    <hthreadid>%d</hthreadid>\n",
119323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct->errmsg_index);
119423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit("  </xauxwhat>\n");
119523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
119623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         }
119723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
119823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h1_ct) {
119923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "  <xauxwhat>\n");
120023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "    <text>This conflicts with a previous access "
120123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  "by thread #%d, after</text>\n",
120223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h1_ct->errmsg_index );
120323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "    <hthreadid>%d</hthreadid>\n",
120423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h1_ct->errmsg_index );
120523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit("  </xauxwhat>\n");
120623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            if (xe->XE.Race.h1_ct_mbsegstartEC) {
120723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
120824118491f347852bc311069a273fce13608dd531sewardj            } else {
120923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               emit( "  <auxwhat>(the start of the thread)</auxwhat>\n" );
121023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            }
121123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( "  <auxwhat>but before</auxwhat>\n" );
121223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            if (xe->XE.Race.h1_ct_mbsegendEC) {
121323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
121423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            } else {
1215ad4e979f408239dabbaae955d8ffcb84a51a5c85florian               emit( "  <auxwhat>(the end of the thread)</auxwhat>\n" );
121624118491f347852bc311069a273fce13608dd531sewardj            }
1217f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         }
1218f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
121924118491f347852bc311069a273fce13608dd531sewardj      } else {
122024118491f347852bc311069a273fce13608dd531sewardj
122124118491f347852bc311069a273fce13608dd531sewardj         /* ------ Text ------ */
1222ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         announce_combined_LockP_vecs( xe->XE.Race.locksHeldW,
1223ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj                                       xe->XE.Race.h2_ct_locksHeldW );
1224ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
122524118491f347852bc311069a273fce13608dd531sewardj         emit( "Possible data race during %s of size %d "
1226ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               "at %p by thread #%d\n",
1227ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj               what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index );
1228ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj
1229ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         tl_assert(xe->XE.Race.locksHeldW);
1230ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj         show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" );
123124118491f347852bc311069a273fce13608dd531sewardj         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
123223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
123323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h2_ct) {
123423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra
1235ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            tl_assert(xe->XE.Race.h2_ct_locksHeldW);
1236ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit( "\n" );
1237ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            emit( "This conflicts with a previous %s of size %d "
123823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  "by thread #%d\n",
123923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct_accIsW ? "write" : "read",
124023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct_accSzB,
124123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h2_ct->errmsg_index );
1242ffce8159a95134f0a2bc1cea3c3e6e265f096d9fsewardj            show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" );
124323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC );
124423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         }
124523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj
124623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj         if (xe->XE.Race.h1_ct) {
124723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( " This conflicts with a previous access by thread #%d, "
124823f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  "after\n",
124923f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj                  xe->XE.Race.h1_ct->errmsg_index );
125023f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            if (xe->XE.Race.h1_ct_mbsegstartEC) {
125123f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC );
125223f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            } else {
125323f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               emit( "   (the start of the thread)\n" );
125423f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            }
125523f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            emit( " but before\n" );
125623f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj            if (xe->XE.Race.h1_ct_mbsegendEC) {
125723f1200ba3aa3d8dbb484626ba1bdb7cfcf3b3a9sewardj               VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC );
125824118491f347852bc311069a273fce13608dd531sewardj            } else {
1259ad4e979f408239dabbaae955d8ffcb84a51a5c85florian               emit( "   (the end of the thread)\n" );
126024118491f347852bc311069a273fce13608dd531sewardj            }
126124118491f347852bc311069a273fce13608dd531sewardj         }
126224118491f347852bc311069a273fce13608dd531sewardj
126324118491f347852bc311069a273fce13608dd531sewardj      }
126407c08527f05caeb0062b42ca9a58ee774ec5fba1philippe      VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo);
1265f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      break; /* case XE_Race */
1266f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } /* case XE_Race */
1267f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1268f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   default:
1269f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      tl_assert(0);
1270f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   } /* switch (VG_(get_error_kind)(err)) */
1271f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1272f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1273328d6627c26471332610da3f5a0b9cc3cdd410c7philippevoid HG_(print_access) (StackTrace ips, UInt n_ips,
1274328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                        Thr* thr_a,
1275328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                        Addr  ga,
1276328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                        SizeT SzB,
1277328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                        Bool  isW,
1278328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                        WordSetID locksHeldW )
1279328d6627c26471332610da3f5a0b9cc3cdd410c7philippe{
1280328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   Thread* threadp;
1281328d6627c26471332610da3f5a0b9cc3cdd410c7philippe
1282328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   threadp = libhb_get_Thr_hgthread( thr_a );
1283328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   tl_assert(threadp);
1284328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   if (!threadp->announced) {
1285328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      /* This is for interactive use. We announce the thread if needed,
1286328d6627c26471332610da3f5a0b9cc3cdd410c7philippe         but reset it to not announced afterwards, because we want
1287328d6627c26471332610da3f5a0b9cc3cdd410c7philippe         the thread to be announced on the error output/log if needed. */
1288328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      announce_one_thread (threadp);
1289328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      threadp->announced = False;
1290328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   }
1291328d6627c26471332610da3f5a0b9cc3cdd410c7philippe
1292328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   announce_one_thread (threadp);
1293328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   VG_(printf) ("%s of size %d at %p by thread #%d",
1294328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                isW ? "write" : "read",
1295328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                (int)SzB, (void*)ga, threadp->errmsg_index);
1296328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   if (threadp->coretid == VG_INVALID_THREADID)
1297328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      VG_(printf)(" tid (exited)\n");
1298328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   else
12995e5cb009574352880f1bc530e1a73ddaae5003fcflorian      VG_(printf)(" tid %u\n", threadp->coretid);
1300328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   {
1301328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      Lock** locksHeldW_P;
1302328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      locksHeldW_P = enumerate_WordSet_into_LockP_vector(
1303328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                       HG_(get_univ_lsets)(),
1304328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                       locksHeldW,
1305328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                       True/*allowed_to_be_invalid*/
1306328d6627c26471332610da3f5a0b9cc3cdd410c7philippe                    );
1307328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      show_LockP_summary_textmode( locksHeldW_P, "" );
1308328d6627c26471332610da3f5a0b9cc3cdd410c7philippe      HG_(free) (locksHeldW_P);
1309328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   }
1310328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   VG_(pp_StackTrace) (ips, n_ips);
1311328d6627c26471332610da3f5a0b9cc3cdd410c7philippe   VG_(printf) ("\n");
1312328d6627c26471332610da3f5a0b9cc3cdd410c7philippe}
1313328d6627c26471332610da3f5a0b9cc3cdd410c7philippe
13148e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianconst HChar* HG_(get_error_name) ( const Error* err )
1315f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1316f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   switch (VG_(get_error_kind)(err)) {
1317f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_Race:           return "Race";
1318f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockUnlocked: return "UnlockUnlocked";
1319f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockForeign:  return "UnlockForeign";
1320f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_UnlockBogus:    return "UnlockBogus";
1321f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_PthAPIerror:    return "PthAPIerror";
1322f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_LockOrder:      return "LockOrder";
1323f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      case XE_Misc:           return "Misc";
1324f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      default: tl_assert(0); /* fill in missing case */
1325f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1326f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1327f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
132819f91bbaedb4caef8a60ce94b0f507193cc0bc10florianBool HG_(recognised_suppression) ( const HChar* name, Supp *su )
1329f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1330f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#  define TRY(_name,_xskind)                   \
1331f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      if (0 == VG_(strcmp)(name, (_name))) {   \
1332f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         VG_(set_supp_kind)(su, (_xskind));    \
1333f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj         return True;                          \
1334f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      }
1335f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("Race",           XS_Race);
1336f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("FreeMemLock",    XS_FreeMemLock);
1337f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("UnlockUnlocked", XS_UnlockUnlocked);
1338f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("UnlockForeign",  XS_UnlockForeign);
1339f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("UnlockBogus",    XS_UnlockBogus);
1340f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("PthAPIerror",    XS_PthAPIerror);
1341f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("LockOrder",      XS_LockOrder);
1342f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   TRY("Misc",           XS_Misc);
1343f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return False;
1344f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj#  undef TRY
1345f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1346f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
134719f91bbaedb4caef8a60ce94b0f507193cc0bc10florianBool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp,
1348362441db825242200142a91bb07c4a0300b36a3ephilippe                                        Int* lineno, Supp* su )
1349f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1350f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* do nothing -- no extra suppression info present.  Return True to
1351f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj      indicate nothing bad happened. */
1352f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   return True;
1353f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1354f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
13558e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianBool HG_(error_matches_suppression) ( const Error* err, const Supp* su )
1356f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
1357f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   switch (VG_(get_supp_kind)(su)) {
1358f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_Race:           return VG_(get_error_kind)(err) == XE_Race;
1359f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked;
1360f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_UnlockForeign:  return VG_(get_error_kind)(err) == XE_UnlockForeign;
1361f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_UnlockBogus:    return VG_(get_error_kind)(err) == XE_UnlockBogus;
1362f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_PthAPIerror:    return VG_(get_error_kind)(err) == XE_PthAPIerror;
1363f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_LockOrder:      return VG_(get_error_kind)(err) == XE_LockOrder;
1364f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   case XS_Misc:           return VG_(get_error_kind)(err) == XE_Misc;
1365f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   //case XS_: return VG_(get_error_kind)(err) == XE_;
1366f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   default: tl_assert(0); /* fill in missing cases */
1367f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   }
1368f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1369f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
13708e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianSizeT HG_(get_extra_suppression_info) ( const Error* err,
1371dbb3584f591710a15a437918c0fc27e300993566florian                                       /*OUT*/HChar* buf, Int nBuf )
1372f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj{
13733e81b8bed1f7ab6848a83f5507487131a6f9d778florian   tl_assert(nBuf >= 1);
1374f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj   /* Do nothing */
13753e81b8bed1f7ab6848a83f5507487131a6f9d778florian   buf[0] = '\0';
13763e81b8bed1f7ab6848a83f5507487131a6f9d778florian   return 0;
1377f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj}
1378f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
13798e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianSizeT HG_(print_extra_suppression_use) ( const Supp* su,
13804e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe                                        /*OUT*/HChar* buf, Int nBuf )
13814e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe{
13823e81b8bed1f7ab6848a83f5507487131a6f9d778florian   tl_assert(nBuf >= 1);
13834e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe   /* Do nothing */
13843e81b8bed1f7ab6848a83f5507487131a6f9d778florian   buf[0] = '\0';
13853e81b8bed1f7ab6848a83f5507487131a6f9d778florian   return 0;
13864e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe}
13874e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe
13888e3fbb5cd8276a7d07d5712bc05f9b3376d81a6aflorianvoid HG_(update_extra_suppression_use) ( const Error* err, const Supp* su )
13894e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe{
13904e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe   /* Do nothing */
13914e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe   return;
13924e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe}
13934e32d67a5b880bf1d871c5141822078d4dcdc3acphilippe
1394f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj
1395f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
1396f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--- end                                              hg_errors.c ---*/
1397f98e1c03ce4bea1fb092cdea5571c41f29f6df9bsewardj/*--------------------------------------------------------------------*/
1398