6de5742a6a3831681e67e658ebd82461a324f16c
[oota-llvm.git] / tools / llvm-rtdyld / llvm-rtdyld.cpp
1 //===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This is a testing tool for use with the MC-JIT LLVM components.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/Object/MachOObject.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/ManagedStatic.h"
19 #include "llvm/Support/Memory.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Support/system_error.h"
23 using namespace llvm;
24 using namespace llvm::object;
25
26 static cl::opt<std::string>
27 InputFile(cl::Positional, cl::desc("<input file>"), cl::init("-"));
28
29 enum ActionType {
30   AC_Execute
31 };
32
33 static cl::opt<ActionType>
34 Action(cl::desc("Action to perform:"),
35        cl::init(AC_Execute),
36        cl::values(clEnumValN(AC_Execute, "execute",
37                              "Load, link, and execute the inputs."),
38                   clEnumValEnd));
39
40 /* *** */
41
42 static const char *ProgramName;
43
44 static void Message(const char *Type, const Twine &Msg) {
45   errs() << ProgramName << ": " << Type << ": " << Msg << "\n";
46 }
47
48 static int Error(const Twine &Msg) {
49   Message("error", Msg);
50   return 1;
51 }
52
53 /* *** */
54 static bool
55 loadSegment32(const MachOObject *Obj,
56               sys::MemoryBlock &Data,
57               const MachOObject::LoadCommandInfo *SegmentLCI,
58               const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC,
59               StringMap<void*> &SymbolTable) {
60   InMemoryStruct<macho::SegmentLoadCommand> Segment32LC;
61   Obj->ReadSegmentLoadCommand(*SegmentLCI, Segment32LC);
62   if (!Segment32LC)
63     return Error("unable to load segment load command");
64
65   // Map the segment into memory.
66   std::string ErrorStr;
67   Data = sys::Memory::AllocateRWX(Segment32LC->VMSize, 0, &ErrorStr);
68   if (!Data.base())
69     return Error("unable to allocate memory block: '" + ErrorStr + "'");
70   memcpy(Data.base(), Obj->getData(Segment32LC->FileOffset,
71                                    Segment32LC->FileSize).data(),
72          Segment32LC->FileSize);
73   memset((char*)Data.base() + Segment32LC->FileSize, 0,
74          Segment32LC->VMSize - Segment32LC->FileSize);
75
76   // Bind the section indices to address.
77   void **SectionBases = new void*[Segment32LC->NumSections];
78   for (unsigned i = 0; i != Segment32LC->NumSections; ++i) {
79     InMemoryStruct<macho::Section> Sect;
80     Obj->ReadSection(*SegmentLCI, i, Sect);
81     if (!Sect)
82       return Error("unable to load section: '" + Twine(i) + "'");
83
84     // FIXME: We don't support relocations yet.
85     if (Sect->NumRelocationTableEntries != 0)
86       return Error("not yet implemented: relocations!");
87
88     // FIXME: Improve check.
89     if (Sect->Flags != 0x80000400)
90       return Error("unsupported section type!");
91
92     SectionBases[i] = (char*) Data.base() + Sect->Address;
93   }
94
95   // Bind all the symbols to address.
96   for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
97     InMemoryStruct<macho::SymbolTableEntry> STE;
98     Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE);
99     if (!STE)
100       return Error("unable to read symbol: '" + Twine(i) + "'");
101     if (STE->SectionIndex == 0)
102       return Error("unexpected undefined symbol!");
103
104     unsigned Index = STE->SectionIndex - 1;
105     if (Index >= Segment32LC->NumSections)
106       return Error("invalid section index for symbol: '" + Twine() + "'");
107
108     // Get the symbol name.
109     StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
110
111     // Get the section base address.
112     void *SectionBase = SectionBases[Index];
113
114     // Get the symbol address.
115     void *Address = (char*) SectionBase + STE->Value;
116
117     // FIXME: Check the symbol type and flags.
118     if (STE->Type != 0xF)
119       return Error("unexpected symbol type!");
120     if (STE->Flags != 0x0)
121       return Error("unexpected symbol type!");
122
123     SymbolTable[Name] = Address;
124   }
125
126   delete SectionBases;
127   return false;
128 }
129
130 static bool
131 loadSegment64(const MachOObject *Obj,
132               sys::MemoryBlock &Data,
133               const MachOObject::LoadCommandInfo *SegmentLCI,
134               const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC,
135               StringMap<void*> &SymbolTable) {
136   InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
137   Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC);
138   if (!Segment64LC)
139     return Error("unable to load segment load command");
140
141   // Map the segment into memory.
142   std::string ErrorStr;
143   Data = sys::Memory::AllocateRWX(Segment64LC->VMSize, 0, &ErrorStr);
144   if (!Data.base())
145     return Error("unable to allocate memory block: '" + ErrorStr + "'");
146   memcpy(Data.base(), Obj->getData(Segment64LC->FileOffset,
147                                    Segment64LC->FileSize).data(),
148          Segment64LC->FileSize);
149   memset((char*)Data.base() + Segment64LC->FileSize, 0,
150          Segment64LC->VMSize - Segment64LC->FileSize);
151
152   // Bind the section indices to address.
153   void **SectionBases = new void*[Segment64LC->NumSections];
154   for (unsigned i = 0; i != Segment64LC->NumSections; ++i) {
155     InMemoryStruct<macho::Section64> Sect;
156     Obj->ReadSection64(*SegmentLCI, i, Sect);
157     if (!Sect)
158       return Error("unable to load section: '" + Twine(i) + "'");
159
160     // FIXME: We don't support relocations yet.
161     if (Sect->NumRelocationTableEntries != 0)
162       return Error("not yet implemented: relocations!");
163
164     // FIXME: Improve check.
165     if (Sect->Flags != 0x80000400)
166       return Error("unsupported section type!");
167
168     SectionBases[i] = (char*) Data.base() + Sect->Address;
169   }
170
171   // Bind all the symbols to address.
172   for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
173     InMemoryStruct<macho::Symbol64TableEntry> STE;
174     Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
175     if (!STE)
176       return Error("unable to read symbol: '" + Twine(i) + "'");
177     if (STE->SectionIndex == 0)
178       return Error("unexpected undefined symbol!");
179
180     unsigned Index = STE->SectionIndex - 1;
181     if (Index >= Segment64LC->NumSections)
182       return Error("invalid section index for symbol: '" + Twine() + "'");
183
184     // Get the symbol name.
185     StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
186
187     // Get the section base address.
188     void *SectionBase = SectionBases[Index];
189
190     // Get the symbol address.
191     void *Address = (char*) SectionBase + STE->Value;
192
193     // FIXME: Check the symbol type and flags.
194     if (STE->Type != 0xF)
195       return Error("unexpected symbol type!");
196     if (STE->Flags != 0x0)
197       return Error("unexpected symbol type!");
198
199     SymbolTable[Name] = Address;
200   }
201
202   delete SectionBases;
203   return false;
204 }
205
206 static int executeInput() {
207   // Load the input memory buffer.
208   OwningPtr<MemoryBuffer> InputBuffer;
209   if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
210     return Error("unable to read input: '" + ec.message() + "'");
211
212   // Load the Mach-O wrapper object.
213   std::string ErrorStr;
214   OwningPtr<MachOObject> Obj(
215     MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
216   if (!Obj)
217     return Error("unable to load object: '" + ErrorStr + "'");
218
219   // Validate that the load commands match what we expect.
220   const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
221     *DysymtabLCI = 0;
222   for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
223     const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
224     switch (LCI.Command.Type) {
225     case macho::LCT_Segment:
226     case macho::LCT_Segment64:
227       if (SegmentLCI)
228         return Error("unexpected input object (multiple segments)");
229       SegmentLCI = &LCI;
230       break;
231     case macho::LCT_Symtab:
232       if (SymtabLCI)
233         return Error("unexpected input object (multiple symbol tables)");
234       SymtabLCI = &LCI;
235       break;
236     case macho::LCT_Dysymtab:
237       if (DysymtabLCI)
238         return Error("unexpected input object (multiple symbol tables)");
239       DysymtabLCI = &LCI;
240       break;
241     default:
242       return Error("unexpected input object (unexpected load command");
243     }
244   }
245
246   if (!SymtabLCI)
247     return Error("no symbol table found in object");
248   if (!SegmentLCI)
249     return Error("no symbol table found in object");
250
251   // Read and register the symbol table data.
252   InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
253   Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
254   if (!SymtabLC)
255     return Error("unable to load symbol table load command");
256   Obj->RegisterStringTable(*SymtabLC);
257
258   // Read the dynamic link-edit information, if present (not present in static
259   // objects).
260   if (DysymtabLCI) {
261     InMemoryStruct<macho::DysymtabLoadCommand> DysymtabLC;
262     Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC);
263     if (!DysymtabLC)
264       return Error("unable to load dynamic link-exit load command");
265
266     // FIXME: We don't support anything interesting yet.
267     if (DysymtabLC->LocalSymbolsIndex != 0)
268       return Error("NOT YET IMPLEMENTED: local symbol entries");
269     if (DysymtabLC->ExternalSymbolsIndex != 0)
270       return Error("NOT YET IMPLEMENTED: non-external symbol entries");
271     if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries)
272       return Error("NOT YET IMPLEMENTED: undefined symbol entries");
273   }
274
275   // Load the segment load command.
276   sys::MemoryBlock Data;
277   StringMap<void*> SymbolTable;
278   if (SegmentLCI->Command.Type == macho::LCT_Segment) {
279     if (loadSegment32(Obj.get(), Data, SegmentLCI, SymtabLC, SymbolTable))
280       return true;
281   } else {
282     if (loadSegment64(Obj.get(), Data, SegmentLCI, SymtabLC, SymbolTable))
283       return true;
284   }
285
286   // Get the address of "_main".
287   StringMap<void*>::iterator it = SymbolTable.find("_main");
288   if (it == SymbolTable.end())
289     return Error("no definition for '_main'");
290
291   // Invalidate the instruction cache.
292   sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
293
294   // Make sure the memory is executable.
295   if (!sys::Memory::setExecutable(Data, &ErrorStr))
296     return Error("unable to mark function executable: '" + ErrorStr + "'");
297
298   // Dispatch to _main().
299   void *MainAddress = it->second;
300   errs() << "loaded '_main' at: " << MainAddress << "\n";
301
302   int (*Main)(int, const char**) =
303     (int(*)(int,const char**)) uintptr_t(MainAddress);
304   const char **Argv = new const char*[2];
305   Argv[0] = InputFile.c_str();
306   Argv[1] = 0;
307   return Main(1, Argv);
308 }
309
310 int main(int argc, char **argv) {
311   ProgramName = argv[0];
312   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
313
314   cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
315
316   switch (Action) {
317   default:
318   case AC_Execute:
319     return executeInput();
320   }
321
322   return 0;
323 }