[lld] 5112035 - [lld-macho] Emit LSDA info in compact unwind
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 8 10:48:16 PST 2021
Author: Jez Ng
Date: 2021-02-08T13:48:00-05:00
New Revision: 51120357510949fe33cec85b088e1e8a1f46de3f
URL: https://github.com/llvm/llvm-project/commit/51120357510949fe33cec85b088e1e8a1f46de3f
DIFF: https://github.com/llvm/llvm-project/commit/51120357510949fe33cec85b088e1e8a1f46de3f.diff
LOG: [lld-macho] Emit LSDA info in compact unwind
The LSDA pointers are encoded as offsets from the image base,
and arranged in one big contiguous array. Each second-level page records
the offset within that LSDA array which corresponds to the LSDA for its
first CU entry.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D95810
Added:
Modified:
lld/MachO/UnwindInfoSection.cpp
lld/MachO/UnwindInfoSection.h
lld/test/MachO/compact-unwind.s
Removed:
################################################################################
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 7df8a8b62713..73fb50573ce7 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -341,6 +341,14 @@ void UnwindInfoSection::finalize() {
}
}
+ for (const CompactUnwindEntry64 *cu : cuPtrVector) {
+ uint32_t functionOffset = cu->functionAddress - in.header->addr;
+ functionToLsdaIndex[functionOffset] = lsdaEntries.size();
+ if (cu->lsda != 0)
+ lsdaEntries.push_back(
+ {functionOffset, static_cast<uint32_t>(cu->lsda - in.header->addr)});
+ }
+
// compute size of __TEXT,__unwind_info section
level2PagesOffset =
sizeof(unwind_info_section_header) +
@@ -386,9 +394,12 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
uint64_t l2PagesOffset = level2PagesOffset;
auto *iep = reinterpret_cast<unwind_info_section_header_index_entry *>(i32p);
for (const SecondLevelPage &page : secondLevelPages) {
- iep->functionOffset = cuPtrVector[page.entryIndex]->functionAddress;
+ iep->functionOffset =
+ cuPtrVector[page.entryIndex]->functionAddress - in.header->addr;
iep->secondLevelPagesSectionOffset = l2PagesOffset;
- iep->lsdaIndexArraySectionOffset = lsdaOffset;
+ iep->lsdaIndexArraySectionOffset =
+ lsdaOffset + functionToLsdaIndex.lookup(iep->functionOffset) *
+ sizeof(unwind_info_section_header_lsda_index_entry);
iep++;
l2PagesOffset += SECOND_LEVEL_PAGE_BYTES;
}
@@ -396,19 +407,19 @@ void UnwindInfoSection::writeTo(uint8_t *buf) const {
const CompactUnwindEntry64 &cuEnd = cuVector.back();
iep->functionOffset = cuEnd.functionAddress + cuEnd.functionLength;
iep->secondLevelPagesSectionOffset = 0;
- iep->lsdaIndexArraySectionOffset = lsdaOffset;
+ iep->lsdaIndexArraySectionOffset =
+ lsdaOffset +
+ lsdaEntries.size() * sizeof(unwind_info_section_header_lsda_index_entry);
iep++;
// LSDAs
- auto *lep =
- reinterpret_cast<unwind_info_section_header_lsda_index_entry *>(iep);
- for (const unwind_info_section_header_lsda_index_entry &lsda : lsdaEntries) {
- lep->functionOffset = lsda.functionOffset;
- lep->lsdaOffset = lsda.lsdaOffset;
- }
+ size_t lsdaBytes =
+ lsdaEntries.size() * sizeof(unwind_info_section_header_lsda_index_entry);
+ memcpy(iep, lsdaEntries.data(), lsdaBytes);
// Level-2 pages
- auto *pp = reinterpret_cast<uint32_t *>(lep);
+ auto *pp = reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(iep) +
+ lsdaBytes);
for (const SecondLevelPage &page : secondLevelPages) {
if (page.kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
uintptr_t functionAddressBase =
diff --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h
index ebc5c5ca1cc4..1368625c291d 100644
--- a/lld/MachO/UnwindInfoSection.h
+++ b/lld/MachO/UnwindInfoSection.h
@@ -66,6 +66,9 @@ class UnwindInfoSection : public SyntheticSection {
// 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;
diff --git a/lld/test/MachO/compact-unwind.s b/lld/test/MachO/compact-unwind.s
index cd9c07afcc7e..6cddda9adfc9 100644
--- a/lld/test/MachO/compact-unwind.s
+++ b/lld/test/MachO/compact-unwind.s
@@ -1,17 +1,26 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %s -o %t.o
# RUN: %lld -pie -lSystem -lc++ %t.o -o %t
-# RUN: llvm-objdump --macho --unwind-info --indirect-symbols --rebase %t | FileCheck %s
+# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t | FileCheck %s
# CHECK: Indirect symbols for (__DATA_CONST,__got)
# CHECK-NEXT: address index name
# CHECK-DAG: 0x[[#%x,GXX_PERSONALITY:]] [[#]] ___gxx_personality_v0
# CHECK-DAG: 0x[[#%x,MY_PERSONALITY:]] LOCAL
+# CHECK: SYMBOL TABLE:
+# CHECK-DAG: [[#%x,MAIN:]] g F __TEXT,__text _main
+# CHECK-DAG: [[#%x,FOO:]] g F __TEXT,__text _foo
+# CHECK-DAG: [[#%x,EXCEPTION0:]] g O __TEXT,__gcc_except_tab _exception0
+# CHECK-DAG: [[#%x,EXCEPTION1:]] g O __TEXT,__gcc_except_tab _exception1
+
# CHECK: Contents of __unwind_info section:
# CHECK: Personality functions: (count = 2)
# CHECK-NEXT: personality[1]: 0x{{0*}}[[#MY_PERSONALITY-0x100000000]]
# CHECK-NEXT: personality[2]: 0x{{0*}}[[#GXX_PERSONALITY-0x100000000]]
+# CHECK: LSDA descriptors:
+# CHECK-NEXT: [0]: function offset=0x{{0*}}[[#FOO-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION0-0x100000000]]
+# CHECK-NEXT: [1]: function offset=0x{{0*}}[[#MAIN-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION1-0x100000000]]
## Check that we do not add rebase opcodes to the compact unwind section.
# CHECK: Rebase table:
@@ -20,12 +29,13 @@
# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9a-f]*}} pointer
# CHECK-EMPTY:
-.globl _main, _foo, _my_personality, _bar
+.globl _main, _foo, _my_personality, _bar, _exception0, _exception1
.text
_foo:
.cfi_startproc
.cfi_personality 155, _my_personality
+ .cfi_lsda 16, _exception0
.cfi_def_cfa_offset 16
retq
.cfi_endproc
@@ -34,6 +44,7 @@ _bar:
.cfi_startproc
## Check that we dedup references to the same statically-linked personality.
.cfi_personality 155, _my_personality
+ .cfi_lsda 16, _exception0
.cfi_def_cfa_offset 16
retq
.cfi_endproc
@@ -41,9 +52,16 @@ _bar:
_main:
.cfi_startproc
.cfi_personality 155, ___gxx_personality_v0
+ .cfi_lsda 16, _exception1
.cfi_def_cfa_offset 16
retq
.cfi_endproc
_my_personality:
retq
+
+.section __TEXT,__gcc_except_tab
+_exception0:
+ .space 1
+_exception1:
+ .space 1
More information about the llvm-commits
mailing list