//===-- 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 #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(), 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; }