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 const ArchSpec arch = process->GetTarget().GetArchitecture(); 90 flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags); 91 92 AddressRange mmap_range; 93 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 94 { 95 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 96 CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 97 lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; 98 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 99 mmap_range.GetBaseAddress(), 100 clang_void_ptr_type, 101 args, 102 options)); 103 if (call_plan_sp) 104 { 105 StreamFile error_strm; 106 // This plan is a utility plan, so set it to discard itself when done. 107 call_plan_sp->SetIsMasterPlan (true); 108 call_plan_sp->SetOkayToDiscard(true); 109 110 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 111 if (frame) 112 { 113 ExecutionContext exe_ctx; 114 frame->CalculateExecutionContext (exe_ctx); 115 ExpressionResults result = process->RunThreadPlan (exe_ctx, 116 call_plan_sp, 117 options, 118 error_strm); 119 if (result == eExpressionCompleted) 120 { 121 122 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 123 if (process->GetAddressByteSize() == 4) 124 { 125 if (allocated_addr == UINT32_MAX) 126 return false; 127 } 128 else if (process->GetAddressByteSize() == 8) 129 { 130 if (allocated_addr == UINT64_MAX) 131 return false; 132 } 133 return true; 134 } 135 } 136 } 137 } 138 } 139 } 140 141 return false; 142 } 143 144 bool 145 lldb_private::InferiorCallMunmap (Process *process, 146 addr_t addr, 147 addr_t length) 148 { 149 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 150 if (thread == NULL) 151 return false; 152 153 const bool append = true; 154 const bool include_symbols = true; 155 const bool include_inlines = false; 156 SymbolContextList sc_list; 157 const uint32_t count 158 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 159 eFunctionNameTypeFull, 160 include_symbols, 161 include_inlines, 162 append, 163 sc_list); 164 if (count > 0) 165 { 166 SymbolContext sc; 167 if (sc_list.GetContextAtIndex(0, sc)) 168 { 169 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 170 const bool use_inline_block_range = false; 171 EvaluateExpressionOptions options; 172 options.SetStopOthers(true); 173 options.SetUnwindOnError(true); 174 options.SetIgnoreBreakpoints(true); 175 options.SetTryAllThreads(true); 176 options.SetDebug (false); 177 options.SetTimeoutUsec(500000); 178 179 AddressRange munmap_range; 180 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) 181 { 182 lldb::addr_t args[] = { addr, length }; 183 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 184 munmap_range.GetBaseAddress(), 185 CompilerType(), 186 args, 187 options)); 188 if (call_plan_sp) 189 { 190 StreamFile error_strm; 191 // This plan is a utility plan, so set it to discard itself when done. 192 call_plan_sp->SetIsMasterPlan (true); 193 call_plan_sp->SetOkayToDiscard(true); 194 195 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 196 if (frame) 197 { 198 ExecutionContext exe_ctx; 199 frame->CalculateExecutionContext (exe_ctx); 200 ExpressionResults result = process->RunThreadPlan (exe_ctx, 201 call_plan_sp, 202 options, 203 error_strm); 204 if (result == eExpressionCompleted) 205 { 206 return true; 207 } 208 } 209 } 210 } 211 } 212 } 213 214 return false; 215 } 216 217 // FIXME: This has nothing to do with Posix, it is just a convenience function that calls a 218 // function of the form "void * (*)(void)". We should find a better place to put this. 219 220 bool 221 lldb_private::InferiorCall (Process *process, 222 const Address *address, 223 addr_t &returned_func) 224 { 225 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 226 if (thread == NULL || address == NULL) 227 return false; 228 229 EvaluateExpressionOptions options; 230 options.SetStopOthers(true); 231 options.SetUnwindOnError(true); 232 options.SetIgnoreBreakpoints(true); 233 options.SetTryAllThreads(true); 234 options.SetDebug (false); 235 options.SetTimeoutUsec(500000); 236 237 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 238 CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 239 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 240 *address, 241 clang_void_ptr_type, 242 llvm::ArrayRef<addr_t>(), 243 options)); 244 if (call_plan_sp) 245 { 246 StreamString error_strm; 247 // This plan is a utility plan, so set it to discard itself when done. 248 call_plan_sp->SetIsMasterPlan (true); 249 call_plan_sp->SetOkayToDiscard(true); 250 251 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 252 if (frame) 253 { 254 ExecutionContext exe_ctx; 255 frame->CalculateExecutionContext (exe_ctx); 256 ExpressionResults result = process->RunThreadPlan (exe_ctx, 257 call_plan_sp, 258 options, 259 error_strm); 260 if (result == eExpressionCompleted) 261 { 262 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 263 264 if (process->GetAddressByteSize() == 4) 265 { 266 if (returned_func == UINT32_MAX) 267 return false; 268 } 269 else if (process->GetAddressByteSize() == 8) 270 { 271 if (returned_func == UINT64_MAX) 272 return false; 273 } 274 return true; 275 } 276 } 277 } 278 279 return false; 280 } 281