From 71c0a87ab5735df1dc2688afd583b8fcc3dfa0dc Mon Sep 17 00:00:00 2001 From: Jacob Salzberg Date: Tue, 1 Sep 2020 16:31:57 -0400 Subject: [PATCH 1/3] Add instr analysis tool. --- .../drcctlib_instr_analysis/CMakeLists.txt | 71 +++++ .../drcctlib_instr_analysis.cpp | 286 ++++++++++++++++++ 2 files changed, 357 insertions(+) create mode 100644 src/clients/drcctlib_instr_analysis/CMakeLists.txt create mode 100644 src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp diff --git a/src/clients/drcctlib_instr_analysis/CMakeLists.txt b/src/clients/drcctlib_instr_analysis/CMakeLists.txt new file mode 100644 index 0000000..677218f --- /dev/null +++ b/src/clients/drcctlib_instr_analysis/CMakeLists.txt @@ -0,0 +1,71 @@ +# Forked from the CMakeLists.txt +# In drcctlib_instr_statistics +cmake_minimum_required(VERSION 2.6) + +include(../../make/policies.cmake NO_POLICY_SCOPE) + +if (UNIX) + add_compile_options(-Wno-deprecated) + add_compile_options(-Wno-unused-result) + add_compile_options(-Wno-unused-variable) + add_compile_options(-Wno-unused-local-typedefs) + add_compile_options(-Wno-unused-function) + add_compile_options(-Werror=sign-compare) + add_compile_options(-Werror=narrowing) + add_compile_options(-std=c++11) + + if (DEBUG) + add_compile_options(-g3) + endif (DEBUG) +endif (UNIX) + +# add third-party libraries + +add_library(drcctlib_instr_analysis SHARED +drcctlib_instr_analysis.cpp + ) + +configure_DynamoRIO_client(drcctlib_instr_analysis) +use_DynamoRIO_extension(drcctlib_instr_analysis drcctlib) +place_shared_lib_in_lib_dir(drcctlib_instr_analysis) + +add_dependencies(drcctlib_instr_analysis api_headers) + +# Provide a hint for how to use the client +if (NOT DynamoRIO_INTERNAL OR NOT "${CMAKE_GENERATOR}" MATCHES "Ninja") + add_custom_command(TARGET drcctlib_instr_analysis + POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS -E echo "Usage: pass to drconfig or drrun: -t drcctlib_instr_analysis" + VERBATIM) +endif () + +install_target(drcctlib_instr_analysis ${INSTALL_CLIENTS_LIB}) + +set(INSTALL_CCTTEST_CONFIG ${INSTALL_CLIENTS_BASE}) + +function (write_config_file dst bindir libdir) + file(WRITE ${dst} "# drcctlib_instr_analysis tool config file\n") + file(APPEND ${dst} "CLIENT_REL=${libdir}/${LIB_PFX}drcctlib_instr_analysis${LIB_EXT}\n") +endfunction () + +if (X64) + set(CONFIG_INSTALL ${PROJECT_BINARY_DIR}/drcctlib_instr_analysis.drrun64) + set(CONFIG_BUILD ${PROJECT_BINARY_DIR}/tools/drcctlib_instr_analysis.drrun64) +else (X64) + set(CONFIG_INSTALL ${PROJECT_BINARY_DIR}/drcctlib_instr_analysis.drrun32) + set(CONFIG_BUILD ${PROJECT_BINARY_DIR}/tools/drcctlib_instr_analysis.drrun32) +endif (X64) + +set(BUILD_CLIENTS_BIN clients/${INSTALL_BIN}) +set(BUILD_CLIENTS_LIB clients/${INSTALL_LIB}) + +write_config_file(${CONFIG_INSTALL} ${INSTALL_CLIENTS_BIN} ${INSTALL_CLIENTS_LIB}) +write_config_file(${CONFIG_BUILD} ${BUILD_CLIENTS_BIN} ${BUILD_CLIENTS_LIB}) + +DR_install(FILES "${CONFIG_INSTALL}" DESTINATION ${INSTALL_CCTTEST_CONFIG}) +register_tool_file("drcctlib_instr_analysis") + +################################################## +# Documentation + diff --git a/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp new file mode 100644 index 0000000..cbf1454 --- /dev/null +++ b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp @@ -0,0 +1,286 @@ +/** + * @file drcctlib_instr_analysis.cpp + * @author Jacob Salzberg (jssalzbe@ncsu.edu) + * DrCCTProf instruction analysis client. + * Analyzes every instruction, + * grouping them into five groups: + * memory load, memory store, conditional branch, + * unconditional branch, and other. + * Prints the statistics per context to a file. + * Forked from drcctlib_instr_statistics.cpp + */ +// TODO fix count ,it is bugged + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "dr_api.h" +#include "dr_ir_instr.h" +#include "dr_ir_instrlist.h" +#include "dr_ir_utils.h" +#include "drcctlib.h" + +using namespace std; + +#define DRCCTLIB_PRINTF(format, args...) \ + DRCCTLIB_PRINTF_TEMPLATE("instr_statistics", format, ##args) +#define DRCCTLIB_EXIT_PROCESS(format, args...) \ + DRCCTLIB_CLIENT_EXIT_PROCESS_TEMPLATE("instr_statistics", format, ##args) + +#define MAX_CLIENT_CCT_PRINT_DEPTH 10 +#define TOP_REACH_NUM_SHOW 200 + +/** + * The log file. + */ +static file_t gTraceFile; + +/** + * Map from the context handle to the time it first appears + */ +static map *calling_contexts; + +/** + * Map from the context handle to the number of times it is called + */ +static map *calling_contexts_called; + +/** + * Counters for the number of memory loads, + * indexed by calling context index + */ +static vector *memloads; + +/** + * Counters for the number of memory stores, + * indexed by calling context index + */ +static vector *memstores; + +/** + * Counters for the number of conditional branches, + * indexed by calling context index + */ +static vector *branches; + +/** + * Counters for the number of unconditional branches, + * indexed by calling context index + */ +static vector *jumps; + +/** + * Counters for the number of "other" instructions + * that do not fit the above categories + * indexed by calling context index + */ +static vector *others; + +/** + * For every basic block + * Iterate over the instruction list and count the + * number of branches, memory stores, memory loads, + * unconditional jumps + * and other instructions. + * @param drcontext the dynamorio context + * @param ctxt_hndl the context handle + * @param slot_num number of instructions (unused) + * @param mem_ref_num number of memory references (unused) + * @param mem_ref_start where the memory references start (unused) + * @param data additional data passed to this function (unused) + */ +static inline void InstrumentPerBBCache(void *drcontext, + context_handle_t ctxt_hndl, + int32_t slot_num, int32_t mem_ref_num, + mem_ref_msg_t *mem_ref_start, + void **data) +{ + int index; + if (calling_contexts->find(ctxt_hndl) == calling_contexts->end()) { + (*calling_contexts)[ctxt_hndl] = calling_contexts->size(); + memloads->push_back(0); + memstores->push_back(0); + branches->push_back(0); + jumps->push_back(0); + others->push_back(0); + } + index = (*calling_contexts)[ctxt_hndl]; + + if (calling_contexts_called->find(ctxt_hndl) == + calling_contexts_called->end()) { + (*calling_contexts_called)[ctxt_hndl] = 0; + } + (*calling_contexts_called)[ctxt_hndl] += 1; + + context_t *ctxt = drcctlib_get_full_cct(ctxt_hndl, 1); + byte *ip = ctxt->ip; + int memload_count = 0; + int memstore_count = 0; + int branch_count = 0; + int jump_count = 0; + int other_count = 0; + if (ip) { + instrlist_t *bb = decode_as_bb(drcontext, ip); + instr_t *next; + for (instr_t *instr = instrlist_first_app(bb); + instr != instrlist_last_app(bb) && instr != NULL; instr = next) { + if (instr_is_cbr(instr)) { + branch_count += 1; + } else if (instr_writes_memory(instr)) { + memstore_count += 1; + } else if (instr_reads_memory(instr)) { + memload_count += 1; + } else { + other_count += 1; + } + next = instr_get_next_app(instr); + } + + // Only check the last application for unconditional jumps. + // This is because unconditional jumps end a branch + if (instr_is_ubr(instrlist_last_app(bb))) { + jump_count += 1; + } + if (instr_is_cbr(instrlist_last_app(bb))) { + branch_count += 1; + } + instrlist_clear_and_destroy(drcontext, bb); + } + + memloads->at(index) = memload_count; + memstores->at(index) = memstore_count; + branches->at(index) = branch_count; + jumps->at(index) = jump_count; + others->at(index) = other_count; +} + +/** + * Initialize the tool. + * @param argc The tool's argc + * @param argv The tool's argv + */ +static void ClientInit(int argc, const char *argv[]) +{ +#ifdef ARM_CCTLIB + char name[MAXIMUM_PATH] = "arm.drcctlib_instr_statistics.out."; +#else + char name[MAXIMUM_PATH] = "x86.drcctlib_instr_statistics.out."; +#endif + char *envPath = getenv("DR_CCTLIB_CLIENT_OUTPUT_FILE"); + + if (envPath) { + // assumes max of MAXIMUM_PATH + strcpy(name, envPath); + } + + gethostname(name + strlen(name), MAXIMUM_PATH - strlen(name)); + pid_t pid = getpid(); + sprintf(name + strlen(name), "%d", pid); + cerr << "Creating log file at:" << name << endl; + + gTraceFile = + dr_open_file(name, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); + + DR_ASSERT(gTraceFile != INVALID_FILE); + // print the arguments passed + dr_fprintf(gTraceFile, "\n"); + + for (int i = 0; i < argc; i++) { + dr_fprintf(gTraceFile, "%d %s ", i, argv[i]); + } + + dr_fprintf(gTraceFile, "\n"); + + calling_contexts = new map; + calling_contexts_called = new map; + memloads = new vector; + memstores = new vector; + branches = new vector; + jumps = new vector; + others = new vector; +} + +/** + * Record the statistics to a file + */ +static void ClientExit(void) +{ + for (std::pair element : (*calling_contexts)) { + int i = element.second; + context_handle_t cct_hndl = element.first; + int no = i + 1; + int memload_count = memloads->at(i); + int memstore_count = memstores->at(i); + int branch_count = branches->at(i); + int jump_count = jumps->at(i); + int other_count = others->at(i); + int times_called = (*calling_contexts_called)[cct_hndl]; + dr_fprintf(gTraceFile, + "NO. %d" + " loads (%02d)," + " store (%02d)," + " conditional branch (%02d)," + " unconditional branch (%02d)" + " other: (%02d)" + " ins call number %d" + " context handle %d" + "====", + no, memload_count, memstore_count, branch_count, jump_count, + other_count, times_called, cct_hndl); + drcctlib_print_ctxt_hndl_msg(gTraceFile, cct_hndl, false, false); + dr_fprintf(gTraceFile, "===============================================" + "======================" + "===========\n"); + drcctlib_print_full_cct(gTraceFile, cct_hndl, true, false, + MAX_CLIENT_CCT_PRINT_DEPTH); + dr_fprintf(gTraceFile, "===============================================" + "======================" + "===========\n\n\n"); + } + + drcctlib_exit(); + + dr_close_file(gTraceFile); + delete calling_contexts; + delete calling_contexts_called; + delete memloads; + delete memstores; + delete branches; + delete jumps; + delete others; +} + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Main entry point for tool + * @param id the client id: + * @param argc the argument count + * @param argv the argument list + */ +DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) +{ + dr_set_client_name("DynamoRIO Client 'drcctlib_instr_analysis'", + "http://dynamorio.org/issues"); + + ClientInit(argc, argv); + + drcctlib_init_ex(DRCCTLIB_FILTER_ALL_INSTR, INVALID_FILE, NULL, NULL, + InstrumentPerBBCache, DRCCTLIB_CACHE_MODE); + dr_register_exit_event(ClientExit); +} + +#ifdef __cplusplus +} +#endif From 165884a1f132011d3ad33b0987acf1ec339aa42e Mon Sep 17 00:00:00 2001 From: Jacob Salzberg Date: Tue, 1 Sep 2020 16:35:27 -0400 Subject: [PATCH 2/3] Remove TODO that has already been dealt with --- .../drcctlib_instr_analysis.cpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp index cbf1454..78a7135 100644 --- a/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp +++ b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp @@ -9,7 +9,6 @@ * Prints the statistics per context to a file. * Forked from drcctlib_instr_statistics.cpp */ -// TODO fix count ,it is bugged #include #include @@ -31,9 +30,9 @@ using namespace std; -#define DRCCTLIB_PRINTF(format, args...) \ +#define DRCCTLIB_PRINTF(format, args...) \ DRCCTLIB_PRINTF_TEMPLATE("instr_statistics", format, ##args) -#define DRCCTLIB_EXIT_PROCESS(format, args...) \ +#define DRCCTLIB_EXIT_PROCESS(format, args...) \ DRCCTLIB_CLIENT_EXIT_PROCESS_TEMPLATE("instr_statistics", format, ##args) #define MAX_CLIENT_CCT_PRINT_DEPTH 10 @@ -98,11 +97,9 @@ static vector *others; * @param mem_ref_start where the memory references start (unused) * @param data additional data passed to this function (unused) */ -static inline void InstrumentPerBBCache(void *drcontext, - context_handle_t ctxt_hndl, - int32_t slot_num, int32_t mem_ref_num, - mem_ref_msg_t *mem_ref_start, - void **data) +static inline void +InstrumentPerBBCache(void *drcontext, context_handle_t ctxt_hndl, int32_t slot_num, + int32_t mem_ref_num, mem_ref_msg_t *mem_ref_start, void **data) { int index; if (calling_contexts->find(ctxt_hndl) == calling_contexts->end()) { @@ -115,8 +112,7 @@ static inline void InstrumentPerBBCache(void *drcontext, } index = (*calling_contexts)[ctxt_hndl]; - if (calling_contexts_called->find(ctxt_hndl) == - calling_contexts_called->end()) { + if (calling_contexts_called->find(ctxt_hndl) == calling_contexts_called->end()) { (*calling_contexts_called)[ctxt_hndl] = 0; } (*calling_contexts_called)[ctxt_hndl] += 1; @@ -168,7 +164,8 @@ static inline void InstrumentPerBBCache(void *drcontext, * @param argc The tool's argc * @param argv The tool's argv */ -static void ClientInit(int argc, const char *argv[]) +static void +ClientInit(int argc, const char *argv[]) { #ifdef ARM_CCTLIB char name[MAXIMUM_PATH] = "arm.drcctlib_instr_statistics.out."; @@ -187,8 +184,7 @@ static void ClientInit(int argc, const char *argv[]) sprintf(name + strlen(name), "%d", pid); cerr << "Creating log file at:" << name << endl; - gTraceFile = - dr_open_file(name, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); + gTraceFile = dr_open_file(name, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); DR_ASSERT(gTraceFile != INVALID_FILE); // print the arguments passed @@ -212,7 +208,8 @@ static void ClientInit(int argc, const char *argv[]) /** * Record the statistics to a file */ -static void ClientExit(void) +static void +ClientExit(void) { for (std::pair element : (*calling_contexts)) { int i = element.second; @@ -237,14 +234,16 @@ static void ClientExit(void) no, memload_count, memstore_count, branch_count, jump_count, other_count, times_called, cct_hndl); drcctlib_print_ctxt_hndl_msg(gTraceFile, cct_hndl, false, false); - dr_fprintf(gTraceFile, "===============================================" - "======================" - "===========\n"); + dr_fprintf(gTraceFile, + "===============================================" + "======================" + "===========\n"); drcctlib_print_full_cct(gTraceFile, cct_hndl, true, false, MAX_CLIENT_CCT_PRINT_DEPTH); - dr_fprintf(gTraceFile, "===============================================" - "======================" - "===========\n\n\n"); + dr_fprintf(gTraceFile, + "===============================================" + "======================" + "===========\n\n\n"); } drcctlib_exit(); @@ -269,7 +268,8 @@ extern "C" { * @param argc the argument count * @param argv the argument list */ -DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) +DR_EXPORT void +dr_client_main(client_id_t id, int argc, const char *argv[]) { dr_set_client_name("DynamoRIO Client 'drcctlib_instr_analysis'", "http://dynamorio.org/issues"); From 3cd76daf4a61ce0afd3527fcdd7885021f408fc0 Mon Sep 17 00:00:00 2001 From: Jacob Salzberg Date: Sun, 6 Sep 2020 23:51:18 -0400 Subject: [PATCH 3/3] Move all globals to thread-local storage to prevent race conditions. Completes 1/2 of the issue https://github.com/jsalzbergedu/DrCCTProf/issues/1 , and moves closer to being acceptable for https://github.com/Xuhpclab/DrCCTProf/pull/33 . --- .../drcctlib_instr_analysis.cpp | 214 +++++++++++------- 1 file changed, 137 insertions(+), 77 deletions(-) diff --git a/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp index 78a7135..9b81a53 100644 --- a/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp +++ b/src/clients/drcctlib_instr_analysis/drcctlib_instr_analysis.cpp @@ -23,6 +23,7 @@ #include #include "dr_api.h" +#include "drmgr.h" #include "dr_ir_instr.h" #include "dr_ir_instrlist.h" #include "dr_ir_utils.h" @@ -39,50 +40,60 @@ using namespace std; #define TOP_REACH_NUM_SHOW 200 /** - * The log file. - */ -static file_t gTraceFile; - -/** - * Map from the context handle to the time it first appears - */ -static map *calling_contexts; - -/** - * Map from the context handle to the number of times it is called - */ -static map *calling_contexts_called; - -/** - * Counters for the number of memory loads, - * indexed by calling context index + * Thread local storage index */ -static vector *memloads; +static int tls_idx; /** - * Counters for the number of memory stores, - * indexed by calling context index - */ -static vector *memstores; - -/** - * Counters for the number of conditional branches, - * indexed by calling context index - */ -static vector *branches; - -/** - * Counters for the number of unconditional branches, - * indexed by calling context index + * The log file. */ -static vector *jumps; +static file_t gTraceFile; /** - * Counters for the number of "other" instructions - * that do not fit the above categories - * indexed by calling context index + * Per thread storage for counts of instruction kinds */ -static vector *others; +typedef struct _per_thread_t { + /** + * Map from the context handle to the time it first appears + */ + map *calling_contexts; + + /** + * Map from the context handle to the number of times it is called + */ + map *calling_contexts_called; + + /** + * Counters for the number of memory loads, + * indexed by calling context index + */ + vector *memloads; + + /** + * Counters for the number of memory stores, + * indexed by calling context index + */ + vector *memstores; + + /** + * Counters for the number of conditional branches, + * indexed by calling context index + */ + vector *branches; + + /** + * Counters for the number of unconditional branches, + * indexed by calling context index + */ + vector *jumps; + + /** + * Counters for the number of "other" instructions + * that do not fit the above categories + * indexed by calling context index + */ + vector *others; +} per_thread_t; /** * For every basic block @@ -101,21 +112,30 @@ static inline void InstrumentPerBBCache(void *drcontext, context_handle_t ctxt_hndl, int32_t slot_num, int32_t mem_ref_num, mem_ref_msg_t *mem_ref_start, void **data) { + per_thread_t *pt; + if (*data != NULL) { + pt = (per_thread_t *)*data; + } else { + pt = (per_thread_t *)drmgr_get_tls_field(drcontext, tls_idx); + *data = pt; + } + int index; - if (calling_contexts->find(ctxt_hndl) == calling_contexts->end()) { - (*calling_contexts)[ctxt_hndl] = calling_contexts->size(); - memloads->push_back(0); - memstores->push_back(0); - branches->push_back(0); - jumps->push_back(0); - others->push_back(0); + if (pt->calling_contexts->find(ctxt_hndl) == pt->calling_contexts->end()) { + (*(pt->calling_contexts))[ctxt_hndl] = pt->calling_contexts->size(); + pt->memloads->push_back(0); + pt->memstores->push_back(0); + pt->branches->push_back(0); + pt->jumps->push_back(0); + pt->others->push_back(0); } - index = (*calling_contexts)[ctxt_hndl]; + index = (*(pt->calling_contexts))[ctxt_hndl]; - if (calling_contexts_called->find(ctxt_hndl) == calling_contexts_called->end()) { - (*calling_contexts_called)[ctxt_hndl] = 0; + if (pt->calling_contexts_called->find(ctxt_hndl) == + pt->calling_contexts_called->end()) { + (*(pt->calling_contexts_called))[ctxt_hndl] = 0; } - (*calling_contexts_called)[ctxt_hndl] += 1; + (*(pt->calling_contexts_called))[ctxt_hndl] += 1; context_t *ctxt = drcctlib_get_full_cct(ctxt_hndl, 1); byte *ip = ctxt->ip; @@ -152,11 +172,11 @@ InstrumentPerBBCache(void *drcontext, context_handle_t ctxt_hndl, int32_t slot_n instrlist_clear_and_destroy(drcontext, bb); } - memloads->at(index) = memload_count; - memstores->at(index) = memstore_count; - branches->at(index) = branch_count; - jumps->at(index) = jump_count; - others->at(index) = other_count; + pt->memloads->at(index) = memload_count; + pt->memstores->at(index) = memstore_count; + pt->branches->at(index) = branch_count; + pt->jumps->at(index) = jump_count; + pt->others->at(index) = other_count; } /** @@ -195,14 +215,6 @@ ClientInit(int argc, const char *argv[]) } dr_fprintf(gTraceFile, "\n"); - - calling_contexts = new map; - calling_contexts_called = new map; - memloads = new vector; - memstores = new vector; - branches = new vector; - jumps = new vector; - others = new vector; } /** @@ -211,16 +223,27 @@ ClientInit(int argc, const char *argv[]) static void ClientExit(void) { - for (std::pair element : (*calling_contexts)) { + drcctlib_exit(); + dr_close_file(gTraceFile); +} + +/** + * Record the statistics to a file + */ +static void +ClientThreadEnd(void *drcontext) +{ + per_thread_t *pt = (per_thread_t *)drmgr_get_tls_field(drcontext, tls_idx); + for (std::pair element : *(pt->calling_contexts)) { int i = element.second; context_handle_t cct_hndl = element.first; int no = i + 1; - int memload_count = memloads->at(i); - int memstore_count = memstores->at(i); - int branch_count = branches->at(i); - int jump_count = jumps->at(i); - int other_count = others->at(i); - int times_called = (*calling_contexts_called)[cct_hndl]; + int memload_count = pt->memloads->at(i); + int memstore_count = pt->memstores->at(i); + int branch_count = pt->branches->at(i); + int jump_count = pt->jumps->at(i); + int other_count = pt->others->at(i); + int times_called = (*(pt->calling_contexts_called))[cct_hndl]; dr_fprintf(gTraceFile, "NO. %d" " loads (%02d)," @@ -246,16 +269,36 @@ ClientExit(void) "===========\n\n\n"); } - drcctlib_exit(); + delete pt->calling_contexts; + delete pt->calling_contexts_called; + delete pt->memloads; + delete pt->memstores; + delete pt->branches; + delete pt->jumps; + delete pt->others; - dr_close_file(gTraceFile); - delete calling_contexts; - delete calling_contexts_called; - delete memloads; - delete memstores; - delete branches; - delete jumps; - delete others; + dr_thread_free(drcontext, pt, sizeof(per_thread_t)); +} + +/** + * Initialize per thread storage + */ +static void +ClientThreadStart(void *drcontext) +{ + per_thread_t *pt = (per_thread_t *)dr_thread_alloc(drcontext, sizeof(per_thread_t)); + if (pt == NULL) { + DRCCTLIB_EXIT_PROCESS("pt == NULL"); + } + drmgr_set_tls_field(drcontext, tls_idx, (void *)pt); + + pt->calling_contexts = new map; + pt->calling_contexts_called = new map; + pt->memloads = new vector; + pt->memstores = new vector; + pt->branches = new vector; + pt->jumps = new vector; + pt->others = new vector; } #ifdef __cplusplus @@ -275,10 +318,27 @@ dr_client_main(client_id_t id, int argc, const char *argv[]) "http://dynamorio.org/issues"); ClientInit(argc, argv); + if (!drmgr_init()) { + DRCCTLIB_EXIT_PROCESS( + "ERROR: drcctlib_reuse_distance unable to initialize drmgr"); + } + drmgr_priority_t thread_init_pri = { sizeof(thread_init_pri), + "drcctlib_reuse-thread_init", NULL, NULL, + DRCCTLIB_THREAD_EVENT_PRI + 1 }; + drmgr_priority_t thread_exit_pri = { sizeof(thread_exit_pri), + "drcctlib_reuse-thread-exit", NULL, NULL, + DRCCTLIB_THREAD_EVENT_PRI + 1 }; + drmgr_register_thread_init_event_ex(ClientThreadStart, &thread_init_pri); + drmgr_register_thread_exit_event_ex(ClientThreadEnd, &thread_exit_pri); drcctlib_init_ex(DRCCTLIB_FILTER_ALL_INSTR, INVALID_FILE, NULL, NULL, InstrumentPerBBCache, DRCCTLIB_CACHE_MODE); dr_register_exit_event(ClientExit); + tls_idx = drmgr_register_tls_field(); + if (tls_idx == -1) { + DRCCTLIB_EXIT_PROCESS( + "ERROR: drcctlib_reuse_distance drmgr_register_tls_field fail"); + } } #ifdef __cplusplus