blob: ed93cbf3bf09673ea379e5d27b2641320a140e37 [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardjaf44c822007-11-25 14:01:38 +00002/*
bart86562bd2009-02-16 19:43:56 +00003 This file is part of drd, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00004
bart86562bd2009-02-16 19:43:56 +00005 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
sewardjaf44c822007-11-25 14:01:38 +00006
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
bart886b87c2008-06-28 13:40:41 +000026#include "drd_clientobj.h" /* struct mutex_info */
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_error.h"
28#include "drd_malloc_wrappers.h"
bart886b87c2008-06-28 13:40:41 +000029#include "drd_mutex.h"
30#include "drd_suppression.h" /* drd_start_suppression() */
31#include "pub_drd_bitmap.h" /* LHS_W, ... */
sewardjaf44c822007-11-25 14:01:38 +000032#include "pub_tool_vki.h"
33#include "pub_tool_basics.h"
bart886b87c2008-06-28 13:40:41 +000034#include "pub_tool_libcassert.h" /* tl_assert() */
35#include "pub_tool_libcbase.h" /* strlen() */
36#include "pub_tool_libcfile.h" /* VG_(get_startup_wd)() */
37#include "pub_tool_libcprint.h" /* VG_(printf)() */
sewardjaf44c822007-11-25 14:01:38 +000038#include "pub_tool_machine.h"
bart886b87c2008-06-28 13:40:41 +000039#include "pub_tool_mallocfree.h" /* VG_(malloc), VG_(free) */
40#include "pub_tool_threadstate.h" /* VG_(get_pthread_id)() */
41#include "pub_tool_tooliface.h" /* VG_(needs_tool_errors)() */
sewardjaf44c822007-11-25 14:01:38 +000042
43
bart16d76e52008-03-18 17:08:08 +000044/* Local variables. */
45
bartd2c5eae2009-02-21 15:27:04 +000046static Bool s_show_conflicting_segments = True;
bart16d76e52008-03-18 17:08:08 +000047
48
bart246fbf22009-02-15 14:46:17 +000049void DRD_(set_show_conflicting_segments)(const Bool scs)
bart16d76e52008-03-18 17:08:08 +000050{
bartbedfd232009-03-26 19:07:15 +000051 s_show_conflicting_segments = scs;
bart16d76e52008-03-18 17:08:08 +000052}
53
bart246fbf22009-02-15 14:46:17 +000054/**
55 * Describe a data address range [a,a+len[ as good as possible, for error
56 * messages, putting the result in ai.
bart886b87c2008-06-28 13:40:41 +000057 */
bartff1252a2008-03-16 17:27:25 +000058static
bartd2c5eae2009-02-21 15:27:04 +000059void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai)
sewardjaf44c822007-11-25 14:01:38 +000060{
bartbedfd232009-03-26 19:07:15 +000061 Addr data;
sewardjaf44c822007-11-25 14:01:38 +000062
bartbedfd232009-03-26 19:07:15 +000063 if (DRD_(heap_addrinfo)(a, &data, &ai->size, &ai->lastchange))
64 {
65 ai->akind = eMallocd;
66 ai->rwoffset = a - data;
67 }
68 else
69 {
70 ai->akind = eUnknown;
71 }
sewardjaf44c822007-11-25 14:01:38 +000072}
73
bart246fbf22009-02-15 14:46:17 +000074/**
75 * Report where an object has been observed for the first time. The printed
76 * call stack will either refer to a pthread_*_init() or a pthread_*lock()
77 * call.
bart886b87c2008-06-28 13:40:41 +000078 */
bartd2c5eae2009-02-21 15:27:04 +000079static void first_observed(const Addr obj)
bart886b87c2008-06-28 13:40:41 +000080{
bartbedfd232009-03-26 19:07:15 +000081 DrdClientobj* cl;
bart886b87c2008-06-28 13:40:41 +000082
bartbedfd232009-03-26 19:07:15 +000083 cl = DRD_(clientobj_get_any)(obj);
84 if (cl)
85 {
86 tl_assert(cl->any.first_observed_at);
87 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +000088 "%s 0x%lx was first observed at:\n",
bartbedfd232009-03-26 19:07:15 +000089 DRD_(clientobj_type_name)(cl->any.type),
90 obj);
91 VG_(pp_ExeContext)(cl->any.first_observed_at);
92 }
bart886b87c2008-06-28 13:40:41 +000093}
94
sewardjaf44c822007-11-25 14:01:38 +000095static
bartd2c5eae2009-02-21 15:27:04 +000096void drd_report_data_race(Error* const err, const DataRaceErrInfo* const dri)
sewardjaf44c822007-11-25 14:01:38 +000097{
bartbedfd232009-03-26 19:07:15 +000098 AddrInfo ai;
sewardj1e29ebc2009-07-15 14:49:17 +000099
100 XArray* /* of HChar */ descr1
101 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.1",
102 VG_(free), sizeof(HChar) );
103 XArray* /* of HChar */ descr2
104 = VG_(newXA)( VG_(malloc), "drd.error.drdr2.2",
105 VG_(free), sizeof(HChar) );
sewardjaf44c822007-11-25 14:01:38 +0000106
bartbedfd232009-03-26 19:07:15 +0000107 tl_assert(dri);
108 tl_assert(dri->addr);
109 tl_assert(dri->size > 0);
110 tl_assert(descr1);
111 tl_assert(descr2);
bartb515eb12008-03-07 18:52:38 +0000112
sewardj1e29ebc2009-07-15 14:49:17 +0000113 (void) VG_(get_data_description)(descr1, descr2, dri->addr);
114 /* If there's nothing in descr1/2, free them. Why is it safe to to
115 VG_(indexXA) at zero here? Because VG_(get_data_description)
116 guarantees to zero terminate descr1/2 regardless of the outcome
117 of the call. So there's always at least one element in each XA
118 after the call.
119 */
120 if (0 == VG_(strlen)( VG_(indexXA)( descr1, 0 ))) {
121 VG_(deleteXA)( descr1 );
122 descr1 = NULL;
123 }
124 if (0 == VG_(strlen)( VG_(indexXA)( descr2, 0 ))) {
125 VG_(deleteXA)( descr2 );
126 descr2 = NULL;
127 }
128 /* Assume (assert) that VG_(get_data_description) fills in descr1
129 before it fills in descr2 */
130 if (descr1 == NULL)
131 tl_assert(descr2 == NULL);
132 /* So anyway. Do we have something useful? */
133 if (descr1 == NULL)
bartbedfd232009-03-26 19:07:15 +0000134 {
sewardj1e29ebc2009-07-15 14:49:17 +0000135 /* No. Do Plan B. */
bartbedfd232009-03-26 19:07:15 +0000136 describe_malloced_addr(dri->addr, dri->size, &ai);
137 }
138 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000139 "Conflicting %s by thread %d/%d at 0x%08lx size %ld\n",
bartbedfd232009-03-26 19:07:15 +0000140 dri->access_type == eStore ? "store" : "load",
141 DRD_(DrdThreadIdToVgThreadId)(dri->tid),
142 dri->tid,
143 dri->addr,
144 dri->size);
145 VG_(pp_ExeContext)(VG_(get_error_where)(err));
sewardj1e29ebc2009-07-15 14:49:17 +0000146 if (descr1 != NULL)
bartbedfd232009-03-26 19:07:15 +0000147 {
sewardj1e29ebc2009-07-15 14:49:17 +0000148 VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr1, 0));
149 if (descr2 != NULL)
150 VG_(message)(Vg_UserMsg, "%s\n", (HChar*)VG_(indexXA)(descr2, 0));
bartbedfd232009-03-26 19:07:15 +0000151 }
152 else if (ai.akind == eMallocd && ai.lastchange)
153 {
bartfca00e52008-07-09 12:43:35 +0000154 VG_(message)(Vg_UserMsg,
bartbedfd232009-03-26 19:07:15 +0000155 "Address 0x%lx is at offset %ld from 0x%lx."
sewardj1e29ebc2009-07-15 14:49:17 +0000156 " Allocation context:\n",
bartbedfd232009-03-26 19:07:15 +0000157 dri->addr, ai.rwoffset, dri->addr - ai.rwoffset);
158 VG_(pp_ExeContext)(ai.lastchange);
159 }
160 else
161 {
162 char sect_name[64];
163 VgSectKind sect_kind;
bartf993b872008-04-01 18:19:50 +0000164
bartbedfd232009-03-26 19:07:15 +0000165 sect_kind = VG_(seginfo_sect_kind)(sect_name, sizeof(sect_name),
166 dri->addr);
167 if (sect_kind != Vg_SectUnknown)
168 {
169 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000170 "Allocation context: %s section of %s\n",
bartbedfd232009-03-26 19:07:15 +0000171 VG_(pp_SectKind)(sect_kind),
172 sect_name);
173 }
174 else
175 {
sewardj1e29ebc2009-07-15 14:49:17 +0000176 VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n");
bartbedfd232009-03-26 19:07:15 +0000177 }
178 }
179 if (s_show_conflicting_segments)
180 {
181 DRD_(thread_report_conflicting_segments)(dri->tid,
182 dri->addr, dri->size,
183 dri->access_type);
184 }
185
sewardj1e29ebc2009-07-15 14:49:17 +0000186 if (descr2)
187 VG_(deleteXA)(descr2);
188 if (descr1)
189 VG_(deleteXA)(descr1);
sewardjaf44c822007-11-25 14:01:38 +0000190}
191
bartd2c5eae2009-02-21 15:27:04 +0000192static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
sewardjaf44c822007-11-25 14:01:38 +0000193{
bartbedfd232009-03-26 19:07:15 +0000194 return False;
sewardjaf44c822007-11-25 14:01:38 +0000195}
196
sewardj1e29ebc2009-07-15 14:49:17 +0000197static void drd_tool_error_before_pp(Error* const e)
198{
199 /* No need to do anything; drd_tool_error_pp does all
200 the work. */
201}
202
bartd2c5eae2009-02-21 15:27:04 +0000203static void drd_tool_error_pp(Error* const e)
sewardjaf44c822007-11-25 14:01:38 +0000204{
bartd45d9952009-05-31 18:53:54 +0000205 static DrdThreadId s_last_tid_printed = 1;
206 DrdThreadId* err_extra;
207
208 err_extra = VG_(get_error_extra)(e);
209
210 if (err_extra && *err_extra != s_last_tid_printed)
211 {
sewardj1e29ebc2009-07-15 14:49:17 +0000212 VG_(umsg)("%s:\n", DRD_(thread_get_name)(*err_extra));
bartd45d9952009-05-31 18:53:54 +0000213 s_last_tid_printed = *err_extra;
214 }
215
bartbedfd232009-03-26 19:07:15 +0000216 switch (VG_(get_error_kind)(e))
217 {
218 case DataRaceErr: {
219 drd_report_data_race(e, VG_(get_error_extra)(e));
220 break;
221 }
222 case MutexErr: {
223 MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
224 tl_assert(p);
225 if (p->recursion_count >= 0)
226 {
227 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000228 "%s: mutex 0x%lx, recursion count %d, owner %d.\n",
bartbedfd232009-03-26 19:07:15 +0000229 VG_(get_error_string)(e),
230 p->mutex,
231 p->recursion_count,
232 p->owner);
233 }
234 else
235 {
236 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000237 "The object at address 0x%lx is not a mutex.\n",
bartbedfd232009-03-26 19:07:15 +0000238 p->mutex);
239 }
240 VG_(pp_ExeContext)(VG_(get_error_where)(e));
241 first_observed(p->mutex);
242 break;
243 }
244 case CondErr: {
245 CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
bart6b717612008-03-24 09:29:38 +0000246 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000247 "%s: cond 0x%lx\n",
bart6b717612008-03-24 09:29:38 +0000248 VG_(get_error_string)(e),
bartbedfd232009-03-26 19:07:15 +0000249 cdei->cond);
250 VG_(pp_ExeContext)(VG_(get_error_where)(e));
251 first_observed(cdei->cond);
252 break;
253 }
254 case CondDestrErr: {
255 CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
bart6b717612008-03-24 09:29:38 +0000256 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000257 "%s: cond 0x%lx, mutex 0x%lx locked by thread %d/%d\n",
bartbedfd232009-03-26 19:07:15 +0000258 VG_(get_error_string)(e),
259 cdi->cond, cdi->mutex,
bartd45d9952009-05-31 18:53:54 +0000260 DRD_(DrdThreadIdToVgThreadId)(cdi->owner), cdi->owner);
bartbedfd232009-03-26 19:07:15 +0000261 VG_(pp_ExeContext)(VG_(get_error_where)(e));
262 first_observed(cdi->mutex);
263 break;
264 }
265 case CondRaceErr: {
266 CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
bartd2c5eae2009-02-21 15:27:04 +0000267 VG_(message)(Vg_UserMsg,
bartbedfd232009-03-26 19:07:15 +0000268 "Probably a race condition: condition variable 0x%lx has"
269 " been signaled but the associated mutex 0x%lx is not"
sewardj1e29ebc2009-07-15 14:49:17 +0000270 " locked by the signalling thread.\n",
bartbedfd232009-03-26 19:07:15 +0000271 cei->cond, cei->mutex);
272 VG_(pp_ExeContext)(VG_(get_error_where)(e));
273 first_observed(cei->cond);
274 first_observed(cei->mutex);
275 break;
276 }
277 case CondWaitErr: {
278 CondWaitErrInfo* cwei = (CondWaitErrInfo*)(VG_(get_error_extra)(e));
279 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000280 "%s: condition variable 0x%lx, mutexes 0x%lx and 0x%lx\n",
bartbedfd232009-03-26 19:07:15 +0000281 VG_(get_error_string)(e),
282 cwei->cond,
283 cwei->mutex1,
284 cwei->mutex2);
285 VG_(pp_ExeContext)(VG_(get_error_where)(e));
286 first_observed(cwei->cond);
287 first_observed(cwei->mutex1);
288 first_observed(cwei->mutex2);
289 break;
290 }
291 case SemaphoreErr: {
292 SemaphoreErrInfo* sei = (SemaphoreErrInfo*)(VG_(get_error_extra)(e));
293 tl_assert(sei);
294 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000295 "%s: semaphore 0x%lx\n",
bartbedfd232009-03-26 19:07:15 +0000296 VG_(get_error_string)(e),
297 sei->semaphore);
298 VG_(pp_ExeContext)(VG_(get_error_where)(e));
299 first_observed(sei->semaphore);
300 break;
301 }
302 case BarrierErr: {
303 BarrierErrInfo* bei = (BarrierErrInfo*)(VG_(get_error_extra)(e));
304 tl_assert(bei);
305 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000306 "%s: barrier 0x%lx\n",
bartbedfd232009-03-26 19:07:15 +0000307 VG_(get_error_string)(e),
308 bei->barrier);
309 VG_(pp_ExeContext)(VG_(get_error_where)(e));
310 if (bei->other_context)
311 {
312 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000313 "Conflicting wait call by thread %d/%d:\n",
bartbedfd232009-03-26 19:07:15 +0000314 DRD_(DrdThreadIdToVgThreadId)(bei->other_tid),
315 bei->other_tid);
316 VG_(pp_ExeContext)(bei->other_context);
317 }
318 first_observed(bei->barrier);
319 break;
320 }
321 case RwlockErr: {
322 RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
323 tl_assert(p);
324 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000325 "%s: rwlock 0x%lx.\n",
bartbedfd232009-03-26 19:07:15 +0000326 VG_(get_error_string)(e),
327 p->rwlock);
328 VG_(pp_ExeContext)(VG_(get_error_where)(e));
329 first_observed(p->rwlock);
330 break;
331 }
332 case HoldtimeErr: {
333 HoldtimeErrInfo* p =(HoldtimeErrInfo*)(VG_(get_error_extra)(e));
334 tl_assert(p);
335 tl_assert(p->acquired_at);
sewardj1e29ebc2009-07-15 14:49:17 +0000336 VG_(message)(Vg_UserMsg, "Acquired at:\n");
bartbedfd232009-03-26 19:07:15 +0000337 VG_(pp_ExeContext)(p->acquired_at);
338 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000339 "Lock on %s 0x%lx was held during %d ms (threshold: %d ms).\n",
bartbedfd232009-03-26 19:07:15 +0000340 VG_(get_error_string)(e),
341 p->synchronization_object,
342 p->hold_time_ms,
343 p->threshold_ms);
344 VG_(pp_ExeContext)(VG_(get_error_where)(e));
345 first_observed(p->synchronization_object);
346 break;
347 }
348 case GenericErr: {
349 //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e));
sewardj1e29ebc2009-07-15 14:49:17 +0000350 VG_(message)(Vg_UserMsg, "%s\n", VG_(get_error_string)(e));
bartbedfd232009-03-26 19:07:15 +0000351 VG_(pp_ExeContext)(VG_(get_error_where)(e));
352 break;
353 }
354 default:
355 VG_(message)(Vg_UserMsg,
sewardj1e29ebc2009-07-15 14:49:17 +0000356 "%s\n",
bartbedfd232009-03-26 19:07:15 +0000357 VG_(get_error_string)(e));
358 VG_(pp_ExeContext)(VG_(get_error_where)(e));
359 break;
360 }
sewardjaf44c822007-11-25 14:01:38 +0000361}
362
bartd2c5eae2009-02-21 15:27:04 +0000363static UInt drd_tool_error_update_extra(Error* e)
sewardjaf44c822007-11-25 14:01:38 +0000364{
bartbedfd232009-03-26 19:07:15 +0000365 switch (VG_(get_error_kind)(e))
366 {
367 case DataRaceErr:
368 return sizeof(DataRaceErrInfo);
369 case MutexErr:
370 return sizeof(MutexErrInfo);
371 case CondErr:
372 return sizeof(CondErrInfo);
373 case CondDestrErr:
374 return sizeof(CondDestrErrInfo);
375 case CondRaceErr:
376 return sizeof(CondRaceErrInfo);
377 case CondWaitErr:
378 return sizeof(CondWaitErrInfo);
379 case SemaphoreErr:
380 return sizeof(SemaphoreErrInfo);
381 case BarrierErr:
382 return sizeof(BarrierErrInfo);
383 case RwlockErr:
384 return sizeof(RwlockErrInfo);
385 case HoldtimeErr:
386 return sizeof(HoldtimeErrInfo);
387 case GenericErr:
388 return sizeof(GenericErrInfo);
389 default:
390 tl_assert(False);
391 break;
392 }
sewardjaf44c822007-11-25 14:01:38 +0000393}
394
bartd2c5eae2009-02-21 15:27:04 +0000395static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
sewardjaf44c822007-11-25 14:01:38 +0000396{
bartbedfd232009-03-26 19:07:15 +0000397 SuppKind skind = 0;
sewardjaf44c822007-11-25 14:01:38 +0000398
bartbedfd232009-03-26 19:07:15 +0000399 if (VG_(strcmp)(name, STR_DataRaceErr) == 0)
400 ;
401 else if (VG_(strcmp)(name, STR_MutexErr) == 0)
402 ;
403 else if (VG_(strcmp)(name, STR_CondErr) == 0)
404 ;
405 else if (VG_(strcmp)(name, STR_CondDestrErr) == 0)
406 ;
407 else if (VG_(strcmp)(name, STR_CondRaceErr) == 0)
408 ;
409 else if (VG_(strcmp)(name, STR_CondWaitErr) == 0)
410 ;
411 else if (VG_(strcmp)(name, STR_SemaphoreErr) == 0)
412 ;
413 else if (VG_(strcmp)(name, STR_BarrierErr) == 0)
414 ;
415 else if (VG_(strcmp)(name, STR_RwlockErr) == 0)
416 ;
417 else if (VG_(strcmp)(name, STR_HoldtimeErr) == 0)
418 ;
419 else if (VG_(strcmp)(name, STR_GenericErr) == 0)
420 ;
421 else
422 return False;
sewardjaf44c822007-11-25 14:01:38 +0000423
bartbedfd232009-03-26 19:07:15 +0000424 VG_(set_supp_kind)(supp, skind);
425 return True;
sewardjaf44c822007-11-25 14:01:38 +0000426}
427
bart246fbf22009-02-15 14:46:17 +0000428static
bartd2c5eae2009-02-21 15:27:04 +0000429Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
sewardjaf44c822007-11-25 14:01:38 +0000430{
bartbedfd232009-03-26 19:07:15 +0000431 return True;
sewardjaf44c822007-11-25 14:01:38 +0000432}
433
bartd2c5eae2009-02-21 15:27:04 +0000434static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
sewardjaf44c822007-11-25 14:01:38 +0000435{
bartbedfd232009-03-26 19:07:15 +0000436 switch (VG_(get_supp_kind)(supp))
437 {
438 }
439 return True;
sewardjaf44c822007-11-25 14:01:38 +0000440}
441
bartd2c5eae2009-02-21 15:27:04 +0000442static Char* drd_tool_error_name(Error* e)
sewardjaf44c822007-11-25 14:01:38 +0000443{
bartbedfd232009-03-26 19:07:15 +0000444 switch (VG_(get_error_kind)(e))
445 {
446 case DataRaceErr: return VGAPPEND(STR_, DataRaceErr);
447 case MutexErr: return VGAPPEND(STR_, MutexErr);
448 case CondErr: return VGAPPEND(STR_, CondErr);
449 case CondDestrErr: return VGAPPEND(STR_, CondDestrErr);
450 case CondRaceErr: return VGAPPEND(STR_, CondRaceErr);
451 case CondWaitErr: return VGAPPEND(STR_, CondWaitErr);
452 case SemaphoreErr: return VGAPPEND(STR_, SemaphoreErr);
453 case BarrierErr: return VGAPPEND(STR_, BarrierErr);
454 case RwlockErr: return VGAPPEND(STR_, RwlockErr);
455 case HoldtimeErr: return VGAPPEND(STR_, HoldtimeErr);
456 case GenericErr: return VGAPPEND(STR_, GenericErr);
457 default:
458 tl_assert(0);
459 }
460 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000461}
462
bartd2c5eae2009-02-21 15:27:04 +0000463static void drd_tool_error_print_extra(Error* e)
bart246fbf22009-02-15 14:46:17 +0000464{ }
sewardjaf44c822007-11-25 14:01:38 +0000465
bart1335ecc2009-02-14 16:10:53 +0000466void DRD_(register_error_handlers)(void)
sewardjaf44c822007-11-25 14:01:38 +0000467{
bartbedfd232009-03-26 19:07:15 +0000468 // Tool error reporting.
469 VG_(needs_tool_errors)(drd_tool_error_eq,
sewardj1e29ebc2009-07-15 14:49:17 +0000470 drd_tool_error_before_pp,
bartbedfd232009-03-26 19:07:15 +0000471 drd_tool_error_pp,
bartd45d9952009-05-31 18:53:54 +0000472 False,
bartbedfd232009-03-26 19:07:15 +0000473 drd_tool_error_update_extra,
474 drd_tool_error_recog,
475 drd_tool_error_read_extra,
476 drd_tool_error_matches,
477 drd_tool_error_name,
478 drd_tool_error_print_extra);
sewardjaf44c822007-11-25 14:01:38 +0000479}