15ffd83dbSDimitry Andric //===- InputFiles.h ---------------------------------------------*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLD_MACHO_INPUT_FILES_H 105ffd83dbSDimitry Andric #define LLD_MACHO_INPUT_FILES_H 115ffd83dbSDimitry Andric 125ffd83dbSDimitry Andric #include "MachOStructs.h" 13fe6060f1SDimitry Andric #include "Target.h" 145ffd83dbSDimitry Andric 1581ad6265SDimitry Andric #include "lld/Common/DWARF.h" 165ffd83dbSDimitry Andric #include "lld/Common/LLVM.h" 17e8d8bef9SDimitry Andric #include "lld/Common/Memory.h" 18349cc55cSDimitry Andric #include "llvm/ADT/CachedHashString.h" 195ffd83dbSDimitry Andric #include "llvm/ADT/DenseSet.h" 20e8d8bef9SDimitry Andric #include "llvm/ADT/SetVector.h" 215ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h" 22e8d8bef9SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 235ffd83dbSDimitry Andric #include "llvm/Object/Archive.h" 245ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h" 2581ad6265SDimitry Andric #include "llvm/Support/Threading.h" 26fe6060f1SDimitry Andric #include "llvm/TextAPI/TextAPIReader.h" 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric #include <vector> 295ffd83dbSDimitry Andric 30e8d8bef9SDimitry Andric namespace llvm { 31e8d8bef9SDimitry Andric namespace lto { 32e8d8bef9SDimitry Andric class InputFile; 33e8d8bef9SDimitry Andric } // namespace lto 34fe6060f1SDimitry Andric namespace MachO { 35fe6060f1SDimitry Andric class InterfaceFile; 36fe6060f1SDimitry Andric } // namespace MachO 37e8d8bef9SDimitry Andric class TarWriter; 38e8d8bef9SDimitry Andric } // namespace llvm 39e8d8bef9SDimitry Andric 405ffd83dbSDimitry Andric namespace lld { 415ffd83dbSDimitry Andric namespace macho { 425ffd83dbSDimitry Andric 43fe6060f1SDimitry Andric struct PlatformInfo; 44fe6060f1SDimitry Andric class ConcatInputSection; 455ffd83dbSDimitry Andric class Symbol; 46349cc55cSDimitry Andric class Defined; 47bdd1243dSDimitry Andric class AliasSymbol; 485ffd83dbSDimitry Andric struct Reloc; 49e8d8bef9SDimitry Andric enum class RefState : uint8_t; 50e8d8bef9SDimitry Andric 51e8d8bef9SDimitry Andric // If --reproduce option is given, all input files are written 52e8d8bef9SDimitry Andric // to this tar archive. 53e8d8bef9SDimitry Andric extern std::unique_ptr<llvm::TarWriter> tar; 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric // If .subsections_via_symbols is set, each InputSection will be split along 56fe6060f1SDimitry Andric // symbol boundaries. The field offset represents the offset of the subsection 57fe6060f1SDimitry Andric // from the start of the original pre-split InputSection. 58349cc55cSDimitry Andric struct Subsection { 59349cc55cSDimitry Andric uint64_t offset = 0; 60349cc55cSDimitry Andric InputSection *isec = nullptr; 61fe6060f1SDimitry Andric }; 62349cc55cSDimitry Andric 63349cc55cSDimitry Andric using Subsections = std::vector<Subsection>; 6481ad6265SDimitry Andric class InputFile; 65349cc55cSDimitry Andric 6681ad6265SDimitry Andric class Section { 6781ad6265SDimitry Andric public: 6881ad6265SDimitry Andric InputFile *file; 6981ad6265SDimitry Andric StringRef segname; 7081ad6265SDimitry Andric StringRef name; 7181ad6265SDimitry Andric uint32_t flags; 7281ad6265SDimitry Andric uint64_t addr; 73349cc55cSDimitry Andric Subsections subsections; 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric Section(InputFile *file, StringRef segname, StringRef name, uint32_t flags, 7681ad6265SDimitry Andric uint64_t addr) 7781ad6265SDimitry Andric : file(file), segname(segname), name(name), flags(flags), addr(addr) {} 7881ad6265SDimitry Andric // Ensure pointers to Sections are never invalidated. 7981ad6265SDimitry Andric Section(const Section &) = delete; 8081ad6265SDimitry Andric Section &operator=(const Section &) = delete; 8181ad6265SDimitry Andric Section(Section &&) = delete; 8281ad6265SDimitry Andric Section &operator=(Section &&) = delete; 8381ad6265SDimitry Andric 8481ad6265SDimitry Andric private: 8581ad6265SDimitry Andric // Whether we have already split this section into individual subsections. 8681ad6265SDimitry Andric // For sections that cannot be split (e.g. literal sections), this is always 8781ad6265SDimitry Andric // false. 8881ad6265SDimitry Andric bool doneSplitting = false; 8981ad6265SDimitry Andric friend class ObjFile; 90349cc55cSDimitry Andric }; 915ffd83dbSDimitry Andric 9204eeddc0SDimitry Andric // Represents a call graph profile edge. 9304eeddc0SDimitry Andric struct CallGraphEntry { 9404eeddc0SDimitry Andric // The index of the caller in the symbol table. 9504eeddc0SDimitry Andric uint32_t fromIndex; 9604eeddc0SDimitry Andric // The index of the callee in the symbol table. 9704eeddc0SDimitry Andric uint32_t toIndex; 9804eeddc0SDimitry Andric // Number of calls from callee to caller in the profile. 9904eeddc0SDimitry Andric uint64_t count; 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric CallGraphEntry(uint32_t fromIndex, uint32_t toIndex, uint64_t count) 10281ad6265SDimitry Andric : fromIndex(fromIndex), toIndex(toIndex), count(count) {} 10304eeddc0SDimitry Andric }; 10404eeddc0SDimitry Andric 1055ffd83dbSDimitry Andric class InputFile { 1065ffd83dbSDimitry Andric public: 1075ffd83dbSDimitry Andric enum Kind { 1085ffd83dbSDimitry Andric ObjKind, 109e8d8bef9SDimitry Andric OpaqueKind, 1105ffd83dbSDimitry Andric DylibKind, 1115ffd83dbSDimitry Andric ArchiveKind, 112e8d8bef9SDimitry Andric BitcodeKind, 1135ffd83dbSDimitry Andric }; 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric virtual ~InputFile() = default; 1165ffd83dbSDimitry Andric Kind kind() const { return fileKind; } 117e8d8bef9SDimitry Andric StringRef getName() const { return name; } 118349cc55cSDimitry Andric static void resetIdCount() { idCount = 0; } 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric MemoryBufferRef mb; 121e8d8bef9SDimitry Andric 1225ffd83dbSDimitry Andric std::vector<Symbol *> symbols; 12381ad6265SDimitry Andric std::vector<Section *> sections; 124fcaf7f86SDimitry Andric ArrayRef<uint8_t> objCImageInfo; 125e8d8bef9SDimitry Andric 126e8d8bef9SDimitry Andric // If not empty, this stores the name of the archive containing this file. 127e8d8bef9SDimitry Andric // We use this string for creating error messages. 128e8d8bef9SDimitry Andric std::string archiveName; 1295ffd83dbSDimitry Andric 13004eeddc0SDimitry Andric // Provides an easy way to sort InputFiles deterministically. 13104eeddc0SDimitry Andric const int id; 13204eeddc0SDimitry Andric 13304eeddc0SDimitry Andric // True if this is a lazy ObjFile or BitcodeFile. 13404eeddc0SDimitry Andric bool lazy = false; 13504eeddc0SDimitry Andric 1365ffd83dbSDimitry Andric protected: 13704eeddc0SDimitry Andric InputFile(Kind kind, MemoryBufferRef mb, bool lazy = false) 13804eeddc0SDimitry Andric : mb(mb), id(idCount++), lazy(lazy), fileKind(kind), 13904eeddc0SDimitry Andric name(mb.getBufferIdentifier()) {} 1405ffd83dbSDimitry Andric 141fe6060f1SDimitry Andric InputFile(Kind, const llvm::MachO::InterfaceFile &); 1425ffd83dbSDimitry Andric 143*cb14a3feSDimitry Andric // If true, this input's arch is compatible with target. 1445f757f3fSDimitry Andric bool compatArch = true; 1455f757f3fSDimitry Andric 1465ffd83dbSDimitry Andric private: 1475ffd83dbSDimitry Andric const Kind fileKind; 148e8d8bef9SDimitry Andric const StringRef name; 149e8d8bef9SDimitry Andric 150e8d8bef9SDimitry Andric static int idCount; 1515ffd83dbSDimitry Andric }; 1525ffd83dbSDimitry Andric 15381ad6265SDimitry Andric struct FDE { 15481ad6265SDimitry Andric uint32_t funcLength; 15581ad6265SDimitry Andric Symbol *personality; 15681ad6265SDimitry Andric InputSection *lsda; 15781ad6265SDimitry Andric }; 15881ad6265SDimitry Andric 1595ffd83dbSDimitry Andric // .o file 160fe6060f1SDimitry Andric class ObjFile final : public InputFile { 1615ffd83dbSDimitry Andric public: 16204eeddc0SDimitry Andric ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName, 1635f757f3fSDimitry Andric bool lazy = false, bool forceHidden = false, bool compatArch = true, 1645f757f3fSDimitry Andric bool builtFromBitcode = false); 1650eae32dcSDimitry Andric ArrayRef<llvm::MachO::data_in_code_entry> getDataInCode() const; 166bdd1243dSDimitry Andric ArrayRef<uint8_t> getOptimizationHints() const; 16704eeddc0SDimitry Andric template <class LP> void parse(); 1685f757f3fSDimitry Andric template <class LP> 1695f757f3fSDimitry Andric void parseLinkerOptions(llvm::SmallVectorImpl<StringRef> &LinkerOptions); 1700eae32dcSDimitry Andric 1715ffd83dbSDimitry Andric static bool classof(const InputFile *f) { return f->kind() == ObjKind; } 172e8d8bef9SDimitry Andric 17381ad6265SDimitry Andric std::string sourceFile() const; 17481ad6265SDimitry Andric // Parses line table information for diagnostics. compileUnit should be used 17581ad6265SDimitry Andric // for other purposes. 17681ad6265SDimitry Andric lld::DWARFCache *getDwarf(); 17781ad6265SDimitry Andric 178e8d8bef9SDimitry Andric llvm::DWARFUnit *compileUnit = nullptr; 17981ad6265SDimitry Andric std::unique_ptr<lld::DWARFCache> dwarfCache; 18081ad6265SDimitry Andric Section *addrSigSection = nullptr; 181e8d8bef9SDimitry Andric const uint32_t modTime; 182972a253aSDimitry Andric bool forceHidden; 1835f757f3fSDimitry Andric bool builtFromBitcode; 184fe6060f1SDimitry Andric std::vector<ConcatInputSection *> debugSections; 18504eeddc0SDimitry Andric std::vector<CallGraphEntry> callGraph; 18681ad6265SDimitry Andric llvm::DenseMap<ConcatInputSection *, FDE> fdes; 187bdd1243dSDimitry Andric std::vector<AliasSymbol *> aliases; 188e8d8bef9SDimitry Andric 189e8d8bef9SDimitry Andric private: 19081ad6265SDimitry Andric llvm::once_flag initDwarf; 19104eeddc0SDimitry Andric template <class LP> void parseLazy(); 192349cc55cSDimitry Andric template <class SectionHeader> void parseSections(ArrayRef<SectionHeader>); 193fe6060f1SDimitry Andric template <class LP> 194fe6060f1SDimitry Andric void parseSymbols(ArrayRef<typename LP::section> sectionHeaders, 195fe6060f1SDimitry Andric ArrayRef<typename LP::nlist> nList, const char *strtab, 196e8d8bef9SDimitry Andric bool subsectionsViaSymbols); 197fe6060f1SDimitry Andric template <class NList> 198bdd1243dSDimitry Andric Symbol *parseNonSectionSymbol(const NList &sym, const char *strtab); 199349cc55cSDimitry Andric template <class SectionHeader> 200349cc55cSDimitry Andric void parseRelocations(ArrayRef<SectionHeader> sectionHeaders, 20181ad6265SDimitry Andric const SectionHeader &, Section &); 202e8d8bef9SDimitry Andric void parseDebugInfo(); 20381ad6265SDimitry Andric void splitEhFrames(ArrayRef<uint8_t> dataArr, Section &ehFrameSection); 20481ad6265SDimitry Andric void registerCompactUnwind(Section &compactUnwindSection); 20581ad6265SDimitry Andric void registerEhFrames(Section &ehFrameSection); 206e8d8bef9SDimitry Andric }; 207e8d8bef9SDimitry Andric 208e8d8bef9SDimitry Andric // command-line -sectcreate file 209fe6060f1SDimitry Andric class OpaqueFile final : public InputFile { 210e8d8bef9SDimitry Andric public: 211e8d8bef9SDimitry Andric OpaqueFile(MemoryBufferRef mb, StringRef segName, StringRef sectName); 212e8d8bef9SDimitry Andric static bool classof(const InputFile *f) { return f->kind() == OpaqueKind; } 2135ffd83dbSDimitry Andric }; 2145ffd83dbSDimitry Andric 215fe6060f1SDimitry Andric // .dylib or .tbd file 216fe6060f1SDimitry Andric class DylibFile final : public InputFile { 2175ffd83dbSDimitry Andric public: 2185ffd83dbSDimitry Andric // Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the 2195ffd83dbSDimitry Andric // symbols in those sub-libraries will be available under the umbrella 2205ffd83dbSDimitry Andric // library's namespace. Those sub-libraries can also have their own 2215ffd83dbSDimitry Andric // re-exports. When loading a re-exported dylib, `umbrella` should be set to 2225ffd83dbSDimitry Andric // the root dylib to ensure symbols in the child library are correctly bound 2235ffd83dbSDimitry Andric // to the root. On the other hand, if a dylib is being directly loaded 2245ffd83dbSDimitry Andric // (through an -lfoo flag), then `umbrella` should be a nullptr. 225fe6060f1SDimitry Andric explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella, 22681ad6265SDimitry Andric bool isBundleLoader, bool explicitlyLinked); 227e8d8bef9SDimitry Andric explicit DylibFile(const llvm::MachO::InterfaceFile &interface, 22881ad6265SDimitry Andric DylibFile *umbrella, bool isBundleLoader, 22981ad6265SDimitry Andric bool explicitlyLinked); 23061cfbce3SDimitry Andric explicit DylibFile(DylibFile *umbrella); 231fe6060f1SDimitry Andric 232fe6060f1SDimitry Andric void parseLoadCommands(MemoryBufferRef mb); 233fe6060f1SDimitry Andric void parseReexports(const llvm::MachO::InterfaceFile &interface); 2341fd87a68SDimitry Andric bool isReferenced() const { return numReferencedSymbols > 0; } 23561cfbce3SDimitry Andric bool isExplicitlyLinked() const; 23661cfbce3SDimitry Andric void setExplicitlyLinked() { explicitlyLinked = true; } 237e8d8bef9SDimitry Andric 2385ffd83dbSDimitry Andric static bool classof(const InputFile *f) { return f->kind() == DylibKind; } 2395ffd83dbSDimitry Andric 240fe6060f1SDimitry Andric StringRef installName; 241fe6060f1SDimitry Andric DylibFile *exportingFile = nullptr; 242fe6060f1SDimitry Andric DylibFile *umbrella; 243fe6060f1SDimitry Andric SmallVector<StringRef, 2> rpaths; 244e8d8bef9SDimitry Andric uint32_t compatibilityVersion = 0; 245e8d8bef9SDimitry Andric uint32_t currentVersion = 0; 246fe6060f1SDimitry Andric int64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel 2471fd87a68SDimitry Andric unsigned numReferencedSymbols = 0; 248e8d8bef9SDimitry Andric RefState refState; 2495ffd83dbSDimitry Andric bool reexport = false; 250fe6060f1SDimitry Andric bool forceNeeded = false; 251e8d8bef9SDimitry Andric bool forceWeakImport = false; 252fe6060f1SDimitry Andric bool deadStrippable = false; 25361cfbce3SDimitry Andric 25461cfbce3SDimitry Andric private: 25561cfbce3SDimitry Andric bool explicitlyLinked = false; // Access via isExplicitlyLinked(). 25661cfbce3SDimitry Andric 25761cfbce3SDimitry Andric public: 258fe6060f1SDimitry Andric // An executable can be used as a bundle loader that will load the output 259fe6060f1SDimitry Andric // file being linked, and that contains symbols referenced, but not 260fe6060f1SDimitry Andric // implemented in the bundle. When used like this, it is very similar 2611fd87a68SDimitry Andric // to a dylib, so we've used the same class to represent it. 262fe6060f1SDimitry Andric bool isBundleLoader; 263fe6060f1SDimitry Andric 26461cfbce3SDimitry Andric // Synthetic Dylib objects created by $ld$previous symbols in this dylib. 26561cfbce3SDimitry Andric // Usually empty. These synthetic dylibs won't have synthetic dylibs 26661cfbce3SDimitry Andric // themselves. 26761cfbce3SDimitry Andric SmallVector<DylibFile *, 2> extraDylibs; 26861cfbce3SDimitry Andric 269fe6060f1SDimitry Andric private: 27061cfbce3SDimitry Andric DylibFile *getSyntheticDylib(StringRef installName, uint32_t currentVersion, 27161cfbce3SDimitry Andric uint32_t compatVersion); 27261cfbce3SDimitry Andric 273fe6060f1SDimitry Andric bool handleLDSymbol(StringRef originalName); 274fe6060f1SDimitry Andric void handleLDPreviousSymbol(StringRef name, StringRef originalName); 275fe6060f1SDimitry Andric void handleLDInstallNameSymbol(StringRef name, StringRef originalName); 2760eae32dcSDimitry Andric void handleLDHideSymbol(StringRef name, StringRef originalName); 277fe6060f1SDimitry Andric void checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const; 278753f127fSDimitry Andric void parseExportedSymbols(uint32_t offset, uint32_t size); 279bdd1243dSDimitry Andric void loadReexport(StringRef path, DylibFile *umbrella, 280bdd1243dSDimitry Andric const llvm::MachO::InterfaceFile *currentTopLevelTapi); 2810eae32dcSDimitry Andric 2820eae32dcSDimitry Andric llvm::DenseSet<llvm::CachedHashStringRef> hiddenSymbols; 2835ffd83dbSDimitry Andric }; 2845ffd83dbSDimitry Andric 2855ffd83dbSDimitry Andric // .a file 286fe6060f1SDimitry Andric class ArchiveFile final : public InputFile { 2875ffd83dbSDimitry Andric public: 288972a253aSDimitry Andric explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file, 289972a253aSDimitry Andric bool forceHidden); 290349cc55cSDimitry Andric void addLazySymbols(); 291349cc55cSDimitry Andric void fetch(const llvm::object::Archive::Symbol &); 292349cc55cSDimitry Andric // LLD normally doesn't use Error for error-handling, but the underlying 293349cc55cSDimitry Andric // Archive library does, so this is the cleanest way to wrap it. 294349cc55cSDimitry Andric Error fetch(const llvm::object::Archive::Child &, StringRef reason); 295349cc55cSDimitry Andric const llvm::object::Archive &getArchive() const { return *file; }; 2965ffd83dbSDimitry Andric static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } 2975ffd83dbSDimitry Andric 2985ffd83dbSDimitry Andric private: 2995ffd83dbSDimitry Andric std::unique_ptr<llvm::object::Archive> file; 3005ffd83dbSDimitry Andric // Keep track of children fetched from the archive by tracking 3015ffd83dbSDimitry Andric // which address offsets have been fetched already. 3025ffd83dbSDimitry Andric llvm::DenseSet<uint64_t> seen; 303972a253aSDimitry Andric // Load all symbols with hidden visibility (-load_hidden). 304972a253aSDimitry Andric bool forceHidden; 3055ffd83dbSDimitry Andric }; 3065ffd83dbSDimitry Andric 307fe6060f1SDimitry Andric class BitcodeFile final : public InputFile { 308e8d8bef9SDimitry Andric public: 309fe6060f1SDimitry Andric explicit BitcodeFile(MemoryBufferRef mb, StringRef archiveName, 310972a253aSDimitry Andric uint64_t offsetInArchive, bool lazy = false, 3115f757f3fSDimitry Andric bool forceHidden = false, bool compatArch = true); 312e8d8bef9SDimitry Andric static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } 31304eeddc0SDimitry Andric void parse(); 314e8d8bef9SDimitry Andric 315e8d8bef9SDimitry Andric std::unique_ptr<llvm::lto::InputFile> obj; 316972a253aSDimitry Andric bool forceHidden; 31704eeddc0SDimitry Andric 31804eeddc0SDimitry Andric private: 31904eeddc0SDimitry Andric void parseLazy(); 320e8d8bef9SDimitry Andric }; 321e8d8bef9SDimitry Andric 322e8d8bef9SDimitry Andric extern llvm::SetVector<InputFile *> inputFiles; 323349cc55cSDimitry Andric extern llvm::DenseMap<llvm::CachedHashStringRef, MemoryBufferRef> cachedReads; 3245f757f3fSDimitry Andric extern llvm::SmallVector<StringRef> unprocessedLCLinkerOptions; 3255ffd83dbSDimitry Andric 326bdd1243dSDimitry Andric std::optional<MemoryBufferRef> readFile(StringRef path); 3275ffd83dbSDimitry Andric 32804eeddc0SDimitry Andric void extract(InputFile &file, StringRef reason); 32904eeddc0SDimitry Andric 330fe6060f1SDimitry Andric namespace detail { 331fe6060f1SDimitry Andric 332fe6060f1SDimitry Andric template <class CommandType, class... Types> 333fe6060f1SDimitry Andric std::vector<const CommandType *> 334fe6060f1SDimitry Andric findCommands(const void *anyHdr, size_t maxCommands, Types... types) { 335fe6060f1SDimitry Andric std::vector<const CommandType *> cmds; 336fe6060f1SDimitry Andric std::initializer_list<uint32_t> typesList{types...}; 337fe6060f1SDimitry Andric const auto *hdr = reinterpret_cast<const llvm::MachO::mach_header *>(anyHdr); 338fe6060f1SDimitry Andric const uint8_t *p = 339fe6060f1SDimitry Andric reinterpret_cast<const uint8_t *>(hdr) + target->headerSize; 340fe6060f1SDimitry Andric for (uint32_t i = 0, n = hdr->ncmds; i < n; ++i) { 341fe6060f1SDimitry Andric auto *cmd = reinterpret_cast<const CommandType *>(p); 342fe6060f1SDimitry Andric if (llvm::is_contained(typesList, cmd->cmd)) { 343fe6060f1SDimitry Andric cmds.push_back(cmd); 344fe6060f1SDimitry Andric if (cmds.size() == maxCommands) 345fe6060f1SDimitry Andric return cmds; 346fe6060f1SDimitry Andric } 347fe6060f1SDimitry Andric p += cmd->cmdsize; 348fe6060f1SDimitry Andric } 349fe6060f1SDimitry Andric return cmds; 350fe6060f1SDimitry Andric } 351fe6060f1SDimitry Andric 352fe6060f1SDimitry Andric } // namespace detail 353fe6060f1SDimitry Andric 354fe6060f1SDimitry Andric // anyHdr should be a pointer to either mach_header or mach_header_64 355fe6060f1SDimitry Andric template <class CommandType = llvm::MachO::load_command, class... Types> 356fe6060f1SDimitry Andric const CommandType *findCommand(const void *anyHdr, Types... types) { 357fe6060f1SDimitry Andric std::vector<const CommandType *> cmds = 358fe6060f1SDimitry Andric detail::findCommands<CommandType>(anyHdr, 1, types...); 359fe6060f1SDimitry Andric return cmds.size() ? cmds[0] : nullptr; 360fe6060f1SDimitry Andric } 361fe6060f1SDimitry Andric 362fe6060f1SDimitry Andric template <class CommandType = llvm::MachO::load_command, class... Types> 363fe6060f1SDimitry Andric std::vector<const CommandType *> findCommands(const void *anyHdr, 364fe6060f1SDimitry Andric Types... types) { 365fe6060f1SDimitry Andric return detail::findCommands<CommandType>(anyHdr, 0, types...); 366fe6060f1SDimitry Andric } 367e8d8bef9SDimitry Andric 368bdd1243dSDimitry Andric std::string replaceThinLTOSuffix(StringRef path); 3695ffd83dbSDimitry Andric } // namespace macho 3705ffd83dbSDimitry Andric 3715ffd83dbSDimitry Andric std::string toString(const macho::InputFile *file); 37281ad6265SDimitry Andric std::string toString(const macho::Section &); 3735ffd83dbSDimitry Andric } // namespace lld 3745ffd83dbSDimitry Andric 3755ffd83dbSDimitry Andric #endif 376