diff --git a/api/docs/release.dox b/api/docs/release.dox index 00c58fdd242629c4cae7f8de6ba36e063dc28255..1741b3a528d96c99d6b219ed9523304de9f005db 100644 --- a/api/docs/release.dox +++ b/api/docs/release.dox @@ -141,6 +141,10 @@ changes: member fields of classes are now following a consistent style with an underscore suffix. References to renamed fields will need to be updated. + - A change in the load callbacks used with drmodtrack_add_custom_data() + and drmemtrace_custom_module_data(): they each take an additional parameter, the + segment index. The custom data field is now per-segment and not per-module, + and all callbacks are invoked separately for each segment. The changes between version \DR_VERSION and 8.0.0 include the following minor compatibility changes: diff --git a/clients/drcachesim/tests/burst_replace.cpp b/clients/drcachesim/tests/burst_replace.cpp index a47cae88d3a087317b6f063f11241cf3fad3d048..cba8977a0c68334ee2377354a3e126b2ebe80f53 100644 --- a/clients/drcachesim/tests/burst_replace.cpp +++ b/clients/drcachesim/tests/burst_replace.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2016-2020 Google, Inc. All rights reserved. + * Copyright (c) 2016-2021 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -139,8 +139,12 @@ local_create_dir(const char *dir) } static void * -load_cb(module_data_t *module) +load_cb(module_data_t *module, int seg_idx) { +#ifndef WINDOWS + if (seg_idx > 0) + return (void *)module->segments[seg_idx].start; +#endif return (void *)module->start; } @@ -163,7 +167,7 @@ parse_cb(const char *src, OUT void **data) static std::string process_cb(drmodtrack_info_t *info, void *data, void *user_data) { - assert((app_pc)data == info->start || info->containing_index != info->index); + assert((app_pc)data == info->start); assert(user_data == MAGIC_VALUE); return ""; } diff --git a/clients/drcachesim/tracer/drmemtrace.h b/clients/drcachesim/tracer/drmemtrace.h index 0ecb12e33c729817cfb93bfa16917934b4534f9c..bcb9bfbff8fa7aafc73df7519478fdeaf6717605 100644 --- a/clients/drcachesim/tracer/drmemtrace.h +++ b/clients/drcachesim/tracer/drmemtrace.h @@ -249,17 +249,19 @@ drmemtrace_get_funclist_path(OUT const char **path); DR_EXPORT /** * Adds custom data stored with each module in the module list produced for - * offline trace post-processing. The \p load_cb is called for each new module, + * offline trace post-processing. The \p load_cb is called for each segment + * of each new module (with \p seg_idx indicating the segment number, starting at 0), * and its return value is the data that is stored. That data is later printed * to a string with \p print_cb, which should return the number of characters - * printed or -1 on error. The data is freed with \p free_cb. + * printed or -1 on error. The data is freed with \p free_cb. Each is called + * separately for each segment of each module. * * On the post-processing side, the user should create a custom post-processor * by linking with raw2trace and calling raw2trace_t::handle_custom_data() to provide * parsing and processing routines for the custom data. */ drmemtrace_status_t -drmemtrace_custom_module_data(void *(*load_cb)(module_data_t *module), +drmemtrace_custom_module_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), void (*free_cb)(void *data)); diff --git a/clients/drcachesim/tracer/instru.h b/clients/drcachesim/tracer/instru.h index 78bc7cbe4b704a7af196bbb9d43b42e69d5b717e..4e26a34a59153b4b6bdfad0904eba4e1d974c8f5 100644 --- a/clients/drcachesim/tracer/instru.h +++ b/clients/drcachesim/tracer/instru.h @@ -399,7 +399,7 @@ public: bool repstr_expanded) override; static bool - custom_module_data(void *(*load_cb)(module_data_t *module), + custom_module_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), void (*free_cb)(void *data)); @@ -460,11 +460,11 @@ private: // Custom module fields are global (since drmodtrack's support is global, we don't // try to pass void* user data params through). - static void *(*user_load_)(module_data_t *module); + static void *(*user_load_)(module_data_t *module, int seg_idx); static int (*user_print_)(void *data, char *dst, size_t max_len); static void (*user_free_)(void *data); static void * - load_custom_module_data(module_data_t *module); + load_custom_module_data(module_data_t *module, int seg_idx); static int print_custom_module_data(void *data, char *dst, size_t max_len); static void diff --git a/clients/drcachesim/tracer/instru_offline.cpp b/clients/drcachesim/tracer/instru_offline.cpp index bc92db6ca6f87236d56edf346787bef6ed97b282..7c0dfe8d2c9b55cd55e51f2f167d1ae51ac2bc6f 100644 --- a/clients/drcachesim/tracer/instru_offline.cpp +++ b/clients/drcachesim/tracer/instru_offline.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2016-2020 Google, Inc. All rights reserved. + * Copyright (c) 2016-2021 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -47,7 +47,7 @@ static const ptr_uint_t MAX_INSTR_COUNT = 64 * 1024; -void *(*offline_instru_t::user_load_)(module_data_t *module); +void *(*offline_instru_t::user_load_)(module_data_t *module, int seg_idx); int (*offline_instru_t::user_print_)(void *data, char *dst, size_t max_len); void (*offline_instru_t::user_free_)(void *data); @@ -115,11 +115,11 @@ offline_instru_t::~offline_instru_t() } void * -offline_instru_t::load_custom_module_data(module_data_t *module) +offline_instru_t::load_custom_module_data(module_data_t *module, int seg_idx) { void *user_data = nullptr; if (user_load_ != nullptr) - user_data = (*user_load_)(module); + user_data = (*user_load_)(module, seg_idx); const char *name = dr_module_preferred_name(module); // For vdso we include the entire contents so we can decode it during // post-processing. @@ -129,8 +129,17 @@ offline_instru_t::load_custom_module_data(module_data_t *module) strstr(name, "linux-vdso.so") == name)) || (module->names.file_name != NULL && strcmp(name, "[vdso]") == 0)) { void *alloc = dr_global_alloc(sizeof(custom_module_data_t)); - return new (alloc) custom_module_data_t((const char *)module->start, - module->end - module->start, user_data); +#ifdef WINDOWS + byte *start = module->start; + byte *end = module->end; +#else + byte *start = + (module->num_segments > 0) ? module->segments[seg_idx].start : module->start; + byte *end = + (module->num_segments > 0) ? module->segments[seg_idx].end : module->end; +#endif + return new (alloc) + custom_module_data_t((const char *)start, end - start, user_data); } else if (user_data != nullptr) { void *alloc = dr_global_alloc(sizeof(custom_module_data_t)); return new (alloc) custom_module_data_t(nullptr, 0, user_data); @@ -190,7 +199,7 @@ offline_instru_t::free_custom_module_data(void *data) } bool -offline_instru_t::custom_module_data(void *(*load_cb)(module_data_t *module), +offline_instru_t::custom_module_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), void (*free_cb)(void *data)) diff --git a/clients/drcachesim/tracer/tracer.cpp b/clients/drcachesim/tracer/tracer.cpp index b409dcf4f2e68a66dbb054a673b5a8954967366b..ef49eeac9b0ed2459da45a8c94895e0874311454 100644 --- a/clients/drcachesim/tracer/tracer.cpp +++ b/clients/drcachesim/tracer/tracer.cpp @@ -1,5 +1,5 @@ /* ****************************************************************************** - * Copyright (c) 2011-2020 Google, Inc. All rights reserved. + * Copyright (c) 2011-2021 Google, Inc. All rights reserved. * Copyright (c) 2010 Massachusetts Institute of Technology All rights reserved. * ******************************************************************************/ @@ -282,7 +282,7 @@ drmemtrace_get_funclist_path(OUT const char **path) } drmemtrace_status_t -drmemtrace_custom_module_data(void *(*load_cb)(module_data_t *module), +drmemtrace_custom_module_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), void (*free_cb)(void *data)) { diff --git a/ext/drcovlib/drcovlib.h b/ext/drcovlib/drcovlib.h index 37725c3ee4667a6956e2d6868778281a140f44ce..6cebe74ff1919ab5e94fd9a2cdb833633590b78a 100644 --- a/ext/drcovlib/drcovlib.h +++ b/ext/drcovlib/drcovlib.h @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2016-2017 Google, Inc. All rights reserved. + * Copyright (c) 2016-2021 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -378,15 +378,16 @@ DR_EXPORT * and writes the parsed data to its output parameter, which can subsequently be * retrieved from drmodtrack_offline_lookup()'s \p custom output parameter. * - * If a module contains non-contiguous segments, \p load_cb is called - * only once, and the resulting custom field is shared among all - * separate entries returned by drmodtrack_offline_lookup(). + * If a module contains multiple segments, \p load_cb is called + * multiple times, once for each segment, with \p seg_idx indicating the segment. + * Each segment stores its own custom field, and each callback is invoked separately + * for each segment. * * Only one value for each callback is supported. Calling this routine again * with a different value will replace the existing callbacks. */ drcovlib_status_t -drmodtrack_add_custom_data(void *(*load_cb)(module_data_t *module), +drmodtrack_add_custom_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), const char *(*parse_cb)(const char *src, OUT void **data), void (*free_cb)(void *data)); diff --git a/ext/drcovlib/modules.c b/ext/drcovlib/modules.c index 286277ae639a7ed5b5df2625e38cb540177aae7b..5facc34a2285ae4150702e9a72ddb9cfb6129adb 100644 --- a/ext/drcovlib/modules.c +++ b/ext/drcovlib/modules.c @@ -80,7 +80,7 @@ static int tls_idx = -1; static module_table_t module_table; /* Custom per-module field support. */ -static void *(*module_load_cb)(module_data_t *module); +static void *(*module_load_cb)(module_data_t *module, int seg_idx); static int (*module_print_cb)(void *data, char *dst, size_t max_len); static const char *(*module_parse_cb)(const char *src, OUT void **data); static void (*module_free_cb)(void *data); @@ -117,11 +117,10 @@ static void module_table_entry_free(void *tofree) { module_entry_t *entry = (module_entry_t *)tofree; - if (entry->id == entry->containing_id) { - if (module_free_cb != NULL) - module_free_cb(((module_entry_t *)entry)->custom); + if (module_free_cb != NULL) + module_free_cb(((module_entry_t *)entry)->custom); + if (entry->id == entry->containing_id) /* Else a sub-entry which shares data. */ dr_free_module_data(((module_entry_t *)entry)->data); - } /* else a sub-entry which shares custom and data */ dr_global_free(entry, sizeof(module_entry_t)); } @@ -190,7 +189,7 @@ event_module_load(void *drcontext, const module_data_t *data, bool loaded) entry->unload = false; entry->data = dr_copy_module_data(data); if (module_load_cb != NULL) - entry->custom = module_load_cb(entry->data); + entry->custom = module_load_cb(entry->data, 0); drvector_append(&module_table.vector, entry); #ifndef WINDOWS entry->offset = data->segments[0].offset; @@ -208,9 +207,9 @@ event_module_load(void *drcontext, const module_data_t *data, bool loaded) sub_entry->start = data->segments[j].start; sub_entry->end = data->segments[j].end; sub_entry->unload = false; - /* These fields are shared. */ - sub_entry->data = entry->data; - sub_entry->custom = entry->custom; + sub_entry->data = entry->data; /* Shared among all segments. */ + if (module_load_cb != NULL) + sub_entry->custom = module_load_cb(sub_entry->data, j); sub_entry->offset = data->segments[j].offset; drvector_append(&module_table.vector, sub_entry); global_module_cache_add(module_table.cache, sub_entry); @@ -792,7 +791,7 @@ drmodtrack_offline_exit(void *handle) } drcovlib_status_t -drmodtrack_add_custom_data(void *(*load_cb)(module_data_t *module), +drmodtrack_add_custom_data(void *(*load_cb)(module_data_t *module, int seg_idx), int (*print_cb)(void *data, char *dst, size_t max_len), const char *(*parse_cb)(const char *src, OUT void **data), void (*free_cb)(void *data)) diff --git a/suite/tests/client-interface/drmodtrack-test.dll.cpp b/suite/tests/client-interface/drmodtrack-test.dll.cpp index 7f41686ce0a3a223148923173a1c66b44c64cc5d..0815620ef856671fb683eba0f513f837db9f7ad7 100644 --- a/suite/tests/client-interface/drmodtrack-test.dll.cpp +++ b/suite/tests/client-interface/drmodtrack-test.dll.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2017-2019 Google, Inc. All rights reserved. + * Copyright (c) 2017-2021 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -55,8 +55,12 @@ static client_id_t client_id; static void * -load_cb(module_data_t *module) +load_cb(module_data_t *module, int seg_idx) { +#ifndef WINDOWS + if (seg_idx > 0) + return (void *)module->segments[seg_idx].start; +#endif return (void *)module->start; } @@ -189,8 +193,7 @@ event_exit(void) }; res = drmodtrack_offline_lookup(modhandle, i, &info); CHECK(res == DRCOVLIB_SUCCESS, "lookup failed"); - CHECK(((app_pc)info.custom) == info.start || info.containing_index != i, - "custom field doesn't match"); + CHECK(((app_pc)info.custom) == info.start, "custom field doesn't match"); CHECK(info.index == i, "index field doesn't match"); #ifndef WINDOWS if (info.struct_size > offsetof(drmodtrack_info_t, offset)) {