[lld] 9598778 - [lld-macho] Add support for emitting dylibs with a single symbol

Shoaib Meenai via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 27 13:35:29 PDT 2020


Author: Jez Ng
Date: 2020-04-27T13:33:46-07:00
New Revision: 9598778bd1910e77ccd399f2c9e979c8ecf98e55

URL: https://github.com/llvm/llvm-project/commit/9598778bd1910e77ccd399f2c9e979c8ecf98e55
DIFF: https://github.com/llvm/llvm-project/commit/9598778bd1910e77ccd399f2c9e979c8ecf98e55.diff

LOG: [lld-macho] Add support for emitting dylibs with a single symbol

Summary:
Add logic for emitting the correct set of load commands and segments
when `-dylib` is passed.

I haven't gotten to implementing a real export trie yet, so we can only
emit a single symbol, but it's enough to replace the YAML test files
introduced in D76252.

Differential Revision: https://reviews.llvm.org/D76908

Added: 
    lld/test/MachO/Inputs/libgoodbye.s
    lld/test/MachO/Inputs/libhello.s
    lld/test/MachO/dylib.s

Modified: 
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/MachO/Options.td
    lld/MachO/SyntheticSections.cpp
    lld/MachO/SyntheticSections.h
    lld/MachO/Writer.cpp
    lld/test/MachO/dylink.s
    lld/test/MachO/load-commands.s
    lld/test/MachO/symtab.s

Removed: 
    lld/test/MachO/Inputs/goodbye-dylib.yaml
    lld/test/MachO/Inputs/hello-dylib.yaml


################################################################################
diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 7542de052169..5a3566fd09ce 100644
--- 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 <vector>
 
@@ -19,9 +20,10 @@ namespace macho {
 class Symbol;
 
 struct Configuration {
-  llvm::StringRef outputFile;
   Symbol *entry;
-
+  llvm::MachO::HeaderFileType outputType;
+  llvm::StringRef installName;
+  llvm::StringRef outputFile;
   std::vector<llvm::StringRef> searchPaths;
 };
 

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index bff12009df03..abf5c09c6812 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -128,7 +128,10 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
 
   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;
 
   if (args.hasArg(OPT_v)) {
     message(getLLDVersion());
@@ -151,7 +154,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
     }
   }
 
-  if (!isa<Defined>(config->entry)) {
+  if (config->outputType == MH_EXECUTE && !isa<Defined>(config->entry)) {
     error("undefined symbol: " + config->entry->getName());
     return false;
   }

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 5a291d022edc..8327bb9d4abc 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -9,8 +9,14 @@ def Z: Flag<["-"], "Z">,
 def arch: Separate<["-"], "arch">, MetaVarName<"<arch-name>">,
   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<"<install-name>">,
+  HelpText<"Set the install path of the dynamic library.">;
+
 def l: Joined<["-"], "l">, MetaVarName<"<libname>">,
   HelpText<"Base name of library searched for in -L directories">;
 

diff  --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 5f08547aa127..f872f5ffb68c 100644
--- 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 @@ void MachHeaderSection::writeTo(uint8_t *buf) {
   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,45 @@ void BindingSection::writeTo(uint8_t *buf) {
   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<const Defined *> exported;
+  // TODO: We should check symbol visibility.
+  for (const Symbol *sym : symtab->getSymbols())
+    if (auto *defined = dyn_cast<Defined>(sym))
+      exported.push_back(defined);
+
+  if (exported.empty())
+    return;
+
+  if (exported.size() > 1) {
+    error("TODO: Unable to export more than 1 symbol");
+    return;
+  }
+
+  const Defined *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(StringTableSection &stringTableSection)
     : stringTableSection(stringTableSection) {
   segname = segment_names::linkEdit;
@@ -140,24 +180,24 @@ size_t SymtabSection::getSize() const {
 }
 
 void SymtabSection::finalizeContents() {
-  // TODO: We should filter out some symbols.
+  // TODO support other symbol types
   for (Symbol *sym : symtab->getSymbols())
-    symbols.push_back({sym, stringTableSection.addString(sym->getName())});
+    if (isa<Defined>(sym))
+      symbols.push_back({sym, stringTableSection.addString(sym->getName())});
 }
 
 void SymtabSection::writeTo(uint8_t *buf) {
   auto *nList = reinterpret_cast<nlist_64 *>(buf);
   for (const SymtabEntry &entry : symbols) {
+    nList->n_strx = entry.strx;
     // TODO support other symbol types
     // TODO populate n_desc
     if (auto defined = dyn_cast<Defined>(entry.sym)) {
-      nList->n_strx = entry.strx;
       nList->n_type = N_EXT | N_SECT;
       nList->n_sect = defined->isec->sectionIndex;
       // For the N_SECT symbol type, n_value is the address of the symbol
       nList->n_value = defined->value + defined->isec->addr;
     }
-
     ++nList;
   }
 }

diff  --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 3988772906ec..1d59312ac14e 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -23,6 +23,7 @@ namespace section_names {
 constexpr const char *pageZero = "__pagezero";
 constexpr const char *header = "__mach_header";
 constexpr const char *binding = "__binding";
+constexpr const char *export_ = "__export";
 constexpr const char *symbolTable = "__symbol_table";
 constexpr const char *stringTable = "__string_table";
 
@@ -95,6 +96,21 @@ class BindingSection : public InputSection {
   SmallVector<char, 128> 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<char, 128> contents;
+};
+
 // Stores the strings referenced by the symbol table.
 class StringTableSection : public InputSection {
 public:

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 7041df2d6e82..350ce40c7d07 100644
--- 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 @@ class Writer {
   uint64_t fileOff = 0;
   MachHeaderSection *headerSection = nullptr;
   BindingSection *bindingSection = nullptr;
-  SymtabSection *symtabSection = nullptr;
+  ExportSection *exportSection = nullptr;
   StringTableSection *stringTableSection = 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 @@ class LCDyldInfo : public LoadCommand {
       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 @@ class LCLoadDylib : public LoadCommand {
   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<dylib_command *>(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 {
@@ -253,6 +281,7 @@ class SectionComparator {
         {segment_names::linkEdit,
          {
              section_names::binding,
+             section_names::export_,
              section_names::symbolTable,
              section_names::stringTable,
          }},
@@ -309,12 +338,23 @@ void Writer::scanRelocations() {
 }
 
 void Writer::createLoadCommands() {
-  headerSection->addLoadCommand(make<LCDyldInfo>(bindingSection));
-  headerSection->addLoadCommand(make<LCLoadDylinker>());
+  headerSection->addLoadCommand(
+      make<LCDyldInfo>(bindingSection, exportSection));
   headerSection->addLoadCommand(
       make<LCSymtab>(symtabSection, stringTableSection));
   headerSection->addLoadCommand(make<LCDysymtab>());
-  headerSection->addLoadCommand(make<LCMain>());
+
+  switch (config->outputType) {
+  case MH_EXECUTE:
+    headerSection->addLoadCommand(make<LCMain>());
+    headerSection->addLoadCommand(make<LCLoadDylinker>());
+    break;
+  case MH_DYLIB:
+    headerSection->addLoadCommand(make<LCIdDylib>(config->installName));
+    break;
+  default:
+    llvm_unreachable("unhandled output file type");
+  }
 
   uint8_t segIndex = 0;
   for (OutputSegment *seg : outputSegments) {
@@ -343,7 +383,17 @@ void Writer::createHiddenSections() {
   bindingSection = createInputSection<BindingSection>();
   stringTableSection = createInputSection<StringTableSection>();
   symtabSection = createInputSection<SymtabSection>(*stringTableSection);
-  createInputSection<PageZeroSection>();
+  exportSection = createInputSection<ExportSection>();
+
+  switch (config->outputType) {
+  case MH_EXECUTE:
+    createInputSection<PageZeroSection>();
+    break;
+  case MH_DYLIB:
+    break;
+  default:
+    llvm_unreachable("unhandled output file type");
+  }
 }
 
 void Writer::sortSections() {
@@ -425,6 +475,7 @@ void Writer::run() {
 
   // 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/test/MachO/Inputs/goodbye-dylib.yaml b/lld/test/MachO/Inputs/goodbye-dylib.yaml
deleted file mode 100644
index 55797f7cc22a..000000000000
--- 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
index fde922856efa..000000000000
--- 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
index 000000000000..205f877fbf01
--- /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
index 000000000000..4b09ab430418
--- /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
index 000000000000..507a7de87423
--- /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
+# RUN: llvm-objdump --macho --dylib-id %t.dylib | FileCheck %s
+# CHECK: @executable_path/libfoo.dylib
+
+## If we are building a dylib, we shouldn't error out even if we are passed
+## a flag for a missing entry symbol (since dylibs don't have entry symbols).
+## Also check that we come up with the right install name if one isn't
+## specified.
+# RUN: lld -flavor darwinnew -dylib %t.o -o %t.defaultInstallName.dylib -e missing_entry
+# RUN: obj2yaml %t.defaultInstallName.dylib | FileCheck %s -DOUTPUT=%t.defaultInstallName.dylib --check-prefix=DEFAULT-INSTALL-NAME
+# DEFAULT-INSTALL-NAME: [[OUTPUT]]
+
+## Check for the absence of load commands / segments that should not be in a
+## dylib.
+# RUN: llvm-objdump --macho --all-headers %t.dylib | FileCheck %s --check-prefix=NCHECK
+# NCHECK-NOT: cmd LC_LOAD_DYLINKER
+# NCHECK-NOT: cmd LC_MAIN
+# NCHECK-NOT: segname __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
index 6ec7ed05a40f..18265aa0ffe9 100644
--- 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
index 298cb76cc55a..c9f5d9b5c218 100644
--- 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: llvm-objdump --macho --all-headers %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: llvm-objdump --macho --all-headers %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
index 44a016912bd6..a647e4a5bb39 100644
--- 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


        


More information about the llvm-commits mailing list