diff --git a/lldb/include/lldb/Expression/ClangExpression.h b/lldb/include/lldb/Expression/ClangExpression.h index 8bf48959fc80..37c76cae6f94 100644 --- a/lldb/include/lldb/Expression/ClangExpression.h +++ b/lldb/include/lldb/Expression/ClangExpression.h @@ -78,6 +78,9 @@ public: lldb::addr_t GetFunctionAddress (const char *name); + + Error + DisassembleFunction (Stream &stream, ExecutionContext &exc_context, const char *name); clang::CompilerInstance * GetCompilerInstance () diff --git a/lldb/include/lldb/Expression/RecordingMemoryManager.h b/lldb/include/lldb/Expression/RecordingMemoryManager.h index ce9d92a51a8f..f313688a5a4f 100644 --- a/lldb/include/lldb/Expression/RecordingMemoryManager.h +++ b/lldb/include/lldb/Expression/RecordingMemoryManager.h @@ -113,6 +113,9 @@ public: lldb::addr_t GetRemoteAddressForLocal (lldb::addr_t local_address); + + std::pair + GetRemoteRangeForLocal (lldb::addr_t local_address); bool WriteJITRegions (const ExecutionContext &exc_context); diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 303ca17cc56d..af19641d88e3 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -321,8 +321,21 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream { log->Printf("Function address : 0x%llx", (uint64_t)function_address); log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); - } + StreamString insns; + + Error err = clang_expr.DisassembleFunction(insns, m_exe_ctx, "___clang_expr"); + + if (!err.Success()) + { + log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); + } + else + { + log->Printf("Function disassembly:\n%s", insns.GetData()); + } + } + ClangFunction::ExecutionResults execution_result = ClangFunction::ExecuteFunction (m_exe_ctx, function_address, struct_address, true, true, 10000, error_stream); diff --git a/lldb/source/Expression/ClangExpression.cpp b/lldb/source/Expression/ClangExpression.cpp index 9468a706c0bf..cdb3383fd37f 100644 --- a/lldb/source/Expression/ClangExpression.cpp +++ b/lldb/source/Expression/ClangExpression.cpp @@ -56,6 +56,8 @@ // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/ClangForward.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Disassembler.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangResultSynthesizer.h" @@ -66,6 +68,7 @@ #include "lldb/Expression/RecordingMemoryManager.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" #include "lldb/Core/StreamString.h" #include "lldb/Host/Mutex.h" @@ -613,6 +616,128 @@ ClangExpression::GetFunctionAddress (const char *name) return LLDB_INVALID_ADDRESS; } +Error +ClangExpression::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, const char *name) +{ + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + Error ret; + + ret.Clear(); + + lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; + + std::vector::iterator pos, end = m_jitted_functions.end(); + + for (pos = m_jitted_functions.begin(); pos < end; pos++) + { + if (strcmp(pos->m_name.c_str(), name) == 0) + { + func_local_addr = pos->m_local_addr; + func_remote_addr = pos->m_remote_addr; + } + } + + if (func_local_addr == LLDB_INVALID_ADDRESS) + { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name); + return ret; + } + + if(log) + log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); + + std::pair func_range; + + func_range = m_jit_mm_ptr->GetRemoteRangeForLocal(func_local_addr); + + if (func_range.first == 0 && func_range.second == 0) + { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name); + return ret; + } + + if(log) + log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second); + + if (!exe_ctx.target) + { + ret.SetErrorToGenericError(); + ret.SetErrorString("Couldn't find the target"); + } + + lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_range.first, 0)); + + Error err; + exe_ctx.process->ReadMemory(func_range.first, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); + + if (!err.Success()) + { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); + return ret; + } + + ArchSpec arch(exe_ctx.target->GetArchitecture()); + + Disassembler *disassembler = Disassembler::FindPlugin(arch); + + if (disassembler == NULL) + { + ret.SetErrorToGenericError(); + ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString()); + return ret; + } + + if (!exe_ctx.process) + { + ret.SetErrorToGenericError(); + ret.SetErrorString("Couldn't find the process"); + return ret; + } + + DataExtractor extractor(buffer_sp, + exe_ctx.process->GetByteOrder(), + 32); + + if(log) + { + log->Printf("Function data has contents:"); + extractor.PutToLog (log, + 0, + extractor.GetByteSize(), + func_range.first, + 16, + DataExtractor::TypeUInt8); + } + + disassembler->DecodeInstructions(extractor, 0, UINT32_MAX); + + Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList(); + + uint32_t bytes_offset = 0; + + for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); + instruction_index < num_instructions; + ++instruction_index) + { + Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index); + instruction->Dump (&stream, + NULL, + &extractor, + bytes_offset, + exe_ctx, + true); + stream.PutChar('\n'); + bytes_offset += instruction->GetByteSize(); + } + + return ret; +} + unsigned ClangExpression::Compile() { diff --git a/lldb/source/Expression/RecordingMemoryManager.cpp b/lldb/source/Expression/RecordingMemoryManager.cpp index e1ccdbe7267c..08d315de7794 100644 --- a/lldb/source/Expression/RecordingMemoryManager.cpp +++ b/lldb/source/Expression/RecordingMemoryManager.cpp @@ -122,6 +122,25 @@ RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address) return LLDB_INVALID_ADDRESS; } +std::pair +RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address) +{ + std::vector::iterator pos, end = m_address_map.end(); + + for (pos = m_address_map.begin(); pos < end; ++pos) + { + lldb::addr_t lstart = pos->m_local_start; + lldb::addr_t lend = lstart + pos->m_size; + + if (local_address >= lstart && local_address < lend) + { + return std::pair (pos->m_remote_start, pos->m_remote_start + pos->m_size); + } + } + + return std::pair (0, 0); +} + void RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart) { diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp index 945ef871d688..ba98cb5a4509 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp @@ -140,14 +140,18 @@ DisassemblerLLVM::Instruction::Dump int currentOpIndex = -1; lldb_private::Process *process = exe_ctx.process; - addr_t base_addr = LLDB_INVALID_ADDRESS; - if (process && process->IsAlive()) - base_addr = inst_addr_ptr->GetLoadAddress (process); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = inst_addr_ptr->GetFileAddress (); - - RegisterReaderArg rra(base_addr + EDInstByteSize(m_inst), m_disassembler); - + std::auto_ptr rra; + + if (!raw) + { + addr_t base_addr = LLDB_INVALID_ADDRESS; + if (process && process->IsAlive()) + base_addr = inst_addr_ptr->GetLoadAddress (process); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = inst_addr_ptr->GetFileAddress (); + + rra.reset(new RegisterReaderArg(base_addr + EDInstByteSize(m_inst), m_disassembler)); + } bool printTokenized = false; @@ -228,7 +232,7 @@ DisassemblerLLVM::Instruction::Dump { uint64_t operand_value; - if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra)) + if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, rra.get())) { if (EDInstIsBranch(m_inst)) {