[lld] r263590 - Fix EHFrame processing to add implicit references when needed.

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 15 14:33:11 PDT 2016


Author: pete
Date: Tue Mar 15 16:33:10 2016
New Revision: 263590

URL: http://llvm.org/viewvc/llvm-project?rev=263590&view=rev
Log:
Fix EHFrame processing to add implicit references when needed.

The current code for processCIE and processFDE returns out if it sees
any references.  The problem with this is that some references could be
explicit in the binary, while others are implicit as they can be
inferred from the content of the EHFrame itself.

This change walks the references we have against the references we
need, and verifies that all explicit references are in the correct place,
and generates any missing implicit ones.

Reviewed by Lang Hames and Nick Kledzik.

Differential Revision: http://reviews.llvm.org/D15439

Added:
    lld/trunk/test/mach-o/eh-frame-relocs-arm64.yaml
Modified:
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/test/mach-o/do-not-emit-unwind-fde-arm64.yaml

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Mar 15 16:33:10 2016
@@ -346,6 +346,14 @@ public:
              atomContentType == DefinedAtom::typeTLVInitialZeroFill);
   }
 
+  /// Utility function to check if relocations in this atom to other defined
+  /// atoms can be implicitly generated, and so we don't need to explicitly
+  /// emit those relocations.
+  bool relocsToDefinedCanBeImplicit() const {
+    ContentType atomContentType = contentType();
+    return atomContentType == typeCFI;
+  }
+
   // Returns true if lhs should be placed before rhs in the final output.
   static bool compareByPosition(const DefinedAtom *lhs,
                                 const DefinedAtom *rhs);

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Tue Mar 15 16:33:10 2016
@@ -78,6 +78,11 @@ public:
   /// actually be used.
   virtual uint32_t dwarfCompactUnwindType() = 0;
 
+  /// Reference from an __eh_frame CIE atom to its personality function it's
+  /// describing. Usually pointer-sized and PC-relative, but differs in whether
+  /// it needs to be in relocatable objects.
+  virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0;
+
   /// Reference from an __eh_frame FDE to the CIE it's based on.
   virtual Reference::KindValue unwindRefToCIEKind() = 0;
 

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Mar 15 16:33:10 2016
@@ -51,6 +51,10 @@ public:
     return invalid;
   }
 
+  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+    return invalid;
+  }
+
   Reference::KindValue unwindRefToCIEKind() override {
     return invalid;
   }

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=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Tue Mar 15 16:33:10 2016
@@ -53,6 +53,9 @@ public:
     case delta32ToGOT:
       canBypassGOT = false;
       return true;
+    case unwindCIEToPersonalityFunction:
+      canBypassGOT = false;
+      return true;
     case imageOffsetGot:
       canBypassGOT = false;
       return true;
@@ -108,6 +111,10 @@ public:
     return imageOffsetGot;
   }
 
+  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+    return unwindCIEToPersonalityFunction;
+  }
+
   Reference::KindValue unwindRefToCIEKind() override {
     return negDelta32;
   }
@@ -201,6 +208,9 @@ private:
     imageOffset,           /// Location contains offset of atom in final image
     imageOffsetGot,        /// Location contains offset of GOT entry for atom in
                            /// final image (typically personality function).
+    unwindCIEToPersonalityFunction,   /// Nearly delta32ToGOT, but cannot be
+                           /// rematerialized in relocatable object
+                           /// (yay for implicit contracts!).
     unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
                            /// relocatable object (yay for implicit contracts!).
     unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
@@ -248,6 +258,7 @@ const Registry::KindStrings ArchHandler_
   LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
   LLD_KIND_STRING_ENTRY(imageOffset),
   LLD_KIND_STRING_ENTRY(imageOffsetGot),
+  LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction),
   LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
   LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
 
@@ -442,7 +453,14 @@ std::error_code ArchHandler_arm64::getRe
     return std::error_code();
   case ARM64_RELOC_POINTER_TO_GOT     | rPcRel | rExtern | rLength4:
     // ex: .long _foo at GOT - .
-    *kind = delta32ToGOT;
+
+    // If we are in an .eh_frame section, then the kind of the relocation should
+    // not be delta32ToGOT.  It may instead be unwindCIEToPersonalityFunction.
+    if (inAtom->contentType() == DefinedAtom::typeCFI)
+      *kind = unwindCIEToPersonalityFunction;
+    else
+      *kind = delta32ToGOT;
+
     if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
       return ec;
     *addend = 0;
@@ -488,9 +506,16 @@ std::error_code ArchHandler_arm64::getPa
   case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength8) << 16 |
          ARM64_RELOC_UNSIGNED                    | rExtern | rLength8):
     // ex: .quad _foo - .
-    *kind = delta64;
     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
       return ec;
+
+    // If we are in an .eh_frame section, then the kind of the relocation should
+    // not be delta64.  It may instead be unwindFDEToFunction.
+    if (inAtom->contentType() == DefinedAtom::typeCFI)
+      *kind = unwindFDEToFunction;
+    else
+      *kind = delta64;
+
     // The offsets of the 2 relocations must match
     if (reloc1.offset != reloc2.offset)
       return make_dynamic_error_code("paired relocs must have the same offset");
@@ -629,6 +654,7 @@ void ArchHandler_arm64::applyFixupFinal(
     return;
   case delta32:
   case delta32ToGOT:
+  case unwindCIEToPersonalityFunction:
     *loc32 = (targetAddress - fixupAddress) + ref.addend();
     return;
   case negDelta32:
@@ -719,6 +745,13 @@ void ArchHandler_arm64::applyFixupReloca
   case delta32ToGOT:
     *loc32 = inAtomAddress - fixupAddress;
     return;
+  case unwindCIEToPersonalityFunction:
+    // We don't emit unwindCIEToPersonalityFunction in -r mode as they are
+    // implicitly generated from the data in the __eh_frame section.  So here we
+    // need to use the targetAddress so that we can generate the full relocation
+    // when we parse again later.
+    *loc32 = targetAddress - fixupAddress;
+    return;
   case addOffset12:
     llvm_unreachable("lazy reference kind implies GOT pass was run");
   case lazyPointer:
@@ -841,6 +874,7 @@ void ArchHandler_arm64::appendSectionRel
   case imageOffset:
   case imageOffsetGot:
     llvm_unreachable("deltas from mach_header can only be in final images");
+  case unwindCIEToPersonalityFunction:
   case unwindFDEToFunction:
   case unwindInfoToEhFrame:
   case negDelta32:

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Tue Mar 15 16:33:10 2016
@@ -58,6 +58,10 @@ public:
     return invalid;
   }
 
+  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+    return invalid;
+  }
+
   Reference::KindValue unwindRefToCIEKind() override {
     return negDelta32;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Tue Mar 15 16:33:10 2016
@@ -104,6 +104,10 @@ public:
     return imageOffsetGot;
   }
 
+  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
+    return ripRel32Got;
+  }
+
   Reference::KindValue unwindRefToCIEKind() override {
     return negDelta32;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue Mar 15 16:33:10 2016
@@ -689,18 +689,21 @@ static int64_t readSPtr(bool is64, bool
 
 struct CIEInfo {
   bool _augmentationDataPresent = false;
-  bool _mayHaveLSDA = false;
+  bool _mayHaveEH = false;
+  uint32_t _offsetOfLSDA = ~0U;
+  uint32_t _offsetOfPersonality = ~0U;
+  uint32_t _offsetOfFDEPointerEncoding = ~0U;
+  uint32_t _augmentationDataLength = ~0U;
 };
 
 typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
 
 static std::error_code processAugmentationString(const uint8_t *augStr,
                                                  CIEInfo &cieInfo,
-                                                 unsigned *len = nullptr) {
+                                                 unsigned &len) {
 
   if (augStr[0] == '\0') {
-    if (len)
-      *len = 1;
+    len = 1;
     return std::error_code();
   }
 
@@ -711,21 +714,54 @@ static std::error_code processAugmentati
   cieInfo._augmentationDataPresent = true;
   uint64_t idx = 1;
 
+  uint32_t offsetInAugmentationData = 0;
   while (augStr[idx] != '\0') {
     if (augStr[idx] == 'L') {
-      cieInfo._mayHaveLSDA = true;
+      cieInfo._offsetOfLSDA = offsetInAugmentationData;
+      // This adds a single byte to the augmentation data.
+      ++offsetInAugmentationData;
       ++idx;
-    } else
+      continue;
+    }
+    if (augStr[idx] == 'P') {
+      cieInfo._offsetOfPersonality = offsetInAugmentationData;
+      // This adds a single byte to the augmentation data for the encoding,
+      // then a number of bytes for the pointer data.
+      // FIXME: We are assuming 4 is correct here for the pointer size as we
+      // always currently use delta32ToGOT.
+      offsetInAugmentationData += 5;
+      ++idx;
+      continue;
+    }
+    if (augStr[idx] == 'R') {
+      cieInfo._offsetOfFDEPointerEncoding = offsetInAugmentationData;
+      // This adds a single byte to the augmentation data.
+      ++offsetInAugmentationData;
       ++idx;
+      continue;
+    }
+    if (augStr[idx] == 'e') {
+      if (augStr[idx + 1] != 'h')
+        return make_dynamic_error_code("expected 'eh' in augmentation string");
+      cieInfo._mayHaveEH = true;
+      idx += 2;
+      continue;
+    }
+    ++idx;
   }
 
-  if (len)
-    *len = idx + 1;
+  cieInfo._augmentationDataLength = offsetInAugmentationData;
+
+  len = idx + 1;
   return std::error_code();
 }
 
 static std::error_code processCIE(const NormalizedFile &normalizedFile,
+                                  MachOFile &file,
+                                  mach_o::ArchHandler &handler,
+                                  const Section *ehFrameSection,
                                   MachODefinedAtom *atom,
+                                  uint64_t offset,
                                   CIEInfoMap &cieInfos) {
   const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
   const uint8_t *frameData = atom->rawContent().data();
@@ -739,10 +775,85 @@ static std::error_code processCIE(const
   uint64_t versionField = cieIDField + sizeof(uint32_t);
   uint64_t augmentationStringField = versionField + sizeof(uint8_t);
 
+  unsigned augmentationStringLength = 0;
   if (auto err = processAugmentationString(frameData + augmentationStringField,
-                                           cieInfo))
+                                           cieInfo, augmentationStringLength))
     return err;
 
+  if (cieInfo._offsetOfPersonality != ~0U) {
+    // If we have augmentation data for the personality function, then we may
+    // need to implicitly generate its relocation.
+
+    // Parse the EH Data field which is pointer sized.
+    uint64_t EHDataField = augmentationStringField + augmentationStringLength;
+    const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
+    unsigned EHDataFieldSize = (cieInfo._mayHaveEH ? (is64 ? 8 : 4) : 0);
+
+    // Parse Code Align Factor which is a ULEB128.
+    uint64_t CodeAlignField = EHDataField + EHDataFieldSize;
+    unsigned lengthFieldSize = 0;
+    llvm::decodeULEB128(frameData + CodeAlignField, &lengthFieldSize);
+
+    // Parse Data Align Factor which is a SLEB128.
+    uint64_t DataAlignField = CodeAlignField + lengthFieldSize;
+    llvm::decodeSLEB128(frameData + DataAlignField, &lengthFieldSize);
+
+    // Parse Return Address Register which is a byte.
+    uint64_t ReturnAddressField = DataAlignField + lengthFieldSize;
+
+    // Parse the augmentation length which is a ULEB128.
+    uint64_t AugmentationLengthField = ReturnAddressField + 1;
+    uint64_t AugmentationLength =
+      llvm::decodeULEB128(frameData + AugmentationLengthField,
+                          &lengthFieldSize);
+
+    if (AugmentationLength != cieInfo._augmentationDataLength)
+      return make_dynamic_error_code("CIE augmentation data length mismatch");
+
+    // Get the start address of the augmentation data.
+    uint64_t AugmentationDataField = AugmentationLengthField + lengthFieldSize;
+
+    // Parse the personality function from the augmentation data.
+    uint64_t PersonalityField =
+      AugmentationDataField + cieInfo._offsetOfPersonality;
+
+    // Parse the personality encoding.
+    // FIXME: Verify that this is a 32-bit pcrel offset.
+    uint64_t PersonalityFunctionField = PersonalityField + 1;
+
+    if (atom->begin() != atom->end()) {
+      // If we have an explicit relocation, then make sure it matches this
+      // offset as this is where we'd expect it to be applied to.
+      DefinedAtom::reference_iterator CurrentRef = atom->begin();
+      if (CurrentRef->offsetInAtom() != PersonalityFunctionField)
+        return make_dynamic_error_code("CIE personality reloc at wrong offset");
+
+      if (++CurrentRef != atom->end())
+        return make_dynamic_error_code("CIE contains too many relocs");
+    } else {
+      // Implicitly generate the personality function reloc.  It's assumed to
+      // be a delta32 offset to a GOT entry.
+      // FIXME: Parse the encoding and check this.
+      int32_t funcDelta = read32(frameData + PersonalityFunctionField, isBig);
+      uint64_t funcAddress = ehFrameSection->address + offset +
+                             PersonalityFunctionField;
+      funcAddress += funcDelta;
+
+      const MachODefinedAtom *func = nullptr;
+      Reference::Addend addend;
+      func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
+                                     &addend);
+      atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
+                         handler.unwindRefToPersonalityFunctionKind(),
+                         PersonalityFunctionField, func, addend);
+    }
+  } else if (atom->begin() != atom->end()) {
+    // Otherwise, we expect there to be no relocations in this atom as the only
+    // relocation would have been to the personality function.
+    return make_dynamic_error_code("unexpected relocation in CIE");
+  }
+
+
   cieInfos[atom] = std::move(cieInfo);
 
   return std::error_code();
@@ -760,10 +871,72 @@ static std::error_code processFDE(const
   const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
 
   // Compiler wasn't lazy and actually told us what it meant.
+  // Unfortunately, the compiler may not have generated references for all of
+  // [cie, func, lsda] and so we still need to parse the FDE and add references
+  // for any the compiler didn't generate.
   if (atom->begin() != atom->end())
-    return std::error_code();
+    atom->sortReferences();
+
+  DefinedAtom::reference_iterator CurrentRef = atom->begin();
+
+  // This helper returns the reference (if one exists) at the offset we are
+  // currently processing.  It automatically increments the ref iterator if we
+  // do return a ref, and throws an error if we pass over a ref without
+  // comsuming it.
+  auto currentRefGetter = [&CurrentRef,
+                           &atom](uint64_t Offset)->const Reference* {
+    // If there are no more refs found, then we are done.
+    if (CurrentRef == atom->end())
+      return nullptr;
+
+    const Reference *Ref = *CurrentRef;
+
+    // If we haven't reached the offset for this reference, then return that
+    // we don't yet have a reference to process.
+    if (Offset < Ref->offsetInAtom())
+      return nullptr;
+
+    // If the offset is equal, then we want to process this ref.
+    if (Offset == Ref->offsetInAtom()) {
+      ++CurrentRef;
+      return Ref;
+    }
+
+    // The current ref is at an offset which is earlier than the current
+    // offset, then we failed to consume it when we should have.  In this case
+    // throw an error.
+    llvm::report_fatal_error("Skipped reference when processing FDE");
+  };
+
+  // Helper to either get the reference at this current location, and verify
+  // that it is of the expected type, or add a reference of that type.
+  // Returns the reference target.
+  auto verifyOrAddReference = [&](uint64_t targetAddress,
+                                  Reference::KindValue refKind,
+                                  uint64_t refAddress,
+                                  bool allowsAddend)->const Atom* {
+    if (auto *ref = currentRefGetter(refAddress)) {
+      // The compiler already emitted a relocation for the CIE ref.  This should
+      // have been converted to the correct type of reference in
+      // get[Pair]ReferenceInfo().
+      assert(ref->kindValue() == refKind &&
+             "Incorrect EHFrame reference kind");
+      return ref->target();
+    }
+    Reference::Addend addend;
+    auto *target = findAtomCoveringAddress(normalizedFile, file,
+                                           targetAddress, &addend);
+    atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
+                       refKind, refAddress, target, addend);
+
+    if (!allowsAddend)
+      assert(!addend && "EHFrame reference cannot have addend");
+    return target;
+  };
+
+  const uint8_t *startFrameData = atom->rawContent().data();
+  const uint8_t *frameData = startFrameData;
 
-  const uint8_t *frameData = atom->rawContent().data();
   uint32_t size = read32(frameData, isBig);
   uint64_t cieFieldInFDE = size == 0xffffffffU
     ? sizeof(uint32_t) + sizeof(uint64_t)
@@ -775,13 +948,11 @@ static std::error_code processFDE(const
   uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
   cieAddress -= cieDelta;
 
-  Reference::Addend addend;
-  const MachODefinedAtom *cie =
-    findAtomCoveringAddress(normalizedFile, file, cieAddress, &addend);
-  atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
-                     handler.unwindRefToCIEKind(), cieFieldInFDE, cie, addend);
-
-  assert(cie && cie->contentType() == DefinedAtom::typeCFI && !addend &&
+  auto *cieRefTarget = verifyOrAddReference(cieAddress,
+                                            handler.unwindRefToCIEKind(),
+                                            cieFieldInFDE, false);
+  const MachODefinedAtom *cie = dyn_cast<MachODefinedAtom>(cieRefTarget);
+  assert(cie && cie->contentType() == DefinedAtom::typeCFI &&
          "FDE's CIE field does not point at the start of a CIE.");
 
   const CIEInfo &cieInfo = cieInfos.find(cie)->second;
@@ -797,11 +968,9 @@ static std::error_code processFDE(const
   uint64_t rangeStart = ehFrameSection->address + offset + rangeFieldInFDE;
   rangeStart += functionFromFDE;
 
-  const Atom *func =
-    findAtomCoveringAddress(normalizedFile, file, rangeStart, &addend);
-  atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
-                     handler.unwindRefToFunctionKind(), rangeFieldInFDE, func,
-                     addend);
+  verifyOrAddReference(rangeStart,
+                       handler.unwindRefToFunctionKind(),
+                       rangeFieldInFDE, true);
 
   // Handle the augmentation data if there is any.
   if (cieInfo._augmentationDataPresent) {
@@ -813,7 +982,7 @@ static std::error_code processFDE(const
       llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
                           &lengthFieldSize);
 
-    if (cieInfo._mayHaveLSDA && augmentationDataLength > 0) {
+    if (cieInfo._offsetOfLSDA != ~0U && augmentationDataLength > 0) {
 
       // Look at the augmentation data field.
       uint64_t augmentationDataFieldInFDE =
@@ -824,11 +993,10 @@ static std::error_code processFDE(const
       uint64_t lsdaStart =
         ehFrameSection->address + offset + augmentationDataFieldInFDE +
         lsdaFromFDE;
-      const Atom *lsda =
-        findAtomCoveringAddress(normalizedFile, file, lsdaStart, &addend);
-      atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
-                         handler.unwindRefToFunctionKind(),
-                         augmentationDataFieldInFDE, lsda, addend);
+
+      verifyOrAddReference(lsdaStart,
+                           handler.unwindRefToFunctionKind(),
+                           augmentationDataFieldInFDE, true);
     }
   }
 
@@ -864,7 +1032,8 @@ std::error_code addEHFrameReferences(con
 
     const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
     if (ArchHandler::isDwarfCIE(isBig, atom))
-      ehFrameErr = processCIE(normalizedFile, atom, cieInfos);
+      ehFrameErr = processCIE(normalizedFile, file, handler, ehFrameSection,
+                              atom, offset, cieInfos);
     else
       ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
                               atom, offset, cieInfos);

Modified: lld/trunk/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/do-not-emit-unwind-fde-arm64.yaml?rev=263590&r1=263589&r2=263590&view=diff
==============================================================================
--- lld/trunk/test/mach-o/do-not-emit-unwind-fde-arm64.yaml (original)
+++ lld/trunk/test/mach-o/do-not-emit-unwind-fde-arm64.yaml Tue Mar 15 16:33:10 2016
@@ -74,7 +74,7 @@ sections:
     address:         0x0000000000000050
     content:         [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x01, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
-                       0x1E, 0x0B, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF,
+                       0x1E, 0x07, 0x00, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF,
                        0xFF, 0xFF, 0xFF, 0x00, 0x10, 0x0C, 0x1F, 0x00,
                        0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
                        0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -142,8 +142,8 @@ page-size:       0x00000000
 # CHECK:   - ref-name:        L{{[0-9]*}}
 # CHECK:     type:            unwind-cfi
 # CHECK:     content:         [ 1C, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 50, 4C,
-# CHECK:                        52, 00, 01, 78, 1E, 0B, 00, ED, FF, FF, FF, FF,
-# CHECK:                        FF, FF, FF, 00, 10, 0C, 1F, 00 ]
+# CHECK:                        52, 00, 01, 78, 1E, 07, 00, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK:                        {{..}}, {{..}}, {{..}}, 00, 10, 0C, 1F, 00 ]
 # CHECK:   - type:            unwind-cfi
 # CHECK:     content:         [ 24, 00, 00, 00, 24, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
 # CHECK:                        {{..}}, {{..}}, {{..}}, {{..}}, 20, 00, 00, 00, 00, 00, 00, 00,
@@ -197,7 +197,7 @@ page-size:       0x00000000
 # CODE: Contents of section __eh_frame:
 # This is the CIE:
 # CODE-NEXT: {{[0-9abcdef]*}} 1c000000 00000000 017a504c 52000178
-# CODE-NEXT: {{[0-9abcdef]*}} 1e0b00ed ffffffff ffffff00 100c1f00
+# CODE-NEXT: {{[0-9abcdef]*}} 1e0700bd ffffffff ffffff00 100c1f00
 # This is the FDE:
 # CODE-NEXT: {{[0-9abcdef]*}} 24000000 24000000 a8ffffff ffffffff
 # This is the important offset for FDE->func    ^~~~~~~~ ~~~~~~~~

Added: lld/trunk/test/mach-o/eh-frame-relocs-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/eh-frame-relocs-arm64.yaml?rev=263590&view=auto
==============================================================================
--- lld/trunk/test/mach-o/eh-frame-relocs-arm64.yaml (added)
+++ lld/trunk/test/mach-o/eh-frame-relocs-arm64.yaml Tue Mar 15 16:33:10 2016
@@ -0,0 +1,318 @@
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t | FileCheck -check-prefix=CODE %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t2 | FileCheck -check-prefix=CODE %s
+
+
+--- !mach-o
+arch:            arm64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version:  0.0
+current-version: 0.0
+has-UUID:        false
+OS:              unknown
+sections:        
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       4
+    address:         0x0000000000000000
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0xC0, 0x03, 0x5F, 0xD6, 0xC0, 0x03, 0x5F, 0xD6, 
+                       0xC0, 0x03, 0x5F, 0xD6 ]
+  - segment:         __TEXT
+    section:         __gcc_except_tab
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x0000000000000014
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x000000000000001C
+    content:         [ 0x00, 0x00, 0x00, 0x00 ]
+  - segment:         __LD
+    section:         __compact_unwind
+    type:            S_REGULAR
+    attributes:      [  ]
+    alignment:       8
+    address:         0x0000000000000020
+    content:         [ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - 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
+  - segment:         __TEXT
+    section:         __eh_frame
+    type:            S_COALESCED
+    attributes:      [  ]
+    alignment:       8
+    address:         0x0000000000000060
+    content:         [ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78, 
+                       0x1E, 0x07, 0x9B, 0xED, 0xFF, 0xFF, 0xFF, 0x10, 
+                       0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00, 
+                       0x20, 0x00, 0x00, 0x00, 0xDC, 0xFF, 0xFF, 0xFF, 
+                       0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x08, 0xCB, 0xFF, 0xFF, 
+                       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E, 
+                       0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                       0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78, 
+                       0x1E, 0x07, 0x9B, 0xA9, 0xFF, 0xFF, 0xFF, 0x10, 
+                       0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00, 
+                       0x20, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 
+                       0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 
+                       0x00, 0x00, 0x00, 0x00, 0x08, 0x83, 0xFF, 0xFF, 
+                       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E, 
+                       0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - offset:          0x0000007D
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          6
+      - offset:          0x0000007D
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+      - offset:          0x0000006C
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          6
+      - offset:          0x0000006C
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          8
+      - offset:          0x0000005B
+        type:            ARM64_RELOC_POINTER_TO_GOT
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          10
+      - offset:          0x00000035
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          6
+      - offset:          0x00000035
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000024
+        type:            ARM64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          6
+      - offset:          0x00000024
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          7
+      - offset:          0x00000013
+        type:            ARM64_RELOC_POINTER_TO_GOT
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          9
+local-symbols:   
+  - name:            ltmp0
+    type:            N_SECT
+    sect:            1
+    value:           0x0000000000000000
+  - name:            ltmp1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000014
+  - name:            _bar1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000014
+  - name:            _bar2
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000018
+  - name:            ltmp12
+    type:            N_SECT
+    sect:            3
+    value:           0x000000000000001C
+  - name:            ltmp13
+    type:            N_SECT
+    sect:            4
+    value:           0x0000000000000020
+  - name:            ltmp16
+    type:            N_SECT
+    sect:            5
+    value:           0x0000000000000060
+global-symbols:  
+  - name:            __Z3fooi
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000008
+  - name:            __Z4foo2i
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x000000000000000C
+  - name:            __gxx_personality_v0
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+  - name:            __gxx_personality_v1
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000004
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000010
+  - name:            _someData
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            3
+    value:           0x000000000000001C
+page-size:       0x00000000
+...
+
+# CHECK: --- !native
+# CHECK: path:            '<linker-internal>'
+# CHECK: defined-atoms:   
+# CHECK:   - ref-name:        L000
+# CHECK:     type:            unwind-cfi
+# CHECK:     content:         [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C, 
+# CHECK:                        52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10, 
+# CHECK:                        10, 0C, 1F, 00 ]
+# CHECK:     alignment:       8
+# CHECK:     references:      
+# CHECK:       - kind:            unwindCIEToPersonalityFunction
+# CHECK:         offset:          19
+# CHECK:         target:          __gxx_personality_v0
+# CHECK:   - type:            unwind-cfi
+# CHECK:     content:         [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}}, 
+# CHECK:                        {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00, 
+# CHECK:                        08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E, 
+# CHECK:                        01, 9D, 02, 00, 00, 00, 00, 00 ]
+# CHECK:     alignment:       4 mod 8
+# CHECK:     references:      
+# CHECK:       - kind:            negDelta32
+# CHECK:         offset:          4
+# CHECK:         target:          L000
+# CHECK:       - kind:            unwindFDEToFunction
+# CHECK:         offset:          8
+# CHECK:         target:          __Z3fooi
+# CHECK:       - kind:            unwindFDEToFunction
+# CHECK:         offset:          25
+# CHECK:         target:          _bar1
+# CHECK:   - ref-name:        L001
+# CHECK:     type:            unwind-cfi
+# CHECK:     content:         [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C, 
+# CHECK:                        52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10, 
+# CHECK:                        10, 0C, 1F, 00 ]
+# CHECK:     alignment:       8
+# CHECK:     references:      
+# CHECK:       - kind:            unwindCIEToPersonalityFunction
+# CHECK:         offset:          19
+# CHECK:         target:          __gxx_personality_v1
+# CHECK:   - type:            unwind-cfi
+# CHECK:     content:         [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}}, 
+# CHECK:                        {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00, 
+# CHECK:                        08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E, 
+# CHECK:                        01, 9D, 02, 00, 00, 00, 00, 00 ]
+# CHECK:     alignment:       4 mod 8
+# CHECK:     references:      
+# CHECK:       - kind:            negDelta32
+# CHECK:         offset:          4
+# CHECK:         target:          L001
+# CHECK:       - kind:            unwindFDEToFunction
+# CHECK:         offset:          8
+# CHECK:         target:          __Z4foo2i
+# CHECK:       - kind:            unwindFDEToFunction
+# CHECK:         offset:          25
+# CHECK:         target:          _bar2
+# CHECK:   - name:            _bar1
+# CHECK:     type:            unwind-lsda
+# CHECK:     content:         [ 00, 00, 00, 00 ]
+# CHECK:   - name:            _bar2
+# CHECK:     type:            unwind-lsda
+# CHECK:     content:         [ 00, 00, 00, 00 ]
+# CHECK:   - name:            _someData
+# CHECK:     scope:           global
+# CHECK:     type:            data
+# CHECK:     content:         [ 00, 00, 00, 00 ]
+# CHECK:   - name:            __gxx_personality_v0
+# CHECK:     scope:           global
+# CHECK:     content:         [ 00, 00, 00, 00 ]
+# CHECK:     alignment:       4
+# CHECK:   - name:            __gxx_personality_v1
+# CHECK:     scope:           global
+# CHECK:     content:         [ 00, 00, 00, 00 ]
+# CHECK:     alignment:       4
+# CHECK:   - name:            __Z3fooi
+# CHECK:     scope:           global
+# CHECK:     content:         [ C0, 03, 5F, D6 ]
+# CHECK:     alignment:       4
+# CHECK:   - name:            __Z4foo2i
+# CHECK:     scope:           global
+# CHECK:     content:         [ C0, 03, 5F, D6 ]
+# CHECK:     alignment:       4
+# CHECK:   - name:            _main
+# CHECK:     scope:           global
+# CHECK:     content:         [ C0, 03, 5F, D6 ]
+# CHECK:     alignment:       4
+# CHECK: ...
+
+# # Make sure we don't have any relocations in the __eh_frame section
+# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
+
+# Also make sure the reloc for the CIE->personality function is the
+# correct offset
+# It should be the offset from the fixup location back to the address
+# of the function we are referencing
+# CODE: Contents of section __eh_frame:
+# This is the CIE:
+# CODE-NEXT: {{[0-9abcdef]*}} 18000000 00000000 037a504c 52000178
+# CODE-NEXT: {{[0-9abcdef]*}} 1e079bd1 ffffff10 100c1f00 28000000
+# This is the important offset for CIE->pfunc
+#                                   ^~~~~~~~~
+# Then we have an FDE starting from 28000000 above
+# CODE-NEXT: {{[0-9abcdef]*}} 20000000 c8ffffff ffffffff 04000000
+# CODE-NEXT: {{[0-9abcdef]*}} 00000000 08c3ffff ffffffff ff0e109e
+# And a new CIE starts at this 00000018 right below here
+# CODE-NEXT: {{[0-9abcdef]*}} 019d0200 00000000 18000000 00000000
+# CODE-NEXT: {{[0-9abcdef]*}} 037a504c 52000178 1e079b8d ffffff10
+# This is the important offset for its CIE->pfunc     ^~~~~~~~~
\ No newline at end of file




More information about the llvm-commits mailing list