Skip to content

Commit 97fefec

Browse files
i#7598 attach gap: Add drmgr pre-detach event (#7641)
Adds drmgr mediation of the pre-detach event to provide a user-data version and priorities. Adds testing in an existing test that uses drmgr and detach. Updates the changelist compatibility section as this requires clients to switch from the base DR event. Issue: #7598, #7604
1 parent 0eecefa commit 97fefec

File tree

5 files changed

+146
-1
lines changed

5 files changed

+146
-1
lines changed

api/docs/release.dox

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ compatibility changes:
199199
drmgr_unregister_post_attach_event_user_data(), which are required to be used
200200
instead of dr_register_post_attach_event() when using drmgr and provide
201201
priorities and user data to the post-attach event.
202+
- Added drmgr_register_pre_detach_event(), drmgr_unregister_pre_detach_event(),
203+
drmgr_register_pre_detach_event_user_data(), and
204+
drmgr_unregister_pre_detach_event_user_data(), which are required to be used
205+
instead of dr_register_pre_detach_event() when using drmgr and provide
206+
priorities and user data to the pre-detach event.
202207

203208
Further non-compatibility-affecting changes include:
204209
- Changed the types of `block_size`, `total_size`, `num_blocks`, to `int64_t`

clients/drcachesim/tracer/tracer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,7 @@ event_exit(void)
20862086
}
20872087
drmgr_unregister_exit_event(event_exit);
20882088
drmgr_unregister_post_attach_event(event_post_attach);
2089+
drmgr_unregister_pre_detach_event(event_pre_detach);
20892090

20902091
/* Clear callbacks and globals to support re-attach when linked statically. */
20912092
file_ops_func = file_ops_func_t();
@@ -2545,7 +2546,7 @@ drmemtrace_client_main(client_id_t id, int argc, const char *argv[])
25452546
FATAL("Failed to register post-attach event.\n");
25462547
attached_midway = dr_attached_midrun();
25472548

2548-
dr_register_pre_detach_event(event_pre_detach);
2549+
drmgr_register_pre_detach_event(event_pre_detach);
25492550
dr_register_nudge_event(event_nudge, id);
25502551

25512552
/* We need our thread exit event to run *before* drmodtrack's as we may

ext/drmgr/drmgr.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
#undef dr_unregister_exit_event
5656
#undef dr_register_post_attach_event
5757
#undef dr_unregister_post_attach_event
58+
#undef dr_register_pre_detach_event
59+
#undef dr_unregister_pre_detach_event
5860
#undef dr_register_thread_init_event
5961
#undef dr_unregister_thread_init_event
6062
#undef dr_register_thread_exit_event
@@ -144,6 +146,10 @@ typedef struct _generic_event_entry_t {
144146
void (*cb_no_user_data)();
145147
void (*cb_user_data)(void *);
146148
} post_attach_cb;
149+
union {
150+
void (*cb_no_user_data)();
151+
void (*cb_user_data)(void *);
152+
} pre_detach_cb;
147153
union {
148154
void (*cb_no_user_data)(void *);
149155
void (*cb_user_data)(void *, void *);
@@ -349,6 +355,8 @@ static void *exit_event_lock;
349355

350356
static cb_list_t cb_list_post_attach;
351357
static void *post_attach_event_lock;
358+
static cb_list_t cb_list_pre_detach;
359+
static void *pre_detach_event_lock;
352360

353361
/* Thread event cbs and rwlock */
354362
static cb_list_t cb_list_thread_init;
@@ -414,6 +422,9 @@ drmgr_exit_event(void);
414422
static void
415423
drmgr_post_attach_event(void);
416424

425+
static void
426+
drmgr_pre_detach_event(void);
427+
417428
static void
418429
drmgr_thread_init_event(void *drcontext);
419430

@@ -501,6 +512,7 @@ drmgr_init(void)
501512
bb_cb_lock = dr_rwlock_create();
502513
exit_event_lock = dr_rwlock_create();
503514
post_attach_event_lock = dr_rwlock_create();
515+
pre_detach_event_lock = dr_rwlock_create();
504516
thread_event_lock = dr_rwlock_create();
505517
tls_lock = dr_mutex_create();
506518
cls_event_lock = dr_rwlock_create();
@@ -523,6 +535,7 @@ drmgr_init(void)
523535

524536
dr_register_exit_event(drmgr_exit_event);
525537
dr_register_post_attach_event(drmgr_post_attach_event);
538+
dr_register_pre_detach_event(drmgr_pre_detach_event);
526539

527540
dr_register_thread_init_event(drmgr_thread_init_event);
528541
dr_register_thread_exit_event(drmgr_thread_exit_event);
@@ -567,6 +580,7 @@ our_exit_event(void)
567580
drmgr_event_exit();
568581

569582
dr_unregister_post_attach_event(drmgr_post_attach_event);
583+
dr_unregister_pre_detach_event(drmgr_pre_detach_event);
570584

571585
dr_unregister_thread_init_event(drmgr_thread_init_event);
572586
dr_unregister_thread_exit_event(drmgr_thread_exit_event);
@@ -614,6 +628,7 @@ our_exit_event(void)
614628
dr_rwlock_destroy(thread_event_lock);
615629
dr_rwlock_destroy(exit_event_lock);
616630
dr_rwlock_destroy(post_attach_event_lock);
631+
dr_rwlock_destroy(pre_detach_event_lock);
617632
dr_rwlock_destroy(bb_cb_lock);
618633

619634
dr_mutex_destroy(note_lock);
@@ -1955,6 +1970,7 @@ drmgr_event_init(void)
19551970
{
19561971
cblist_init(&cb_list_exit, sizeof(generic_event_entry_t));
19571972
cblist_init(&cb_list_post_attach, sizeof(generic_event_entry_t));
1973+
cblist_init(&cb_list_pre_detach, sizeof(generic_event_entry_t));
19581974
cblist_init(&cb_list_thread_init, sizeof(generic_event_entry_t));
19591975
cblist_init(&cb_list_thread_exit, sizeof(generic_event_entry_t));
19601976
cblist_init(&cblist_cls_init, sizeof(generic_event_entry_t));
@@ -1986,6 +2002,7 @@ drmgr_event_exit(void)
19862002
*/
19872003
cblist_delete(&cb_list_exit);
19882004
cblist_delete(&cb_list_post_attach);
2005+
cblist_delete(&cb_list_pre_detach);
19892006
cblist_delete(&cb_list_thread_init);
19902007
cblist_delete(&cb_list_thread_exit);
19912008
cblist_delete(&cblist_cls_init);
@@ -2130,6 +2147,65 @@ drmgr_post_attach_event(void)
21302147
cblist_delete_local(drcontext, &iter, BUFFER_SIZE_ELEMENTS(local));
21312148
}
21322149

2150+
DR_EXPORT
2151+
bool
2152+
drmgr_register_pre_detach_event(void (*func)(void))
2153+
{
2154+
return drmgr_generic_event_add(&cb_list_pre_detach, pre_detach_event_lock, func, NULL,
2155+
false, NULL);
2156+
}
2157+
2158+
DR_EXPORT
2159+
bool
2160+
drmgr_register_pre_detach_event_user_data(void (*func)(void *user_data),
2161+
drmgr_priority_t *priority, void *user_data)
2162+
{
2163+
return drmgr_generic_event_add(&cb_list_pre_detach, pre_detach_event_lock,
2164+
(void (*)(void))func, priority, true, user_data);
2165+
}
2166+
2167+
DR_EXPORT
2168+
bool
2169+
drmgr_unregister_pre_detach_event(void (*func)(void))
2170+
{
2171+
return drmgr_generic_event_remove(&cb_list_pre_detach, pre_detach_event_lock,
2172+
(void (*)(void))func);
2173+
}
2174+
2175+
DR_EXPORT
2176+
bool
2177+
drmgr_unregister_pre_detach_event_user_data(void (*func)(void *user_data))
2178+
{
2179+
return drmgr_generic_event_remove(&cb_list_pre_detach, pre_detach_event_lock,
2180+
(void (*)(void))func);
2181+
}
2182+
2183+
static void
2184+
drmgr_pre_detach_event(void)
2185+
{
2186+
generic_event_entry_t local[EVENTS_STACK_SZ];
2187+
cb_list_t iter;
2188+
uint i;
2189+
void *drcontext = GLOBAL_DCONTEXT;
2190+
dr_rwlock_read_lock(pre_detach_event_lock);
2191+
cblist_create_local(drcontext, &cb_list_pre_detach, &iter, (byte *)local,
2192+
BUFFER_SIZE_ELEMENTS(local));
2193+
dr_rwlock_read_unlock(pre_detach_event_lock);
2194+
2195+
for (i = 0; i < iter.num_def; i++) {
2196+
if (!iter.cbs.generic[i].pri.valid)
2197+
continue;
2198+
bool is_using_user_data = iter.cbs.generic[i].is_using_user_data;
2199+
void *user_data = iter.cbs.generic[i].user_data;
2200+
if (is_using_user_data == false)
2201+
(*iter.cbs.generic[i].cb.pre_detach_cb.cb_no_user_data)();
2202+
else {
2203+
(*iter.cbs.generic[i].cb.pre_detach_cb.cb_user_data)(user_data);
2204+
}
2205+
}
2206+
cblist_delete_local(drcontext, &iter, BUFFER_SIZE_ELEMENTS(local));
2207+
}
2208+
21332209
DR_EXPORT
21342210
bool
21352211
drmgr_register_thread_init_event(void (*func)(void *drcontext))

ext/drmgr/drmgr.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,45 @@ DR_EXPORT
11921192
bool
11931193
drmgr_unregister_post_attach_event_user_data(void (*func)(void *user_data));
11941194

1195+
DR_EXPORT
1196+
/**
1197+
* Registers a callback function for the pre_detach event, which behaves
1198+
* just like the event registered by dr_register_pre_detach_event().
1199+
* \return whether successful.
1200+
*/
1201+
bool
1202+
drmgr_register_pre_detach_event(void (*func)(void));
1203+
1204+
DR_EXPORT
1205+
/**
1206+
* Registers a callback function for the pre_detach event, which behaves
1207+
* just like the event registered by dr_register_pre_detach_event() but is
1208+
* ordered by \p priority. Allows for the passing of user data \p user_data
1209+
* which is available upon the execution of the callback.
1210+
* \return whether successful.
1211+
*/
1212+
bool
1213+
drmgr_register_pre_detach_event_user_data(void (*func)(void *user_data),
1214+
drmgr_priority_t *priority, void *user_data);
1215+
1216+
DR_EXPORT
1217+
/**
1218+
* Unregister a callback function for the pre_detach event.
1219+
* \return true if unregistration is successful and false if it is not
1220+
* (e.g., \p func was not registered).
1221+
*/
1222+
bool
1223+
drmgr_unregister_pre_detach_event(void (*func)(void));
1224+
1225+
DR_EXPORT
1226+
/**
1227+
* Unregister a callback function for the pre_detach event.
1228+
* \return true if unregistration is successful and false if it is not
1229+
* (e.g., \p func was not registered).
1230+
*/
1231+
bool
1232+
drmgr_unregister_pre_detach_event_user_data(void (*func)(void *user_data));
1233+
11951234
DR_EXPORT
11961235
/**
11971236
* Registers a callback function for the thread initialization event.

suite/tests/client-interface/drx_timeout_scale-test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
#include <iostream>
6767
#include <thread>
6868

69+
static constexpr ptr_uint_t PRE_DETACH_USER_DATA = 0x12345678;
70+
6971
namespace dynamorio {
7072
namespace drmemtrace {
7173

@@ -87,6 +89,7 @@ static pthread_cond_t condvar;
8789
static bool child_ready;
8890
static pthread_mutex_t lock;
8991
static std::atomic<bool> child_should_exit;
92+
static bool pre_detach_ran;
9093

9194
bool
9295
my_setenv(const char *var, const char *value)
@@ -267,6 +270,13 @@ do_some_work(drx_time_scale_type_t optype)
267270
return reinterpret_cast<int64_t>(retval);
268271
}
269272

273+
static void
274+
event_pre_detach(void *user_data)
275+
{
276+
pre_detach_ran = true;
277+
assert(reinterpret_cast<ptr_uint_t>(user_data) == PRE_DETACH_USER_DATA);
278+
}
279+
270280
static void
271281
event_exit(void *user_data)
272282
{
@@ -298,8 +308,15 @@ event_exit(void *user_data)
298308
} else
299309
assert(false);
300310

311+
assert(pre_detach_ran);
312+
301313
ok = drx_unregister_time_scaling();
302314
assert(ok);
315+
ok = drmgr_unregister_exit_event_user_data(event_exit);
316+
assert(ok);
317+
ok = drmgr_unregister_pre_detach_event_user_data(event_pre_detach);
318+
assert(ok);
319+
303320
drx_exit();
304321
drmgr_exit();
305322
dr_fprintf(STDERR, "client done\n");
@@ -364,6 +381,13 @@ dr_client_main(client_id_t id, int argc, const char *argv[])
364381
ok = drx_init();
365382
assert(ok);
366383

384+
// We sanity-test the drmgr pre-detach user data here as this is one
385+
// of the few tests that does a detach and uses drmgr.
386+
ok = drmgr_register_pre_detach_event_user_data(
387+
dynamorio::drmemtrace::event_pre_detach, nullptr,
388+
reinterpret_cast<void *>(PRE_DETACH_USER_DATA));
389+
assert(ok);
390+
367391
drx_time_scale_t scale = {
368392
sizeof(scale),
369393
};

0 commit comments

Comments
 (0)