diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -10,6 +10,7 @@ #define LLD_MACHO_CONFIG_H #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/MachO.h" #include @@ -19,9 +20,10 @@ class Symbol; struct Configuration { - llvm::StringRef outputFile; Symbol *entry; - + llvm::MachO::HeaderFileType outputType; + llvm::StringRef installName; + llvm::StringRef outputFile; std::vector searchPaths; }; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -133,7 +133,10 @@ config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main")); config->outputFile = args.getLastArgValue(OPT_o, "a.out"); + config->installName = + args.getLastArgValue(OPT_install_name, config->outputFile); config->searchPaths = getSearchPaths(args); + config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE; for (opt::Arg *arg : args) { switch (arg->getOption().getID()) { @@ -147,7 +150,7 @@ } } - if (!isa(config->entry)) { + if (config->outputType == MH_EXECUTE && !isa(config->entry)) { error("undefined symbol: " + config->entry->getName()); return false; } diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -9,8 +9,14 @@ def arch: Separate<["-"], "arch">, MetaVarName<"">, HelpText<"Architecture to link">; +def dylib: Flag<["-"], "dylib">, HelpText<"Emit a shared library">; + def e: Separate<["-"], "e">, HelpText<"Name of entry point symbol">; +def install_name: Separate<["-"], "install_name">, + MetaVarName<"">, + HelpText<"Set the install path of the dynamic library.">; + def l: Joined<["-"], "l">, MetaVarName<"">, HelpText<"Base name of library searched for in -L directories">; diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -23,6 +23,7 @@ constexpr const char *binding = "__binding"; constexpr const char *header = "__mach_header"; constexpr const char *pageZero = "__pagezero"; +constexpr const char *export_ = "__export"; constexpr const char *stringPool = "__string_pool"; constexpr const char *symbolTable = "__symbol_table"; @@ -95,6 +96,21 @@ SmallVector contents; }; +// Stores a trie that describes the set of exported symbols. +class ExportSection : public InputSection { +public: + ExportSection(); + void finalizeContents(); + size_t getSize() const override { return contents.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. + bool isHidden() const override { return true; } + void writeTo(uint8_t *buf) override; + + SmallVector contents; +}; + // Stores the strings referenced by the symbol table. class StringPoolSection : public InputSection { public: diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "SyntheticSections.h" +#include "Config.h" #include "InputFiles.h" #include "OutputSegment.h" #include "SymbolTable.h" @@ -45,7 +46,7 @@ hdr->magic = MH_MAGIC_64; hdr->cputype = CPU_TYPE_X86_64; hdr->cpusubtype = CPU_SUBTYPE_X86_64_ALL | CPU_SUBTYPE_LIB64; - hdr->filetype = MH_EXECUTE; + hdr->filetype = config->outputType; hdr->ncmds = loadCommands.size(); hdr->sizeofcmds = sizeOfCmds; hdr->flags = MH_NOUNDEFS | MH_DYLDLINK | MH_TWOLEVEL; @@ -129,6 +130,44 @@ memcpy(buf, contents.data(), contents.size()); } +ExportSection::ExportSection() { + segname = segment_names::linkEdit; + name = section_names::export_; +} + +void ExportSection::finalizeContents() { + raw_svector_ostream os{contents}; + std::vector exported; + for (const Symbol *sym : symtab->getSymbols()) + if (auto *defined = dyn_cast(sym)) + exported.push_back(defined); + + if (exported.empty()) + return; + + if (exported.size() > 1) { + error("TODO: Unable to export more than 1 symbol"); + return; + } + + auto *sym = exported.front(); + os << (char)0; // Indicates non-leaf node + os << (char)1; // # of children + os << sym->getName() << '\0'; + encodeULEB128(sym->getName().size() + 4, os); // Leaf offset + + // Leaf node + uint64_t addr = sym->getVA() + ImageBase; + os << (char)(1 + getULEB128Size(addr)); + os << (char)0; // Flags + encodeULEB128(addr, os); + os << (char)0; // Terminator +} + +void ExportSection::writeTo(uint8_t *buf) { + memcpy(buf, contents.data(), contents.size()); +} + SymtabSection::SymtabSection(StringPoolSection &stringPoolSection) : stringPoolSection(stringPoolSection) { segname = segment_names::linkEdit; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -19,6 +19,7 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" using namespace llvm; @@ -52,14 +53,16 @@ uint64_t fileOff = 0; MachHeaderSection *headerSection = nullptr; BindingSection *bindingSection = nullptr; - SymtabSection *symtabSection = nullptr; + ExportSection *exportSection = nullptr; StringPoolSection *stringPoolSection = nullptr; + SymtabSection *symtabSection = nullptr; }; // LC_DYLD_INFO_ONLY stores the offsets of symbol import/export information. class LCDyldInfo : public LoadCommand { public: - LCDyldInfo(BindingSection *bindingSection) : bindingSection(bindingSection) {} + LCDyldInfo(BindingSection *bindingSection, ExportSection *exportSection) + : bindingSection(bindingSection), exportSection(exportSection) {} uint32_t getSize() const override { return sizeof(dyld_info_command); } @@ -71,13 +74,14 @@ c->bind_off = bindingSection->getFileOffset(); c->bind_size = bindingSection->getFileSize(); } - c->export_off = exportOff; - c->export_size = exportSize; + if (exportSection->isNeeded()) { + c->export_off = exportSection->getFileOffset(); + c->export_size = exportSection->getFileSize(); + } } BindingSection *bindingSection; - uint64_t exportOff = 0; - uint64_t exportSize = 0; + ExportSection *exportSection; }; class LCDysymtab : public LoadCommand { @@ -208,6 +212,30 @@ StringRef path; }; +class LCIdDylib : public LoadCommand { +public: + LCIdDylib(StringRef name) : name(name) {} + + uint32_t getSize() const override { + return alignTo(sizeof(dylib_command) + name.size() + 1, 8); + } + + void writeTo(uint8_t *buf) const override { + auto *c = reinterpret_cast(buf); + buf += sizeof(dylib_command); + + c->cmd = LC_ID_DYLIB; + c->cmdsize = getSize(); + c->dylib.name = sizeof(dylib_command); + + memcpy(buf, name.data(), name.size()); + buf[name.size()] = '\0'; + } + +private: + StringRef name; +}; + class LCLoadDylinker : public LoadCommand { public: uint32_t getSize() const override { @@ -245,6 +273,7 @@ // Make sure __LINKEDIT is the last segment (i.e. all its hidden // sections must be ordered after other sections). section_names::binding, + section_names::export_, section_names::symbolTable, section_names::stringPool, }; @@ -287,12 +316,24 @@ } void Writer::createLoadCommands() { - headerSection->addLoadCommand(make(bindingSection)); - headerSection->addLoadCommand(make()); + headerSection->addLoadCommand( + make(bindingSection, exportSection)); headerSection->addLoadCommand( make(symtabSection, stringPoolSection)); headerSection->addLoadCommand(make()); - headerSection->addLoadCommand(make()); + + switch (config->outputType) { + case MH_EXECUTE: + headerSection->addLoadCommand(make()); + headerSection->addLoadCommand(make()); + break; + case MH_DYLIB: + headerSection->addLoadCommand(make(config->installName)); + break; + default: + error("unhandled output file type"); + return; + } uint8_t segIndex = 0; for (OutputSegment *seg : outputSegments) { @@ -321,7 +362,18 @@ bindingSection = createInputSection(); stringPoolSection = createInputSection(); symtabSection = createInputSection(*stringPoolSection); - createInputSection(); + exportSection = createInputSection(); + + switch (config->outputType) { + case MH_EXECUTE: + createInputSection(); + break; + case MH_DYLIB: + break; + default: + error("unhandled output file type"); + return; + } } void Writer::sortSections() { @@ -403,6 +455,7 @@ // Fill __LINKEDIT contents. bindingSection->finalizeContents(); + exportSection->finalizeContents(); symtabSection->finalizeContents(); // Now that __LINKEDIT is filled out, do a proper calculation of its diff --git a/lld/include/lld/Common/Sort.h b/lld/include/lld/Common/Sort.h new file mode 100644 --- /dev/null +++ b/lld/include/lld/Common/Sort.h @@ -0,0 +1,33 @@ +//===- Sort.h ---------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_SORT_H +#define LLD_SORT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" + +namespace lld { + +// Sort the array such that order(arr[i]) ... order(arr[n]) is an ascending +// sequence. +template +void sortByOrder(llvm::MutableArrayRef arr, + llvm::function_ref order) { + std::vector> v; + for (T &value : arr) + v.emplace_back(order(value), value); + llvm::stable_sort(v, llvm::less_first()); + + for (size_t i = 0; i < v.size(); ++i) + arr[i] = v[i].second; +} + +} // namespace lld + +#endif diff --git a/lld/test/MachO/Inputs/goodbye-dylib.yaml b/lld/test/MachO/Inputs/goodbye-dylib.yaml deleted file mode 100644 --- a/lld/test/MachO/Inputs/goodbye-dylib.yaml +++ /dev/null @@ -1,175 +0,0 @@ -## This yaml file was originally generated from linking the following source -## input with ld64: -## -## .section __TEXT,__cstring -## .globl _goodbye_world -## -## _goodbye_world: -## .asciz "Goodbye world!\n" -## -## When lld can produce dylibs, we will use that instead for our test setup. - ---- !mach-o -FileHeader: - magic: 0xFEEDFACF - cputype: 0x01000007 - cpusubtype: 0x00000003 - filetype: 0x00000006 - ncmds: 11 - sizeofcmds: 624 - flags: 0x00100085 - reserved: 0x00000000 -LoadCommands: - - cmd: LC_SEGMENT_64 - cmdsize: 232 - segname: __TEXT - vmaddr: 0 - vmsize: 4096 - fileoff: 0 - filesize: 4096 - maxprot: 5 - initprot: 5 - nsects: 2 - flags: 0 - Sections: - - sectname: __text - segname: __TEXT - addr: 0x0000000000000FF0 - size: 0 - offset: 0x00000FF0 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x80000400 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - content: '' - - sectname: __cstring - segname: __TEXT - addr: 0x0000000000000FF0 - size: 16 - offset: 0x00000FF0 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000002 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - content: 476F6F6462796520776F726C64210A00 - - cmd: LC_SEGMENT_64 - cmdsize: 72 - segname: __LINKEDIT - vmaddr: 4096 - vmsize: 4096 - fileoff: 4096 - filesize: 72 - maxprot: 1 - initprot: 1 - nsects: 0 - flags: 0 - - cmd: LC_ID_DYLIB - cmdsize: 64 - dylib: - name: 24 - timestamp: 1 - current_version: 0 - compatibility_version: 0 - PayloadString: '@executable_path/libgoodbye.dylib' - ZeroPadBytes: 7 - - cmd: LC_DYLD_INFO_ONLY - cmdsize: 48 - rebase_off: 0 - rebase_size: 0 - bind_off: 0 - bind_size: 0 - weak_bind_off: 0 - weak_bind_size: 0 - lazy_bind_off: 0 - lazy_bind_size: 0 - export_off: 4096 - export_size: 24 - - cmd: LC_SYMTAB - cmdsize: 24 - symoff: 4128 - nsyms: 1 - stroff: 4144 - strsize: 24 - - cmd: LC_DYSYMTAB - cmdsize: 80 - ilocalsym: 0 - nlocalsym: 0 - iextdefsym: 0 - nextdefsym: 1 - iundefsym: 1 - nundefsym: 0 - tocoff: 0 - ntoc: 0 - modtaboff: 0 - nmodtab: 0 - extrefsymoff: 0 - nextrefsyms: 0 - indirectsymoff: 0 - nindirectsyms: 0 - extreloff: 0 - nextrel: 0 - locreloff: 0 - nlocrel: 0 - - cmd: LC_UUID - cmdsize: 24 - uuid: EA09CDDC-A3EA-3EB9-8C4F-334077FE6E5A - - cmd: LC_BUILD_VERSION - cmdsize: 32 - platform: 1 - minos: 659200 - sdk: 659200 - ntools: 1 - Tools: - - tool: 3 - version: 34734080 - - cmd: LC_SOURCE_VERSION - cmdsize: 16 - version: 0 - - cmd: LC_FUNCTION_STARTS - cmdsize: 16 - dataoff: 4120 - datasize: 8 - - cmd: LC_DATA_IN_CODE - cmdsize: 16 - dataoff: 4128 - datasize: 0 -LinkEditData: - ExportTrie: - TerminalSize: 0 - NodeOffset: 0 - Name: '' - Flags: 0x0000000000000000 - Address: 0x0000000000000000 - Other: 0x0000000000000000 - ImportName: '' - Children: - - TerminalSize: 3 - NodeOffset: 18 - Name: _goodbye_world - Flags: 0x0000000000000000 - Address: 0x0000000000000FF0 - Other: 0x0000000000000000 - ImportName: '' - NameList: - - n_strx: 2 - n_type: 0x0F - n_sect: 2 - n_desc: 0 - n_value: 4080 - StringTable: - - ' ' - - _goodbye_world - - '' - - '' - - '' - - '' - - '' - - '' - - '' -... diff --git a/lld/test/MachO/Inputs/hello-dylib.yaml b/lld/test/MachO/Inputs/hello-dylib.yaml deleted file mode 100644 --- a/lld/test/MachO/Inputs/hello-dylib.yaml +++ /dev/null @@ -1,169 +0,0 @@ -## This yaml file was originally generated from linking the following source -## input with ld64: -## -## .section __TEXT,__cstring -## .globl _hello_world -## -## _hello_world: -## .asciz "Hello world!\n" -## -## When lld can produce dylibs, we will use that instead for our test setup. - ---- !mach-o -FileHeader: - magic: 0xFEEDFACF - cputype: 0x01000007 - cpusubtype: 0x00000003 - filetype: 0x00000006 - ncmds: 11 - sizeofcmds: 616 - flags: 0x00100085 - reserved: 0x00000000 -LoadCommands: - - cmd: LC_SEGMENT_64 - cmdsize: 232 - segname: __TEXT - vmaddr: 0 - vmsize: 4096 - fileoff: 0 - filesize: 4096 - maxprot: 5 - initprot: 5 - nsects: 2 - flags: 0 - Sections: - - sectname: __text - segname: __TEXT - addr: 0x0000000000000FF2 - size: 0 - offset: 0x00000FF2 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x80000400 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - content: '' - - sectname: __cstring - segname: __TEXT - addr: 0x0000000000000FF2 - size: 14 - offset: 0x00000FF2 - align: 0 - reloff: 0x00000000 - nreloc: 0 - flags: 0x00000002 - reserved1: 0x00000000 - reserved2: 0x00000000 - reserved3: 0x00000000 - content: 48656C6C6F20776F726C64210A00 - - cmd: LC_SEGMENT_64 - cmdsize: 72 - segname: __LINKEDIT - vmaddr: 4096 - vmsize: 4096 - fileoff: 4096 - filesize: 64 - maxprot: 1 - initprot: 1 - nsects: 0 - flags: 0 - - cmd: LC_ID_DYLIB - cmdsize: 56 - dylib: - name: 24 - timestamp: 1 - current_version: 0 - compatibility_version: 0 - PayloadString: '@executable_path/libhello.dylib' - ZeroPadBytes: 1 - - cmd: LC_DYLD_INFO_ONLY - cmdsize: 48 - rebase_off: 0 - rebase_size: 0 - bind_off: 0 - bind_size: 0 - weak_bind_off: 0 - weak_bind_size: 0 - lazy_bind_off: 0 - lazy_bind_size: 0 - export_off: 4096 - export_size: 24 - - cmd: LC_SYMTAB - cmdsize: 24 - symoff: 4128 - nsyms: 1 - stroff: 4144 - strsize: 16 - - cmd: LC_DYSYMTAB - cmdsize: 80 - ilocalsym: 0 - nlocalsym: 0 - iextdefsym: 0 - nextdefsym: 1 - iundefsym: 1 - nundefsym: 0 - tocoff: 0 - ntoc: 0 - modtaboff: 0 - nmodtab: 0 - extrefsymoff: 0 - nextrefsyms: 0 - indirectsymoff: 0 - nindirectsyms: 0 - extreloff: 0 - nextrel: 0 - locreloff: 0 - nlocrel: 0 - - cmd: LC_UUID - cmdsize: 24 - uuid: 4826226E-9210-3984-A388-D5BD6D6DB368 - - cmd: LC_BUILD_VERSION - cmdsize: 32 - platform: 1 - minos: 659200 - sdk: 659200 - ntools: 1 - Tools: - - tool: 3 - version: 34734080 - - cmd: LC_SOURCE_VERSION - cmdsize: 16 - version: 0 - - cmd: LC_FUNCTION_STARTS - cmdsize: 16 - dataoff: 4120 - datasize: 8 - - cmd: LC_DATA_IN_CODE - cmdsize: 16 - dataoff: 4128 - datasize: 0 -LinkEditData: - ExportTrie: - TerminalSize: 0 - NodeOffset: 0 - Name: '' - Flags: 0x0000000000000000 - Address: 0x0000000000000000 - Other: 0x0000000000000000 - ImportName: '' - Children: - - TerminalSize: 3 - NodeOffset: 16 - Name: _hello_world - Flags: 0x0000000000000000 - Address: 0x0000000000000FF2 - Other: 0x0000000000000000 - ImportName: '' - NameList: - - n_strx: 2 - n_type: 0x0F - n_sect: 2 - n_desc: 0 - n_value: 4082 - StringTable: - - ' ' - - _hello_world - - '' -... diff --git a/lld/test/MachO/Inputs/libgoodbye.s b/lld/test/MachO/Inputs/libgoodbye.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/Inputs/libgoodbye.s @@ -0,0 +1,5 @@ +.section __TEXT,__cstring +.globl _goodbye_world + +_goodbye_world: +.asciz "Goodbye world!\n" diff --git a/lld/test/MachO/Inputs/libhello.s b/lld/test/MachO/Inputs/libhello.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/Inputs/libhello.s @@ -0,0 +1,5 @@ +.section __TEXT,__cstring +.globl _hello_world + +_hello_world: +.asciz "Hello world!\n" diff --git a/lld/test/MachO/dylib.s b/lld/test/MachO/dylib.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/dylib.s @@ -0,0 +1,35 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o + +# RUN: lld -flavor darwinnew -dylib -install_name @executable_path/libfoo.dylib \ +# RUN: %t.o -o %t.dylib +# CHECK: cmd: LC_ID_DYLIB +# CHECK-NOT: cmd: +# CHECK: PayloadString: '@executable_path/libfoo.dylib' + +## Check that -e is a no-op when -dylib is also passed. +# RUN: lld -flavor darwinnew -dylib %t.o -o %t.dylib -e missing_entry +# RUN: obj2yaml %t.dylib | FileCheck %s -DOUTPUT=%t.dylib --check-prefix=DEFAULT-INSTALL-NAME +# DEFAULT-INSTALL-NAME: cmd: LC_ID_DYLIB +# DEFAULT-INSTALL-NAME-NOT: cmd: +# DEFAULT-INSTALL-NAME: PayloadString: '[[OUTPUT]]' + +## Check for the absence of load commands / segments that should not be in a +## dylib. +# RUN: obj2yaml %t.dylib | FileCheck %s --check-prefix=NCHECK +# NCHECK-NOT: cmd: LC_LOAD_DYLINKER +# NCHECK-NOT: cmd: LC_MAIN +# NCHECK-NOT: Name: __PAGEZERO + +# RUN: llvm-objdump --syms --exports-trie %t.dylib | \ +# RUN: FileCheck %s --check-prefix=EXPORTS +# EXPORTS-LABEL: SYMBOL TABLE: +# EXPORTS: [[#%x, HELLO_WORLD_ADDR:]] {{.*}} _hello_world +# EXPORTS-LABEL: Exports trie: +# EXPORTS: 0x{{0*}}[[#%X, HELLO_WORLD_ADDR]] _hello_world + +.section __TEXT,__cstring +.globl _hello_world + +_hello_world: +.asciz "Hello world!\n" diff --git a/lld/test/MachO/dylink.s b/lld/test/MachO/dylink.s --- a/lld/test/MachO/dylink.s +++ b/lld/test/MachO/dylink.s @@ -1,7 +1,13 @@ # REQUIRES: x86 # RUN: mkdir -p %t -# RUN: yaml2obj %p/Inputs/hello-dylib.yaml -o %t/libhello.dylib -# RUN: yaml2obj %p/Inputs/goodbye-dylib.yaml -o %t/libgoodbye.dylib +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/libhello.s \ +# RUN: -o %t/libhello.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %p/Inputs/libgoodbye.s \ +# RUN: -o %t/libgoodbye.o +# RUN: lld -flavor darwinnew -dylib -install_name \ +# RUN: @executable_path/libhello.dylib %t/libhello.o -o %t/libhello.dylib +# RUN: lld -flavor darwinnew -dylib -install_name \ +# RUN: @executable_path/libgoodbye.dylib %t/libgoodbye.o -o %t/libgoodbye.dylib # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/dylink.o # RUN: lld -flavor darwinnew -o %t/dylink -Z -L%t -lhello -lgoodbye %t/dylink.o # RUN: llvm-objdump --bind -d %t/dylink | FileCheck %s diff --git a/lld/test/MachO/load-commands.s b/lld/test/MachO/load-commands.s --- a/lld/test/MachO/load-commands.s +++ b/lld/test/MachO/load-commands.s @@ -1,14 +1,19 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o # RUN: lld -flavor darwinnew -o %t %t.o -# RUN: obj2yaml %t | FileCheck %s -# Check for the presence of a couple of load commands that are essential for -# a working binary. +## Check for the presence of load commands that are essential for a working +## executable. +# RUN: obj2yaml %t | FileCheck %s +# CHECK-DAG: cmd: LC_DYLD_INFO_ONLY +# CHECK-DAG: cmd: LC_SYMTAB +# CHECK-DAG: cmd: LC_DYSYMTAB +# CHECK-DAG: cmd: LC_MAIN +# CHECK-DAG: cmd: LC_LOAD_DYLINKER -# CHECK-DAG: cmd: LC_DYLD_INFO_ONLY -# CHECK-DAG: cmd: LC_SYMTAB -# CHECK-DAG: cmd: LC_DYSYMTAB +## Check for the absence of load commands that should not be in an executable. +# RUN: obj2yaml %t | FileCheck %s --check-prefix=NCHECK +# NCHECK-NOT: cmd: LC_ID_DYLIB .text .global _main diff --git a/lld/test/MachO/symtab.s b/lld/test/MachO/symtab.s --- a/lld/test/MachO/symtab.s +++ b/lld/test/MachO/symtab.s @@ -14,41 +14,10 @@ # CHECK-NEXT: ] # CHECK-NEXT: Value: # CHECK-NEXT: } -# CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: bar -# CHECK-NEXT: Extern -# CHECK-NEXT: Type: Section (0xE) -# CHECK-NEXT: Section: __text (0x1) -# CHECK-NEXT: RefType: -# CHECK-NEXT: Flags [ (0x0) -# CHECK-NEXT: ] -# CHECK-NEXT: Value: -# CHECK-NEXT: } -# CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: foo -# CHECK-NEXT: Extern -# CHECK-NEXT: Type: Section (0xE) -# CHECK-NEXT: Section: __data -# CHECK-NEXT: RefType: -# CHECK-NEXT: Flags [ (0x0) -# CHECK-NEXT: ] -# CHECK-NEXT: Value: -# CHECK-NEXT: } # CHECK-NEXT: ] -.data -.global foo -foo: - .asciz "Hello world!\n" - -.text -.global bar .global _main _main: mov $0, %rax ret - -bar: - mov $2, %rax - ret