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.

llvm-svn: 129138
This commit is contained in:
Jim Grosbach 2011-04-08 17:31:24 +00:00
parent 74c74ba81c
commit 18b81c52bb
4 changed files with 74 additions and 86 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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,93 +274,72 @@ 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<uint32_t, macho::RelocationEntry> RelocationMap;
SmallVector<RelocationMap, 64> Relocations;
SmallVector<void *, 16> SectionBases;
for (unsigned i = 0; i != Segment32LC->NumSections; ++i) {
for (unsigned SectNum = 0; SectNum != Segment32LC->NumSections; ++SectNum) {
InMemoryStruct<macho::Section> 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<macho::RelocationEntry> 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<uint64_t, StringRef> SymbolEntry;
SmallVector<SymbolEntry, 32> Symbols;
for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
InMemoryStruct<macho::SymbolTableEntry> 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() + "'");
// Just skip symbols not defined in this section.
if (STE->SectionIndex - 1 != SectNum)
continue;
// 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());
// 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);
}
// Bind all the symbols to address. Keep a record of the names for use
// by relocation resolution.
SmallVector<StringRef, 64> SymbolNames;
for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
InMemoryStruct<macho::SymbolTableEntry> 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;
}
// 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;
}
// 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());
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);
}

View File

@ -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'");