blob: fb6a23d16974d86a0447e74ee0d2914208f1cd0d [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
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
26#include "drd_error.h"
27#include "drd_malloc_wrappers.h"
28#include "drd_mutex.h" // struct mutex_info
29#include "drd_suppression.h" // drd_start_suppression()
30#include "pub_drd_bitmap.h" // LHS_W, ...
31#include "pub_tool_vki.h"
32#include "pub_tool_basics.h"
33#include "pub_tool_libcassert.h" // tl_assert()
34#include "pub_tool_libcbase.h" // strlen()
35#include "pub_tool_libcfile.h" // VG_(get_startup_wd)()
36#include "pub_tool_libcprint.h" // VG_(printf)()
37#include "pub_tool_machine.h"
38#include "pub_tool_threadstate.h" // VG_(get_pthread_id)()
39#include "pub_tool_tooliface.h" // VG_(needs_tool_errors)()
40
41
42typedef enum {
43 ConflictingAccessSupp
44} DRD_SuppKind;
45
46
47static void make_path_relative(Char* const path)
48{
49 int offset = 0;
50 Char cwd[512];
51
52 if (! VG_(get_startup_wd)(cwd, sizeof(cwd)))
53 tl_assert(False);
54 if (VG_(strncmp)(path + offset, cwd, VG_(strlen)(cwd)) == 0)
55 {
56 offset += VG_(strlen)(cwd);
57 if (path[offset] == '/')
58 {
59 offset++;
60 }
61 }
62 VG_(memmove)(path, path + offset, VG_(strlen)(path + offset) + 1);
63}
64
65
66/* Describe a data address range [a,a+len[ as good as you can, for error */
67/* messages, putting the result in ai. */
68void describe_addr(Addr const a, SizeT const len, AddrInfo* const ai)
69{
70 Addr stack_min, stack_max;
sewardjb8b79ad2008-03-03 01:35:41 +000071 DebugInfo* sg;
sewardjaf44c822007-11-25 14:01:38 +000072
73 /* Perhaps it's on a thread's stack? */
74 ai->stack_tid = thread_lookup_stackaddr(a, &stack_min, &stack_max);
75 if (ai->stack_tid != DRD_INVALID_THREADID)
76 {
77 ai->akind = eStack;
78 ai->size = len;
79 ai->rwoffset = a - stack_max;
80 tl_assert(a + ai->size <= stack_max);
81 tl_assert(ai->rwoffset < 0);
82 return;
83 }
84
85 /* Perhaps it's in a mapped segment ? */
86 sg = VG_(find_seginfo)(a);
87 if (sg)
88 {
89 int i, n;
90
91 ai->akind = eSegment;
sewardjb8b79ad2008-03-03 01:35:41 +000092 ai->debuginfo = sg;
sewardjaf44c822007-11-25 14:01:38 +000093 ai->name[0] = 0;
94 ai->size = 1;
95 ai->rwoffset = 0;
96
97 n = VG_(seginfo_syms_howmany)(sg);
98 for (i = 0; i < n; i++)
99 {
100 Addr addr;
101 Addr tocptr;
102 UInt size;
103 HChar* name;
104 Char filename[256];
105 Int linenum;
sewardjb8b79ad2008-03-03 01:35:41 +0000106 Bool isText;
sewardjaf44c822007-11-25 14:01:38 +0000107
sewardjb8b79ad2008-03-03 01:35:41 +0000108 VG_(seginfo_syms_getidx)(sg, i, &addr, &tocptr, &size, &name, &isText);
109 if (isText && addr <= a && a < addr + size)
sewardjaf44c822007-11-25 14:01:38 +0000110 {
111 ai->size = size;
112 ai->rwoffset = a - addr;
113 tl_assert(name && name[0]);
114 VG_(snprintf)(ai->name, sizeof(ai->name), "%s", name);
115 if (VG_(get_filename_linenum)(addr,
116 filename, sizeof(filename),
117 0, 0, 0,
118 &linenum))
119 {
120 make_path_relative(filename);
121 VG_(snprintf)(ai->descr, sizeof(ai->descr),
122 " in %s:%d", filename, linenum);
123 }
124 else
125 {
126 i = n;
127 }
128 break;
129 }
130 }
131 if (i == n)
132 {
133 Char filename[512];
134 Char soname[512];
sewardjb8b79ad2008-03-03 01:35:41 +0000135 VgSectKind kind = VG_(seginfo_sect_kind)(NULL, 0, a);
136 const HChar* sect_kind_name = VG_(pp_SectKind)(kind);
sewardjaf44c822007-11-25 14:01:38 +0000137 VG_(strncpy)(filename, VG_(seginfo_filename)(sg), sizeof(filename));
138 filename[sizeof(filename) - 1] = 0;
139 make_path_relative(filename);
140 VG_(strncpy)(soname, VG_(seginfo_soname)(sg), sizeof(soname));
141 soname[sizeof(soname) - 1] = 0;
142 make_path_relative(soname);
143 VG_(snprintf)(ai->descr, sizeof(ai->descr),
144 "%s, %s:%s",
145 filename,
146 soname,
147 sect_kind_name);
148 }
149 return;
150 }
151
152 /* Search for a currently malloc'd block which might bracket it. */
153 {
154 Addr data;
155 if (drd_heap_addrinfo(a, &data, &ai->size, &ai->lastchange))
156 {
157 ai->akind = eMallocd;
158 ai->rwoffset = a - data;
159 return;
160 }
161 }
162
163 /* Clueless ... */
164 ai->akind = eUnknown;
165 return;
166}
167
168/**
169 * Generate a description string for the data residing at address a.
170 */
171Char* describe_addr_text(Addr const a, SizeT const len, AddrInfo* const ai,
172 Char* const buf, UInt const n_buf)
173{
174 tl_assert(a);
175 tl_assert(ai);
176 tl_assert(buf);
177
178 describe_addr(a, len, ai);
179
180 switch (ai->akind)
181 {
182 case eStack: {
183 VG_(snprintf)(buf, n_buf,
184 "stack of %s, offset %d",
185 thread_get_name(ai->stack_tid), ai->rwoffset);
186 break;
187 }
188 case eSegment: {
189 if (ai->name[0])
190 {
191 VG_(snprintf)(buf, n_buf,
192 "%s (offset %ld, size %ld) in %s",
193 ai->name, ai->rwoffset, ai->size, ai->descr);
194 }
195 else
196 {
197 VG_(snprintf)(buf, n_buf,
198 "%s",
199 ai->descr);
200 }
201 break;
202 }
203 case eMallocd: {
204 VG_(snprintf)(buf, n_buf, "heap");
205 VG_(snprintf)(buf + VG_(strlen)(buf), n_buf - VG_(strlen)(buf),
206 ", offset %ld in block at 0x%lx of size %ld",
207 ai->rwoffset, a - ai->rwoffset, ai->size);
208 break;
209 }
210 case eUnknown:
211 VG_(snprintf)(buf, n_buf, "unknown");
212 break;
213 default:
214 tl_assert(0);
215 }
216 return buf;
217}
218
sewardjaf44c822007-11-25 14:01:38 +0000219static
220void drd_report_data_race2(Error* const err, const DataRaceErrInfo* const dri)
221{
222 AddrInfo ai;
bartb515eb12008-03-07 18:52:38 +0000223 Char descr1[256];
224 Char descr2[256];
sewardjaf44c822007-11-25 14:01:38 +0000225
226 tl_assert(dri);
227 tl_assert(dri->addr);
228 tl_assert(dri->size > 0);
bartb515eb12008-03-07 18:52:38 +0000229
230 descr1[0] = 0;
231 descr2[0] = 0;
232 VG_(get_data_description)(descr1, descr2, sizeof(descr1), dri->addr);
233 if (descr1[0] == 0)
234 {
235 describe_addr(dri->addr, dri->size, &ai);
236 }
sewardjaf44c822007-11-25 14:01:38 +0000237 VG_(message)(Vg_UserMsg,
238 "Conflicting %s by %s at 0x%08lx size %ld",
239 dri->access_type == eStore ? "store" : "load",
240 thread_get_name(VgThreadIdToDrdThreadId(dri->tid)),
241 dri->addr,
242 dri->size);
243 VG_(pp_ExeContext)(VG_(get_error_where)(err));
bartb515eb12008-03-07 18:52:38 +0000244 if (descr1[0])
245 {
246 VG_(message)(Vg_UserMsg, "%s", descr1);
247 VG_(message)(Vg_UserMsg, "%s", descr2);
248 }
249 else if (ai.akind == eMallocd && ai.lastchange)
sewardjaf44c822007-11-25 14:01:38 +0000250 {
bart97fab402008-03-09 08:46:11 +0000251 VG_(message)(Vg_UserMsg,
252 "Address 0x%08lx is at offset %ld. Allocation context:",
253 dri->addr, ai.rwoffset);
sewardjaf44c822007-11-25 14:01:38 +0000254 VG_(pp_ExeContext)(ai.lastchange);
255 }
bartb515eb12008-03-07 18:52:38 +0000256 else
257 {
258 VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n");
259 }
sewardjaf44c822007-11-25 14:01:38 +0000260 thread_report_conflicting_segments(VgThreadIdToDrdThreadId(dri->tid),
261 dri->addr, dri->size, dri->access_type);
262}
263
264static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
265{
266 return False;
267}
268
269static void drd_tool_error_pp(Error* const e)
270{
271 switch (VG_(get_error_kind)(e))
272 {
273 case DataRaceErr: {
274 drd_report_data_race2(e, VG_(get_error_extra)(e));
275 break;
276 }
277 case MutexErr: {
278 MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
barte883bc82008-02-26 19:13:04 +0000279 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000280 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000281 "%s: mutex 0x%lx, recursion count %d, owner %d.",
sewardjaf44c822007-11-25 14:01:38 +0000282 VG_(get_error_string)(e),
barte883bc82008-02-26 19:13:04 +0000283 p->mutex,
284 p->recursion_count,
285 p->owner);
sewardjaf44c822007-11-25 14:01:38 +0000286 VG_(pp_ExeContext)(VG_(get_error_where)(e));
287 break;
288 }
sewardjaf44c822007-11-25 14:01:38 +0000289 case CondErr: {
290 CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
291 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000292 "%s: cond 0x%lx",
sewardjaf44c822007-11-25 14:01:38 +0000293 cdei->cond,
294 VG_(get_error_string)(e));
295 VG_(pp_ExeContext)(VG_(get_error_where)(e));
296 break;
297 }
bart3b1ee452008-02-29 19:28:15 +0000298 case CondRaceErr: {
299 CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
300 VG_(message)(Vg_UserMsg,
301 "Race condition: condition variable 0x%lx has been"
302 " signalled but the associated mutex 0x%lx is not locked"
303 " by the signalling thread",
304 cei->cond, cei->mutex);
305 VG_(pp_ExeContext)(VG_(get_error_where)(e));
306 break;
307 }
308 case CondDestrErr: {
309 CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
310 VG_(message)(Vg_UserMsg,
311 "%s: cond 0x%lx, mutex 0x%lx locked by thread %d",
312 cdi->cond, cdi->mutex, cdi->tid);
313 VG_(pp_ExeContext)(VG_(get_error_where)(e));
314 break;
315 }
316 case SemaphoreErr: {
317 SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e));
318 tl_assert(sei);
319 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000320 "%s: semaphore 0x%lx",
bart3b1ee452008-02-29 19:28:15 +0000321 VG_(get_error_string)(e),
322 sei->semaphore);
323 VG_(pp_ExeContext)(VG_(get_error_where)(e));
324 break;
325 }
326 case BarrierErr: {
327 BarrierErrInfo* sei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
328 tl_assert(sei);
329 VG_(message)(Vg_UserMsg,
330 "%s: barrier 0x%lx",
331 VG_(get_error_string)(e),
332 sei->barrier);
333 VG_(pp_ExeContext)(VG_(get_error_where)(e));
334 break;
335 }
bart777f7fe2008-03-02 17:43:18 +0000336 case RwlockErr: {
337 RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
338 tl_assert(p);
339 VG_(message)(Vg_UserMsg,
340 "%s: rwlock 0x%lx.",
341 VG_(get_error_string)(e),
342 p->rwlock);
343 VG_(pp_ExeContext)(VG_(get_error_where)(e));
344 break;
345 }
barte883bc82008-02-26 19:13:04 +0000346 case GenericErr: {
347 //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e));
348 VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e));
349 VG_(pp_ExeContext)(VG_(get_error_where)(e));
350 break;
351 }
sewardjaf44c822007-11-25 14:01:38 +0000352 default:
353 VG_(message)(Vg_UserMsg,
354 "%s",
355 VG_(get_error_string)(e));
356 VG_(pp_ExeContext)(VG_(get_error_where)(e));
357 break;
358 }
359}
360
361static UInt drd_tool_error_update_extra(Error* e)
362{
363 switch (VG_(get_error_kind)(e))
364 {
365 case DataRaceErr:
366 return sizeof(DataRaceErrInfo);
367 case MutexErr:
368 return sizeof(MutexErrInfo);
sewardjaf44c822007-11-25 14:01:38 +0000369 case CondErr:
370 return sizeof(CondErrInfo);
bart3b1ee452008-02-29 19:28:15 +0000371 case CondRaceErr:
372 return sizeof(CondRaceErrInfo);
373 case CondDestrErr:
374 return sizeof(CondDestrErrInfo);
375 case SemaphoreErr:
376 return sizeof(SemaphoreErrInfo);
377 case BarrierErr:
378 return sizeof(BarrierErrInfo);
bart777f7fe2008-03-02 17:43:18 +0000379 case RwlockErr:
380 return sizeof(RwlockErrInfo);
barte883bc82008-02-26 19:13:04 +0000381 case GenericErr:
382 return sizeof(GenericErrInfo);
sewardjaf44c822007-11-25 14:01:38 +0000383 default:
384 tl_assert(False);
385 break;
386 }
387}
388
389static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
390{
391 SuppKind skind;
392
393 if (VG_(strcmp)(name, "ConflictingAccess") == 0)
394 skind = ConflictingAccessSupp;
395 else
396 return False;
397
398 VG_(set_supp_kind)(supp, skind);
399 return True;
400}
401
402static Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
403{
404 return True;
405}
406
407static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
408{
409 switch (VG_(get_supp_kind)(supp))
410 {
411 }
412 return True;
413}
414
415static Char* drd_tool_error_name(Error* e)
416{
417 switch (VG_(get_error_kind)(e))
418 {
bart777f7fe2008-03-02 17:43:18 +0000419 case DataRaceErr: return "DataRaceErr";
420 case MutexErr: return "MutexErr";
421 case CondErr: return "CondErr";
422 case CondRaceErr: return "CondRaceErr";
423 case CondDestrErr: return "CondDestrErr";
424 case SemaphoreErr: return "SemaphoreErr";
425 case BarrierErr: return "BarrierErr";
426 case RwlockErr: return "RwlockErr";
427 case GenericErr: return "GenericErr";
sewardjaf44c822007-11-25 14:01:38 +0000428 default:
429 tl_assert(0);
430 }
431 return 0;
432}
433
434static void drd_tool_error_print_extra(Error* e)
435{
436 switch (VG_(get_error_kind)(e))
437 {
438 // VG_(printf)(" %s\n", VG_(get_error_string)(err));
439 }
440}
441
442void drd_register_error_handlers(void)
443{
444 // Tool error reporting.
445 VG_(needs_tool_errors)(drd_tool_error_eq,
446 drd_tool_error_pp,
447 True,
448 drd_tool_error_update_extra,
449 drd_tool_error_recog,
450 drd_tool_error_read_extra,
451 drd_tool_error_matches,
452 drd_tool_error_name,
453 drd_tool_error_print_extra);
454}
455
456/*
457 * Local variables:
458 * c-basic-offset: 3
459 * End:
460 */