[lld] d6565a2 - [lld/mac] Add explicit "no unwind info" entries for functions without unwind info

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 22 03:12:54 PDT 2021


Author: Nico Weber
Date: 2021-06-22T06:12:42-04:00
New Revision: d6565a2dbcbe0932cd5cbb95bf2fc06855dfe938

URL: https://github.com/llvm/llvm-project/commit/d6565a2dbcbe0932cd5cbb95bf2fc06855dfe938
DIFF: https://github.com/llvm/llvm-project/commit/d6565a2dbcbe0932cd5cbb95bf2fc06855dfe938.diff

LOG: [lld/mac] Add explicit "no unwind info" entries for functions without unwind info

Fixes PR50529. With this, lld-linked Chromium base_unittests passes on arm macs.

Surprisingly, no measurable impact on link time.

Differential Revision: https://reviews.llvm.org/D104681

Added: 
    

Modified: 
    lld/MachO/UnwindInfoSection.cpp
    lld/test/MachO/compact-unwind.s
    lld/test/MachO/tools/validate-unwind-info.py

Removed: 
    


################################################################################
diff  --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index deeef18f0bb36..13be8565e861d 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -256,9 +256,9 @@ relocateCompactUnwind(ConcatOutputSection *compactUnwindSection,
 // There should only be a handful of unique personality pointers, so we can
 // encode them as 2-bit indices into a small array.
 template <class Ptr>
-void encodePersonalities(
-    const std::vector<CompactUnwindEntry<Ptr> *> &cuPtrVector,
-    std::vector<uint32_t> &personalities) {
+static void
+encodePersonalities(const std::vector<CompactUnwindEntry<Ptr> *> &cuPtrVector,
+                    std::vector<uint32_t> &personalities) {
   for (CompactUnwindEntry<Ptr> *cu : cuPtrVector) {
     if (cu->personality == 0)
       continue;
@@ -280,6 +280,40 @@ void encodePersonalities(
           ") for compact unwind to encode");
 }
 
+// __unwind_info stores unwind data for address ranges. If several
+// adjacent functions have the same unwind encoding, LSDA, and personality
+// function, they share one unwind entry. For this to work, functions without
+// unwind info need explicit "no unwind info" unwind entries -- else the
+// unwinder would think they have the unwind info of the closest function
+// with unwind info right before in the image.
+template <class Ptr>
+static void addEntriesForFunctionsWithoutUnwindInfo(
+    std::vector<CompactUnwindEntry<Ptr>> &cuVector) {
+  DenseSet<Ptr> hasUnwindInfo;
+  for (CompactUnwindEntry<Ptr> &cuEntry : cuVector)
+    if (cuEntry.functionAddress != UINT64_MAX)
+      hasUnwindInfo.insert(cuEntry.functionAddress);
+
+  // Add explicit "has no unwind info" entries for all global and local symbols
+  // without unwind info.
+  auto markNoUnwindInfo = [&cuVector, &hasUnwindInfo](const Defined *d) {
+    if (d->isLive() && isCodeSection(d->isec)) {
+      Ptr ptr = d->getVA();
+      if (!hasUnwindInfo.count(ptr))
+        cuVector.push_back({ptr, 0, 0, 0, 0});
+    }
+  };
+  for (Symbol *sym : symtab->getSymbols())
+    if (auto *d = dyn_cast<Defined>(sym))
+      markNoUnwindInfo(d);
+  for (const InputFile *file : inputFiles)
+    if (auto *objFile = dyn_cast<ObjFile>(file))
+      for (Symbol *sym : objFile->symbols)
+        if (auto *d = dyn_cast_or_null<Defined>(sym))
+          if (!d->isExternal())
+            markNoUnwindInfo(d);
+}
+
 // Scan the __LD,__compact_unwind entries and compute the space needs of
 // __TEXT,__unwind_info and __TEXT,__eh_frame
 template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
@@ -301,6 +335,8 @@ template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
   cuVector.resize(cuCount);
   relocateCompactUnwind(compactUnwindSection, cuVector);
 
+  addEntriesForFunctionsWithoutUnwindInfo(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);

diff  --git a/lld/test/MachO/compact-unwind.s b/lld/test/MachO/compact-unwind.s
index 1da965f2b3198..72aeaf85ffcba 100644
--- a/lld/test/MachO/compact-unwind.s
+++ b/lld/test/MachO/compact-unwind.s
@@ -33,7 +33,9 @@
 
 # CHECK:      SYMBOL TABLE:
 # CHECK-DAG:  [[#%x,MAIN:]]       g  F __TEXT,__text _main
+# CHECK-DAG:  [[#%x,QUUX:]]       g  F __TEXT,__text _quux
 # CHECK-DAG:  [[#%x,FOO:]]        l  F __TEXT,__text _foo
+# CHECK-DAG:  [[#%x,BAZ:]]        l  F __TEXT,__text _baz
 # CHECK-DAG:  [[#%x,EXCEPTION0:]] g  O __TEXT,__gcc_except_tab _exception0
 # CHECK-DAG:  [[#%x,EXCEPTION1:]] g  O __TEXT,__gcc_except_tab _exception1
 
@@ -44,6 +46,11 @@
 # CHECK:        LSDA descriptors:
 # 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:        Second level indices:
+# CHECK-DAG:     function offset=0x[[#%.8x,MAIN-BASE]], encoding
+# CHECK-DAG:     function offset=0x[[#%.8x,FOO-BASE]], encoding
+# CHECK-DAG:     function offset=0x[[#%.8x,BAZ-BASE]], encoding
+# CHECK-DAG:     function offset=0x[[#%.8x,QUUX-BASE]], encoding{{.*}}=0x00000000
 
 ## Check that we do not add rebase opcodes to the compact unwind section.
 # CHECK:      Rebase table:
@@ -83,7 +90,7 @@ _exception0:
   .space 1
 
 #--- main.s
-.globl _main, _my_personality, _exception1
+.globl _main, _quux, _my_personality, _exception1
 
 .text
 .p2align 2
@@ -95,6 +102,14 @@ _main:
   ret
   .cfi_endproc
 
+## _quux has no unwind information.
+## (In real life, it'd be part of a separate TU that was built with
+## -fno-exceptions, while the previous and next TU might be Objective-C++
+## which has unwind info for Objective-C).
+.p2align 2
+_quux:
+  ret
+
 .p2align 2
 _baz:
   .cfi_startproc

diff  --git a/lld/test/MachO/tools/validate-unwind-info.py b/lld/test/MachO/tools/validate-unwind-info.py
index 9f1b726124d98..592751ca39f6b 100755
--- a/lld/test/MachO/tools/validate-unwind-info.py
+++ b/lld/test/MachO/tools/validate-unwind-info.py
@@ -37,9 +37,12 @@ def main():
   if not object_encodings_map:
     sys.exit("no object encodings found in input")
 
+  # generate-cfi-funcs.py doesn't generate unwind info for _main.
+  object_encodings_map['_main'] = '00000000'
+
   program_symbols_map = {address:symbol
     for address, symbol in
-    re.findall(r"^%s(%s) g\s+F __TEXT,__text (x\1)$" % (hex8, hex8),
+    re.findall(r"^%s(%s) g\s+F __TEXT,__text (x\1|_main)$" % (hex8, hex8),
                objdump_string, re.MULTILINE)}
   if not program_symbols_map:
     sys.exit("no program symbols found in input")


        


More information about the llvm-commits mailing list