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/Expression/DiagnosticManager.h" 15 #include "lldb/Host/Config.h" 16 #include "lldb/Symbol/ClangASTContext.h" 17 #include "lldb/Symbol/SymbolContext.h" 18 #include "lldb/Target/ExecutionContext.h" 19 #include "lldb/Target/Platform.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Target/ThreadPlanCallFunction.h" 23 24 #ifndef LLDB_DISABLE_POSIX 25 #include <sys/mman.h> 26 #else 27 // define them 28 #define PROT_NONE 0 29 #define PROT_READ 1 30 #define PROT_WRITE 2 31 #define PROT_EXEC 4 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 = 41 process->GetThreadList().GetExpressionExecutionThread().get(); 42 if (thread == NULL) 43 return false; 44 45 const bool append = true; 46 const bool include_symbols = true; 47 const bool include_inlines = false; 48 SymbolContextList sc_list; 49 const uint32_t count = process->GetTarget().GetImages().FindFunctions( 50 ConstString("mmap"), eFunctionNameTypeFull, include_symbols, 51 include_inlines, append, sc_list); 52 if (count > 0) { 53 SymbolContext sc; 54 if (sc_list.GetContextAtIndex(0, sc)) { 55 const uint32_t range_scope = 56 eSymbolContextFunction | eSymbolContextSymbol; 57 const bool use_inline_block_range = false; 58 EvaluateExpressionOptions options; 59 options.SetStopOthers(true); 60 options.SetUnwindOnError(true); 61 options.SetIgnoreBreakpoints(true); 62 options.SetTryAllThreads(true); 63 options.SetDebug(false); 64 options.SetTimeoutUsec(500000); 65 options.SetTrapExceptions(false); 66 67 addr_t prot_arg, flags_arg = 0; 68 if (prot == eMmapProtNone) 69 prot_arg = PROT_NONE; 70 else { 71 prot_arg = 0; 72 if (prot & eMmapProtExec) 73 prot_arg |= PROT_EXEC; 74 if (prot & eMmapProtRead) 75 prot_arg |= PROT_READ; 76 if (prot & eMmapProtWrite) 77 prot_arg |= PROT_WRITE; 78 } 79 80 const ArchSpec arch = process->GetTarget().GetArchitecture(); 81 flags_arg = 82 process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch, 83 flags); 84 85 AddressRange mmap_range; 86 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, 87 mmap_range)) { 88 ClangASTContext *clang_ast_context = 89 process->GetTarget().GetScratchClangASTContext(); 90 CompilerType clang_void_ptr_type = 91 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 92 lldb::addr_t args[] = {addr, length, prot_arg, flags_arg, fd, offset}; 93 lldb::ThreadPlanSP call_plan_sp( 94 new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), 95 clang_void_ptr_type, args, options)); 96 if (call_plan_sp) { 97 DiagnosticManager diagnostics; 98 99 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 100 if (frame) { 101 ExecutionContext exe_ctx; 102 frame->CalculateExecutionContext(exe_ctx); 103 ExpressionResults result = process->RunThreadPlan( 104 exe_ctx, call_plan_sp, options, diagnostics); 105 if (result == eExpressionCompleted) { 106 107 allocated_addr = 108 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( 109 LLDB_INVALID_ADDRESS); 110 if (process->GetAddressByteSize() == 4) { 111 if (allocated_addr == UINT32_MAX) 112 return false; 113 } else if (process->GetAddressByteSize() == 8) { 114 if (allocated_addr == UINT64_MAX) 115 return false; 116 } 117 return true; 118 } 119 } 120 } 121 } 122 } 123 } 124 125 return false; 126 } 127 128 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, 129 addr_t length) { 130 Thread *thread = 131 process->GetThreadList().GetExpressionExecutionThread().get(); 132 if (thread == NULL) 133 return false; 134 135 const bool append = true; 136 const bool include_symbols = true; 137 const bool include_inlines = false; 138 SymbolContextList sc_list; 139 const uint32_t count = process->GetTarget().GetImages().FindFunctions( 140 ConstString("munmap"), eFunctionNameTypeFull, include_symbols, 141 include_inlines, append, sc_list); 142 if (count > 0) { 143 SymbolContext sc; 144 if (sc_list.GetContextAtIndex(0, sc)) { 145 const uint32_t range_scope = 146 eSymbolContextFunction | eSymbolContextSymbol; 147 const bool use_inline_block_range = false; 148 EvaluateExpressionOptions options; 149 options.SetStopOthers(true); 150 options.SetUnwindOnError(true); 151 options.SetIgnoreBreakpoints(true); 152 options.SetTryAllThreads(true); 153 options.SetDebug(false); 154 options.SetTimeoutUsec(500000); 155 options.SetTrapExceptions(false); 156 157 AddressRange munmap_range; 158 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, 159 munmap_range)) { 160 lldb::addr_t args[] = {addr, length}; 161 lldb::ThreadPlanSP call_plan_sp( 162 new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), 163 CompilerType(), args, options)); 164 if (call_plan_sp) { 165 DiagnosticManager diagnostics; 166 167 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 168 if (frame) { 169 ExecutionContext exe_ctx; 170 frame->CalculateExecutionContext(exe_ctx); 171 ExpressionResults result = process->RunThreadPlan( 172 exe_ctx, call_plan_sp, options, diagnostics); 173 if (result == eExpressionCompleted) { 174 return true; 175 } 176 } 177 } 178 } 179 } 180 } 181 182 return false; 183 } 184 185 // FIXME: This has nothing to do with Posix, it is just a convenience function 186 // that calls a 187 // function of the form "void * (*)(void)". We should find a better place to 188 // put this. 189 190 bool lldb_private::InferiorCall(Process *process, const Address *address, 191 addr_t &returned_func, bool trap_exceptions) { 192 Thread *thread = 193 process->GetThreadList().GetExpressionExecutionThread().get(); 194 if (thread == NULL || address == NULL) 195 return false; 196 197 EvaluateExpressionOptions options; 198 options.SetStopOthers(true); 199 options.SetUnwindOnError(true); 200 options.SetIgnoreBreakpoints(true); 201 options.SetTryAllThreads(true); 202 options.SetDebug(false); 203 options.SetTimeoutUsec(500000); 204 options.SetTrapExceptions(trap_exceptions); 205 206 ClangASTContext *clang_ast_context = 207 process->GetTarget().GetScratchClangASTContext(); 208 CompilerType clang_void_ptr_type = 209 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 210 lldb::ThreadPlanSP call_plan_sp( 211 new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, 212 llvm::ArrayRef<addr_t>(), options)); 213 if (call_plan_sp) { 214 DiagnosticManager diagnostics; 215 216 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 217 if (frame) { 218 ExecutionContext exe_ctx; 219 frame->CalculateExecutionContext(exe_ctx); 220 ExpressionResults result = 221 process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); 222 if (result == eExpressionCompleted) { 223 returned_func = 224 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( 225 LLDB_INVALID_ADDRESS); 226 227 if (process->GetAddressByteSize() == 4) { 228 if (returned_func == UINT32_MAX) 229 return false; 230 } else if (process->GetAddressByteSize() == 8) { 231 if (returned_func == UINT64_MAX) 232 return false; 233 } 234 return true; 235 } 236 } 237 } 238 239 return false; 240 } 241