Index: lld/MachO/Driver.cpp =================================================================== --- lld/MachO/Driver.cpp +++ lld/MachO/Driver.cpp @@ -1196,6 +1196,27 @@ createSyntheticSections(); createSyntheticSymbols(); + if (!config->exportedSymbols.empty()) { + for (Symbol *sym : symtab->getSymbols()) { + if (auto *defined = dyn_cast(sym)) { + StringRef symbolName = defined->getName(); + if (config->exportedSymbols.match(symbolName)) { + if (defined->privateExtern) { + error("cannot export hidden symbol " + symbolName + + "\n>>> defined in " + toString(defined->getFile())); + } + } else { + defined->privateExtern = true; + } + } + } + } else if (!config->unexportedSymbols.empty()) { + for (Symbol *sym : symtab->getSymbols()) + if (auto *defined = dyn_cast(sym)) + if (config->unexportedSymbols.match(defined->getName())) + defined->privateExtern = true; + } + for (const Arg *arg : args.filtered(OPT_sectcreate)) { StringRef segName = arg->getValue(0); StringRef sectName = arg->getValue(1); Index: lld/MachO/SyntheticSections.cpp =================================================================== --- lld/MachO/SyntheticSections.cpp +++ lld/MachO/SyntheticSections.cpp @@ -566,31 +566,11 @@ ExportSection::ExportSection() : LinkEditSection(segment_names::linkEdit, section_names::export_) {} -static void validateExportSymbol(const Defined *defined) { - StringRef symbolName = defined->getName(); - if (defined->privateExtern && config->exportedSymbols.match(symbolName)) - error("cannot export hidden symbol " + symbolName + "\n>>> defined in " + - toString(defined->getFile())); -} - static bool shouldExportSymbol(const Defined *defined) { if (defined->privateExtern) { assert(defined->isExternal() && "invalid input file"); return false; } - // TODO: Is this a performance bottleneck? If a build has mostly - // global symbols in the input but uses -exported_symbols to filter - // out most of them, then it would be better to set the value of - // privateExtern at parse time instead of calling - // exportedSymbols.match() more than once. - // - // Measurements show that symbol ordering (which again looks up - // every symbol in a hashmap) is the biggest bottleneck when linking - // chromium_framework, so this will likely be worth optimizing. - if (!config->exportedSymbols.empty()) - return config->exportedSymbols.match(defined->getName()); - if (!config->unexportedSymbols.empty()) - return !config->unexportedSymbols.match(defined->getName()); return true; } @@ -598,7 +578,6 @@ trieBuilder.setImageBase(in.header->addr); for (const Symbol *sym : symtab->getSymbols()) { if (const auto *defined = dyn_cast(sym)) { - validateExportSymbol(defined); if (!shouldExportSymbol(defined)) continue; trieBuilder.addSymbol(*defined);