InferiorCallPOSIX.cpp revision 269024
1//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "InferiorCallPOSIX.h" 11#include "lldb/Core/Address.h" 12#include "lldb/Core/StreamFile.h" 13#include "lldb/Core/ValueObject.h" 14#include "lldb/Symbol/ClangASTContext.h" 15#include "lldb/Symbol/SymbolContext.h" 16#include "lldb/Target/ExecutionContext.h" 17#include "lldb/Target/Process.h" 18#include "lldb/Target/Target.h" 19#include "lldb/Target/ThreadPlanCallFunction.h" 20#include "lldb/Host/Config.h" 21 22#ifndef LLDB_DISABLE_POSIX 23#include <sys/mman.h> 24#else 25// define them 26#define PROT_NONE 0 27#define PROT_READ 1 28#define PROT_WRITE 2 29#define PROT_EXEC 4 30#define MAP_PRIVATE 2 31#define MAP_ANON 0x1000 32#endif 33 34using namespace lldb; 35using namespace lldb_private; 36 37bool 38lldb_private::InferiorCallMmap (Process *process, 39 addr_t &allocated_addr, 40 addr_t addr, 41 addr_t length, 42 unsigned prot, 43 unsigned flags, 44 addr_t fd, 45 addr_t offset) 46{ 47 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 48 if (thread == NULL) 49 return false; 50 51 const bool append = true; 52 const bool include_symbols = true; 53 const bool include_inlines = false; 54 SymbolContextList sc_list; 55 const uint32_t count 56 = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 57 eFunctionNameTypeFull, 58 include_symbols, 59 include_inlines, 60 append, 61 sc_list); 62 if (count > 0) 63 { 64 SymbolContext sc; 65 if (sc_list.GetContextAtIndex(0, sc)) 66 { 67 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 68 const bool use_inline_block_range = false; 69 EvaluateExpressionOptions options; 70 options.SetStopOthers(true); 71 options.SetUnwindOnError(true); 72 options.SetIgnoreBreakpoints(true); 73 options.SetTryAllThreads(true); 74 options.SetDebug (false); 75 options.SetTimeoutUsec(500000); 76 77 addr_t prot_arg, flags_arg = 0; 78 if (prot == eMmapProtNone) 79 prot_arg = PROT_NONE; 80 else { 81 prot_arg = 0; 82 if (prot & eMmapProtExec) 83 prot_arg |= PROT_EXEC; 84 if (prot & eMmapProtRead) 85 prot_arg |= PROT_READ; 86 if (prot & eMmapProtWrite) 87 prot_arg |= PROT_WRITE; 88 } 89 90 if (flags & eMmapFlagsPrivate) 91 flags_arg |= MAP_PRIVATE; 92 if (flags & eMmapFlagsAnon) 93 flags_arg |= MAP_ANON; 94 95 AddressRange mmap_range; 96 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 97 { 98 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 99 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 100 lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; 101 ThreadPlanCallFunction *call_function_thread_plan 102 = new ThreadPlanCallFunction (*thread, 103 mmap_range.GetBaseAddress(), 104 clang_void_ptr_type, 105 args, 106 options); 107 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 108 if (call_plan_sp) 109 { 110 StreamFile error_strm; 111 // This plan is a utility plan, so set it to discard itself when done. 112 call_plan_sp->SetIsMasterPlan (true); 113 call_plan_sp->SetOkayToDiscard(true); 114 115 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 116 if (frame) 117 { 118 ExecutionContext exe_ctx; 119 frame->CalculateExecutionContext (exe_ctx); 120 ExecutionResults result = process->RunThreadPlan (exe_ctx, 121 call_plan_sp, 122 options, 123 error_strm); 124 if (result == eExecutionCompleted) 125 { 126 127 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 128 if (process->GetAddressByteSize() == 4) 129 { 130 if (allocated_addr == UINT32_MAX) 131 return false; 132 } 133 else if (process->GetAddressByteSize() == 8) 134 { 135 if (allocated_addr == UINT64_MAX) 136 return false; 137 } 138 return true; 139 } 140 } 141 } 142 } 143 } 144 } 145 146 return false; 147} 148 149bool 150lldb_private::InferiorCallMunmap (Process *process, 151 addr_t addr, 152 addr_t length) 153{ 154 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 155 if (thread == NULL) 156 return false; 157 158 const bool append = true; 159 const bool include_symbols = true; 160 const bool include_inlines = false; 161 SymbolContextList sc_list; 162 const uint32_t count 163 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 164 eFunctionNameTypeFull, 165 include_symbols, 166 include_inlines, 167 append, 168 sc_list); 169 if (count > 0) 170 { 171 SymbolContext sc; 172 if (sc_list.GetContextAtIndex(0, sc)) 173 { 174 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 175 const bool use_inline_block_range = false; 176 EvaluateExpressionOptions options; 177 options.SetStopOthers(true); 178 options.SetUnwindOnError(true); 179 options.SetIgnoreBreakpoints(true); 180 options.SetTryAllThreads(true); 181 options.SetDebug (false); 182 options.SetTimeoutUsec(500000); 183 184 AddressRange munmap_range; 185 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) 186 { 187 lldb::addr_t args[] = { addr, length }; 188 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 189 munmap_range.GetBaseAddress(), 190 ClangASTType(), 191 args, 192 options)); 193 if (call_plan_sp) 194 { 195 StreamFile error_strm; 196 // This plan is a utility plan, so set it to discard itself when done. 197 call_plan_sp->SetIsMasterPlan (true); 198 call_plan_sp->SetOkayToDiscard(true); 199 200 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 201 if (frame) 202 { 203 ExecutionContext exe_ctx; 204 frame->CalculateExecutionContext (exe_ctx); 205 ExecutionResults result = process->RunThreadPlan (exe_ctx, 206 call_plan_sp, 207 options, 208 error_strm); 209 if (result == eExecutionCompleted) 210 { 211 return true; 212 } 213 } 214 } 215 } 216 } 217 } 218 219 return false; 220} 221 222// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a 223// function of the form "void * (*)(void)". We should find a better place to put this. 224 225bool 226lldb_private::InferiorCall (Process *process, 227 const Address *address, 228 addr_t &returned_func) 229{ 230 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 231 if (thread == NULL || address == NULL) 232 return false; 233 234 EvaluateExpressionOptions options; 235 options.SetStopOthers(true); 236 options.SetUnwindOnError(true); 237 options.SetIgnoreBreakpoints(true); 238 options.SetTryAllThreads(true); 239 options.SetDebug (false); 240 options.SetTimeoutUsec(500000); 241 242 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 243 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 244 ThreadPlanCallFunction *call_function_thread_plan 245 = new ThreadPlanCallFunction (*thread, 246 *address, 247 clang_void_ptr_type, 248 llvm::ArrayRef<addr_t>(), 249 options); 250 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 251 if (call_plan_sp) 252 { 253 StreamString error_strm; 254 // This plan is a utility plan, so set it to discard itself when done. 255 call_plan_sp->SetIsMasterPlan (true); 256 call_plan_sp->SetOkayToDiscard(true); 257 258 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 259 if (frame) 260 { 261 ExecutionContext exe_ctx; 262 frame->CalculateExecutionContext (exe_ctx); 263 ExecutionResults result = process->RunThreadPlan (exe_ctx, 264 call_plan_sp, 265 options, 266 error_strm); 267 if (result == eExecutionCompleted) 268 { 269 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 270 271 if (process->GetAddressByteSize() == 4) 272 { 273 if (returned_func == UINT32_MAX) 274 return false; 275 } 276 else if (process->GetAddressByteSize() == 8) 277 { 278 if (returned_func == UINT64_MAX) 279 return false; 280 } 281 return true; 282 } 283 } 284 } 285 286 return false; 287} 288