From 2d9004e496767ba23de67183055b3f0c985853da Mon Sep 17 00:00:00 2001 From: Derek Bruening Date: Tue, 7 Jul 2020 08:33:01 -0400 Subject: [PATCH] i#4318 xarch memtrace: Make alt lib dir take precedence (#4360) Moves the -alt_module_dir for finding binaries during trace post-processing to take precedence over the recorded path, to allow avoiding problems when an identical-seeming path exists on the processing machine (e.g., system libraries) on UNIX where we have no checksum or other library distinguisher. Tested manually on a case where a system library in the same path as on the recorded machine caused failure. Issue: #4318 --- clients/drcachesim/common/options.cpp | 2 +- .../drcachesim/tools/opcode_mix_launcher.cpp | 3 +- clients/drcachesim/tracer/raw2trace.cpp | 28 +++++++++++++++---- .../drcachesim/tracer/raw2trace_launcher.cpp | 2 +- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/clients/drcachesim/common/options.cpp b/clients/drcachesim/common/options.cpp index e98349d0a05..64c5c2d02ad 100644 --- a/clients/drcachesim/common/options.cpp +++ b/clients/drcachesim/common/options.cpp @@ -98,7 +98,7 @@ droption_t op_alt_module_dir( DROPTION_SCOPE_FRONTEND, "alt_module_dir", "", "Alternate module search directory", "Specifies a directory containing libraries referenced in -module_file for " "analysis tools, or in the raw modules file for post-prcoessing of offline " - "raw trace files."); + "raw trace files. This directory takes precedence over the recorded path."); droption_t op_funclist_file( DROPTION_SCOPE_ALL, "funclist_file", "", diff --git a/clients/drcachesim/tools/opcode_mix_launcher.cpp b/clients/drcachesim/tools/opcode_mix_launcher.cpp index 40d5a36d876..79e3c123273 100644 --- a/clients/drcachesim/tools/opcode_mix_launcher.cpp +++ b/clients/drcachesim/tools/opcode_mix_launcher.cpp @@ -64,7 +64,8 @@ static droption_t op_module_file( static droption_t op_alt_module_dir( DROPTION_SCOPE_FRONTEND, "alt_module_dir", "", "Alternate module search directory", - "Specifies a directory containing libraries referenced in -module_file."); + "Specifies a directory containing libraries referenced in -module_file. " + "This directory takes precedence over the recorded path."); droption_t op_verbose(DROPTION_SCOPE_ALL, "verbose", 0, 0, 64, "Verbosity level", diff --git a/clients/drcachesim/tracer/raw2trace.cpp b/clients/drcachesim/tracer/raw2trace.cpp index ddc99c6095a..0c04df0f9f1 100644 --- a/clients/drcachesim/tracer/raw2trace.cpp +++ b/clients/drcachesim/tracer/raw2trace.cpp @@ -311,6 +311,14 @@ raw2trace_t::read_and_map_modules() return module_mapper_->get_last_error(); } +// Maps each module into the address space. +// There are several types of mapping entries in the module list: +// 1) Raw bits directly stored. It is simply pointed at. +// 2) Extra segments for a module. A single mapping is used for all +// segments, so extras are ignored. +// 3) A main segment. The module's file is located by first looking in +// the alt_module_dir_; if not found, the path present during tracing +// is searched. void module_mapper_t::read_and_map_modules() { @@ -345,19 +353,29 @@ module_mapper_t::read_and_map_modules() // 0 size indicates this is a secondary segment. modvec_[info.containing_index].map_base, 0)); } else { - size_t map_size; - byte *base_pc = - dr_map_executable_file(info.path, DR_MAPEXE_SKIP_WRITABLE, &map_size); - if (base_pc == NULL && !alt_module_dir_.empty()) { + size_t map_size = 0; + byte *base_pc = NULL; + if (!alt_module_dir_.empty()) { + // First try the specified module dir. It takes precedence to allow + // overriding the recorded path even when an identical-seeming path + // exists on the processing machine (e.g., system libraries). + // XXX: We should add a checksum on UNIX to match Windows and have + // a sanity check on the library version. std::string basename(info.path); size_t sep_index = basename.find_last_of(DIRSEP ALT_DIRSEP); if (sep_index != std::string::npos) basename = std::string(basename, sep_index + 1, std::string::npos); std::string new_path = alt_module_dir_ + DIRSEP + basename; - VPRINT(1, "Failed to find %s; trying %s\n", info.path, new_path.c_str()); + VPRINT(2, "Trying to map %s\n", new_path.c_str()); base_pc = dr_map_executable_file(new_path.c_str(), DR_MAPEXE_SKIP_WRITABLE, &map_size); } + if (base_pc == NULL) { + // Try the recorded path. + VPRINT(2, "Trying to map %s\n", info.path); + base_pc = + dr_map_executable_file(info.path, DR_MAPEXE_SKIP_WRITABLE, &map_size); + } if (base_pc == NULL) { // We expect to fail to map dynamorio.dll for x64 Windows as it // is built /fixed. (We could try to have the map succeed w/o relocs, diff --git a/clients/drcachesim/tracer/raw2trace_launcher.cpp b/clients/drcachesim/tracer/raw2trace_launcher.cpp index cd25c19b2c9..50f5ff3f487 100644 --- a/clients/drcachesim/tracer/raw2trace_launcher.cpp +++ b/clients/drcachesim/tracer/raw2trace_launcher.cpp @@ -57,7 +57,7 @@ static droption_t static droption_t op_alt_module_dir( DROPTION_SCOPE_FRONTEND, "alt_module_dir", "", "Alternate module search directory", "Specifies a directory to look for binaries needed to post-process " - "the trace that are not found in the path recorded during tracing."); + "the trace. This directory takes precedence over the recorded path."); static droption_t op_verbose(DROPTION_SCOPE_FRONTEND, "verbose", 0, "Verbosity level for diagnostic output",