Skip to content

Commit

Permalink
Expression evaluation, a new ThreadPlanCallFunctionUsingABI for execu…
Browse files Browse the repository at this point in the history
…ting 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
  • Loading branch information
EwanC committed Jul 14, 2015
1 parent 469609a commit 90ff791
Show file tree
Hide file tree
Showing 20 changed files with 636 additions and 53 deletions.
6 changes: 4 additions & 2 deletions lldb/include/lldb/Expression/IRInterpreter.h
Expand Up @@ -44,7 +44,8 @@ class IRInterpreter
static bool
CanInterpret (llvm::Module &module,
llvm::Function &function,
lldb_private::Error &error);
lldb_private::Error &error,
const bool support_function_calls);

static bool
Interpret (llvm::Module &module,
Expand All @@ -53,7 +54,8 @@ class IRInterpreter
lldb_private::IRMemoryMap &memory_map,
lldb_private::Error &error,
lldb::addr_t stack_frame_bottom,
lldb::addr_t stack_frame_top);
lldb::addr_t stack_frame_top,
lldb_private::ExecutionContext &exe_ctx);

private:
static bool
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Expression/IRMemoryMap.h
Expand Up @@ -60,7 +60,7 @@ class IRMemoryMap
void ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error);
void ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error);
void ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error);

bool GetAllocSize(lldb::addr_t address, size_t &size);
void GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error);

lldb::ByteOrder GetByteOrder();
Expand Down
9 changes: 4 additions & 5 deletions lldb/include/lldb/Target/ABI.h
Expand Up @@ -39,10 +39,9 @@ class ABI :
};
eType type; /* value of eType */
size_t size; /* size in bytes of this argument */
union {
lldb::addr_t value; /* literal value */
uint8_t *data; /* host data pointer */
};

lldb::addr_t value; /* literal value */
std::unique_ptr<uint8_t[]> data_ap; /* host data pointer */
};

virtual
Expand All @@ -58,7 +57,7 @@ class ABI :
lldb::addr_t returnAddress,
llvm::ArrayRef<lldb::addr_t> args) const = 0;

// Prepare trivial call used from ThreadPlanFunctionCallGDB
// Prepare trivial call used from ThreadPlanFunctionCallUsingABI
// AD:
// . Because i don't want to change other ABI's this is not declared pure virtual.
// The dummy implementation will simply fail. Only HexagonABI will currently
Expand Down
34 changes: 34 additions & 0 deletions lldb/include/lldb/Target/Process.h
Expand Up @@ -2471,7 +2471,40 @@ class Process :
/// True if execution of JIT code is possible; false otherwise.
//------------------------------------------------------------------
void SetCanJIT (bool can_jit);

//------------------------------------------------------------------
/// Determines whether executing function calls using the interpreter
/// is possible for this process.
///
/// @return
/// True if possible; false otherwise.
//------------------------------------------------------------------
bool CanInterpretFunctionCalls ()
{
return m_can_interpret_function_calls;
}

//------------------------------------------------------------------
/// Sets whether executing function calls using the interpreter
/// is possible for this process.
///
/// @param[in] can_interpret_function_calls
/// True if possible; false otherwise.
//------------------------------------------------------------------
void SetCanInterpretFunctionCalls (bool can_interpret_function_calls)
{
m_can_interpret_function_calls = can_interpret_function_calls;
}

//------------------------------------------------------------------
/// Sets whether executing code in this process is possible.
/// This could be either through JIT or interpreting.
///
/// @param[in] can_run_code
/// True if execution of code is possible; false otherwise.
//------------------------------------------------------------------
void SetCanRunCode (bool can_run_code);

//------------------------------------------------------------------
/// Actually deallocate memory in the process.
///
Expand Down Expand Up @@ -3268,6 +3301,7 @@ class Process :
lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent.
std::map<lldb::addr_t,lldb::addr_t> m_resolved_indirect_addresses;
bool m_destroy_in_process;
bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, don't support the ability to modify the stack.

enum {
eCanJITDontKnow= 0,
Expand Down
12 changes: 9 additions & 3 deletions lldb/include/lldb/Target/ThreadPlanCallFunction.h
Expand Up @@ -34,6 +34,10 @@ class ThreadPlanCallFunction : public ThreadPlan
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options);

ThreadPlanCallFunction(Thread &thread,
const Address &function,
const EvaluateExpressionOptions &options);

virtual
~ThreadPlanCallFunction ();

Expand Down Expand Up @@ -134,7 +138,8 @@ class ThreadPlanCallFunction : public ThreadPlan
virtual bool
DoPlanExplainsStop (Event *event_ptr);

private:
virtual void
SetReturnValue();

bool
ConstructorSetup (Thread &thread,
Expand All @@ -153,7 +158,7 @@ class ThreadPlanCallFunction : public ThreadPlan

bool
BreakpointsExplainStop ();

bool m_valid;
bool m_stop_other_threads;
bool m_unwind_on_error;
Expand All @@ -172,13 +177,14 @@ class ThreadPlanCallFunction : public ThreadPlan
// it's nice to know the real stop reason.
// This gets set in DoTakedown.
StreamString m_constructor_errors;
ClangASTType m_return_type;
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
bool m_should_clear_objc_exception_bp;
bool m_should_clear_cxx_exception_bp;
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;

private:
ClangASTType m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};

Expand Down
58 changes: 58 additions & 0 deletions lldb/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
@@ -0,0 +1,58 @@
//===-- ThreadPlanCallFunctionUsingABI.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ThreadPlanCallFunctionUsingABI_h_
#define liblldb_ThreadPlanCallFunctionUsingABI_h_

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanCallFunction.h"

#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Type.h"

namespace lldb_private {

class ThreadPlanCallFunctionUsingABI : public ThreadPlanCallFunction
{
// Create a thread plan to call a function at the address passed in the "function"
// argument, this function is executed using register manipulation instead of JIT.
// Class derives from ThreadPlanCallFunction and differs by calling a alternative
// ABI interface ABI::PrepareTrivialCall() which provides more detailed information.
public:
ThreadPlanCallFunctionUsingABI (Thread &thread,
const Address &function_address,
llvm::Type &function_prototype,
llvm::Type &return_type,
llvm::ArrayRef<ABI::CallArgument> args,
const EvaluateExpressionOptions &options);

~ThreadPlanCallFunctionUsingABI ();

void
GetDescription (Stream *s, lldb::DescriptionLevel level) override;

protected:
void
SetReturnValue () override;


private:
llvm::Type &m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunctionUsingABI);
};

} // namespace lldb_private

#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_
5 changes: 5 additions & 0 deletions lldb/lldb.xcodeproj/project.pbxproj
Expand Up @@ -2689,6 +2689,8 @@
E7723D4B1AC4A944002BA082 /* RegisterContextPOSIX_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_arm64.h; path = Utility/RegisterContextPOSIX_arm64.h; sourceTree = "<group>"; };
E778E99F1B062D1700247609 /* EmulateInstructionMIPS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionMIPS.cpp; sourceTree = "<group>"; };
E778E9A01B062D1700247609 /* EmulateInstructionMIPS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionMIPS.h; sourceTree = "<group>"; };
EBDD01241B39B62F00E04792 /* ThreadPlanCallFunctionUsingABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunctionUsingABI.cpp; path = source/Target/ThreadPlanCallFunctionUsingABI.cpp; sourceTree = "<group>"; };
EBDD01261B39B66700E04792 /* ThreadPlanCallFunctionUsingABI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallFunctionUsingABI.h; path = include/lldb/Target/ThreadPlanCallFunctionUsingABI.h; sourceTree = "<group>"; };
ED88244F15114CA200BC98B9 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
ED88245215114CFC00BC98B9 /* LauncherRootXPCService.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LauncherRootXPCService.mm; sourceTree = "<group>"; };
EDB919B214F6EC85008FF64B /* LauncherXPCService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LauncherXPCService.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4522,6 +4524,8 @@
26BC7DEF10F1B80200F91463 /* Target */ = {
isa = PBXGroup;
children = (
EBDD01261B39B66700E04792 /* ThreadPlanCallFunctionUsingABI.h */,
EBDD01241B39B62F00E04792 /* ThreadPlanCallFunctionUsingABI.cpp */,
8CF02AE019DCBF3B00B14BE0 /* InstrumentationRuntime.h */,
8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */,
8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */,
Expand Down Expand Up @@ -6315,6 +6319,7 @@
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */,
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */,
264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */,
EBDD01251B39B62F00E04792 /* ThreadPlanCallFunctionUsingABI.cpp in Sources */,
2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */,
26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */,
3FDFED0B19B7C8DE009756A7 /* HostThreadMacOSX.mm in Sources */,
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Expression/ClangExpressionParser.cpp
Expand Up @@ -541,10 +541,11 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());

Error interpret_error;
Process *process = exe_ctx.GetProcessPtr();

can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);
bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);

Process *process = exe_ctx.GetProcessPtr();

if (!ir_can_run)
{
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Expression/ClangUserExpression.cpp
Expand Up @@ -891,7 +891,8 @@ ClangUserExpression::Execute (Stream &error_stream,
*m_execution_unit_sp.get(),
interpreter_error,
function_stack_bottom,
function_stack_top);
function_stack_top,
exe_ctx);

if (!interpreter_error.Success())
{
Expand Down

0 comments on commit 90ff791

Please sign in to comment.