Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -692,6 +692,7 @@ ListOfModules() : modules_(kInitialCapacity) {} ~ListOfModules() { clear(); } void init(); + bool enableFallbackInit(); const LoadedModule *begin() const { return modules_.begin(); } LoadedModule *begin() { return modules_.begin(); } const LoadedModule *end() const { return modules_.end(); } @@ -711,6 +712,8 @@ InternalMmapVector modules_; // We rarely have more than 16K loaded modules. static const uptr kInitialCapacity = 1 << 14; + + bool use_fallback_init_ = false; }; // Callback type for iterating over a set of memory ranges. Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -26,6 +26,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,18 @@ return 0; } +// 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. +// Returns false if the fallback init is already enabled to allow callers +// to prevent unnecessary reloads. +bool ListOfModules::enableFallbackInit() { + if (use_fallback_init_) { + return false; + } + use_fallback_init_ = true; + return true; +} + #if SANITIZER_ANDROID && __ANDROID_API__ < 21 extern "C" __attribute__((weak)) int dl_iterate_phdr( int (*)(struct dl_phdr_info *, size_t, void *), void *); @@ -470,11 +483,16 @@ // 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 + enableFallbackInit(); + } +#endif + + if (use_fallback_init_) { MemoryMappingLayout memory_mapping(false); memory_mapping.DumpListOfModules(&modules_); return; } -#endif + DlIteratePhdrData data = {&modules_, true}; dl_iterate_phdr(dl_iterate_phdr_cb, &data); } Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -410,6 +410,8 @@ #endif } +bool ListOfModules::enableFallbackInit() { return false; } + void ListOfModules::init() { clear(); MemoryMappingLayout memory_mapping(false); Index: lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -176,6 +176,7 @@ return &modules_[i]; } } + // 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. @@ -185,7 +186,11 @@ return FindModuleForAddress(address); } #endif - return 0; + + if (modules_.enableFallbackInit()) { + return FindModuleForAddress(address); + } + return nullptr; } // For now we assume the following protocol: Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -524,6 +524,8 @@ return (uptr)pe_header->ImageBase; } +bool ListOfModules::enableFallbackInit() { return false; } + void ListOfModules::init() { clear(); HANDLE cur_process = GetCurrentProcess();