blob: 20d3aff2487a9d28e054e455dd7af1359e0bdb4a [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 {
251 VG_(pp_ExeContext)(ai.lastchange);
252 }
bartb515eb12008-03-07 18:52:38 +0000253 else
254 {
255 VG_(message)(Vg_UserMsg, "Allocation context: unknown.\n");
256 }
sewardjaf44c822007-11-25 14:01:38 +0000257 thread_report_conflicting_segments(VgThreadIdToDrdThreadId(dri->tid),
258 dri->addr, dri->size, dri->access_type);
259}
260
261static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
262{
263 return False;
264}
265
266static void drd_tool_error_pp(Error* const e)
267{
268 switch (VG_(get_error_kind)(e))
269 {
270 case DataRaceErr: {
271 drd_report_data_race2(e, VG_(get_error_extra)(e));
272 break;
273 }
274 case MutexErr: {
275 MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
barte883bc82008-02-26 19:13:04 +0000276 tl_assert(p);
sewardjaf44c822007-11-25 14:01:38 +0000277 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000278 "%s: mutex 0x%lx, recursion count %d, owner %d.",
sewardjaf44c822007-11-25 14:01:38 +0000279 VG_(get_error_string)(e),
barte883bc82008-02-26 19:13:04 +0000280 p->mutex,
281 p->recursion_count,
282 p->owner);
sewardjaf44c822007-11-25 14:01:38 +0000283 VG_(pp_ExeContext)(VG_(get_error_where)(e));
284 break;
285 }
sewardjaf44c822007-11-25 14:01:38 +0000286 case CondErr: {
287 CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
288 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000289 "%s: cond 0x%lx",
sewardjaf44c822007-11-25 14:01:38 +0000290 cdei->cond,
291 VG_(get_error_string)(e));
292 VG_(pp_ExeContext)(VG_(get_error_where)(e));
293 break;
294 }
bart3b1ee452008-02-29 19:28:15 +0000295 case CondRaceErr: {
296 CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
297 VG_(message)(Vg_UserMsg,
298 "Race condition: condition variable 0x%lx has been"
299 " signalled but the associated mutex 0x%lx is not locked"
300 " by the signalling thread",
301 cei->cond, cei->mutex);
302 VG_(pp_ExeContext)(VG_(get_error_where)(e));
303 break;
304 }
305 case CondDestrErr: {
306 CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
307 VG_(message)(Vg_UserMsg,
308 "%s: cond 0x%lx, mutex 0x%lx locked by thread %d",
309 cdi->cond, cdi->mutex, cdi->tid);
310 VG_(pp_ExeContext)(VG_(get_error_where)(e));
311 break;
312 }
313 case SemaphoreErr: {
314 SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e));
315 tl_assert(sei);
316 VG_(message)(Vg_UserMsg,
bart777f7fe2008-03-02 17:43:18 +0000317 "%s: semaphore 0x%lx",
bart3b1ee452008-02-29 19:28:15 +0000318 VG_(get_error_string)(e),
319 sei->semaphore);
320 VG_(pp_ExeContext)(VG_(get_error_where)(e));
321 break;
322 }
323 case BarrierErr: {
324 BarrierErrInfo* sei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
325 tl_assert(sei);
326 VG_(message)(Vg_UserMsg,
327 "%s: barrier 0x%lx",
328 VG_(get_error_string)(e),
329 sei->barrier);
330 VG_(pp_ExeContext)(VG_(get_error_where)(e));
331 break;
332 }
bart777f7fe2008-03-02 17:43:18 +0000333 case RwlockErr: {
334 RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
335 tl_assert(p);
336 VG_(message)(Vg_UserMsg,
337 "%s: rwlock 0x%lx.",
338 VG_(get_error_string)(e),
339 p->rwlock);
340 VG_(pp_ExeContext)(VG_(get_error_where)(e));
341 break;
342 }
barte883bc82008-02-26 19:13:04 +0000343 case GenericErr: {
344 //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e));
345 VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e));
346 VG_(pp_ExeContext)(VG_(get_error_where)(e));
347 break;
348 }
sewardjaf44c822007-11-25 14:01:38 +0000349 default:
350 VG_(message)(Vg_UserMsg,
351 "%s",
352 VG_(get_error_string)(e));
353 VG_(pp_ExeContext)(VG_(get_error_where)(e));
354 break;
355 }
356}
357
358static UInt drd_tool_error_update_extra(Error* e)
359{
360 switch (VG_(get_error_kind)(e))
361 {
362 case DataRaceErr:
363 return sizeof(DataRaceErrInfo);
364 case MutexErr:
365 return sizeof(MutexErrInfo);
sewardjaf44c822007-11-25 14:01:38 +0000366 case CondErr:
367 return sizeof(CondErrInfo);
bart3b1ee452008-02-29 19:28:15 +0000368 case CondRaceErr:
369 return sizeof(CondRaceErrInfo);
370 case CondDestrErr:
371 return sizeof(CondDestrErrInfo);
372 case SemaphoreErr:
373 return sizeof(SemaphoreErrInfo);
374 case BarrierErr:
375 return sizeof(BarrierErrInfo);
bart777f7fe2008-03-02 17:43:18 +0000376 case RwlockErr:
377 return sizeof(RwlockErrInfo);
barte883bc82008-02-26 19:13:04 +0000378 case GenericErr:
379 return sizeof(GenericErrInfo);
sewardjaf44c822007-11-25 14:01:38 +0000380 default:
381 tl_assert(False);
382 break;
383 }
384}
385
386static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
387{
388 SuppKind skind;
389
390 if (VG_(strcmp)(name, "ConflictingAccess") == 0)
391 skind = ConflictingAccessSupp;
392 else
393 return False;
394
395 VG_(set_supp_kind)(supp, skind);
396 return True;
397}
398
399static Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
400{
401 return True;
402}
403
404static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
405{
406 switch (VG_(get_supp_kind)(supp))
407 {
408 }
409 return True;
410}
411
412static Char* drd_tool_error_name(Error* e)
413{
414 switch (VG_(get_error_kind)(e))
415 {
bart777f7fe2008-03-02 17:43:18 +0000416 case DataRaceErr: return "DataRaceErr";
417 case MutexErr: return "MutexErr";
418 case CondErr: return "CondErr";
419 case CondRaceErr: return "CondRaceErr";
420 case CondDestrErr: return "CondDestrErr";
421 case SemaphoreErr: return "SemaphoreErr";
422 case BarrierErr: return "BarrierErr";
423 case RwlockErr: return "RwlockErr";
424 case GenericErr: return "GenericErr";
sewardjaf44c822007-11-25 14:01:38 +0000425 default:
426 tl_assert(0);
427 }
428 return 0;
429}
430
431static void drd_tool_error_print_extra(Error* e)
432{
433 switch (VG_(get_error_kind)(e))
434 {
435 // VG_(printf)(" %s\n", VG_(get_error_string)(err));
436 }
437}
438
439void drd_register_error_handlers(void)
440{
441 // Tool error reporting.
442 VG_(needs_tool_errors)(drd_tool_error_eq,
443 drd_tool_error_pp,
444 True,
445 drd_tool_error_update_extra,
446 drd_tool_error_recog,
447 drd_tool_error_read_extra,
448 drd_tool_error_matches,
449 drd_tool_error_name,
450 drd_tool_error_print_extra);
451}
452
453/*
454 * Local variables:
455 * c-basic-offset: 3
456 * End:
457 */