X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-rtdyld%2Fllvm-rtdyld.cpp;h=990582d7f45957e29c732d22efa44e385c1ed9cb;hb=a21bb20f5943f5f4c66d4727784c26007db2470c;hp=01c3ead10e51bdd89be352212740d6dd3228387e;hpb=1cb19a4470533be84eb61e8f5fc40aa9d45f86f9;p=oota-llvm.git diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 01c3ead10e5..990582d7f45 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/MachOObject.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" @@ -23,8 +24,9 @@ using namespace llvm; using namespace llvm::object; -static cl::opt -InputFile(cl::Positional, cl::desc(""), cl::init("-")); +static cl::list +InputFileList(cl::Positional, cl::ZeroOrMore, + cl::desc("")); enum ActionType { AC_Execute @@ -37,8 +39,54 @@ Action(cl::desc("Action to perform:"), "Load, link, and execute the inputs."), clEnumValEnd)); +static cl::opt +EntryPoint("entry", + cl::desc("Function to call as entry point."), + cl::init("_main")); + /* *** */ +// A trivial memory manager that doesn't do anything fancy, just uses the +// support library allocation routines directly. +class TrivialMemoryManager : public RTDyldMemoryManager { +public: + SmallVector FunctionMemory; + SmallVector DataMemory; + + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); + void endFunctionBody(const char *Name, uint8_t *FunctionStart, + uint8_t *FunctionEnd); +}; + +uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); +} + +uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, + unsigned Alignment, + unsigned SectionID) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); +} + +uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, + uintptr_t &Size) { + return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); +} + +void TrivialMemoryManager::endFunctionBody(const char *Name, + uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + uintptr_t Size = FunctionEnd - FunctionStart + 1; + FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); +} + static const char *ProgramName; static void Message(const char *Type, const Twine &Msg) { @@ -52,165 +100,55 @@ static int Error(const Twine &Msg) { /* *** */ -static int ExecuteInput() { - // Load the input memory buffer. - OwningPtr InputBuffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); - - // Load the Mach-O wrapper object. - std::string ErrorStr; - OwningPtr Obj( - MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); - if (!Obj) - return Error("unable to load object: '" + ErrorStr + "'"); - - // Validate that the load commands match what we expect. - const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0, - *DysymtabLCI = 0; - for (unsigned i = 0; i != Obj->getHeader().NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i); - switch (LCI.Command.Type) { - case macho::LCT_Segment: - case macho::LCT_Segment64: - if (SegmentLCI) - return Error("unexpected input object (multiple segments)"); - SegmentLCI = &LCI; - break; - case macho::LCT_Symtab: - if (SymtabLCI) - return Error("unexpected input object (multiple symbol tables)"); - SymtabLCI = &LCI; - break; - case macho::LCT_Dysymtab: - if (DysymtabLCI) - return Error("unexpected input object (multiple symbol tables)"); - DysymtabLCI = &LCI; - break; - default: - return Error("unexpected input object (unexpected load command"); +static int executeInput() { + // Instantiate a dynamic linker. + TrivialMemoryManager *MemMgr = new TrivialMemoryManager; + RuntimeDyld Dyld(MemMgr); + + // If we don't have any input files, read from stdin. + if (!InputFileList.size()) + InputFileList.push_back("-"); + for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { + // Load the input memory buffer. + OwningPtr InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], + InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Load the object file into it. + if (Dyld.loadObject(InputBuffer.take())) { + return Error(Dyld.getErrorString()); } } - if (!SymtabLCI) - return Error("no symbol table found in object"); - if (!SegmentLCI) - return Error("no symbol table found in object"); - - // Read and register the symbol table data. - InMemoryStruct SymtabLC; - Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); - if (!SymtabLC) - return Error("unable to load symbol table load command"); - Obj->RegisterStringTable(*SymtabLC); - - // Read the dynamic link-edit information, if present (not present in static - // objects). - if (DysymtabLCI) { - InMemoryStruct DysymtabLC; - Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC); - if (!DysymtabLC) - return Error("unable to load dynamic link-exit load command"); - - // FIXME: We don't support anything interesting yet. - if (DysymtabLC->LocalSymbolsIndex != 0) - return Error("NOT YET IMPLEMENTED: local symbol entries"); - if (DysymtabLC->ExternalSymbolsIndex != 0) - return Error("NOT YET IMPLEMENTED: non-external symbol entries"); - if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries) - return Error("NOT YET IMPLEMENTED: undefined symbol entries"); - } - - // Load the segment load command. - if (SegmentLCI->Command.Type != macho::LCT_Segment64) - return Error("Segment32 not yet implemented!"); - InMemoryStruct Segment64LC; - Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC); - if (!Segment64LC) - return Error("unable to load segment load command"); - - // Map the segment into memory. - sys::MemoryBlock Data = sys::Memory::AllocateRWX(Segment64LC->VMSize, - 0, &ErrorStr); - if (!Data.base()) - return Error("unable to allocate memory block: '" + ErrorStr + "'"); - memcpy(Data.base(), Obj->getData(Segment64LC->FileOffset, - Segment64LC->FileSize).data(), - Segment64LC->FileSize); - memset((char*)Data.base() + Segment64LC->FileSize, 0, - Segment64LC->VMSize - Segment64LC->FileSize); - - // Bind the section indices to address. - void **SectionBases = new void*[Segment64LC->NumSections]; - for (unsigned i = 0; i != Segment64LC->NumSections; ++i) { - InMemoryStruct Sect; - Obj->ReadSection64(*SegmentLCI, i, Sect); - if (!Sect) - return Error("unable to load section: '" + Twine(i) + "'"); - - // FIXME: We don't support relocations yet. - if (Sect->NumRelocationTableEntries != 0) - return Error("not yet implemented: relocations!"); - - // FIXME: Improve check. - if (Sect->Flags != 0x80000400) - return Error("unsupported section type!"); - - SectionBases[i] = (char*) Data.base() + Sect->Address; - } - - // Bind all the symbols to address. - StringMap SymbolTable; - for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { - InMemoryStruct STE; - Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE); - if (!STE) - return Error("unable to read symbol: '" + Twine(i) + "'"); - if (STE->SectionIndex == 0) - return Error("unexpected undefined symbol!"); - - unsigned Index = STE->SectionIndex - 1; - if (Index >= Segment64LC->NumSections) - return Error("invalid section index for symbol: '" + Twine() + "'"); + // Resolve all the relocations we can. + Dyld.resolveRelocations(); - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + // FIXME: Error out if there are unresolved relocations. - // Get the section base address. - void *SectionBase = SectionBases[Index]; + // Get the address of the entry point (_main by default). + void *MainAddress = Dyld.getSymbolAddress(EntryPoint); + if (MainAddress == 0) + return Error("no definition for '" + EntryPoint + "'"); - // Get the symbol address. - void *Address = (char*) SectionBase + STE->Value; - - // FIXME: Check the symbol type and flags. - if (STE->Type != 0xF) - return Error("unexpected symbol type!"); - if (STE->Flags != 0x0) - return Error("unexpected symbol type!"); - - SymbolTable[Name] = Address; + // Invalidate the instruction cache for each loaded function. + for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { + sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; + // Make sure the memory is executable. + std::string ErrorStr; + sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); + if (!sys::Memory::setExecutable(Data, &ErrorStr)) + return Error("unable to mark function executable: '" + ErrorStr + "'"); } - // Get the address of "_main". - StringMap::iterator it = SymbolTable.find("_main"); - if (it == SymbolTable.end()) - return Error("no definition for '_main'"); - - // Invalidate the instruction cache. - sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); - - // Make sure the memory is executable. - if (!sys::Memory::setExecutable(Data, &ErrorStr)) - return Error("unable to mark function executable: '" + ErrorStr + "'"); - // Dispatch to _main(). - void *MainAddress = it->second; - errs() << "loaded '_main' at: " << MainAddress << "\n"; + errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; int (*Main)(int, const char**) = (int(*)(int,const char**)) uintptr_t(MainAddress); const char **Argv = new const char*[2]; - Argv[0] = InputFile.c_str(); + // Use the name of the first input object module as argv[0] for the target. + Argv[0] = InputFileList[0].c_str(); Argv[1] = 0; return Main(1, Argv); } @@ -222,10 +160,7 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); switch (Action) { - default: case AC_Execute: - return ExecuteInput(); + return executeInput(); } - - return 0; }