[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