[lld] ecad968 - Revert "[lld-macho] Warn on method name collisions from category definitions"

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 8 15:57:56 PST 2023


Author: Jez Ng
Date: 2023-03-08T15:57:24-08:00
New Revision: ecad968f4a517110f978f63d92459f7318e193f5

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

LOG: Revert "[lld-macho] Warn on method name collisions from category definitions"

This reverts commit ef122753db7fe8e9a0b7bedd46d2f3668a780fcb.

Apparently it is causing some crashes:
https://reviews.llvm.org/D142916#4178869

Added: 
    

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/InputFiles.cpp
    lld/MachO/InputSection.cpp
    lld/MachO/InputSection.h
    lld/MachO/ObjC.cpp
    lld/MachO/ObjC.h
    lld/MachO/Relocations.cpp
    lld/MachO/Relocations.h
    lld/MachO/UnwindInfoSection.cpp
    lld/test/MachO/objc-imageinfo.s

Removed: 
    lld/MachO/Layout.h
    lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libobjc.tbd
    lld/test/MachO/objc-category-conflicts.s


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 322d7de30b63f..0f2326b305b13 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1920,8 +1920,6 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
     if (config->deadStrip)
       markLive();
 
-    objc::checkCategories();
-
     // ICF assumes that all literals have been folded already, so we must run
     // foldIdenticalLiterals before foldIdenticalSections.
     foldIdenticalLiterals();

diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 65e06a8557d9c..ed0d98a2ececd 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -1272,10 +1272,13 @@ static CIE parseCIE(const InputSection *isec, const EhReader &reader,
     }
   }
   if (personalityAddrOff != 0) {
-    const auto *personalityReloc = isec->getRelocAt(personalityAddrOff);
-    if (!personalityReloc)
+    auto personalityRelocIt =
+        llvm::find_if(isec->relocs, [=](const macho::Reloc &r) {
+          return r.offset == personalityAddrOff;
+        });
+    if (personalityRelocIt == isec->relocs.end())
       reader.failOn(off, "Failed to locate relocation for personality symbol");
-    cie.personalitySymbol = personalityReloc->referent.get<macho::Symbol *>();
+    cie.personalitySymbol = personalityRelocIt->referent.get<macho::Symbol *>();
   }
   return cie;
 }

diff  --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index ff5a15067adcd..1d8d58477139f 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -135,14 +135,6 @@ std::string InputSection::getSourceLocation(uint64_t off) const {
   return {};
 }
 
-const Reloc *InputSection::getRelocAt(uint32_t off) const {
-  auto it = llvm::find_if(
-      relocs, [=](const macho::Reloc &r) { return r.offset == off; });
-  if (it == relocs.end())
-    return nullptr;
-  return &*it;
-}
-
 void ConcatInputSection::foldIdentical(ConcatInputSection *copy) {
   align = std::max(align, copy->align);
   copy->live = false;
@@ -267,15 +259,6 @@ const StringPiece &CStringInputSection::getStringPiece(uint64_t off) const {
   return const_cast<CStringInputSection *>(this)->getStringPiece(off);
 }
 
-size_t CStringInputSection::getStringPieceIndex(uint64_t off) const {
-  if (off >= data.size())
-    fatal(toString(this) + ": offset is outside the section");
-
-  auto it =
-      partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; });
-  return std::distance(pieces.begin(), it) - 1;
-}
-
 uint64_t CStringInputSection::getOffset(uint64_t off) const {
   const StringPiece &piece = getStringPiece(off);
   uint64_t addend = off - piece.inSecOff;

diff  --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index becb01017d633..5a6a205f9047c 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -55,8 +55,6 @@ class InputSection {
   // Return the source line corresponding to an address, or the empty string.
   // Format: Source.cpp:123 (/path/to/Source.cpp:123)
   std::string getSourceLocation(uint64_t off) const;
-  // Return the relocation at \p off, if it exists. This does a linear search.
-  const Reloc *getRelocAt(uint32_t off) const;
   // Whether the data at \p off in this InputSection is live.
   virtual bool isLive(uint64_t off) const = 0;
   virtual void markLive(uint64_t off) = 0;
@@ -220,10 +218,6 @@ class CStringInputSection final : public InputSection {
     return toStringRef(data.slice(begin, end - begin));
   }
 
-  StringRef getStringRefAtOffset(uint64_t off) const {
-    return getStringRef(getStringPieceIndex(off));
-  }
-
   // Returns i'th piece as a CachedHashStringRef. This function is very hot when
   // string merging is enabled, so we want to inline.
   LLVM_ATTRIBUTE_ALWAYS_INLINE
@@ -238,9 +232,6 @@ class CStringInputSection final : public InputSection {
 
   bool deduplicateLiterals = false;
   std::vector<StringPiece> pieces;
-
-private:
-  size_t getStringPieceIndex(uint64_t off) const;
 };
 
 class WordLiteralInputSection final : public InputSection {

diff  --git a/lld/MachO/Layout.h b/lld/MachO/Layout.h
deleted file mode 100644
index 6a7653f315e3c..0000000000000
--- a/lld/MachO/Layout.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//===- Layout.h -----------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// Convenience macros for obtaining offsets of members in structs.
-//
-// Usage:
-//
-//   #define FOR_EACH_FOO_FIELD(DO) \
-//     DO(Ptr, bar)                 \
-//     DO(uint32_t, baz)            \
-//   CREATE_LAYOUT_CLASS(Foo, FOR_EACH_FOO_FIELD)
-//   #undef FOR_EACH_FOO_FIELD
-//
-// This will generate
-//
-//   struct FooLayout {
-//     uint32_t barOffset;
-//     uint32_t bazOffset;
-//     uint32_t totalSize;
-//
-//     FooLayout(size_t wordSize) {
-//       if (wordSize == 8)
-//         init<uint64_t>();
-//       else {
-//         assert(wordSize == 4);
-//         init<uint32_t>();
-//       }
-//     }
-//
-//   private:
-//     template <class Ptr> void init() {
-//       FOR_EACH_FIELD(_INIT_OFFSET);
-//       barOffset = offsetof(Layout<Ptr>, bar);
-//       bazOffset = offsetof(Layout<Ptr>, baz);
-//       totalSize = sizeof(Layout<Ptr>);
-//     }
-//     template <class Ptr> struct Layout {
-//       Ptr bar;
-//       uint32_t baz;
-//     };
-//   };
-
-#define _OFFSET_FOR_FIELD(_, name) uint32_t name##Offset;
-#define _INIT_OFFSET(type, name) name##Offset = offsetof(Layout<Ptr>, name);
-#define _LAYOUT_ENTRY(type, name) type name;
-
-#define CREATE_LAYOUT_CLASS(className, FOR_EACH_FIELD)                         \
-  struct className##Layout {                                                   \
-    FOR_EACH_FIELD(_OFFSET_FOR_FIELD)                                          \
-    uint32_t totalSize;                                                        \
-                                                                               \
-    className##Layout(size_t wordSize) {                                       \
-      if (wordSize == 8)                                                       \
-        init<uint64_t>();                                                      \
-      else {                                                                   \
-        assert(wordSize == 4);                                                 \
-        init<uint32_t>();                                                      \
-      }                                                                        \
-    }                                                                          \
-                                                                               \
-  private:                                                                     \
-    template <class Ptr> void init() {                                         \
-      FOR_EACH_FIELD(_INIT_OFFSET);                                            \
-      totalSize = sizeof(Layout<Ptr>);                                         \
-    }                                                                          \
-    template <class Ptr> struct Layout {                                       \
-      FOR_EACH_FIELD(_LAYOUT_ENTRY)                                            \
-    };                                                                         \
-  }

diff  --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index bdb125859b719..d484c4029f6be 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -9,12 +9,10 @@
 #include "ObjC.h"
 #include "InputFiles.h"
 #include "InputSection.h"
-#include "Layout.h"
 #include "OutputSegment.h"
 #include "Target.h"
 
 #include "lld/Common/ErrorHandler.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/BinaryFormat/MachO.h"
 #include "llvm/Bitcode/BitcodeReader.h"
 
@@ -68,228 +66,3 @@ bool macho::hasObjCSection(MemoryBufferRef mb) {
     return false;
   }
 }
-
-namespace {
-
-#define FOR_EACH_CATEGORY_FIELD(DO)                                            \
-  DO(Ptr, name)                                                                \
-  DO(Ptr, klass)                                                               \
-  DO(Ptr, instanceMethods)                                                     \
-  DO(Ptr, classMethods)                                                        \
-  DO(Ptr, protocols)                                                           \
-  DO(Ptr, instanceProps)                                                       \
-  DO(Ptr, classProps)
-
-CREATE_LAYOUT_CLASS(Category, FOR_EACH_CATEGORY_FIELD);
-
-#undef FOR_EACH_CATEGORY_FIELD
-
-#define FOR_EACH_CLASS_FIELD(DO)                                               \
-  DO(Ptr, metaClass)                                                           \
-  DO(Ptr, superClass)                                                          \
-  DO(Ptr, methodCache)                                                         \
-  DO(Ptr, vtable)                                                              \
-  DO(Ptr, roData)
-
-CREATE_LAYOUT_CLASS(Class, FOR_EACH_CLASS_FIELD);
-
-#undef FOR_EACH_CLASS_FIELD
-
-#define FOR_EACH_RO_CLASS_FIELD(DO)                                            \
-  DO(uint32_t, flags)                                                          \
-  DO(uint32_t, instanceStart)                                                  \
-  DO(Ptr, instanceSize)                                                        \
-  DO(Ptr, ivarLayout)                                                          \
-  DO(Ptr, name)                                                                \
-  DO(Ptr, baseMethods)                                                         \
-  DO(Ptr, baseProtocols)                                                       \
-  DO(Ptr, ivars)                                                               \
-  DO(Ptr, weakIvarLayout)                                                      \
-  DO(Ptr, baseProperties)
-
-CREATE_LAYOUT_CLASS(ROClass, FOR_EACH_RO_CLASS_FIELD);
-
-#undef FOR_EACH_RO_CLASS_FIELD
-
-#define FOR_EACH_LIST_HEADER(DO)                                               \
-  DO(uint32_t, size)                                                           \
-  DO(uint32_t, count)
-
-CREATE_LAYOUT_CLASS(ListHeader, FOR_EACH_LIST_HEADER);
-
-#undef FOR_EACH_LIST_HEADER
-
-#define FOR_EACH_METHOD(DO)                                                    \
-  DO(Ptr, name)                                                                \
-  DO(Ptr, type)                                                                \
-  DO(Ptr, impl)
-
-CREATE_LAYOUT_CLASS(Method, FOR_EACH_METHOD);
-
-#undef FOR_EACH_METHOD
-
-enum MethodContainerKind {
-  MCK_Class,
-  MCK_Category,
-};
-
-struct MethodContainer {
-  MethodContainerKind kind;
-  const ConcatInputSection *isec;
-};
-
-enum MethodKind {
-  MK_Instance,
-  MK_Static,
-};
-
-struct ObjcClass {
-  DenseMap<CachedHashStringRef, MethodContainer> instanceMethods;
-  DenseMap<CachedHashStringRef, MethodContainer> classMethods;
-};
-
-} // namespace
-
-class ObjcCategoryChecker {
-public:
-  ObjcCategoryChecker();
-  void parseCategory(const ConcatInputSection *catListIsec);
-
-private:
-  void parseClass(const Defined *classSym);
-  void parseMethods(const ConcatInputSection *methodsIsec,
-                    const Symbol *methodContainer,
-                    const ConcatInputSection *containerIsec,
-                    MethodContainerKind, MethodKind);
-
-  CategoryLayout catLayout;
-  ClassLayout classLayout;
-  ROClassLayout roClassLayout;
-  ListHeaderLayout listHeaderLayout;
-  MethodLayout methodLayout;
-
-  DenseMap<const Symbol *, ObjcClass> classMap;
-};
-
-ObjcCategoryChecker::ObjcCategoryChecker()
-    : catLayout(target->wordSize), classLayout(target->wordSize),
-      roClassLayout(target->wordSize), listHeaderLayout(target->wordSize),
-      methodLayout(target->wordSize) {}
-
-// \p r must point to an offset within a cstring section.
-static StringRef getReferentString(const Reloc &r) {
-  if (auto *isec = r.referent.dyn_cast<InputSection *>())
-    return cast<CStringInputSection>(isec)->getStringRefAtOffset(r.addend);
-  auto *d = cast<Defined>(r.referent.get<Symbol *>());
-  return cast<CStringInputSection>(d->isec)->getStringRefAtOffset(d->value + r.addend);
-}
-
-void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
-                                       const Symbol *methodContainerSym,
-                                       const ConcatInputSection *containerIsec,
-                                       MethodContainerKind mcKind,
-                                       MethodKind mKind) {
-  ObjcClass &klass = classMap[methodContainerSym];
-  for (const Reloc &r : methodsIsec->relocs) {
-    if ((r.offset - listHeaderLayout.totalSize) % methodLayout.totalSize !=
-        methodLayout.nameOffset)
-      continue;
-
-    CachedHashStringRef methodName(getReferentString(r));
-    auto &methodMap =
-        mKind == MK_Instance ? klass.instanceMethods : klass.classMethods;
-    if (methodMap
-            .try_emplace(methodName, MethodContainer{mcKind, containerIsec})
-            .second)
-      continue;
-
-    // We have a duplicate; generate a warning message.
-    const auto &mc = methodMap.lookup(methodName);
-    const Reloc *nameReloc = nullptr;
-    if (mc.kind == MCK_Category) {
-      nameReloc = mc.isec->getRelocAt(catLayout.nameOffset);
-    } else {
-      assert(mc.kind == MCK_Class);
-      const auto *roIsec = mc.isec->getRelocAt(classLayout.roDataOffset)
-                         ->getReferentInputSection();
-      nameReloc = roIsec->getRelocAt(roClassLayout.nameOffset);
-    }
-    StringRef containerName = getReferentString(*nameReloc);
-    StringRef methPrefix = mKind == MK_Instance ? "-" : "+";
-
-    // We should only ever encounter collisions when parsing category methods
-    // (since the Class struct is parsed before any of its categories).
-    assert(mcKind == MCK_Category);
-    StringRef newCatName =
-        getReferentString(*containerIsec->getRelocAt(catLayout.nameOffset));
-
-    StringRef containerType = mc.kind == MCK_Category ? "category" : "class";
-    warn("method '" + methPrefix + methodName.val() +
-         "' has conflicting definitions:\n>>> defined in category " +
-         newCatName + " from " + toString(containerIsec->getFile()) +
-         "\n>>> defined in " + containerType + " " + containerName + " from " +
-         toString(mc.isec->getFile()));
-  }
-}
-
-void ObjcCategoryChecker::parseCategory(const ConcatInputSection *catIsec) {
-  auto *classReloc = catIsec->getRelocAt(catLayout.klassOffset);
-  if (!classReloc)
-    return;
-
-  auto *classSym = classReloc->referent.get<Symbol *>();
-  if (auto *d = dyn_cast<Defined>(classSym))
-    if (!classMap.count(d))
-      parseClass(d);
-
-  if (const auto *r = catIsec->getRelocAt(catLayout.classMethodsOffset)) {
-    parseMethods(cast<ConcatInputSection>(r->getReferentInputSection()),
-                 classSym, catIsec, MCK_Category, MK_Static);
-  }
-
-  if (const auto *r = catIsec->getRelocAt(catLayout.instanceMethodsOffset)) {
-    parseMethods(cast<ConcatInputSection>(r->getReferentInputSection()),
-                 classSym, catIsec, MCK_Category, MK_Instance);
-  }
-}
-
-void ObjcCategoryChecker::parseClass(const Defined *classSym) {
-  // Given a Class struct, get its corresponding Methods struct
-  auto getMethodsIsec =
-      [&](const InputSection *classIsec) -> ConcatInputSection * {
-    if (const auto *r = classIsec->getRelocAt(classLayout.roDataOffset)) {
-      const auto *roIsec =
-          cast<ConcatInputSection>(r->getReferentInputSection());
-      if (const auto *r = roIsec->getRelocAt(roClassLayout.baseMethodsOffset)) {
-        if (auto *methodsIsec =
-                cast_or_null<ConcatInputSection>(r->getReferentInputSection()))
-          return methodsIsec;
-      }
-    }
-    return nullptr;
-  };
-
-  const auto *classIsec = cast<ConcatInputSection>(classSym->isec);
-
-  // Parse instance methods.
-  if (const auto *instanceMethodsIsec = getMethodsIsec(classIsec))
-    parseMethods(instanceMethodsIsec, classSym, classIsec, MCK_Class,
-                 MK_Instance);
-
-  // Class methods are contained in the metaclass.
-  if (const auto *r = classSym->isec->getRelocAt(classLayout.metaClassOffset))
-    if (const auto *classMethodsIsec = getMethodsIsec(
-            cast<ConcatInputSection>(r->getReferentInputSection())))
-      parseMethods(classMethodsIsec, classSym, classIsec, MCK_Class, MK_Static);
-}
-
-void objc::checkCategories() {
-  ObjcCategoryChecker checker;
-  for (const InputSection *isec : inputSections) {
-    if (isec->getName() == section_names::objcCatList)
-      for (const Reloc &r : isec->relocs) {
-        auto *catIsec = cast<ConcatInputSection>(r.getReferentInputSection());
-        checker.parseCategory(catIsec);
-      }
-  }
-}

diff  --git a/lld/MachO/ObjC.h b/lld/MachO/ObjC.h
index 560c5cc0bc509..67fa4114db007 100644
--- a/lld/MachO/ObjC.h
+++ b/lld/MachO/ObjC.h
@@ -20,9 +20,6 @@ constexpr const char metaclass[] = "_OBJC_METACLASS_$_";
 constexpr const char ehtype[] = "_OBJC_EHTYPE_$_";
 constexpr const char ivar[] = "_OBJC_IVAR_$_";
 
-// Check for duplicate method names within related categories / classes.
-void checkCategories();
-
 } // namespace objc
 
 bool hasObjCSection(llvm::MemoryBufferRef);

diff  --git a/lld/MachO/Relocations.cpp b/lld/MachO/Relocations.cpp
index 4e840c6912cc5..9e5ac69612cfd 100644
--- a/lld/MachO/Relocations.cpp
+++ b/lld/MachO/Relocations.cpp
@@ -21,16 +21,6 @@ using namespace lld::macho;
 static_assert(sizeof(void *) != 8 || sizeof(Reloc) == 24,
               "Try to minimize Reloc's size; we create many instances");
 
-InputSection *Reloc::getReferentInputSection() const {
-  if (const auto *sym = referent.dyn_cast<Symbol *>()) {
-    if (const auto *d = dyn_cast<Defined>(sym))
-      return d->isec;
-    return nullptr;
-  } else {
-    return referent.get<InputSection *>();
-  }
-}
-
 bool macho::validateSymbolRelocation(const Symbol *sym,
                                      const InputSection *isec, const Reloc &r) {
   const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);

diff  --git a/lld/MachO/Relocations.h b/lld/MachO/Relocations.h
index 5f161c8fcbfde..023d25a795a0d 100644
--- a/lld/MachO/Relocations.h
+++ b/lld/MachO/Relocations.h
@@ -67,8 +67,6 @@ struct Reloc {
         int64_t addend, llvm::PointerUnion<Symbol *, InputSection *> referent)
       : type(type), pcrel(pcrel), length(length), offset(offset),
         addend(addend), referent(referent) {}
-
-  InputSection *getReferentInputSection() const;
 };
 
 bool validateSymbolRelocation(const Symbol *, const InputSection *,

diff  --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index d480f7ed294a6..b7d0d563360a4 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -8,7 +8,6 @@
 
 #include "UnwindInfoSection.h"
 #include "InputSection.h"
-#include "Layout.h"
 #include "OutputSection.h"
 #include "OutputSegment.h"
 #include "SymbolTable.h"
@@ -89,18 +88,41 @@ using namespace lld::macho;
 
 // TODO(gkm): how do we align the 2nd-level pages?
 
-// The various fields in the on-disk representation of each compact unwind
-// entry.
-#define FOR_EACH_CU_FIELD(DO)                                                  \
-  DO(Ptr, functionAddress)                                                     \
-  DO(uint32_t, functionLength)                                                 \
-  DO(compact_unwind_encoding_t, encoding)                                      \
-  DO(Ptr, personality)                                                         \
-  DO(Ptr, lsda)
+// The offsets of various fields in the on-disk representation of each compact
+// unwind entry.
+struct CompactUnwindOffsets {
+  uint32_t functionAddress;
+  uint32_t functionLength;
+  uint32_t encoding;
+  uint32_t personality;
+  uint32_t lsda;
+
+  CompactUnwindOffsets(size_t wordSize) {
+    if (wordSize == 8)
+      init<uint64_t>();
+    else {
+      assert(wordSize == 4);
+      init<uint32_t>();
+    }
+  }
 
-CREATE_LAYOUT_CLASS(CompactUnwind, FOR_EACH_CU_FIELD);
+private:
+  template <class Ptr> void init() {
+    functionAddress = offsetof(Layout<Ptr>, functionAddress);
+    functionLength = offsetof(Layout<Ptr>, functionLength);
+    encoding = offsetof(Layout<Ptr>, encoding);
+    personality = offsetof(Layout<Ptr>, personality);
+    lsda = offsetof(Layout<Ptr>, lsda);
+  }
 
-#undef FOR_EACH_CU_FIELD
+  template <class Ptr> struct Layout {
+    Ptr functionAddress;
+    uint32_t functionLength;
+    compact_unwind_encoding_t encoding;
+    Ptr personality;
+    Ptr lsda;
+  };
+};
 
 // LLD's internal representation of a compact unwind entry.
 struct CompactUnwindEntry {
@@ -126,7 +148,7 @@ struct SecondLevelPage {
 // lengthy definition of UnwindInfoSection.
 class UnwindInfoSectionImpl final : public UnwindInfoSection {
 public:
-  UnwindInfoSectionImpl() : cuLayout(target->wordSize) {}
+  UnwindInfoSectionImpl() : cuOffsets(target->wordSize) {}
   uint64_t getSize() const override { return unwindInfoSize; }
   void prepare() override;
   void finalize() override;
@@ -140,7 +162,7 @@ class UnwindInfoSectionImpl final : public UnwindInfoSection {
 
   uint64_t unwindInfoSize = 0;
   std::vector<decltype(symbols)::value_type> symbolsVec;
-  CompactUnwindLayout cuLayout;
+  CompactUnwindOffsets cuOffsets;
   std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;
   EncodingMap commonEncodingIndexes;
   // The entries here will be in the same order as their originating symbols
@@ -239,7 +261,7 @@ void UnwindInfoSectionImpl::prepareRelocations(ConcatInputSection *isec) {
     // compact unwind entries that references them, and thus appear as section
     // relocs. There is no need to prepare them. We only prepare relocs for
     // personality functions.
-    if (r.offset != cuLayout.personalityOffset)
+    if (r.offset != cuOffsets.personality)
       continue;
 
     if (auto *s = r.referent.dyn_cast<Symbol *>()) {
@@ -351,13 +373,17 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
     auto buf = reinterpret_cast<const uint8_t *>(d->unwindEntry->data.data()) -
                target->wordSize;
     cu.functionLength =
-        support::endian::read32le(buf + cuLayout.functionLengthOffset);
-    cu.encoding = support::endian::read32le(buf + cuLayout.encodingOffset);
+        support::endian::read32le(buf + cuOffsets.functionLength);
+    cu.encoding = support::endian::read32le(buf + cuOffsets.encoding);
     for (const Reloc &r : d->unwindEntry->relocs) {
-      if (r.offset == cuLayout.personalityOffset)
+      if (r.offset == cuOffsets.personality) {
         cu.personality = r.referent.get<Symbol *>();
-      else if (r.offset == cuLayout.lsdaOffset)
-        cu.lsda = r.getReferentInputSection();
+      } else if (r.offset == cuOffsets.lsda) {
+        if (auto *referentSym = r.referent.dyn_cast<Symbol *>())
+          cu.lsda = cast<Defined>(referentSym)->isec;
+        else
+          cu.lsda = r.referent.get<InputSection *>();
+      }
     }
   });
 }

diff  --git a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libobjc.tbd b/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libobjc.tbd
deleted file mode 100644
index 9340c4abf93cd..0000000000000
--- a/lld/test/MachO/Inputs/MacOSX.sdk/usr/lib/libobjc.tbd
+++ /dev/null
@@ -1,10 +0,0 @@
---- !tapi-tbd-v3
-archs:            [ i386, x86_64, arm64 ]
-uuids:            [ 'i386: 00000000-0000-0000-0000-000000000000', 'x86_64: 00000000-0000-0000-0000-000000000001', 'arm64: 00000000-0000-0000-0000-000000000002' ]
-platform:         macosx
-install-name:     '/usr/lib/libobjc.dylib'
-current-version:  1281
-exports:
-  - archs:        [ i386, x86_64, arm64 ]
-    symbols:      [ __objc_empty_cache ]
-...

diff  --git a/lld/test/MachO/objc-category-conflicts.s b/lld/test/MachO/objc-category-conflicts.s
deleted file mode 100644
index c88783e751fdb..0000000000000
--- a/lld/test/MachO/objc-category-conflicts.s
+++ /dev/null
@@ -1,252 +0,0 @@
-# REQUIRES: x86
-# RUN: rm -rf %t; split-file %s %t
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o
-# RUN: %lld -dylib -lobjc %t/klass.o -o %t/libklass.dylib
-
-# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \
-# RUN:   /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT
-# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/libklass.dylib %t/cat1.o \
-# RUN:   %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT
-
-# CATCLS:      warning: method '+s1' has conflicting definitions:
-# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
-# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
-
-# CATCLS:      warning: method '-m1' has conflicting definitions:
-# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
-# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
-
-# CATCAT:      warning: method '+s2' has conflicting definitions:
-# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2.o
-# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
-
-# CATCAT:      warning: method '-m2' has conflicting definitions:
-# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2.o
-# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
-
-#--- cat1.s
-
-.include "objc-macros.s"
-
-## @interface Foo(Cat1)
-## -(void) m1;
-## -(void) m2;
-## +(void) s1;
-## +(void) s2;
-## @end
-## 
-## @implementation Foo(Cat1)
-## -(void) m1 {}
-## -(void) m2 {}
-## +(void) s1 {}
-## +(void) s2 {}
-## @end
-
-.section __DATA,__objc_catlist,regular,no_dead_strip
-  .quad __OBJC_$_CATEGORY_Foo_$_Cat1
-
-.section __DATA,__objc_const
-__OBJC_$_CATEGORY_Foo_$_Cat1:
-  .objc_classname "Cat1"
-  .quad _OBJC_CLASS_$_Foo
-  .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1
-  .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1
-  .quad 0
-  .quad 0
-  .quad 0
-  .long 64
-  .space 4
-
-__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1:
-  .long 24 # size of method entry
-  .long 2 # number of methods
-  .empty_objc_method "m1", "v16 at 0:8", "-[Foo(Cat1) m1]"
-  .empty_objc_method "m2", "v16 at 0:8", "-[Foo(Cat2) m2]"
-
-__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1:
-  .long 24
-  .long 2
-  .empty_objc_method "s1", "v16 at 0:8", "+[Foo(Cat1) s1]"
-  .empty_objc_method "s2", "v16 at 0:8", "+[Foo(Cat1) s2]"
-
-.section __DATA,__objc_imageinfo,regular,no_dead_strip
-  .long 0
-  .long 64
-
-.subsections_via_symbols
-
-#--- cat2.s
-
-.include "objc-macros.s"
-
-## @interface Foo(Cat2)
-## -(void) m2;
-## +(void) s2;
-## @end
-## 
-## @implementation Foo(Cat2)
-## -(void) m2 {}
-## +(void) s2 {}
-## @end
-
-.section __DATA,__objc_catlist,regular,no_dead_strip
-  .quad __OBJC_$_CATEGORY_Foo_$_Cat2
-
-.section __DATA,__objc_const
-__OBJC_$_CATEGORY_Foo_$_Cat2:
-  .objc_classname "Cat2"
-  .quad _OBJC_CLASS_$_Foo
-  .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2
-  .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2
-  .quad 0
-  .quad 0
-  .quad 0
-  .long 64
-  .space 4
-
-__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2:
-  .long 24
-  .long 1
-  .empty_objc_method "m2", "v16 at 0:8", "-[Foo(Cat2) m2]"
-
-__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2:
-  .long 24
-  .long 1
-  .empty_objc_method "s2", "v16 at 0:8", "+[Foo(Cat2) m2]"
-
-.section __DATA,__objc_imageinfo,regular,no_dead_strip
-  .long 0
-  .long 64
-
-.subsections_via_symbols
-
-#--- klass.s
-
-.include "objc-macros.s"
-
-## @interface Foo
-## -(void) m1;
-## +(void) s1;
-## @end
-##
-## @implementation Foo
-## -(void) m1 {}
-## +(void) s1 {}
-## @end
-
-.globl _OBJC_CLASS_$_Foo, _OBJC_METACLASS_$_Foo
-
-.section __DATA,__objc_data
-_OBJC_CLASS_$_Foo:
-  .quad _OBJC_METACLASS_$_Foo
-  .quad 0
-  .quad __objc_empty_cache
-  .quad 0
-  .quad __OBJC_CLASS_RO_$_Foo
-
-_OBJC_METACLASS_$_Foo:
-  .quad _OBJC_METACLASS_$_Foo
-  .quad _OBJC_CLASS_$_Foo
-  .quad __objc_empty_cache
-  .quad 0
-  .quad __OBJC_METACLASS_RO_$_Foo
-
-.section __DATA,__objc_const
-__OBJC_METACLASS_RO_$_Foo:
-  .long 3
-  .long 40
-  .long 40
-  .space 4
-  .quad 0
-  .objc_classname "Foo"
-  .quad __OBJC_$_CLASS_METHODS_Foo
-  .quad 0
-  .quad 0
-  .quad 0
-  .quad 0
-
-__OBJC_CLASS_RO_$_Foo:
-  .long 2
-  .long 0
-  .long 0
-  .space 4
-  .quad 0
-  .objc_classname "Foo"
-  .quad __OBJC_$_INSTANCE_METHODS_Foo
-  .quad 0
-  .quad 0
-  .quad 0
-  .quad 0
-
-__OBJC_$_CLASS_METHODS_Foo:
-  .long 24
-  .long 1
-  .empty_objc_method "s1", "v16 at 0:8", "+[Foo s1]"
-
-__OBJC_$_INSTANCE_METHODS_Foo:
-  .long 24
-  .long 1
-  .empty_objc_method "m1", "v16 at 0:8", "-[Foo m1]"
-
-.section __DATA,__objc_classlist,regular,no_dead_strip
-  .quad _OBJC_CLASS_$_Foo
-
-.section __DATA,__objc_imageinfo,regular,no_dead_strip
-  .long 0
-  .long 64
-
-.subsections_via_symbols
-
-#--- objc-macros.s
-
-# Macros for taking some of the boilerplate out of defining objc structs.
-
-# NOTE: \@ below is a variable that gets auto-incremented by the assembler on
-# each macro invocation. It serves as a mechanism for generating unique symbol
-# names for each macro call.
-
-.macro .objc_classname name
-
-  .section __TEXT,__objc_classname,cstring_literals
-  L_OBJC_CLASS_NAME_.\@:
-    .asciz "\name"
-
-  .section __DATA,__objc_const
-  .quad L_OBJC_CLASS_NAME_.\@
-
-.endm
-
-# struct method_t {
-#   const char *name;
-#   const char *type;
-#   void *impl;
-# }
-.macro .objc_method name, type, impl
-
-  .section __TEXT,__objc_methname,cstring_literals
-  L_OBJC_METH_VAR_NAME_.\@:
-    .asciz "\name"
-
-  .section __TEXT,__objc_methtype,cstring_literals
-  L_OBJC_METH_VAR_TYPE_.\@:
-    .asciz "\type"
-
-  .section __DATA,__objc_const
-    .quad L_OBJC_METH_VAR_NAME_.\@
-    .quad L_OBJC_METH_VAR_TYPE_.\@
-    .quad "\impl"
-
-.endm
-
-# Generate a method_t with a basic impl that just contains `ret`.
-.macro .empty_objc_method name, type, impl
-
-  .text
-  "\impl":
-    ret
-
-  .objc_method "\name", "\type", "\impl"
-
-.endm

diff  --git a/lld/test/MachO/objc-imageinfo.s b/lld/test/MachO/objc-imageinfo.s
index f83e93e7c0348..0523aac841c77 100644
--- a/lld/test/MachO/objc-imageinfo.s
+++ b/lld/test/MachO/objc-imageinfo.s
@@ -152,11 +152,14 @@ _OBJC_CLASS_$_FooClass:
 .space 40
 
 .section __DATA,__objc_const
+.p2align 3
+__OBJC_$_CATEGORY_INSTANCE_METHODS_FooClass_$_barcat:
+
 .p2align 3
 __OBJC_$_CATEGORY_FooClass_$_barcat:
 .quad L_CAT_NAME
 .quad _OBJC_CLASS_$_FooClass
-.quad 0
+.quad __OBJC_$_CATEGORY_INSTANCE_METHODS_FooClass_$_barcat
 .quad 0
 .quad 0
 .quad 0


        


More information about the llvm-commits mailing list