Index: lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.h +++ lib/sanitizer_common/sanitizer_symbolizer.h @@ -113,10 +113,16 @@ /// Platform-specific function for creating a Symbolizer object. static Symbolizer *PlatformInit(); - virtual bool PlatformFindModuleNameAndOffsetForAddress( - uptr address, const char **module_name, uptr *module_offset) { - UNIMPLEMENTED(); - } + LoadedModule *FindModuleForAddress(uptr address); + bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, + uptr *module_offset); + // 16K loaded modules should be enough for everyone. + static const uptr kMaxNumberOfModuleContexts = 1 << 14; + LoadedModule *modules_; // Array of module descriptions is leaked. + uptr n_modules_; + // If stale, need to reload the modules before looking up addresses. + bool modules_fresh_; + // Platform-specific default demangler, must not return nullptr. virtual const char *PlatformDemangle(const char *name) { UNIMPLEMENTED(); } virtual void PlatformPrepareForSandboxing() { UNIMPLEMENTED(); } Index: lib/sanitizer_common/sanitizer_symbolizer.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer.cc +++ lib/sanitizer_common/sanitizer_symbolizer.cc @@ -94,8 +94,7 @@ const char *module_name; uptr module_offset; SymbolizedStack *res = SymbolizedStack::New(addr); - if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, - &module_offset)) + if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) return res; // Always fill data about module name and offset. res->info.FillModuleInfo(module_name, module_offset); @@ -113,8 +112,7 @@ BlockingMutexLock l(&mu_); const char *module_name; uptr module_offset; - if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, - &module_offset)) + if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) return false; info->Clear(); info->module = internal_strdup(module_name); @@ -130,10 +128,9 @@ } bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, - uptr *module_address) { + uptr *module_address) { BlockingMutexLock l(&mu_); - return PlatformFindModuleNameAndOffsetForAddress(pc, module_name, - module_address); + return FindModuleNameAndOffsetForAddress(pc, module_name, module_address); } void Symbolizer::Flush() { @@ -161,4 +158,44 @@ PlatformPrepareForSandboxing(); } +LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { + bool modules_were_reloaded = false; + if (modules_ == 0 || !modules_fresh_) { + modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate( + kMaxNumberOfModuleContexts * sizeof(LoadedModule))); + CHECK(modules_); + n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts, + /* filter */ 0); + CHECK_GT(n_modules_, 0); + CHECK_LT(n_modules_, kMaxNumberOfModuleContexts); + modules_fresh_ = true; + modules_were_reloaded = true; + } + for (uptr i = 0; i < n_modules_; i++) { + if (modules_[i].containsAddress(address)) { + return &modules_[i]; + } + } + // Reload the modules and look up again, if we haven't tried it yet. + if (!modules_were_reloaded) { + // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors. + // It's too aggressive to reload the list of modules each time we fail + // to find a module for a given address. + modules_fresh_ = false; + return FindModuleForAddress(address); + } + return 0; +} + +bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, + const char **module_name, + uptr *module_offset) { + LoadedModule *module = FindModuleForAddress(address); + if (module == 0) + return false; + *module_name = module->full_name(); + *module_offset = address - module->base_address(); + return true; +} + } // namespace __sanitizer Index: lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -364,53 +364,6 @@ CacheBinaryName(); #endif } - - LoadedModule *FindModuleForAddress(uptr address) { - bool modules_were_reloaded = false; - if (modules_ == 0 || !modules_fresh_) { - modules_ = (LoadedModule*)(symbolizer_allocator_.Allocate( - kMaxNumberOfModuleContexts * sizeof(LoadedModule))); - CHECK(modules_); - n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts, - /* filter */ 0); - CHECK_GT(n_modules_, 0); - CHECK_LT(n_modules_, kMaxNumberOfModuleContexts); - modules_fresh_ = true; - modules_were_reloaded = true; - } - for (uptr i = 0; i < n_modules_; i++) { - if (modules_[i].containsAddress(address)) { - return &modules_[i]; - } - } - // Reload the modules and look up again, if we haven't tried it yet. - if (!modules_were_reloaded) { - // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors. - // It's too aggressive to reload the list of modules each time we fail - // to find a module for a given address. - modules_fresh_ = false; - return FindModuleForAddress(address); - } - return 0; - } - - bool PlatformFindModuleNameAndOffsetForAddress(uptr address, - const char **module_name, - uptr *module_offset) override { - LoadedModule *module = FindModuleForAddress(address); - if (module == 0) - return false; - *module_name = module->full_name(); - *module_offset = address - module->base_address(); - return true; - } - - // 16K loaded modules should be enough for everyone. - static const uptr kMaxNumberOfModuleContexts = 1 << 14; - LoadedModule *modules_; // Array of module descriptions is leaked. - uptr n_modules_; - // If stale, need to reload the modules before looking up addresses. - bool modules_fresh_; }; static SymbolizerTool *ChooseSymbolizer(LowLevelAllocator *allocator) { Index: lib/sanitizer_common/sanitizer_symbolizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -129,21 +129,6 @@ return name; } -bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name, - uptr *module_offset) { - InitializeDbgHelpIfNeeded(); - - IMAGEHLP_MODULE64 mod_info; - internal_memset(&mod_info, 0, sizeof(mod_info)); - mod_info.SizeOfStruct = sizeof(mod_info); - if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) { - *module_name = mod_info.ImageName; - *module_offset = addr - (uptr)mod_info.BaseOfImage; - return true; - } - return false; -} - // TODO(kuba.brecka): To be merged with POSIXSymbolizer. class WinSymbolizer : public Symbolizer { public: @@ -151,11 +136,6 @@ : Symbolizer(tools) {} private: - bool PlatformFindModuleNameAndOffsetForAddress( - uptr addr, const char **module_name, uptr *module_offset) override { - return ::FindModuleNameAndOffsetForAddress(addr, module_name, - module_offset); - } const char *PlatformDemangle(const char *name) override { return name; } void PlatformPrepareForSandboxing() override { } }; Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -205,77 +205,35 @@ } namespace { -struct ModuleInfo { - HMODULE handle; - uptr base_address; - uptr end_address; -}; - int CompareModulesBase(const void *pl, const void *pr) { - const ModuleInfo &l = *(ModuleInfo *)pl, &r = *(ModuleInfo *)pr; - if (l.base_address < r.base_address) + const LoadedModule *l = (LoadedModule *)pl, *r = (LoadedModule *)pr; + if (l->base_address() < r->base_address()) return -1; - return l.base_address > r.base_address; + return l->base_address() > r->base_address(); } } // namespace #ifndef SANITIZER_GO void DumpProcessMap() { Report("Dumping process modules:\n"); - HANDLE cur_process = GetCurrentProcess(); - - // Query the list of modules. Start by assuming there are no more than 256 - // modules and retry if that's not sufficient. - ModuleInfo *modules; - size_t num_modules; - { - HMODULE *hmodules = 0; - uptr modules_buffer_size = sizeof(HMODULE) * 256; - DWORD bytes_required; - while (!hmodules) { - hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__); - CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size, - &bytes_required)); - if (bytes_required > modules_buffer_size) { - // Either there turned out to be more than 256 hmodules, or new hmodules - // could have loaded since the last try. Retry. - UnmapOrDie(hmodules, modules_buffer_size); - hmodules = 0; - modules_buffer_size = bytes_required; - } - } - num_modules = bytes_required / sizeof(HMODULE); - modules = - (ModuleInfo *)MmapOrDie(num_modules * sizeof(ModuleInfo), __FUNCTION__); - for (size_t i = 0; i < num_modules; ++i) { - modules[i].handle = hmodules[i]; - MODULEINFO mi; - if (!GetModuleInformation(cur_process, hmodules[i], &mi, sizeof(mi))) - continue; - modules[i].base_address = (uptr)mi.lpBaseOfDll; - modules[i].end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; - } - UnmapOrDie(hmodules, modules_buffer_size); - } + static const uptr kMaxNumberOfModules = 1 << 14; + InternalScopedBuffer modules(kMaxNumberOfModules); + CHECK(modules.data()); + int num_modules = GetListOfModules(modules.data(), kMaxNumberOfModules, + /* filter */ 0); - qsort(modules, num_modules, sizeof(ModuleInfo), CompareModulesBase); + qsort(modules.data(), num_modules, sizeof(LoadedModule), CompareModulesBase); for (size_t i = 0; i < num_modules; ++i) { - const ModuleInfo &mi = modules[i]; - char module_name[MAX_PATH]; - bool got_module_name = GetModuleFileNameA( - mi.handle, module_name, sizeof(module_name)); - if (mi.end_address != 0) { - Printf("\t%p-%p %s\n", mi.base_address, mi.end_address, - got_module_name ? module_name : "[no name]"); - } else if (got_module_name) { - Printf("\t??\?-??? %s\n", module_name); - } else { - Printf("\t???\n"); - } + const char *module_name = modules[i].full_name(); + // On Windows, the module contains a single address range describing the + // whole module. + uptr beg = modules[i].ranges().next()->beg; + uptr end = modules[i].ranges().next()->end; + Printf("\t%p-%p %s\n", beg, end, module_name); + modules[i].clear(); } - UnmapOrDie(modules, num_modules * sizeof(ModuleInfo)); } #endif @@ -346,7 +304,54 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, string_predicate_t filter) { - UNIMPLEMENTED(); + HANDLE cur_process = GetCurrentProcess(); + + // Query the list of modules. Start by assuming there are no more than 256 + // modules and retry if that's not sufficient. + HMODULE *hmodules = 0; + uptr modules_buffer_size = sizeof(HMODULE) * 256; + DWORD bytes_required; + while (!hmodules) { + hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__); + CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size, + &bytes_required)); + if (bytes_required > modules_buffer_size) { + // Either there turned out to be more than 256 hmodules, or new hmodules + // could have loaded since the last try. Retry. + UnmapOrDie(hmodules, modules_buffer_size); + hmodules = 0; + modules_buffer_size = bytes_required; + } + } + + size_t n = bytes_required / sizeof(HMODULE); + size_t num_modules = 0; + for (size_t i = 0; i < n && num_modules < max_modules; ++i) { + HMODULE handle = hmodules[i]; + MODULEINFO mi; + if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi))) + continue; + uptr base_address = (uptr)mi.lpBaseOfDll; + uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; + + char module_name[MAX_PATH]; + bool got_module_name = + GetModuleFileNameA(handle, module_name, sizeof(module_name)); + if (!got_module_name) + module_name[0] = '\0'; + + if (filter && !filter(module_name)) + continue; + + void *mem = &modules[num_modules]; + LoadedModule *cur_module = new(mem) LoadedModule(module_name, base_address); + // We add the whole module as one single address range. + cur_module->addAddressRange(base_address, end_address, /*executable*/ true); + num_modules++; + } + UnmapOrDie(hmodules, modules_buffer_size); + + return num_modules; }; #ifndef SANITIZER_GO