2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2020 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, see <http://www.gnu.org/licenses/>.
19 The GNU General Public License is contained in the file COPYING.
23 #include "drd_barrier.h"
24 #include "drd_clientreq.h"
26 #include "drd_error.h"
28 #include "drd_load_store.h"
29 #include "drd_malloc_wrappers.h"
30 #include "drd_mutex.h"
31 #include "drd_rwlock.h"
32 #include "drd_semaphore.h"
33 #include "drd_suppression.h" // drd_start_suppression()
34 #include "drd_thread.h"
35 #include "pub_tool_basics.h" // Bool
36 #include "pub_tool_libcassert.h"
37 #include "pub_tool_libcassert.h" // tl_assert()
38 #include "pub_tool_libcprint.h" // VG_(message)()
39 #include "pub_tool_machine.h" // VG_(get_SP)()
40 #include "pub_tool_threadstate.h"
41 #include "pub_tool_tooliface.h" // VG_(needs_...)()
44 /* Global variables. */
46 Bool
DRD_(g_free_is_write
);
49 /* Local function declarations. */
51 static Bool
handle_client_request(ThreadId vg_tid
, UWord
* arg
, UWord
* ret
);
54 /* Function definitions. */
57 * Tell the Valgrind core the address of the DRD function that processes
58 * client requests. Must be called before any client code is run.
60 void DRD_(clientreq_init
)(void)
62 VG_(needs_client_requests
)(handle_client_request
);
66 * DRD's handler for Valgrind client requests. The code below handles both
67 * DRD's public and tool-internal client requests.
69 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
70 /* There is a cse related issue in gcc for MIPS. Optimization level
71 has to be lowered, so cse related optimizations are not
73 __attribute__((optimize("O1")))
75 static Bool
handle_client_request(ThreadId vg_tid
, UWord
* arg
, UWord
* ret
)
78 const DrdThreadId drd_tid
= DRD_(thread_get_running_tid
)();
80 if (!VG_IS_TOOL_USERREQ('D','R',arg
[0])
81 && !VG_IS_TOOL_USERREQ('D','r',arg
[0])
82 && !VG_IS_TOOL_USERREQ('H','G',arg
[0])
83 && VG_USERREQ__MALLOCLIKE_BLOCK
!= arg
[0]
84 && VG_USERREQ__RESIZEINPLACE_BLOCK
!= arg
[0]
85 && VG_USERREQ__FREELIKE_BLOCK
!= arg
[0]
86 #if defined(VGO_solaris)
87 && VG_USERREQ_DRD_RTLD_BIND_GUARD
!= arg
[0]
88 && VG_USERREQ_DRD_RTLD_BIND_CLEAR
!= arg
[0]
89 #endif /* VGO_solaris */
90 && VG_USERREQ__GDB_MONITOR_COMMAND
!= arg
[0]) {
94 tl_assert(vg_tid
== VG_(get_running_tid
)());
95 tl_assert(DRD_(VgThreadIdToDrdThreadId
)(vg_tid
) == drd_tid
96 || (VG_USERREQ__GDB_MONITOR_COMMAND
== arg
[0]
97 && vg_tid
== VG_INVALID_THREADID
));
98 /* Check the consistency of vg_tid and drd_tid, unless
99 vgdb has forced the invocation of a gdb monitor cmd
100 when no threads was running (i.e. all threads blocked
101 in a syscall. In such a case, vg_tid is invalid,
102 its conversion to a drd thread id gives also an invalid
103 drd thread id, but drd_tid is not invalid (probably
104 equal to the last running drd thread. */
108 case VG_USERREQ__MALLOCLIKE_BLOCK
:
109 if (DRD_(g_free_is_write
)) {
110 GenericErrInfo GEI
= {
111 .tid
= DRD_(thread_get_running_tid
)(),
114 VG_(maybe_record_error
)(vg_tid
,
117 "--free-is-write=yes is incompatible with"
118 " custom memory allocator client requests",
122 DRD_(malloclike_block
)(vg_tid
, arg
[1]/*addr*/, arg
[2]/*size*/);
125 case VG_USERREQ__RESIZEINPLACE_BLOCK
:
126 if (!DRD_(freelike_block
)(vg_tid
, arg
[1]/*addr*/, False
))
128 GenericErrInfo GEI
= {
129 .tid
= DRD_(thread_get_running_tid
)(),
132 VG_(maybe_record_error
)(vg_tid
,
135 "Invalid VG_USERREQ__RESIZEINPLACE_BLOCK request",
138 DRD_(malloclike_block
)(vg_tid
, arg
[1]/*addr*/, arg
[3]/*newSize*/);
141 case VG_USERREQ__FREELIKE_BLOCK
:
142 if (arg
[1] && ! DRD_(freelike_block
)(vg_tid
, arg
[1]/*addr*/, False
))
144 GenericErrInfo GEI
= {
145 .tid
= DRD_(thread_get_running_tid
)(),
148 VG_(maybe_record_error
)(vg_tid
,
151 "Invalid VG_USERREQ__FREELIKE_BLOCK request",
156 case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID
:
160 case VG_USERREQ__DRD_GET_DRD_THREAD_ID
:
164 case VG_USERREQ__DRD_SET_THREAD_NAME
:
165 DRD_(thread_set_name
)(drd_tid
, (const HChar
*)arg
[1]);
168 case VG_USERREQ__DRD_START_SUPPRESSION
:
169 /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
170 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
171 DRD_(start_suppression
)(arg
[1], arg
[1] + arg
[2], "client");
174 case VG_USERREQ__DRD_FINISH_SUPPRESSION
:
175 /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
176 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
177 DRD_(finish_suppression
)(arg
[1], arg
[1] + arg
[2]);
180 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE
:
181 DRD_(hb_happens_before
)(drd_tid
, arg
[1]);
184 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER
:
185 DRD_(hb_happens_after
)(drd_tid
, arg
[1]);
188 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE
:
191 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
192 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
195 DRD_(rwlock_pre_init
)(arg
[1], user_rwlock
);
198 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY
:
201 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
202 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
205 DRD_(rwlock_post_destroy
)(arg
[1], user_rwlock
);
208 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED
:
211 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
212 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
215 tl_assert(arg
[2] == !! arg
[2]);
218 DRD_(rwlock_pre_wrlock
)(arg
[1], user_rwlock
);
219 DRD_(rwlock_post_wrlock
)(arg
[1], user_rwlock
, True
);
223 DRD_(rwlock_pre_rdlock
)(arg
[1], user_rwlock
);
224 DRD_(rwlock_post_rdlock
)(arg
[1], user_rwlock
, True
);
228 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED
:
231 struct mutex_info
* const mutex_p
= DRD_(mutex_get
)(arg
[1]);
232 if (mutex_p
&& mutex_p
->mutex_type
== mutex_type_spinlock
)
235 tl_assert(arg
[2] == !! arg
[2]);
236 DRD_(rwlock_pre_unlock
)(arg
[1], user_rwlock
);
239 case VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE
:
240 DRD_(semaphore_init
)(arg
[1], 0, arg
[2]);
243 case VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST
:
244 DRD_(semaphore_destroy
)(arg
[1]);
247 case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE
:
248 DRD_(semaphore_pre_wait
)(arg
[1]);
251 case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST
:
252 DRD_(semaphore_post_wait
)(drd_tid
, arg
[1], True
/* waited */);
255 case VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE
:
256 DRD_(semaphore_pre_post
)(drd_tid
, arg
[1]);
259 case VG_USERREQ_DRD_SET_PTHREAD_COND_INITIALIZER
:
260 DRD_(pthread_cond_initializer
) = (Addr
)arg
[1];
261 DRD_(pthread_cond_initializer_size
) = arg
[2];
264 case VG_USERREQ_DRD_START_NEW_SEGMENT
:
265 DRD_(thread_new_segment
)(DRD_(PtThreadIdToDrdThreadId
)(arg
[1]));
268 case VG_USERREQ__DRD_START_TRACE_ADDR
:
269 DRD_(start_tracing_address_range
)(arg
[1], arg
[1] + arg
[2], False
);
272 case VG_USERREQ__DRD_STOP_TRACE_ADDR
:
273 DRD_(stop_tracing_address_range
)(arg
[1], arg
[1] + arg
[2]);
276 case VG_USERREQ__DRD_RECORD_LOADS
:
277 DRD_(thread_set_record_loads
)(drd_tid
, arg
[1]);
280 case VG_USERREQ__DRD_RECORD_STORES
:
281 DRD_(thread_set_record_stores
)(drd_tid
, arg
[1]);
284 case VG_USERREQ_DRD_SET_PTHREADID
:
285 // pthread_self() returns 0 for programs not linked with libpthread.so.
286 if (arg
[1] != INVALID_POSIX_THREADID
)
287 DRD_(thread_set_pthreadid
)(drd_tid
, arg
[1]);
290 case VG_USERREQ_DRD_SET_JOINABLE
:
292 const DrdThreadId drd_joinable
= DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
293 if (drd_joinable
!= DRD_INVALID_THREADID
)
294 DRD_(thread_set_joinable
)(drd_joinable
, (Bool
)arg
[2]);
296 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
297 VG_(maybe_record_error
)(vg_tid
,
300 "pthread_detach(): invalid thread ID",
306 case VG_USERREQ_DRD_ENTERING_PTHREAD_CREATE
:
307 DRD_(thread_entering_pthread_create
)(drd_tid
);
310 case VG_USERREQ_DRD_LEFT_PTHREAD_CREATE
:
311 DRD_(thread_left_pthread_create
)(drd_tid
);
314 case VG_USERREQ_DRD_POST_THREAD_JOIN
:
316 const DrdThreadId thread_to_join
= DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
317 if (thread_to_join
== DRD_INVALID_THREADID
)
319 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
320 VG_(maybe_record_error
)(vg_tid
,
323 "pthread_join(): invalid thread ID",
328 DRD_(thread_post_join
)(drd_tid
, thread_to_join
);
333 case VG_USERREQ_DRD_PRE_THREAD_CANCEL
:
335 const DrdThreadId thread_to_cancel
=DRD_(PtThreadIdToDrdThreadId
)(arg
[1]);
336 if (thread_to_cancel
== DRD_INVALID_THREADID
)
338 InvalidThreadIdInfo ITI
= { DRD_(thread_get_running_tid
)(), arg
[1] };
339 VG_(maybe_record_error
)(vg_tid
,
342 "pthread_cancel(): invalid thread ID",
347 DRD_(thread_pre_cancel
)(thread_to_cancel
);
352 case VG_USERREQ_DRD_POST_THREAD_CANCEL
:
355 case VG_USERREQ_DRD_PRE_MUTEX_INIT
:
356 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
357 DRD_(mutex_init
)(arg
[1], arg
[2]);
360 case VG_USERREQ_DRD_POST_MUTEX_INIT
:
361 DRD_(thread_leave_synchr
)(drd_tid
);
364 case VG_USERREQ_DRD_PRE_MUTEX_DESTROY
:
365 DRD_(thread_enter_synchr
)(drd_tid
);
368 case VG_USERREQ_DRD_POST_MUTEX_DESTROY
:
369 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
370 DRD_(mutex_post_destroy
)(arg
[1]);
373 case VG_USERREQ_DRD_PRE_MUTEX_LOCK
:
374 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
375 DRD_(mutex_pre_lock
)(arg
[1], arg
[2], arg
[3]);
378 case VG_USERREQ_DRD_POST_MUTEX_LOCK
:
379 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
380 DRD_(mutex_post_lock
)(arg
[1], arg
[2], False
/*post_cond_wait*/);
383 case VG_USERREQ_DRD_PRE_MUTEX_UNLOCK
:
384 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
385 DRD_(mutex_unlock
)(arg
[1], arg
[2]);
388 case VG_USERREQ_DRD_POST_MUTEX_UNLOCK
:
389 DRD_(thread_leave_synchr
)(drd_tid
);
392 case VG_USERREQ__DRD_IGNORE_MUTEX_ORDERING
:
393 DRD_(mutex_ignore_ordering
)(arg
[1]);
396 case VG_USERREQ_DRD_PRE_SPIN_INIT_OR_UNLOCK
:
397 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
398 DRD_(spinlock_init_or_unlock
)(arg
[1]);
401 case VG_USERREQ_DRD_POST_SPIN_INIT_OR_UNLOCK
:
402 DRD_(thread_leave_synchr
)(drd_tid
);
405 case VG_USERREQ_DRD_PRE_COND_INIT
:
406 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
407 DRD_(cond_pre_init
)(arg
[1]);
410 case VG_USERREQ_DRD_POST_COND_INIT
:
411 DRD_(thread_leave_synchr
)(drd_tid
);
414 case VG_USERREQ_DRD_PRE_COND_DESTROY
:
415 DRD_(thread_enter_synchr
)(drd_tid
);
418 case VG_USERREQ_DRD_POST_COND_DESTROY
:
419 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
420 DRD_(cond_post_destroy
)(arg
[1], arg
[2]);
423 case VG_USERREQ_DRD_PRE_COND_WAIT
:
424 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
426 const Addr cond
= arg
[1];
427 const Addr mutex
= arg
[2];
428 const MutexT mutex_type
= arg
[3];
429 DRD_(mutex_unlock
)(mutex
, mutex_type
);
430 DRD_(cond_pre_wait
)(cond
, mutex
);
434 case VG_USERREQ_DRD_POST_COND_WAIT
:
435 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
437 const Addr cond
= arg
[1];
438 const Addr mutex
= arg
[2];
439 const Bool took_lock
= arg
[3];
440 DRD_(cond_post_wait
)(cond
);
441 DRD_(mutex_post_lock
)(mutex
, took_lock
, True
);
445 case VG_USERREQ_DRD_PRE_COND_SIGNAL
:
446 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
447 DRD_(cond_pre_signal
)(arg
[1]);
450 case VG_USERREQ_DRD_POST_COND_SIGNAL
:
451 DRD_(thread_leave_synchr
)(drd_tid
);
454 case VG_USERREQ_DRD_PRE_COND_BROADCAST
:
455 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
456 DRD_(cond_pre_broadcast
)(arg
[1]);
459 case VG_USERREQ_DRD_POST_COND_BROADCAST
:
460 DRD_(thread_leave_synchr
)(drd_tid
);
463 case VG_USERREQ_DRD_PRE_SEM_INIT
:
464 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
465 DRD_(semaphore_init
)(arg
[1], arg
[2], arg
[3]);
468 case VG_USERREQ_DRD_POST_SEM_INIT
:
469 DRD_(thread_leave_synchr
)(drd_tid
);
472 case VG_USERREQ_DRD_PRE_SEM_DESTROY
:
473 DRD_(thread_enter_synchr
)(drd_tid
);
476 case VG_USERREQ_DRD_POST_SEM_DESTROY
:
477 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
478 DRD_(semaphore_destroy
)(arg
[1]);
481 case VG_USERREQ_DRD_PRE_SEM_OPEN
:
482 DRD_(thread_enter_synchr
)(drd_tid
);
485 case VG_USERREQ_DRD_POST_SEM_OPEN
:
486 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
487 DRD_(semaphore_open
)(arg
[1], (HChar
*)arg
[2], arg
[3], arg
[4], arg
[5]);
490 case VG_USERREQ_DRD_PRE_SEM_CLOSE
:
491 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
492 DRD_(semaphore_close
)(arg
[1]);
495 case VG_USERREQ_DRD_POST_SEM_CLOSE
:
496 DRD_(thread_leave_synchr
)(drd_tid
);
499 case VG_USERREQ_DRD_PRE_SEM_WAIT
:
500 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
501 DRD_(semaphore_pre_wait
)(arg
[1]);
504 case VG_USERREQ_DRD_POST_SEM_WAIT
:
505 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
506 DRD_(semaphore_post_wait
)(drd_tid
, arg
[1], arg
[2]);
509 case VG_USERREQ_DRD_PRE_SEM_POST
:
510 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
511 DRD_(semaphore_pre_post
)(drd_tid
, arg
[1]);
514 case VG_USERREQ_DRD_POST_SEM_POST
:
515 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
516 DRD_(semaphore_post_post
)(drd_tid
, arg
[1], arg
[2]);
519 case VG_USERREQ_DRD_PRE_BARRIER_INIT
:
520 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
521 DRD_(barrier_init
)(arg
[1], arg
[2], arg
[3], arg
[4]);
524 case VG_USERREQ_DRD_POST_BARRIER_INIT
:
525 DRD_(thread_leave_synchr
)(drd_tid
);
528 case VG_USERREQ_DRD_PRE_BARRIER_DESTROY
:
529 DRD_(thread_enter_synchr
)(drd_tid
);
532 case VG_USERREQ_DRD_POST_BARRIER_DESTROY
:
533 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
534 DRD_(barrier_destroy
)(arg
[1], arg
[2]);
537 case VG_USERREQ_DRD_PRE_BARRIER_WAIT
:
538 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
539 DRD_(barrier_pre_wait
)(drd_tid
, arg
[1], arg
[2]);
542 case VG_USERREQ_DRD_POST_BARRIER_WAIT
:
543 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
544 DRD_(barrier_post_wait
)(drd_tid
, arg
[1], arg
[2], arg
[3], arg
[4]);
547 case VG_USERREQ_DRD_PRE_RWLOCK_INIT
:
548 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
549 DRD_(rwlock_pre_init
)(arg
[1], pthread_rwlock
);
552 case VG_USERREQ_DRD_POST_RWLOCK_INIT
:
553 DRD_(thread_leave_synchr
)(drd_tid
);
556 case VG_USERREQ_DRD_PRE_RWLOCK_DESTROY
:
557 DRD_(thread_enter_synchr
)(drd_tid
);
560 case VG_USERREQ_DRD_POST_RWLOCK_DESTROY
:
561 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
562 DRD_(rwlock_post_destroy
)(arg
[1], pthread_rwlock
);
565 case VG_USERREQ_DRD_PRE_RWLOCK_RDLOCK
:
566 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
567 DRD_(rwlock_pre_rdlock
)(arg
[1], pthread_rwlock
);
570 case VG_USERREQ_DRD_POST_RWLOCK_RDLOCK
:
571 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
572 DRD_(rwlock_post_rdlock
)(arg
[1], pthread_rwlock
, arg
[2]);
575 case VG_USERREQ_DRD_PRE_RWLOCK_WRLOCK
:
576 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
577 DRD_(rwlock_pre_wrlock
)(arg
[1], pthread_rwlock
);
580 case VG_USERREQ_DRD_POST_RWLOCK_WRLOCK
:
581 if (DRD_(thread_leave_synchr
)(drd_tid
) == 0)
582 DRD_(rwlock_post_wrlock
)(arg
[1], pthread_rwlock
, arg
[2]);
585 case VG_USERREQ_DRD_PRE_RWLOCK_UNLOCK
:
586 if (DRD_(thread_enter_synchr
)(drd_tid
) == 0)
587 DRD_(rwlock_pre_unlock
)(arg
[1], pthread_rwlock
);
590 case VG_USERREQ_DRD_POST_RWLOCK_UNLOCK
:
591 DRD_(thread_leave_synchr
)(drd_tid
);
594 case VG_USERREQ__DRD_CLEAN_MEMORY
:
596 DRD_(clean_memory
)(arg
[1], arg
[2]);
599 case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP
:
601 /* Note: it is assumed below that the text arg[1] points to is never
602 * freed, e.g. because it points to static data.
604 UnimpClReqInfo UICR
=
605 { DRD_(thread_get_running_tid
)(), (HChar
*)arg
[1] };
606 VG_(maybe_record_error
)(vg_tid
,
614 case VG_USERREQ__DRD_ANNOTATION_UNIMP
:
616 /* Note: it is assumed below that the text arg[1] points to is never
617 * freed, e.g. because it points to static data.
619 UnimpClReqInfo UICR
=
620 { DRD_(thread_get_running_tid
)(), (HChar
*)arg
[1] };
621 VG_(maybe_record_error
)(vg_tid
,
629 #if defined(VGO_solaris)
630 case VG_USERREQ_DRD_RTLD_BIND_GUARD
:
631 DRD_(thread_entering_rtld_bind_guard
)(drd_tid
, arg
[1]);
634 case VG_USERREQ_DRD_RTLD_BIND_CLEAR
:
635 DRD_(thread_leaving_rtld_bind_clear
)(drd_tid
, arg
[1]);
637 #endif /* VGO_solaris */
640 if (VG_IS_TOOL_USERREQ('D','R',arg
[0]) ||
641 VG_IS_TOOL_USERREQ('D','r',arg
[0])) {
642 /* don't warn about any unhandled HG client reqs */
643 VG_(message
)(Vg_UserMsg
,
644 "Warning: unknown DRD client request code %llx\n",