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