1 //===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "ExecutableAtoms.h" 11 #include "MachONormalizedFile.h" 12 #include "lld/Core/File.h" 13 #include "lld/Core/Writer.h" 14 #include "lld/ReaderWriter/MachOLinkingContext.h" 15 #include "llvm/BinaryFormat/MachO.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/ErrorHandling.h" 18 #include "llvm/Support/FileOutputBuffer.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <system_error> 21 22 using lld::mach_o::normalized::NormalizedFile; 23 24 namespace lld { 25 namespace mach_o { 26 27 class MachOWriter : public Writer { 28 public: MachOWriter(const MachOLinkingContext & ctxt)29 MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {} 30 writeFile(const lld::File & file,StringRef path)31 llvm::Error writeFile(const lld::File &file, StringRef path) override { 32 // Construct empty normalized file from atoms. 33 llvm::Expected<std::unique_ptr<NormalizedFile>> nFile = 34 normalized::normalizedFromAtoms(file, _ctx); 35 if (auto ec = nFile.takeError()) 36 return ec; 37 38 // For testing, write out yaml form of normalized file. 39 if (_ctx.printAtoms()) { 40 std::unique_ptr<Writer> yamlWriter = createWriterYAML(_ctx); 41 if (auto ec = yamlWriter->writeFile(file, "-")) 42 return ec; 43 } 44 45 // Write normalized file as mach-o binary. 46 return writeBinary(*nFile->get(), path); 47 } 48 createImplicitFiles(std::vector<std::unique_ptr<File>> & r)49 void createImplicitFiles(std::vector<std::unique_ptr<File>> &r) override { 50 // When building main executables, add _main as required entry point. 51 if (_ctx.outputTypeHasEntry()) 52 r.emplace_back(new CEntryFile(_ctx)); 53 // If this can link with dylibs, need helper function (dyld_stub_binder). 54 if (_ctx.needsStubsPass()) 55 r.emplace_back(new StubHelperFile(_ctx)); 56 // Final linked images can access a symbol for their mach_header. 57 if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) 58 r.emplace_back(new MachHeaderAliasFile(_ctx)); 59 } 60 private: 61 const MachOLinkingContext &_ctx; 62 }; 63 64 65 } // namespace mach_o 66 createWriterMachO(const MachOLinkingContext & context)67std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &context) { 68 return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(context)); 69 } 70 71 } // namespace lld 72