1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Error management for Helgrind. ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- hg_errors.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Helgrind, a Valgrind tool for detecting errors 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in threaded programs. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2007-2013 OpenWorks Ltd 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info@open-works.co.uk 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_execontext.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_errormgr.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_wordfm.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_xarray.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h" // VG_(clo_xml) 43eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "pub_tool_addrinfo.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "hg_basics.h" 46eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "hg_addrdescr.h" 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "hg_wordset.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "hg_lock_n_thread.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libhb.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "hg_errors.h" /* self */ 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Error management -- storage ---*/ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* maps (by value) strings to a copy of them in ARENA_TOOL */ 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic WordFM* string_table = NULL; 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong HG_(stats__string_table_queries) = 0; 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong HG_(stats__string_table_get_map_size) ( void ) { 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return string_table ? (ULong)VG_(sizeFM)(string_table) : 0; 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word string_table_cmp ( UWord s1, UWord s2 ) { 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 ); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* string_table_strdup ( const HChar* str ) { 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* copy = NULL; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HG_(stats__string_table_queries)++; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!str) 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown str = "(null)"; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!string_table) { 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown string_table = VG_(newFM)( HG_(zalloc), "hg.sts.1", 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HG_(free), string_table_cmp ); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(string_table); 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(lookupFM)( string_table, 82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov NULL, (UWord*)©, (UWord)str )) { 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(copy); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("string_table_strdup: %p -> %p\n", str, copy ); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return copy; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown copy = HG_(strdup)("hg.sts.2", str); 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(copy); 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(addToFM)( string_table, (UWord)copy, (UWord)copy ); 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return copy; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* maps from Lock .unique fields to LockP*s */ 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic WordFM* map_LockN_to_P = NULL; 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong HG_(stats__LockN_to_P_queries) = 0; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong HG_(stats__LockN_to_P_get_map_size) ( void ) { 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return map_LockN_to_P ? (ULong)VG_(sizeFM)(map_LockN_to_P) : 0; 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word lock_unique_cmp ( UWord lk1W, UWord lk2W ) 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Lock* lk1 = (Lock*)lk1W; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Lock* lk2 = (Lock*)lk2W; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockNorP)(lk1) ); 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockNorP)(lk2) ); 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lk1->unique < lk2->unique) return -1; 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lk1->unique > lk2->unique) return 1; 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Given a normal Lock (LockN), convert it to a persistent Lock 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (LockP). In some cases the LockN could be invalid (if it's been 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed), so we enquire, in hg_main.c's admin_locks list, whether it 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov is in fact valid. If allowed_to_be_invalid is True, then it's OK 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for the LockN to be invalid, in which case Lock_INVALID is 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov returned. In all other cases, we insist that the LockN is a valid 121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lock, and return its corresponding LockP. 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Why can LockNs sometimes be invalid? Because they are harvested 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from locksets that are attached to the OldRef info for conflicting 125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov threads. By the time we detect a race, the some of the elements of 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the lockset may have been destroyed by the client, in which case 127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the corresponding Lock structures we maintain will have been freed. 128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov So we check that each LockN is a member of the admin_locks double 130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov linked list of all Lock structures. That stops us prodding around 131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov in potentially freed-up Lock structures. However, it's not quite a 132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov proper check: if a new Lock has been reallocated at the same 133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov address as one which was previously freed, we'll wind up copying 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the new one as the basis for the LockP, which is completely bogus 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov because it is unrelated to the previous Lock that lived there. 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Let's hope that doesn't happen too often. 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/ 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Lock* mk_LockP_from_LockN ( Lock* lkn, 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool allowed_to_be_invalid ) 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Lock* lkp = NULL; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HG_(stats__LockN_to_P_queries)++; 143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* First off, let's do some sanity checks. If 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov allowed_to_be_invalid is False, we _must_ be able to find 'lkn' 146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov in admin_locks; else we must assert. If it is True, it's OK for 147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov it not to be findable, but in that case we must return 148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock_INVALID right away. */ 149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock* lock_list = HG_(get_admin_locks)(); 150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (lock_list) { 151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (lock_list == lkn) 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lock_list = lock_list->admin_next; 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (lock_list == NULL) { 156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We didn't find it. That possibility has to be OK'd by the 157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov caller. */ 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(allowed_to_be_invalid); 159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return Lock_INVALID; 160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* So we must be looking at a valid LockN. */ 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockN)(lkn) ); 164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!map_LockN_to_P) { 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown map_LockN_to_P = VG_(newFM)( HG_(zalloc), "hg.mLPfLN.1", 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HG_(free), lock_unique_cmp ); 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(map_LockN_to_P); 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!VG_(lookupFM)( map_LockN_to_P, NULL, (UWord*)&lkp, (UWord)lkn)) { 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp = HG_(zalloc)( "hg.mLPfLN.2", sizeof(Lock) ); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *lkp = *lkn; 173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lkp->admin_next = NULL; 174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lkp->admin_prev = NULL; 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp->magic = LockP_MAGIC; 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Forget about the bag of lock holders - don't copy that. 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Also, acquired_at should be NULL whenever heldBy is, and vice 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown versa. Also forget about the associated libhb synch object. */ 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp->heldW = False; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp->heldBy = NULL; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp->acquired_at = NULL; 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lkp->hbso = NULL; 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(addToFM)( map_LockN_to_P, (UWord)lkp, (UWord)lkp ); 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockP)(lkp) ); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lkp; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Expand a WordSet of LockN*'s into a NULL-terminated vector of 190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov LockP*'s. Any LockN's that can't be converted into a LockP 191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (because they have been freed, see comment on mk_LockP_from_LockN) 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are converted instead into the value Lock_INVALID. Hence the 193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov returned vector is a sequence: zero or more (valid LockP* or 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov LockN_INVALID), terminated by a NULL. */ 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovLock** enumerate_WordSet_into_LockP_vector( WordSetU* univ_lsets, 197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov WordSetID lockset, 198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool allowed_to_be_invalid ) 199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(univ_lsets); 201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert( HG_(plausibleWS)(univ_lsets, lockset) ); 202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nLocks = HG_(cardinalityWS)(univ_lsets, lockset); 203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock** lockPs = HG_(zalloc)( "hg.eWSiLPa", 204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (nLocks+1) * sizeof(Lock*) ); 205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lockPs); 206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lockPs[nLocks] == NULL); /* pre-NULL terminated */ 207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord* lockNs = NULL; 208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nLockNs = 0; 209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nLocks > 0) { 210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* HG_(getPayloadWS) doesn't assign non-NULL to &lockNs if the 211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lockset is empty; hence the guarding "if". Sigh. */ 212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HG_(getPayloadWS)( &lockNs, &nLockNs, univ_lsets, lockset ); 213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lockNs); 214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord i; 216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Convert to LockPs. */ 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < nLockNs; i++) { 218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lockPs[i] = mk_LockP_from_LockN( (Lock*)lockNs[i], 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov allowed_to_be_invalid ); 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return lockPs; 222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Get the number of useful elements in a vector created by 225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov enumerate_WordSet_into_LockP_vector. Returns both the total number 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov of elements (not including the terminating NULL) and the number of 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov non-Lock_INVALID elements. */ 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void count_LockP_vector ( /*OUT*/UWord* nLocks, 229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /*OUT*/UWord* nLocksValid, 230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock** vec ) 231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(vec); 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *nLocks = *nLocksValid = 0; 234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord n = 0; 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (vec[n]) { 236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (*nLocks)++; 237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (vec[n] != Lock_INVALID) 238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (*nLocksValid)++; 239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov n++; 240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Find out whether 'lk' is in 'vec'. */ 244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool elem_LockP_vector ( Lock** vec, Lock* lk ) 245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(vec); 247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lk); 248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord n = 0; 249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (vec[n]) { 250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (vec[n] == lk) 251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return True; 252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov n++; 253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return False; 255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Errors: 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown race: program counter 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown read or write 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data size 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown previous state 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown current state 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: how does state printing interact with lockset gc? 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Are the locksets in prev/curr state always valid? 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ditto question for the threadsets 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadSets - probably are always valid if Threads 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are never thrown away. 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LockSets - could at least print the lockset elements that 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown correspond to actual locks at the time of printing. Hmm. 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Error kinds */ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_Race=1101, // race 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockUnlocked, // unlocking a not-locked lock 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockForeign, // unlocking a lock held by some other thread 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockBogus, // unlocking an address not known to be a lock 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_PthAPIerror, // error from the POSIX pthreads API 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_LockOrder, // lock order error 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_Misc // misc other error (w/ string to describe it) 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XErrorTag; 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extra contexts for kinds */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XErrorTag tag; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB; 296eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov AddrInfo data_addrinfo; 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool isWrite; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; 299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock** locksHeldW; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* h1_* and h2_* provide some description of a previously 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown observed access with which we are conflicting. */ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* h1_ct; /* non-NULL means h1 info present */ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* h1_ct_mbsegstartEC; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* h1_ct_mbsegendEC; 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* h2_ct; /* non-NULL means h2 info present */ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* h2_ct_accEC; 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int h2_ct_accSzB; 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool h2_ct_accIsW; 309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock** h2_ct_locksHeldW; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Race; 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; /* doing the unlocking */ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Lock* lock; /* lock (that is already unlocked) */ 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } UnlockUnlocked; 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; /* doing the unlocking */ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* owner; /* thread that actually holds the lock */ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Lock* lock; /* lock (that is held by 'owner') */ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } UnlockForeign; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; /* doing the unlocking */ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr lock_ga; /* purported address of the lock */ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } UnlockBogus; 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* fnname; /* persistent, in tool-arena */ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word err; /* pth error code */ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* errstr; /* persistent, in tool-arena */ 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } PthAPIerror; 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; 332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* The first 4 fields describe the previously observed 333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (should-be) ordering. */ 334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr shouldbe_earlier_ga; 335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr shouldbe_later_ga; 336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* shouldbe_earlier_ec; 337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* shouldbe_later_ec; 338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* In principle we need to record two more stacks, from 339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov this thread, when acquiring the locks in the "wrong" 340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov order. In fact the wallclock-later acquisition by this 341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread is recorded in the main stack for this error. 342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov So we only need a stack for the earlier acquisition by 343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov this thread. */ 344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* actual_earlier_ec; 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } LockOrder; 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* thr; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* errstr; /* persistent, in tool-arena */ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* auxstr; /* optional, persistent, in tool-arena */ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* auxctx; /* optional */ 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } Misc; 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } XE; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_XError ( XError* xe ) { 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(xe, 0, sizeof(*xe) ); 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->tag = XE_Race-1; /* bogus */ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extensions of suppressions */ 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enum { 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_Race=1201, /* race */ 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_FreeMemLock, 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_UnlockUnlocked, 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_UnlockForeign, 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_UnlockBogus, 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_PthAPIerror, 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_LockOrder, 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XS_Misc 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XSuppTag; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Updates the copy with address info if necessary. */ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt HG_(update_extra) ( Error* err ) 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError* xe = (XError*)VG_(get_error_extra)(err); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //if (extra != NULL && Undescribed == extra->addrinfo.akind) { 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) ); 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //} 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->tag == XE_Race) { 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Note the set of locks that the thread is (w-)holding. 389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Convert the WordSetID of LockN*'s into a NULL-terminated 390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vector of LockP*'s. We don't expect to encounter any invalid 391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov LockNs in this conversion. */ 392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(xe->XE.Race.thr); 393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe->XE.Race.locksHeldW 394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = enumerate_WordSet_into_LockP_vector( 395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HG_(get_univ_lsets)(), 396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe->XE.Race.thr->locksetW, 397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov False/*!allowed_to_be_invalid*/ 398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ); 399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* See if we can come up with a source level description of the 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown raced-upon address. This is potentially expensive, which is 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why it's only done at the update_extra point, not when the 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error is initially created. */ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Int xxx = 0; 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xxx++; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("HG_(update_extra): " 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%d conflicting-event queries\n", xxx); 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 410eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov HG_(describe_addr) (xe->XE.Race.data_addr, &xe->XE.Race.data_addrinfo); 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* And poke around in the conflicting-event map, to see if we 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can rustle up a plausible-looking conflicting memory access 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to show. */ 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (HG_(clo_history_level) >= 2) { 416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Thr* thrp = NULL; 417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* wherep = NULL; 418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr acc_addr = xe->XE.Race.data_addr; 419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int acc_szB = xe->XE.Race.szB; 420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Thr* acc_thr = xe->XE.Race.thr->hbthr; 421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool acc_isW = xe->XE.Race.isWrite; 422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT conf_szB = 0; 423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool conf_isW = False; 424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov WordSetID conf_locksHeldW = 0; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(!xe->XE.Race.h2_ct_accEC); 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(!xe->XE.Race.h2_ct); 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (libhb_event_map_lookup( 428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov &wherep, &thrp, &conf_szB, &conf_isW, &conf_locksHeldW, 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown acc_thr, acc_addr, acc_szB, acc_isW )) { 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* threadp; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(wherep); 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thrp); 433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov threadp = libhb_get_Thr_hgthread( thrp ); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(threadp); 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accEC = wherep; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct = threadp; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accSzB = (Int)conf_szB; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accIsW = conf_isW; 439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe->XE.Race.h2_ct_locksHeldW 440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = enumerate_WordSet_into_LockP_vector( 441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HG_(get_univ_lsets)(), 442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov conf_locksHeldW, 443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov True/*allowed_to_be_invalid*/ 444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // both NULL or both non-NULL 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( (!!xe->XE.Race.h2_ct) == (!!xe->XE.Race.h2_ct_accEC) ); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sizeof(XError); 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(record_error_Race) ( Thread* thr, 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr data_addr, Int szB, Bool isWrite, 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* h1_ct, 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* h1_ct_segstart, 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* h1_ct_mbsegendEC ) 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Skip any races on locations apparently in GOTPLT sections. This 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is said to be caused by ld.so poking PLT table entries (or 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whatever) when it writes the resolved address of a dynamically 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown linked routine, into the table (or whatever) when it is called 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the first time. */ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgSectKind sect = VG_(DebugInfo_sect_kind)( NULL, 0, data_addr ); 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("XXXXXXXXX RACE on %#lx %s\n", 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown data_addr, VG_(pp_SectKind)(sect)); 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SectPLT is required on ???-linux */ 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sect == Vg_SectGOTPLT) return; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SectPLT is required on ppc32/64-linux */ 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sect == Vg_SectPLT) return; 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_Race; 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.data_addr = data_addr; 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.szB = szB; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.isWrite = isWrite; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.thr = thr; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(isWrite == False || isWrite == True); 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1); 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Skip on the detailed description of the raced-on address at this 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point; it's expensive. Leave it for the update_extra function 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if we ever make it that far. */ 492eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov xe.XE.Race.data_addrinfo.tag = Addr_Undescribed; 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Skip on any of the conflicting-access info at this point. 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // It's expensive to obtain, and this error is more likely than 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // not to be discarded. We'll fill these fields in in 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // HG_(update_extra) just above, assuming the error ever makes 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // it that far (unlikely). 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h2_ct_accSzB = 0; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h2_ct_accIsW = False; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h2_ct_accEC = NULL; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h2_ct = NULL; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h1_ct = h1_ct; 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h1_ct_mbsegstartEC = h1_ct_segstart; 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Race.h1_ct_mbsegendEC = h1_ct_mbsegendEC; 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_Race, data_addr, NULL, &xe ); 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(record_error_UnlockUnlocked) ( Thread* thr, Lock* lk ) 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockN)(lk) ); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_UnlockUnlocked; 521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.UnlockUnlocked.thr 522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = thr; 523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.UnlockUnlocked.lock 524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockUnlocked, 0, NULL, &xe ); 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(record_error_UnlockForeign) ( Thread* thr, 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Thread* owner, Lock* lk ) 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(owner) ); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockN)(lk) ); 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_UnlockForeign; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.UnlockForeign.thr = thr; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.UnlockForeign.owner = owner; 543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.UnlockForeign.lock 544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = mk_LockP_from_LockN(lk, False/*!allowed_to_be_invalid*/); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockForeign, 0, NULL, &xe ); 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(record_error_UnlockBogus) ( Thread* thr, Addr lock_ga ) 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_UnlockBogus; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.UnlockBogus.thr = thr; 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.UnlockBogus.lock_ga = lock_ga; 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_UnlockBogus, 0, NULL, &xe ); 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(record_error_LockOrder)( 568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Thread* thr, 569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr shouldbe_earlier_ga, 570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr shouldbe_later_ga, 571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* shouldbe_earlier_ec, 572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* shouldbe_later_ec, 573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* actual_earlier_ec 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(HG_(clo_track_lockorders)); 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_LockOrder; 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.LockOrder.thr = thr; 582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.LockOrder.shouldbe_earlier_ga = shouldbe_earlier_ga; 583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.LockOrder.shouldbe_earlier_ec = shouldbe_earlier_ec; 584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.LockOrder.shouldbe_later_ga = shouldbe_later_ga; 585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.LockOrder.shouldbe_later_ec = shouldbe_later_ec; 586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe.XE.LockOrder.actual_earlier_ec = actual_earlier_ec; 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_LockOrder, 0, NULL, &xe ); 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid HG_(record_error_PthAPIerror) ( Thread* thr, const HChar* fnname, 595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Word err, const HChar* errstr ) 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(fnname); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(errstr); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_PthAPIerror; 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.PthAPIerror.thr = thr; 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.PthAPIerror.fnname = string_table_strdup(fnname); 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.PthAPIerror.err = err; 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.PthAPIerror.errstr = string_table_strdup(errstr); 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_PthAPIerror, 0, NULL, &xe ); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid HG_(record_error_Misc_w_aux) ( Thread* thr, const HChar* errstr, 615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* auxstr, ExeContext* auxctx ) 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError xe; 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)(thr) ); 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(errstr); 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown init_XError(&xe); 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.tag = XE_Misc; 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Misc.thr = thr; 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Misc.errstr = string_table_strdup(errstr); 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Misc.auxstr = auxstr ? string_table_strdup(auxstr) : NULL; 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe.XE.Misc.auxctx = auxctx; 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // FIXME: tid vs thr 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_ThreadId)(thr->coretid) ); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( thr->coretid != VG_INVALID_THREADID ); 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(maybe_record_error)( thr->coretid, 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XE_Misc, 0, NULL, &xe ); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid HG_(record_error_Misc) ( Thread* thr, const HChar* errstr ) 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HG_(record_error_Misc_w_aux)(thr, errstr, NULL, NULL); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool HG_(eq_Error) ( VgRes not_used, Error* e1, Error* e2 ) 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError *xe1, *xe2; 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2)); 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe1 = (XError*)VG_(get_error_extra)(e1); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe2 = (XError*)VG_(get_error_extra)(e2); 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe1); 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe2); 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_(get_error_kind)(e1)) { 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Race: 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.Race.szB == xe2->XE.Race.szB 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.Race.isWrite == xe2->XE.Race.isWrite 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (HG_(clo_cmp_race_err_addrs) 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? xe1->XE.Race.data_addr == xe2->XE.Race.data_addr 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : True); 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockUnlocked: 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.UnlockUnlocked.thr == xe2->XE.UnlockUnlocked.thr 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.UnlockUnlocked.lock == xe2->XE.UnlockUnlocked.lock; 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockForeign: 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.UnlockForeign.thr == xe2->XE.UnlockForeign.thr 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.UnlockForeign.owner == xe2->XE.UnlockForeign.owner 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.UnlockForeign.lock == xe2->XE.UnlockForeign.lock; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockBogus: 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.UnlockBogus.thr == xe2->XE.UnlockBogus.thr 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.UnlockBogus.lock_ga == xe2->XE.UnlockBogus.lock_ga; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_PthAPIerror: 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.PthAPIerror.thr == xe2->XE.PthAPIerror.thr 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0==VG_(strcmp)(xe1->XE.PthAPIerror.fnname, 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe2->XE.PthAPIerror.fnname) 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && xe1->XE.PthAPIerror.err == xe2->XE.PthAPIerror.err; 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_LockOrder: 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.LockOrder.thr == xe2->XE.LockOrder.thr; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Misc: 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return xe1->XE.Misc.thr == xe2->XE.Misc.thr 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0==VG_(strcmp)(xe1->XE.Misc.errstr, xe2->XE.Misc.errstr); 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Error management -- printing ---*/ 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a printf-style operation on either the XML or normal output 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown channel, depending on the setting of VG_(clo_xml). 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void emit_WRK ( const HChar* format, va_list vargs ) 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_xml)) { 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vprintf_xml)(format, vargs); 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)(Vg_UserMsg, format, vargs); 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2); 701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void emit ( const HChar* format, ... ) 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list vargs; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_start(vargs, format); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit_WRK(format, vargs); 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_end(vargs); 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Announce (that is, print the point-of-creation) of 'thr'. Only do 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this once, as we only want to see these announcements once per 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread. Returned Bool indicates whether or not an announcement was 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown made. 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool announce_one_thread ( Thread* thr ) 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(HG_(is_sane_Thread)(thr)); 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thr->errmsg_index >= 1); 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thr->announced) 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_xml)) { 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf_xml)("<announcethread>\n"); 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf_xml)(" <hthreadid>%d</hthreadid>\n", thr->errmsg_index); 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thr->errmsg_index == 1) { 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thr->created_at == NULL); 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf_xml)(" <isrootthread></isrootthread>\n"); 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thr->created_at != NULL); 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( thr->created_at ); 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf_xml)("</announcethread>\n\n"); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("---Thread-Announcement----------" 738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "--------------------------------" "\n"); 739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\n"); 740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thr->errmsg_index == 1) { 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thr->created_at == NULL); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread #%d is the program's root thread\n", 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thr->errmsg_index); 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(thr->created_at != NULL); 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Thread #%d was created\n", 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thr->errmsg_index); 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( thr->created_at ); 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thr->announced = True; 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Announce 'lk'. */ 761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void announce_LockP ( Lock* lk ) 762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lk); 764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (lk == Lock_INVALID) 765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; /* Can't be announced -- we know nothing about it. */ 766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lk->magic == LockP_MAGIC); 767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!lk->appeared_at) 768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; /* There's nothing we can show */ 769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_xml)) { 771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* fixme: add announcement */ 772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)( "Lock at %p was first observed\n", 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)lk->guestaddr ); 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)( lk->appeared_at ); 776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\n"); 777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Announce (that is, print point-of-first-observation) for the 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov locks in 'lockvec' and, if non-NULL, 'lockvec2'. */ 782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void announce_combined_LockP_vecs ( Lock** lockvec, 783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock** lockvec2 ) 784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord i; 786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(lockvec); 787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; lockvec[i]; i++) { 788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov announce_LockP(lockvec[i]); 789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (lockvec2) { 791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; lockvec2[i]; i++) { 792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Lock* lk = lockvec2[i]; 793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!elem_LockP_vector(lockvec, lk)) 794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov announce_LockP(lk); 795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void show_LockP_summary_textmode ( Lock** locks, const HChar* pre ) 801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(locks); 803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord i; 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nLocks = 0, nLocksValid = 0; 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov count_LockP_vector(&nLocks, &nLocksValid, locks); 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(nLocksValid <= nLocks); 807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nLocks == 0) { 809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)( "%sLocks held: none", pre ); 810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)( "%sLocks held: %lu, at address%s ", 812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pre, nLocks, nLocksValid == 1 ? "" : "es" ); 813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nLocks > 0) { 816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < nLocks; i++) { 817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (locks[i] == Lock_INVALID) 818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov continue; 819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)( "%p", (void*)locks[i]->guestaddr); 820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (locks[i+1] != NULL) 821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)(" "); 822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (nLocksValid < nLocks) 824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)(" (and %lu that can't be shown)", nLocks - nLocksValid); 825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\n"); 827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the "this error is due to be printed shortly; so have a 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown look at it any print any preamble you want" function. We use it to 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce any previously un-announced threads in the upcoming error 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown message. 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(before_pp_Error) ( Error* err ) 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError* xe; 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(err); 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe = (XError*)VG_(get_error_extra)(err); 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe); 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_(get_error_kind)(err)) { 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Misc: 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.Misc.thr ); 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_LockOrder: 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.LockOrder.thr ); 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_PthAPIerror: 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.PthAPIerror.thr ); 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockBogus: 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.UnlockBogus.thr ); 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockForeign: 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.UnlockForeign.thr ); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.UnlockForeign.owner ); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockUnlocked: 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.UnlockUnlocked.thr ); 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Race: 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.Race.thr ); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h2_ct) 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.Race.h2_ct ); 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct) 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown announce_one_thread( xe->XE.Race.h1_ct ); 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid HG_(pp_Error) ( Error* err ) 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Bool xml = VG_(clo_xml); /* a shorthand, that's all */ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!xml) { 879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("--------------------------------" 880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "--------------------------------" "\n"); 881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("\n"); 882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown XError *xe = (XError*)VG_(get_error_extra)(err); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe); 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (xml) 888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( " <kind>%s</kind>\n", HG_(get_error_name)(err)); 889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_(get_error_kind)(err)) { 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Misc: { 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.Misc.thr ) ); 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Thread #%d: %s</text>\n", 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.Misc.thr->errmsg_index, 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Misc.errstr ); 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.Misc.thr->errmsg_index ); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Misc.auxstr) { 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit(" <auxwhat>%s</auxwhat>\n", xe->XE.Misc.auxstr); 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Misc.auxctx) 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Misc.auxctx ); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Thread #%d: %s\n", 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.Misc.thr->errmsg_index, 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Misc.errstr ); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Misc.auxstr) { 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit(" %s\n", xe->XE.Misc.auxstr); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Misc.auxctx) 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Misc.auxctx ); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_LockOrder: { 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.LockOrder.thr ) ); 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Thread #%d: lock order \"%p before %p\" " 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "violated</text>\n", 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.LockOrder.thr->errmsg_index, 936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_earlier_ga, 937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_later_ga ); 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.LockOrder.thr->errmsg_index ); 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (xe->XE.LockOrder.shouldbe_earlier_ec 943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && xe->XE.LockOrder.shouldbe_later_ec) { 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>Required order was established by " 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "acquisition of lock at %p</auxwhat>\n", 946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_earlier_ga ); 947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec ); 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>followed by a later acquisition " 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "of lock at %p</auxwhat>\n", 950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_later_ga ); 951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec ); 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Thread #%d: lock order \"%p before %p\" violated\n", 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.LockOrder.thr->errmsg_index, 958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_earlier_ga, 959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_later_ga ); 960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "\n" ); 961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "Observed (incorrect) order is: " 962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "acquisition of lock at %p\n", 963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_later_ga); 964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (xe->XE.LockOrder.actual_earlier_ec) { 965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)(xe->XE.LockOrder.actual_earlier_ec); 966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit(" (stack unavailable)\n"); 968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "\n" ); 970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit(" followed by a later acquisition of lock at %p\n", 971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_earlier_ga); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (xe->XE.LockOrder.shouldbe_earlier_ec 974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && xe->XE.LockOrder.shouldbe_later_ec) { 975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit("\n"); 976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "Required order was established by " 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "acquisition of lock at %p\n", 978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_earlier_ga ); 979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_earlier_ec ); 980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "\n" ); 981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( " followed by a later acquisition of lock at %p\n", 982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (void*)xe->XE.LockOrder.shouldbe_later_ga ); 983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(pp_ExeContext)( xe->XE.LockOrder.shouldbe_later_ec ); 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_PthAPIerror: { 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.PthAPIerror.thr ) ); 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( 998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov " <text>Thread #%d's call to %pS failed</text>\n", 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.PthAPIerror.thr->errmsg_index, 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.PthAPIerror.fnname ); 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.PthAPIerror.thr->errmsg_index ); 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <what>with error code %ld (%s)</what>\n", 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr ); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "Thread #%d's call to %pS failed\n", 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.PthAPIerror.thr->errmsg_index, 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.PthAPIerror.fnname ); 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " with error code %ld (%s)\n", 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.PthAPIerror.err, xe->XE.PthAPIerror.errstr ); 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockBogus: { 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockBogus.thr ) ); 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Thread #%d unlocked an invalid " 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "lock at %p</text>\n", 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockBogus.thr->errmsg_index, 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockBogus.lock_ga ); 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockBogus.thr->errmsg_index ); 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Thread #%d unlocked an invalid lock at %p\n", 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockBogus.thr->errmsg_index, 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockBogus.lock_ga ); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockForeign: { 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockForeign.lock ) ); 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.owner ) ); 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockForeign.thr ) ); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Thread #%d unlocked lock at %p " 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "currently held by thread #%d</text>\n", 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.thr->errmsg_index, 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockForeign.lock->guestaddr, 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.thr->errmsg_index ); 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.UnlockForeign.lock->appeared_at) { 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n", 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockForeign.lock->guestaddr ); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at ); 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Thread #%d unlocked lock at %p " 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "currently held by thread #%d\n", 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.thr->errmsg_index, 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockForeign.lock->guestaddr, 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockForeign.owner->errmsg_index ); 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.UnlockForeign.lock->appeared_at) { 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " Lock at %p was first observed\n", 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockForeign.lock->guestaddr ); 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.UnlockForeign.lock->appeared_at ); 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockUnlocked: { 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_LockP)( xe->XE.UnlockUnlocked.lock ) ); 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.UnlockUnlocked.thr ) ); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Thread #%d unlocked a " 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "not-locked lock at %p</text>\n", 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockUnlocked.thr->errmsg_index, 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockUnlocked.thr->errmsg_index ); 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.UnlockUnlocked.lock->appeared_at) { 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>Lock at %p was first observed</auxwhat>\n", 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at ); 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Thread #%d unlocked a not-locked lock at %p\n", 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.UnlockUnlocked.thr->errmsg_index, 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.UnlockUnlocked.lock->appeared_at) { 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " Lock at %p was first observed\n", 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)xe->XE.UnlockUnlocked.lock->guestaddr ); 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.UnlockUnlocked.lock->appeared_at ); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Race: { 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr err_ga; 1134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* what; 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB; 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = xe->XE.Race.isWrite ? "write" : "read"; 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown szB = xe->XE.Race.szB; 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown err_ga = VG_(get_error_address)(err); 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.Race.thr )); 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h2_ct) 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert( HG_(is_sane_Thread)( xe->XE.Race.h2_ct )); 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xml) { 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------ XML ------ */ 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xwhat>\n" ); 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>Possible data race during %s of size %d " 1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "at %p by thread #%d</text>\n", 1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index ); 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)xe->XE.Race.thr->errmsg_index ); 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " </xwhat>\n" ); 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h2_ct) { 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xauxwhat>\n"); 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>This conflicts with a previous %s of size %d " 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by thread #%d</text>\n", 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accIsW ? "write" : "read", 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accSzB, 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct->errmsg_index ); 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct->errmsg_index); 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit(" </xauxwhat>\n"); 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC ); 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct) { 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <xauxwhat>\n"); 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <text>This conflicts with a previous access " 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by thread #%d, after</text>\n", 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h1_ct->errmsg_index ); 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <hthreadid>%d</hthreadid>\n", 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h1_ct->errmsg_index ); 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit(" </xauxwhat>\n"); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct_mbsegstartEC) { 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC ); 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>(the start of the thread)</auxwhat>\n" ); 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>but before</auxwhat>\n" ); 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct_mbsegendEC) { 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC ); 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " <auxwhat>(the end of the the thread)</auxwhat>\n" ); 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------ Text ------ */ 1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov announce_combined_LockP_vecs( xe->XE.Race.locksHeldW, 1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov xe->XE.Race.h2_ct_locksHeldW ); 1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( "Possible data race during %s of size %d " 1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "at %p by thread #%d\n", 1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov what, szB, (void*)err_ga, (Int)xe->XE.Race.thr->errmsg_index ); 1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(xe->XE.Race.locksHeldW); 1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_LockP_summary_textmode( xe->XE.Race.locksHeldW, "" ); 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( VG_(get_error_where)(err) ); 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h2_ct) { 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(xe->XE.Race.h2_ct_accEC); // assured by update_extra 1207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(xe->XE.Race.h2_ct_locksHeldW); 1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "\n" ); 1209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov emit( "This conflicts with a previous %s of size %d " 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "by thread #%d\n", 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accIsW ? "write" : "read", 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct_accSzB, 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h2_ct->errmsg_index ); 1214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov show_LockP_summary_textmode( xe->XE.Race.h2_ct_locksHeldW, "" ); 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h2_ct_accEC ); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct) { 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " This conflicts with a previous access by thread #%d, " 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "after\n", 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xe->XE.Race.h1_ct->errmsg_index ); 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct_mbsegstartEC) { 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegstartEC ); 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " (the start of the thread)\n" ); 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " but before\n" ); 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (xe->XE.Race.h1_ct_mbsegendEC) { 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)( xe->XE.Race.h1_ct_mbsegendEC ); 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown emit( " (the end of the the thread)\n" ); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1236eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_(pp_addrinfo) (err_ga, &xe->XE.Race.data_addrinfo); 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* case XE_Race */ 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* case XE_Race */ 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (VG_(get_error_kind)(err)) */ 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst HChar* HG_(get_error_name) ( Error* err ) 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_(get_error_kind)(err)) { 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Race: return "Race"; 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockUnlocked: return "UnlockUnlocked"; 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockForeign: return "UnlockForeign"; 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_UnlockBogus: return "UnlockBogus"; 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_PthAPIerror: return "PthAPIerror"; 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_LockOrder: return "LockOrder"; 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XE_Misc: return "Misc"; 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); /* fill in missing case */ 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool HG_(recognised_suppression) ( const HChar* name, Supp *su ) 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define TRY(_name,_xskind) \ 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(name, (_name))) { \ 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_supp_kind)(su, (_xskind)); \ 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; \ 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("Race", XS_Race); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("FreeMemLock", XS_FreeMemLock); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("UnlockUnlocked", XS_UnlockUnlocked); 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("UnlockForeign", XS_UnlockForeign); 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("UnlockBogus", XS_UnlockBogus); 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("PthAPIerror", XS_PthAPIerror); 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("LockOrder", XS_LockOrder); 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRY("Misc", XS_Misc); 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef TRY 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool HG_(read_extra_suppression_info) ( Int fd, HChar** bufpp, SizeT* nBufp, 1279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int* lineno, Supp* su ) 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do nothing -- no extra suppression info present. Return True to 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicate nothing bad happened. */ 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool HG_(error_matches_suppression) ( Error* err, Supp* su ) 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (VG_(get_supp_kind)(su)) { 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_Race: return VG_(get_error_kind)(err) == XE_Race; 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_UnlockUnlocked: return VG_(get_error_kind)(err) == XE_UnlockUnlocked; 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_UnlockForeign: return VG_(get_error_kind)(err) == XE_UnlockForeign; 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_UnlockBogus: return VG_(get_error_kind)(err) == XE_UnlockBogus; 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_PthAPIerror: return VG_(get_error_kind)(err) == XE_PthAPIerror; 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_LockOrder: return VG_(get_error_kind)(err) == XE_LockOrder; 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case XS_Misc: return VG_(get_error_kind)(err) == XE_Misc; 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //case XS_: return VG_(get_error_kind)(err) == XE_; 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: tl_assert(0); /* fill in missing cases */ 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool HG_(get_extra_suppression_info) ( Error* err, 1302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/HChar* buf, Int nBuf ) 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do nothing */ 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool HG_(print_extra_suppression_use) ( Supp* su, 1309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/HChar* buf, Int nBuf ) 1310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 1311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Do nothing */ 1312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; 1313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 1314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid HG_(update_extra_suppression_use) ( Error* err, Supp* su ) 1316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 1317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Do nothing */ 1318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 1319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 1320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end hg_errors.c ---*/ 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1325