[lld] 942f4e3 - Revert "[lld-macho] Initial support for EH Frames"
Douglas Yung via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 9 05:27:05 PDT 2022
Author: Douglas Yung
Date: 2022-06-09T05:25:43-07:00
New Revision: 942f4e3a7cc9a9f8b2654817cff12907d1276031
URL: https://github.com/llvm/llvm-project/commit/942f4e3a7cc9a9f8b2654817cff12907d1276031
DIFF: https://github.com/llvm/llvm-project/commit/942f4e3a7cc9a9f8b2654817cff12907d1276031.diff
LOG: Revert "[lld-macho] Initial support for EH Frames"
This reverts commit 826be330af9c0a8553a5b32718ecd2d97e10438e.
This was causing a test failure on build bots:
- https://lab.llvm.org/buildbot/#/builders/36/builds/21770
- https://lab.llvm.org/buildbot/#/builders/58/builds/23913
Added:
Modified:
lld/MachO/Arch/ARM64.cpp
lld/MachO/Arch/ARM64_32.cpp
lld/MachO/Arch/X86_64.cpp
lld/MachO/CMakeLists.txt
lld/MachO/Config.h
lld/MachO/Driver.cpp
lld/MachO/ICF.cpp
lld/MachO/InputFiles.cpp
lld/MachO/InputFiles.h
lld/MachO/InputSection.cpp
lld/MachO/InputSection.h
lld/MachO/Relocations.h
lld/MachO/Symbols.h
lld/MachO/Target.h
lld/MachO/UnwindInfoSection.cpp
lld/MachO/Writer.cpp
lld/test/MachO/obj-file-with-stabs.s
lld/test/MachO/tools/generate-cfi-funcs.py
Removed:
lld/MachO/EhFrame.cpp
lld/MachO/EhFrame.h
lld/test/MachO/Inputs/eh-frame-x86_64-r.o
lld/test/MachO/eh-frame.s
lld/test/MachO/invalid/eh-frame.s
################################################################################
diff --git a/lld/MachO/Arch/ARM64.cpp b/lld/MachO/Arch/ARM64.cpp
index e5b8a1b722f6..932a081acf39 100644
--- a/lld/MachO/Arch/ARM64.cpp
+++ b/lld/MachO/Arch/ARM64.cpp
@@ -13,7 +13,6 @@
#include "Target.h"
#include "lld/Common/ErrorHandler.h"
-#include "mach-o/compact_unwind_encoding.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/MachO.h"
@@ -142,10 +141,6 @@ ARM64::ARM64() : ARM64Common(LP64()) {
backwardBranchRange = 128 * 1024 * 1024;
forwardBranchRange = backwardBranchRange - 4;
- modeDwarfEncoding = UNWIND_ARM64_MODE_DWARF;
- subtractorRelocType = ARM64_RELOC_SUBTRACTOR;
- unsignedRelocType = ARM64_RELOC_UNSIGNED;
-
stubHelperHeaderSize = sizeof(stubHelperHeaderCode);
stubHelperEntrySize = sizeof(stubHelperEntryCode);
}
diff --git a/lld/MachO/Arch/ARM64_32.cpp b/lld/MachO/Arch/ARM64_32.cpp
index 5be411e40342..b1036912c39a 100644
--- a/lld/MachO/Arch/ARM64_32.cpp
+++ b/lld/MachO/Arch/ARM64_32.cpp
@@ -105,10 +105,6 @@ ARM64_32::ARM64_32() : ARM64Common(ILP32()) {
cpuType = CPU_TYPE_ARM64_32;
cpuSubtype = CPU_SUBTYPE_ARM64_V8;
- modeDwarfEncoding = 0x04000000; // UNWIND_ARM_MODE_DWARF
- subtractorRelocType = GENERIC_RELOC_INVALID; // FIXME
- unsignedRelocType = GENERIC_RELOC_INVALID; // FIXME
-
stubSize = sizeof(stubCode);
stubHelperHeaderSize = sizeof(stubHelperHeaderCode);
stubHelperEntrySize = sizeof(stubHelperEntryCode);
diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index d675356b9ffb..8b998288bb52 100644
--- a/lld/MachO/Arch/X86_64.cpp
+++ b/lld/MachO/Arch/X86_64.cpp
@@ -12,7 +12,6 @@
#include "Target.h"
#include "lld/Common/ErrorHandler.h"
-#include "mach-o/compact_unwind_encoding.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/Endian.h"
@@ -186,10 +185,6 @@ X86_64::X86_64() : TargetInfo(LP64()) {
cpuType = CPU_TYPE_X86_64;
cpuSubtype = CPU_SUBTYPE_X86_64_ALL;
- modeDwarfEncoding = UNWIND_X86_MODE_DWARF;
- subtractorRelocType = X86_64_RELOC_SUBTRACTOR;
- unsignedRelocType = X86_64_RELOC_UNSIGNED;
-
stubSize = sizeof(stub);
stubHelperHeaderSize = sizeof(stubHelperHeader);
stubHelperEntrySize = sizeof(stubHelperEntry);
diff --git a/lld/MachO/CMakeLists.txt b/lld/MachO/CMakeLists.txt
index f8b1d45c489a..4bd0816bca66 100644
--- a/lld/MachO/CMakeLists.txt
+++ b/lld/MachO/CMakeLists.txt
@@ -14,7 +14,6 @@ add_lld_library(lldMachO
Driver.cpp
DriverUtils.cpp
Dwarf.cpp
- EhFrame.cpp
ExportTrie.cpp
ICF.cpp
InputFiles.cpp
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 69e42c596d16..de64dc47591d 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -130,9 +130,6 @@ struct Configuration {
bool dedupLiterals = true;
bool omitDebugInfo = false;
bool warnDylibInstallName = false;
- // Temporary config flag that will be removed once we have fully implemented
- // support for __eh_frame.
- bool parseEhFrames = false;
uint32_t headerPad;
uint32_t dylibCompatibilityVersion = 0;
uint32_t dylibCurrentVersion = 0;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 0a86b09f911b..9e3ea8eedcfc 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1039,9 +1039,8 @@ static void gatherInputSections() {
int inputOrder = 0;
for (const InputFile *file : inputFiles) {
for (const Section *section : file->sections) {
- // Compact unwind entries require special handling elsewhere. (In
- // contrast, EH frames are handled like regular ConcatInputSections.)
if (section->name == section_names::compactUnwind)
+ // Compact unwind entries require special handling elsewhere.
continue;
ConcatOutputSection *osec = nullptr;
for (const Subsection &subsection : section->subsections) {
@@ -1303,7 +1302,6 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
config->callGraphProfileSort = args.hasFlag(
OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);
config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order);
- config->parseEhFrames = static_cast<bool>(getenv("LLD_IN_TEST"));
// FIXME: Add a commandline flag for this too.
config->zeroModTime = getenv("ZERO_AR_DATE");
diff --git a/lld/MachO/EhFrame.cpp b/lld/MachO/EhFrame.cpp
deleted file mode 100644
index 50d8accc0596..000000000000
--- a/lld/MachO/EhFrame.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-//===- EhFrame.cpp --------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "EhFrame.h"
-#include "InputFiles.h"
-
-#include "lld/Common/ErrorHandler.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/Support/Endian.h"
-
-using namespace llvm;
-using namespace lld;
-using namespace lld::macho;
-using namespace llvm::support::endian;
-
-uint64_t EhReader::readLength(size_t *off) const {
- const size_t errOff = *off;
- if (*off + 4 > data.size())
- failOn(errOff, "CIE/FDE too small");
- uint64_t len = read32le(data.data() + *off);
- *off += 4;
- if (len == dwarf::DW_LENGTH_DWARF64) {
- // FIXME: test this DWARF64 code path
- if (*off + 8 > data.size())
- failOn(errOff, "CIE/FDE too small");
- len = read64le(data.data() + *off);
- *off += 8;
- }
- if (*off + len > data.size())
- failOn(errOff, "CIE/FDE extends past the end of the section");
- return len;
-}
-
-void EhReader::skipValidLength(size_t *off) const {
- uint32_t len = read32le(data.data() + *off);
- *off += 4;
- if (len == dwarf::DW_LENGTH_DWARF64)
- *off += 8;
-}
-
-// Read a byte and advance off by one byte.
-uint8_t EhReader::readByte(size_t *off) const {
- if (*off + 1 > data.size())
- failOn(*off, "unexpected end of CIE/FDE");
- return data[(*off)++];
-}
-
-uint32_t EhReader::readU32(size_t *off) const {
- if (*off + 4 > data.size())
- failOn(*off, "unexpected end of CIE/FDE");
- uint32_t v = read32le(data.data() + *off);
- *off += 4;
- return v;
-}
-
-uint64_t EhReader::readPointer(size_t *off) const {
- if (*off + wordSize > data.size())
- failOn(*off, "unexpected end of CIE/FDE");
- uint64_t v;
- if (wordSize == 8)
- v = read64le(data.data() + *off);
- else {
- assert(wordSize == 4);
- v = read32le(data.data() + *off);
- }
- *off += wordSize;
- return v;
-}
-
-// Read a null-terminated string.
-StringRef EhReader::readString(size_t *off) const {
- if (*off > data.size())
- failOn(*off, "corrupted CIE (failed to read string)");
- const size_t maxlen = data.size() - *off;
- auto *c = reinterpret_cast<const char *>(data.data() + *off);
- size_t len = strnlen(c, maxlen);
- if (len == maxlen) // we failed to find the null terminator
- failOn(*off, "corrupted CIE (failed to read string)");
- *off += len + 1; // skip the null byte too
- return StringRef(c, len);
-}
-
-void EhReader::skipLeb128(size_t *off) const {
- const size_t errOff = *off;
- while (*off < data.size()) {
- uint8_t val = data[(*off)++];
- if ((val & 0x80) == 0)
- return;
- }
- failOn(errOff, "corrupted CIE (failed to read LEB128)");
-}
-
-void EhReader::failOn(size_t errOff, const Twine &msg) const {
- fatal(toString(file) + ":(__eh_frame+0x" +
- Twine::utohexstr(dataOff + errOff) + "): " + msg);
-}
-
-/*
- * Create a pair of relocs to write the value of:
- * `b - (offset + a)` if Invert == false
- * `(a + offset) - b` if Invert == true
- */
-template <bool Invert = false>
-static void createSubtraction(PointerUnion<Symbol *, InputSection *> a,
- PointerUnion<Symbol *, InputSection *> b,
- uint64_t off, uint8_t length,
- SmallVectorImpl<Reloc> *newRelocs) {
- auto subtrahend = a;
- auto minuend = b;
- if (Invert)
- std::swap(subtrahend, minuend);
- assert(subtrahend.is<Symbol *>());
- Reloc subtrahendReloc(target->subtractorRelocType, /*pcrel=*/false, length,
- off, /*addend=*/0, subtrahend);
- Reloc minuendReloc(target->unsignedRelocType, /*pcrel=*/false, length, off,
- (Invert ? 1 : -1) * off, minuend);
- newRelocs->push_back(subtrahendReloc);
- newRelocs->push_back(minuendReloc);
-}
-
-void EhRelocator::makePcRel(uint64_t off,
- PointerUnion<Symbol *, InputSection *> target,
- uint8_t length) {
- createSubtraction(isec->symbols[0], target, off, length, &newRelocs);
-}
-
-void EhRelocator::makeNegativePcRel(
- uint64_t off, PointerUnion<Symbol *, InputSection *> target,
- uint8_t length) {
- createSubtraction</*Invert=*/true>(isec, target, off, length, &newRelocs);
-}
-
-void EhRelocator::commit() {
- isec->relocs.insert(isec->relocs.end(), newRelocs.begin(), newRelocs.end());
-}
diff --git a/lld/MachO/EhFrame.h b/lld/MachO/EhFrame.h
deleted file mode 100644
index c8269b941bcf..000000000000
--- a/lld/MachO/EhFrame.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//===- EhFrame.h ------------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_MACHO_EH_FRAME_H
-#define LLD_MACHO_EH_FRAME_H
-
-#include "InputSection.h"
-#include "Relocations.h"
-
-#include "lld/Common/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/SmallVector.h"
-
-/*
- * NOTE: The main bulk of the EH frame parsing logic is in InputFiles.cpp as it
- * is closely coupled with other file parsing logic; EhFrame.h just contains a
- * few helpers.
- */
-
-/*
- * === The EH frame format ===
- *
- * EH frames can either be Common Information Entries (CIEs) or Frame
- * Description Entries (FDEs). CIEs contain information that is common amongst
- * several FDEs. Each FDE contains a pointer to its CIE. Thus all the EH frame
- * entries together form a forest of two-level trees, with CIEs as the roots
- * and FDEs as the leaves. Note that a CIE must precede the FDEs which point
- * to it.
- *
- * A CIE comprises the following fields in order:
- * 1. Length of the entry (4 or 12 bytes)
- * 2. CIE offset (4 bytes; always 0 for CIEs)
- * 3. CIE version (byte)
- * 4. Null-terminated augmentation string
- * 5-8. LEB128 values that we don't care about
- * 9. Augmentation data, to be interpreted using the aug string
- * 10. DWARF instructions (ignored by LLD)
- *
- * An FDE comprises of the following:
- * 1. Length of the entry (4 or 12 bytes)
- * 2. CIE offset (4 bytes pcrel offset that points backwards to this FDE's CIE)
- * 3. Function address (pointer-sized pcrel offset)
- * 4. (Optional) Augmentation data length
- * 5. (Optional) LSDA address (pointer-sized pcrel offset)
- * 6. DWARF instructions (ignored by LLD)
- */
-namespace lld {
-namespace macho {
-
-class EhReader {
-public:
- EhReader(const ObjFile *file, ArrayRef<uint8_t> data, size_t dataOff,
- size_t wordSize)
- : file(file), data(data), dataOff(dataOff), wordSize(wordSize) {}
- size_t size() const { return data.size(); }
- // Read and validate the length field.
- uint64_t readLength(size_t *off) const;
- // Skip the length field without doing validation.
- void skipValidLength(size_t *off) const;
- uint8_t readByte(size_t *off) const;
- uint32_t readU32(size_t *off) const;
- uint64_t readPointer(size_t *off) const;
- StringRef readString(size_t *off) const;
- void skipLeb128(size_t *off) const;
- void failOn(size_t errOff, const Twine &msg) const;
-
-private:
- const ObjFile *file;
- ArrayRef<uint8_t> data;
- // The offset of the data array within its section. Used only for error
- // reporting.
- const size_t dataOff;
- size_t wordSize;
-};
-
-// The EH frame format, when emitted by llvm-mc, consists of a number of
-// "abs-ified" relocations, i.e. relocations that are implicitly encoded as
-// pcrel offsets in the section data. The offsets refer to the locations of
-// symbols in the input object file. When we ingest these EH frames, we convert
-// these implicit relocations into explicit Relocs.
-//
-// These pcrel relocations are semantically similar to X86_64_RELOC_SIGNED_4.
-// However, we need this operation to be cross-platform, and ARM does not have a
-// similar relocation that is applicable. We therefore use the more verbose (but
-// more generic) subtractor relocation to encode these pcrel values. ld64
-// appears to do something similar -- its `-r` output contains these explicit
-// subtractor relocations.
-class EhRelocator {
-public:
- EhRelocator(InputSection *isec) : isec(isec) {}
-
- // For the next two methods, let `PC` denote `isec address + off`.
- // Create relocs writing the value of target - PC to PC.
- void makePcRel(uint64_t off,
- llvm::PointerUnion<Symbol *, InputSection *> target,
- uint8_t length);
- // Create relocs writing the value of PC - target to PC.
- void makeNegativePcRel(uint64_t off,
- llvm::PointerUnion<Symbol *, InputSection *> target,
- uint8_t length);
- // Insert the new relocations into isec->relocs.
- void commit();
-
-private:
- InputSection *isec;
- // Insert new relocs here so that we don't invalidate iterators into the
- // existing relocs vector.
- SmallVector<Reloc, 6> newRelocs;
-};
-
-} // namespace macho
-} // namespace lld
-
-#endif
diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index 4771e51e5135..e35944343012 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -212,9 +212,9 @@ bool ICF::equalsVariable(const ConcatInputSection *ia,
// info matches. For simplicity, we only handle the case where there are only
// symbols at offset zero within the section (which is typically the case with
// .subsections_via_symbols.)
- auto hasUnwind = [](Defined *d) { return d->unwindEntry != nullptr; };
- auto itA = std::find_if(ia->symbols.begin(), ia->symbols.end(), hasUnwind);
- auto itB = std::find_if(ib->symbols.begin(), ib->symbols.end(), hasUnwind);
+ auto hasCU = [](Defined *d) { return d->unwindEntry != nullptr; };
+ auto itA = std::find_if(ia->symbols.begin(), ia->symbols.end(), hasCU);
+ auto itB = std::find_if(ib->symbols.begin(), ib->symbols.end(), hasCU);
if (itA == ia->symbols.end())
return itB == ib->symbols.end();
if (itB == ib->symbols.end())
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 16d019fb477b..05f491e1b7ba 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -45,7 +45,6 @@
#include "Config.h"
#include "Driver.h"
#include "Dwarf.h"
-#include "EhFrame.h"
#include "ExportTrie.h"
#include "InputSection.h"
#include "MachOStructs.h"
@@ -324,7 +323,6 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
section, data.slice(off, recordSize), align);
subsections.push_back({off, isec});
}
- section.doneSplitting = true;
};
if (sectionType(sec.flags) == S_CSTRING_LITERALS ||
@@ -346,9 +344,6 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
section.subsections.push_back({0, isec});
} else if (auto recordSize = getRecordSize(segname, name)) {
splitRecords(*recordSize);
- } else if (config->parseEhFrames && name == section_names::ehFrame &&
- segname == segment_names::text) {
- splitEhFrames(data, *sections.back());
} else if (segname == segment_names::llvm) {
if (config->callGraphProfileSort && name == section_names::cgProfile)
checkError(parseCallGraph(data, callGraph));
@@ -376,45 +371,6 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
}
}
-void ObjFile::splitEhFrames(ArrayRef<uint8_t> data, Section &ehFrameSection) {
- EhReader reader(this, data, /*dataOff=*/0, target->wordSize);
- size_t off = 0;
- while (off < reader.size()) {
- uint64_t frameOff = off;
- uint64_t length = reader.readLength(&off);
- if (length == 0)
- break;
- uint64_t fullLength = length + (off - frameOff);
- off += length;
- // We hard-code an alignment of 1 here because we don't actually want our
- // EH frames to be aligned to the section alignment. EH frame decoders don't
- // expect this alignment. Moreover, each EH frame must start where the
- // previous one ends, and where it ends is indicated by the length field.
- // Unless we update the length field (troublesome), we should keep the
- // alignment to 1.
- // Note that we still want to preserve the alignment of the overall section,
- // just not of the individual EH frames.
- ehFrameSection.subsections.push_back(
- {frameOff, make<ConcatInputSection>(ehFrameSection,
- data.slice(frameOff, fullLength),
- /*align=*/1)});
- }
- ehFrameSection.doneSplitting = true;
-}
-
-template <class T>
-static Section *findContainingSection(const std::vector<Section *> §ions,
- T *offset) {
- static_assert(std::is_same<uint64_t, T>::value ||
- std::is_same<uint32_t, T>::value,
- "unexpected type for offset");
- auto it = std::prev(llvm::upper_bound(
- sections, *offset,
- [](uint64_t value, const Section *sec) { return value < sec->addr; }));
- *offset -= (*it)->addr;
- return *it;
-}
-
// Find the subsection corresponding to the greatest section offset that is <=
// that of the given offset.
//
@@ -519,6 +475,13 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
relocation_info relInfo = relInfos[i];
bool isSubtrahend =
target->hasAttr(relInfo.r_type, RelocAttrBits::SUBTRAHEND);
+ if (isSubtrahend && StringRef(sec.sectname) == section_names::ehFrame) {
+ // __TEXT,__eh_frame only has symbols and SUBTRACTOR relocs when ld64 -r
+ // adds local "EH_Frame1" and "func.eh". Ignore them because they have
+ // gone unused by Mac OS since Snow Leopard (10.6), vintage 2009.
+ ++i;
+ continue;
+ }
int64_t pairedAddend = 0;
if (target->hasAttr(relInfo.r_type, RelocAttrBits::ADDEND)) {
pairedAddend = SignExtend64<24>(relInfo.r_symbolnum);
@@ -674,8 +637,7 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
}
assert(!isWeakDefCanBeHidden &&
"weak_def_can_be_hidden on already-hidden symbol?");
- bool includeInSymtab =
- !name.startswith("l") && !name.startswith("L") && !isEhFrameSection(isec);
+ bool includeInSymtab = !name.startswith("l") && !name.startswith("L");
return make<Defined>(
name, isec->getFile(), isec, value, size, sym.n_desc & N_WEAK_DEF,
/*isExternal=*/false, /*isPrivateExtern=*/false, includeInSymtab,
@@ -768,14 +730,20 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
Subsections &subsections = sections[i]->subsections;
if (subsections.empty())
continue;
+ if (sections[i]->name == section_names::ehFrame) {
+ // __TEXT,__eh_frame only has symbols and SUBTRACTOR relocs when ld64 -r
+ // adds local "EH_Frame1" and "func.eh". Ignore them because they have
+ // gone unused by Mac OS since Snow Leopard (10.6), vintage 2009.
+ continue;
+ }
std::vector<uint32_t> &symbolIndices = symbolsBySection[i];
uint64_t sectionAddr = sectionHeaders[i].addr;
uint32_t sectionAlign = 1u << sectionHeaders[i].align;
- // Some sections have already been split into subsections during
+ // Record-based sections have already been split into subsections during
// parseSections(), so we simply need to match Symbols to the corresponding
// subsection here.
- if (sections[i]->doneSplitting) {
+ if (getRecordSize(sections[i]->segname, sections[i]->name)) {
for (size_t j = 0; j < symbolIndices.size(); ++j) {
uint32_t symIndex = symbolIndices[j];
const NList &sym = nList[symIndex];
@@ -792,7 +760,6 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
}
continue;
}
- sections[i]->doneSplitting = true;
// Calculate symbol sizes and create subsections by splitting the sections
// along symbol boundaries.
@@ -963,8 +930,6 @@ template <class LP> void ObjFile::parse() {
}
if (compactUnwindSection)
registerCompactUnwind(*compactUnwindSection);
- if (config->parseEhFrames && ehFrameSection)
- registerEhFrames(*ehFrameSection);
}
template <class LP> void ObjFile::parseLazy() {
@@ -1038,12 +1003,6 @@ void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
// of the corresponding relocations.) We rely on `relocateCompactUnwind()`
// to correctly handle these truncated input sections.
isec->data = isec->data.slice(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
- // CU entries from the DWARF info during the output phase.
- if ((encoding & target->modeDwarfEncoding) == target->modeDwarfEncoding)
- continue;
ConcatInputSection *referentIsec;
for (auto it = isec->relocs.begin(); it != isec->relocs.end();) {
@@ -1094,252 +1053,6 @@ void ObjFile::registerCompactUnwind(Section &compactUnwindSection) {
}
}
-struct CIE {
- macho::Symbol *personalitySymbol = nullptr;
- bool fdesHaveLsda = false;
- bool fdesHaveAug = false;
-};
-
-static CIE parseCIE(const InputSection *isec, const EhReader &reader,
- size_t off) {
- // Handling the full generality of possible DWARF encodings would be a major
- // pain. We instead take advantage of our knowledge of how llvm-mc encodes
- // DWARF and handle just that.
- constexpr uint8_t expectedPersonalityEnc =
- dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_sdata4;
- constexpr uint8_t expectedPointerEnc =
- dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_absptr;
-
- CIE cie;
- uint8_t version = reader.readByte(&off);
- if (version != 1 && version != 3)
- fatal("Expected CIE version of 1 or 3, got " + Twine(version));
- StringRef aug = reader.readString(&off);
- reader.skipLeb128(&off); // skip code alignment
- reader.skipLeb128(&off); // skip data alignment
- reader.skipLeb128(&off); // skip return address register
- reader.skipLeb128(&off); // skip aug data length
- uint64_t personalityAddrOff = 0;
- for (char c : aug) {
- switch (c) {
- case 'z':
- cie.fdesHaveAug = true;
- break;
- case 'P': {
- uint8_t personalityEnc = reader.readByte(&off);
- if (personalityEnc != expectedPersonalityEnc)
- reader.failOn(off, "unexpected personality encoding 0x" +
- Twine::utohexstr(personalityEnc));
- personalityAddrOff = off;
- off += 4;
- break;
- }
- case 'L': {
- cie.fdesHaveLsda = true;
- uint8_t lsdaEnc = reader.readByte(&off);
- if (lsdaEnc != expectedPointerEnc)
- reader.failOn(off, "unexpected LSDA encoding 0x" +
- Twine::utohexstr(lsdaEnc));
- break;
- }
- case 'R': {
- uint8_t pointerEnc = reader.readByte(&off);
- if (pointerEnc != expectedPointerEnc)
- reader.failOn(off, "unexpected pointer encoding 0x" +
- Twine::utohexstr(pointerEnc));
- break;
- }
- default:
- break;
- }
- }
- if (personalityAddrOff != 0) {
- auto personalityRelocIt =
- llvm::find_if(isec->relocs, [=](const macho::Reloc &r) {
- return r.offset == personalityAddrOff;
- });
- if (personalityRelocIt == isec->relocs.end())
- reader.failOn(off, "Failed to locate relocation for personality symbol");
- cie.personalitySymbol = personalityRelocIt->referent.get<macho::Symbol *>();
- }
- return cie;
-}
-
-// EH frame target addresses may be encoded as pcrel offsets. However, instead
-// of using an actual pcrel reloc, ld64 emits subtractor relocations instead.
-// This function recovers the target address from the subtractors, essentially
-// performing the inverse operation of EhRelocator.
-//
-// Concretely, we expect our relocations to write the value of `PC -
-// target_addr` to `PC`. `PC` itself is denoted by a minuend relocation that
-// points to a symbol or section plus an addend.
-//
-// If `Invert` is set, then we instead expect `target_addr - PC` to be written
-// to `PC`.
-template <bool Invert = false>
-Defined *
-getTargetSymbolFromSubtraction(const InputSection *isec,
- std::vector<macho::Reloc>::iterator relocIt) {
- const macho::Reloc &subtrahend = *relocIt;
- const macho::Reloc &minuend = *std::next(relocIt);
- assert(target->hasAttr(subtrahend.type, RelocAttrBits::SUBTRAHEND));
- assert(target->hasAttr(minuend.type, RelocAttrBits::UNSIGNED));
- // Note: pcSym may *not* be exactly at the PC; there's usually a non-zero
- // addend.
- auto *pcSym = cast<Defined>(subtrahend.referent.get<macho::Symbol *>());
- Defined *target =
- cast_or_null<Defined>(minuend.referent.dyn_cast<macho::Symbol *>());
- if (!pcSym) {
- auto *targetIsec =
- cast<ConcatInputSection>(minuend.referent.get<InputSection *>());
- target = findSymbolAtOffset(targetIsec, minuend.addend);
- }
- if (Invert)
- std::swap(pcSym, target);
- if (pcSym->isec != isec ||
- pcSym->value - (Invert ? -1 : 1) * minuend.addend != subtrahend.offset)
- fatal("invalid FDE relocation in __eh_frame");
- return target;
-}
-
-Defined *findSymbolAtAddress(const std::vector<Section *> §ions,
- uint64_t addr) {
- Section *sec = findContainingSection(sections, &addr);
- auto *isec = cast<ConcatInputSection>(findContainingSubsection(*sec, &addr));
- return findSymbolAtOffset(isec, addr);
-}
-
-// For symbols that don't have compact unwind info, associate them with the more
-// general-purpose (and verbose) DWARF unwind info found in __eh_frame.
-//
-// This requires us to parse the contents of __eh_frame. See EhFrame.h for a
-// description of its format.
-//
-// While parsing, we also look for what MC calls "abs-ified" relocations -- they
-// are relocations which are implicitly encoded as offsets in the section data.
-// We convert them into explicit Reloc structs so that the EH frames can be
-// handled just like a regular ConcatInputSection later in our output phase.
-//
-// We also need to handle the case where our input object file has explicit
-// relocations. This is the case when e.g. it's the output of `ld -r`. We only
-// look for the "abs-ified" relocation if an explicit relocation is absent.
-void ObjFile::registerEhFrames(Section &ehFrameSection) {
- DenseMap<const InputSection *, CIE> cieMap;
- for (const Subsection &subsec : ehFrameSection.subsections) {
- auto *isec = cast<ConcatInputSection>(subsec.isec);
- uint64_t isecOff = subsec.offset;
-
- // Subtractor relocs require the subtrahend to be a symbol reloc. Ensure
- // that all EH frames have an associated symbol so that we can generate
- // subtractor relocs that reference them.
- if (isec->symbols.size() == 0)
- isec->symbols.push_back(make<Defined>(
- "EH_Frame", isec->getFile(), isec, /*value=*/0, /*size=*/0,
- /*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false,
- /*includeInSymtab=*/false, /*isThumb=*/false,
- /*isReferencedDynamically=*/false, /*noDeadStrip=*/false));
- else if (isec->symbols[0]->value != 0)
- fatal("found symbol at unexpected offset in __eh_frame");
-
- EhReader reader(this, isec->data, subsec.offset, target->wordSize);
- size_t dataOff = 0; // Offset from the start of the EH frame.
- reader.skipValidLength(&dataOff); // readLength() already validated this.
- // cieOffOff is the offset from the start of the EH frame to the cieOff
- // value, which is itself an offset from the current PC to a CIE.
- const size_t cieOffOff = dataOff;
-
- EhRelocator ehRelocator(isec);
- auto cieOffRelocIt = llvm::find_if(
- isec->relocs, [=](const Reloc &r) { return r.offset == cieOffOff; });
- InputSection *cieIsec = nullptr;
- if (cieOffRelocIt != isec->relocs.end()) {
- // We already have an explicit relocation for the CIE offset.
- cieIsec =
- getTargetSymbolFromSubtraction</*Invert=*/true>(isec, cieOffRelocIt)
- ->isec;
- dataOff += sizeof(uint32_t);
- } else {
- // If we haven't found a relocation, then the CIE offset is most likely
- // embedded in the section data (AKA an "abs-ified" reloc.). Parse that
- // and generate a Reloc struct.
- uint32_t cieMinuend = reader.readU32(&dataOff);
- if (cieMinuend == 0)
- cieIsec = isec;
- else {
- uint32_t cieOff = isecOff + dataOff - cieMinuend;
- cieIsec = findContainingSubsection(ehFrameSection, &cieOff);
- if (cieIsec == nullptr)
- fatal("failed to find CIE");
- }
- if (cieIsec != isec)
- ehRelocator.makeNegativePcRel(cieOffOff, cieIsec->symbols[0],
- /*length=*/2);
- }
- if (cieIsec == isec) {
- cieMap[cieIsec] = parseCIE(isec, reader, dataOff);
- continue;
- }
-
- // Offset of the function address within the EH frame.
- const size_t funcAddrOff = dataOff;
- uint64_t funcAddr = reader.readPointer(&dataOff) + ehFrameSection.addr +
- isecOff + funcAddrOff;
- uint32_t funcLength = reader.readPointer(&dataOff);
- size_t lsdaAddrOff = 0; // Offset of the LSDA address within the EH frame.
- assert(cieMap.count(cieIsec));
- const CIE &cie = cieMap[cieIsec];
- Optional<uint64_t> lsdaAddrOpt;
- if (cie.fdesHaveAug) {
- reader.skipLeb128(&dataOff);
- lsdaAddrOff = dataOff;
- if (cie.fdesHaveLsda) {
- uint64_t lsdaOff = reader.readPointer(&dataOff);
- if (lsdaOff != 0) // FIXME possible to test this?
- lsdaAddrOpt = ehFrameSection.addr + isecOff + lsdaAddrOff + lsdaOff;
- }
- }
-
- auto funcAddrRelocIt = isec->relocs.end();
- auto lsdaAddrRelocIt = isec->relocs.end();
- for (auto it = isec->relocs.begin(); it != isec->relocs.end(); ++it) {
- if (it->offset == funcAddrOff)
- funcAddrRelocIt = it++; // Found subtrahend; skip over minuend reloc
- else if (lsdaAddrOpt && it->offset == lsdaAddrOff)
- lsdaAddrRelocIt = it++; // Found subtrahend; skip over minuend reloc
- }
-
- Defined *funcSym;
- if (funcAddrRelocIt != isec->relocs.end()) {
- funcSym = getTargetSymbolFromSubtraction(isec, funcAddrRelocIt);
- } else {
- funcSym = findSymbolAtAddress(sections, funcAddr);
- ehRelocator.makePcRel(funcAddrOff, funcSym, target->p2WordSize);
- }
- // The symbol has been coalesced, or already has a compact unwind entry.
- if (!funcSym || funcSym->getFile() != this || funcSym->unwindEntry) {
- // We must prune unused FDEs for correctness, so we cannot rely on
- // -dead_strip being enabled.
- isec->live = false;
- continue;
- }
-
- InputSection *lsdaIsec = nullptr;
- if (lsdaAddrRelocIt != isec->relocs.end()) {
- lsdaIsec = getTargetSymbolFromSubtraction(isec, lsdaAddrRelocIt)->isec;
- } else if (lsdaAddrOpt) {
- uint64_t lsdaAddr = *lsdaAddrOpt;
- Section *sec = findContainingSection(sections, &lsdaAddr);
- lsdaIsec =
- cast<ConcatInputSection>(findContainingSubsection(*sec, &lsdaAddr));
- ehRelocator.makePcRel(lsdaAddrOff, lsdaIsec, target->p2WordSize);
- }
-
- fdes[isec] = {funcLength, cie.personalitySymbol, lsdaIsec};
- funcSym->unwindEntry = isec;
- ehRelocator.commit();
- }
-}
-
// The path can point to either a dylib or a .tbd file.
static DylibFile *loadDylib(StringRef path, DylibFile *umbrella) {
Optional<MemoryBufferRef> mbref = readFile(path);
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 3e66a791d9b8..b33e510a6901 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -60,8 +60,7 @@ struct Subsection {
using Subsections = std::vector<Subsection>;
class InputFile;
-class Section {
-public:
+struct Section {
InputFile *file;
StringRef segname;
StringRef name;
@@ -77,13 +76,6 @@ class Section {
Section &operator=(const Section &) = delete;
Section(Section &&) = delete;
Section &operator=(Section &&) = delete;
-
-private:
- // Whether we have already split this section into individual subsections.
- // For sections that cannot be split (e.g. literal sections), this is always
- // false.
- bool doneSplitting = false;
- friend class ObjFile;
};
// Represents a call graph profile edge.
@@ -143,12 +135,6 @@ class InputFile {
static int idCount;
};
-struct FDE {
- uint32_t funcLength;
- Symbol *personality;
- InputSection *lsda;
-};
-
// .o file
class ObjFile final : public InputFile {
public:
@@ -160,11 +146,10 @@ class ObjFile final : public InputFile {
static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
llvm::DWARFUnit *compileUnit = nullptr;
- Section *addrSigSection = nullptr;
const uint32_t modTime;
std::vector<ConcatInputSection *> debugSections;
std::vector<CallGraphEntry> callGraph;
- llvm::DenseMap<ConcatInputSection *, FDE> fdes;
+ Section *addrSigSection = nullptr;
private:
template <class LP> void parseLazy();
@@ -179,9 +164,7 @@ class ObjFile final : public InputFile {
void parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
const SectionHeader &, Section &);
void parseDebugInfo();
- void splitEhFrames(ArrayRef<uint8_t> dataArr, Section &ehFrameSection);
void registerCompactUnwind(Section &compactUnwindSection);
- void registerEhFrames(Section &ehFrameSection);
};
// command-line -sectcreate file
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 444a1e9b17c1..bd5978b7c32e 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -268,11 +268,6 @@ bool macho::isClassRefsSection(const InputSection *isec) {
isec->getSegName() == segment_names::data;
}
-bool macho::isEhFrameSection(const InputSection *isec) {
- return isec->getName() == section_names::ehFrame &&
- isec->getSegName() == segment_names::text;
-}
-
std::string lld::toString(const InputSection *isec) {
return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str();
}
diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index ad8404d0a64b..e0184431d6d0 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -273,7 +273,6 @@ inline bool isWordLiteralSection(uint32_t flags) {
bool isCodeSection(const InputSection *);
bool isCfStringSection(const InputSection *);
bool isClassRefsSection(const InputSection *);
-bool isEhFrameSection(const InputSection *);
extern std::vector<ConcatInputSection *> inputSections;
diff --git a/lld/MachO/Relocations.h b/lld/MachO/Relocations.h
index 3c134d55cb20..b82ca4ebebcc 100644
--- a/lld/MachO/Relocations.h
+++ b/lld/MachO/Relocations.h
@@ -61,13 +61,6 @@ struct Reloc {
// gives the destination that this relocation refers to.
int64_t addend = 0;
llvm::PointerUnion<Symbol *, InputSection *> referent = nullptr;
-
- Reloc() = default;
-
- Reloc(uint8_t type, bool pcrel, uint8_t length, uint32_t offset,
- int64_t addend, llvm::PointerUnion<Symbol *, InputSection *> referent)
- : type(type), pcrel(pcrel), length(length), offset(offset),
- addend(addend), referent(referent) {}
};
bool validateSymbolRelocation(const Symbol *, const InputSection *,
diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h
index 227244711c08..7dbab691c564 100644
--- a/lld/MachO/Symbols.h
+++ b/lld/MachO/Symbols.h
@@ -183,7 +183,6 @@ class Defined : public Symbol {
uint64_t value;
// size is only calculated for regular (non-bitcode) symbols.
uint64_t size;
- // This can be a subsection of either __compact_unwind or __eh_frame.
ConcatInputSection *unwindEntry = nullptr;
};
diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h
index e66a6966b59d..b56497a99b0b 100644
--- a/lld/MachO/Target.h
+++ b/lld/MachO/Target.h
@@ -14,7 +14,6 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstddef>
@@ -38,7 +37,6 @@ class TargetInfo {
pageZeroSize = LP::pageZeroSize;
headerSize = sizeof(typename LP::mach_header);
wordSize = LP::wordSize;
- p2WordSize = llvm::CTLog2<LP::wordSize>();
}
virtual ~TargetInfo() = default;
@@ -87,17 +85,12 @@ class TargetInfo {
size_t stubSize;
size_t stubHelperHeaderSize;
size_t stubHelperEntrySize;
- uint8_t p2WordSize;
size_t wordSize;
size_t thunkSize = 0;
uint64_t forwardBranchRange = 0;
uint64_t backwardBranchRange = 0;
- uint32_t modeDwarfEncoding;
- uint8_t subtractorRelocType;
- uint8_t unsignedRelocType;
-
// We contrive this value as sufficiently far from any valid address that it
// will always be out-of-range for any architecture. UINT64_MAX is not a
// good choice because it is (a) only 1 away from wrapping to 0, and (b) the
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 1d6d658f9788..7aa0e8253c76 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -28,7 +28,6 @@
using namespace llvm;
using namespace llvm::MachO;
-using namespace llvm::support::endian;
using namespace lld;
using namespace lld::macho;
@@ -223,8 +222,7 @@ void UnwindInfoSectionImpl::prepareRelocations() {
// entries to the GOT. Hence the use of a MapVector for
// UnwindInfoSection::symbols.
for (const Defined *d : make_second_range(symbols))
- if (d->unwindEntry &&
- d->unwindEntry->getName() == section_names::compactUnwind)
+ if (d->unwindEntry)
prepareRelocations(d->unwindEntry);
}
@@ -333,18 +331,6 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
if (!d->unwindEntry)
return;
- // If we have DWARF unwind info, create a CU entry that points to it.
- if (d->unwindEntry->getName() == section_names::ehFrame) {
- cu.encoding = target->modeDwarfEncoding | d->unwindEntry->outSecOff;
- const FDE &fde = cast<ObjFile>(d->getFile())->fdes[d->unwindEntry];
- cu.functionLength = fde.funcLength;
- cu.personality = fde.personality;
- cu.lsda = fde.lsda;
- return;
- }
-
- assert(d->unwindEntry->getName() == section_names::compactUnwind);
-
auto buf = reinterpret_cast<const uint8_t *>(d->unwindEntry->data.data()) -
target->wordSize;
cu.functionLength =
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 3e9641ba5ef7..a485ba97d8d3 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -950,14 +950,8 @@ template <class LP> void Writer::createOutputSections() {
StringRef segname = it.first.first;
ConcatOutputSection *osec = it.second;
assert(segname != segment_names::ld);
- if (osec->isNeeded()) {
- // See comment in ObjFile::splitEhFrames()
- if (osec->name == section_names::ehFrame &&
- segname == segment_names::text)
- osec->align = target->wordSize;
-
+ if (osec->isNeeded())
getOrCreateOutputSegment(segname)->addOutputSection(osec);
- }
}
for (SyntheticSection *ssec : syntheticSections) {
diff --git a/lld/test/MachO/Inputs/eh-frame-x86_64-r.o b/lld/test/MachO/Inputs/eh-frame-x86_64-r.o
deleted file mode 100644
index d98e14ec81bf..000000000000
Binary files a/lld/test/MachO/Inputs/eh-frame-x86_64-r.o and /dev/null
diff er
diff --git a/lld/test/MachO/eh-frame.s b/lld/test/MachO/eh-frame.s
deleted file mode 100644
index 24fd7bfc93f9..000000000000
--- a/lld/test/MachO/eh-frame.s
+++ /dev/null
@@ -1,161 +0,0 @@
-# REQUIRES: x86
-# RUN: rm -rf %t; mkdir %t
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %s -o %t/eh-frame-x86_64.o
-# RUN: %lld -lSystem -lc++ %t/eh-frame-x86_64.o -o %t/eh-frame-x86_64
-# RUN: llvm-objdump --macho --syms --indirect-symbols --unwind-info \
-# RUN: --dwarf=frames %t/eh-frame-x86_64 | FileCheck %s -D#BASE=0x100000000 -D#DWARF_ENC=4
-# RUN: llvm-nm -m %t/eh-frame-x86_64 | FileCheck %s --check-prefix NO-EH-SYMS
-# RUN: llvm-readobj --section-headers %t/eh-frame-x86_64 | FileCheck %s --check-prefix=ALIGN -D#ALIGN=3
-
-## Test that we correctly handle the output of `ld -r`, which emits EH frames
-## using subtractor relocations instead of implicitly encoding the offsets.
-## In order to keep this test cross-platform, we check in ld64's output rather
-## than invoking ld64 directly. NOTE: whenever this test is updated, the
-## checked-in copy of `ld -r`'s output should be updated too!
-# COM: ld -r %t/eh-frame-x86_64.o -o %S/Inputs/eh-frame-x86_64-r.o
-# RUN: %lld -lSystem -lc++ %S/Inputs/eh-frame-x86_64-r.o -o %t/eh-frame-x86_64-r
-# RUN: llvm-objdump --macho --syms --indirect-symbols --unwind-info \
-# RUN: --dwarf=frames %t/eh-frame-x86_64-r | FileCheck %s -D#BASE=0x100000000 -D#DWARF_ENC=4
-# RUN: llvm-nm -m %t/eh-frame-x86_64-r | FileCheck %s --check-prefix NO-EH-SYMS
-# RUN: llvm-readobj --section-headers %t/eh-frame-x86_64-r | FileCheck %s --check-prefix=ALIGN -D#ALIGN=3
-
-# ALIGN: Name: __eh_frame
-# ALIGN-NEXT: Segment: __TEXT
-# ALIGN-NEXT: Address:
-# ALIGN-NEXT: Size:
-# ALIGN-NEXT: Offset:
-# ALIGN-NEXT: Alignment: [[#ALIGN]]
-
-# NO-EH-SYMS-NOT: __eh_frame
-
-# CHECK: Indirect symbols for (__DATA_CONST,__got) 2 entries
-# CHECK: address index name
-# CHECK: 0x[[#%x,GXX_PERSONALITY_GOT:]] {{.*}} ___gxx_personality_v0
-# CHECK: 0x[[#%x,MY_PERSONALITY_GOT:]]
-# CHECK: SYMBOL TABLE:
-# CHECK-DAG: [[#%x,F:]] l F __TEXT,__text _f
-# CHECK-DAG: [[#%x,NO_UNWIND:]] l F __TEXT,__text _no_unwind
-# CHECK-DAG: [[#%x,G:]] l F __TEXT,__text _g
-# CHECK-DAG: [[#%x,H:]] l F __TEXT,__text _h
-# CHECK-DAG: [[#%x,EXCEPT0:]] l O __TEXT,__gcc_except_tab GCC_except_table0
-# CHECK-DAG: [[#%x,EXCEPT1:]] l O __TEXT,__gcc_except_tab GCC_except_table1
-# CHECK-DAG: [[#%x,EXCEPT2:]] l O __TEXT,custom_except custom_except_table2
-# CHECK-DAG: [[#%x,MY_PERSONALITY:]] g F __TEXT,__text _my_personality
-# CHECK: Contents of __unwind_info section:
-# CHECK: Version: 0x1
-# CHECK: Number of personality functions in array: 0x2
-# CHECK: Number of indices in array: 0x2
-# CHECK: Personality functions: (count = 2)
-# CHECK: personality[1]: 0x[[#%.8x,GXX_PERSONALITY_GOT - BASE]]
-# CHECK: personality[2]: 0x[[#%.8x,MY_PERSONALITY_GOT - BASE]]
-# CHECK: LSDA descriptors:
-# CHECK: [0]: function offset=0x[[#%.8x,F - BASE]], LSDA offset=0x[[#%.8x,EXCEPT0 - BASE]]
-# CHECK: [1]: function offset=0x[[#%.8x,G - BASE]], LSDA offset=0x[[#%.8x,EXCEPT1 - BASE]]
-# CHECK: [2]: function offset=0x[[#%.8x,H - BASE]], LSDA offset=0x[[#%.8x,EXCEPT2 - BASE]]
-# CHECK: Second level indices:
-# CHECK: Second level index[0]:
-# CHECK: [0]: function offset=0x[[#%.8x,F - BASE]], encoding[{{.*}}]=0x52{{.*}}
-# CHECK: [1]: function offset=0x[[#%.8x,NO_UNWIND - BASE]], encoding[{{.*}}]=0x00000000
-# CHECK: [2]: function offset=0x[[#%.8x,G - BASE]], encoding[{{.*}}]=0x1[[#%x,DWARF_ENC]][[#%.6x, G_DWARF_OFF:]]
-# CHECK: [3]: function offset=0x[[#%.8x,H - BASE]], encoding[{{.*}}]=0x2[[#%x,DWARF_ENC]][[#%.6x, H_DWARF_OFF:]]
-# CHECK: [4]: function offset=0x[[#%.8x,MY_PERSONALITY - BASE]], encoding[{{.*}}]=0x00000000
-
-# CHECK: .debug_frame contents:
-# CHECK: .eh_frame contents:
-
-# CHECK: [[#%.8x,CIE1_OFF:]] {{.*}} CIE
-# CHECK: Format: DWARF32
-# CHECK: Version: 1
-# CHECK: Augmentation: "zPLR"
-# CHECK: Code alignment factor: 1
-# CHECK: Data alignment factor: -8
-# CHECK: Return address column:
-# CHECK: Personality Address: [[#%.16x,GXX_PERSONALITY_GOT]]
-# CHECK: Augmentation data: 9B {{(([[:xdigit:]]{2} ){4})}}10 10
-
-# CHECK: [[#%.8x,G_DWARF_OFF]] {{.*}} [[#%.8x,G_DWARF_OFF + 4 - CIE1_OFF]] FDE cie=[[#CIE1_OFF]] pc=[[#%x,G]]
-# CHECK: Format: DWARF32
-# CHECK: LSDA Address: [[#%.16x,EXCEPT1]]
-# CHECK: DW_CFA_def_cfa_offset: +8
-# CHECK: 0x[[#%x,G]]:
-
-# CHECK: [[#%.8x,CIE2_OFF:]] {{.*}} CIE
-# CHECK: Format: DWARF32
-# CHECK: Version: 1
-# CHECK: Augmentation: "zPLR"
-# CHECK: Code alignment factor: 1
-# CHECK: Data alignment factor: -8
-# CHECK: Return address column:
-# CHECK: Personality Address: [[#%.16x,MY_PERSONALITY_GOT]]
-# CHECK: Augmentation data: 9B {{(([[:xdigit:]]{2} ){4})}}10 10
-
-# CHECK: [[#%.8x,H_DWARF_OFF]] {{.*}} [[#%.8x,H_DWARF_OFF + 4 - CIE2_OFF]] FDE cie=[[#CIE2_OFF]] pc=[[#%x,H]]
-# CHECK: Format: DWARF32
-# CHECK: LSDA Address: [[#%.16x,EXCEPT2]]
-# CHECK: DW_CFA_def_cfa_offset: +8
-# CHECK: 0x[[#%x,H]]:
-
-.globl _my_personality, _main
-
-.text
-## _f's unwind info can be encoded with compact unwind, so we shouldn't see an
-## FDE entry for it in the output file.
-.p2align 2
-_f:
- .cfi_startproc
- .cfi_personality 155, ___gxx_personality_v0
- .cfi_lsda 16, Lexception0
- .cfi_def_cfa_offset 8
- ret
- .cfi_endproc
-
-.p2align 2
-_no_unwind:
- ret
-
-.p2align 2
-_g:
- .cfi_startproc
- .cfi_personality 155, ___gxx_personality_v0
- .cfi_lsda 16, Lexception1
- .cfi_def_cfa_offset 8
- ## cfi_escape cannot be encoded in compact unwind, so we must keep _g's FDE
- .cfi_escape 0x2e, 0x10
- ret
- .cfi_endproc
-
-.p2align 2
-_h:
- .cfi_startproc
- .cfi_personality 155, _my_personality
- .cfi_lsda 16, Lexception2
- .cfi_def_cfa_offset 8
- ## cfi_escape cannot be encoded in compact unwind, so we must keep _h's FDE
- .cfi_escape 0x2e, 0x10
- ret
- .cfi_endproc
-
-.p2align 2
-_my_personality:
- ret
-
-.p2align 2
-_main:
- ret
-
-.section __TEXT,__gcc_except_tab
-GCC_except_table0:
-Lexception0:
- .byte 255
-
-GCC_except_table1:
-Lexception1:
- .byte 255
-
-.section __TEXT,custom_except
-custom_except_table2:
-Lexception2:
- .byte 255
-
-.subsections_via_symbols
diff --git a/lld/test/MachO/invalid/eh-frame.s b/lld/test/MachO/invalid/eh-frame.s
deleted file mode 100644
index 0e51975bfa4b..000000000000
--- a/lld/test/MachO/invalid/eh-frame.s
+++ /dev/null
@@ -1,83 +0,0 @@
-# REQUIRES: x86
-# RUN: rm -rf %t; split-file %s %t
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %t/too-small-1.s -o %t/too-small-1.o
-# RUN: not %lld -lSystem -dylib %t/too-small-1.o -o /dev/null 2>&1 | FileCheck %s --check-prefix TOO-SMALL-1
-# TOO-SMALL-1: error: {{.*}}too-small-1.o:(__eh_frame+0x0): CIE/FDE too small
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %t/too-small-2.s -o %t/too-small-2.o
-# RUN: not %lld -lSystem -dylib %t/too-small-2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix TOO-SMALL-2
-# TOO-SMALL-2: error: {{.*}}too-small-2.o:(__eh_frame+0x0): CIE/FDE extends past the end of the section
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %t/personality-enc.s -o %t/personality-enc.o
-# RUN: not %lld -lSystem -dylib %t/personality-enc.o -o /dev/null 2>&1 | FileCheck %s --check-prefix PERS-ENC
-# PERS-ENC: error: {{.*}}personality-enc.o:(__eh_frame+0x12): unexpected personality encoding 0xb
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %t/pointer-enc.s -o %t/pointer-enc.o
-# RUN: not %lld -lSystem -dylib %t/pointer-enc.o -o /dev/null 2>&1 | FileCheck %s --check-prefix PTR-ENC
-# PTR-ENC: error: {{.*}}pointer-enc.o:(__eh_frame+0x11): unexpected pointer encoding 0x12
-
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15 %t/string-err.s -o %t/string-err.o
-# RUN: not %lld -lSystem -dylib %t/string-err.o -o /dev/null 2>&1 | FileCheck %s --check-prefix STR
-# STR: error: {{.*}}string-err.o:(__eh_frame+0x9): corrupted CIE (failed to read string)
-
-#--- too-small-1.s
-.p2align 3
-.section __TEXT,__eh_frame
-.short 0x3
-
-.subsections_via_symbols
-
-#--- too-small-2.s
-.p2align 3
-.section __TEXT,__eh_frame
-.long 0x3 # length
-
-.subsections_via_symbols
-
-#--- personality-enc.s
-.p2align 3
-.section __TEXT,__eh_frame
-
-.long 0x14 # length
-.long 0 # CIE offset
-.byte 1 # version
-.asciz "zPR" # aug string
-.byte 0x01 # code alignment
-.byte 0x78 # data alignment
-.byte 0x10 # return address register
-.byte 0x01 # aug length
-.byte 0x0b # personality encoding
-.long 0xffff # personality pointer
-.byte 0x10 # pointer encoding
-.space 1 # pad to alignment
-
-.subsections_via_symbols
-
-#--- pointer-enc.s
-.p2align 3
-.section __TEXT,__eh_frame
-
-.long 0x14 # length
-.long 0 # CIE offset
-.byte 1 # version
-.asciz "zR" # aug string
-.byte 0x01 # code alignment
-.byte 0x78 # data alignment
-.byte 0x10 # return address register
-.byte 0x01 # aug length
-.byte 0x12 # pointer encoding
-.space 7 # pad to alignment
-
-.subsections_via_symbols
-
-#--- string-err.s
-.p2align 3
-.section __TEXT,__eh_frame
-
-.long 0x7 # length
-.long 0 # CIE offset
-.byte 1 # version
-.ascii "zR" # invalid aug string
-
-.subsections_via_symbols
diff --git a/lld/test/MachO/obj-file-with-stabs.s b/lld/test/MachO/obj-file-with-stabs.s
index fd558e8f3e8c..134a748a7ec2 100644
--- a/lld/test/MachO/obj-file-with-stabs.s
+++ b/lld/test/MachO/obj-file-with-stabs.s
@@ -1,33 +1,27 @@
# REQUIRES: x86
-## FIXME: This yaml is from an object file produced with 'ld -r':
-##
-## echo "int main() {return 1;}" > test.c
-## clang -c -g -o test.o test.c
-## ld -r -o test2.o test.o -no_data_in_code_info
-##
-## Replace this with "normal" .s test format once lld supports `-r`
+## FIXME: This yaml is from an object file produced with 'ld -r'
+## Replace this with "normal" .s test format once lld supports `-r`
# RUN: yaml2obj %s -o %t.o
-# RUN: %lld -lSystem -arch x86_64 %t.o -o %t
-
+# RUN: %lld -lSystem -platform_version macos 11.3 11.0 -arch x86_64 %t.o -o %t
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
- cputype: 0x1000007
- cpusubtype: 0x3
- filetype: 0x1
- ncmds: 3
- sizeofcmds: 288
- flags: 0x2000
- reserved: 0x0
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 2
+ sizeofcmds: 384
+ flags: 0x00002000
+ reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
- cmdsize: 232
+ cmdsize: 312
segname: ''
vmaddr: 0
- vmsize: 56
- fileoff: 352
- filesize: 56
+ vmsize: 120
+ fileoff: 448
+ filesize: 120
maxprot: 7
initprot: 7
nsects: 2
@@ -35,33 +29,57 @@ LoadCommands:
Sections:
- sectname: __text
segname: __TEXT
- addr: 0x0
+ addr: 0x0000000000000000
size: 18
- offset: 0x160
+ offset: 0x000001C0
align: 4
- reloff: 0x0
+ reloff: 0x00000000
nreloc: 0
flags: 0x80000400
- reserved1: 0x0
- reserved2: 0x0
- reserved3: 0x0
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
content: 554889E5C745FC00000000B8010000005DC3
- - sectname: __compact_unwind
- segname: __LD
- addr: 0x18
- size: 32
- offset: 0x178
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x0000000000000018
+ size: 64
+ offset: 0x000001D8
align: 3
- reloff: 0x198
- nreloc: 1
- flags: 0x2000000
- reserved1: 0x0
- reserved2: 0x0
- reserved3: 0x0
- content: '0000000000000000120000000000000100000000000000000000000000000000'
+ reloff: 0x00000238
+ nreloc: 4
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ content: 1400000000000000017A520001781001100C0708900100002400000004000000F8FFFFFFFFFFFFFF120000000000000000410E108602430D0600000000000000
relocations:
- - address: 0x0
- symbolnum: 8
+ - address: 0x0000001C
+ symbolnum: 0
+ pcrel: false
+ length: 2
+ extern: true
+ type: 5
+ scattered: false
+ value: 0
+ - address: 0x0000001C
+ symbolnum: 1
+ pcrel: false
+ length: 2
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - address: 0x00000020
+ symbolnum: 1
+ pcrel: false
+ length: 3
+ extern: true
+ type: 5
+ scattered: false
+ value: 0
+ - address: 0x00000020
+ symbolnum: 10
pcrel: false
length: 3
extern: true
@@ -70,72 +88,39 @@ LoadCommands:
value: 0
- cmd: LC_SYMTAB
cmdsize: 24
- symoff: 416
- nsyms: 9
- stroff: 560
- strsize: 48
- - cmd: LC_BUILD_VERSION
- cmdsize: 32
- platform: 1
- minos: 659200
- sdk: 0
- ntools: 1
- Tools:
- - tool: 3
- version: 46596096
+ symoff: 608
+ nsyms: 11
+ stroff: 784
+ strsize: 72
LinkEditData:
NameList:
- - n_strx: 8
- n_type: 0x64 ## N_SO STAB
- n_sect: 0
+ - n_strx: 8 ## N_STAB sym (in got)
+ n_type: 0x0E
+ n_sect: 2
n_desc: 0
- n_value: 0
- - n_strx: 14
- n_type: 0x64 ## N_SO STAB
- n_sect: 0
- n_desc: 0
- n_value: 0
- - n_strx: 21
- n_type: 0x66 ## N_OSO STAB
- n_sect: 3
- n_desc: 1
- n_value: 1651001352
- - n_strx: 1
- n_type: 0x2E ## N_BNSYM STAB
- n_sect: 1
- n_desc: 0
- n_value: 0
- - n_strx: 41
- n_type: 0x24 ## N_FUN STAB
- n_sect: 1
+ n_value: 24
+ - n_strx: 18
+ n_type: 0x0E
+ n_sect: 2
n_desc: 0
- n_value: 0
- - n_strx: 1
- n_type: 0x24 ## N_FUN STAB
- n_sect: 0
- n_desc: 0
- n_value: 18
+ n_value: 48
- n_strx: 1
- n_type: 0x4E ## N_ENSYM STAB
+ n_type: 0x4E
n_sect: 1
n_desc: 0
n_value: 18
- - n_strx: 1
- n_type: 0x64 ## N_SO STAB
- n_sect: 1
- n_desc: 0
- n_value: 0
- - n_strx: 2
- n_type: 0xF
+ - n_strx: 2 ## _main
+ n_type: 0x0F
n_sect: 1
n_desc: 0
n_value: 0
StringTable:
- ' '
- _main
- - '/tmp/'
- - test.c
- - '/private/tmp/test.o'
+ - EH_Frame1
+ - func.eh
+ - '/Users/vyng/'
+ - test.cc
+ - '/Users/vyng/test.o'
- _main
- - ''
...
diff --git a/lld/test/MachO/tools/generate-cfi-funcs.py b/lld/test/MachO/tools/generate-cfi-funcs.py
index c8af2c4876f4..a91eab3eeac6 100755
--- a/lld/test/MachO/tools/generate-cfi-funcs.py
+++ b/lld/test/MachO/tools/generate-cfi-funcs.py
@@ -24,6 +24,9 @@ def print_function(name):
have_lsda = (random.random() < lsda_odds)
frame_size = random.randint(4, 64) * 16
frame_offset = -random.randint(0, (frame_size/16 - 4)) * 16
+ reg_count = random.randint(0, 5)
+ reg_combo = random.randint(0, factorial(reg_count) - 1)
+ regs_saved = saved_regs_combined[reg_count][reg_combo]
global func_size_low, func_size_high
func_size = random.randint(func_size_low, func_size_high) * 0x10
func_size_high += 1
@@ -31,13 +34,13 @@ def print_function(name):
func_size_low += 1
print("""\
-### %s frame=%d lsda=%s size=%d
+### %s regs=%d frame=%d lsda=%s size=%d
.section __TEXT,__text,regular,pure_instructions
.p2align 4, 0x90
.globl %s
%s:
.cfi_startproc""" % (
- name, frame_size, have_lsda, func_size, name, name))
+ name, reg_count, frame_size, have_lsda, func_size, name, name))
if have_lsda:
global lsda_n
lsda_n += 1
@@ -50,6 +53,8 @@ def print_function(name):
.cfi_offset %%rbp, %d
movq %%rsp, %%rbp
.cfi_def_cfa_register %%rbp""" % (frame_size, frame_offset + 6*8))
+ for i in range(reg_count):
+ print(".cfi_offset %s, %d" % (regs_saved[i], frame_offset+(i*8)))
print("""\
.fill %d
popq %%rbp
More information about the llvm-commits
mailing list