From b027105fa50c864d44873dc78daafb3db3ec9c14 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Fri, 8 Apr 2011 17:31:24 +0000 Subject: [PATCH] Refactor MCJIT 32-bit section loading. Teach 32-bit section loading to use the Memory Manager interface, just like the 64-bit loading does. Tidy up a few other things here and there. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129138 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ExecutionEngine/RuntimeDyld.h | 5 +- lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h | 6 + lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 143 ++++++++++-------------- tools/llvm-rtdyld/llvm-rtdyld.cpp | 2 +- 4 files changed, 72 insertions(+), 84 deletions(-) diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 416acceee97..87ba119457c 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -58,7 +58,10 @@ public: ~RuntimeDyld(); bool loadObject(MemoryBuffer *InputBuffer); - uint64_t getSymbolAddress(StringRef Name); + // Get the address of our local copy of the symbol. This may or may not + // be the address used for relocation (clients can copy the data around + // and resolve relocatons based on where they put it). + void *getSymbolAddress(StringRef Name); void reassignSymbolAddress(StringRef Name, uint64_t Addr); // FIXME: Should be parameterized to get the memory block associated with // a particular loaded object. diff --git a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h index 0108ecca84f..e3c6fda63b4 100644 --- a/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h +++ b/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h @@ -32,6 +32,9 @@ public: // a pointer to the allocated memory and update Size to reflect how much // memory was acutally allocated. uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; Function *F = M->getFunction(Name); assert(F && "No matching function in JIT IR Module!"); return JMM->startFunctionBody(F, Size); @@ -41,6 +44,9 @@ public: // memory was actually used. void endFunctionBody(const char *Name, uint8_t *FunctionStart, uint8_t *FunctionEnd) { + // FIXME: This should really reference the MCAsmInfo to get the global + // prefix. + if (Name[0] == '_') ++Name; Function *F = M->getFunction(Name); assert(F && "No matching function in JIT IR Module!"); JMM->endFunctionBody(F, FunctionStart, FunctionEnd); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 29fced4e6c6..9cbaaa19f84 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -85,10 +85,10 @@ public: bool loadObject(MemoryBuffer *InputBuffer); - uint64_t getSymbolAddress(StringRef Name) { + void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - return (uint64_t)Functions.lookup(Name).base(); + return Functions.lookup(Name).base(); } sys::MemoryBlock getMemoryBlock() { return Data; } @@ -274,92 +274,71 @@ loadSegment32(const MachOObject *Obj, if (!Segment32LC) return Error("unable to load segment load command"); - // Map the segment into memory. - std::string ErrorStr; - Data = sys::Memory::AllocateRWX(Segment32LC->VMSize, 0, &ErrorStr); - if (!Data.base()) - return Error("unable to allocate memory block: '" + ErrorStr + "'"); - memcpy(Data.base(), Obj->getData(Segment32LC->FileOffset, - Segment32LC->FileSize).data(), - Segment32LC->FileSize); - memset((char*)Data.base() + Segment32LC->FileSize, 0, - Segment32LC->VMSize - Segment32LC->FileSize); - - // Bind the section indices to addresses and record the relocations we - // need to resolve. - typedef std::pair RelocationMap; - SmallVector Relocations; - - SmallVector SectionBases; - for (unsigned i = 0; i != Segment32LC->NumSections; ++i) { + for (unsigned SectNum = 0; SectNum != Segment32LC->NumSections; ++SectNum) { InMemoryStruct Sect; - Obj->ReadSection(*SegmentLCI, i, Sect); - if (!Sect) - return Error("unable to load section: '" + Twine(i) + "'"); - - // Remember any relocations the section has so we can resolve them later. - for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { - InMemoryStruct RE; - Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); - Relocations.push_back(RelocationMap(j, *RE)); - } + Obj->ReadSection(*SegmentLCI, SectNum, Sect); + if (!Sect) + return Error("unable to load section: '" + Twine(SectNum) + "'"); // FIXME: Improve check. -// if (Sect->Flags != 0x80000400) -// return Error("unsupported section type!"); + if (Sect->Flags != 0x80000400) + return Error("unsupported section type!"); - SectionBases.push_back((char*) Data.base() + Sect->Address); - } + // Address and names of symbols in the section. + typedef std::pair SymbolEntry; + SmallVector Symbols; + for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { + InMemoryStruct STE; + Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); + if (!STE) + return Error("unable to read symbol: '" + Twine(i) + "'"); + if (STE->SectionIndex > Segment32LC->NumSections) + return Error("invalid section index for symbol: '" + Twine() + "'"); - // Bind all the symbols to address. Keep a record of the names for use - // by relocation resolution. - SmallVector SymbolNames; - for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { - InMemoryStruct STE; - Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); - if (!STE) - return Error("unable to read symbol: '" + Twine(i) + "'"); - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); - SymbolNames.push_back(Name); - - // Just skip undefined symbols. They'll be loaded from whatever - // module they come from (or system dylib) when we resolve relocations - // involving them. - if (STE->SectionIndex == 0) - continue; - - unsigned Index = STE->SectionIndex - 1; - if (Index >= Segment32LC->NumSections) - return Error("invalid section index for symbol: '" + Twine() + "'"); - - // Get the section base address. - void *SectionBase = SectionBases[Index]; - - // Get the symbol address. - uint64_t Address = (uint64_t)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!"); - - DEBUG(dbgs() << "Symbol: '" << Name << "' @ " << Address << "\n"); - - SymbolTable[Name] = Address; - } + // Just skip symbols not defined in this section. + if (STE->SectionIndex - 1 != SectNum) + continue; - // Now resolve any relocations. - for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { - if (resolveRelocation(Relocations[i].first, Relocations[i].second, - SectionBases, SymbolNames)) - return true; - } + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + + // FIXME: Check the symbol type and flags. + if (STE->Type != 0xF) // external, defined in this section. + return Error("unexpected symbol type!"); + if (STE->Flags != 0x0) + return Error("unexpected symbol type!"); + + uint64_t BaseAddress = Sect->Address; + uint64_t Address = BaseAddress + STE->Value; + + // Remember the symbol. + Symbols.push_back(SymbolEntry(Address, Name)); + + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << Address << "\n"); + } + // Sort the symbols by address, just in case they didn't come in that + // way. + array_pod_sort(Symbols.begin(), Symbols.end()); - // We've loaded the section; now mark the functions in it as executable. - // FIXME: We really should use the MemoryManager for this. - sys::Memory::setRangeExecutable(Data.base(), Data.size()); + // Extract the function data. + uint8_t *Base = (uint8_t*)Obj->getData(Segment32LC->FileOffset, + Segment32LC->FileSize).data(); + for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { + uint64_t StartOffset = Symbols[i].first; + uint64_t EndOffset = Symbols[i + 1].first - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[i].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[i].second, Base + StartOffset, Base + EndOffset); + } + // The last symbol we do after since the end address is calculated + // differently because there is no next symbol to reference. + uint64_t StartOffset = Symbols[Symbols.size() - 1].first; + uint64_t EndOffset = Sect->Size - 1; + DEBUG(dbgs() << "Extracting function: " << Symbols[Symbols.size()-1].second + << " from [" << StartOffset << ", " << EndOffset << "]\n"); + extractFunction(Symbols[Symbols.size()-1].second, + Base + StartOffset, Base + EndOffset); + } return false; } @@ -545,7 +524,7 @@ bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { return Dyld->loadObject(InputBuffer); } -uint64_t RuntimeDyld::getSymbolAddress(StringRef Name) { +void *RuntimeDyld::getSymbolAddress(StringRef Name) { return Dyld->getSymbolAddress(Name); } diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index ddd6683a2f2..c2f1c3c48dd 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -82,7 +82,7 @@ static int executeInput() { } // Get the address of "_main". - uint64_t MainAddress = Dyld.getSymbolAddress("_main"); + void *MainAddress = Dyld.getSymbolAddress("_main"); if (MainAddress == 0) return Error("no definition for '_main'"); -- 2.11.0