summaryrefslogtreecommitdiff
path: root/lld/MachO/InputFiles.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-24 15:03:44 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-24 15:03:44 +0000
commit4b4fe385e49bd883fd183b5f21c1ea486c722e61 (patch)
treec3d8fdb355c9c73e57723718c22103aaf7d15aa6 /lld/MachO/InputFiles.cpp
parent1f917f69ff07f09b6dbb670971f57f8efe718b84 (diff)
Vendor import of llvm-project main llvmorg-15-init-17485-ga3e38b4a206b.vendor/llvm-project/llvmorg-15-init-17485-ga3e38b4a206b
Diffstat (limited to 'lld/MachO/InputFiles.cpp')
-rw-r--r--lld/MachO/InputFiles.cpp74
1 files changed, 57 insertions, 17 deletions
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index fda6900edabe..e3bf553e5334 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -263,11 +263,15 @@ static Optional<size_t> getRecordSize(StringRef segname, StringRef name) {
if (segname == segment_names::ld)
return target->wordSize == 8 ? 32 : 20;
}
- if (config->icfLevel == ICFLevel::none)
+ if (!config->dedupLiterals)
return {};
if (name == section_names::cfString && segname == segment_names::data)
return target->wordSize == 8 ? 32 : 16;
+
+ if (config->icfLevel == ICFLevel::none)
+ return {};
+
if (name == section_names::objcClassRefs && segname == segment_names::data)
return target->wordSize;
return {};
@@ -359,6 +363,9 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
// have the same name without causing duplicate symbol errors. To avoid
// spurious duplicate symbol errors, we do not parse these sections.
// TODO: Evaluate whether the bitcode metadata is needed.
+ } else if (name == section_names::objCImageInfo &&
+ segname == segment_names::data) {
+ objCImageInfo = data;
} else {
if (name == section_names::addrSig)
addrSigSection = sections.back();
@@ -556,7 +563,7 @@ void ObjFile::parseOptimizationHints(ArrayRef<uint8_t> data) {
if (section == sections.end())
return;
++subsection;
- if (subsection == (*section)->subsections.end()) {
+ while (subsection == (*section)->subsections.end()) {
++section;
if (section == sections.end())
return;
@@ -578,6 +585,7 @@ void ObjFile::parseOptimizationHints(ArrayRef<uint8_t> data) {
if (section == sections.end())
break;
updateAddr();
+ assert(hintStart->offset0 >= subsectionBase);
}
}
@@ -899,7 +907,6 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
if (sym.n_type & N_STAB)
continue;
- StringRef name = strtab + sym.n_strx;
if ((sym.n_type & N_TYPE) == N_SECT) {
Subsections &subsections = sections[sym.n_sect - 1]->subsections;
// parseSections() may have chosen not to parse this section.
@@ -909,7 +916,7 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
} else if (isUndef(sym)) {
undefineds.push_back(i);
} else {
- symbols[i] = parseNonSectionSymbol(sym, name);
+ symbols[i] = parseNonSectionSymbol(sym, StringRef(strtab + sym.n_strx));
}
}
@@ -1186,14 +1193,27 @@ ArrayRef<data_in_code_entry> ObjFile::getDataInCode() const {
void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
for (const Subsection &subsection : compactUnwindSection.subsections) {
ConcatInputSection *isec = cast<ConcatInputSection>(subsection.isec);
- // Hack!! Since each CUE contains a different function address, if ICF
- // operated naively and compared the entire contents of each CUE, entries
- // with identical unwind info but belonging to different functions would
- // never be considered equivalent. To work around this problem, we slice
- // away the function address here. (Note that we do not adjust the offsets
- // of the corresponding relocations.) We rely on `relocateCompactUnwind()`
- // to correctly handle these truncated input sections.
- isec->data = isec->data.slice(target->wordSize);
+ // Hack!! Each compact unwind entry (CUE) has its UNSIGNED relocations embed
+ // their addends in its data. Thus if ICF operated naively and compared the
+ // entire contents of each CUE, entries with identical unwind info but e.g.
+ // belonging to different functions would never be considered equivalent. To
+ // work around this problem, we remove some parts of the data containing the
+ // embedded addends. In particular, we remove the function address and LSDA
+ // pointers. Since these locations are at the start and end of the entry,
+ // we can do this using a simple, efficient slice rather than performing a
+ // copy. We are not losing any information here because the embedded
+ // addends have already been parsed in the corresponding Reloc structs.
+ //
+ // Removing these pointers would not be safe if they were pointers to
+ // absolute symbols. In that case, there would be no corresponding
+ // relocation. However, (AFAIK) MC cannot emit references to absolute
+ // symbols for either the function address or the LSDA. However, it *can* do
+ // so for the personality pointer, so we are not slicing that field away.
+ //
+ // Note that we do not adjust the offsets of the corresponding relocations;
+ // instead, we rely on `relocateCompactUnwind()` to correctly handle these
+ // truncated input sections.
+ isec->data = isec->data.slice(target->wordSize, 8 + target->wordSize);
uint32_t encoding = read32le(isec->data.data() + sizeof(uint32_t));
// llvm-mc omits CU entries for functions that need DWARF encoding, but
// `ld -r` doesn't. We can ignore them because we will re-synthesize these
@@ -1240,11 +1260,23 @@ void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
continue;
}
d->unwindEntry = isec;
- // Since we've sliced away the functionAddress, we should remove the
- // corresponding relocation too. Given that clang emits relocations in
- // reverse order of address, this relocation should be at the end of the
- // vector for most of our input object files, so this is typically an O(1)
- // operation.
+ // Now that the symbol points to the unwind entry, we can remove the reloc
+ // that points from the unwind entry back to the symbol.
+ //
+ // First, the symbol keeps the unwind entry alive (and not vice versa), so
+ // this keeps dead-stripping simple.
+ //
+ // Moreover, it reduces the work that ICF needs to do to figure out if
+ // functions with unwind info are foldable.
+ //
+ // However, this does make it possible for ICF to fold CUEs that point to
+ // distinct functions (if the CUEs are otherwise identical).
+ // UnwindInfoSection takes care of this by re-duplicating the CUEs so that
+ // each one can hold a distinct functionAddress value.
+ //
+ // Given that clang emits relocations in reverse order of address, this
+ // relocation should be at the end of the vector for most of our input
+ // object files, so this erase() is typically an O(1) operation.
it = isec->relocs.erase(it);
}
}
@@ -1500,6 +1532,14 @@ void ObjFile::registerEhFrames(Section &ehFrameSection) {
Defined *funcSym;
if (funcAddrRelocIt != isec->relocs.end()) {
funcSym = targetSymFromCanonicalSubtractor(isec, funcAddrRelocIt);
+ // Canonicalize the symbol. If there are multiple symbols at the same
+ // address, we want both `registerEhFrame` and `registerCompactUnwind`
+ // to register the unwind entry under same symbol.
+ // This is not particularly efficient, but we should run into this case
+ // infrequently (only when handling the output of `ld -r`).
+ if (funcSym->isec)
+ funcSym = findSymbolAtOffset(cast<ConcatInputSection>(funcSym->isec),
+ funcSym->value);
} else {
funcSym = findSymbolAtAddress(sections, funcAddr);
ehRelocator.makePcRel(funcAddrOff, funcSym, target->p2WordSize);