Files
llvm/lldb/source/Target/ThreadPlanCallFunctionUsingABI.cpp
Ewan Crawford 90ff791141 Expression evaluation, a new ThreadPlanCallFunctionUsingABI for executing a function call on target via register manipulation
For Hexagon we want to be able to call functions during debugging, however currently lldb only supports this when there is JIT support. 
Although emulation using IR interpretation is an alternative, it is currently limited in that it can't make function calls.

In this patch we have extended the IR interpreter so that it can execute a function call on the target using register manipulation. 
To do this we need to handle the Call IR instruction, passing arguments to a new thread plan and collecting any return values to pass back into the IR interpreter. 

The new thread plan is needed to call an alternative ABI interface of "ABI::PerpareTrivialCall()", allowing more detailed information about arguments and return values.

Reviewers: jingham, spyffe

Subscribers: emaste, lldb-commits, ted, ADodds, deepak2427

Differential Revision: http://reviews.llvm.org/D9404

llvm-svn: 242137
2015-07-14 10:56:58 +00:00

92 lines
3.0 KiB
C++

//===-- ThreadPlanCallFunctionUsingABI.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
//--------------------------------------------------------------------------------------------
// ThreadPlanCallFunctionUsingABI: Plan to call a single function using the ABI instead of JIT
//-------------------------------------------------------------------------------------------
ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI (Thread &thread,
const Address &function,
llvm::Type &prototype,
llvm::Type &return_type,
llvm::ArrayRef<ABI::CallArgument> args,
const EvaluateExpressionOptions &options) :
ThreadPlanCallFunction(thread,function,options),
m_return_type(return_type)
{
lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
ABI *abi = nullptr;
if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr))
return;
if (!abi->PrepareTrivialCall(thread,
m_function_sp,
function_load_addr,
start_load_addr,
prototype,
args))
return;
ReportRegisterState("ABI Function call was set up. Register state was:");
m_valid = true;
}
ThreadPlanCallFunctionUsingABI::~ThreadPlanCallFunctionUsingABI()
{
}
void
ThreadPlanCallFunctionUsingABI::GetDescription(Stream *s, DescriptionLevel level)
{
if (level == eDescriptionLevelBrief)
{
s->Printf("Function call thread plan using ABI instead of JIT");
}
else
{
TargetSP target_sp(m_thread.CalculateTarget());
s->Printf("Thread plan to call 0x%" PRIx64" using ABI instead of JIT", m_function_addr.GetLoadAddress(target_sp.get()));
}
}
void
ThreadPlanCallFunctionUsingABI::SetReturnValue()
{
ProcessSP process_sp(m_thread.GetProcess());
const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
// Ask the abi for the return value
if (abi)
{
const bool persistent = false;
m_return_valobj_sp = abi->GetReturnValueObject(m_thread, m_return_type, persistent);
}
}