blob: 50e8ff9f688830780b31014b08b1621d289378b1 [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 {
bart3772a982008-03-15 08:11:03 +000043 ConflictingAccessSupp
sewardjaf44c822007-11-25 14:01:38 +000044} DRD_SuppKind;
45
46
47static void make_path_relative(Char* const path)
48{
bart3772a982008-03-15 08:11:03 +000049 int offset = 0;
50 Char cwd[512];
sewardjaf44c822007-11-25 14:01:38 +000051
bart3772a982008-03-15 08:11:03 +000052 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);
sewardjaf44c822007-11-25 14:01:38 +000063}
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{
bart3772a982008-03-15 08:11:03 +000070 Addr stack_min, stack_max;
71 DebugInfo* sg;
sewardjaf44c822007-11-25 14:01:38 +000072
bart3772a982008-03-15 08:11:03 +000073 /* 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;
92 ai->debuginfo = sg;
93 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;
106 Bool isText;
107
108 VG_(seginfo_syms_getidx)(sg, i, &addr, &tocptr, &size, &name, &isText);
109 if (isText && addr <= a && a < addr + size)
110 {
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];
135 VgSectKind kind = VG_(seginfo_sect_kind)(NULL, 0, a);
136 const HChar* sect_kind_name = VG_(pp_SectKind)(kind);
137 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;
sewardjaf44c822007-11-25 14:01:38 +0000159 return;
bart3772a982008-03-15 08:11:03 +0000160 }
161 }
sewardjaf44c822007-11-25 14:01:38 +0000162
bart3772a982008-03-15 08:11:03 +0000163 /* Clueless ... */
164 ai->akind = eUnknown;
165 return;
sewardjaf44c822007-11-25 14:01:38 +0000166}
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{
bart3772a982008-03-15 08:11:03 +0000174 tl_assert(a);
175 tl_assert(ai);
176 tl_assert(buf);
sewardjaf44c822007-11-25 14:01:38 +0000177
bart3772a982008-03-15 08:11:03 +0000178 describe_addr(a, len, ai);
sewardjaf44c822007-11-25 14:01:38 +0000179
bart3772a982008-03-15 08:11:03 +0000180 switch (ai->akind)
181 {
182 case eStack: {
183 VG_(snprintf)(buf, n_buf,
bart354009c2008-03-16 10:42:33 +0000184 "stack of thread %d, offset %d",
185 ai->stack_tid, ai->rwoffset);
bart3772a982008-03-15 08:11:03 +0000186 break;
187 }
188 case eSegment: {
189 if (ai->name[0])
190 {
sewardjaf44c822007-11-25 14:01:38 +0000191 VG_(snprintf)(buf, n_buf,
bart3772a982008-03-15 08:11:03 +0000192 "%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;
sewardjaf44c822007-11-25 14:01:38 +0000217}
218
sewardjaf44c822007-11-25 14:01:38 +0000219static
220void drd_report_data_race2(Error* const err, const DataRaceErrInfo* const dri)
221{
bart3772a982008-03-15 08:11:03 +0000222 AddrInfo ai;
223 Char descr1[256];
224 Char descr2[256];
sewardjaf44c822007-11-25 14:01:38 +0000225
bart3772a982008-03-15 08:11:03 +0000226 tl_assert(dri);
227 tl_assert(dri->addr);
228 tl_assert(dri->size > 0);
bartb515eb12008-03-07 18:52:38 +0000229
bart3772a982008-03-15 08:11:03 +0000230 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 }
237 VG_(message)(Vg_UserMsg,
bart354009c2008-03-16 10:42:33 +0000238 "Conflicting %s by thread %d at 0x%08lx size %ld",
bart3772a982008-03-15 08:11:03 +0000239 dri->access_type == eStore ? "store" : "load",
bart354009c2008-03-16 10:42:33 +0000240 DrdThreadIdToVgThreadId(dri->tid),
bart3772a982008-03-15 08:11:03 +0000241 dri->addr,
242 dri->size);
243 VG_(pp_ExeContext)(VG_(get_error_where)(err));
244 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)
250 {
251 VG_(message)(Vg_UserMsg,
252 "Address 0x%lx is at offset %ld from 0x%lx."
253 " Allocation context:",
254 dri->addr, ai.rwoffset, dri->addr - ai.rwoffset);
255 VG_(pp_ExeContext)(ai.lastchange);
256 }
257 else
258 {
259 VG_(message)(Vg_UserMsg, "Allocation context: unknown.");
260 }
bart354009c2008-03-16 10:42:33 +0000261 thread_report_conflicting_segments(dri->tid,
bart3772a982008-03-15 08:11:03 +0000262 dri->addr, dri->size, dri->access_type);
sewardjaf44c822007-11-25 14:01:38 +0000263}
264
265static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
266{
bart3772a982008-03-15 08:11:03 +0000267 return False;
sewardjaf44c822007-11-25 14:01:38 +0000268}
269
270static void drd_tool_error_pp(Error* const e)
271{
bart3772a982008-03-15 08:11:03 +0000272 switch (VG_(get_error_kind)(e))
273 {
274 case DataRaceErr: {
275 drd_report_data_race2(e, VG_(get_error_extra)(e));
276 break;
277 }
278 case MutexErr: {
279 MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
280 tl_assert(p);
281 VG_(message)(Vg_UserMsg,
282 "%s: mutex 0x%lx, recursion count %d, owner %d.",
283 VG_(get_error_string)(e),
284 p->mutex,
285 p->recursion_count,
286 p->owner);
287 VG_(pp_ExeContext)(VG_(get_error_where)(e));
288 break;
289 }
290 case CondErr: {
291 CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
292 VG_(message)(Vg_UserMsg,
293 "%s: cond 0x%lx",
294 cdei->cond,
295 VG_(get_error_string)(e));
296 VG_(pp_ExeContext)(VG_(get_error_where)(e));
297 break;
298 }
299 case CondRaceErr: {
300 CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
301 VG_(message)(Vg_UserMsg,
302 "Race condition: condition variable 0x%lx has been"
303 " signalled but the associated mutex 0x%lx is not locked"
304 " by the signalling thread",
305 cei->cond, cei->mutex);
306 VG_(pp_ExeContext)(VG_(get_error_where)(e));
307 break;
308 }
309 case CondDestrErr: {
310 CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
311 VG_(message)(Vg_UserMsg,
312 "%s: cond 0x%lx, mutex 0x%lx locked by thread %d",
313 cdi->cond, cdi->mutex, cdi->tid);
314 VG_(pp_ExeContext)(VG_(get_error_where)(e));
315 break;
316 }
317 case SemaphoreErr: {
318 SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e));
319 tl_assert(sei);
320 VG_(message)(Vg_UserMsg,
321 "%s: semaphore 0x%lx",
322 VG_(get_error_string)(e),
323 sei->semaphore);
324 VG_(pp_ExeContext)(VG_(get_error_where)(e));
325 break;
326 }
327 case BarrierErr: {
328 BarrierErrInfo* sei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
329 tl_assert(sei);
330 VG_(message)(Vg_UserMsg,
331 "%s: barrier 0x%lx",
332 VG_(get_error_string)(e),
333 sei->barrier);
334 VG_(pp_ExeContext)(VG_(get_error_where)(e));
335 break;
336 }
337 case RwlockErr: {
338 RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
339 tl_assert(p);
340 VG_(message)(Vg_UserMsg,
341 "%s: rwlock 0x%lx.",
342 VG_(get_error_string)(e),
343 p->rwlock);
344 VG_(pp_ExeContext)(VG_(get_error_where)(e));
345 break;
346 }
347 case GenericErr: {
348 //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e));
349 VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e));
350 VG_(pp_ExeContext)(VG_(get_error_where)(e));
351 break;
352 }
353 default:
354 VG_(message)(Vg_UserMsg,
355 "%s",
356 VG_(get_error_string)(e));
357 VG_(pp_ExeContext)(VG_(get_error_where)(e));
358 break;
359 }
sewardjaf44c822007-11-25 14:01:38 +0000360}
361
362static UInt drd_tool_error_update_extra(Error* e)
363{
bart3772a982008-03-15 08:11:03 +0000364 switch (VG_(get_error_kind)(e))
365 {
366 case DataRaceErr:
367 return sizeof(DataRaceErrInfo);
368 case MutexErr:
369 return sizeof(MutexErrInfo);
370 case CondErr:
371 return sizeof(CondErrInfo);
372 case CondRaceErr:
373 return sizeof(CondRaceErrInfo);
374 case CondDestrErr:
375 return sizeof(CondDestrErrInfo);
376 case SemaphoreErr:
377 return sizeof(SemaphoreErrInfo);
378 case BarrierErr:
379 return sizeof(BarrierErrInfo);
380 case RwlockErr:
381 return sizeof(RwlockErrInfo);
382 case GenericErr:
383 return sizeof(GenericErrInfo);
384 default:
385 tl_assert(False);
386 break;
387 }
sewardjaf44c822007-11-25 14:01:38 +0000388}
389
390static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
391{
bart3772a982008-03-15 08:11:03 +0000392 SuppKind skind;
sewardjaf44c822007-11-25 14:01:38 +0000393
bart3772a982008-03-15 08:11:03 +0000394 if (VG_(strcmp)(name, "ConflictingAccess") == 0)
395 skind = ConflictingAccessSupp;
396 else
397 return False;
sewardjaf44c822007-11-25 14:01:38 +0000398
bart3772a982008-03-15 08:11:03 +0000399 VG_(set_supp_kind)(supp, skind);
400 return True;
sewardjaf44c822007-11-25 14:01:38 +0000401}
402
403static Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
404{
bart3772a982008-03-15 08:11:03 +0000405 return True;
sewardjaf44c822007-11-25 14:01:38 +0000406}
407
408static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
409{
bart3772a982008-03-15 08:11:03 +0000410 switch (VG_(get_supp_kind)(supp))
411 {
412 }
413 return True;
sewardjaf44c822007-11-25 14:01:38 +0000414}
415
416static Char* drd_tool_error_name(Error* e)
417{
bart3772a982008-03-15 08:11:03 +0000418 switch (VG_(get_error_kind)(e))
419 {
420 case DataRaceErr: return "DataRaceErr";
421 case MutexErr: return "MutexErr";
422 case CondErr: return "CondErr";
423 case CondRaceErr: return "CondRaceErr";
424 case CondDestrErr: return "CondDestrErr";
425 case SemaphoreErr: return "SemaphoreErr";
426 case BarrierErr: return "BarrierErr";
427 case RwlockErr: return "RwlockErr";
428 case GenericErr: return "GenericErr";
429 default:
430 tl_assert(0);
431 }
432 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000433}
434
435static void drd_tool_error_print_extra(Error* e)
436{
bart3772a982008-03-15 08:11:03 +0000437 switch (VG_(get_error_kind)(e))
438 {
439 // VG_(printf)(" %s\n", VG_(get_error_string)(err));
440 }
sewardjaf44c822007-11-25 14:01:38 +0000441}
442
443void drd_register_error_handlers(void)
444{
bart3772a982008-03-15 08:11:03 +0000445 // Tool error reporting.
446 VG_(needs_tool_errors)(drd_tool_error_eq,
447 drd_tool_error_pp,
448 True,
449 drd_tool_error_update_extra,
450 drd_tool_error_recog,
451 drd_tool_error_read_extra,
452 drd_tool_error_matches,
453 drd_tool_error_name,
454 drd_tool_error_print_extra);
sewardjaf44c822007-11-25 14:01:38 +0000455}