xref: /freebsd/contrib/llvm-project/lld/MachO/InputFiles.h (revision cab6a39d7b343596a5823e65c0f7b426551ec22d)
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 
14 #include "lld/Common/LLVM.h"
15 #include "lld/Common/Memory.h"
16 #include "llvm/ADT/DenseSet.h"
17 #include "llvm/ADT/SetVector.h"
18 #include "llvm/BinaryFormat/MachO.h"
19 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
20 #include "llvm/Object/Archive.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/TextAPI/MachO/InterfaceFile.h"
23 #include "llvm/TextAPI/MachO/TextAPIReader.h"
24 
25 #include <map>
26 #include <vector>
27 
28 namespace llvm {
29 namespace lto {
30 class InputFile;
31 } // namespace lto
32 class TarWriter;
33 } // namespace llvm
34 
35 namespace lld {
36 namespace macho {
37 
38 class InputSection;
39 class Symbol;
40 struct Reloc;
41 enum class RefState : uint8_t;
42 
43 // If --reproduce option is given, all input files are written
44 // to this tar archive.
45 extern std::unique_ptr<llvm::TarWriter> tar;
46 
47 // If .subsections_via_symbols is set, each InputSection will be split along
48 // symbol boundaries. The keys of a SubsectionMap represent the offsets of
49 // each subsection from the start of the original pre-split InputSection.
50 using SubsectionMap = std::map<uint32_t, InputSection *>;
51 
52 class InputFile {
53 public:
54   enum Kind {
55     ObjKind,
56     OpaqueKind,
57     DylibKind,
58     ArchiveKind,
59     BitcodeKind,
60   };
61 
62   virtual ~InputFile() = default;
63   Kind kind() const { return fileKind; }
64   StringRef getName() const { return name; }
65 
66   MemoryBufferRef mb;
67 
68   std::vector<Symbol *> symbols;
69   std::vector<SubsectionMap> subsections;
70   // Provides an easy way to sort InputFiles deterministically.
71   const int id;
72 
73   // If not empty, this stores the name of the archive containing this file.
74   // We use this string for creating error messages.
75   std::string archiveName;
76 
77 protected:
78   InputFile(Kind kind, MemoryBufferRef mb)
79       : mb(mb), id(idCount++), fileKind(kind), name(mb.getBufferIdentifier()) {}
80 
81   InputFile(Kind kind, const llvm::MachO::InterfaceFile &interface)
82       : id(idCount++), fileKind(kind), name(saver.save(interface.getPath())) {}
83 
84 private:
85   const Kind fileKind;
86   const StringRef name;
87 
88   static int idCount;
89 };
90 
91 // .o file
92 class ObjFile : public InputFile {
93 public:
94   ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName);
95   static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
96 
97   llvm::DWARFUnit *compileUnit = nullptr;
98   const uint32_t modTime;
99   ArrayRef<llvm::MachO::section_64> sectionHeaders;
100   std::vector<InputSection *> debugSections;
101 
102 private:
103   void parseSections(ArrayRef<llvm::MachO::section_64>);
104   void parseSymbols(ArrayRef<lld::structs::nlist_64> nList, const char *strtab,
105                     bool subsectionsViaSymbols);
106   Symbol *parseNonSectionSymbol(const structs::nlist_64 &sym, StringRef name);
107   void parseRelocations(const llvm::MachO::section_64 &, SubsectionMap &);
108   void parseDebugInfo();
109 };
110 
111 // command-line -sectcreate file
112 class OpaqueFile : public InputFile {
113 public:
114   OpaqueFile(MemoryBufferRef mb, StringRef segName, StringRef sectName);
115   static bool classof(const InputFile *f) { return f->kind() == OpaqueKind; }
116 };
117 
118 // .dylib file
119 class DylibFile : public InputFile {
120 public:
121   // Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the
122   // symbols in those sub-libraries will be available under the umbrella
123   // library's namespace. Those sub-libraries can also have their own
124   // re-exports. When loading a re-exported dylib, `umbrella` should be set to
125   // the root dylib to ensure symbols in the child library are correctly bound
126   // to the root. On the other hand, if a dylib is being directly loaded
127   // (through an -lfoo flag), then `umbrella` should be a nullptr.
128   explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella = nullptr);
129 
130   explicit DylibFile(const llvm::MachO::InterfaceFile &interface,
131                      DylibFile *umbrella = nullptr);
132 
133   static bool classof(const InputFile *f) { return f->kind() == DylibKind; }
134 
135   StringRef dylibName;
136   uint32_t compatibilityVersion = 0;
137   uint32_t currentVersion = 0;
138   uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
139   RefState refState;
140   bool reexport = false;
141   bool forceWeakImport = false;
142 };
143 
144 // .a file
145 class ArchiveFile : public InputFile {
146 public:
147   explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file);
148   static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
149   void fetch(const llvm::object::Archive::Symbol &sym);
150 
151 private:
152   std::unique_ptr<llvm::object::Archive> file;
153   // Keep track of children fetched from the archive by tracking
154   // which address offsets have been fetched already.
155   llvm::DenseSet<uint64_t> seen;
156 };
157 
158 class BitcodeFile : public InputFile {
159 public:
160   explicit BitcodeFile(MemoryBufferRef mb);
161   static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
162 
163   std::unique_ptr<llvm::lto::InputFile> obj;
164 };
165 
166 extern llvm::SetVector<InputFile *> inputFiles;
167 
168 llvm::Optional<MemoryBufferRef> readFile(StringRef path);
169 
170 const llvm::MachO::load_command *
171 findCommand(const llvm::MachO::mach_header_64 *, uint32_t type);
172 
173 } // namespace macho
174 
175 std::string toString(const macho::InputFile *file);
176 } // namespace lld
177 
178 #endif
179