[lld/mac] Propagate -(un)exported_symbol(s_list) to privateExtern in Driver

That way, it's done only once instead of every time shouldExportSymbol() is
called.

Possibly a bit faster:

    % ministat at_main at_symtodo
    x at_main
    + at_symtodo
        N           Min           Max        Median           Avg        Stddev
    x  30     3.9732189      4.114846      4.024621     4.0304692   0.037022865
    +  30       3.93766     4.0510042     3.9973931      3.991469   0.028472565
    Difference at 95.0% confidence
            -0.0390002 +/- 0.0170714
            -0.967635% +/- 0.423559%
            (Student's t, pooled s = 0.0330256)

In other runs with n=30 it makes no perf difference, so maybe it's just noise.
But being able to quickly and conveniently answer "is this symbol exported?"
is useful for fixing PR50373 and for implementing -dead_strip, so this seems
like a good change regardless.

No behavior change.

Differential Revision: https://reviews.llvm.org/D102661
This commit is contained in:
Nico Weber 2021-05-17 20:53:55 -04:00
parent fff84d3a2e
commit 095c520fb4
2 changed files with 23 additions and 31 deletions

View File

@ -1196,6 +1196,27 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
createSyntheticSections();
createSyntheticSymbols();
if (!config->exportedSymbols.empty()) {
for (Symbol *sym : symtab->getSymbols()) {
if (auto *defined = dyn_cast<Defined>(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<Defined>(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);

View File

@ -566,40 +566,11 @@ uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
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;
}
void ExportSection::finalizeContents() {
trieBuilder.setImageBase(in.header->addr);
for (const Symbol *sym : symtab->getSymbols()) {
if (const auto *defined = dyn_cast<Defined>(sym)) {
validateExportSymbol(defined);
if (!shouldExportSymbol(defined))
if (defined->privateExtern)
continue;
trieBuilder.addSymbol(*defined);
hasWeakSymbol = hasWeakSymbol || sym->isWeakDef();
@ -834,7 +805,7 @@ template <class LP> void SymtabSectionImpl<LP>::writeTo(uint8_t *buf) const {
// TODO populate n_desc with more flags
if (auto *defined = dyn_cast<Defined>(entry.sym)) {
uint8_t scope = 0;
if (!shouldExportSymbol(defined)) {
if (defined->privateExtern) {
// Private external -- dylib scoped symbol.
// Promote to non-external at link time.
scope = N_PEXT;