[lld-macho] Only fold private-label aliases that do not have flags

This will enable us to re-land {D139069}.

The issue with the original diff was that we were folding all
private-label symbols. We were not merging the symbol flags during this
folding; instead we just made all references to the folded symbol point
to its aliasee. This caused some flags to be incorrectly discarded. This
surfaced as code that was incorrectly stripped due to LLD dropping the
`.no_dead_strip` flag.

This diff fixes things by only folding flag-less private-label aliases.
Most (maybe all) of the `ltmp<N>` symbols that are generated by the MC
aarch64 backend are flag-less, so this conservative folding behavior
does the job.

Reviewed By: #lld-macho, thakis

Differential Revision: https://reviews.llvm.org/D140606
This commit is contained in:
Jez Ng
2022-12-23 14:50:58 -05:00
parent 7f60ed12ef
commit 61f94f2768
2 changed files with 52 additions and 15 deletions

View File

@@ -845,10 +845,15 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
// We populate subsections by repeatedly splitting the last (highest
// address) subsection.
llvm::stable_sort(symbolIndices, [&](uint32_t lhs, uint32_t rhs) {
// Put private-label symbols after other symbols at the same address.
if (nList[lhs].n_value == nList[rhs].n_value)
return !isPrivateLabel(getSymName(nList[lhs])) &&
isPrivateLabel(getSymName(nList[rhs]));
// Put private-label symbols that have no flags after other symbols at the
// same address.
StringRef lhsName = getSymName(nList[lhs]);
StringRef rhsName = getSymName(nList[rhs]);
if (nList[lhs].n_value == nList[rhs].n_value) {
if (isPrivateLabel(lhsName) && isPrivateLabel(rhsName))
return nList[lhs].n_desc > nList[rhs].n_desc;
return !isPrivateLabel(lhsName) && isPrivateLabel(rhsName);
}
return nList[lhs].n_value < nList[rhs].n_value;
});
for (size_t j = 0; j < symbolIndices.size(); ++j) {
@@ -874,11 +879,13 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
if (!subsectionsViaSymbols || symbolOffset == 0 ||
sym.n_desc & N_ALT_ENTRY || !isa<ConcatInputSection>(isec)) {
isec->hasAltEntry = symbolOffset != 0;
// If we have an private-label symbol that's an alias, just reuse the
// aliased symbol. Our sorting step above ensures that any such symbols
// will appear after the non-private-label ones. See
// weak-def-alias-ignored.s for the motivation behind this.
if (symbolOffset == 0 && isPrivateLabel(name) && j != 0)
// If we have an private-label symbol that's an alias, and that alias
// doesn't have any flags of its own, then we can just reuse the aliased
// symbol. Our sorting step above ensures that any such symbols will
// appear after the non-private-label ones. See weak-def-alias-ignored.s
// for the motivation behind this.
if (symbolOffset == 0 && isPrivateLabel(name) && j != 0 &&
sym.n_desc == 0)
symbols[symIndex] = symbols[symbolIndices[j - 1]];
else
symbols[symIndex] = createDefined(sym, name, isec, symbolOffset,