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
25namespace lld {
26namespace 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//
33class CEntryFile : public SimpleFile {
34public:
35  CEntryFile(const MachOLinkingContext &context)
36      : SimpleFile("C entry", kindCEntryObject),
37       _undefMain(*this, context.entrySymbolName()) {
38    this->addAtom(_undefMain);
39  }
40
41private:
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//
50class StubHelperFile : public SimpleFile {
51public:
52  StubHelperFile(const MachOLinkingContext &context)
53      : SimpleFile("stub runtime", kindStubHelperObject),
54        _undefBinder(*this, context.binderSymbolName()) {
55    this->addAtom(_undefBinder);
56  }
57
58private:
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//
67class MachHeaderAliasFile : public SimpleFile {
68public:
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
124  const AtomRange<DefinedAtom> defined() const override {
125    return _definedAtoms;
126  }
127  const AtomRange<UndefinedAtom> undefined() const override {
128    return _noUndefinedAtoms;
129  }
130
131  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
132    return _noSharedLibraryAtoms;
133  }
134
135  const AtomRange<AbsoluteAtom> absolute() const override {
136    return _noAbsoluteAtoms;
137  }
138
139  void clearAtoms() override {
140    _definedAtoms.clear();
141    _noUndefinedAtoms.clear();
142    _noSharedLibraryAtoms.clear();
143    _noAbsoluteAtoms.clear();
144  }
145
146
147private:
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