blob: 38e2456ac3f376efd83d7c2a4d6fb296596be05e [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
bart16d76e52008-03-18 17:08:08 +000042/* Local type definitions. */
43
sewardjaf44c822007-11-25 14:01:38 +000044typedef enum {
bart3772a982008-03-15 08:11:03 +000045 ConflictingAccessSupp
sewardjaf44c822007-11-25 14:01:38 +000046} DRD_SuppKind;
47
48
bart16d76e52008-03-18 17:08:08 +000049/* Local variables. */
50
51static Bool s_drd_show_conflicting_segments = True;
52
53
54void set_show_conflicting_segments(const Bool scs)
55{
56 s_drd_show_conflicting_segments = scs;
57}
58
bartff1252a2008-03-16 17:27:25 +000059/* Describe a data address range [a,a+len[ as good as possible, for error */
sewardjaf44c822007-11-25 14:01:38 +000060/* messages, putting the result in ai. */
bartff1252a2008-03-16 17:27:25 +000061static
62void describe_malloced_addr(Addr const a, SizeT const len, AddrInfo* const ai)
sewardjaf44c822007-11-25 14:01:38 +000063{
bartff1252a2008-03-16 17:27:25 +000064 Addr data;
sewardjaf44c822007-11-25 14:01:38 +000065
bartff1252a2008-03-16 17:27:25 +000066 if (drd_heap_addrinfo(a, &data, &ai->size, &ai->lastchange))
bart3772a982008-03-15 08:11:03 +000067 {
bartff1252a2008-03-16 17:27:25 +000068 ai->akind = eMallocd;
69 ai->rwoffset = a - data;
bart3772a982008-03-15 08:11:03 +000070 }
bartff1252a2008-03-16 17:27:25 +000071 else
bart3772a982008-03-15 08:11:03 +000072 {
bartff1252a2008-03-16 17:27:25 +000073 ai->akind = eUnknown;
bart3772a982008-03-15 08:11:03 +000074 }
sewardjaf44c822007-11-25 14:01:38 +000075}
76
sewardjaf44c822007-11-25 14:01:38 +000077static
78void drd_report_data_race2(Error* const err, const DataRaceErrInfo* const dri)
79{
bart3772a982008-03-15 08:11:03 +000080 AddrInfo ai;
81 Char descr1[256];
82 Char descr2[256];
sewardjaf44c822007-11-25 14:01:38 +000083
bart3772a982008-03-15 08:11:03 +000084 tl_assert(dri);
85 tl_assert(dri->addr);
86 tl_assert(dri->size > 0);
bartb515eb12008-03-07 18:52:38 +000087
bart3772a982008-03-15 08:11:03 +000088 descr1[0] = 0;
89 descr2[0] = 0;
90 VG_(get_data_description)(descr1, descr2, sizeof(descr1), dri->addr);
91 if (descr1[0] == 0)
92 {
bartff1252a2008-03-16 17:27:25 +000093 describe_malloced_addr(dri->addr, dri->size, &ai);
bart3772a982008-03-15 08:11:03 +000094 }
95 VG_(message)(Vg_UserMsg,
bartaa97a542008-03-16 17:57:01 +000096 "Conflicting %s by thread %d/%d at 0x%08lx size %ld",
bart3772a982008-03-15 08:11:03 +000097 dri->access_type == eStore ? "store" : "load",
bart354009c2008-03-16 10:42:33 +000098 DrdThreadIdToVgThreadId(dri->tid),
bartaa97a542008-03-16 17:57:01 +000099 dri->tid,
bart3772a982008-03-15 08:11:03 +0000100 dri->addr,
101 dri->size);
102 VG_(pp_ExeContext)(VG_(get_error_where)(err));
103 if (descr1[0])
104 {
105 VG_(message)(Vg_UserMsg, "%s", descr1);
106 VG_(message)(Vg_UserMsg, "%s", descr2);
107 }
108 else if (ai.akind == eMallocd && ai.lastchange)
109 {
110 VG_(message)(Vg_UserMsg,
111 "Address 0x%lx is at offset %ld from 0x%lx."
112 " Allocation context:",
113 dri->addr, ai.rwoffset, dri->addr - ai.rwoffset);
114 VG_(pp_ExeContext)(ai.lastchange);
115 }
116 else
117 {
118 VG_(message)(Vg_UserMsg, "Allocation context: unknown.");
119 }
bart16d76e52008-03-18 17:08:08 +0000120 if (s_drd_show_conflicting_segments)
121 {
122 thread_report_conflicting_segments(dri->tid,
123 dri->addr, dri->size, dri->access_type);
124 }
sewardjaf44c822007-11-25 14:01:38 +0000125}
126
127static Bool drd_tool_error_eq(VgRes res, Error* e1, Error* e2)
128{
bart3772a982008-03-15 08:11:03 +0000129 return False;
sewardjaf44c822007-11-25 14:01:38 +0000130}
131
132static void drd_tool_error_pp(Error* const e)
133{
bart3772a982008-03-15 08:11:03 +0000134 switch (VG_(get_error_kind)(e))
135 {
136 case DataRaceErr: {
137 drd_report_data_race2(e, VG_(get_error_extra)(e));
138 break;
139 }
140 case MutexErr: {
141 MutexErrInfo* p = (MutexErrInfo*)(VG_(get_error_extra)(e));
142 tl_assert(p);
143 VG_(message)(Vg_UserMsg,
144 "%s: mutex 0x%lx, recursion count %d, owner %d.",
145 VG_(get_error_string)(e),
146 p->mutex,
147 p->recursion_count,
148 p->owner);
149 VG_(pp_ExeContext)(VG_(get_error_where)(e));
150 break;
151 }
152 case CondErr: {
153 CondErrInfo* cdei =(CondErrInfo*)(VG_(get_error_extra)(e));
154 VG_(message)(Vg_UserMsg,
155 "%s: cond 0x%lx",
bartbe8a12c2008-03-17 18:36:55 +0000156 VG_(get_error_string)(e),
157 cdei->cond);
bart3772a982008-03-15 08:11:03 +0000158 VG_(pp_ExeContext)(VG_(get_error_where)(e));
159 break;
160 }
161 case CondRaceErr: {
162 CondRaceErrInfo* cei = (CondRaceErrInfo*)(VG_(get_error_extra)(e));
163 VG_(message)(Vg_UserMsg,
164 "Race condition: condition variable 0x%lx has been"
165 " signalled but the associated mutex 0x%lx is not locked"
166 " by the signalling thread",
167 cei->cond, cei->mutex);
168 VG_(pp_ExeContext)(VG_(get_error_where)(e));
169 break;
170 }
171 case CondDestrErr: {
172 CondDestrErrInfo* cdi = (CondDestrErrInfo*)(VG_(get_error_extra)(e));
173 VG_(message)(Vg_UserMsg,
bartaa97a542008-03-16 17:57:01 +0000174 "%s: cond 0x%lx, mutex 0x%lx locked by thread %d/%d",
bartbe8a12c2008-03-17 18:36:55 +0000175 VG_(get_error_string)(e),
bartaa97a542008-03-16 17:57:01 +0000176 cdi->cond, cdi->mutex,
177 DrdThreadIdToVgThreadId(cdi->tid), cdi->tid);
bart3772a982008-03-15 08:11:03 +0000178 VG_(pp_ExeContext)(VG_(get_error_where)(e));
179 break;
180 }
181 case SemaphoreErr: {
182 SemaphoreErrInfo* sei =(SemaphoreErrInfo*)(VG_(get_error_extra)(e));
183 tl_assert(sei);
184 VG_(message)(Vg_UserMsg,
185 "%s: semaphore 0x%lx",
186 VG_(get_error_string)(e),
187 sei->semaphore);
188 VG_(pp_ExeContext)(VG_(get_error_where)(e));
189 break;
190 }
191 case BarrierErr: {
192 BarrierErrInfo* sei =(BarrierErrInfo*)(VG_(get_error_extra)(e));
193 tl_assert(sei);
194 VG_(message)(Vg_UserMsg,
195 "%s: barrier 0x%lx",
196 VG_(get_error_string)(e),
197 sei->barrier);
198 VG_(pp_ExeContext)(VG_(get_error_where)(e));
199 break;
200 }
201 case RwlockErr: {
202 RwlockErrInfo* p = (RwlockErrInfo*)(VG_(get_error_extra)(e));
203 tl_assert(p);
204 VG_(message)(Vg_UserMsg,
205 "%s: rwlock 0x%lx.",
206 VG_(get_error_string)(e),
207 p->rwlock);
208 VG_(pp_ExeContext)(VG_(get_error_where)(e));
209 break;
210 }
211 case GenericErr: {
212 //GenericErrInfo* gei =(GenericErrInfo*)(VG_(get_error_extra)(e));
213 VG_(message)(Vg_UserMsg, "%s", VG_(get_error_string)(e));
214 VG_(pp_ExeContext)(VG_(get_error_where)(e));
215 break;
216 }
217 default:
218 VG_(message)(Vg_UserMsg,
219 "%s",
220 VG_(get_error_string)(e));
221 VG_(pp_ExeContext)(VG_(get_error_where)(e));
222 break;
223 }
sewardjaf44c822007-11-25 14:01:38 +0000224}
225
226static UInt drd_tool_error_update_extra(Error* e)
227{
bart3772a982008-03-15 08:11:03 +0000228 switch (VG_(get_error_kind)(e))
229 {
230 case DataRaceErr:
231 return sizeof(DataRaceErrInfo);
232 case MutexErr:
233 return sizeof(MutexErrInfo);
234 case CondErr:
235 return sizeof(CondErrInfo);
236 case CondRaceErr:
237 return sizeof(CondRaceErrInfo);
238 case CondDestrErr:
239 return sizeof(CondDestrErrInfo);
240 case SemaphoreErr:
241 return sizeof(SemaphoreErrInfo);
242 case BarrierErr:
243 return sizeof(BarrierErrInfo);
244 case RwlockErr:
245 return sizeof(RwlockErrInfo);
246 case GenericErr:
247 return sizeof(GenericErrInfo);
248 default:
249 tl_assert(False);
250 break;
251 }
sewardjaf44c822007-11-25 14:01:38 +0000252}
253
254static Bool drd_tool_error_recog(Char* const name, Supp* const supp)
255{
bart3772a982008-03-15 08:11:03 +0000256 SuppKind skind;
sewardjaf44c822007-11-25 14:01:38 +0000257
bart3772a982008-03-15 08:11:03 +0000258 if (VG_(strcmp)(name, "ConflictingAccess") == 0)
259 skind = ConflictingAccessSupp;
bartd1c9d222008-03-22 17:35:56 +0000260 else if (VG_(strcmp)(name, "CondErr") == 0)
261 skind = CondErr;
bart3772a982008-03-15 08:11:03 +0000262 else
263 return False;
sewardjaf44c822007-11-25 14:01:38 +0000264
bart3772a982008-03-15 08:11:03 +0000265 VG_(set_supp_kind)(supp, skind);
266 return True;
sewardjaf44c822007-11-25 14:01:38 +0000267}
268
269static Bool drd_tool_error_read_extra(Int fd, Char* buf, Int nBuf, Supp* supp)
270{
bart3772a982008-03-15 08:11:03 +0000271 return True;
sewardjaf44c822007-11-25 14:01:38 +0000272}
273
274static Bool drd_tool_error_matches(Error* const e, Supp* const supp)
275{
bart3772a982008-03-15 08:11:03 +0000276 switch (VG_(get_supp_kind)(supp))
277 {
278 }
279 return True;
sewardjaf44c822007-11-25 14:01:38 +0000280}
281
282static Char* drd_tool_error_name(Error* e)
283{
bart3772a982008-03-15 08:11:03 +0000284 switch (VG_(get_error_kind)(e))
285 {
bartff1252a2008-03-16 17:27:25 +0000286 case DataRaceErr: return "ConflictingAccess";
bart3772a982008-03-15 08:11:03 +0000287 case MutexErr: return "MutexErr";
288 case CondErr: return "CondErr";
289 case CondRaceErr: return "CondRaceErr";
290 case CondDestrErr: return "CondDestrErr";
291 case SemaphoreErr: return "SemaphoreErr";
292 case BarrierErr: return "BarrierErr";
293 case RwlockErr: return "RwlockErr";
294 case GenericErr: return "GenericErr";
295 default:
296 tl_assert(0);
297 }
298 return 0;
sewardjaf44c822007-11-25 14:01:38 +0000299}
300
301static void drd_tool_error_print_extra(Error* e)
302{
bart3772a982008-03-15 08:11:03 +0000303 switch (VG_(get_error_kind)(e))
304 {
305 // VG_(printf)(" %s\n", VG_(get_error_string)(err));
306 }
sewardjaf44c822007-11-25 14:01:38 +0000307}
308
309void drd_register_error_handlers(void)
310{
bart3772a982008-03-15 08:11:03 +0000311 // Tool error reporting.
312 VG_(needs_tool_errors)(drd_tool_error_eq,
313 drd_tool_error_pp,
314 True,
315 drd_tool_error_update_extra,
316 drd_tool_error_recog,
317 drd_tool_error_read_extra,
318 drd_tool_error_matches,
319 drd_tool_error_name,
320 drd_tool_error_print_extra);
sewardjaf44c822007-11-25 14:01:38 +0000321}