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 21using lld::mach_o::normalized::NormalizedFile; 22 23namespace lld { 24namespace mach_o { 25 26class MachOWriter : public Writer { 27public: 28 MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {} 29 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 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 } 59private: 60 const MachOLinkingContext &_ctx; 61 }; 62 63 64} // namespace mach_o 65 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