[lld] r223103 - [mach-o] add support for arm64 compact unwind info

Nick Kledzik kledzik at apple.com
Mon Dec 1 17:50:40 PST 2014


Author: kledzik
Date: Mon Dec  1 19:50:38 2014
New Revision: 223103

URL: http://llvm.org/viewvc/llvm-project?rev=223103&view=rev
Log:
[mach-o] add support for arm64 compact unwind info

Tim previously added generic compact unwind processing and x86_64 support.
This patch adds arm64 support.

Added:
    lld/trunk/test/mach-o/unwind-info-simple-arm64.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=223103&r1=223102&r2=223103&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Mon Dec  1 19:50:38 2014
@@ -51,6 +51,9 @@ public:
     case gotOffset12:
       canBypassGOT = true;
       return true;
+    case imageOffsetGot:
+      canBypassGOT = false;
+      return true;
     default:
       return false;
     }
@@ -72,6 +75,9 @@ public:
       const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
                                                  offset12scale8 : addOffset12);
       break;
+    case imageOffsetGot:
+      const_cast<Reference *>(ref)->setKindValue(imageOffset);
+      break;
     default:
       llvm_unreachable("Not a GOT reference");
     }
@@ -88,30 +94,29 @@ public:
   bool isPairedReloc(const normalized::Relocation &) override;
 
   bool needsCompactUnwind() override {
-    return false;
+    return true;
   }
   Reference::KindValue imageOffsetKind() override {
-    return invalid;
+    return imageOffset;
   }
   Reference::KindValue imageOffsetKindIndirect() override {
-    return invalid;
+    return imageOffsetGot;
   }
 
   Reference::KindValue unwindRefToCIEKind() override {
-    return invalid;
+    return negDelta32;
   }
 
   Reference::KindValue unwindRefToFunctionKind() override {
-    return invalid;
+    return unwindFDEToFunction;
   }
 
   Reference::KindValue unwindRefToEhFrameKind() override {
-    return invalid;
+    return unwindInfoToEhFrame;
   }
 
   uint32_t dwarfCompactUnwindType() override {
-    // FIXME
-    return -1;
+    return 0x03000000;
   }
 
   std::error_code getReferenceInfo(const normalized::Relocation &reloc,
@@ -176,6 +181,7 @@ private:
     pointer64,             /// ex: .quad _foo
     delta64,               /// ex: .quad _foo - .
     delta32,               /// ex: .long _foo - .
+    negDelta32,            /// ex: .long . - _foo
     pointer64ToGOT,        /// ex: .quad _foo at GOT
     delta32ToGOT,          /// ex: .long _foo at GOT - .
 
@@ -183,11 +189,19 @@ private:
     addOffset12,           /// Location contains LDR to change into ADD.
     lazyPointer,           /// Location contains a lazy pointer.
     lazyImmediateLocation, /// Location contains immediate value used in stub.
+    imageOffset,           /// Location contains offset of atom in final image
+    imageOffsetGot,        /// Location contains offset of GOT entry for atom in
+                           /// final image (typically personality function).
+    unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
+                           /// relocatable object (yay for implicit contracts!).
+    unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
+                           /// refer to __eh_frame entry.
   };
 
   void applyFixupFinal(const Reference &ref, uint8_t *location,
                        uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress);
+                       uint64_t inAtomAddress, uint64_t imageBaseAddress,
+                       FindAddressForAtom findSectionAddress);
 
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
                              uint64_t fixupAddress, uint64_t targetAddress,
@@ -220,12 +234,17 @@ const Registry::KindStrings ArchHandler_
   LLD_KIND_STRING_ENTRY(pointer64),
   LLD_KIND_STRING_ENTRY(delta64),
   LLD_KIND_STRING_ENTRY(delta32),
+  LLD_KIND_STRING_ENTRY(negDelta32),
   LLD_KIND_STRING_ENTRY(pointer64ToGOT),
   LLD_KIND_STRING_ENTRY(delta32ToGOT),
 
   LLD_KIND_STRING_ENTRY(addOffset12),
   LLD_KIND_STRING_ENTRY(lazyPointer),
   LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
+  LLD_KIND_STRING_ENTRY(imageOffset),
+  LLD_KIND_STRING_ENTRY(imageOffsetGot),
+  LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
+  LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
 
   LLD_KIND_STRING_END
 };
@@ -498,7 +517,8 @@ void ArchHandler_arm64::generateAtomCont
                             targetAddress, atomAddress, targetUnnamed);
     } else {
       applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
-                      targetAddress, atomAddress);
+                      targetAddress, atomAddress, imageBaseAddress,
+                      findSectionAddress);
     }
   }
 }
@@ -506,7 +526,9 @@ void ArchHandler_arm64::generateAtomCont
 void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
                                         uint64_t fixupAddress,
                                         uint64_t targetAddress,
-                                        uint64_t inAtomAddress) {
+                                        uint64_t inAtomAddress,
+                                        uint64_t imageBaseAddress,
+                                        FindAddressForAtom findSectionAddress) {
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
   assert(ref.kindArch() == Reference::KindArch::AArch64);
@@ -515,6 +537,7 @@ void ArchHandler_arm64::applyFixupFinal(
   int32_t displacement;
   uint32_t instruction;
   uint32_t value32;
+  uint32_t value64;
   switch (static_cast<Arm64_Kinds>(ref.kindValue())) {
   case branch26:
     displacement = (targetAddress - fixupAddress) + ref.addend();
@@ -571,18 +594,33 @@ void ArchHandler_arm64::applyFixupFinal(
     *loc64 = targetAddress + ref.addend();
     return;
   case delta64:
+  case unwindFDEToFunction:
     *loc64 = (targetAddress - fixupAddress) + ref.addend();
     return;
   case delta32:
   case delta32ToGOT:
     *loc32 = (targetAddress - fixupAddress) + ref.addend();
     return;
+  case negDelta32:
+    *loc32 = fixupAddress - targetAddress + ref.addend();
+    return;
   case lazyPointer:
     // Do nothing
     return;
   case lazyImmediateLocation:
     *loc32 = ref.addend();
     return;
+  case imageOffset:
+    *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
+    return;
+  case imageOffsetGot:
+    llvm_unreachable("imageOffsetGot should have been changed to imageOffset");
+    break;
+  case unwindInfoToEhFrame:
+    value64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
+    assert(value64 < 0xffffffU && "offset in __eh_frame too large");
+    *loc32 = (*loc32 & 0xff000000U) | value64;
+    return;
   case invalid:
     // Fall into llvm_unreachable().
     break;
@@ -631,6 +669,9 @@ void ArchHandler_arm64::applyFixupReloca
   case delta32:
     *loc32 = ref.addend() + inAtomAddress - fixupAddress;
     return;
+  case negDelta32:
+    *loc32 = fixupAddress - inAtomAddress + ref.addend();
+    return;
   case pointer64ToGOT:
     *loc64 = 0;
     return;
@@ -642,6 +683,14 @@ void ArchHandler_arm64::applyFixupReloca
   case lazyPointer:
   case lazyImmediateLocation:
     llvm_unreachable("lazy reference kind implies Stubs pass was run");
+  case imageOffset:
+  case imageOffsetGot:
+  case unwindInfoToEhFrame:
+    llvm_unreachable("fixup implies __unwind_info");
+    return;
+  case unwindFDEToFunction:
+    // Do nothing for now
+    return;
   case invalid:
     // Fall into llvm_unreachable().
     break;
@@ -751,6 +800,14 @@ void ArchHandler_arm64::appendSectionRel
   case lazyPointer:
   case lazyImmediateLocation:
     llvm_unreachable("lazy reference kind implies Stubs pass was run");
+  case imageOffset:
+  case imageOffsetGot:
+    llvm_unreachable("deltas from mach_header can only be in final images");
+  case unwindFDEToFunction:
+  case unwindInfoToEhFrame:
+  case negDelta32:
+    // Do nothing.
+    return;
   case invalid:
     // Fall into llvm_unreachable().
     break;

Added: lld/trunk/test/mach-o/unwind-info-simple-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/unwind-info-simple-arm64.yaml?rev=223103&view=auto
==============================================================================
--- lld/trunk/test/mach-o/unwind-info-simple-arm64.yaml (added)
+++ lld/trunk/test/mach-o/unwind-info-simple-arm64.yaml Mon Dec  1 19:50:38 2014
@@ -0,0 +1,280 @@
+# RUN: lld -flavor darwin -arch arm64 %s -o %t -e _main %p/Inputs/libSystem.yaml
+# RUN: llvm-objdump -unwind-info %t | FileCheck %s
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       2
+    address:         0x0000000000000000
+    content:         [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91, 
+                       0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94, 
+                       0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9, 
+                       0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90, 
+                       0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94, 
+                       0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91, 
+                       0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94, 
+                       0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9, 
+                       0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90, 
+                       0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94, 
+                       0x3F, 0x04, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54, 
+                       0x00, 0x00, 0x00, 0x94, 0xFD, 0x7B, 0xC1, 0xA8, 
+                       0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94, 
+                       0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91, 
+                       0x00, 0x00, 0x00, 0x94 ]
+    relocations:
+      - offset:          0x00000070
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          5
+      - offset:          0x00000064
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          7
+      - offset:          0x00000060
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          12
+      - offset:          0x00000058
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          11
+      - offset:          0x0000004C
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          13
+      - offset:          0x00000048
+        type:            ARM64_RELOC_GOT_LOAD_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          8
+      - offset:          0x00000044
+        type:            ARM64_RELOC_GOT_LOAD_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          8
+      - offset:          0x00000034
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          10
+      - offset:          0x00000024
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          13
+      - offset:          0x00000020
+        type:            ARM64_RELOC_GOT_LOAD_PAGEOFF12
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          8
+      - offset:          0x0000001C
+        type:            ARM64_RELOC_GOT_LOAD_PAGE21
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          8
+      - offset:          0x0000000C
+        type:            ARM64_RELOC_BRANCH26
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          10
+  - segment:         __TEXT
+    section:         __gcc_except_tab
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       2
+    address:         0x0000000000000074
+    content:         [ 0xFF, 0x9B, 0xAF, 0x80, 0x00, 0x03, 0x27, 0x00, 
+                       0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 
+                       0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 
+                       0x01, 0x28, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+                       0xD0, 0xFF, 0xFF, 0xFF ]
+    relocations:     
+      - offset:          0x00000030
+        type:            ARM64_RELOC_POINTER_TO_GOT
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          9
+  - segment:         __LD
+    section:         __compact_unwind
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       3
+    address:         0x00000000000000A8
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - offset:          0x00000040
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000038
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
+      - offset:          0x00000030
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          14
+      - offset:          0x00000020
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000000
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+local-symbols:
+  - name:            ltmp0
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            ltmp14
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000074
+  - name:            GCC_except_table1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000074
+  - name:            ltmp21
+    type:            N_SECT
+    sect:            3
+    value:           0x00000000000000A8
+global-symbols:  
+  - name:            __Z3barv
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000028
+  - name:            __Z3foov
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000068
+undefined-symbols: 
+  - name:            __Unwind_Resume
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            __ZTIi
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            __ZTIl
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            ___cxa_allocate_exception
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            ___cxa_begin_catch
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            ___cxa_end_catch
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            ___cxa_throw
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            ___gxx_personality_v0
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_DYLIB
+install-name:    /usr/lib/libc++.dylib
+exports:
+  - name:            __Unwind_Resume
+  - name:            __ZTIl
+  - name:            __ZTIi
+  - name:            ___cxa_end_catch
+  - name:            ___cxa_begin_catch
+  - name:            ___cxa_allocate_exception
+  - name:            ___cxa_throw
+  - name:            ___gxx_personality_v0
+
+...
+
+
+# CHECK: Contents of __unwind_info section:
+# CHECK:   Version:                                   0x1
+# CHECK:   Common encodings array section offset:     0x1c
+# CHECK:   Number of common encodings in array:       0x0
+# CHECK:   Personality function array section offset: 0x1c
+# CHECK:   Number of personality functions in array:  0x1
+# CHECK:   Index array section offset:                0x20
+# CHECK:   Number of indices in array:                0x2
+# CHECK:   Common encodings: (count = 0)
+# CHECK:   Personality functions: (count = 1)
+# CHECK:     personality[1]: 0x00004018
+# CHECK:   Top level indices: (count = 2)
+# CHECK:     [0]: function offset=0x00003e68, 2nd level page offset=0x00000040, LSDA offset=0x00000038
+# CHECK:     [1]: function offset=0x00003edc, 2nd level page offset=0x00000000, LSDA offset=0x00000040
+# CHECK:   LSDA descriptors:
+# CHECK:     [0]: function offset=0x00003e90, LSDA offset=0x00003f6c
+# CHECK:   Second level indices:
+# CHECK:     Second level index[0]: offset in section=0x00000040, base function offset=0x00003e68
+# CHECK:       [0]: function offset=0x00003e68, encoding=0x04000000
+# CHECK:       [1]: function offset=0x00003e90, encoding=0x54000000
+# CHECK:       [2]: function offset=0x00003ed0, encoding=0x04000000
+# CHECK-NOT: Contents of __compact_unwind section
+
+
+





More information about the llvm-commits mailing list