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