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