diff --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h
--- a/lld/MachO/UnwindInfoSection.h
+++ b/lld/MachO/UnwindInfoSection.h
@@ -23,19 +23,15 @@
// If all functions are free of unwind info, we can omit the unwind info
// section entirely.
bool isNeeded() const override { return !allEntriesAreOmitted; }
- uint64_t getSize() const override { return unwindInfoSize; }
void addSymbol(const Defined *);
- void prepareRelocations();
+ virtual void prepareRelocations() = 0;
protected:
UnwindInfoSection();
- virtual void prepareRelocations(ConcatInputSection *) = 0;
llvm::MapVector,
const Defined *>
symbols;
- std::vector symbolsVec;
- uint64_t unwindInfoSize = 0;
bool allEntriesAreOmitted = true;
};
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -95,14 +95,43 @@
// TODO(gkm): prune __eh_frame entries superseded by __unwind_info, PR50410
// TODO(gkm): how do we align the 2nd-level pages?
-template struct CompactUnwindLayout {
- Ptr functionAddress;
+// The offsets of various fields in the on-disk representation of each compact
+// unwind entry.
+struct CompactUnwindOffsets {
+ uint32_t functionAddress;
uint32_t functionLength;
- compact_unwind_encoding_t encoding;
- Ptr personality;
- Ptr lsda;
+ uint32_t encoding;
+ uint32_t personality;
+ uint32_t lsda;
+
+ CompactUnwindOffsets(size_t wordSize) {
+ if (wordSize == 8)
+ init();
+ else {
+ assert(wordSize == 4);
+ init();
+ }
+ }
+
+private:
+ template void init() {
+ functionAddress = offsetof(Layout, functionAddress);
+ functionLength = offsetof(Layout, functionLength);
+ encoding = offsetof(Layout, encoding);
+ personality = offsetof(Layout, personality);
+ lsda = offsetof(Layout, lsda);
+ }
+
+ template struct Layout {
+ Ptr functionAddress;
+ uint32_t functionLength;
+ compact_unwind_encoding_t encoding;
+ Ptr personality;
+ Ptr lsda;
+ };
};
+// LLD's internal representation of a compact unwind entry.
struct CompactUnwindEntry {
uint64_t functionAddress;
uint32_t functionLength;
@@ -122,16 +151,24 @@
EncodingMap localEncodingIndexes;
};
-template
+// UnwindInfoSectionImpl allows us to avoid cluttering our header file with a
+// lengthy definition of UnwindInfoSection.
class UnwindInfoSectionImpl final : public UnwindInfoSection {
public:
- void prepareRelocations(ConcatInputSection *) override;
- void relocateCompactUnwind(std::vector &);
- void encodePersonalities();
+ UnwindInfoSectionImpl() : cuOffsets(target->wordSize) {}
+ uint64_t getSize() const override { return unwindInfoSize; }
+ void prepareRelocations() override;
void finalize() override;
void writeTo(uint8_t *buf) const override;
private:
+ void prepareRelocations(ConcatInputSection *);
+ void relocateCompactUnwind(std::vector &);
+ void encodePersonalities();
+
+ uint64_t unwindInfoSize = 0;
+ std::vector symbolsVec;
+ CompactUnwindOffsets cuOffsets;
std::vector> commonEncodings;
EncodingMap commonEncodingIndexes;
// The entries here will be in the same order as their originating symbols
@@ -155,15 +192,6 @@
align = 4;
}
-void UnwindInfoSection::prepareRelocations() {
- // This iteration needs to be deterministic, since prepareRelocations may add
- // entries to the GOT. Hence the use of a MapVector for
- // UnwindInfoSection::symbols.
- for (const Defined *d : make_second_range(symbols))
- if (d->unwindEntry)
- prepareRelocations(d->unwindEntry);
-}
-
// Record function symbols that may need entries emitted in __unwind_info, which
// stores unwind data for address ranges.
//
@@ -189,13 +217,21 @@
}
}
+void UnwindInfoSectionImpl::prepareRelocations() {
+ // This iteration needs to be deterministic, since prepareRelocations may add
+ // entries to the GOT. Hence the use of a MapVector for
+ // UnwindInfoSection::symbols.
+ for (const Defined *d : make_second_range(symbols))
+ if (d->unwindEntry)
+ prepareRelocations(d->unwindEntry);
+}
+
// Compact unwind relocations have different semantics, so we handle them in a
// separate code path from regular relocations. First, we do not wish to add
// rebase opcodes for __LD,__compact_unwind, because that section doesn't
// actually end up in the final binary. Second, personality pointers always
// reside in the GOT and must be treated specially.
-template
-void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
+void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
assert(!isec->shouldOmitFromOutput() &&
"__compact_unwind section should not be omitted");
@@ -212,7 +248,7 @@
// compact unwind entries that references them, and thus appear as section
// relocs. There is no need to prepare them. We only prepare relocs for
// personality functions.
- if (r.offset != offsetof(CompactUnwindLayout, personality))
+ if (r.offset != cuOffsets.personality)
continue;
if (auto *s = r.referent.dyn_cast()) {
@@ -285,8 +321,7 @@
// before converting it to post-link form. There should only be absolute
// relocations here: since we are not emitting the pre-link CU section, there
// is no source address to make a relative location meaningful.
-template
-void UnwindInfoSectionImpl::relocateCompactUnwind(
+void UnwindInfoSectionImpl::relocateCompactUnwind(
std::vector &cuEntries) {
parallelForEachN(0, symbolsVec.size(), [&](size_t i) {
CompactUnwindEntry &cu = cuEntries[i];
@@ -296,15 +331,14 @@
return;
auto buf = reinterpret_cast(d->unwindEntry->data.data()) -
- sizeof(Ptr);
- cu.functionLength = support::endian::read32le(
- buf + offsetof(CompactUnwindLayout, functionLength));
- cu.encoding = support::endian::read32le(
- buf + offsetof(CompactUnwindLayout, encoding));
+ target->wordSize;
+ cu.functionLength =
+ support::endian::read32le(buf + cuOffsets.functionLength);
+ cu.encoding = support::endian::read32le(buf + cuOffsets.encoding);
for (const Reloc &r : d->unwindEntry->relocs) {
- if (r.offset == offsetof(CompactUnwindLayout, personality)) {
+ if (r.offset == cuOffsets.personality) {
cu.personality = r.referent.get();
- } else if (r.offset == offsetof(CompactUnwindLayout, lsda)) {
+ } else if (r.offset == cuOffsets.lsda) {
if (auto *referentSym = r.referent.dyn_cast())
cu.lsda = cast(referentSym)->isec;
else
@@ -316,7 +350,7 @@
// There should only be a handful of unique personality pointers, so we can
// encode them as 2-bit indices into a small array.
-template void UnwindInfoSectionImpl::encodePersonalities() {
+void UnwindInfoSectionImpl::encodePersonalities() {
for (size_t idx : cuIndices) {
CompactUnwindEntry &cu = cuEntries[idx];
if (cu.personality == nullptr)
@@ -366,7 +400,7 @@
// Scan the __LD,__compact_unwind entries and compute the space needs of
// __TEXT,__unwind_info and __TEXT,__eh_frame.
-template void UnwindInfoSectionImpl::finalize() {
+void UnwindInfoSectionImpl::finalize() {
if (symbols.empty())
return;
@@ -520,8 +554,7 @@
// All inputs are relocated and output addresses are known, so write!
-template
-void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
+void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const {
assert(!cuIndices.empty() && "call only if there is unwind info");
// section header
@@ -631,8 +664,5 @@
}
UnwindInfoSection *macho::makeUnwindInfoSection() {
- if (target->wordSize == 8)
- return make>();
- else
- return make>();
+ return make();
}