Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -770,6 +770,7 @@ ListOfModules() : modules_(kInitialCapacity) {} ~ListOfModules() { clear(); } void init(); + void fallbackInit(); const LoadedModule *begin() const { return modules_.begin(); } LoadedModule *begin() { return modules_.begin(); } const LoadedModule *end() const { return modules_.end(); } Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -25,6 +25,7 @@ #include "sanitizer_placement_new.h" #include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" +#include "sanitizer_symbolizer.h" #include // for dlsym() #include @@ -457,6 +458,8 @@ int (*)(struct dl_phdr_info *, size_t, void *), void *); #endif +// When a custom loader is used, dl_iterate_phdr may not contain the full +// list of modules. Allow callers to fall back to using procmaps. void ListOfModules::init() { clear(); #if SANITIZER_ANDROID && __ANDROID_API__ <= 22 @@ -465,15 +468,20 @@ // The runtime check allows the same library to work with // both K and L (and future) Android releases. if (api_level <= ANDROID_LOLLIPOP_MR1) { // L or earlier - MemoryMappingLayout memory_mapping(false); - memory_mapping.DumpListOfModules(&modules_); - return; + return fallbackInit(); } #endif + DlIteratePhdrData data = {&modules_, true}; dl_iterate_phdr(dl_iterate_phdr_cb, &data); } +void ListOfModules::fallbackInit() { + clear(); + MemoryMappingLayout memory_mapping(false); + memory_mapping.DumpListOfModules(&modules_); +} + // getrusage does not give us the current RSS, only the max RSS. // Still, this is better than nothing if /proc/self/statm is not available // for some reason, e.g. due to a sandbox. Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -415,6 +415,10 @@ memory_mapping.DumpListOfModules(&modules_); } +void ListOfModules::fallbackInit() { + init(); +} + static HandleSignalMode GetHandleSignalModeImpl(int signum) { switch (signum) { case SIGABRT: Index: lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.h +++ lib/sanitizer_common/sanitizer_symbolizer.h @@ -119,6 +119,8 @@ void AddHooks(StartSymbolizationHook start_hook, EndSymbolizationHook end_hook); + void RefreshModules(bool fallback_init); + const LoadedModule *SearchForModule(uptr address); const LoadedModule *FindModuleForAddress(uptr address); void InvalidateModuleList(); Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -151,29 +151,44 @@ return true; } -const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { - bool modules_were_reloaded = false; - if (!modules_fresh_) { - modules_.init(); +void Symbolizer::RefreshModules(bool fallback_init) { + fallback_init ? modules_.fallbackInit() : modules_.init(); RAW_CHECK(modules_.size() > 0); modules_fresh_ = true; - modules_were_reloaded = true; - } +} + +const LoadedModule *Symbolizer::SearchForModule(uptr address) { for (uptr i = 0; i < modules_.size(); i++) { if (modules_[i].containsAddress(address)) { return &modules_[i]; } } + return nullptr; +} + +const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { + bool modules_were_reloaded = false; + if (!modules_fresh_) { + RefreshModules(false); + modules_were_reloaded = true; + } + const LoadedModule *module = SearchForModule(address); + // dlopen/dlclose interceptors invalidate the module list, but when // interception is disabled, we need to retry if the lookup fails in // case the module list changed. #if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE - if (!modules_were_reloaded) { - modules_fresh_ = false; - return FindModuleForAddress(address); + if (!module && !modules_were_reloaded) { + RefreshModules(false); + module = SearchForModule(address); } #endif - return 0; + + if (!module) { + RefreshModules(true); + module = SearchForModule(address); + } + return module; } Symbolizer *Symbolizer::GetOrInit() { Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -583,7 +583,11 @@ modules_.push_back(cur_module); } UnmapOrDie(hmodules, modules_buffer_size); -}; +} + +void ListOfModules::fallbackInit() { + init(); +} // We can't use atexit() directly at __asan_init time as the CRT is not fully // initialized at this point. Place the functions into a vector and use