forked from OSchip/llvm-project
Added extensive logging of the code that is actually going
to be executed by the inferior. This required explicit support from RecordingMemoryManager for finding the address range belonging to a particular function. Also fixed a bug in DisassemblerLLVM where the disassembler assumed there was an AddressRange available even when it was NULL. llvm-svn: 109209
This commit is contained in:
parent
318e40360d
commit
6dde30e964
|
@ -79,6 +79,9 @@ public:
|
||||||
lldb::addr_t
|
lldb::addr_t
|
||||||
GetFunctionAddress (const char *name);
|
GetFunctionAddress (const char *name);
|
||||||
|
|
||||||
|
Error
|
||||||
|
DisassembleFunction (Stream &stream, ExecutionContext &exc_context, const char *name);
|
||||||
|
|
||||||
clang::CompilerInstance *
|
clang::CompilerInstance *
|
||||||
GetCompilerInstance ()
|
GetCompilerInstance ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -114,6 +114,9 @@ public:
|
||||||
lldb::addr_t
|
lldb::addr_t
|
||||||
GetRemoteAddressForLocal (lldb::addr_t local_address);
|
GetRemoteAddressForLocal (lldb::addr_t local_address);
|
||||||
|
|
||||||
|
std::pair <lldb::addr_t, lldb::addr_t>
|
||||||
|
GetRemoteRangeForLocal (lldb::addr_t local_address);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WriteJITRegions (const ExecutionContext &exc_context);
|
WriteJITRegions (const ExecutionContext &exc_context);
|
||||||
|
|
||||||
|
|
|
@ -321,6 +321,19 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
|
||||||
{
|
{
|
||||||
log->Printf("Function address : 0x%llx", (uint64_t)function_address);
|
log->Printf("Function address : 0x%llx", (uint64_t)function_address);
|
||||||
log->Printf("Structure address : 0x%llx", (uint64_t)struct_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::ExecutionResults execution_result =
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
// Project includes
|
// Project includes
|
||||||
#include "lldb/Core/Log.h"
|
#include "lldb/Core/Log.h"
|
||||||
#include "lldb/Core/ClangForward.h"
|
#include "lldb/Core/ClangForward.h"
|
||||||
|
#include "lldb/Core/DataBufferHeap.h"
|
||||||
|
#include "lldb/Core/Disassembler.h"
|
||||||
#include "lldb/Expression/ClangExpression.h"
|
#include "lldb/Expression/ClangExpression.h"
|
||||||
#include "lldb/Expression/ClangASTSource.h"
|
#include "lldb/Expression/ClangASTSource.h"
|
||||||
#include "lldb/Expression/ClangResultSynthesizer.h"
|
#include "lldb/Expression/ClangResultSynthesizer.h"
|
||||||
|
@ -66,6 +68,7 @@
|
||||||
#include "lldb/Expression/RecordingMemoryManager.h"
|
#include "lldb/Expression/RecordingMemoryManager.h"
|
||||||
#include "lldb/Target/ExecutionContext.h"
|
#include "lldb/Target/ExecutionContext.h"
|
||||||
#include "lldb/Target/Process.h"
|
#include "lldb/Target/Process.h"
|
||||||
|
#include "lldb/Target/Target.h"
|
||||||
|
|
||||||
#include "lldb/Core/StreamString.h"
|
#include "lldb/Core/StreamString.h"
|
||||||
#include "lldb/Host/Mutex.h"
|
#include "lldb/Host/Mutex.h"
|
||||||
|
@ -613,6 +616,128 @@ ClangExpression::GetFunctionAddress (const char *name)
|
||||||
return LLDB_INVALID_ADDRESS;
|
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<JittedFunction>::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 <lldb::addr_t, lldb::addr_t> 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
|
unsigned
|
||||||
ClangExpression::Compile()
|
ClangExpression::Compile()
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,6 +122,25 @@ RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address)
|
||||||
return LLDB_INVALID_ADDRESS;
|
return LLDB_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair <lldb::addr_t, lldb::addr_t>
|
||||||
|
RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address)
|
||||||
|
{
|
||||||
|
std::vector<LocalToRemoteAddressRange>::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 <lldb::addr_t, lldb::addr_t> (pos->m_remote_start, pos->m_remote_start + pos->m_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::pair <lldb::addr_t, lldb::addr_t> (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart)
|
RecordingMemoryManager::AddToLocalToRemoteMap (lldb::addr_t lstart, size_t size, lldb::addr_t rstart)
|
||||||
{
|
{
|
||||||
|
|
|
@ -140,14 +140,18 @@ DisassemblerLLVM::Instruction::Dump
|
||||||
int currentOpIndex = -1;
|
int currentOpIndex = -1;
|
||||||
|
|
||||||
lldb_private::Process *process = exe_ctx.process;
|
lldb_private::Process *process = exe_ctx.process;
|
||||||
|
std::auto_ptr<RegisterReaderArg> rra;
|
||||||
|
|
||||||
|
if (!raw)
|
||||||
|
{
|
||||||
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
||||||
if (process && process->IsAlive())
|
if (process && process->IsAlive())
|
||||||
base_addr = inst_addr_ptr->GetLoadAddress (process);
|
base_addr = inst_addr_ptr->GetLoadAddress (process);
|
||||||
if (base_addr == LLDB_INVALID_ADDRESS)
|
if (base_addr == LLDB_INVALID_ADDRESS)
|
||||||
base_addr = inst_addr_ptr->GetFileAddress ();
|
base_addr = inst_addr_ptr->GetFileAddress ();
|
||||||
|
|
||||||
RegisterReaderArg rra(base_addr + EDInstByteSize(m_inst), m_disassembler);
|
rra.reset(new RegisterReaderArg(base_addr + EDInstByteSize(m_inst), m_disassembler));
|
||||||
|
}
|
||||||
|
|
||||||
bool printTokenized = false;
|
bool printTokenized = false;
|
||||||
|
|
||||||
|
@ -228,7 +232,7 @@ DisassemblerLLVM::Instruction::Dump
|
||||||
{
|
{
|
||||||
uint64_t operand_value;
|
uint64_t operand_value;
|
||||||
|
|
||||||
if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
|
if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, rra.get()))
|
||||||
{
|
{
|
||||||
if (EDInstIsBranch(m_inst))
|
if (EDInstIsBranch(m_inst))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue