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