llvm-project/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp

259 lines
9.9 KiB
C++

//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "InferiorCallPOSIX.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#ifndef LLDB_DISABLE_POSIX
#include <sys/mman.h>
#else
// define them
#define PROT_NONE 0
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#endif
using namespace lldb;
using namespace lldb_private;
bool
lldb_private::InferiorCallMmap (Process *process,
addr_t &allocated_addr,
addr_t addr,
addr_t length,
unsigned prot,
unsigned flags,
addr_t fd,
addr_t offset)
{
Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get();
if (thread == NULL)
return false;
const bool append = true;
const bool include_symbols = true;
const bool include_inlines = false;
SymbolContextList sc_list;
const uint32_t count
= process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
eFunctionNameTypeFull,
include_symbols,
include_inlines,
append,
sc_list);
if (count > 0)
{
SymbolContext sc;
if (sc_list.GetContextAtIndex(0, sc))
{
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
options.SetTrapExceptions(false);
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
prot_arg = PROT_NONE;
else {
prot_arg = 0;
if (prot & eMmapProtExec)
prot_arg |= PROT_EXEC;
if (prot & eMmapProtRead)
prot_arg |= PROT_READ;
if (prot & eMmapProtWrite)
prot_arg |= PROT_WRITE;
}
const ArchSpec arch = process->GetTarget().GetArchitecture();
flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags);
AddressRange mmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
{
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
clang_void_ptr_type, args, options));
if (call_plan_sp)
{
DiagnosticManager diagnostics;
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame)
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
if (result == eExpressionCompleted)
{
allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
if (process->GetAddressByteSize() == 4)
{
if (allocated_addr == UINT32_MAX)
return false;
}
else if (process->GetAddressByteSize() == 8)
{
if (allocated_addr == UINT64_MAX)
return false;
}
return true;
}
}
}
}
}
}
return false;
}
bool
lldb_private::InferiorCallMunmap (Process *process,
addr_t addr,
addr_t length)
{
Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get();
if (thread == NULL)
return false;
const bool append = true;
const bool include_symbols = true;
const bool include_inlines = false;
SymbolContextList sc_list;
const uint32_t count
= process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
eFunctionNameTypeFull,
include_symbols,
include_inlines,
append,
sc_list);
if (count > 0)
{
SymbolContext sc;
if (sc_list.GetContextAtIndex(0, sc))
{
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
options.SetTrapExceptions(false);
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
{
lldb::addr_t args[] = { addr, length };
lldb::ThreadPlanSP call_plan_sp(
new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options));
if (call_plan_sp)
{
DiagnosticManager diagnostics;
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame)
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
if (result == eExpressionCompleted)
{
return true;
}
}
}
}
}
}
return false;
}
// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a
// function of the form "void * (*)(void)". We should find a better place to put this.
bool
lldb_private::InferiorCall (Process *process,
const Address *address,
addr_t &returned_func,
bool trap_exceptions)
{
Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get();
if (thread == NULL || address == NULL)
return false;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
options.SetTrapExceptions(trap_exceptions);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::ThreadPlanSP call_plan_sp(
new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, llvm::ArrayRef<addr_t>(), options));
if (call_plan_sp)
{
DiagnosticManager diagnostics;
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame)
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
if (result == eExpressionCompleted)
{
returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
if (process->GetAddressByteSize() == 4)
{
if (returned_func == UINT32_MAX)
return false;
}
else if (process->GetAddressByteSize() == 8)
{
if (returned_func == UINT64_MAX)
return false;
}
return true;
}
}
}
return false;
}