From 2e236fd3ee5002641a8c7e64eee156f06465d681 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Wed, 13 Oct 2021 10:43:33 -0400 Subject: [PATCH] Cache the dyninst of the binaries Reading and processing the binary with dyninst can take a lot of time (and space). Added caching to avoid repeated processing of the same binary. --- analysis.cxx | 47 +++++++++++++++++++++++++++++++++++++---------- analysis.h | 2 +- tapsets.cxx | 2 +- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/analysis.cxx b/analysis.cxx index f2099e325..d77cf1c35 100644 --- a/analysis.cxx +++ b/analysis.cxx @@ -22,27 +22,55 @@ using namespace ParseAPI; using namespace std; +// Data structures to cache dyninst parsing of binaries +class bin_info { +public: + bin_info(SymtabCodeSource *s=NULL, CodeObject *c=NULL): sts(s), co(c) {}; + ~bin_info(){}; + SymtabCodeSource *sts; + CodeObject *co; +}; +typedef map parsed_bin; +static parsed_bin cached_info; + class analysis { public: - analysis(char *name); + analysis(string name); SymtabCodeSource *sts; CodeObject *co; }; // Get the binary set up for anaysis -analysis::analysis(char *name) +analysis::analysis(string name) { - // Should see if binary already cached + char *name_str = strdup(name.c_str()); sts = NULL; co = NULL; - // If not seen before + // Use cached information if available + if (cached_info.find(name) != cached_info.end()) { + cout << "liveness analysis using cached info for " << name << endl; + sts = cached_info[name].sts; + co = cached_info[name].co; + goto cleanup; + } + + // Not not seen before // Create a new binary code object from the filename argument - sts = new SymtabCodeSource(name); - if(!sts) return; + sts = new SymtabCodeSource(name_str); + if(!sts) goto cleanup; co = new CodeObject(sts); - if(!co) return; + if(!co) goto cleanup; + + // Cache the info for future reference + { + bin_info entry(sts,co); + cached_info.insert(make_pair(name,entry)); + } + +cleanup: + free(name_str); } #if defined(__i386__) || defined(__x86_64__) @@ -187,13 +215,12 @@ static const MachRegister dyninst_register_32[] = { }; #endif -int liveness(const char *executable, +int liveness(string executable, Dwarf_Addr addr, location_context ctx) { // should cache the executable names like the other things - char *exe = strdup(executable); - analysis func_to_analyze(exe); + analysis func_to_analyze(executable); MachRegister r; // Determine whether 32-bit or 64-bit code as the register names are different in dyninst diff --git a/analysis.h b/analysis.h index 470bca57d..9b6d115e7 100644 --- a/analysis.h +++ b/analysis.h @@ -17,7 +17,7 @@ #ifdef HAVE_DYNINST -extern int liveness(const char *executable, +extern int liveness(std::string executable, Dwarf_Addr location, location_context ctx); diff --git a/tapsets.cxx b/tapsets.cxx index b8a8c8bc6..5a7ad3ebb 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4732,7 +4732,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) // Now that have location information check if change to variable has any effect if (lvalue) { - if (liveness(q.dw.mod_info->elf_path.c_str(), addr, ctx) < 0) { + if (liveness(q.dw.mod_info->elf_path, addr, ctx) < 0) { q.sess.print_warning(_F("write at %lx will have no effect", addr), e->tok); } -- 2.43.5