[lld] r258197 - Add an ObjCPass to the MachO linker.

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 19 13:54:22 PST 2016


Author: pete
Date: Tue Jan 19 15:54:21 2016
New Revision: 258197

URL: http://llvm.org/viewvc/llvm-project?rev=258197&view=rev
Log:
Add an ObjCPass to the MachO linker.

This pass currently emits an objc image info section if one is required.

This section contains the aggregated version and flags for all of the input
files.

Added:
    lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp
    lld/trunk/test/mach-o/objc-image-info-pass-output.yaml
Modified:
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/lib/Core/DefinedAtom.cpp
    lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Jan 19 15:54:21 2016
@@ -134,6 +134,7 @@ public:
     typeCStringPtr,         // pointer to UTF8 C string [Darwin]
     typeObjCClassPtr,       // pointer to ObjC class [Darwin]
     typeObjC2CategoryList,  // pointers to ObjC category [Darwin]
+    typeObjCImageInfo,      // pointer to ObjC class [Darwin]
     typeDTraceDOF,          // runtime data for Dtrace [Darwin]
     typeInterposingTuples,  // tuples of interposing info for dyld [Darwin]
     typeTempLTO,            // temporary atom for bitcode reader

Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Jan 19 15:54:21 2016
@@ -154,7 +154,8 @@ public:
   void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
 
   ObjCConstraint objcConstraint() const { return _objcConstraint; }
-  void setObjcConstraint(ObjCConstraint v) { _objcConstraint = v; }
+
+  uint32_t swiftVersion() const { return _swiftVersion; }
 
   /// \brief Checks whether a given path on the filesystem exists.
   ///
@@ -310,6 +311,9 @@ public:
   /// Pass to add shims switching between thumb and arm mode.
   bool needsShimPass() const;
 
+  /// Pass to add objc image info and optimized objc data.
+  bool needsObjCPass() const;
+
   /// Magic symbol name stubs will need to help lazy bind.
   StringRef binderSymbolName() const;
 

Modified: lld/trunk/lib/Core/DefinedAtom.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/DefinedAtom.cpp?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/Core/DefinedAtom.cpp (original)
+++ lld/trunk/lib/Core/DefinedAtom.cpp Tue Jan 19 15:54:21 2016
@@ -43,6 +43,7 @@ DefinedAtom::ContentPermissions DefinedA
   case typeProcessedUnwindInfo:
   case typeRONote:
   case typeNoAlloc:
+  case typeObjCImageInfo:
     return permR__;
 
   case typeData:

Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Tue Jan 19 15:54:21 2016
@@ -13,6 +13,7 @@ add_lld_library(lldMachO
   MachONormalizedFileFromAtoms.cpp
   MachONormalizedFileToAtoms.cpp
   MachONormalizedFileYAML.cpp
+  ObjCPass.cpp
   ShimPass.cpp
   StubsPass.cpp
   TLVPass.cpp

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Jan 19 15:54:21 2016
@@ -326,6 +326,11 @@ bool MachOLinkingContext::needsCompactUn
   }
 }
 
+bool MachOLinkingContext::needsObjCPass() const {
+  // ObjC pass is only needed if any of the inputs were ObjC.
+  return _objcConstraint != objc_unknown;
+}
+
 bool MachOLinkingContext::needsShimPass() const {
   // Shim pass only used in final executables.
   if (_outputMachOType == MH_OBJECT)
@@ -590,6 +595,10 @@ bool MachOLinkingContext::validateImpl(r
 }
 
 void MachOLinkingContext::addPasses(PassManager &pm) {
+  // objc pass should be before layout pass.  Otherwise test cases may contain
+  // no atoms which confuses the layout pass.
+  if (needsObjCPass())
+    mach_o::addObjCPass(pm, *this);
   mach_o::addLayoutPass(pm, *this);
   if (needsStubsPass())
     mach_o::addStubsPass(pm, *this);
@@ -1060,6 +1069,7 @@ std::error_code MachOLinkingContext::han
     // Swift versions are different.
     return make_dynamic_error_code("different swift versions");
   }
+
   return std::error_code();
 }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue Jan 19 15:54:21 2016
@@ -88,6 +88,7 @@ const MachORelocatableSectionToAtomType
   ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
   ENTRY("__DATA", "__thread_bss",     S_THREAD_LOCAL_ZEROFILL,
                                                         typeTLVInitialZeroFill),
+  ENTRY("__DATA", "__objc_imageinfo", S_REGULAR,          typeObjCImageInfo),
   ENTRY("",       "",                 S_INTERPOSING,      typeInterposingTuples),
   ENTRY("__LD",   "__compact_unwind", S_REGULAR,
                                                          typeCompactUnwindInfo),
@@ -867,52 +868,35 @@ std::error_code addEHFrameReferences(con
   return ehFrameErr;
 }
 
-std::error_code parseObjCImageInfo(const NormalizedFile &normalizedFile,
+std::error_code parseObjCImageInfo(const Section &sect,
+                                   const NormalizedFile &normalizedFile,
                                    MachOFile &file) {
 
-  const Section *imageInfoSection = nullptr;
-  for (auto &section : normalizedFile.sections) {
-    if (section.segmentName == "__OBJC" &&
-        section.sectionName == "__image_info") {
-      imageInfoSection = §ion;
-      break;
-    }
-    if (section.segmentName == "__DATA" &&
-        section.sectionName == "__objc_imageinfo") {
-      imageInfoSection = §ion;
-      break;
-    }
-  }
-
-  // No image info section so nothing to do.
-  if (!imageInfoSection)
-    return std::error_code();
-
   //	struct objc_image_info  {
   //		uint32_t	version;	// initially 0
   //		uint32_t	flags;
   //	};
 
-  ArrayRef<uint8_t> content = imageInfoSection->content;
+  ArrayRef<uint8_t> content = sect.content;
   if (content.size() != 8)
-    return make_dynamic_error_code(imageInfoSection->segmentName + "/" +
-                                   imageInfoSection->sectionName +
+    return make_dynamic_error_code(sect.segmentName + "/" +
+                                   sect.sectionName +
                                    " in file " + file.path() +
                                    " should be 8 bytes in size");
 
   const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
   uint32_t version = read32(content.data(), isBig);
   if (version)
-    return make_dynamic_error_code(imageInfoSection->segmentName + "/" +
-                                   imageInfoSection->sectionName +
+    return make_dynamic_error_code(sect.segmentName + "/" +
+                                   sect.sectionName +
                                    " in file " + file.path() +
                                    " should have version=0");
 
   uint32_t flags = read32(content.data() + 4, isBig);
   if (flags & (MachOLinkingContext::objc_supports_gc |
                MachOLinkingContext::objc_gc_only))
-    return make_dynamic_error_code(imageInfoSection->segmentName + "/" +
-                                   imageInfoSection->sectionName +
+    return make_dynamic_error_code(sect.segmentName + "/" +
+                                   sect.sectionName +
                                    " in file " + file.path() +
                                    " uses GC.  This is not supported");
 
@@ -951,6 +935,11 @@ dylibToAtoms(const NormalizedFile &norma
 
 namespace normalized {
 
+static bool isObjCImageInfo(const Section &sect) {
+  return (sect.segmentName == "__OBJC" && sect.sectionName == "__image_info") ||
+    (sect.segmentName == "__DATA" && sect.sectionName == "__objc_imageinfo");
+}
+
 std::error_code
 normalizedObjectToAtoms(MachOFile *file,
                         const NormalizedFile &normalizedFile,
@@ -964,6 +953,18 @@ normalizedObjectToAtoms(MachOFile *file,
     DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump());
     if (isDebugInfoSection(sect))
       continue;
+
+
+    // If the file contains an objc_image_info struct, then we should parse the
+    // ObjC flags and Swift version.
+    if (isObjCImageInfo(sect)) {
+      if (std::error_code ec = parseObjCImageInfo(sect, normalizedFile, *file))
+        return ec;
+      // We then skip adding atoms for this section as we use the ObjCPass to
+      // re-emit this data after it has been aggregated for all files.
+      continue;
+    }
+
     bool customSectionName;
     DefinedAtom::ContentType atomType = atomTypeFromSection(sect,
                                                             customSectionName);
@@ -1007,11 +1008,6 @@ normalizedObjectToAtoms(MachOFile *file,
   if (std::error_code ec = addEHFrameReferences(normalizedFile, *file, *handler))
     return ec;
 
-  // If the file contains an objc_image_info struct, then we should parse the
-  // ObjC flags and Swift version.
-  if (std::error_code ec = parseObjCImageInfo(normalizedFile, *file))
-    return ec;
-
   // Process mach-o data-in-code regions array. That information is encoded in
   // atoms as References at each transition point.
   unsigned nextIndex = 0;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h Tue Jan 19 15:54:21 2016
@@ -21,6 +21,7 @@ void addStubsPass(PassManager &pm, const
 void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
 void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx);
 void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
+void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx);
 void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
 
 } // namespace mach_o

Added: lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp?rev=258197&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp (added)
+++ lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp Tue Jan 19 15:54:21 2016
@@ -0,0 +1,126 @@
+//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+
+#include "ArchHandler.h"
+#include "File.h"
+#include "MachOPasses.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Simple.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+
+namespace lld {
+namespace mach_o {
+
+//
+// ObjC Image Info Atom created by the ObjC pass.
+//
+class ObjCImageInfoAtom : public SimpleDefinedAtom {
+public:
+  ObjCImageInfoAtom(const File &file,
+                    MachOLinkingContext::ObjCConstraint objCConstraint,
+                    uint32_t swiftVersion)
+      : SimpleDefinedAtom(file) {
+
+    Data.info.version = 0;
+
+    switch (objCConstraint) {
+    case MachOLinkingContext::objc_unknown:
+      llvm_unreachable("Shouldn't run the objc pass without a constraint");
+    case MachOLinkingContext::objc_supports_gc:
+    case MachOLinkingContext::objc_gc_only:
+      llvm_unreachable("GC is not supported");
+    case MachOLinkingContext::objc_retainReleaseForSimulator:
+      // The retain/release for simulator flag is already the correct
+      // encoded value for the data so just set it here.
+      Data.info.flags = (uint32_t)objCConstraint;
+      break;
+    case MachOLinkingContext::objc_retainRelease:
+      // We don't need to encode this flag, so just leave the flags as 0.
+      Data.info.flags = 0;
+      break;
+    }
+
+    Data.info.flags |= (swiftVersion << 8);
+  }
+
+  ContentType contentType() const override {
+    return DefinedAtom::typeObjCImageInfo;
+  }
+
+  Alignment alignment() const override {
+    return 4;
+  }
+
+  uint64_t size() const override {
+    return 8;
+  }
+
+  ContentPermissions permissions() const override {
+    return DefinedAtom::permR__;
+  }
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(Data.bytes, size());
+  }
+
+private:
+
+  struct objc_image_info  {
+    uint32_t	version;
+    uint32_t	flags;
+  };
+
+  union {
+    objc_image_info info;
+    uint8_t bytes[8];
+  } Data;
+};
+
+class ObjCPass : public Pass {
+public:
+  ObjCPass(const MachOLinkingContext &context)
+      : _ctx(context),
+        _file("<mach-o objc pass>") {
+    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
+  }
+
+  std::error_code perform(SimpleFile &mergedFile) override {
+    // Add the image info.
+    mergedFile.addAtom(*getImageInfo());
+
+    return std::error_code();
+  }
+
+private:
+
+  const DefinedAtom* getImageInfo() {
+    return new (_file.allocator()) ObjCImageInfoAtom(_file,
+                                                     _ctx.objcConstraint(),
+                                                     _ctx.swiftVersion());
+  }
+
+  const MachOLinkingContext   &_ctx;
+  MachOFile                   _file;
+};
+
+
+
+void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) {
+  pm.add(llvm::make_unique<ObjCPass>(ctx));
+}
+
+} // end namespace mach_o
+} // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=258197&r1=258196&r2=258197&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Tue Jan 19 15:54:21 2016
@@ -418,6 +418,8 @@ template <> struct ScalarEnumerationTrai
                                           DefinedAtom::typeObjCClassPtr);
     io.enumCase(value, "objc-category-list",
                                           DefinedAtom::typeObjC2CategoryList);
+    io.enumCase(value, "objc-image-info",
+                                          DefinedAtom::typeObjCImageInfo);
     io.enumCase(value, "objc-class1",     DefinedAtom::typeObjC1Class);
     io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);
     io.enumCase(value, "interposing-tuples",

Added: lld/trunk/test/mach-o/objc-image-info-pass-output.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/objc-image-info-pass-output.yaml?rev=258197&view=auto
==============================================================================
--- lld/trunk/test/mach-o/objc-image-info-pass-output.yaml (added)
+++ lld/trunk/test/mach-o/objc-image-info-pass-output.yaml Tue Jan 19 15:54:21 2016
@@ -0,0 +1,30 @@
+# RUN: lld -flavor darwin -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s
+
+# Make sure that we have an objc image info in the output.  It should have
+# been generated by the objc pass.
+
+--- !mach-o
+arch:            x86_64
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version:  0.0
+current-version: 0.0
+has-UUID:        false
+OS:              unknown
+sections:
+  - segment:         __DATA
+    section:         __objc_imageinfo
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_NO_DEAD_STRIP ]
+    address:         0x0000000000000100
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 ]
+...
+
+# CHECK: --- !native
+# CHECK: path:            '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK:   - scope:           hidden
+# CHECK:     type:            objc-image-info
+# CHECK:     content:         [ 00, 00, 00, 00, 20, 02, 00, 00 ]
+# CHECK:     alignment:       4
+# CHECK: ...
\ No newline at end of file




More information about the llvm-commits mailing list