MachO file loader and execution utility.
[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
55 static int ExecuteInput() {
56   // Load the input memory buffer.
57   OwningPtr<MemoryBuffer> InputBuffer;
58   if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
59     return Error("unable to read input: '" + ec.message() + "'");
60
61   // Load the Mach-O wrapper object.
62   std::string ErrorStr;
63   OwningPtr<MachOObject> Obj(
64     MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
65   if (!Obj)
66     return Error("unable to load object: '" + ErrorStr + "'");
67
68   // Validate that the load commands match what we expect.
69   const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
70     *DysymtabLCI = 0;
71   for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) {
72     const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
73     switch (LCI.Command.Type) {
74     case macho::LCT_Segment:
75     case macho::LCT_Segment64:
76       if (SegmentLCI)
77         return Error("unexpected input object (multiple segments)");
78       SegmentLCI = &LCI;
79       break;
80     case macho::LCT_Symtab:
81       if (SymtabLCI)
82         return Error("unexpected input object (multiple symbol tables)");
83       SymtabLCI = &LCI;
84       break;
85     case macho::LCT_Dysymtab:
86       if (DysymtabLCI)
87         return Error("unexpected input object (multiple symbol tables)");
88       DysymtabLCI = &LCI;
89       break;
90     default:
91       return Error("unexpected input object (unexpected load command");
92     }
93   }
94
95   if (!SymtabLCI)
96     return Error("no symbol table found in object");
97   if (!SegmentLCI)
98     return Error("no symbol table found in object");
99
100   // Read and register the symbol table data.
101   InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
102   Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
103   if (!SymtabLC)
104     return Error("unable to load symbol table load command");
105   Obj->RegisterStringTable(*SymtabLC);
106
107   // Read the dynamic link-edit information, if present (not present in static
108   // objects).
109   if (DysymtabLCI) {
110     InMemoryStruct<macho::DysymtabLoadCommand> DysymtabLC;
111     Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC);
112     if (!DysymtabLC)
113       return Error("unable to load dynamic link-exit load command");
114
115     // FIXME: We don't support anything interesting yet.
116     if (DysymtabLC->LocalSymbolsIndex != 0)
117       return Error("NOT YET IMPLEMENTED: local symbol entries");
118     if (DysymtabLC->ExternalSymbolsIndex != 0)
119       return Error("NOT YET IMPLEMENTED: non-external symbol entries");
120     if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries)
121       return Error("NOT YET IMPLEMENTED: undefined symbol entries");
122   }
123
124   // Load the segment load command.
125   if (SegmentLCI->Command.Type != macho::LCT_Segment64)
126     return Error("Segment32 not yet implemented!");
127   InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
128   Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC);
129   if (!Segment64LC)
130     return Error("unable to load segment load command");
131
132   // Map the segment into memory.
133   sys::MemoryBlock Data = sys::Memory::AllocateRWX(Segment64LC->VMSize,
134                                                    0, &ErrorStr);
135   if (!Data.base())
136     return Error("unable to allocate memory block: '" + ErrorStr + "'");
137   memcpy(Data.base(), Obj->getData(Segment64LC->FileOffset,
138                                    Segment64LC->FileSize).data(),
139          Segment64LC->FileSize);
140   memset((char*)Data.base() + Segment64LC->FileSize, 0,
141          Segment64LC->VMSize - Segment64LC->FileSize);
142
143   // Bind the section indices to address.
144   void **SectionBases = new void*[Segment64LC->NumSections];
145   for (unsigned i = 0; i != Segment64LC->NumSections; ++i) {
146     InMemoryStruct<macho::Section64> Sect;
147     Obj->ReadSection64(*SegmentLCI, i, Sect);
148     if (!Sect)
149       return Error("unable to load section: '" + Twine(i) + "'");
150
151     // FIXME: We don't support relocations yet.
152     if (Sect->NumRelocationTableEntries != 0)
153       return Error("not yet implemented: relocations!");
154
155     // FIXME: Improve check.
156     if (Sect->Flags != 0x80000400)
157       return Error("unsupported section type!");
158
159     SectionBases[i] = (char*) Data.base() + Sect->Address;
160   }
161
162   // Bind all the symbols to address.
163   StringMap<void*> SymbolTable;
164   for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
165     InMemoryStruct<macho::Symbol64TableEntry> STE;
166     Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
167     if (!STE)
168       return Error("unable to read symbol: '" + Twine(i) + "'");
169     if (STE->SectionIndex == 0)
170       return Error("unexpected undefined symbol!");
171
172     unsigned Index = STE->SectionIndex - 1;
173     if (Index >= Segment64LC->NumSections)
174       return Error("invalid section index for symbol: '" + Twine() + "'");
175
176     // Get the symbol name.
177     StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
178
179     // Get the section base address.
180     void *SectionBase = SectionBases[Index];
181
182     // Get the symbol address.
183     void *Address = (char*) SectionBase + STE->Value;
184
185     // FIXME: Check the symbol type and flags.
186     if (STE->Type != 0xF)
187       return Error("unexpected symbol type!");
188     if (STE->Flags != 0x0)
189       return Error("unexpected symbol type!");
190
191     SymbolTable[Name] = Address;
192   }
193
194   // Get the address of "_main".
195   StringMap<void*>::iterator it = SymbolTable.find("_main");
196   if (it == SymbolTable.end())
197     return Error("no definition for '_main'");
198
199   // Invalidate the instruction cache.
200   sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
201
202   // Make sure the memory is executable.
203   if (!sys::Memory::setExecutable(Data, &ErrorStr))
204     return Error("unable to mark function executable: '" + ErrorStr + "'");
205
206   // Dispatch to _main().
207   void *MainAddress = it->second;
208   errs() << "loaded '_main' at: " << MainAddress << "\n";
209
210   int (*Main)(int, const char**) =
211     (int(*)(int,const char**)) uintptr_t(MainAddress);
212   const char **Argv = new const char*[2];
213   Argv[0] = InputFile.c_str();
214   Argv[1] = 0;
215   return Main(1, Argv);
216 }
217
218 int main(int argc, char **argv) {
219   ProgramName = argv[0];
220   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
221
222   cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
223
224   switch (Action) {
225   default:
226   case AC_Execute:
227     return ExecuteInput();
228   }
229
230   return 0;
231 }