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

llvm-svn: 209700
This commit is contained in:
Nick Kledzik 2014-05-27 23:20:52 +00:00
parent 329912f54c
commit a4a08d31cf
5 changed files with 229 additions and 2 deletions

View File

@ -36,6 +36,14 @@ public:
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);

View File

@ -179,6 +179,12 @@ SectionInfo *Util::makeSection(DefinedAtom::ContentType type) {
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);

View File

@ -109,8 +109,9 @@ static void processUndefindeSymbol(MachOFile &file, const Symbol &sym,
}
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 @@ static error_code processSection(MachOFile &file, const Section &section,
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 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
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;
}

View File

@ -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 ]

View File

@ -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 ]