[mach-o] Add support for initializers and terminators in object files

llvm-svn: 209700
diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h
index 0d41d60..9f505a2 100644
--- a/lld/lib/ReaderWriter/MachO/Atoms.h
+++ b/lld/lib/ReaderWriter/MachO/Atoms.h
@@ -36,6 +36,14 @@
 
   Scope scope() const override { return _scope; }
 
+  DeadStripKind deadStrip() const override {
+    if (_contentType == DefinedAtom::typeInitializerPtr)
+      return deadStripNever;
+    if (_contentType == DefinedAtom::typeTerminatorPtr)
+      return deadStripNever;
+    return deadStripNormal;
+  }
+
   ArrayRef<uint8_t> rawContent() const override {
     // Zerofill atoms have a content pointer which is null.
     assert(_content.data() != nullptr);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index c6d1e2c..1b548d9 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -179,6 +179,12 @@
   case DefinedAtom::typeZeroFill:
      return new (_allocator) SectionInfo("__DATA", "__bss",
                             S_ZEROFILL);
+  case DefinedAtom::typeInitializerPtr:
+     return new (_allocator) SectionInfo("__DATA", "__mod_init_func",
+                            S_MOD_INIT_FUNC_POINTERS);
+  case DefinedAtom::typeTerminatorPtr:
+     return new (_allocator) SectionInfo("__DATA", "__mod_term_func",
+                            S_MOD_TERM_FUNC_POINTERS);
   case DefinedAtom::typeLiteral4:
      return new (_allocator) SectionInfo("__TEXT", "__literal4",
                             S_4BYTE_LITERALS);
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 69ff193..2b87c23 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -109,8 +109,9 @@
 }
 
 static error_code processSection(MachOFile &file, const Section &section,
-                                 bool copyRefs) {
+                                 bool is64, bool copyRefs) {
   unsigned offset = 0;
+  const unsigned pointerSize = (is64 ? 8 : 4);
   switch (section.type) {
   case llvm::MachO::S_REGULAR:
     if (section.segmentName.equals("__TEXT") && 
@@ -142,6 +143,40 @@
   case llvm::MachO::S_ZEROFILL:
     // These sections are broken in to atoms based on symbols.
     break;
+  case S_MOD_INIT_FUNC_POINTERS:
+    if ((section.content.size() % pointerSize) != 0) {
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName
+                                     + " has type S_MOD_INIT_FUNC_POINTERS but "
+                                     "its size ("
+                                     + Twine(section.content.size())
+                                     + ") is not a multiple of "
+                                     + Twine(pointerSize));
+    }
+    for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
+      ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
+      file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
+                          DefinedAtom::typeInitializerPtr, bytes, copyRefs);
+      offset += pointerSize;
+    }
+    break;
+  case S_MOD_TERM_FUNC_POINTERS:
+    if ((section.content.size() % pointerSize) != 0) {
+      return make_dynamic_error_code(Twine("Section ") + section.segmentName
+                                     + "/" + section.sectionName
+                                     + " has type S_MOD_TERM_FUNC_POINTERS but "
+                                     "its size ("
+                                     + Twine(section.content.size())
+                                     + ") is not a multiple of "
+                                     + Twine(pointerSize));
+    }
+    for (size_t i = 0, e = section.content.size(); i != e; i += pointerSize) {
+      ArrayRef<uint8_t> bytes = section.content.slice(offset, pointerSize);
+      file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit,
+                          DefinedAtom::typeTerminatorPtr, bytes, copyRefs);
+      offset += pointerSize;
+    }
+    break;
   case llvm::MachO::S_CSTRING_LITERALS:
     for (size_t i = 0, e = section.content.size(); i != e; ++i) {
       if (section.content[i] == 0) {
@@ -227,8 +262,9 @@
     processUndefindeSymbol(*file, sym, copyRefs);
   }
   // Create atoms from sections that don't have symbols.
+  bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
   for (auto &sect : normalizedFile.sections) {
-    if (error_code ec = processSection(*file, sect, copyRefs))
+    if (error_code ec = processSection(*file, sect, is64, copyRefs))
       return ec;
   }