diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -49,6 +49,27 @@ const StringRef segname; }; +// All sections in __LINKEDIT should inherit from this. +class LinkEditSection : public SyntheticSection { +public: + LinkEditSection(const char *segname, const char *name) + : SyntheticSection(segname, name) { + align = WordSize; + } + + virtual uint64_t getRawSize() const = 0; + + // codesign (or more specifically libstuff) checks that each section in + // __LINKEDIT ends where the next one starts -- no gaps are permitted. We + // therefore align every section's start and end points to WordSize. + // + // NOTE: This assumes that the extra bytes required for alignment can be + // zero-valued bytes. + uint64_t getSize() const override final { + return llvm::alignTo(getRawSize(), WordSize); + } +}; + // The header of the Mach-O file, which must have a file offset of zero. class MachHeaderSection : public SyntheticSection { public: @@ -105,11 +126,11 @@ }; // Stores bind opcodes for telling dyld which symbols to load non-lazily. -class BindingSection : public SyntheticSection { +class BindingSection : public LinkEditSection { public: BindingSection(); void finalizeContents(); - uint64_t getSize() const override { return contents.size(); } + uint64_t getRawSize() const override { return contents.size(); } // Like other sections in __LINKEDIT, the binding section is special: its // offsets are recorded in the LC_DYLD_INFO_ONLY load command, instead of in // section headers. @@ -194,11 +215,11 @@ void writeTo(uint8_t *buf) const override; }; -class LazyBindingSection : public SyntheticSection { +class LazyBindingSection : public LinkEditSection { public: LazyBindingSection(); void finalizeContents(); - uint64_t getSize() const override { return contents.size(); } + uint64_t getRawSize() const override { return contents.size(); } uint32_t encode(const DylibSymbol &); // Like other sections in __LINKEDIT, the lazy binding section is special: its // offsets are recorded in the LC_DYLD_INFO_ONLY load command, instead of in @@ -213,11 +234,11 @@ }; // Stores a trie that describes the set of exported symbols. -class ExportSection : public SyntheticSection { +class ExportSection : public LinkEditSection { public: ExportSection(); void finalizeContents(); - uint64_t getSize() const override { return size; } + uint64_t getRawSize() const override { return size; } // Like other sections in __LINKEDIT, the export section is special: its // offsets are recorded in the LC_DYLD_INFO_ONLY load command, instead of in // section headers. @@ -230,12 +251,12 @@ }; // Stores the strings referenced by the symbol table. -class StringTableSection : public SyntheticSection { +class StringTableSection : public LinkEditSection { public: StringTableSection(); // Returns the start offset of the added string. uint32_t addString(StringRef); - uint64_t getSize() const override { return size; } + uint64_t getRawSize() const override { return size; } // Like other sections in __LINKEDIT, the string table section is special: its // offsets are recorded in the LC_SYMTAB load command, instead of in section // headers. diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -94,7 +94,7 @@ } BindingSection::BindingSection() - : SyntheticSection(segment_names::linkEdit, section_names::binding) {} + : LinkEditSection(segment_names::linkEdit, section_names::binding) {} bool BindingSection::isNeeded() const { return bindings.size() != 0 || in.got->isNeeded(); @@ -301,7 +301,7 @@ } LazyBindingSection::LazyBindingSection() - : SyntheticSection(segment_names::linkEdit, section_names::lazyBinding) {} + : LinkEditSection(segment_names::linkEdit, section_names::lazyBinding) {} bool LazyBindingSection::isNeeded() const { return in.stubs->isNeeded(); } @@ -344,7 +344,7 @@ } ExportSection::ExportSection() - : SyntheticSection(segment_names::linkEdit, section_names::export_) {} + : LinkEditSection(segment_names::linkEdit, section_names::export_) {} void ExportSection::finalizeContents() { // TODO: We should check symbol visibility. @@ -358,11 +358,7 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection) : SyntheticSection(segment_names::linkEdit, section_names::symbolTable), - stringTableSection(stringTableSection) { - // TODO: When we introduce the SyntheticSections superclass, we should make - // all synthetic sections aligned to WordSize by default. - align = WordSize; -} + stringTableSection(stringTableSection) {} uint64_t SymtabSection::getSize() const { return symbols.size() * sizeof(structs::nlist_64); @@ -392,7 +388,7 @@ } StringTableSection::StringTableSection() - : SyntheticSection(segment_names::linkEdit, section_names::stringTable) {} + : LinkEditSection(segment_names::linkEdit, section_names::stringTable) {} uint32_t StringTableSection::addString(StringRef str) { uint32_t strx = size; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -353,7 +353,8 @@ return -1; } else if (segname == segment_names::linkEdit) { return StringSwitch(osec->name) - .Case(section_names::binding, -4) + .Case(section_names::binding, -5) + .Case(section_names::lazyBinding, -4) .Case(section_names::export_, -3) .Case(section_names::symbolTable, -2) .Case(section_names::stringTable, -1) diff --git a/lld/test/MachO/linkedit-contiguity.s b/lld/test/MachO/linkedit-contiguity.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/linkedit-contiguity.s @@ -0,0 +1,41 @@ +# REQUIRES: x86 +# RUN: mkdir -p %t + +## codesign requires that each setion in __LINKEDIT ends where the next one +## starts. This test enforces that invariant. +## TODO: Test other __LINKEDIT sections here as support for them gets added. +## Examples of such sections include the data for LC_CODE_SIGNATURE and +## LC_DATA_IN_CODE. + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/libhello.s \ +# RUN: -o %t/libhello.o +# RUN: lld -flavor darwinnew -dylib -L%S/Inputs/MacOSX.sdk/usr/lib \ +# RUN: -install_name @executable_path/libhello.dylib %t/libhello.o \ +# RUN: -o %t/libhello.dylib + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/test.o +# RUN: lld -flavor darwinnew -o %t/test \ +# RUN: -L%S/Inputs/MacOSX.sdk/usr/lib -L%t -lhello %t/test.o -lSystem + +# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s + +# CHECK: cmd LC_DYLD_INFO_ONLY +# CHECK-NEXT: cmdsize 48 +# CHECK-NEXT: rebase_off 0 +# CHECK-NEXT: rebase_size 0 +# CHECK-NEXT: bind_off [[#BIND_OFF:]] +# CHECK-NEXT: bind_size [[#BIND_SIZE:]] +# CHECK-NEXT: weak_bind_off 0 +# CHECK-NEXT: weak_bind_size 0 +# CHECK-NEXT: lazy_bind_off [[#LAZY_OFF: BIND_OFF + BIND_SIZE]] +# CHECK-NEXT: lazy_bind_size [[#LAZY_SIZE:]] +# CHECK-NEXT: export_off [[#EXPORT_OFF: LAZY_OFF + LAZY_SIZE]] +# CHECK-NEXT: export_size [[#]] + +.text +.globl _main +_main: + sub $8, %rsp # 16-byte-align the stack; dyld checks for this + callq _print_hello + add $8, %rsp + ret