summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
diff options
context:
space:
mode:
authorDanil Malyshev <dmalyshev@accesssoftek.com>2012-03-30 16:45:19 +0000
committerDanil Malyshev <dmalyshev@accesssoftek.com>2012-03-30 16:45:19 +0000
commit0e4fa5ff365fccff46870b7d5d8d4d1d46e77986 (patch)
tree12e52172ef1700378c904466cae3f05de3b68981 /lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
parentc0164f86080bc9d7a41fd5eabd0d6556396f5b38 (diff)
downloadllvm-0e4fa5ff365fccff46870b7d5d8d4d1d46e77986.tar.gz
llvm-0e4fa5ff365fccff46870b7d5d8d4d1d46e77986.tar.bz2
llvm-0e4fa5ff365fccff46870b7d5d8d4d1d46e77986.tar.xz
Re-factored RuntimeDyLd:
1. The main works will made in the RuntimeDyLdImpl with uses the ObjectFile class. RuntimeDyLdMachO and RuntimeDyLdELF now only parses relocations and resolve it. This is allows to make improvements of the RuntimeDyLd more easily. In addition the support for COFF can be easily added. 2. Added ARM relocations to RuntimeDyLdELF. 3. Added support for stub functions for the ARM, allowing to do a long branch. 4. Added support for external functions that are not loaded from the object files, but can be loaded from external libraries. Now MCJIT can correctly execute the code containing the printf, putc, and etc. 5. The sections emitted instead functions, thanks Jim Grosbach. MemoryManager.startFunctionBody() and MemoryManager.endFunctionBody() have been removed. 6. MCJITMemoryManager.allocateDataSection() and MCJITMemoryManager. allocateCodeSection() used JMM->allocateSpace() instead of JMM->allocateCodeSection() and JMM->allocateDataSection(), because I got an error: "Cannot allocate an allocated block!" with object file contains more than one code or data sections. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153754 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp409
1 files changed, 181 insertions, 228 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index e15b200c5e..9d46b21f59 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -25,222 +25,58 @@ using namespace llvm::object;
namespace llvm {
-namespace {
-// FIXME: this function should probably not live here...
-//
-// Returns the name and address of an unrelocated symbol in an ELF section
-void getSymbolInfo(symbol_iterator Sym, uint64_t &Addr, StringRef &Name) {
- //FIXME: error checking here required to catch corrupt ELF objects...
- error_code Err = Sym->getName(Name);
-
- uint64_t AddrInSection;
- Err = Sym->getAddress(AddrInSection);
-
- SectionRef empty_section;
- section_iterator Section(empty_section);
- Err = Sym->getSection(Section);
-
- StringRef SectionContents;
- Section->getContents(SectionContents);
-
- Addr = reinterpret_cast<uint64_t>(SectionContents.data()) + AddrInSection;
-}
-
-}
-
-bool RuntimeDyldELF::loadObject(MemoryBuffer *InputBuffer) {
- if (!isCompatibleFormat(InputBuffer))
- return true;
-
- OwningPtr<ObjectFile> Obj(ObjectFile::createELFObjectFile(InputBuffer));
-
- Arch = Obj->getArch();
-
- // Map address in the Object file image to function names
- IntervalMap<uint64_t, StringRef>::Allocator A;
- IntervalMap<uint64_t, StringRef> FuncMap(A);
-
- // This is a bit of a hack. The ObjectFile we've just loaded reports
- // section addresses as 0 and doesn't provide access to the section
- // offset (from which we could calculate the address. Instead,
- // we're storing the address when it comes up in the ST_Debug case
- // below.
- //
- StringMap<uint64_t> DebugSymbolMap;
-
- symbol_iterator SymEnd = Obj->end_symbols();
- error_code Err;
- for (symbol_iterator Sym = Obj->begin_symbols();
- Sym != SymEnd; Sym.increment(Err)) {
- SymbolRef::Type Type;
- Sym->getType(Type);
- if (Type == SymbolRef::ST_Function) {
- StringRef Name;
- uint64_t Addr;
- getSymbolInfo(Sym, Addr, Name);
-
- uint64_t Size;
- Err = Sym->getSize(Size);
-
- uint8_t *Start;
- uint8_t *End;
- Start = reinterpret_cast<uint8_t*>(Addr);
- End = reinterpret_cast<uint8_t*>(Addr + Size - 1);
-
- extractFunction(Name, Start, End);
- FuncMap.insert(Addr, Addr + Size - 1, Name);
- } else if (Type == SymbolRef::ST_Debug) {
- // This case helps us find section addresses
- StringRef Name;
- uint64_t Addr;
- getSymbolInfo(Sym, Addr, Name);
- DebugSymbolMap[Name] = Addr;
- }
- }
-
- // Iterate through the relocations for this object
- section_iterator SecEnd = Obj->end_sections();
- for (section_iterator Sec = Obj->begin_sections();
- Sec != SecEnd; Sec.increment(Err)) {
- StringRef SecName;
- uint64_t SecAddr;
- Sec->getName(SecName);
- // Ignore sections that aren't in our map
- if (DebugSymbolMap.find(SecName) == DebugSymbolMap.end()) {
- continue;
- }
- SecAddr = DebugSymbolMap[SecName];
- relocation_iterator RelEnd = Sec->end_relocations();
- for (relocation_iterator Rel = Sec->begin_relocations();
- Rel != RelEnd; Rel.increment(Err)) {
- uint64_t RelOffset;
- uint64_t RelType;
- int64_t RelAddend;
- SymbolRef RelSym;
- StringRef SymName;
- uint64_t SymAddr;
- uint64_t SymOffset;
-
- Rel->getAddress(RelOffset);
- Rel->getType(RelType);
- Rel->getAdditionalInfo(RelAddend);
- Rel->getSymbol(RelSym);
- RelSym.getName(SymName);
- RelSym.getAddress(SymAddr);
- RelSym.getFileOffset(SymOffset);
-
- // If this relocation is inside a function, we want to store the
- // function name and a function-relative offset
- IntervalMap<uint64_t, StringRef>::iterator ContainingFunc
- = FuncMap.find(SecAddr + RelOffset);
- if (ContainingFunc.valid()) {
- // Re-base the relocation to make it relative to the target function
- RelOffset = (SecAddr + RelOffset) - ContainingFunc.start();
- Relocations[SymName].push_back(RelocationEntry(ContainingFunc.value(),
- RelOffset,
- RelType,
- RelAddend,
- true));
- } else {
- Relocations[SymName].push_back(RelocationEntry(SecName,
- RelOffset,
- RelType,
- RelAddend,
- false));
- }
- }
- }
- return false;
-}
-
-void RuntimeDyldELF::resolveRelocations() {
- // FIXME: deprecated. should be changed to use the by-section
- // allocation and relocation scheme.
-
- // Just iterate over the symbols in our symbol table and assign their
- // addresses.
- StringMap<SymbolLoc>::iterator i = SymbolTable.begin();
- StringMap<SymbolLoc>::iterator e = SymbolTable.end();
- for (;i != e; ++i) {
- assert (i->getValue().second == 0 && "non-zero offset in by-function sym!");
- reassignSymbolAddress(i->getKey(),
- (uint8_t*)Sections[i->getValue().first].base());
- }
-}
-
-void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
- uint8_t *Addr,
- const RelocationEntry &RE) {
- uint8_t *TargetAddr;
- if (RE.IsFunctionRelative) {
- StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
- assert(Loc != SymbolTable.end() && "Function for relocation not found");
- TargetAddr =
- reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
- Loc->second.second + RE.Offset;
- } else {
- // FIXME: Get the address of the target section and add that to RE.Offset
- llvm_unreachable("Non-function relocation not implemented yet!");
- }
-
- switch (RE.Type) {
- default: llvm_unreachable("Relocation type not implemented yet!");
+void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
+ switch (Type) {
+ default:
+ llvm_unreachable("Relocation type not implemented yet!");
+ break;
case ELF::R_X86_64_64: {
- uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
- *Target = Addr + RE.Addend;
+ uint64_t *Target = (uint64_t*)(LocalAddress);
+ *Target = Value + Addend;
break;
}
case ELF::R_X86_64_32:
case ELF::R_X86_64_32S: {
- uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
+ Value += Addend;
// FIXME: Handle the possibility of this assertion failing
- assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
- (RE.Type == ELF::R_X86_64_32S &&
+ assert((Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
+ (Type == ELF::R_X86_64_32S &&
(Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
- uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
+ uint32_t *Target = reinterpret_cast<uint32_t*>(LocalAddress);
*Target = TruncatedAddr;
break;
}
case ELF::R_X86_64_PC32: {
- uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
- uint64_t RealOffset = *Placeholder +
- reinterpret_cast<uint64_t>(Addr) +
- RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
- assert((RealOffset & 0xFFFFFFFF) == RealOffset);
- uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
+ int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
+ assert(RealOffset <= 214783647 && RealOffset >= -214783648);
+ int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
*Placeholder = TruncOffset;
break;
}
}
}
-void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
- uint8_t *Addr,
- const RelocationEntry &RE) {
- uint8_t *TargetAddr;
- if (RE.IsFunctionRelative) {
- StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
- assert(Loc != SymbolTable.end() && "Function for relocation not found");
- TargetAddr =
- reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
- Loc->second.second + RE.Offset;
- } else {
- // FIXME: Get the address of the target section and add that to RE.Offset
- llvm_unreachable("Non-function relocation not implemented yet!");
- }
-
- switch (RE.Type) {
+void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
+ uint32_t FinalAddress,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ switch (Type) {
case ELF::R_386_32: {
- uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
- *Target = Addr + RE.Addend;
+ uint32_t *Target = (uint32_t*)(LocalAddress);
+ *Target = Value + Addend;
break;
}
case ELF::R_386_PC32: {
- uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
- uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
- RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
+ uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
+ uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
*Placeholder = RealOffset;
break;
}
@@ -248,57 +84,174 @@ void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
// There are other relocation types, but it appears these are the
// only ones currently used by the LLVM ELF object writer
llvm_unreachable("Relocation type not implemented yet!");
+ break;
}
}
-void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
- uint8_t *Addr,
- const RelocationEntry &RE) {
+void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
+ uint32_t FinalAddress,
+ uint32_t Value,
+ uint32_t Type,
+ int32_t Addend) {
+ // TODO: Add Thumb relocations.
+ uint32_t* TargetPtr = (uint32_t*)LocalAddress;
+ Value += Addend;
+
+ DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << LocalAddress
+ << " FinalAddress: " << format("%p",FinalAddress)
+ << " Value: " << format("%x",Value)
+ << " Type: " << format("%x",Type)
+ << " Addend: " << format("%x",Addend)
+ << "\n");
+
+ switch(Type) {
+ default:
+ llvm_unreachable("Not implemented relocation type!");
+
+ // Just write 32bit value to relocation address
+ case ELF::R_ARM_ABS32 :
+ *TargetPtr = Value;
+ break;
+
+ // Write first 16 bit of 32 bit value to the mov instruction.
+ // Last 4 bit should be shifted.
+ case ELF::R_ARM_MOVW_ABS_NC :
+ Value = Value & 0xFFFF;
+ *TargetPtr |= Value & 0xFFF;
+ *TargetPtr |= ((Value >> 12) & 0xF) << 16;
+ break;
+
+ // Write last 16 bit of 32 bit value to the mov instruction.
+ // Last 4 bit should be shifted.
+ case ELF::R_ARM_MOVT_ABS :
+ Value = (Value >> 16) & 0xFFFF;
+ *TargetPtr |= Value & 0xFFF;
+ *TargetPtr |= ((Value >> 12) & 0xF) << 16;
+ break;
+
+ // Write 24 bit relative value to the branch instruction.
+ case ELF::R_ARM_PC24 : // Fall through.
+ case ELF::R_ARM_CALL : // Fall through.
+ case ELF::R_ARM_JUMP24 :
+ int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
+ RelValue = (RelValue & 0x03FFFFFC) >> 2;
+ *TargetPtr &= 0xFF000000;
+ *TargetPtr |= RelValue;
+ break;
+ }
}
-void RuntimeDyldELF::resolveRelocation(StringRef Name,
- uint8_t *Addr,
- const RelocationEntry &RE) {
+void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
+ uint64_t FinalAddress,
+ uint64_t Value,
+ uint32_t Type,
+ int64_t Addend) {
switch (Arch) {
case Triple::x86_64:
- resolveX86_64Relocation(Name, Addr, RE);
+ resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
break;
case Triple::x86:
- resolveX86Relocation(Name, Addr, RE);
+ resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
+ (uint32_t)(Value & 0xffffffffL), Type,
+ (uint32_t)(Addend & 0xffffffffL));
break;
- case Triple::arm:
- resolveArmRelocation(Name, Addr, RE);
+ case Triple::arm: // Fall through.
+ case Triple::thumb:
+ resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
+ (uint32_t)(Value & 0xffffffffL), Type,
+ (uint32_t)(Addend & 0xffffffffL));
break;
default: llvm_unreachable("Unsupported CPU type!");
}
}
-void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
- // FIXME: deprecated. switch to reassignSectionAddress() instead.
- //
- // Actually moving the symbol address requires by-section mapping.
- assert(Sections[SymbolTable.lookup(Name).first].base() == (void*)Addr &&
- "Unable to relocate section in by-function JIT allocation model!");
-
- RelocationList &Relocs = Relocations[Name];
- for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
- RelocationEntry &RE = Relocs[i];
- resolveRelocation(Name, Addr, RE);
+void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
+ const ObjectFile &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
+ LocalSymbolMap &Symbols,
+ StubMap &Stubs) {
+
+ uint32_t RelType = (uint32_t)(Rel.Type & 0xffffffffL);
+ intptr_t Addend = (intptr_t)Rel.AdditionalInfo;
+ RelocationValueRef Value;
+ StringRef TargetName;
+ const SymbolRef &Symbol = Rel.Symbol;
+ Symbol.getName(TargetName);
+ DEBUG(dbgs() << "\t\tRelType: " << RelType
+ << " Addend: " << Addend
+ << " TargetName: " << TargetName
+ << "\n");
+ // First look the symbol in object file symbols.
+ LocalSymbolMap::iterator lsi = Symbols.find(TargetName.data());
+ if (lsi != Symbols.end()) {
+ Value.SectionID = lsi->second.first;
+ Value.Addend = lsi->second.second;
+ } else {
+ // Second look the symbol in global symbol table.
+ StringMap<SymbolLoc>::iterator gsi = SymbolTable.find(TargetName.data());
+ if (gsi != SymbolTable.end()) {
+ Value.SectionID = gsi->second.first;
+ Value.Addend = gsi->second.second;
+ } else {
+ SymbolRef::Type SymType;
+ Symbol.getType(SymType);
+ switch (SymType) {
+ case SymbolRef::ST_Debug: {
+ // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
+ // and can be changed by another developers. Maybe best way is add
+ // a new symbol type ST_Section to SymbolRef and use it.
+ section_iterator si = Obj.end_sections();
+ Symbol.getSection(si);
+ if (si == Obj.end_sections())
+ llvm_unreachable("Symbol section not found, bad object file format!");
+ DEBUG(dbgs() << "\t\tThis is section symbol\n");
+ Value.SectionID = findOrEmitSection((*si), true, ObjSectionToID);
+ Value.Addend = Addend;
+ break;
+ }
+ case SymbolRef::ST_Unknown: {
+ Value.SymbolName = TargetName.data();
+ Value.Addend = Addend;
+ break;
+ }
+ default:
+ llvm_unreachable("Unresolved symbol type!");
+ break;
+ }
+ }
}
-}
-
-// Assign an address to a symbol name and resolve all the relocations
-// associated with it.
-void RuntimeDyldELF::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
- // The address to use for relocation resolution is not
- // the address of the local section buffer. We must be doing
- // a remote execution environment of some sort. Re-apply any
- // relocations referencing this section with the given address.
- //
- // Addr is a uint64_t because we can't assume the pointer width
- // of the target is the same as that of the host. Just use a generic
- // "big enough" type.
- assert(0);
+ DEBUG(dbgs() << "\t\tRel.SectionID: " << Rel.SectionID
+ << " Rel.Offset: " << Rel.Offset
+ << "\n");
+ if (Arch == Triple::arm &&
+ (RelType == ELF::R_ARM_PC24 ||
+ RelType == ELF::R_ARM_CALL ||
+ RelType == ELF::R_ARM_JUMP24)) {
+ // This is an ARM branch relocation, need to use a stub function.
+ DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
+ SectionEntry &Section = Sections[Rel.SectionID];
+ uint8_t *Target = Section.Address + Rel.Offset;
+
+ // Look up for existing stub.
+ StubMap::const_iterator i = Stubs.find(Value);
+ if (i != Stubs.end()) {
+ resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
+ i->second, RelType, 0);
+ DEBUG(dbgs() << " Stub function found\n");
+ } else {
+ // Create a new stub function.
+ DEBUG(dbgs() << " Create a new stub function\n");
+ Stubs[Value] = Section.StubOffset;
+ uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+ Section.StubOffset);
+ AddRelocation(Value, Rel.SectionID,
+ StubTargetAddr - Section.Address, ELF::R_ARM_ABS32);
+ resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
+ Section.StubOffset, RelType, 0);
+ Section.StubOffset += getMaxStubSize();
+ }
+ } else
+ AddRelocation(Value, Rel.SectionID, Rel.Offset, RelType);
}
bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {