[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 §ion,
- 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 § : normalizedFile.sections) {
- if (error_code ec = processSection(*file, sect, copyRefs))
+ if (error_code ec = processSection(*file, sect, is64, copyRefs))
return ec;
}
diff --git a/lld/test/mach-o/parse-initializers32.yaml b/lld/test/mach-o/parse-initializers32.yaml
new file mode 100644
index 0000000..ede7b90
--- /dev/null
+++ b/lld/test/mach-o/parse-initializers32.yaml
@@ -0,0 +1,84 @@
+# RUN: lld -flavor darwin -arch i386 -r -print_atoms %s -o %t | FileCheck %s
+#
+# Test parsing of literal sections.
+#
+
+--- !mach-o
+arch: x86
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x89, 0xE5,
+ 0x5D, 0xC3, 0x55, 0x89, 0xE5, 0x5D, 0xC3 ]
+ - segment: __DATA
+ section: __mod_init_func
+ type: S_MOD_INIT_FUNC_POINTERS
+ attributes: [ ]
+ alignment: 2
+ address: 0x0000000000000044
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000000
+ type: GENERIC_RELOC_VANILLA
+ length: 2
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - offset: 0x00000004
+ type: GENERIC_RELOC_VANILLA
+ length: 2
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - segment: __DATA
+ section: __mod_term_func
+ type: S_MOD_TERM_FUNC_POINTERS
+ attributes: [ ]
+ alignment: 2
+ address: 0x0000000000000104
+ content: [ 0x0A, 0x00, 0x00, 0x00 ]
+global-symbols:
+ - name: _init
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _init2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000005
+ - name: _term
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x000000000000000A
+...
+
+
+# CHECK:defined-atoms:
+# CHECK: - type: initializer-pointer
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - type: initializer-pointer
+# CHECK: content: [ 05, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - type: terminator-pointer
+# CHECK: content: [ 0A, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - name: _init
+# CHECK: scope: global
+# CHECK: content: [ 55, 89, E5, 5D, C3 ]
+# CHECK: - name: _init2
+# CHECK: scope: global
+# CHECK: content: [ 55, 89, E5, 5D, C3 ]
+# CHECK: - name: _term
+# CHECK: scope: global
+# CHECK: content: [ 55, 89, E5, 5D, C3 ]
diff --git a/lld/test/mach-o/parse-initializers64.yaml b/lld/test/mach-o/parse-initializers64.yaml
new file mode 100644
index 0000000..d44ce1f
--- /dev/null
+++ b/lld/test/mach-o/parse-initializers64.yaml
@@ -0,0 +1,93 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
+#
+# Test parsing of literal sections.
+#
+
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
+ 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48, 0x89, 0xE5,
+ 0x5D, 0xC3 ]
+ - segment: __DATA
+ section: __mod_init_func
+ type: S_MOD_INIT_FUNC_POINTERS
+ attributes: [ ]
+ alignment: 0
+ address: 0x0000000000000100
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000000
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 1
+ - offset: 0x00000008
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 2
+ - segment: __DATA
+ section: __mod_term_func
+ type: S_MOD_TERM_FUNC_POINTERS
+ attributes: [ ]
+ alignment: 3
+ address: 0x0000000000000108
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000000
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 3
+global-symbols:
+ - name: _init
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _init2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000006
+ - name: _term
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x000000000000000C
+...
+
+
+# CHECK:defined-atoms:
+# CHECK: - type: initializer-pointer
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - type: initializer-pointer
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - type: terminator-pointer
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: dead-strip: never
+# CHECK: - name: _init
+# CHECK: scope: global
+# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]
+# CHECK: - name: _init2
+# CHECK: scope: global
+# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]
+# CHECK: - name: _term
+# CHECK: scope: global
+# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]