aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
blob: 90e1d4704f342847d8910633ca3feb509852da68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//===-- MachOPlatform.h - Utilities for executing MachO in Orc --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Utilities for executing JIT'd MachO in Orc.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H
#define LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H

#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"

#include <future>
#include <thread>
#include <vector>

namespace llvm {
namespace orc {

/// Enable registration of JIT'd ObjC classes and selectors.
Error enableObjCRegistration(const char *PathToLibObjC);
bool objCRegistrationEnabled();

class MachOJITDylibInitializers {
public:
  struct SectionExtent {
    SectionExtent() = default;
    SectionExtent(JITTargetAddress Address, uint64_t NumPtrs)
        : Address(Address), NumPtrs(NumPtrs) {}
    JITTargetAddress Address = 0;
    uint64_t NumPtrs = 0;
  };

  using RawPointerSectionList = std::vector<SectionExtent>;

  void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) {
    this->ObjCImageInfoAddr = ObjCImageInfoAddr;
  }

  void addModInitsSection(SectionExtent ModInit) {
    ModInitSections.push_back(std::move(ModInit));
  }

  const RawPointerSectionList &getModInitsSections() const {
    return ModInitSections;
  }

  void addObjCSelRefsSection(SectionExtent ObjCSelRefs) {
    ObjCSelRefsSections.push_back(std::move(ObjCSelRefs));
  }

  const RawPointerSectionList &getObjCSelRefsSections() const {
    return ObjCSelRefsSections;
  }

  void addObjCClassListSection(SectionExtent ObjCClassList) {
    ObjCClassListSections.push_back(std::move(ObjCClassList));
  }

  const RawPointerSectionList &getObjCClassListSections() const {
    return ObjCClassListSections;
  }

  void runModInits() const;
  void registerObjCSelectors() const;
  Error registerObjCClasses() const;

private:

  JITTargetAddress ObjCImageInfoAddr;
  RawPointerSectionList ModInitSections;
  RawPointerSectionList ObjCSelRefsSections;
  RawPointerSectionList ObjCClassListSections;
};

class MachOJITDylibDeinitializers {};

/// Mediates between MachO initialization and ExecutionSession state.
class MachOPlatform : public Platform {
public:
  using InitializerSequence =
      std::vector<std::pair<JITDylib *, MachOJITDylibInitializers>>;

  using DeinitializerSequence =
      std::vector<std::pair<JITDylib *, MachOJITDylibDeinitializers>>;

  MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
                std::unique_ptr<MemoryBuffer> StandardSymbolsObject);

  ExecutionSession &getExecutionSession() const { return ES; }

  Error setupJITDylib(JITDylib &JD) override;
  Error notifyAdding(ResourceTracker &RT,
                     const MaterializationUnit &MU) override;
  Error notifyRemoving(ResourceTracker &RT) override;

  Expected<InitializerSequence> getInitializerSequence(JITDylib &JD);

  Expected<DeinitializerSequence> getDeinitializerSequence(JITDylib &JD);

private:
  // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func,
  // __objc_classlist and __sel_ref sections and records their extents so that
  // they can be run in the target process.
  class InitScraperPlugin : public ObjectLinkingLayer::Plugin {
  public:
    InitScraperPlugin(MachOPlatform &MP) : MP(MP) {}

    void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
                          jitlink::PassConfiguration &Config) override;

    LocalDependenciesMap getSyntheticSymbolLocalDependencies(
        MaterializationResponsibility &MR) override;

    // FIXME: We should be tentatively tracking scraped sections and discarding
    // if the MR fails.
    Error notifyFailed(MaterializationResponsibility &MR) override {
      return Error::success();
    }

    Error notifyRemovingResources(ResourceKey K) override {
      return Error::success();
    }

    void notifyTransferringResources(ResourceKey DstKey,
                                     ResourceKey SrcKey) override {}

  private:
    using InitSymbolDepMap =
        DenseMap<MaterializationResponsibility *, JITLinkSymbolVector>;

    void preserveInitSectionIfPresent(JITLinkSymbolVector &Syms,
                                      jitlink::LinkGraph &G,
                                      StringRef SectionName);

    Error processObjCImageInfo(jitlink::LinkGraph &G,
                               MaterializationResponsibility &MR);

    std::mutex InitScraperMutex;
    MachOPlatform &MP;
    DenseMap<JITDylib *, std::pair<uint32_t, uint32_t>> ObjCImageInfos;
    InitSymbolDepMap InitSymbolDeps;
  };

  void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
                        MachOJITDylibInitializers::SectionExtent ModInits,
                        MachOJITDylibInitializers::SectionExtent ObjCSelRefs,
                        MachOJITDylibInitializers::SectionExtent ObjCClassList);

  ExecutionSession &ES;
  ObjectLinkingLayer &ObjLinkingLayer;
  std::unique_ptr<MemoryBuffer> StandardSymbolsObject;

  DenseMap<JITDylib *, SymbolLookupSet> RegisteredInitSymbols;

  // InitSeqs gets its own mutex to avoid locking the whole session when
  // aggregating data from the jitlink.
  std::mutex InitSeqsMutex;
  DenseMap<JITDylib *, MachOJITDylibInitializers> InitSeqs;
};

} // end namespace orc
} // end namespace llvm

#endif // LLVM_EXECUTIONENGINE_ORC_MACHOPLATFORM_H