InferiorCallPOSIX.cpp revision 263363
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 lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, 38 addr_t addr, addr_t length, unsigned prot, 39 unsigned flags, addr_t fd, addr_t offset) { 40 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 41 if (thread == NULL) 42 return false; 43 44 const bool append = true; 45 const bool include_symbols = true; 46 const bool include_inlines = false; 47 SymbolContextList sc_list; 48 const uint32_t count 49 = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 50 eFunctionNameTypeFull, 51 include_symbols, 52 include_inlines, 53 append, 54 sc_list); 55 if (count > 0) 56 { 57 SymbolContext sc; 58 if (sc_list.GetContextAtIndex(0, sc)) 59 { 60 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 61 const bool use_inline_block_range = false; 62 const bool stop_other_threads = true; 63 const bool unwind_on_error = true; 64 const bool ignore_breakpoints = true; 65 const bool try_all_threads = true; 66 const uint32_t timeout_usec = 500000; 67 68 addr_t prot_arg, flags_arg = 0; 69 if (prot == eMmapProtNone) 70 prot_arg = PROT_NONE; 71 else { 72 prot_arg = 0; 73 if (prot & eMmapProtExec) 74 prot_arg |= PROT_EXEC; 75 if (prot & eMmapProtRead) 76 prot_arg |= PROT_READ; 77 if (prot & eMmapProtWrite) 78 prot_arg |= PROT_WRITE; 79 } 80 81 if (flags & eMmapFlagsPrivate) 82 flags_arg |= MAP_PRIVATE; 83 if (flags & eMmapFlagsAnon) 84 flags_arg |= MAP_ANON; 85 86 AddressRange mmap_range; 87 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 88 { 89 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 90 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 91 ThreadPlanCallFunction *call_function_thread_plan 92 = new ThreadPlanCallFunction (*thread, 93 mmap_range.GetBaseAddress(), 94 clang_void_ptr_type, 95 stop_other_threads, 96 unwind_on_error, 97 ignore_breakpoints, 98 &addr, 99 &length, 100 &prot_arg, 101 &flags_arg, 102 &fd, 103 &offset); 104 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 105 if (call_plan_sp) 106 { 107 StreamFile error_strm; 108 // This plan is a utility plan, so set it to discard itself when done. 109 call_plan_sp->SetIsMasterPlan (true); 110 call_plan_sp->SetOkayToDiscard(true); 111 112 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 113 if (frame) 114 { 115 ExecutionContext exe_ctx; 116 frame->CalculateExecutionContext (exe_ctx); 117 ExecutionResults result = process->RunThreadPlan (exe_ctx, 118 call_plan_sp, 119 stop_other_threads, 120 try_all_threads, 121 unwind_on_error, 122 ignore_breakpoints, 123 timeout_usec, 124 error_strm); 125 if (result == eExecutionCompleted) 126 { 127 128 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 129 if (process->GetAddressByteSize() == 4) 130 { 131 if (allocated_addr == UINT32_MAX) 132 return false; 133 } 134 else if (process->GetAddressByteSize() == 8) 135 { 136 if (allocated_addr == UINT64_MAX) 137 return false; 138 } 139 return true; 140 } 141 } 142 } 143 } 144 } 145 } 146 147 return false; 148} 149 150bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, 151 addr_t length) { 152 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 153 if (thread == NULL) 154 return false; 155 156 const bool append = true; 157 const bool include_symbols = true; 158 const bool include_inlines = false; 159 SymbolContextList sc_list; 160 const uint32_t count 161 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 162 eFunctionNameTypeFull, 163 include_symbols, 164 include_inlines, 165 append, 166 sc_list); 167 if (count > 0) 168 { 169 SymbolContext sc; 170 if (sc_list.GetContextAtIndex(0, sc)) 171 { 172 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 173 const bool use_inline_block_range = false; 174 const bool stop_other_threads = true; 175 const bool unwind_on_error = true; 176 const bool ignore_breakpoints = true; 177 const bool try_all_threads = true; 178 const uint32_t timeout_usec = 500000; 179 180 AddressRange munmap_range; 181 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) 182 { 183 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 184 munmap_range.GetBaseAddress(), 185 ClangASTType(), 186 stop_other_threads, 187 unwind_on_error, 188 ignore_breakpoints, 189 &addr, 190 &length)); 191 if (call_plan_sp) 192 { 193 StreamFile error_strm; 194 // This plan is a utility plan, so set it to discard itself when done. 195 call_plan_sp->SetIsMasterPlan (true); 196 call_plan_sp->SetOkayToDiscard(true); 197 198 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 199 if (frame) 200 { 201 ExecutionContext exe_ctx; 202 frame->CalculateExecutionContext (exe_ctx); 203 ExecutionResults result = process->RunThreadPlan (exe_ctx, 204 call_plan_sp, 205 stop_other_threads, 206 try_all_threads, 207 unwind_on_error, 208 ignore_breakpoints, 209 timeout_usec, 210 error_strm); 211 if (result == eExecutionCompleted) 212 { 213 return true; 214 } 215 } 216 } 217 } 218 } 219 } 220 221 return false; 222} 223 224bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) { 225 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 226 if (thread == NULL || address == NULL) 227 return false; 228 229 const bool stop_other_threads = true; 230 const bool unwind_on_error = true; 231 const bool ignore_breakpoints = true; 232 const bool try_all_threads = true; 233 const uint32_t timeout_usec = 500000; 234 235 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 236 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 237 ThreadPlanCallFunction *call_function_thread_plan 238 = new ThreadPlanCallFunction (*thread, 239 *address, 240 clang_void_ptr_type, 241 stop_other_threads, 242 unwind_on_error, 243 ignore_breakpoints); 244 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 245 if (call_plan_sp) 246 { 247 StreamFile error_strm; 248 // This plan is a utility plan, so set it to discard itself when done. 249 call_plan_sp->SetIsMasterPlan (true); 250 call_plan_sp->SetOkayToDiscard(true); 251 252 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 253 if (frame) 254 { 255 ExecutionContext exe_ctx; 256 frame->CalculateExecutionContext (exe_ctx); 257 ExecutionResults result = process->RunThreadPlan (exe_ctx, 258 call_plan_sp, 259 stop_other_threads, 260 try_all_threads, 261 unwind_on_error, 262 ignore_breakpoints, 263 timeout_usec, 264 error_strm); 265 if (result == eExecutionCompleted) 266 { 267 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 268 269 if (process->GetAddressByteSize() == 4) 270 { 271 if (returned_func == UINT32_MAX) 272 return false; 273 } 274 else if (process->GetAddressByteSize() == 8) 275 { 276 if (returned_func == UINT64_MAX) 277 return false; 278 } 279 return true; 280 } 281 } 282 } 283 284 return false; 285} 286