Skip to content

Commit

Permalink
i#2833 user data: add module events with user data (#2837)
Browse files Browse the repository at this point in the history
Adds new versions of drmgr's module load/unload events that take in user data parameters.
Adds tests of the new functions.
    
Issue: #2833
  • Loading branch information
johnfxgalea authored and derekbruening committed Mar 8, 2018
1 parent f0a1f28 commit 13e4f95
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 13 deletions.
4 changes: 4 additions & 0 deletions api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ Further non-compatibility-affecting changes include:
drmgr_unregister_thread_init_event_user_data() to enable passing of user data.
- Added drmgr_register_thread_exit_event_user_data() and
drmgr_unregister_thread_exit_event_usr_data() to enable passing of user data.
- Added drmgr_register_module_load_event_user_data() and
drmgr_unregister_module_load_event_user_data() to enable passing of user data.
- Added drmgr_register_module_unload_event_user_data() and
drmgr_unregister_module_unload_event() to enable passing of user data.
- Added a new drcachesim feature that records which cpu each thread
executed on along with an optional simulator scheduling feature to
schedule threads on simulated cores to match the recorded execution on
Expand Down
72 changes: 68 additions & 4 deletions ext/drmgr/drmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,14 @@ typedef struct _generic_event_entry_t {
void (*cls_cb)(void *, bool);
bool (*presys_cb)(void *, int);
void (*postsys_cb)(void *, int);
void (*modload_cb)(void *, const module_data_t *, bool);
void (*modunload_cb)(void *, const module_data_t *);
union {
void (*cb_no_user_data)(void *, const module_data_t *, bool);
void (*cb_user_data)(void *, const module_data_t *, bool, void *user_data);
} modload_cb;
union {
void (*cb_no_user_data)(void *, const module_data_t *);
void (*cb_user_data)(void *, const module_data_t *, void *user_data);
} modunload_cb;
void (*kernel_xfer_cb)(void *, const dr_kernel_xfer_info_t *);
#ifdef UNIX
dr_signal_action_t (*signal_cb)(void *, dr_siginfo_t *);
Expand Down Expand Up @@ -1458,6 +1464,17 @@ drmgr_register_module_load_event_ex(void (*func)
(void (*)(void)) func, priority, false, NULL);
}

DR_EXPORT
bool
drmgr_register_module_load_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
bool loaded, void *user_data),
drmgr_priority_t *priority, void *user_data)
{
return drmgr_generic_event_add(&cblist_modload, modload_event_lock,
(void (*)(void)) func, priority, true, user_data);
}

DR_EXPORT
bool
drmgr_unregister_module_load_event(void (*func)
Expand All @@ -1468,6 +1485,16 @@ drmgr_unregister_module_load_event(void (*func)
(void (*)(void)) func);
}

DR_EXPORT
bool
drmgr_unregister_module_load_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
bool loaded, void *user_data))
{
return drmgr_generic_event_remove(&cblist_modload, modload_event_lock,
(void (*)(void)) func);
}

static void
drmgr_modload_event(void *drcontext, const module_data_t *info,
bool loaded)
Expand All @@ -1483,7 +1510,15 @@ drmgr_modload_event(void *drcontext, const module_data_t *info,
for (i = 0; i < iter.num; i++) {
if (!iter.cbs.generic[i].pri.valid)
continue;
(*iter.cbs.generic[i].cb.modload_cb)(drcontext, info, loaded);
bool is_using_user_data = iter.cbs.generic[i].is_using_user_data;
void *user_data = iter.cbs.generic[i].user_data;
if (is_using_user_data == false) {
(*iter.cbs.generic[i].cb.modload_cb.cb_no_user_data)(drcontext, info,
loaded);
} else {
(*iter.cbs.generic[i].cb.modload_cb.cb_user_data)(drcontext, info, loaded,
user_data);
}
}
cblist_delete_local(drcontext, &iter, BUFFER_SIZE_ELEMENTS(local));
}
Expand All @@ -1507,6 +1542,17 @@ drmgr_register_module_unload_event_ex(void (*func)
(void (*)(void)) func, priority, false, NULL);
}

DR_EXPORT
bool
drmgr_register_module_unload_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
void *user_data),
drmgr_priority_t *priority, void *user_data)
{
return drmgr_generic_event_add(&cblist_modunload, modunload_event_lock,
(void (*)(void)) func, priority, true, user_data);
}

DR_EXPORT
bool
drmgr_unregister_module_unload_event(void (*func)
Expand All @@ -1516,6 +1562,17 @@ drmgr_unregister_module_unload_event(void (*func)
(void (*)(void)) func);
}

DR_EXPORT
bool
drmgr_unregister_module_unload_event_user_data(void (*func)
(void *drcontext,
const module_data_t *info,
void *user_data))
{
return drmgr_generic_event_remove(&cblist_modunload, modunload_event_lock,
(void (*)(void)) func);
}

static void
drmgr_modunload_event(void *drcontext, const module_data_t *info)
{
Expand All @@ -1530,7 +1587,14 @@ drmgr_modunload_event(void *drcontext, const module_data_t *info)
for (i = 0; i < iter.num; i++) {
if (!iter.cbs.generic[i].pri.valid)
continue;
(*iter.cbs.generic[i].cb.modunload_cb)(drcontext, info);
bool is_using_user_data = iter.cbs.generic[i].is_using_user_data;
void *user_data = iter.cbs.generic[i].user_data;
if (is_using_user_data == false)
(*iter.cbs.generic[i].cb.modunload_cb.cb_no_user_data)(drcontext, info);
else {
(*iter.cbs.generic[i].cb.modunload_cb.cb_user_data)(drcontext, info,
user_data);
}
}
cblist_delete_local(drcontext, &iter, BUFFER_SIZE_ELEMENTS(local));
}
Expand Down
49 changes: 49 additions & 0 deletions ext/drmgr/drmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,19 @@ drmgr_register_module_load_event_ex(void (*func)
bool loaded),
drmgr_priority_t *priority);

DR_EXPORT
/**
* Registers a callback function for the module load event, which
* behaves just like DR's module load event dr_register_module_load_event().
* Allows for the passing of user input \p user_data, which is available upon
* the execution of the callback. \return whether successful.
*/
bool
drmgr_register_module_load_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
bool loaded, void *user_data),
drmgr_priority_t *priority, void *user_data);

DR_EXPORT
/**
* Unregister a callback function for the module load event.
Expand All @@ -937,6 +950,17 @@ drmgr_unregister_module_load_event(void (*func)
(void *drcontext, const module_data_t *info,
bool loaded));

DR_EXPORT
/**
* Unregister a callback function, which takes user data as a parameter
* for the module load event. \return true if unregistration is successful
* and false if it is not (e.g., \p func was not registered).
*/
bool
drmgr_unregister_module_load_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
bool loaded, void *user_data));

DR_EXPORT
/**
* Registers a callback function for the module unload event, which
Expand All @@ -963,6 +987,19 @@ drmgr_register_module_unload_event_ex(void (*func)
drmgr_priority_t *priority);

DR_EXPORT
/**
* Registers a callback function for the module unload event, which
* behaves just like DR's module unload event dr_register_module_unload_event().
* Allows for the passing of user data, \p user_data, which is available upon the
* execution of the callback. \return whether successful.
*/
bool
drmgr_register_module_unload_event_user_data(void (*func)
(void *drcontext, const module_data_t *info,
void *user_data),
drmgr_priority_t *priority,
void *user_data);
DR_EXPORT
/**
* Unregister a callback function for the module unload event.
* \return true if unregistration is successful and false if it is not
Expand All @@ -972,6 +1009,18 @@ bool
drmgr_unregister_module_unload_event(void (*func)
(void *drcontext, const module_data_t *info));

DR_EXPORT
/**
* Unregister a callback function, that takes user data as a parameter,
* for the module unload event. \return true if unregistration is
* successful and false if it is not (e.g., \p func was not registered).
*/
bool
drmgr_unregister_module_unload_event_user_data(void (*func)
(void *drcontext,
const module_data_t *info,
void *user_data));

DR_EXPORT
/**
* Registers a callback function for the kernel transfer event, which
Expand Down
2 changes: 1 addition & 1 deletion suite/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2037,7 +2037,7 @@ if (CLIENT_INTERFACE)
tobuild_ci(client.drcontainers-test client-interface/drcontainers-test.c "" "" "")
use_DynamoRIO_extension(client.drcontainers-test.dll drcontainers)

tobuild_ci(client.drmgr-test client-interface/drmgr-test.c "" "" "")
tobuild_ci(client.drmgr-test client-interface/drmgr-test.c "" "" "${events_appdll_path}")
use_DynamoRIO_extension(client.drmgr-test.dll drmgr)
if (UNIX AND NOT ANDROID) # pthreads is inside Bionic on Android
target_link_libraries(client.drmgr-test ${libpthread})
Expand Down
18 changes: 17 additions & 1 deletion suite/tests/client-interface/drmgr-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ run_func(void * arg)
}

int
main()
main(int argc, char **argv)
{
int tid;
HANDLE hThread;
Expand Down Expand Up @@ -232,6 +232,14 @@ main()
WaitForSingleObject(hThread, INFINITE);
print("All done\n");

HMODULE hmod;

/*
* Load and unload a module to cause a module unload event
*/
hmod = LoadLibrary(argv[1]);
FreeLibrary(hmod);

return 0;
}

Expand All @@ -243,6 +251,7 @@ main()
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
# include <dlfcn.h>

volatile double pi = 0.0; /* Approximation to pi (shared) */
pthread_mutex_t pi_lock; /* Lock for above */
Expand Down Expand Up @@ -320,6 +329,13 @@ main(int argc, char **argv)
exit(1);
}

void *hmod;
hmod = dlopen(argv[1], RTLD_LAZY|RTLD_LOCAL);
if (hmod != NULL)
dlclose(hmod);
else
print("module load failed: %s\n", dlerror());

/* Print the result */
print("Estimation of pi is %16.15f\n", pi);
return 0;
Expand Down
Loading

0 comments on commit 13e4f95

Please sign in to comment.