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/Platform.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/ThreadPlanCallFunction.h" 21 #include "lldb/Host/Config.h" 22 23 #ifndef LLDB_DISABLE_POSIX 24 #include <sys/mman.h> 25 #else 26 // define them 27 #define PROT_NONE 0 28 #define PROT_READ 1 29 #define PROT_WRITE 2 30 #define PROT_EXEC 4 31 #endif 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 bool 37 lldb_private::InferiorCallMmap (Process *process, 38 addr_t &allocated_addr, 39 addr_t addr, 40 addr_t length, 41 unsigned prot, 42 unsigned flags, 43 addr_t fd, 44 addr_t offset) 45 { 46 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 47 if (thread == NULL) 48 return false; 49 50 const bool append = true; 51 const bool include_symbols = true; 52 const bool include_inlines = false; 53 SymbolContextList sc_list; 54 const uint32_t count 55 = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 56 eFunctionNameTypeFull, 57 include_symbols, 58 include_inlines, 59 append, 60 sc_list); 61 if (count > 0) 62 { 63 SymbolContext sc; 64 if (sc_list.GetContextAtIndex(0, sc)) 65 { 66 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 67 const bool use_inline_block_range = false; 68 EvaluateExpressionOptions options; 69 options.SetStopOthers(true); 70 options.SetUnwindOnError(true); 71 options.SetIgnoreBreakpoints(true); 72 options.SetTryAllThreads(true); 73 options.SetDebug (false); 74 options.SetTimeoutUsec(500000); 75 76 addr_t prot_arg, flags_arg = 0; 77 if (prot == eMmapProtNone) 78 prot_arg = PROT_NONE; 79 else { 80 prot_arg = 0; 81 if (prot & eMmapProtExec) 82 prot_arg |= PROT_EXEC; 83 if (prot & eMmapProtRead) 84 prot_arg |= PROT_READ; 85 if (prot & eMmapProtWrite) 86 prot_arg |= PROT_WRITE; 87 } 88 89 flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(flags); 90 91 AddressRange mmap_range; 92 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 93 { 94 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 95 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 96 lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; 97 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 98 mmap_range.GetBaseAddress(), 99 clang_void_ptr_type, 100 args, 101 options)); 102 if (call_plan_sp) 103 { 104 StreamFile error_strm; 105 // This plan is a utility plan, so set it to discard itself when done. 106 call_plan_sp->SetIsMasterPlan (true); 107 call_plan_sp->SetOkayToDiscard(true); 108 109 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 110 if (frame) 111 { 112 ExecutionContext exe_ctx; 113 frame->CalculateExecutionContext (exe_ctx); 114 ExpressionResults result = process->RunThreadPlan (exe_ctx, 115 call_plan_sp, 116 options, 117 error_strm); 118 if (result == eExpressionCompleted) 119 { 120 121 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 122 if (process->GetAddressByteSize() == 4) 123 { 124 if (allocated_addr == UINT32_MAX) 125 return false; 126 } 127 else if (process->GetAddressByteSize() == 8) 128 { 129 if (allocated_addr == UINT64_MAX) 130 return false; 131 } 132 return true; 133 } 134 } 135 } 136 } 137 } 138 } 139 140 return false; 141 } 142 143 bool 144 lldb_private::InferiorCallMunmap (Process *process, 145 addr_t addr, 146 addr_t length) 147 { 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::addr_t args[] = { addr, length }; 182 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 183 munmap_range.GetBaseAddress(), 184 ClangASTType(), 185 args, 186 options)); 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 ExpressionResults result = process->RunThreadPlan (exe_ctx, 200 call_plan_sp, 201 options, 202 error_strm); 203 if (result == eExpressionCompleted) 204 { 205 return true; 206 } 207 } 208 } 209 } 210 } 211 } 212 213 return false; 214 } 215 216 // FIXME: This has nothing to do with Posix, it is just a convenience function that calls a 217 // function of the form "void * (*)(void)". We should find a better place to put this. 218 219 bool 220 lldb_private::InferiorCall (Process *process, 221 const Address *address, 222 addr_t &returned_func) 223 { 224 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 225 if (thread == NULL || address == NULL) 226 return false; 227 228 EvaluateExpressionOptions options; 229 options.SetStopOthers(true); 230 options.SetUnwindOnError(true); 231 options.SetIgnoreBreakpoints(true); 232 options.SetTryAllThreads(true); 233 options.SetDebug (false); 234 options.SetTimeoutUsec(500000); 235 236 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 237 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 238 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 239 *address, 240 clang_void_ptr_type, 241 llvm::ArrayRef<addr_t>(), 242 options)); 243 if (call_plan_sp) 244 { 245 StreamString error_strm; 246 // This plan is a utility plan, so set it to discard itself when done. 247 call_plan_sp->SetIsMasterPlan (true); 248 call_plan_sp->SetOkayToDiscard(true); 249 250 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 251 if (frame) 252 { 253 ExecutionContext exe_ctx; 254 frame->CalculateExecutionContext (exe_ctx); 255 ExpressionResults result = process->RunThreadPlan (exe_ctx, 256 call_plan_sp, 257 options, 258 error_strm); 259 if (result == eExpressionCompleted) 260 { 261 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 262 263 if (process->GetAddressByteSize() == 4) 264 { 265 if (returned_func == UINT32_MAX) 266 return false; 267 } 268 else if (process->GetAddressByteSize() == 8) 269 { 270 if (returned_func == UINT64_MAX) 271 return false; 272 } 273 return true; 274 } 275 } 276 } 277 278 return false; 279 } 280