[lld] 1460942 - [lld-macho] Add 32-bit compact unwind support
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 15 18:16:50 PDT 2021
Author: Jez Ng
Date: 2021-04-15T21:16:33-04:00
New Revision: 1460942c15a71f5e9ad55344c0e17771ea0ecb57
URL: https://github.com/llvm/llvm-project/commit/1460942c15a71f5e9ad55344c0e17771ea0ecb57
DIFF: https://github.com/llvm/llvm-project/commit/1460942c15a71f5e9ad55344c0e17771ea0ecb57.diff
LOG: [lld-macho] Add 32-bit compact unwind support
This could probably have been part of D99633, but I split it up to make
things a bit more reviewable. I also fixed some bugs in the implementation that
were masked through integer underflows when operating in 64-bit mode.
Reviewed By: #lld-macho, gkm
Differential Revision: https://reviews.llvm.org/D99823
Added:
Modified:
lld/MachO/Relocations.h
lld/MachO/SyntheticSections.h
lld/MachO/UnwindInfoSection.cpp
lld/MachO/UnwindInfoSection.h
lld/MachO/Writer.cpp
lld/test/MachO/compact-unwind.s
Removed:
################################################################################
diff --git a/lld/MachO/Relocations.h b/lld/MachO/Relocations.h
index 6d31d27ec832..91b2d00f26a1 100644
--- a/lld/MachO/Relocations.h
+++ b/lld/MachO/Relocations.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Support/Endian.h"
#include <cstddef>
#include <cstdint>
@@ -93,6 +94,19 @@ inline void checkUInt(Diagnostic d, uint64_t v, int bits) {
reportRangeError(d, llvm::Twine(v), bits, 0, llvm::maxUIntN(bits));
}
+inline void writeAddress(uint8_t *loc, uint64_t addr, uint8_t length) {
+ switch (length) {
+ case 2:
+ llvm::support::endian::write32le(loc, addr);
+ break;
+ case 3:
+ llvm::support::endian::write64le(loc, addr);
+ break;
+ default:
+ llvm_unreachable("invalid r_length");
+ }
+}
+
extern const RelocAttrs invalidRelocAttrs;
} // namespace macho
diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index eaad8aa3455f..38d966e61825 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -32,6 +32,7 @@ class Defined;
class DylibSymbol;
class LoadCommand;
class ObjFile;
+class UnwindInfoSection;
class SyntheticSection : public OutputSection {
public:
@@ -503,6 +504,7 @@ struct InStruct {
StubsSection *stubs = nullptr;
StubHelperSection *stubHelper = nullptr;
ImageLoaderCacheSection *imageLoaderCache = nullptr;
+ UnwindInfoSection *unwindInfo = nullptr;
};
extern InStruct in;
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 52abdc6b0400..b94642404091 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -91,31 +91,62 @@ using namespace lld::macho;
// TODO(gkm): prune __eh_frame entries superseded by __unwind_info
// TODO(gkm): how do we align the 2nd-level pages?
-UnwindInfoSection::UnwindInfoSection()
- : SyntheticSection(segment_names::text, section_names::unwindInfo) {
- align = 4; // mimic ld64
-}
-
-bool UnwindInfoSection::isNeeded() const {
- return (compactUnwindSection != nullptr);
-}
-
-SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *>
- personalityTable;
+using EncodingMap = llvm::DenseMap<compact_unwind_encoding_t, size_t>;
+
+template <class Ptr> struct CompactUnwindEntry {
+ Ptr functionAddress;
+ uint32_t functionLength;
+ compact_unwind_encoding_t encoding;
+ Ptr personality;
+ Ptr lsda;
+};
+
+struct SecondLevelPage {
+ uint32_t kind;
+ size_t entryIndex;
+ size_t entryCount;
+ size_t byteCount;
+ std::vector<compact_unwind_encoding_t> localEncodings;
+ EncodingMap localEncodingIndexes;
+};
+
+template <class Ptr> class UnwindInfoSectionImpl : public UnwindInfoSection {
+public:
+ void prepareRelocations(InputSection *) override;
+ void finalize() override;
+ void writeTo(uint8_t *buf) const override;
+
+private:
+ std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;
+ EncodingMap commonEncodingIndexes;
+ // Indices of personality functions within the GOT.
+ std::vector<uint32_t> personalities;
+ SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *>
+ personalityTable;
+ std::vector<unwind_info_section_header_lsda_index_entry> lsdaEntries;
+ // Map of function offset (from the image base) to an index within the LSDA
+ // array.
+ llvm::DenseMap<uint32_t, uint32_t> functionToLsdaIndex;
+ std::vector<CompactUnwindEntry<Ptr>> cuVector;
+ std::vector<CompactUnwindEntry<Ptr> *> cuPtrVector;
+ std::vector<SecondLevelPage> secondLevelPages;
+ uint64_t level2PagesOffset = 0;
+};
// Compact unwind relocations have
diff erent 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.
-void macho::prepareCompactUnwind(InputSection *isec) {
+template <class Ptr>
+void UnwindInfoSectionImpl<Ptr>::prepareRelocations(InputSection *isec) {
assert(isec->segname == segment_names::ld &&
isec->name == section_names::compactUnwind);
for (Reloc &r : isec->relocs) {
assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED));
- if (r.offset % sizeof(CompactUnwindEntry64) !=
- offsetof(struct CompactUnwindEntry64, personality))
+ if (r.offset % sizeof(CompactUnwindEntry<Ptr>) !=
+ offsetof(CompactUnwindEntry<Ptr>, personality))
continue;
if (auto *s = r.referent.dyn_cast<Symbol *>()) {
@@ -172,8 +203,10 @@ static void checkTextSegment(InputSection *isec) {
// 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.
-static void relocateCompactUnwind(MergedOutputSection *compactUnwindSection,
- std::vector<CompactUnwindEntry64> &cuVector) {
+template <class Ptr>
+static void
+relocateCompactUnwind(MergedOutputSection *compactUnwindSection,
+ std::vector<CompactUnwindEntry<Ptr>> &cuVector) {
for (const InputSection *isec : compactUnwindSection->inputs) {
uint8_t *buf =
reinterpret_cast<uint8_t *>(cuVector.data()) + isec->outSecFileOff;
@@ -195,21 +228,23 @@ static void relocateCompactUnwind(MergedOutputSection *compactUnwindSection,
checkTextSegment(referentIsec);
referentVA = referentIsec->getVA() + r.addend;
}
- support::endian::write64le(buf + r.offset, referentVA);
+
+ writeAddress(buf + r.offset, referentVA, r.length);
}
}
}
// There should only be a handful of unique personality pointers, so we can
// encode them as 2-bit indices into a small array.
-void encodePersonalities(const std::vector<CompactUnwindEntry64 *> &cuPtrVector,
- std::vector<uint32_t> &personalities) {
- for (CompactUnwindEntry64 *cu : cuPtrVector) {
+template <class Ptr>
+void encodePersonalities(
+ const std::vector<CompactUnwindEntry<Ptr> *> &cuPtrVector,
+ std::vector<uint32_t> &personalities) {
+ for (CompactUnwindEntry<Ptr> *cu : cuPtrVector) {
if (cu->personality == 0)
continue;
- uint32_t personalityOffset = cu->personality - in.header->addr;
// Linear search is fast enough for a small array.
- auto it = find(personalities, personalityOffset);
+ auto it = find(personalities, cu->personality);
uint32_t personalityIndex; // 1-based index
if (it != personalities.end()) {
personalityIndex = std::distance(personalities.begin(), it) + 1;
@@ -228,7 +263,7 @@ void encodePersonalities(const std::vector<CompactUnwindEntry64 *> &cuPtrVector,
// Scan the __LD,__compact_unwind entries and compute the space needs of
// __TEXT,__unwind_info and __TEXT,__eh_frame
-void UnwindInfoSection::finalize() {
+template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
if (compactUnwindSection == nullptr)
return;
@@ -240,21 +275,23 @@ void UnwindInfoSection::finalize() {
// encoding+personality+lsda. Folding is necessary because it reduces
// the number of CU entries by as much as 3 orders of magnitude!
compactUnwindSection->finalize();
- assert(compactUnwindSection->getSize() % sizeof(CompactUnwindEntry64) == 0);
+ assert(compactUnwindSection->getSize() % sizeof(CompactUnwindEntry<Ptr>) ==
+ 0);
size_t cuCount =
- compactUnwindSection->getSize() / sizeof(CompactUnwindEntry64);
+ compactUnwindSection->getSize() / sizeof(CompactUnwindEntry<Ptr>);
cuVector.resize(cuCount);
relocateCompactUnwind(compactUnwindSection, cuVector);
// Rather than sort & fold the 32-byte entries directly, we create a
// vector of pointers to entries and sort & fold that instead.
cuPtrVector.reserve(cuCount);
- for (CompactUnwindEntry64 &cuEntry : cuVector)
+ for (CompactUnwindEntry<Ptr> &cuEntry : cuVector)
cuPtrVector.emplace_back(&cuEntry);
- std::sort(cuPtrVector.begin(), cuPtrVector.end(),
- [](const CompactUnwindEntry64 *a, const CompactUnwindEntry64 *b) {
- return a->functionAddress < b->functionAddress;
- });
+ std::sort(
+ cuPtrVector.begin(), cuPtrVector.end(),
+ [](const CompactUnwindEntry<Ptr> *a, const CompactUnwindEntry<Ptr> *b) {
+ return a->functionAddress < b->functionAddress;
+ });
// Fold adjacent entries with matching encoding+personality+lsda
// We use three iterators on the same cuPtrVector to fold in-situ:
@@ -280,7 +317,7 @@ void UnwindInfoSection::finalize() {
// Count frequencies of the folded encodings
EncodingMap encodingFrequencies;
- for (const CompactUnwindEntry64 *cuPtrEntry : cuPtrVector)
+ for (const CompactUnwindEntry<Ptr> *cuPtrEntry : cuPtrVector)
encodingFrequencies[cuPtrEntry->encoding]++;
// Make a vector of encodings, sorted by descending frequency
@@ -316,7 +353,7 @@ void UnwindInfoSection::finalize() {
// If more entries fit in the regular format, we use that.
for (size_t i = 0; i < cuPtrVector.size();) {
secondLevelPages.emplace_back();
- UnwindInfoSection::SecondLevelPage &page = secondLevelPages.back();
+ SecondLevelPage &page = secondLevelPages.back();
page.entryIndex = i;
uintptr_t functionAddressMax =
cuPtrVector[i]->functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK;
@@ -326,7 +363,7 @@ void UnwindInfoSection::finalize() {
sizeof(unwind_info_compressed_second_level_page_header) /
sizeof(uint32_t);
while (wordsRemaining >= 1 && i < cuPtrVector.size()) {
- const CompactUnwindEntry64 *cuPtr = cuPtrVector[i];
+ const CompactUnwindEntry<Ptr> *cuPtr = cuPtrVector[i];
if (cuPtr->functionAddress >= functionAddressMax) {
break;
} else if (commonEncodingIndexes.count(cuPtr->encoding) ||
@@ -359,7 +396,7 @@ void UnwindInfoSection::finalize() {
}
}
- for (const CompactUnwindEntry64 *cu : cuPtrVector) {
+ for (const CompactUnwindEntry<Ptr> *cu : cuPtrVector) {
uint32_t functionOffset = cu->functionAddress - in.header->addr;
functionToLsdaIndex[functionOffset] = lsdaEntries.size();
if (cu->lsda != 0)
@@ -382,7 +419,8 @@ void UnwindInfoSection::finalize() {
// All inputs are relocated and output addresses are known, so write!
-void UnwindInfoSection::writeTo(uint8_t *buf) const {
+template <class Ptr>
+void UnwindInfoSectionImpl<Ptr>::writeTo(uint8_t *buf) const {
// section header
auto *uip = reinterpret_cast<unwind_info_section_header *>(buf);
uip->version = 1;
@@ -403,7 +441,8 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
// Personalities
for (const uint32_t &personality : personalities)
- *i32p++ = in.got->addr + (personality - 1) * target->wordSize;
+ *i32p++ =
+ in.got->addr + (personality - 1) * target->wordSize - in.header->addr;
// Level-1 index
uint32_t lsdaOffset =
@@ -422,7 +461,7 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
l2PagesOffset += SECOND_LEVEL_PAGE_BYTES;
}
// Level-1 sentinel
- const CompactUnwindEntry64 &cuEnd = cuVector.back();
+ const CompactUnwindEntry<Ptr> &cuEnd = cuVector.back();
iep->functionOffset = cuEnd.functionAddress + cuEnd.functionLength;
iep->secondLevelPagesSectionOffset = 0;
iep->lsdaIndexArraySectionOffset =
@@ -455,7 +494,7 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
p2p->encodingsCount = page.localEncodings.size();
auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);
for (size_t i = 0; i < page.entryCount; i++) {
- const CompactUnwindEntry64 *cuep = cuPtrVector[page.entryIndex + i];
+ const CompactUnwindEntry<Ptr> *cuep = cuPtrVector[page.entryIndex + i];
auto it = commonEncodingIndexes.find(cuep->encoding);
if (it == commonEncodingIndexes.end())
it = page.localEncodingIndexes.find(cuep->encoding);
@@ -474,7 +513,7 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
p2p->entryCount = page.entryCount;
auto *ep = reinterpret_cast<uint32_t *>(&p2p[1]);
for (size_t i = 0; i < page.entryCount; i++) {
- const CompactUnwindEntry64 *cuep = cuPtrVector[page.entryIndex + i];
+ const CompactUnwindEntry<Ptr> *cuep = cuPtrVector[page.entryIndex + i];
*ep++ = cuep->functionAddress;
*ep++ = cuep->encoding;
}
@@ -482,3 +521,10 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
pp += SECOND_LEVEL_PAGE_WORDS;
}
}
+
+UnwindInfoSection *macho::makeUnwindInfoSection() {
+ if (target->wordSize == 8)
+ return make<UnwindInfoSectionImpl<uint64_t>>();
+ else
+ return make<UnwindInfoSectionImpl<uint32_t>>();
+}
diff --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h
index 1368625c291d..a33cd381a36e 100644
--- a/lld/MachO/UnwindInfoSection.h
+++ b/lld/MachO/UnwindInfoSection.h
@@ -17,66 +17,30 @@
#include <vector>
-// In 2020, we mostly care about 64-bit targets: x86_64 and arm64
-struct CompactUnwindEntry64 {
- uint64_t functionAddress;
- uint32_t functionLength;
- compact_unwind_encoding_t encoding;
- uint64_t personality;
- uint64_t lsda;
-};
-
-// FIXME(gkm): someday we might care about 32-bit targets: x86 & arm
-struct CompactUnwindEntry32 {
- uint32_t functionAddress;
- uint32_t functionLength;
- compact_unwind_encoding_t encoding;
- uint32_t personality;
- uint32_t lsda;
-};
-
namespace lld {
namespace macho {
class UnwindInfoSection : public SyntheticSection {
public:
- UnwindInfoSection();
+ bool isNeeded() const override { return compactUnwindSection != nullptr; }
uint64_t getSize() const override { return unwindInfoSize; }
- bool isNeeded() const override;
- void finalize() override;
- void writeTo(uint8_t *buf) const override;
+ virtual void prepareRelocations(InputSection *) = 0;
+
void setCompactUnwindSection(MergedOutputSection *cuSection) {
compactUnwindSection = cuSection;
}
- using EncodingMap = llvm::DenseMap<compact_unwind_encoding_t, size_t>;
-
- struct SecondLevelPage {
- uint32_t kind;
- size_t entryIndex;
- size_t entryCount;
- size_t byteCount;
- std::vector<compact_unwind_encoding_t> localEncodings;
- EncodingMap localEncodingIndexes;
- };
+protected:
+ UnwindInfoSection()
+ : SyntheticSection(segment_names::text, section_names::unwindInfo) {
+ align = 4;
+ }
-private:
- std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;
- EncodingMap commonEncodingIndexes;
- // Indices of personality functions within the GOT.
- std::vector<uint32_t> personalities;
- std::vector<unwind_info_section_header_lsda_index_entry> lsdaEntries;
- // Map of function offset (from the image base) to an index within the LSDA
- // array.
- llvm::DenseMap<uint32_t, uint32_t> functionToLsdaIndex;
- std::vector<CompactUnwindEntry64> cuVector;
- std::vector<CompactUnwindEntry64 *> cuPtrVector;
- std::vector<SecondLevelPage> secondLevelPages;
MergedOutputSection *compactUnwindSection = nullptr;
- uint64_t level2PagesOffset = 0;
uint64_t unwindInfoSize = 0;
};
+UnwindInfoSection *makeUnwindInfoSection();
void prepareCompactUnwind(InputSection *isec);
} // namespace macho
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 60fd5a9c647f..9afe73d872d2 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -71,7 +71,6 @@ class Writer {
SymtabSection *symtabSection = nullptr;
IndirectSymtabSection *indirectSymtabSection = nullptr;
CodeSignatureSection *codeSignatureSection = nullptr;
- UnwindInfoSection *unwindInfoSection = nullptr;
FunctionStartsSection *functionStartsSection = nullptr;
LCUuid *uuidCommand = nullptr;
@@ -517,7 +516,7 @@ void Writer::scanRelocations() {
TimeTraceScope timeScope("Scan relocations");
for (InputSection *isec : inputSections) {
if (isec->segname == segment_names::ld) {
- prepareCompactUnwind(isec);
+ in.unwindInfo->prepareRelocations(isec);
continue;
}
@@ -798,7 +797,6 @@ template <class LP> void Writer::createOutputSections() {
TimeTraceScope timeScope("Create output sections");
// First, create hidden sections
stringTableSection = make<StringTableSection>();
- unwindInfoSection = make<UnwindInfoSection>(); // TODO(gkm): only when no -r
symtabSection = makeSymtabSection<LP>(*stringTableSection);
indirectSymtabSection = make<IndirectSymtabSection>();
if (config->adhocCodesign)
@@ -830,9 +828,9 @@ template <class LP> void Writer::createOutputSections() {
for (const auto &it : mergedOutputSections) {
StringRef segname = it.first.first;
MergedOutputSection *osec = it.second;
- if (unwindInfoSection && segname == segment_names::ld) {
+ if (segname == segment_names::ld) {
assert(osec->name == section_names::compactUnwind);
- unwindInfoSection->setCompactUnwindSection(osec);
+ in.unwindInfo->setCompactUnwindSection(osec);
} else {
getOrCreateOutputSegment(segname)->addOutputSection(osec);
}
@@ -993,6 +991,7 @@ template <class LP> void macho::createSyntheticSections() {
in.stubs = make<StubsSection>();
in.stubHelper = make<StubHelperSection>();
in.imageLoaderCache = make<ImageLoaderCacheSection>();
+ in.unwindInfo = makeUnwindInfoSection();
}
OutputSection *macho::firstTLVDataSection = nullptr;
diff --git a/lld/test/MachO/compact-unwind.s b/lld/test/MachO/compact-unwind.s
index 1d65d41964e0..1da965f2b319 100644
--- a/lld/test/MachO/compact-unwind.s
+++ b/lld/test/MachO/compact-unwind.s
@@ -3,16 +3,23 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/my-personality.s -o %t/x86_64-my-personality.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/main.s -o %t/x86_64-main.o
# RUN: %lld -arch x86_64 -pie -lSystem -lc++ %t/x86_64-my-personality.o %t/x86_64-main.o -o %t/x86_64-personality-first
-# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x100000000
# RUN: %lld -arch x86_64 -pie -lSystem -lc++ %t/x86_64-main.o %t/x86_64-my-personality.o -o %t/x86_64-personality-second
-# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x100000000
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin19.0.0 %t/my-personality.s -o %t/arm64-my-personality.o
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin19.0.0 %t/main.s -o %t/arm64-main.o
# RUN: %lld -arch arm64 -pie -lSystem -lc++ %t/arm64-my-personality.o %t/arm64-main.o -o %t/arm64-personality-first
-# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x100000000
# RUN: %lld -arch arm64 -pie -lSystem -lc++ %t/arm64-main.o %t/arm64-my-personality.o -o %t/arm64-personality-second
-# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x100000000
+
+# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/my-personality.s -o %t/arm64-32-my-personality.o
+# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/main.s -o %t/arm64-32-main.o
+# RUN: %lld-watchos -pie -lSystem -lc++ %t/arm64-32-my-personality.o %t/arm64-32-main.o -o %t/arm64-32-personality-first
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-32-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x4000
+# RUN: %lld-watchos -pie -lSystem -lc++ %t/arm64-32-main.o %t/arm64-32-my-personality.o -o %t/arm64-32-personality-second
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-32-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x4000
# FIRST: Indirect symbols for (__DATA_CONST,__got)
# FIRST-NEXT: address index name
@@ -32,16 +39,16 @@
# CHECK: Contents of __unwind_info section:
# CHECK: Personality functions: (count = 2)
-# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#MY_PERSONALITY-0x100000000]]
-# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#GXX_PERSONALITY-0x100000000]]
+# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#MY_PERSONALITY-BASE]]
+# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#GXX_PERSONALITY-BASE]]
# CHECK: LSDA descriptors:
-# CHECK-DAG: function offset=0x{{0*}}[[#FOO-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION0-0x100000000]]
-# CHECK-DAG: function offset=0x{{0*}}[[#MAIN-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION1-0x100000000]]
+# CHECK-DAG: function offset=0x[[#%.8x,FOO-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION0-BASE]]
+# CHECK-DAG: function offset=0x[[#%.8x,MAIN-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION1-BASE]]
## Check that we do not add rebase opcodes to the compact unwind section.
# CHECK: Rebase table:
# CHECK-NEXT: segment section address type
-# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9a-f]*}} pointer
+# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9A-F]*}} pointer
# CHECK-NOT: __TEXT
#--- my-personality.s
More information about the llvm-commits
mailing list