diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-24 15:03:44 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-24 15:03:44 +0000 |
| commit | 4b4fe385e49bd883fd183b5f21c1ea486c722e61 (patch) | |
| tree | c3d8fdb355c9c73e57723718c22103aaf7d15aa6 /lld/MachO/InputFiles.cpp | |
| parent | 1f917f69ff07f09b6dbb670971f57f8efe718b84 (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.cpp | 74 |
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); |
