xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===------------- JITLink.cpp - Core Run-time JIT linker APIs ------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric //                     The LLVM Compiler Infrastructure
4*0b57cec5SDimitry Andric //
5*0b57cec5SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*0b57cec5SDimitry Andric // License. See LICENSE.TXT for details.
7*0b57cec5SDimitry Andric //
8*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9*0b57cec5SDimitry Andric 
10*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h"
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
13*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/MachO.h"
14*0b57cec5SDimitry Andric #include "llvm/Support/Format.h"
15*0b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h"
16*0b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
17*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric using namespace llvm;
20*0b57cec5SDimitry Andric using namespace llvm::object;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric #define DEBUG_TYPE "jitlink"
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric namespace {
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric enum JITLinkErrorCode { GenericJITLinkError = 1 };
27*0b57cec5SDimitry Andric 
28*0b57cec5SDimitry Andric // FIXME: This class is only here to support the transition to llvm::Error. It
29*0b57cec5SDimitry Andric // will be removed once this transition is complete. Clients should prefer to
30*0b57cec5SDimitry Andric // deal with the Error value directly, rather than converting to error_code.
31*0b57cec5SDimitry Andric class JITLinkerErrorCategory : public std::error_category {
32*0b57cec5SDimitry Andric public:
33*0b57cec5SDimitry Andric   const char *name() const noexcept override { return "runtimedyld"; }
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric   std::string message(int Condition) const override {
36*0b57cec5SDimitry Andric     switch (static_cast<JITLinkErrorCode>(Condition)) {
37*0b57cec5SDimitry Andric     case GenericJITLinkError:
38*0b57cec5SDimitry Andric       return "Generic JITLink error";
39*0b57cec5SDimitry Andric     }
40*0b57cec5SDimitry Andric     llvm_unreachable("Unrecognized JITLinkErrorCode");
41*0b57cec5SDimitry Andric   }
42*0b57cec5SDimitry Andric };
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric } // namespace
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric namespace llvm {
49*0b57cec5SDimitry Andric namespace jitlink {
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric char JITLinkError::ID = 0;
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; }
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric std::error_code JITLinkError::convertToErrorCode() const {
56*0b57cec5SDimitry Andric   return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory);
57*0b57cec5SDimitry Andric }
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric const StringRef getGenericEdgeKindName(Edge::Kind K) {
60*0b57cec5SDimitry Andric   switch (K) {
61*0b57cec5SDimitry Andric   case Edge::Invalid:
62*0b57cec5SDimitry Andric     return "INVALID RELOCATION";
63*0b57cec5SDimitry Andric   case Edge::KeepAlive:
64*0b57cec5SDimitry Andric     return "Keep-Alive";
65*0b57cec5SDimitry Andric   case Edge::LayoutNext:
66*0b57cec5SDimitry Andric     return "Layout-Next";
67*0b57cec5SDimitry Andric   default:
68*0b57cec5SDimitry Andric     llvm_unreachable("Unrecognized relocation kind");
69*0b57cec5SDimitry Andric   }
70*0b57cec5SDimitry Andric }
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const Atom &A) {
73*0b57cec5SDimitry Andric   OS << "<";
74*0b57cec5SDimitry Andric   if (A.getName().empty())
75*0b57cec5SDimitry Andric     OS << "anon@" << format("0x%016" PRIx64, A.getAddress());
76*0b57cec5SDimitry Andric   else
77*0b57cec5SDimitry Andric     OS << A.getName();
78*0b57cec5SDimitry Andric   OS << " [";
79*0b57cec5SDimitry Andric   if (A.isDefined()) {
80*0b57cec5SDimitry Andric     auto &DA = static_cast<const DefinedAtom &>(A);
81*0b57cec5SDimitry Andric     OS << " section=" << DA.getSection().getName();
82*0b57cec5SDimitry Andric     if (DA.isLive())
83*0b57cec5SDimitry Andric       OS << " live";
84*0b57cec5SDimitry Andric     if (DA.shouldDiscard())
85*0b57cec5SDimitry Andric       OS << " should-discard";
86*0b57cec5SDimitry Andric   } else
87*0b57cec5SDimitry Andric     OS << " external";
88*0b57cec5SDimitry Andric   OS << " ]>";
89*0b57cec5SDimitry Andric   return OS;
90*0b57cec5SDimitry Andric }
91*0b57cec5SDimitry Andric 
92*0b57cec5SDimitry Andric void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E,
93*0b57cec5SDimitry Andric                StringRef EdgeKindName) {
94*0b57cec5SDimitry Andric   OS << "edge@" << formatv("{0:x16}", FixupAtom.getAddress() + E.getOffset())
95*0b57cec5SDimitry Andric      << ": " << FixupAtom << " + " << E.getOffset() << " -- " << EdgeKindName
96*0b57cec5SDimitry Andric      << " -> " << E.getTarget() << " + " << E.getAddend();
97*0b57cec5SDimitry Andric }
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric Section::~Section() {
100*0b57cec5SDimitry Andric   for (auto *DA : DefinedAtoms)
101*0b57cec5SDimitry Andric     DA->~DefinedAtom();
102*0b57cec5SDimitry Andric }
103*0b57cec5SDimitry Andric 
104*0b57cec5SDimitry Andric void AtomGraph::dump(raw_ostream &OS,
105*0b57cec5SDimitry Andric                      std::function<StringRef(Edge::Kind)> EdgeKindToName) {
106*0b57cec5SDimitry Andric   if (!EdgeKindToName)
107*0b57cec5SDimitry Andric     EdgeKindToName = [](Edge::Kind K) { return StringRef(); };
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric   OS << "Defined atoms:\n";
110*0b57cec5SDimitry Andric   for (auto *DA : defined_atoms()) {
111*0b57cec5SDimitry Andric     OS << "  " << format("0x%016" PRIx64, DA->getAddress()) << ": " << *DA
112*0b57cec5SDimitry Andric        << "\n";
113*0b57cec5SDimitry Andric     for (auto &E : DA->edges()) {
114*0b57cec5SDimitry Andric       OS << "    ";
115*0b57cec5SDimitry Andric       StringRef EdgeName = (E.getKind() < Edge::FirstRelocation
116*0b57cec5SDimitry Andric                                 ? getGenericEdgeKindName(E.getKind())
117*0b57cec5SDimitry Andric                                 : EdgeKindToName(E.getKind()));
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric       if (!EdgeName.empty())
120*0b57cec5SDimitry Andric         printEdge(OS, *DA, E, EdgeName);
121*0b57cec5SDimitry Andric       else {
122*0b57cec5SDimitry Andric         auto EdgeNumberString = std::to_string(E.getKind());
123*0b57cec5SDimitry Andric         printEdge(OS, *DA, E, EdgeNumberString);
124*0b57cec5SDimitry Andric       }
125*0b57cec5SDimitry Andric       OS << "\n";
126*0b57cec5SDimitry Andric     }
127*0b57cec5SDimitry Andric   }
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric   OS << "Absolute atoms:\n";
130*0b57cec5SDimitry Andric   for (auto *A : absolute_atoms())
131*0b57cec5SDimitry Andric     OS << "  " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A
132*0b57cec5SDimitry Andric        << "\n";
133*0b57cec5SDimitry Andric 
134*0b57cec5SDimitry Andric   OS << "External atoms:\n";
135*0b57cec5SDimitry Andric   for (auto *A : external_atoms())
136*0b57cec5SDimitry Andric     OS << "  " << format("0x%016" PRIx64, A->getAddress()) << ": " << *A
137*0b57cec5SDimitry Andric        << "\n";
138*0b57cec5SDimitry Andric }
139*0b57cec5SDimitry Andric 
140*0b57cec5SDimitry Andric JITLinkContext::~JITLinkContext() {}
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric bool JITLinkContext::shouldAddDefaultTargetPasses(const Triple &TT) const {
143*0b57cec5SDimitry Andric   return true;
144*0b57cec5SDimitry Andric }
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric AtomGraphPassFunction JITLinkContext::getMarkLivePass(const Triple &TT) const {
147*0b57cec5SDimitry Andric   return AtomGraphPassFunction();
148*0b57cec5SDimitry Andric }
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric Error JITLinkContext::modifyPassConfig(const Triple &TT,
151*0b57cec5SDimitry Andric                                        PassConfiguration &Config) {
152*0b57cec5SDimitry Andric   return Error::success();
153*0b57cec5SDimitry Andric }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric Error markAllAtomsLive(AtomGraph &G) {
156*0b57cec5SDimitry Andric   for (auto *DA : G.defined_atoms())
157*0b57cec5SDimitry Andric     DA->setLive(true);
158*0b57cec5SDimitry Andric   return Error::success();
159*0b57cec5SDimitry Andric }
160*0b57cec5SDimitry Andric 
161*0b57cec5SDimitry Andric void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
162*0b57cec5SDimitry Andric   auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
163*0b57cec5SDimitry Andric   switch (Magic) {
164*0b57cec5SDimitry Andric   case file_magic::macho_object:
165*0b57cec5SDimitry Andric     return jitLink_MachO(std::move(Ctx));
166*0b57cec5SDimitry Andric   default:
167*0b57cec5SDimitry Andric     Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
168*0b57cec5SDimitry Andric   };
169*0b57cec5SDimitry Andric }
170*0b57cec5SDimitry Andric 
171*0b57cec5SDimitry Andric } // end namespace jitlink
172*0b57cec5SDimitry Andric } // end namespace llvm
173