void jl_dump_function_asm(const char *Fptr, size_t Fsize, #ifndef USE_MCJIT std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, #else const object::ObjectFile *objectfile, #endif formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer #ifdef LLVM35 std::unique_ptr<MCStreamer> Streamer; #else OwningPtr<MCStreamer> Streamer; #endif SourceMgr SrcMgr; #ifdef LLVM35 std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #elif defined(LLVM34) llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); #ifdef LLVM35 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #else llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #endif assert(MRI && "Unable to create target register info!"); #ifdef LLVM35 std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #else OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #endif #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler #ifdef LLVM35 std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; #ifdef LLVM35 std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstrAnalysis> MCIA(TheTarget->createMCInstrAnalysis(MCII.get())); #else OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCInstrAnalysis> MCIA(TheTarget->createMCInstrAnalysis(MCII.get())); #endif MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); #ifdef LLVM36 Streamer->InitSections(true); #else Streamer->InitSections(); #endif // Make the MemoryObject wrapper #ifdef LLVM36 ArrayRef<uint8_t> memoryObject(const_cast<uint8_t*>((const uint8_t*)Fptr),Fsize); #else FuncMCView memoryObject(Fptr, Fsize); #endif SymbolTable DisInfo(Ctx, memoryObject); #ifdef USE_MCJIT if (!objectfile) return; #ifdef LLVM36 DIContext *di_ctx = DIContext::getDWARFContext(*objectfile); #else DIContext *di_ctx = DIContext::getDWARFContext(const_cast<object::ObjectFile*>(objectfile)); #endif if (di_ctx == NULL) return; DILineInfoTable lineinfo = di_ctx->getLineInfoForAddressRange((size_t)Fptr, Fsize); #else typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; #endif // Take two passes: In the first pass we record all branch labels, // in the second we actually perform the output for (int pass = 0; pass < 2; ++ pass) { DisInfo.setPass(pass); if (pass != 0) { // Switch to symbolic disassembly. We cannot do this // before the first pass, because this changes branch // targets from immediate values (constants) to // expressions, which are not handled correctly by // MCIA->evaluateBranch. (It should be possible to rewrite // this routine to handle this case correctly as well.) // Could add OpInfoLookup here #ifdef LLVM35 DisAsm->setSymbolizer(std::unique_ptr<MCSymbolizer>(new MCExternalSymbolizer( Ctx, std::unique_ptr<MCRelocationInfo>(new MCRelocationInfo(Ctx)), OpInfoLookup, SymbolLookup, &DisInfo))); #else DisAsm->setupForSymbolicDisassembly( OpInfoLookup, SymbolLookup, &DisInfo, &Ctx); #endif } uint64_t nextLineAddr = -1; #ifdef USE_MCJIT // Set up the line info DILineInfoTable::iterator lineIter = lineinfo.begin(); DILineInfoTable::iterator lineEnd = lineinfo.end(); if (lineIter != lineEnd) { nextLineAddr = lineIter->first; if (pass != 0) { #ifdef LLVM35 stream << "Filename: " << lineIter->second.FileName << "\n"; #else stream << "Filename: " << lineIter->second.getFileName() << "\n"; #endif } } #else // Set up the line info LInfoVec::iterator lineIter = lineinfo.begin(); LInfoVec::iterator lineEnd = lineinfo.end(); if (lineIter != lineEnd) { nextLineAddr = (*lineIter).Address; DISubprogram debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); if (pass != 0) { stream << "Filename: " << debugscope.getFilename() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } } #endif uint64_t Index = 0; uint64_t absAddr = 0; uint64_t insSize = 0; // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < Fsize; Index += insSize, absAddr += insSize) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { #ifdef USE_MCJIT #ifdef LLVM35 if (pass != 0) stream << "Source line: " << lineIter->second.Line << "\n"; #else if (pass != 0) stream << "Source line: " << lineIter->second.getLine() << "\n"; #endif nextLineAddr = (++lineIter)->first; #else if (pass != 0) stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; #endif } if (pass != 0) { // Uncomment this to output addresses for all instructions // stream << Index << ": "; const char *symbolName = DisInfo.lookupSymbol(Index); if (symbolName) stream << symbolName << ":"; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, insSize, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "invalid instruction encoding"); if (insSize == 0) insSize = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: if (pass == 0) { // Pass 0: Record all branch targets if (MCIA->isBranch(Inst)) { uint64_t addr; #ifdef LLVM35 if (MCIA->evaluateBranch(Inst, Index, insSize, addr)) #else if ((addr = MCIA->evaluateBranch(Inst, Index, insSize)) != (uint64_t)-1) #endif DisInfo.insertAddress(addr); } } else { // Pass 1: Output instruction #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif } break; } } if (pass == 0) DisInfo.createSymbols(); } }
void jl_dump_function_asm(void* Fptr, size_t Fsize, std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer OwningPtr<MCStreamer> Streamer; SourceMgr SrcMgr; #ifdef LLVM34 llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); #ifdef LLVM35 OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); Streamer->InitSections(); // Make the MemoryObject wrapper FuncMCView memoryObject(Fptr, Fsize); uint64_t Size; uint64_t Index; uint64_t absAddr; // Set up the line info typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; LInfoVec::iterator lineIter = lineinfo.begin(); lineIter = lineinfo.begin(); uint64_t nextLineAddr = -1; DISubprogram debugscope; if (lineIter != lineinfo.end()) { nextLineAddr = (*lineIter).Address; debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); stream << "Filename: " << debugscope.getFilename().data() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < memoryObject.getExtent(); Index += Size, absAddr += Size) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "invalid instruction encoding"); if (Size == 0) Size = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif break; } } }