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