// compute stub buffer size for the given section unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, const SectionRef &Section) { unsigned StubSize = getMaxStubSize(); if (StubSize == 0) { return 0; } // FIXME: this is an inefficient way to handle this. We should computed the // necessary section allocation size in loadObject by walking all the sections // once. unsigned StubBufSize = 0; for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); SI != SE; ++SI) { section_iterator RelSecI = SI->getRelocatedSection(); if (!(RelSecI == Section)) continue; for (const RelocationRef &Reloc : SI->relocations()) { (void)Reloc; StubBufSize += StubSize; } } // Get section data size and alignment uint64_t DataSize = Section.getSize(); uint64_t Alignment64 = Section.getAlignment(); // Add stubbuf size alignment unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; unsigned StubAlignment = getStubAlignment(); unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); if (StubAlignment > EndAlignment) StubBufSize += StubAlignment - EndAlignment; return StubBufSize; }
void RuntimeDyldMachO::finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) { unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; unsigned TextSID = RTDYLD_INVALID_SECTION_ID; unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; ObjSectionToIDMap::iterator i, e; for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { const SectionRef &Section = i->first; StringRef Name; Section.getName(Name); if (Name == "__eh_frame") EHFrameSID = i->second; else if (Name == "__text") TextSID = i->second; else if (Name == "__gcc_except_tab") ExceptTabSID = i->second; else if (Name == "__jump_table") populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, i->second); else if (Name == "__pointers") populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, i->second); } UnregisteredEHFrameSections.push_back( EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); }
void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, uint64_t TotalSize, SymbolTableMap &SymbolTable) { // Allocate memory for the section unsigned SectionID = Sections.size(); uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*), SectionID); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; Sections.push_back(SectionEntry(Addr, TotalSize, TotalSize, 0)); memset(Addr, 0, TotalSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " << format("%p", Addr) << " DataSize: " << TotalSize << "\n"); // Assign the address of each symbol for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(), itEnd = CommonSymbols.end(); it != itEnd; it++) { StringRef Name; it->first.getName(Name); Obj.updateSymbolAddress(it->first, (uint64_t)Addr); SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); uint64_t Size = it->second; Offset += Size; Addr += Size; } }
void MCJIT::generateCodeForModule(Module *M) { // This must be a module which has already been added to this MCJIT instance. assert(std::find(Modules.begin(), Modules.end(), M) != Modules.end()); assert(ModuleStates.find(M) != ModuleStates.end()); // Get a thread lock to make sure we aren't trying to load multiple times MutexGuard locked(lock); // Re-compilation is not supported if (ModuleStates[M].hasBeenLoaded()) return; OwningPtr<ObjectBuffer> ObjectToLoad; // Try to load the pre-compiled object from cache if possible if (0 != ObjCache) { OwningPtr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M)); if (0 != PreCompiledObject.get()) ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.take())); } // If the cache did not contain a suitable object, compile the object if (!ObjectToLoad) { ObjectToLoad.reset(emitObject(M)); assert(ObjectToLoad.get() && "Compilation did not produce an object."); } // Load the object into the dynamic linker. // MCJIT now owns the ObjectImage pointer (via its LoadedObjects map). ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.take()); LoadedObjects[M] = LoadedObject; if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); // FIXME: Make this optional, maybe even move it to a JIT event listener LoadedObject->registerWithDebugger(); NotifyObjectEmitted(*LoadedObject); ModuleStates[M] = ModuleLoaded; }
void MCJIT::generateCodeForModule(Module *M) { // Get a thread lock to make sure we aren't trying to load multiple times MutexGuard locked(lock); // This must be a module which has already been added to this MCJIT instance. assert(OwnedModules.ownsModule(M) && "MCJIT::generateCodeForModule: Unknown module."); // Re-compilation is not supported if (OwnedModules.hasModuleBeenLoaded(M)) return; std::unique_ptr<ObjectBuffer> ObjectToLoad; // Try to load the pre-compiled object from cache if possible if (ObjCache) { std::unique_ptr<MemoryBuffer> PreCompiledObject(ObjCache->getObject(M)); if (PreCompiledObject.get()) ObjectToLoad.reset(new ObjectBuffer(PreCompiledObject.release())); } // If the cache did not contain a suitable object, compile the object if (!ObjectToLoad) { ObjectToLoad.reset(emitObject(M)); assert(ObjectToLoad.get() && "Compilation did not produce an object."); } // Load the object into the dynamic linker. // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list). ObjectImage *LoadedObject = Dyld.loadObject(ObjectToLoad.release()); LoadedObjects.push_back(LoadedObject); if (!LoadedObject) report_fatal_error(Dyld.getErrorString()); // FIXME: Make this optional, maybe even move it to a JIT event listener LoadedObject->registerWithDebugger(); NotifyObjectEmitted(*LoadedObject); OwnedModules.markModuleAsLoaded(M); }
virtual void NotifyObjectEmitted(const ObjectImage &obj) { uint64_t Addr; object::SymbolRef::Type SymbolType; #ifdef LLVM35 for (const object::SymbolRef &sym_iter : obj.symbols()) { sym_iter.getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter.getAddress(Addr); ObjectInfo tmp = {obj.getObjectFile(), sym_iter, obj.getData().size()}; objectmap[Addr] = tmp; } #else error_code itererr; object::symbol_iterator sym_iter = obj.begin_symbols(); object::symbol_iterator sym_end = obj.end_symbols(); for (; sym_iter != sym_end; sym_iter.increment(itererr)) { sym_iter->getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter->getAddress(Addr); ObjectInfo tmp = {obj.getObjectFile(), *sym_iter}; objectmap[Addr] = tmp; } #endif }
void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, const relocation_iterator &RI, unsigned OffsetToNextPC) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo); if (IsPCRel) { uint64_t RelocAddr = 0; RI->getAddress(RelocAddr); Value.Addend += RelocAddr + OffsetToNextPC; } }
RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( ObjectImage &ObjImg, const relocation_iterator &RI, const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols) { const MachOObjectFile &Obj = static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); if (IsExternal) { symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); if (SI != Symbols.end()) { Value.SectionID = SI->second.first; Value.Addend = SI->second.second + RE.Addend; } else { SI = GlobalSymbolTable.find(TargetName.data()); if (SI != GlobalSymbolTable.end()) { Value.SectionID = SI->second.first; Value.Addend = SI->second.second + RE.Addend; } else { Value.SymbolName = TargetName.data(); Value.Addend = RE.Addend; } } } else { SectionRef Sec = Obj.getRelocationSection(RelInfo); bool IsCode = false; Sec.isText(IsCode); Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); uint64_t Addr; Sec.getAddress(Addr); Value.Addend = RE.Addend - Addr; } return Value; }
void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, RelocationRef RelI, ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) { const ObjectFile *OF = Obj.getObjectFile(); const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl()); uint32_t RelType = MachO->getAnyRelocationType(RE); // FIXME: Properly handle scattered relocations. // For now, optimistically skip these: they can often be ignored, as // the static linker will already have applied the relocation, and it // only needs to be reapplied if symbols move relative to one another. // Note: This will fail horribly where the relocations *do* need to be // applied, but that was already the case. if (MachO->isRelocationScattered(RE)) return; RelocationValueRef Value; SectionEntry &Section = Sections[SectionID]; bool isExtern = MachO->getPlainRelocationExternal(RE); bool IsPCRel = MachO->getAnyRelocationPCRel(RE); unsigned Size = MachO->getAnyRelocationLength(RE); uint64_t Offset; RelI.getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; uint64_t Addend = 0; memcpy(&Addend, LocalAddress, NumBytes); if (isExtern) { // Obtain the symbol name which is referenced in the relocation symbol_iterator Symbol = RelI.getSymbol(); StringRef TargetName; Symbol->getName(TargetName); // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); if (lsi != Symbols.end()) { Value.SectionID = lsi->second.first; Value.Addend = lsi->second.second + Addend; } else { // Search for the symbol in the global symbol table SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data()); if (gsi != GlobalSymbolTable.end()) { Value.SectionID = gsi->second.first; Value.Addend = gsi->second.second + Addend; } else { Value.SymbolName = TargetName.data(); Value.Addend = Addend; } } } else { SectionRef Sec = MachO->getRelocationSection(RE); bool IsCode = false; Sec.isText(IsCode); Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); uint64_t Addr; Sec.getAddress(Addr); Value.Addend = Addend - Addr; if (IsPCRel) Value.Addend += Offset + NumBytes; } if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || RelType == MachO::X86_64_RELOC_GOT_LOAD)) { assert(IsPCRel); assert(Size == 2); StubMap::const_iterator i = Stubs.find(Value); uint8_t *Addr; if (i != Stubs.end()) { Addr = Section.Address + i->second; } else { Stubs[Value] = Section.StubOffset; uint8_t *GOTEntry = Section.Address + Section.StubOffset; RelocationEntry RE(SectionID, Section.StubOffset, MachO::X86_64_RELOC_UNSIGNED, 0, false, 3); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); Section.StubOffset += 8; Addr = GOTEntry; } resolveRelocation(Section, Offset, (uint64_t)Addr, MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2); } else if (Arch == Triple::arm && (RelType & 0xf) == MachO::ARM_RELOC_BR24) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) resolveRelocation(Section, Offset, (uint64_t)Section.Address + i->second, RelType, 0, IsPCRel, Size); else { // Create a new stub function. Stubs[Value] = Section.StubOffset; uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, MachO::GENERIC_RELOC_VANILLA, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); resolveRelocation(Section, Offset, (uint64_t)Section.Address + Section.StubOffset, RelType, 0, IsPCRel, Size); Section.StubOffset += getMaxStubSize(); } } else { RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, IsPCRel, Size); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); } }
void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel, ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, StubMap &Stubs) { uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL); RelocationValueRef Value; SectionEntry &Section = Sections[Rel.SectionID]; bool isExtern = (RelType >> 27) & 1; if (isExtern) { // Obtain the symbol name which is referenced in the relocation StringRef TargetName; const SymbolRef &Symbol = Rel.Symbol; Symbol.getName(TargetName); // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); if (lsi != Symbols.end()) { Value.SectionID = lsi->second.first; Value.Addend = lsi->second.second; } else { // Search for the symbol in the global symbol table SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data()); if (gsi != GlobalSymbolTable.end()) { Value.SectionID = gsi->second.first; Value.Addend = gsi->second.second; } else Value.SymbolName = TargetName.data(); } } else { error_code err; uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF); section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); for (uint8_t i = 1; i < sectionIndex; i++) { error_code err; si.increment(err); if (si == se) break; } assert(si != se && "No section containing relocation!"); Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID); Value.Addend = 0; // FIXME: The size and type of the relocation determines if we can // encode an Addend in the target location itself, and if so, how many // bytes we should read in order to get it. We don't yet support doing // that, and just assuming it's sizeof(intptr_t) is blatantly wrong. //Value.Addend = *(const intptr_t *)Target; if (Value.Addend) { // The MachO addend is an offset from the current section. We need it // to be an offset from the destination section Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress; } } if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. StubMap::const_iterator i = Stubs.find(Value); if (i != Stubs.end()) resolveRelocation(Section, Rel.Offset, (uint64_t)Section.Address + i->second, RelType, 0); else { // Create a new stub function. Stubs[Value] = Section.StubOffset; uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(Rel.SectionID, StubTargetAddr - Section.Address, macho::RIT_Vanilla, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); resolveRelocation(Section, Rel.Offset, (uint64_t)Section.Address + Section.StubOffset, RelType, 0); Section.StubOffset += getMaxStubSize(); } } else { RelocationEntry RE(Rel.SectionID, Rel.Offset, RelType, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); } }
virtual void NotifyObjectEmitted(const ObjectImage &obj) #endif { int8_t gc_state = jl_gc_safe_enter(); uv_rwlock_wrlock(&threadsafe); jl_gc_safe_leave(gc_state); #ifdef LLVM36 object::section_iterator Section = obj.section_begin(); object::section_iterator EndSection = obj.section_end(); #else object::section_iterator Section = obj.begin_sections(); object::section_iterator EndSection = obj.end_sections(); #endif #if defined(_OS_WINDOWS_) uint64_t SectionAddrCheck = 0; // assert that all of the Sections are at the same location uint8_t *UnwindData = NULL; #if defined(_CPU_X86_64_) uint8_t *catchjmp = NULL; for (const object::SymbolRef &sym_iter : obj.symbols()) { StringRef sName; #ifdef LLVM37 sName = sym_iter.getName().get(); #else sym_iter.getName(sName); #endif uint8_t **pAddr = NULL; if (sName.equals("__UnwindData")) { pAddr = &UnwindData; } else if (sName.equals("__catchjmp")) { pAddr = &catchjmp; } if (pAddr) { uint64_t Addr, SectionAddr; #if defined(LLVM38) Addr = sym_iter.getAddress().get(); Section = sym_iter.getSection().get(); assert(Section != EndSection && Section->isText()); SectionAddr = L.getSectionLoadAddress(*Section); #elif defined(LLVM37) Addr = sym_iter.getAddress().get(); sym_iter.getSection(Section); assert(Section != EndSection && Section->isText()); Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); #elif defined(LLVM36) sym_iter.getAddress(Addr); sym_iter.getSection(Section); assert(Section != EndSection && Section->isText()); Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); #else // LLVM35 sym_iter.getAddress(Addr); sym_iter.getSection(Section); assert(Section != EndSection); assert(!Section->isText(isText) && isText); Section->getAddress(SectionAddr); #endif #ifdef LLVM36 Addr += SectionAddr; #endif *pAddr = (uint8_t*)Addr; if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; } } assert(catchjmp); assert(UnwindData); assert(SectionAddrCheck); catchjmp[0] = 0x48; catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&_seh_exception_handle] *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler; catchjmp[10] = 0xff; catchjmp[11] = 0xe0; // jmp RAX UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER UnwindData[1] = 4; // size of prolog (bytes) UnwindData[2] = 2; // count of unwind codes (slots) UnwindData[3] = 0x05; // frame register (rbp) = rsp UnwindData[4] = 4; // second instruction UnwindData[5] = 0x03; // mov RBP, RSP UnwindData[6] = 1; // first instruction UnwindData[7] = 0x50; // push RBP *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionAddrCheck); // relative location of catchjmp #endif // defined(_OS_X86_64_) #endif // defined(_OS_WINDOWS_) #ifdef LLVM37 auto symbols = object::computeSymbolSizes(obj); for(const auto &sym_size : symbols) { const object::SymbolRef &sym_iter = sym_size.first; object::SymbolRef::Type SymbolType = sym_iter.getType(); if (SymbolType != object::SymbolRef::ST_Function) continue; uint64_t Size = sym_size.second; uint64_t Addr = sym_iter.getAddress().get(); #ifdef LLVM38 Section = sym_iter.getSection().get(); #else sym_iter.getSection(Section); #endif if (Section == EndSection) continue; if (!Section->isText()) continue; #ifdef LLVM38 uint64_t SectionAddr = L.getSectionLoadAddress(*Section); #else StringRef secName; Section->getName(secName); uint64_t SectionAddr = L.getSectionLoadAddress(secName); #endif Addr += SectionAddr; StringRef sName = sym_iter.getName().get(); #if defined(_OS_WINDOWS_) uint64_t SectionSize = Section->getSize(); if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; create_PRUNTIME_FUNCTION( (uint8_t*)(intptr_t)Addr, (size_t)Size, sName, (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData); #endif StringMap<jl_lambda_info_t*>::iterator linfo_it = linfo_in_flight.find(sName); jl_lambda_info_t *linfo = NULL; if (linfo_it != linfo_in_flight.end()) { linfo = linfo_it->second; linfo_in_flight.erase(linfo_it); } ObjectInfo tmp = {&debugObj, (size_t)Size, L.clone().release(), linfo}; objectmap[Addr] = tmp; } #else // pre-LLVM37 uint64_t Addr; uint64_t Size; object::SymbolRef::Type SymbolType; StringRef sName; #ifdef LLVM36 uint64_t SectionAddr = 0; #else bool isText; #ifdef _OS_WINDOWS_ uint64_t SectionAddr = 0; #endif #endif #if defined(LLVM35) for (const object::SymbolRef &sym_iter : obj.symbols()) { sym_iter.getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter.getSize(Size); sym_iter.getAddress(Addr); sym_iter.getSection(Section); if (Section == EndSection) continue; #if defined(LLVM36) if (!Section->isText()) continue; Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); Addr += SectionAddr; #else if (Section->isText(isText) || !isText) continue; #endif sym_iter.getName(sName); #ifdef _OS_DARWIN_ # if !defined(LLVM36) Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); if (!Addr && sName[0] == '_') { Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName.substr(1), true); } if (!Addr) continue; # endif #elif defined(_OS_WINDOWS_) uint64_t SectionSize = 0; # if defined(LLVM36) SectionSize = Section->getSize(); # else Section->getAddress(SectionAddr); Section->getSize(SectionSize); # endif if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; create_PRUNTIME_FUNCTION( (uint8_t*)(intptr_t)Addr, (size_t)Size, sName, (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData); #endif StringMap<jl_lambda_info_t*>::iterator linfo_it = linfo_in_flight.find(sName); jl_lambda_info_t *linfo = NULL; if (linfo_it != linfo_in_flight.end()) { linfo = linfo_it->second; linfo_in_flight.erase(linfo_it); } const object::ObjectFile *objfile = #ifdef LLVM36 &obj; #else obj.getObjectFile(); #endif ObjectInfo tmp = {objfile, (size_t)Size, #ifdef LLVM37 L.clone().release(), #elif defined(LLVM36) (size_t)SectionAddr, #endif #ifdef _OS_DARWIN_ strndup(sName.data(), sName.size()), #endif linfo }; objectmap[Addr] = tmp; } #else //LLVM34 error_code itererr; object::symbol_iterator sym_iter = obj.begin_symbols(); object::symbol_iterator sym_end = obj.end_symbols(); for (; sym_iter != sym_end; sym_iter.increment(itererr)) { sym_iter->getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter->getAddress(Addr); sym_iter->getSize(Size); ObjectInfo tmp = {obj.getObjectFile(), (size_t)Size}; objectmap[Addr] = tmp; } #endif #endif uv_rwlock_wrunlock(&threadsafe); }
// Compute an upper bound of the memory size that is required to load all // sections void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW) { // Compute the size of all sections required for execution std::vector<uint64_t> CodeSectionSizes; std::vector<uint64_t> ROSectionSizes; std::vector<uint64_t> RWSectionSizes; uint64_t MaxAlignment = sizeof(void *); // Collect sizes of all sections to be loaded; // also determine the max alignment of all sections for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); SI != SE; ++SI) { const SectionRef &Section = *SI; bool IsRequired = Section.isRequiredForExecution(); // Consider only the sections that are required to be loaded for execution if (IsRequired) { StringRef Name; uint64_t DataSize = Section.getSize(); uint64_t Alignment64 = Section.getAlignment(); bool IsCode = Section.isText(); bool IsReadOnly = Section.isReadOnlyData(); Check(Section.getName(Name)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section); uint64_t SectionSize = DataSize + StubBufSize; // The .eh_frame section (at least on Linux) needs an extra four bytes // padded // with zeroes added at the end. For MachO objects, this section has a // slightly different name, so this won't have any effect for MachO // objects. if (Name == ".eh_frame") SectionSize += 4; if (SectionSize > 0) { // save the total size of the section if (IsCode) { CodeSectionSizes.push_back(SectionSize); } else if (IsReadOnly) { ROSectionSizes.push_back(SectionSize); } else { RWSectionSizes.push_back(SectionSize); } // update the max alignment if (Alignment > MaxAlignment) { MaxAlignment = Alignment; } } } } // Compute the size of all common symbols uint64_t CommonSize = 0; for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; ++I) { uint32_t Flags = I->getFlags(); if (Flags & SymbolRef::SF_Common) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = 0; Check(I->getSize(Size)); CommonSize += Size; } } if (CommonSize != 0) { RWSectionSizes.push_back(CommonSize); } // Compute the required allocation space for each different type of sections // (code, read-only data, read-write data) assuming that all sections are // allocated with the max alignment. Note that we cannot compute with the // individual alignments of the sections, because then the required size // depends on the order, in which the sections are allocated. CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment); DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment); DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment); }
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode) { unsigned StubBufSize = 0, StubSize = getMaxStubSize(); error_code err; if (StubSize > 0) { for (relocation_iterator i = Section.begin_relocations(), e = Section.end_relocations(); i != e; i.increment(err), Check(err)) StubBufSize += StubSize; } StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; bool IsRequired; bool IsVirtual; bool IsZeroInit; uint64_t DataSize; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); Check(Section.isZeroInit(IsZeroInit)); Check(Section.getSize(DataSize)); unsigned Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + StubBufSize; Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); if (!Addr) report_fatal_error("Unable to allocate section memory!"); // Virtual sections have no data in the object image, so leave pData = 0 if (!IsVirtual) pData = data.data(); // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); else memcpy(Addr, pData, DataSize); DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything // with these sections). Allocate = 0; Addr = 0; DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " obj addr: " << format("%p", data.data()) << " new addr: 0" << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); } Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); return SectionID; }
virtual void NotifyObjectEmitted(const ObjectImage &obj) #endif { uint64_t Addr; uint64_t Size; object::SymbolRef::Type SymbolType; #ifdef LLVM36 object::section_iterator Section = obj.section_begin(); object::section_iterator EndSection = obj.section_end(); uint64_t SectionAddr = 0; StringRef sName; #else object::section_iterator Section = obj.begin_sections(); object::section_iterator EndSection = obj.end_sections(); bool isText; #ifndef _OS_LINUX_ StringRef sName; #endif #endif #ifndef LLVM36 uint64_t SectionAddr = 0; #endif uint64_t SectionSize = 0; uint64_t SectionAddrCheck = 0; // assert that all of the Sections are at the same location #if defined(_OS_WINDOWS_) #if defined(_CPU_X86_64_) uint8_t *UnwindData = NULL; uint8_t *catchjmp = NULL; for (const object::SymbolRef &sym_iter : obj.symbols()) { # ifdef LLVM37 sName = sym_iter.getName().get(); # else sym_iter.getName(sName); # endif if (sName.equals("__UnwindData")) { # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); # ifdef LLVM36 assert(Section->isText()); Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); Addr += SectionAddr; # else if (Section->isText(isText) || !isText) assert(0 && "!isText"); Section->getAddress(SectionAddr); # endif UnwindData = (uint8_t*)Addr; if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; } if (sName.equals("__catchjmp")) { # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); # ifdef LLVM36 assert(Section->isText()); Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); Addr += SectionAddr; # else if (Section->isText(isText) || !isText) assert(0 && "!isText"); Section->getAddress(SectionAddr); # endif catchjmp = (uint8_t*)Addr; if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; } } assert(catchjmp); assert(UnwindData); catchjmp[0] = 0x48; catchjmp[1] = 0xb8; // mov RAX, QWORD PTR [&_seh_exception_handle] *(uint64_t*)(&catchjmp[2]) = (uint64_t)&_seh_exception_handler; catchjmp[10] = 0xff; catchjmp[11] = 0xe0; // jmp RAX UnwindData[0] = 0x09; // version info, UNW_FLAG_EHANDLER UnwindData[1] = 4; // size of prolog (bytes) UnwindData[2] = 2; // count of unwind codes (slots) UnwindData[3] = 0x05; // frame register (rbp) = rsp UnwindData[4] = 4; // second instruction UnwindData[5] = 0x03; // mov RBP, RSP UnwindData[6] = 1; // first instruction UnwindData[7] = 0x50; // push RBP *(DWORD*)&UnwindData[8] = (DWORD)(catchjmp - (uint8_t*)SectionAddr); // relative location of catchjmp #else // defined(_OS_X86_64_) uint8_t *UnwindData = NULL; #endif // defined(_OS_X86_64_) #endif // defined(_OS_WINDOWS_) #ifdef LLVM35 for (const object::SymbolRef &sym_iter : obj.symbols()) { # ifdef LLVM37 SymbolType = sym_iter.getType(); # else sym_iter.getType(SymbolType); # endif if (SymbolType != object::SymbolRef::ST_Function) continue; # ifdef LLVM37 Addr = sym_iter.getAddress().get(); # else sym_iter.getAddress(Addr); # endif sym_iter.getSection(Section); if (Section == EndSection) continue; #if defined(LLVM36) if (!Section->isText()) continue; Section->getName(sName); SectionAddr = L.getSectionLoadAddress(sName); Addr += SectionAddr; #else if (Section->isText(isText) || !isText) continue; #endif #if defined(LLVM36) SectionSize = Section->getSize(); #else Section->getAddress(SectionAddr); Section->getSize(SectionSize); #endif #ifdef _OS_DARWIN_ # if defined(LLVM37) Size = Section->getSize(); sName = sym_iter.getName().get(); # else sym_iter.getName(sName); # endif # if defined(LLVM36) if (sName[0] == '_') { sName = sName.substr(1); } # else Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); if (!Addr && sName[0] == '_') { sName = sName.substr(1); Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); } if (!Addr) continue; # endif #elif defined(_OS_WINDOWS_) # if defined(LLVM37) assert(obj.isELF()); Size = ((llvm::object::ELFSymbolRef)sym_iter).getSize(); sName = sym_iter.getName().get(); # else sym_iter.getSize(Size); sym_iter.getName(sName); # endif # ifdef _CPU_X86_ if (sName[0] == '_') sName = sName.substr(1); # endif if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else SectionAddrCheck = SectionAddr; create_PRUNTIME_FUNCTION( (uint8_t*)(intptr_t)Addr, (size_t)Size, sName, (uint8_t*)(intptr_t)SectionAddr, (size_t)SectionSize, UnwindData); #endif const object::ObjectFile *objfile = #ifdef LLVM36 &obj; #else obj.getObjectFile(); #endif ObjectInfo tmp = {objfile, SectionSize #ifdef LLVM37 ,L.clone().release() #elif defined(LLVM36) ,(size_t)SectionAddr #endif #ifdef _OS_DARWIN_ ,strndup(sName.data(), sName.size()) #endif }; objectmap[Addr] = tmp; } #else //LLVM34 error_code itererr; object::symbol_iterator sym_iter = obj.begin_symbols(); object::symbol_iterator sym_end = obj.end_symbols(); for (; sym_iter != sym_end; sym_iter.increment(itererr)) { sym_iter->getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; sym_iter->getAddress(Addr); sym_iter->getSize(Size); ObjectInfo tmp = {obj.getObjectFile(), (size_t)Size}; objectmap[Addr] = tmp; } #endif }
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode) { unsigned StubBufSize = 0, StubSize = getMaxStubSize(); error_code err; const ObjectFile *ObjFile = Obj.getObjectFile(); // FIXME: this is an inefficient way to handle this. We should computed the // necessary section allocation size in loadObject by walking all the sections // once. if (StubSize > 0) { for (section_iterator SI = ObjFile->begin_sections(), SE = ObjFile->end_sections(); SI != SE; SI.increment(err), Check(err)) { section_iterator RelSecI = SI->getRelocatedSection(); if (!(RelSecI == Section)) continue; for (relocation_iterator I = SI->begin_relocations(), E = SI->end_relocations(); I != E; I.increment(err), Check(err)) { StubBufSize += StubSize; } } } StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; bool IsRequired; bool IsVirtual; bool IsZeroInit; bool IsReadOnly; uint64_t DataSize; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); Check(Section.isZeroInit(IsZeroInit)); Check(Section.isReadOnlyData(IsReadOnly)); Check(Section.getSize(DataSize)); Check(Section.getName(Name)); if (StubSize > 0) { unsigned StubAlignment = getStubAlignment(); unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); if (StubAlignment > EndAlignment) StubBufSize += StubAlignment - EndAlignment; } unsigned Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + StubBufSize; Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); // Virtual sections have no data in the object image, so leave pData = 0 if (!IsVirtual) pData = data.data(); // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); else memcpy(Addr, pData, DataSize); DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything // with these sections). Allocate = 0; Addr = 0; DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", data.data()) << " new addr: 0" << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); } Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); return SectionID; }
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode) { StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; bool IsRequired; bool IsVirtual; bool IsZeroInit; bool IsReadOnly; uint64_t DataSize; unsigned PaddingSize = 0; unsigned StubBufSize = 0; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); Check(Section.isZeroInit(IsZeroInit)); Check(Section.isReadOnlyData(IsReadOnly)); Check(Section.getSize(DataSize)); Check(Section.getName(Name)); StubBufSize = computeSectionStubBufSize(Obj, Section); // The .eh_frame section (at least on Linux) needs an extra four bytes padded // with zeroes added at the end. For MachO objects, this section has a // slightly different name, so this won't have any effect for MachO objects. if (Name == ".eh_frame") PaddingSize = 4; uintptr_t Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + PaddingSize + StubBufSize; Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, Name) : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, Name, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); // Virtual sections have no data in the object image, so leave pData = 0 if (!IsVirtual) pData = data.data(); // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); else memcpy(Addr, pData, DataSize); // Fill in any extra bytes we allocated for padding if (PaddingSize != 0) { memset(Addr + DataSize, 0, PaddingSize); // Update the DataSize variable so that the stub offset is set correctly. DataSize += PaddingSize; } DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything // with these sections). Allocate = 0; Addr = 0; DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", data.data()) << " new addr: 0" << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); } Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); return SectionID; }