xref: /freebsd/contrib/llvm-project/lld/MachO/InputFiles.h (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===- InputFiles.h ---------------------------------------------*- C++ -*-===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #ifndef LLD_MACHO_INPUT_FILES_H
10*5ffd83dbSDimitry Andric #define LLD_MACHO_INPUT_FILES_H
11*5ffd83dbSDimitry Andric 
12*5ffd83dbSDimitry Andric #include "MachOStructs.h"
13*5ffd83dbSDimitry Andric 
14*5ffd83dbSDimitry Andric #include "lld/Common/LLVM.h"
15*5ffd83dbSDimitry Andric #include "llvm/ADT/DenseSet.h"
16*5ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h"
17*5ffd83dbSDimitry Andric #include "llvm/Object/Archive.h"
18*5ffd83dbSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
19*5ffd83dbSDimitry Andric #include "llvm/TextAPI/MachO/InterfaceFile.h"
20*5ffd83dbSDimitry Andric #include "llvm/TextAPI/MachO/TextAPIReader.h"
21*5ffd83dbSDimitry Andric 
22*5ffd83dbSDimitry Andric #include <map>
23*5ffd83dbSDimitry Andric #include <vector>
24*5ffd83dbSDimitry Andric 
25*5ffd83dbSDimitry Andric namespace lld {
26*5ffd83dbSDimitry Andric namespace macho {
27*5ffd83dbSDimitry Andric 
28*5ffd83dbSDimitry Andric class InputSection;
29*5ffd83dbSDimitry Andric class Symbol;
30*5ffd83dbSDimitry Andric struct Reloc;
31*5ffd83dbSDimitry Andric 
32*5ffd83dbSDimitry Andric // If .subsections_via_symbols is set, each InputSection will be split along
33*5ffd83dbSDimitry Andric // symbol boundaries. The keys of a SubsectionMap represent the offsets of
34*5ffd83dbSDimitry Andric // each subsection from the start of the original pre-split InputSection.
35*5ffd83dbSDimitry Andric using SubsectionMap = std::map<uint32_t, InputSection *>;
36*5ffd83dbSDimitry Andric 
37*5ffd83dbSDimitry Andric class InputFile {
38*5ffd83dbSDimitry Andric public:
39*5ffd83dbSDimitry Andric   enum Kind {
40*5ffd83dbSDimitry Andric     ObjKind,
41*5ffd83dbSDimitry Andric     DylibKind,
42*5ffd83dbSDimitry Andric     ArchiveKind,
43*5ffd83dbSDimitry Andric   };
44*5ffd83dbSDimitry Andric 
45*5ffd83dbSDimitry Andric   virtual ~InputFile() = default;
46*5ffd83dbSDimitry Andric   Kind kind() const { return fileKind; }
47*5ffd83dbSDimitry Andric   StringRef getName() const { return mb.getBufferIdentifier(); }
48*5ffd83dbSDimitry Andric 
49*5ffd83dbSDimitry Andric   MemoryBufferRef mb;
50*5ffd83dbSDimitry Andric   std::vector<Symbol *> symbols;
51*5ffd83dbSDimitry Andric   ArrayRef<llvm::MachO::section_64> sectionHeaders;
52*5ffd83dbSDimitry Andric   std::vector<SubsectionMap> subsections;
53*5ffd83dbSDimitry Andric 
54*5ffd83dbSDimitry Andric protected:
55*5ffd83dbSDimitry Andric   InputFile(Kind kind, MemoryBufferRef mb) : mb(mb), fileKind(kind) {}
56*5ffd83dbSDimitry Andric 
57*5ffd83dbSDimitry Andric   void parseSections(ArrayRef<llvm::MachO::section_64>);
58*5ffd83dbSDimitry Andric 
59*5ffd83dbSDimitry Andric   void parseSymbols(ArrayRef<lld::structs::nlist_64> nList, const char *strtab,
60*5ffd83dbSDimitry Andric                     bool subsectionsViaSymbols);
61*5ffd83dbSDimitry Andric 
62*5ffd83dbSDimitry Andric   void parseRelocations(const llvm::MachO::section_64 &, SubsectionMap &);
63*5ffd83dbSDimitry Andric 
64*5ffd83dbSDimitry Andric private:
65*5ffd83dbSDimitry Andric   const Kind fileKind;
66*5ffd83dbSDimitry Andric };
67*5ffd83dbSDimitry Andric 
68*5ffd83dbSDimitry Andric // .o file
69*5ffd83dbSDimitry Andric class ObjFile : public InputFile {
70*5ffd83dbSDimitry Andric public:
71*5ffd83dbSDimitry Andric   explicit ObjFile(MemoryBufferRef mb);
72*5ffd83dbSDimitry Andric   static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
73*5ffd83dbSDimitry Andric };
74*5ffd83dbSDimitry Andric 
75*5ffd83dbSDimitry Andric // .dylib file
76*5ffd83dbSDimitry Andric class DylibFile : public InputFile {
77*5ffd83dbSDimitry Andric public:
78*5ffd83dbSDimitry Andric   explicit DylibFile(std::shared_ptr<llvm::MachO::InterfaceFile> interface,
79*5ffd83dbSDimitry Andric                      DylibFile *umbrella = nullptr);
80*5ffd83dbSDimitry Andric 
81*5ffd83dbSDimitry Andric   // Mach-O dylibs can re-export other dylibs as sub-libraries, meaning that the
82*5ffd83dbSDimitry Andric   // symbols in those sub-libraries will be available under the umbrella
83*5ffd83dbSDimitry Andric   // library's namespace. Those sub-libraries can also have their own
84*5ffd83dbSDimitry Andric   // re-exports. When loading a re-exported dylib, `umbrella` should be set to
85*5ffd83dbSDimitry Andric   // the root dylib to ensure symbols in the child library are correctly bound
86*5ffd83dbSDimitry Andric   // to the root. On the other hand, if a dylib is being directly loaded
87*5ffd83dbSDimitry Andric   // (through an -lfoo flag), then `umbrella` should be a nullptr.
88*5ffd83dbSDimitry Andric   explicit DylibFile(MemoryBufferRef mb, DylibFile *umbrella = nullptr);
89*5ffd83dbSDimitry Andric 
90*5ffd83dbSDimitry Andric   static bool classof(const InputFile *f) { return f->kind() == DylibKind; }
91*5ffd83dbSDimitry Andric 
92*5ffd83dbSDimitry Andric   StringRef dylibName;
93*5ffd83dbSDimitry Andric   uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
94*5ffd83dbSDimitry Andric   bool reexport = false;
95*5ffd83dbSDimitry Andric   std::vector<DylibFile *> reexported;
96*5ffd83dbSDimitry Andric };
97*5ffd83dbSDimitry Andric 
98*5ffd83dbSDimitry Andric // .a file
99*5ffd83dbSDimitry Andric class ArchiveFile : public InputFile {
100*5ffd83dbSDimitry Andric public:
101*5ffd83dbSDimitry Andric   explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file);
102*5ffd83dbSDimitry Andric   static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
103*5ffd83dbSDimitry Andric   void fetch(const llvm::object::Archive::Symbol &sym);
104*5ffd83dbSDimitry Andric 
105*5ffd83dbSDimitry Andric private:
106*5ffd83dbSDimitry Andric   std::unique_ptr<llvm::object::Archive> file;
107*5ffd83dbSDimitry Andric   // Keep track of children fetched from the archive by tracking
108*5ffd83dbSDimitry Andric   // which address offsets have been fetched already.
109*5ffd83dbSDimitry Andric   llvm::DenseSet<uint64_t> seen;
110*5ffd83dbSDimitry Andric };
111*5ffd83dbSDimitry Andric 
112*5ffd83dbSDimitry Andric extern std::vector<InputFile *> inputFiles;
113*5ffd83dbSDimitry Andric 
114*5ffd83dbSDimitry Andric llvm::Optional<MemoryBufferRef> readFile(StringRef path);
115*5ffd83dbSDimitry Andric 
116*5ffd83dbSDimitry Andric } // namespace macho
117*5ffd83dbSDimitry Andric 
118*5ffd83dbSDimitry Andric std::string toString(const macho::InputFile *file);
119*5ffd83dbSDimitry Andric } // namespace lld
120*5ffd83dbSDimitry Andric 
121*5ffd83dbSDimitry Andric #endif
122