1 //===- InputFiles.h ---------------------------------------------*- C++ -*-===// 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 #ifndef LLD_MACHO_INPUT_FILES_H 10 #define LLD_MACHO_INPUT_FILES_H 11 12 #include "MachOStructs.h" 13 #include "Target.h" 14 15 #include "lld/Common/LLVM.h" 16 #include "lld/Common/Memory.h" 17 #include "llvm/ADT/CachedHashString.h" 18 #include "llvm/ADT/DenseSet.h" 19 #include "llvm/ADT/SetVector.h" 20 #include "llvm/BinaryFormat/MachO.h" 21 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 22 #include "llvm/Object/Archive.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "llvm/TextAPI/TextAPIReader.h" 25 26 #include <vector> 27 28 namespace llvm { 29 namespace lto { 30 class InputFile; 31 } // namespace lto 32 namespace MachO { 33 class InterfaceFile; 34 } // namespace MachO 35 class TarWriter; 36 } // namespace llvm 37 38 namespace lld { 39 namespace macho { 40 41 struct PlatformInfo; 42 class ConcatInputSection; 43 class Symbol; 44 class Defined; 45 struct Reloc; 46 enum class RefState : uint8_t; 47 48 // If --reproduce option is given, all input files are written 49 // to this tar archive. 50 extern std::unique_ptr<llvm::TarWriter> tar; 51 52 // If .subsections_via_symbols is set, each InputSection will be split along 53 // symbol boundaries. The field offset represents the offset of the subsection 54 // from the start of the original pre-split InputSection. 55 struct Subsection { 56 uint64_t offset = 0; 57 InputSection *isec = nullptr; 58 }; 59 60 using Subsections = std::vector<Subsection>; 61 class InputFile; 62 63 class Section { 64 public: 65 InputFile *file; 66 StringRef segname; 67 StringRef name; 68 uint32_t flags; 69 uint64_t addr; 70 Subsections subsections; 71 72 Section(InputFile *file, StringRef segname, StringRef name, uint32_t flags, 73 uint64_t addr) 74 : file(file), segname(segname), name(name), flags(flags), addr(addr) {} 75 // Ensure pointers to Sections are never invalidated. 76 Section(const Section &) = delete; 77 Section &operator=(const Section &) = delete; 78 Section(Section &&) = delete; 79 Section &operator=(Section &&) = delete; 80 81 private: 82 // Whether we have already split this section into individual subsections. 83 // For sections that cannot be split (e.g. literal sections), this is always 84 // false. 85 bool doneSplitting = false; 86 friend class ObjFile; 87 }; 88 89 // Represents a call graph profile edge. 90 struct CallGraphEntry { 91 // The index of the caller in the symbol table. 92 uint32_t fromIndex; 93 // The index of the callee in the symbol table. 94 uint32_t toIndex; 95 // Number of calls from callee to caller in the profile. 96 uint64_t count; 97 98 CallGraphEntry(uint32_t fromIndex, uint32_t toIndex, uint64_t count) 99 : fromIndex(fromIndex), toIndex(toIndex), count(count) {} 100 }; 101 102 class InputFile { 103 public: 104 enum Kind { 105 ObjKind, 106 OpaqueKind, 107 DylibKind, 108 ArchiveKind, 109 BitcodeKind, 110 }; 111 112 virtual ~InputFile() = default; 113 Kind kind() const { return fileKind; } 114 StringRef getName() const { return name; } 115 static void resetIdCount() { idCount = 0; } 116 117 MemoryBufferRef mb; 118 119 std::vector<Symbol *> symbols; 120 std::vector<Section *> sections; 121 122 // If not empty, this stores the name of the archive containing this file. 123 // We use this string for creating error messages. 124 std::string archiveName; 125 126 // Provides an easy way to sort InputFiles deterministically. 127 const int id; 128 129 // True if this is a lazy ObjFile or BitcodeFile. 130 bool lazy = false; 131 132 protected: 133 InputFile(Kind kind, MemoryBufferRef mb, bool lazy = false) 134 : mb(mb), id(idCount++), lazy(lazy), fileKind(kind), 135 name(mb.getBufferIdentifier()) {} 136 137 InputFile(Kind, const llvm::MachO::InterfaceFile &); 138 139 private: 140 const Kind fileKind; 141 const StringRef name; 142 143 static int idCount; 144 }; 145 146 struct FDE { 147 uint32_t funcLength; 148 Symbol *personality; 149 InputSection *lsda; 150 }; 151 152 // .o file 153 class ObjFile final : public InputFile { 154 public: 155 ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName, 156 bool lazy = false); 157 ArrayRef<llvm::MachO::data_in_code_entry> getDataInCode() const; 158 template <class LP> void parse(); 159 160 static bool classof(const InputFile *f) { return f->kind() == ObjKind; } 161 162 llvm::DWARFUnit *compileUnit = nullptr; 163 Section *addrSigSection = nullptr; 164 const uint32_t modTime; 165 std::vector<ConcatInputSection *> debugSections; 166 std::vector<CallGraphEntry> callGraph; 167 llvm::DenseMap<ConcatInputSection *, FDE> fdes; 168 169 private: 170 template <class LP> void parseLazy(); 171 template <class SectionHeader> void parseSections(ArrayRef<SectionHeader>); 172 template <class LP> 173 void parseSymbols(ArrayRef<typename LP::section> sectionHeaders, 174 ArrayRef<typename LP::nlist> nList, const char *strtab, 175 bool subsectionsViaSymbols); 176 template <class NList> 177 Symbol *parseNonSectionSymbol(const NList &sym, StringRef name); 178 template <class SectionHeader> 179 void parseRelocations(ArrayRef<SectionHeader> sectionHeaders, 180 const SectionHeader &, Section &); 181 void parseDebugInfo(); 182 void splitEhFrames(ArrayRef<uint8_t> dataArr, Section &ehFrameSection); 183 void registerCompactUnwind(Section &compactUnwindSection); 184 void registerEhFrames(Section &ehFrameSection); 185 }; 186 187 // command-line -sectcreate file 188 class OpaqueFile final : public InputFile { 189 public: 190 OpaqueFile(MemoryBufferRef mb, StringRef segName, StringRef sectName); 191 static bool classof(const InputFile *f) { return f->kind() == OpaqueKind; } 192 }; 193 194 // .dylib or .tbd file 195 class DylibFile final : public InputFile { 196 public: 197 // Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the 198 // symbols in those sub-libraries will be available under the umbrella 199 // library's namespace. Those sub-libraries can also have their own 200 // re-exports. When loading a re-exported dylib, `umbrella` should be set to 201 // the root dylib to ensure symbols in the child library are correctly bound 202 // to the root. On the other hand, if a dylib is being directly loaded 203 // (through an -lfoo flag), then `umbrella` should be a nullptr. 204 explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella, 205 bool isBundleLoader, bool explicitlyLinked); 206 explicit DylibFile(const llvm::MachO::InterfaceFile &interface, 207 DylibFile *umbrella, bool isBundleLoader, 208 bool explicitlyLinked); 209 210 void parseLoadCommands(MemoryBufferRef mb); 211 void parseReexports(const llvm::MachO::InterfaceFile &interface); 212 bool isReferenced() const { return numReferencedSymbols > 0; } 213 214 static bool classof(const InputFile *f) { return f->kind() == DylibKind; } 215 216 StringRef installName; 217 DylibFile *exportingFile = nullptr; 218 DylibFile *umbrella; 219 SmallVector<StringRef, 2> rpaths; 220 uint32_t compatibilityVersion = 0; 221 uint32_t currentVersion = 0; 222 int64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel 223 unsigned numReferencedSymbols = 0; 224 RefState refState; 225 bool reexport = false; 226 bool forceNeeded = false; 227 bool forceWeakImport = false; 228 bool deadStrippable = false; 229 bool explicitlyLinked = false; 230 // An executable can be used as a bundle loader that will load the output 231 // file being linked, and that contains symbols referenced, but not 232 // implemented in the bundle. When used like this, it is very similar 233 // to a dylib, so we've used the same class to represent it. 234 bool isBundleLoader; 235 236 private: 237 bool handleLDSymbol(StringRef originalName); 238 void handleLDPreviousSymbol(StringRef name, StringRef originalName); 239 void handleLDInstallNameSymbol(StringRef name, StringRef originalName); 240 void handleLDHideSymbol(StringRef name, StringRef originalName); 241 void checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const; 242 243 llvm::DenseSet<llvm::CachedHashStringRef> hiddenSymbols; 244 }; 245 246 // .a file 247 class ArchiveFile final : public InputFile { 248 public: 249 explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file); 250 void addLazySymbols(); 251 void fetch(const llvm::object::Archive::Symbol &); 252 // LLD normally doesn't use Error for error-handling, but the underlying 253 // Archive library does, so this is the cleanest way to wrap it. 254 Error fetch(const llvm::object::Archive::Child &, StringRef reason); 255 const llvm::object::Archive &getArchive() const { return *file; }; 256 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } 257 258 private: 259 std::unique_ptr<llvm::object::Archive> file; 260 // Keep track of children fetched from the archive by tracking 261 // which address offsets have been fetched already. 262 llvm::DenseSet<uint64_t> seen; 263 }; 264 265 class BitcodeFile final : public InputFile { 266 public: 267 explicit BitcodeFile(MemoryBufferRef mb, StringRef archiveName, 268 uint64_t offsetInArchive, bool lazy = false); 269 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } 270 void parse(); 271 272 std::unique_ptr<llvm::lto::InputFile> obj; 273 274 private: 275 void parseLazy(); 276 }; 277 278 extern llvm::SetVector<InputFile *> inputFiles; 279 extern llvm::DenseMap<llvm::CachedHashStringRef, MemoryBufferRef> cachedReads; 280 281 llvm::Optional<MemoryBufferRef> readFile(StringRef path); 282 283 void extract(InputFile &file, StringRef reason); 284 285 namespace detail { 286 287 template <class CommandType, class... Types> 288 std::vector<const CommandType *> 289 findCommands(const void *anyHdr, size_t maxCommands, Types... types) { 290 std::vector<const CommandType *> cmds; 291 std::initializer_list<uint32_t> typesList{types...}; 292 const auto *hdr = reinterpret_cast<const llvm::MachO::mach_header *>(anyHdr); 293 const uint8_t *p = 294 reinterpret_cast<const uint8_t *>(hdr) + target->headerSize; 295 for (uint32_t i = 0, n = hdr->ncmds; i < n; ++i) { 296 auto *cmd = reinterpret_cast<const CommandType *>(p); 297 if (llvm::is_contained(typesList, cmd->cmd)) { 298 cmds.push_back(cmd); 299 if (cmds.size() == maxCommands) 300 return cmds; 301 } 302 p += cmd->cmdsize; 303 } 304 return cmds; 305 } 306 307 } // namespace detail 308 309 // anyHdr should be a pointer to either mach_header or mach_header_64 310 template <class CommandType = llvm::MachO::load_command, class... Types> 311 const CommandType *findCommand(const void *anyHdr, Types... types) { 312 std::vector<const CommandType *> cmds = 313 detail::findCommands<CommandType>(anyHdr, 1, types...); 314 return cmds.size() ? cmds[0] : nullptr; 315 } 316 317 template <class CommandType = llvm::MachO::load_command, class... Types> 318 std::vector<const CommandType *> findCommands(const void *anyHdr, 319 Types... types) { 320 return detail::findCommands<CommandType>(anyHdr, 0, types...); 321 } 322 323 } // namespace macho 324 325 std::string toString(const macho::InputFile *file); 326 std::string toString(const macho::Section &); 327 } // namespace lld 328 329 #endif 330