diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -425,8 +425,8 @@ bool isFoldable = (!onlyCfStrings || isCfStringSection(isec)) && (isCodeSection(isec) || isFoldableWithAddendsRemoved || isGccExceptTabSection(isec)) && - !isec->keepUnique && !isec->shouldOmitFromOutput() && - hasFoldableFlags; + !isec->keepUnique && !isec->hasAltEntry && + !isec->shouldOmitFromOutput() && hasFoldableFlags; if (isFoldable) { foldable.push_back(isec); for (Defined *d : isec->symbols) diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -854,6 +854,7 @@ // 4. If we have a literal section (e.g. __cstring and __literal4). if (!subsectionsViaSymbols || symbolOffset == 0 || sym.n_desc & N_ALT_ENTRY || !isa(isec)) { + isec->hasAltEntry = symbolOffset != 0; symbols[symIndex] = createDefined(sym, name, isec, symbolOffset, symbolSize, forceHidden); continue; diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -64,11 +64,12 @@ protected: InputSection(Kind kind, const Section §ion, ArrayRef data, uint32_t align) - : sectionKind(kind), align(align), data(data), section(section) {} + : sectionKind(kind), keepUnique(false), hasAltEntry(false), align(align), + data(data), section(section) {} InputSection(const InputSection &rhs) - : sectionKind(rhs.sectionKind), align(rhs.align), data(rhs.data), - section(rhs.section) {} + : sectionKind(rhs.sectionKind), keepUnique(false), hasAltEntry(false), + align(rhs.align), data(rhs.data), section(rhs.section) {} Kind sectionKind; @@ -77,7 +78,10 @@ bool isFinal = false; // keep the address of the symbol(s) in this section unique in the final // binary ? - bool keepUnique = false; + bool keepUnique : 1; + // Does this section have symbols at offsets other than zero? (NOTE: only + // applies to ConcatInputSections.) + bool hasAltEntry : 1; uint32_t align = 1; OutputSection *parent = nullptr; diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -141,31 +141,15 @@ for (auto ©Sym : copy->symbols) copySym->wasIdenticalCodeFolded = true; - // Merge the sorted vectors of symbols together. - auto it = symbols.begin(); - for (auto copyIt = copy->symbols.begin(); copyIt != copy->symbols.end();) { - if (it == symbols.end()) { - symbols.push_back(*copyIt++); - it = symbols.end(); - } else if ((*it)->value > (*copyIt)->value) { - std::swap(*it++, *copyIt); - } else { - ++it; - } - } + symbols.insert(symbols.end(), copy->symbols.begin(), copy->symbols.end()); copy->symbols.clear(); // Remove duplicate compact unwind info for symbols at the same address. if (symbols.empty()) return; - it = symbols.begin(); - uint64_t v = (*it)->value; - for (++it; it != symbols.end(); ++it) { - Defined *d = *it; - if (d->value == v) - d->unwindEntry = nullptr; - else - v = d->value; + for (auto it = symbols.begin() + 1; it != symbols.end(); ++it) { + assert((*it)->value == 0); + (*it)->unwindEntry = nullptr; } } diff --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s --- a/lld/test/MachO/icf.s +++ b/lld/test/MachO/icf.s @@ -25,7 +25,7 @@ # CHECK: [[#%x,DYLIB_REF_4:]] l F __TEXT,__text _dylib_ref_4 # CHECK: [[#%x,ALT:]] l F __TEXT,__text _alt # CHECK: [[#%x,WITH_ALT_ENTRY:]] l F __TEXT,__text _with_alt_entry -# CHECK: [[#%x,WITH_ALT_ENTRY]] l F __TEXT,__text _no_alt_entry +# CHECK: [[#%x,NO_ALT_ENTRY:]] l F __TEXT,__text _no_alt_entry # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2:]] l F __TEXT,__text _defined_ref_with_addend_1 # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_2]] l F __TEXT,__text _defined_ref_with_addend_2 # CHECK: [[#%x,DEFINED_REF_WITH_ADDEND_3:]] l F __TEXT,__text _defined_ref_with_addend_3 @@ -74,7 +74,7 @@ # CHECK: callq 0x[[#%x,DYLIB_REF_4]] <_dylib_ref_4> # CHECK: callq 0x[[#%x,ALT]] <_alt> # CHECK: callq 0x[[#%x,WITH_ALT_ENTRY]] <_with_alt_entry> -# CHECK: callq 0x[[#%x,WITH_ALT_ENTRY]] <_with_alt_entry> +# CHECK: callq 0x[[#%x,NO_ALT_ENTRY]] <_no_alt_entry> # CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2]] <_defined_ref_with_addend_2> # CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_2]] <_defined_ref_with_addend_2> # CHECK: callq 0x[[#%x,DEFINED_REF_WITH_ADDEND_3]] <_defined_ref_with_addend_3> @@ -161,8 +161,7 @@ mov ___nan + 1@GOTPCREL(%rip), %rax callq ___inf + 1 -## We can merge two sections even if one of them has an alt entry. Just make -## sure we don't merge the alt entry symbol with a regular symbol. +## Sections with alt entries cannot be merged. .alt_entry _alt _with_alt_entry: movq $3132, %rax