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 34 using namespace lldb; 35 using namespace lldb_private; 36 37 bool 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 EvaluateExpressionOptions options; 63 options.SetStopOthers(true); 64 options.SetUnwindOnError(true); 65 options.SetIgnoreBreakpoints(true); 66 options.SetTryAllThreads(true); 67 options.SetDebug (false); 68 options.SetTimeoutUsec(500000); 69 70 addr_t prot_arg, flags_arg = 0; 71 if (prot == eMmapProtNone) 72 prot_arg = PROT_NONE; 73 else { 74 prot_arg = 0; 75 if (prot & eMmapProtExec) 76 prot_arg |= PROT_EXEC; 77 if (prot & eMmapProtRead) 78 prot_arg |= PROT_READ; 79 if (prot & eMmapProtWrite) 80 prot_arg |= PROT_WRITE; 81 } 82 83 if (flags & eMmapFlagsPrivate) 84 flags_arg |= MAP_PRIVATE; 85 if (flags & eMmapFlagsAnon) 86 flags_arg |= MAP_ANON; 87 88 AddressRange mmap_range; 89 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 90 { 91 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 92 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 93 ThreadPlanCallFunction *call_function_thread_plan 94 = new ThreadPlanCallFunction (*thread, 95 mmap_range.GetBaseAddress(), 96 clang_void_ptr_type, 97 options, 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 options, 120 error_strm); 121 if (result == eExecutionCompleted) 122 { 123 124 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 125 if (process->GetAddressByteSize() == 4) 126 { 127 if (allocated_addr == UINT32_MAX) 128 return false; 129 } 130 else if (process->GetAddressByteSize() == 8) 131 { 132 if (allocated_addr == UINT64_MAX) 133 return false; 134 } 135 return true; 136 } 137 } 138 } 139 } 140 } 141 } 142 143 return false; 144 } 145 146 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, 147 addr_t length) { 148 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 149 if (thread == NULL) 150 return false; 151 152 const bool append = true; 153 const bool include_symbols = true; 154 const bool include_inlines = false; 155 SymbolContextList sc_list; 156 const uint32_t count 157 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 158 eFunctionNameTypeFull, 159 include_symbols, 160 include_inlines, 161 append, 162 sc_list); 163 if (count > 0) 164 { 165 SymbolContext sc; 166 if (sc_list.GetContextAtIndex(0, sc)) 167 { 168 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 169 const bool use_inline_block_range = false; 170 EvaluateExpressionOptions options; 171 options.SetStopOthers(true); 172 options.SetUnwindOnError(true); 173 options.SetIgnoreBreakpoints(true); 174 options.SetTryAllThreads(true); 175 options.SetDebug (false); 176 options.SetTimeoutUsec(500000); 177 178 AddressRange munmap_range; 179 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) 180 { 181 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 182 munmap_range.GetBaseAddress(), 183 ClangASTType(), 184 options, 185 &addr, 186 &length)); 187 if (call_plan_sp) 188 { 189 StreamFile error_strm; 190 // This plan is a utility plan, so set it to discard itself when done. 191 call_plan_sp->SetIsMasterPlan (true); 192 call_plan_sp->SetOkayToDiscard(true); 193 194 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 195 if (frame) 196 { 197 ExecutionContext exe_ctx; 198 frame->CalculateExecutionContext (exe_ctx); 199 ExecutionResults result = process->RunThreadPlan (exe_ctx, 200 call_plan_sp, 201 options, 202 error_strm); 203 if (result == eExecutionCompleted) 204 { 205 return true; 206 } 207 } 208 } 209 } 210 } 211 } 212 213 return false; 214 } 215 216 bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) { 217 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 218 if (thread == NULL || address == NULL) 219 return false; 220 221 EvaluateExpressionOptions options; 222 options.SetStopOthers(true); 223 options.SetUnwindOnError(true); 224 options.SetIgnoreBreakpoints(true); 225 options.SetTryAllThreads(true); 226 options.SetDebug (false); 227 options.SetTimeoutUsec(500000); 228 229 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 230 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 231 ThreadPlanCallFunction *call_function_thread_plan 232 = new ThreadPlanCallFunction (*thread, 233 *address, 234 clang_void_ptr_type, 235 options); 236 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 237 if (call_plan_sp) 238 { 239 StreamFile error_strm; 240 // This plan is a utility plan, so set it to discard itself when done. 241 call_plan_sp->SetIsMasterPlan (true); 242 call_plan_sp->SetOkayToDiscard(true); 243 244 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 245 if (frame) 246 { 247 ExecutionContext exe_ctx; 248 frame->CalculateExecutionContext (exe_ctx); 249 ExecutionResults result = process->RunThreadPlan (exe_ctx, 250 call_plan_sp, 251 options, 252 error_strm); 253 if (result == eExecutionCompleted) 254 { 255 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 256 257 if (process->GetAddressByteSize() == 4) 258 { 259 if (returned_func == UINT32_MAX) 260 return false; 261 } 262 else if (process->GetAddressByteSize() == 8) 263 { 264 if (returned_func == UINT64_MAX) 265 return false; 266 } 267 return true; 268 } 269 } 270 } 271 272 return false; 273 } 274