2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 The GNU General Public License is contained in the file COPYING.
25 #include "drd_barrier.h"
26 #include "drd_clientreq.h"
28 #include "drd_error.h"
30 #include "drd_load_store.h"
31 #include "drd_malloc_wrappers.h"
32 #include "drd_mutex.h"
33 #include "drd_rwlock.h"
34 #include "drd_semaphore.h"
35 #include "drd_suppression.h" // drd_start_suppression()
36 #include "drd_thread.h"
37 #include "pub_tool_basics.h" // Bool
38 #include "pub_tool_debuginfo.h" // VG_(describe_IP)()
39 #include "pub_tool_libcassert.h"
40 #include "pub_tool_libcassert.h" // tl_assert()
41 #include "pub_tool_libcprint.h" // VG_(message)()
42 #include "pub_tool_machine.h" // VG_(get_SP)()
43 #include "pub_tool_threadstate.h"
44 #include "pub_tool_tooliface.h" // VG_(needs_...)()
47 /* Global variables. */
49 Bool
DRD_(g_free_is_write
);
52 /* Local function declarations. */
54 static Bool
handle_client_request(ThreadId vg_tid
, UWord
* arg
, UWord
* ret
);
57 /* Function definitions. */
60 * Tell the Valgrind core the address of the DRD function that processes
61 * client requests. Must be called before any client code is run.
63 void DRD_(clientreq_init
)(void)
65 VG_(needs_client_requests
)(handle_client_request
);
69 * DRD's handler for Valgrind client requests. The code below handles both
70 * DRD's public and tool-internal client requests.
72 static Bool
handle_client_request(ThreadId vg_tid
, UWord
* arg
, UWord
* ret
)
75 const DrdThreadId drd_tid
= DRD_(thread_get_running_tid
)();
77 tl_assert(vg_tid
== VG_(get_running_tid()));
78 tl_assert(DRD_(VgThreadIdToDrdThreadId
)(vg_tid
) == drd_tid
);
82 case VG_USERREQ__MALLOCLIKE_BLOCK
:
83 if (DRD_(g_free_is_write
)) {
84 GenericErrInfo GEI
= {
85 .tid
= DRD_(thread_get_running_tid
)(),
88 VG_(maybe_record_error
)(vg_tid
,
91 "--free-is-write=yes is incompatible with"
92 " custom memory allocator client requests",
96 DRD_(malloclike_block
)(vg_tid
, arg
[1]/*addr*/, arg
[2]/*size*/);
99 case VG_USERREQ__RESIZEINPLACE_BLOCK
:
100 if (!DRD_(freelike_block
)(vg_tid
, arg
[1]/*addr*/, False
))
102 GenericErrInfo GEI
= {
103 .tid
= DRD_(thread_get_running_tid
)(),
106 VG_(maybe_record_error
)(vg_tid
,
109 "Invalid VG_USERREQ__RESIZEINPLACE_BLOCK request",
112 DRD_(malloclike_block
)(vg_tid
, arg
[1]/*addr*/, arg
[3]/*newSize*/);
115 case VG_USERREQ__FREELIKE_BLOCK
:
116 if (arg
[1] && ! DRD_(freelike_block
)(vg_tid
, arg
[1]/*addr*/, False
))
118 GenericErrInfo GEI
= {
119 .tid
= DRD_(thread_get_running_tid
)(),
122 VG_(maybe_record_error
)(vg_tid
,
125 "Invalid VG_USERREQ__FREELIKE_BLOCK request",
130 case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID
:
134 case VG_USERREQ__DRD_GET_DRD_THREAD_ID
:
138 case VG_USERREQ__DRD_SET_THREAD_NAME
:
139 DRD_(thread_set_name
)(drd_tid
, (const char*)arg
[1]);
142 case VG_USERREQ__DRD_START_SUPPRESSION
:
143 /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
144 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
145 DRD_(start_suppression
)(arg
[1], arg
[1] + arg
[2], "client");
148 case VG_USERREQ__DRD_FINISH_SUPPRESSION
:
149 /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
150 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
151 DRD_(finish_suppression
)(arg
[1], arg
[1] + arg
[2]);
154 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
:
155 DRD_(hb_happens_before
)(drd_tid
, arg
[1]);
158 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
:
159 DRD_(hb_happens_after
)(drd_tid
, arg
[1]);
162 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
:
165 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
166 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
169 DRD_(rwlock_pre_init
)(arg
[1], user_rwlock
);
172 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
:
175 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
176 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
179 DRD_(rwlock_post_destroy
)(arg
[1], user_rwlock
);
182 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
:
185 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
186 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
189 tl_assert(arg
[2] == !! arg
[2]);
192 DRD_(rwlock_pre_wrlock
)(arg
[1], user_rwlock
);
193 DRD_(rwlock_post_wrlock
)(arg
[1], user_rwlock
, True
);
197 DRD_(rwlock_pre_rdlock
)(arg
[1], user_rwlock
);
198 DRD_(rwlock_post_rdlock
)(arg
[1], user_rwlock
, True
);
202 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
:
205 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
206 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
209 tl_assert(arg
[2] == !! arg
[2]);
210 DRD_(rwlock_pre_unlock
)(arg
[1], user_rwlock
);
213 case VG_USERREQ__SET_PTHREAD_COND_INITIALIZER
:
214 DRD_(pthread_cond_initializer
) = (Addr
)arg
[1];
215 DRD_(pthread_cond_initializer_size
) = arg
[2];
218 case VG_USERREQ__DRD_START_NEW_SEGMENT
:
219 DRD_(thread_new_segment
)(DRD_(PtThreadIdToDrdThreadId
)(arg
[1]));
222 case VG_USERREQ__DRD_START_TRACE_ADDR
:
223 DRD_(start_tracing_address_range
)(arg
[1], arg
[1] + arg
[2]);
226 case VG_USERREQ__DRD_STOP_TRACE_ADDR
:
227 DRD_(stop_tracing_address_range
)(arg
[1], arg
[1] + arg
[2]);
230 case VG_USERREQ__DRD_RECORD_LOADS
:
231 DRD_(thread_set_record_loads
)(drd_tid
, arg
[1]);
234 case VG_USERREQ__DRD_RECORD_STORES
:
235 DRD_(thread_set_record_stores
)(drd_tid
, arg
[1]);
238 case VG_USERREQ__SET_PTHREADID
:
239 // pthread_self() returns 0 for programs not linked with libpthread.so.
240 if (arg
[1] != INVALID_POSIX_THREADID
)
241 DRD_(thread_set_pthreadid
)(drd_tid
, arg
[1]);
244 case VG_USERREQ__SET_JOINABLE
:
246 const DrdThreadId drd_joinable
= DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
247 if (drd_joinable
!= DRD_INVALID_THREADID
)
248 DRD_(thread_set_joinable
)(drd_joinable
, (Bool
)arg
[2]);
250 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
251 VG_(maybe_record_error
)(vg_tid
,
254 "pthread_detach(): invalid thread ID",
260 case VG_USERREQ__ENTERING_PTHREAD_CREATE
:
261 DRD_(thread_entering_pthread_create
)(drd_tid
);
264 case VG_USERREQ__LEFT_PTHREAD_CREATE
:
265 DRD_(thread_left_pthread_create
)(drd_tid
);
268 case VG_USERREQ__POST_THREAD_JOIN
:
270 const DrdThreadId thread_to_join
= DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
271 if (thread_to_join
== DRD_INVALID_THREADID
)
273 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
274 VG_(maybe_record_error
)(vg_tid
,
277 "pthread_join(): invalid thread ID",
282 DRD_(thread_post_join
)(drd_tid
, thread_to_join
);
287 case VG_USERREQ__PRE_THREAD_CANCEL
:
289 const DrdThreadId thread_to_cancel
=DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
290 if (thread_to_cancel
== DRD_INVALID_THREADID
)
292 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
293 VG_(maybe_record_error
)(vg_tid
,
296 "pthread_cancel(): invalid thread ID",
301 DRD_(thread_pre_cancel
)(thread_to_cancel
);
306 case VG_USERREQ__POST_THREAD_CANCEL
:
309 case VG_USERREQ__PRE_MUTEX_INIT
:
310 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
311 DRD_(mutex_init
)(arg
[1], arg
[2]);
314 case VG_USERREQ__POST_MUTEX_INIT
:
315 DRD_(thread_leave_synchr
)(drd_tid
);
318 case VG_USERREQ__PRE_MUTEX_DESTROY
:
319 DRD_(thread_enter_synchr
)(drd_tid
);
322 case VG_USERREQ__POST_MUTEX_DESTROY
:
323 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
324 DRD_(mutex_post_destroy
)(arg
[1]);
327 case VG_USERREQ__PRE_MUTEX_LOCK
:
328 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
329 DRD_(mutex_pre_lock
)(arg
[1], arg
[2], arg
[3]);
332 case VG_USERREQ__POST_MUTEX_LOCK
:
333 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
334 DRD_(mutex_post_lock
)(arg
[1], arg
[2], False
/*post_cond_wait*/);
337 case VG_USERREQ__PRE_MUTEX_UNLOCK
:
338 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
339 DRD_(mutex_unlock
)(arg
[1], arg
[2]);
342 case VG_USERREQ__POST_MUTEX_UNLOCK
:
343 DRD_(thread_leave_synchr
)(drd_tid
);
346 case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK
:
347 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
348 DRD_(spinlock_init_or_unlock
)(arg
[1]);
351 case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK
:
352 DRD_(thread_leave_synchr
)(drd_tid
);
355 case VG_USERREQ__PRE_COND_INIT
:
356 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
357 DRD_(cond_pre_init
)(arg
[1]);
360 case VG_USERREQ__POST_COND_INIT
:
361 DRD_(thread_leave_synchr
)(drd_tid
);
364 case VG_USERREQ__PRE_COND_DESTROY
:
365 DRD_(thread_enter_synchr
)(drd_tid
);
368 case VG_USERREQ__POST_COND_DESTROY
:
369 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
370 DRD_(cond_post_destroy
)(arg
[1]);
373 case VG_USERREQ__PRE_COND_WAIT
:
374 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
376 const Addr cond
= arg
[1];
377 const Addr mutex
= arg
[2];
378 const MutexT mutex_type
= arg
[3];
379 DRD_(mutex_unlock
)(mutex
, mutex_type
);
380 DRD_(cond_pre_wait
)(cond
, mutex
);
384 case VG_USERREQ__POST_COND_WAIT
:
385 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
387 const Addr cond
= arg
[1];
388 const Addr mutex
= arg
[2];
389 const Bool took_lock
= arg
[3];
390 DRD_(cond_post_wait
)(cond
);
391 DRD_(mutex_post_lock
)(mutex
, took_lock
, True
);
395 case VG_USERREQ__PRE_COND_SIGNAL
:
396 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
397 DRD_(cond_pre_signal
)(arg
[1]);
400 case VG_USERREQ__POST_COND_SIGNAL
:
401 DRD_(thread_leave_synchr
)(drd_tid
);
404 case VG_USERREQ__PRE_COND_BROADCAST
:
405 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
406 DRD_(cond_pre_broadcast
)(arg
[1]);
409 case VG_USERREQ__POST_COND_BROADCAST
:
410 DRD_(thread_leave_synchr
)(drd_tid
);
413 case VG_USERREQ__PRE_SEM_INIT
:
414 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
415 DRD_(semaphore_init
)(arg
[1], arg
[2], arg
[3]);
418 case VG_USERREQ__POST_SEM_INIT
:
419 DRD_(thread_leave_synchr
)(drd_tid
);
422 case VG_USERREQ__PRE_SEM_DESTROY
:
423 DRD_(thread_enter_synchr
)(drd_tid
);
426 case VG_USERREQ__POST_SEM_DESTROY
:
427 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
428 DRD_(semaphore_destroy
)(arg
[1]);
431 case VG_USERREQ__PRE_SEM_OPEN
:
432 DRD_(thread_enter_synchr
)(drd_tid
);
435 case VG_USERREQ__POST_SEM_OPEN
:
436 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
437 DRD_(semaphore_open
)(arg
[1], (Char
*)arg
[2], arg
[3], arg
[4], arg
[5]);
440 case VG_USERREQ__PRE_SEM_CLOSE
:
441 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
442 DRD_(semaphore_close
)(arg
[1]);
445 case VG_USERREQ__POST_SEM_CLOSE
:
446 DRD_(thread_leave_synchr
)(drd_tid
);
449 case VG_USERREQ__PRE_SEM_WAIT
:
450 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
451 DRD_(semaphore_pre_wait
)(arg
[1]);
454 case VG_USERREQ__POST_SEM_WAIT
:
455 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
456 DRD_(semaphore_post_wait
)(drd_tid
, arg
[1], arg
[2]);
459 case VG_USERREQ__PRE_SEM_POST
:
460 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
461 DRD_(semaphore_pre_post
)(drd_tid
, arg
[1]);
464 case VG_USERREQ__POST_SEM_POST
:
465 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
466 DRD_(semaphore_post_post
)(drd_tid
, arg
[1], arg
[2]);
469 case VG_USERREQ__PRE_BARRIER_INIT
:
470 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
471 DRD_(barrier_init
)(arg
[1], arg
[2], arg
[3], arg
[4]);
474 case VG_USERREQ__POST_BARRIER_INIT
:
475 DRD_(thread_leave_synchr
)(drd_tid
);
478 case VG_USERREQ__PRE_BARRIER_DESTROY
:
479 DRD_(thread_enter_synchr
)(drd_tid
);
482 case VG_USERREQ__POST_BARRIER_DESTROY
:
483 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
484 DRD_(barrier_destroy
)(arg
[1], arg
[2]);
487 case VG_USERREQ__PRE_BARRIER_WAIT
:
488 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
489 DRD_(barrier_pre_wait
)(drd_tid
, arg
[1], arg
[2]);
492 case VG_USERREQ__POST_BARRIER_WAIT
:
493 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
494 DRD_(barrier_post_wait
)(drd_tid
, arg
[1], arg
[2], arg
[3], arg
[4]);
497 case VG_USERREQ__PRE_RWLOCK_INIT
:
498 DRD_(rwlock_pre_init
)(arg
[1], pthread_rwlock
);
501 case VG_USERREQ__POST_RWLOCK_DESTROY
:
502 DRD_(rwlock_post_destroy
)(arg
[1], pthread_rwlock
);
505 case VG_USERREQ__PRE_RWLOCK_RDLOCK
:
506 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
507 DRD_(rwlock_pre_rdlock
)(arg
[1], pthread_rwlock
);
510 case VG_USERREQ__POST_RWLOCK_RDLOCK
:
511 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
512 DRD_(rwlock_post_rdlock
)(arg
[1], pthread_rwlock
, arg
[2]);
515 case VG_USERREQ__PRE_RWLOCK_WRLOCK
:
516 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
517 DRD_(rwlock_pre_wrlock
)(arg
[1], pthread_rwlock
);
520 case VG_USERREQ__POST_RWLOCK_WRLOCK
:
521 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
522 DRD_(rwlock_post_wrlock
)(arg
[1], pthread_rwlock
, arg
[2]);
525 case VG_USERREQ__PRE_RWLOCK_UNLOCK
:
526 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
527 DRD_(rwlock_pre_unlock
)(arg
[1], pthread_rwlock
);
530 case VG_USERREQ__POST_RWLOCK_UNLOCK
:
531 DRD_(thread_leave_synchr
)(drd_tid
);
534 case VG_USERREQ__DRD_CLEAN_MEMORY
:
536 DRD_(clean_memory
)(arg
[1], arg
[2]);
539 case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
:
541 /* Note: it is assumed below that the text arg[1] points to is never
542 * freed, e.g. because it points to static data.
544 UnimpClReqInfo UICR
=
545 { DRD_(thread_get_running_tid
)(), (Char
*)arg
[1] };
546 VG_(maybe_record_error
)(vg_tid
,
554 case VG_USERREQ__DRD_ANNOTATION_UNIMP
:
556 /* Note: it is assumed below that the text arg[1] points to is never
557 * freed, e.g. because it points to static data.
559 UnimpClReqInfo UICR
=
560 { DRD_(thread_get_running_tid
)(), (Char
*)arg
[1] };
561 VG_(maybe_record_error
)(vg_tid
,
571 VG_(message
)(Vg_DebugMsg
, "Unrecognized client request 0x%lx 0x%lx",