1 //===- lib/ReaderWriter/MachO/ExecutableAtoms.h ---------------------------===//
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_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
10 #define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
11 
12 #include "Atoms.h"
13 #include "File.h"
14 
15 #include "llvm/BinaryFormat/MachO.h"
16 
17 #include "lld/Core/DefinedAtom.h"
18 #include "lld/Core/File.h"
19 #include "lld/Core/LinkingContext.h"
20 #include "lld/Core/Reference.h"
21 #include "lld/Core/Simple.h"
22 #include "lld/Core/UndefinedAtom.h"
23 #include "lld/ReaderWriter/MachOLinkingContext.h"
24 
25 namespace lld {
26 namespace mach_o {
27 
28 
29 //
30 // CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
31 // phase will fail if "_main" is undefined.
32 //
33 class CEntryFile : public SimpleFile {
34 public:
CEntryFile(const MachOLinkingContext & context)35   CEntryFile(const MachOLinkingContext &context)
36       : SimpleFile("C entry", kindCEntryObject),
37        _undefMain(*this, context.entrySymbolName()) {
38     this->addAtom(_undefMain);
39   }
40 
41 private:
42   SimpleUndefinedAtom   _undefMain;
43 };
44 
45 
46 //
47 // StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
48 // the Resolveing phase will fail if "dyld_stub_binder" is undefined.
49 //
50 class StubHelperFile : public SimpleFile {
51 public:
StubHelperFile(const MachOLinkingContext & context)52   StubHelperFile(const MachOLinkingContext &context)
53       : SimpleFile("stub runtime", kindStubHelperObject),
54         _undefBinder(*this, context.binderSymbolName()) {
55     this->addAtom(_undefBinder);
56   }
57 
58 private:
59   SimpleUndefinedAtom   _undefBinder;
60 };
61 
62 
63 //
64 // MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
65 // of the mach_header for final linked images.
66 //
67 class MachHeaderAliasFile : public SimpleFile {
68 public:
MachHeaderAliasFile(const MachOLinkingContext & context)69   MachHeaderAliasFile(const MachOLinkingContext &context)
70     : SimpleFile("mach_header symbols", kindHeaderObject) {
71     StringRef machHeaderSymbolName;
72     DefinedAtom::Scope symbolScope = DefinedAtom::scopeLinkageUnit;
73     StringRef dsoHandleName;
74     switch (context.outputMachOType()) {
75     case llvm::MachO::MH_OBJECT:
76       machHeaderSymbolName = "__mh_object_header";
77       break;
78     case llvm::MachO::MH_EXECUTE:
79       machHeaderSymbolName = "__mh_execute_header";
80       symbolScope = DefinedAtom::scopeGlobal;
81       dsoHandleName = "___dso_handle";
82       break;
83     case llvm::MachO::MH_FVMLIB:
84       llvm_unreachable("no mach_header symbol for file type");
85     case llvm::MachO::MH_CORE:
86       llvm_unreachable("no mach_header symbol for file type");
87     case llvm::MachO::MH_PRELOAD:
88       llvm_unreachable("no mach_header symbol for file type");
89     case llvm::MachO::MH_DYLIB:
90       machHeaderSymbolName = "__mh_dylib_header";
91       dsoHandleName = "___dso_handle";
92       break;
93     case llvm::MachO::MH_DYLINKER:
94       machHeaderSymbolName = "__mh_dylinker_header";
95       dsoHandleName = "___dso_handle";
96       break;
97     case llvm::MachO::MH_BUNDLE:
98       machHeaderSymbolName = "__mh_bundle_header";
99       dsoHandleName = "___dso_handle";
100       break;
101     case llvm::MachO::MH_DYLIB_STUB:
102       llvm_unreachable("no mach_header symbol for file type");
103     case llvm::MachO::MH_DSYM:
104       llvm_unreachable("no mach_header symbol for file type");
105     case llvm::MachO::MH_KEXT_BUNDLE:
106       dsoHandleName = "___dso_handle";
107       break;
108     }
109     if (!machHeaderSymbolName.empty())
110       _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
111           *this, machHeaderSymbolName, symbolScope,
112           DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false,
113           true /* noDeadStrip */,
114           ArrayRef<uint8_t>(), DefinedAtom::Alignment(4096)));
115 
116     if (!dsoHandleName.empty())
117       _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
118           *this, dsoHandleName, DefinedAtom::scopeLinkageUnit,
119           DefinedAtom::typeDSOHandle, DefinedAtom::mergeNo, false,
120           true /* noDeadStrip */,
121           ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
122   }
123 
defined()124   const AtomRange<DefinedAtom> defined() const override {
125     return _definedAtoms;
126   }
undefined()127   const AtomRange<UndefinedAtom> undefined() const override {
128     return _noUndefinedAtoms;
129   }
130 
sharedLibrary()131   const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
132     return _noSharedLibraryAtoms;
133   }
134 
absolute()135   const AtomRange<AbsoluteAtom> absolute() const override {
136     return _noAbsoluteAtoms;
137   }
138 
clearAtoms()139   void clearAtoms() override {
140     _definedAtoms.clear();
141     _noUndefinedAtoms.clear();
142     _noSharedLibraryAtoms.clear();
143     _noAbsoluteAtoms.clear();
144   }
145 
146 
147 private:
148   mutable AtomVector<DefinedAtom> _definedAtoms;
149 };
150 
151 } // namespace mach_o
152 } // namespace lld
153 
154 #endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
155