Index: compiler-rt/trunk/lib/lsan/lsan_common_linux.cc =================================================================== --- compiler-rt/trunk/lib/lsan/lsan_common_linux.cc +++ compiler-rt/trunk/lib/lsan/lsan_common_linux.cc @@ -26,9 +26,8 @@ namespace __lsan { static const char kLinkerName[] = "ld"; -// We request 2 modules matching "ld", so we can print a warning if there's more -// than one match. But only the first one is actually used. -static char linker_placeholder[2 * sizeof(LoadedModule)] ALIGNED(64); + +static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64); static LoadedModule *linker = nullptr; static bool IsLinker(const char* full_name) { @@ -36,20 +35,24 @@ } void InitializePlatformSpecificModules() { - internal_memset(linker_placeholder, 0, sizeof(linker_placeholder)); - uptr num_matches = GetListOfModules( - reinterpret_cast(linker_placeholder), 2, IsLinker); - if (num_matches == 1) { - linker = reinterpret_cast(linker_placeholder); - return; + ListOfModules modules; + modules.init(); + for (LoadedModule &module : modules) { + if (!IsLinker(module.full_name())) continue; + if (linker == nullptr) { + linker = reinterpret_cast(linker_placeholder); + *linker = module; + module = LoadedModule(); + } else { + VReport(1, "LeakSanitizer: Multiple modules match \"%s\". " + "TLS will not be handled correctly.\n", kLinkerName); + linker->clear(); + linker = nullptr; + return; + } } - if (num_matches == 0) - VReport(1, "LeakSanitizer: Dynamic linker not found. " - "TLS will not be handled correctly.\n"); - else if (num_matches > 1) - VReport(1, "LeakSanitizer: Multiple modules match \"%s\". " - "TLS will not be handled correctly.\n", kLinkerName); - linker = nullptr; + VReport(1, "LeakSanitizer: Dynamic linker not found. " + "TLS will not be handled correctly.\n"); } static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size, Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h @@ -44,9 +44,6 @@ const uptr kMaxPathLength = 4096; -// 16K loaded modules should be enough for everyone. -static const uptr kMaxNumberOfModules = 1 << 14; - const uptr kMaxThreadStackSize = 1 << 30; // 1Gb static const uptr kErrorMessageBufferSize = 1 << 16; @@ -666,13 +663,33 @@ IntrusiveList ranges_; }; -// OS-dependent function that fills array with descriptions of at most -// "max_modules" currently loaded modules. Returns the number of -// initialized modules. If filter is nonzero, ignores modules for which -// filter(full_name) is false. -typedef bool (*string_predicate_t)(const char *); -uptr GetListOfModules(LoadedModule *modules, uptr max_modules, - string_predicate_t filter); +// List of LoadedModules. OS-dependent implementation is responsible for +// filling this information. +class ListOfModules { + public: + ListOfModules() : modules_(kInitialCapacity) {} + ~ListOfModules() { clear(); } + void init(); + const LoadedModule *begin() const { return modules_.begin(); } + LoadedModule *begin() { return modules_.begin(); } + const LoadedModule *end() const { return modules_.end(); } + LoadedModule *end() { return modules_.end(); } + uptr size() const { return modules_.size(); } + const LoadedModule &operator[](uptr i) const { + CHECK_LT(i, modules_.size()); + return modules_[i]; + } + + private: + void clear() { + for (auto &module : modules_) module.clear(); + modules_.clear(); + } + + InternalMmapVector modules_; + // We rarely have more than 16K loaded modules. + static const uptr kInitialCapacity = 1 << 14; +}; // Callback type for iterating over a set of memory ranges. typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -805,11 +805,12 @@ sancov_argv.push_back(internal_strdup(cov_file)); } - InternalScopedBuffer LoadedModules(kMaxNumberOfModules); - uptr n_modules = GetListOfModules(LoadedModules.data(), kMaxNumberOfModules, - /* filter */ nullptr); - for (uptr i = 0; i < n_modules; ++i) { - sancov_argv.push_back(internal_strdup(LoadedModules[i].full_name())); + { + ListOfModules modules; + modules.init(); + for (const LoadedModule &module : modules) { + sancov_argv.push_back(internal_strdup(module.full_name())); + } } InternalScopedString report_path(kMaxPathLength); Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc @@ -72,16 +72,13 @@ InternalScopedString text(kMaxTextSize); { - InternalScopedBuffer modules(kMaxNumberOfModules); - CHECK(modules.data()); - int n_modules = GetListOfModules(modules.data(), kMaxNumberOfModules, - /* filter */ nullptr); - text.append("%d\n", sizeof(uptr) * 8); - for (int i = 0; i < n_modules; ++i) { - const char *module_name = StripModuleName(modules[i].full_name()); - uptr base = modules[i].base_address(); - for (const auto &range : modules[i].ranges()) { + ListOfModules modules; + modules.init(); + for (const LoadedModule &module : modules) { + const char *module_name = StripModuleName(module.full_name()); + uptr base = module.base_address(); + for (const auto &range : module.ranges()) { if (range.executable) { uptr start = range.beg; uptr end = range.end; @@ -90,7 +87,6 @@ cached_mapping.SetModuleRange(start, end); } } - modules[i].clear(); } } Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -417,17 +417,12 @@ # endif struct DlIteratePhdrData { - LoadedModule *modules; - uptr current_n; + InternalMmapVector *modules; bool first; - uptr max_n; - string_predicate_t filter; }; static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { DlIteratePhdrData *data = (DlIteratePhdrData*)arg; - if (data->current_n == data->max_n) - return 0; InternalScopedString module_name(kMaxPathLength); if (data->first) { data->first = false; @@ -438,20 +433,18 @@ } if (module_name[0] == '\0') return 0; - if (data->filter && !data->filter(module_name.data())) - return 0; - LoadedModule *cur_module = &data->modules[data->current_n]; - cur_module->set(module_name.data(), info->dlpi_addr); - data->current_n++; + LoadedModule cur_module; + cur_module.set(module_name.data(), info->dlpi_addr); for (int i = 0; i < info->dlpi_phnum; i++) { const Elf_Phdr *phdr = &info->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; uptr cur_end = cur_beg + phdr->p_memsz; bool executable = phdr->p_flags & PF_X; - cur_module->addAddressRange(cur_beg, cur_end, executable); + cur_module.addAddressRange(cur_beg, cur_end, executable); } } + data->modules->push_back(cur_module); return 0; } @@ -460,8 +453,8 @@ int (*)(struct dl_phdr_info *, size_t, void *), void *); #endif -uptr GetListOfModules(LoadedModule *modules, uptr max_modules, - string_predicate_t filter) { +void ListOfModules::init() { + clear(); #if SANITIZER_ANDROID && __ANDROID_API__ <= 22 u32 api_level = AndroidGetApiLevel(); // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken. @@ -469,13 +462,12 @@ // both K and L (and future) Android releases. if (api_level <= ANDROID_LOLLIPOP_MR1) { // L or earlier MemoryMappingLayout memory_mapping(false); - return memory_mapping.DumpListOfModules(modules, max_modules, filter); + memory_mapping.DumpListOfModules(&modules_); + return; } #endif - CHECK(modules); - DlIteratePhdrData data = {modules, 0, true, max_modules, filter}; + DlIteratePhdrData data = {&modules_, true}; dl_iterate_phdr(dl_iterate_phdr_cb, &data); - return data.current_n; } // getrusage does not give us the current RSS, only the max RSS. Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc @@ -361,10 +361,10 @@ #endif } -uptr GetListOfModules(LoadedModule *modules, uptr max_modules, - string_predicate_t filter) { +void ListOfModules::init() { + clear(); MemoryMappingLayout memory_mapping(false); - return memory_mapping.DumpListOfModules(modules, max_modules, filter); + memory_mapping.DumpListOfModules(&modules_); } bool IsHandledDeadlySignal(int signum) { Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h @@ -43,9 +43,8 @@ // instead of aborting. static void CacheMemoryMappings(); - // Stores the list of mapped objects into an array. - uptr DumpListOfModules(LoadedModule *modules, uptr max_modules, - string_predicate_t filter); + // Adds all mapped objects into a vector. + void DumpListOfModules(InternalMmapVector *modules); // Memory protection masks. static const uptr kProtectionRead = 1; Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc @@ -116,22 +116,17 @@ } } -uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules, - uptr max_modules, - string_predicate_t filter) { +void MemoryMappingLayout::DumpListOfModules( + InternalMmapVector *modules) { Reset(); uptr cur_beg, cur_end, cur_offset, prot; InternalScopedString module_name(kMaxPathLength); - uptr n_modules = 0; - for (uptr i = 0; n_modules < max_modules && - Next(&cur_beg, &cur_end, &cur_offset, module_name.data(), - module_name.size(), &prot); + for (uptr i = 0; Next(&cur_beg, &cur_end, &cur_offset, module_name.data(), + module_name.size(), &prot); i++) { const char *cur_name = module_name.data(); if (cur_name[0] == '\0') continue; - if (filter && !filter(cur_name)) - continue; // Don't subtract 'cur_beg' from the first entry: // * If a binary is compiled w/o -pie, then the first entry in // process maps is likely the binary itself (all dynamic libs @@ -144,12 +139,11 @@ // shadow memory of the tool), so the module can't be the // first entry. uptr base_address = (i ? cur_beg : 0) - cur_offset; - LoadedModule *cur_module = &modules[n_modules]; - cur_module->set(cur_name, base_address); - cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute); - n_modules++; + LoadedModule cur_module; + cur_module.set(cur_name, base_address); + cur_module.addAddressRange(cur_beg, cur_end, prot & kProtectionExecute); + modules->push_back(cur_module); } - return n_modules; } void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -155,34 +155,28 @@ return false; } -uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules, - uptr max_modules, - string_predicate_t filter) { +void MemoryMappingLayout::DumpListOfModules( + InternalMmapVector *modules) { Reset(); uptr cur_beg, cur_end, prot; InternalScopedString module_name(kMaxPathLength); - uptr n_modules = 0; - for (uptr i = 0; n_modules < max_modules && - Next(&cur_beg, &cur_end, 0, module_name.data(), - module_name.size(), &prot); + for (uptr i = 0; Next(&cur_beg, &cur_end, 0, module_name.data(), + module_name.size(), &prot); i++) { const char *cur_name = module_name.data(); if (cur_name[0] == '\0') continue; - if (filter && !filter(cur_name)) - continue; LoadedModule *cur_module = nullptr; - if (n_modules > 0 && - 0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) { - cur_module = &modules[n_modules - 1]; + if (!modules->empty() && + 0 == internal_strcmp(cur_name, modules->back().full_name())) { + cur_module = &modules->back(); } else { - cur_module = &modules[n_modules]; + modules->push_back(LoadedModule()); + cur_module = &modules->back(); cur_module->set(cur_name, cur_beg); - n_modules++; } cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute); } - return n_modules; } } // namespace __sanitizer Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h @@ -113,7 +113,7 @@ void AddHooks(StartSymbolizationHook start_hook, EndSymbolizationHook end_hook); - LoadedModule *FindModuleForAddress(uptr address); + const LoadedModule *FindModuleForAddress(uptr address); private: // GetModuleNameAndOffsetForPC has to return a string to the caller. @@ -141,8 +141,7 @@ bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, uptr *module_offset); - LoadedModule modules_[kMaxNumberOfModules]; - uptr n_modules_; + ListOfModules modules_; // If stale, need to reload the modules before looking up addresses. bool modules_fresh_; Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc @@ -96,7 +96,7 @@ } Symbolizer::Symbolizer(IntrusiveList tools) - : module_names_(&mu_), n_modules_(0), modules_fresh_(false), tools_(tools), + : module_names_(&mu_), modules_(), modules_fresh_(false), tools_(tools), start_hook_(0), end_hook_(0) {} Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -135,27 +135,23 @@ bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, uptr *module_offset) { - LoadedModule *module = FindModuleForAddress(address); - if (module == 0) + const LoadedModule *module = FindModuleForAddress(address); + if (module == nullptr) return false; *module_name = module->full_name(); *module_offset = address - module->base_address(); return true; } -LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { +const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { bool modules_were_reloaded = false; if (!modules_fresh_) { - for (uptr i = 0; i < n_modules_; i++) - modules_[i].clear(); - n_modules_ = - GetListOfModules(modules_, kMaxNumberOfModules, /* filter */ nullptr); - CHECK_GT(n_modules_, 0); - CHECK_LT(n_modules_, kMaxNumberOfModules); + modules_.init(); + RAW_CHECK(modules_.size() > 0); modules_fresh_ = true; modules_were_reloaded = true; } - for (uptr i = 0; i < n_modules_; i++) { + for (uptr i = 0; i < modules_.size(); i++) { if (modules_[i].containsAddress(address)) { return &modules_[i]; } Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc @@ -236,9 +236,9 @@ #ifndef SANITIZER_GO void DumpProcessMap() { Report("Dumping process modules:\n"); - InternalScopedBuffer modules(kMaxNumberOfModules); - uptr num_modules = - GetListOfModules(modules.data(), kMaxNumberOfModules, nullptr); + ListOfModules modules; + modules.init(); + uptr num_modules = modules.size(); InternalScopedBuffer module_infos(num_modules); for (size_t i = 0; i < num_modules; ++i) { @@ -372,8 +372,8 @@ } #ifndef SANITIZER_GO -uptr GetListOfModules(LoadedModule *modules, uptr max_modules, - string_predicate_t filter) { +void ListOfModules::init() { + clear(); HANDLE cur_process = GetCurrentProcess(); // Query the list of modules. Start by assuming there are no more than 256 @@ -395,10 +395,8 @@ } // |num_modules| is the number of modules actually present, - // |count| is the number of modules we return. - size_t nun_modules = bytes_required / sizeof(HMODULE), - count = 0; - for (size_t i = 0; i < nun_modules && count < max_modules; ++i) { + size_t num_modules = bytes_required / sizeof(HMODULE); + for (size_t i = 0; i < num_modules; ++i) { HMODULE handle = hmodules[i]; MODULEINFO mi; if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi))) @@ -416,9 +414,6 @@ &module_name[0], kMaxPathLength, NULL, NULL); module_name[module_name_len] = '\0'; - if (filter && !filter(module_name)) - continue; - uptr base_address = (uptr)mi.lpBaseOfDll; uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; @@ -429,15 +424,13 @@ uptr preferred_base = GetPreferredBase(&module_name[0]); uptr adjusted_base = base_address - preferred_base; - LoadedModule *cur_module = &modules[count]; - cur_module->set(module_name, adjusted_base); + LoadedModule cur_module; + cur_module.set(module_name, adjusted_base); // We add the whole module as one single address range. - cur_module->addAddressRange(base_address, end_address, /*executable*/ true); - count++; + cur_module.addAddressRange(base_address, end_address, /*executable*/ true); + modules_.push_back(cur_module); } UnmapOrDie(hmodules, modules_buffer_size); - - return count; }; // We can't use atexit() directly at __asan_init time as the CRT is not fully Index: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc +++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc @@ -37,11 +37,11 @@ const char *binary_name = last_slash ? last_slash + 1 : argv0; MemoryMappingLayout memory_mapping(false); const uptr kMaxModules = 100; - LoadedModule modules[kMaxModules]; - uptr n_modules = memory_mapping.DumpListOfModules(modules, kMaxModules, 0); - EXPECT_GT(n_modules, 0U); + InternalMmapVector modules(kMaxModules); + memory_mapping.DumpListOfModules(&modules); + EXPECT_GT(modules.size(), 0U); bool found = false; - for (uptr i = 0; i < n_modules; ++i) { + for (uptr i = 0; i < modules.size(); ++i) { if (modules[i].containsAddress((uptr)&noop)) { // Verify that the module name is sane. if (strstr(modules[i].full_name(), binary_name) != 0) Index: compiler-rt/trunk/lib/stats/stats.cc =================================================================== --- compiler-rt/trunk/lib/stats/stats.cc +++ compiler-rt/trunk/lib/stats/stats.cc @@ -62,7 +62,7 @@ return; if (!stats_fd) OpenStatsFile(path_env); - LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress( + const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress( reinterpret_cast(smodp)); WriteToFile(stats_fd, mod->full_name(), internal_strlen(mod->full_name()) + 1);