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.SetTimeout(std::chrono::milliseconds(500)); 65 options.SetTrapExceptions(false); 66 67 addr_t prot_arg; 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 AddressRange mmap_range; 81 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, 82 mmap_range)) { 83 ClangASTContext *clang_ast_context = 84 process->GetTarget().GetScratchClangASTContext(); 85 CompilerType clang_void_ptr_type = 86 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 87 const ArchSpec arch = process->GetTarget().GetArchitecture(); 88 MmapArgList args = 89 process->GetTarget().GetPlatform()->GetMmapArgumentList( 90 arch, addr, length, prot_arg, flags, fd, offset); 91 lldb::ThreadPlanSP call_plan_sp( 92 new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), 93 clang_void_ptr_type, args, options)); 94 if (call_plan_sp) { 95 DiagnosticManager diagnostics; 96 97 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 98 if (frame) { 99 ExecutionContext exe_ctx; 100 frame->CalculateExecutionContext(exe_ctx); 101 ExpressionResults result = process->RunThreadPlan( 102 exe_ctx, call_plan_sp, options, diagnostics); 103 if (result == eExpressionCompleted) { 104 105 allocated_addr = 106 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( 107 LLDB_INVALID_ADDRESS); 108 if (process->GetAddressByteSize() == 4) { 109 if (allocated_addr == UINT32_MAX) 110 return false; 111 } else if (process->GetAddressByteSize() == 8) { 112 if (allocated_addr == UINT64_MAX) 113 return false; 114 } 115 return true; 116 } 117 } 118 } 119 } 120 } 121 } 122 123 return false; 124 } 125 126 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, 127 addr_t length) { 128 Thread *thread = 129 process->GetThreadList().GetExpressionExecutionThread().get(); 130 if (thread == NULL) 131 return false; 132 133 const bool append = true; 134 const bool include_symbols = true; 135 const bool include_inlines = false; 136 SymbolContextList sc_list; 137 const uint32_t count = process->GetTarget().GetImages().FindFunctions( 138 ConstString("munmap"), eFunctionNameTypeFull, include_symbols, 139 include_inlines, append, sc_list); 140 if (count > 0) { 141 SymbolContext sc; 142 if (sc_list.GetContextAtIndex(0, sc)) { 143 const uint32_t range_scope = 144 eSymbolContextFunction | eSymbolContextSymbol; 145 const bool use_inline_block_range = false; 146 EvaluateExpressionOptions options; 147 options.SetStopOthers(true); 148 options.SetUnwindOnError(true); 149 options.SetIgnoreBreakpoints(true); 150 options.SetTryAllThreads(true); 151 options.SetDebug(false); 152 options.SetTimeout(std::chrono::milliseconds(500)); 153 options.SetTrapExceptions(false); 154 155 AddressRange munmap_range; 156 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, 157 munmap_range)) { 158 lldb::addr_t args[] = {addr, length}; 159 lldb::ThreadPlanSP call_plan_sp( 160 new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), 161 CompilerType(), args, options)); 162 if (call_plan_sp) { 163 DiagnosticManager diagnostics; 164 165 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 166 if (frame) { 167 ExecutionContext exe_ctx; 168 frame->CalculateExecutionContext(exe_ctx); 169 ExpressionResults result = process->RunThreadPlan( 170 exe_ctx, call_plan_sp, options, diagnostics); 171 if (result == eExpressionCompleted) { 172 return true; 173 } 174 } 175 } 176 } 177 } 178 } 179 180 return false; 181 } 182 183 // FIXME: This has nothing to do with Posix, it is just a convenience function 184 // that calls a 185 // function of the form "void * (*)(void)". We should find a better place to 186 // put this. 187 188 bool lldb_private::InferiorCall(Process *process, const Address *address, 189 addr_t &returned_func, bool trap_exceptions) { 190 Thread *thread = 191 process->GetThreadList().GetExpressionExecutionThread().get(); 192 if (thread == NULL || address == NULL) 193 return false; 194 195 EvaluateExpressionOptions options; 196 options.SetStopOthers(true); 197 options.SetUnwindOnError(true); 198 options.SetIgnoreBreakpoints(true); 199 options.SetTryAllThreads(true); 200 options.SetDebug(false); 201 options.SetTimeout(std::chrono::milliseconds(500)); 202 options.SetTrapExceptions(trap_exceptions); 203 204 ClangASTContext *clang_ast_context = 205 process->GetTarget().GetScratchClangASTContext(); 206 CompilerType clang_void_ptr_type = 207 clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 208 lldb::ThreadPlanSP call_plan_sp( 209 new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, 210 llvm::ArrayRef<addr_t>(), options)); 211 if (call_plan_sp) { 212 DiagnosticManager diagnostics; 213 214 StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); 215 if (frame) { 216 ExecutionContext exe_ctx; 217 frame->CalculateExecutionContext(exe_ctx); 218 ExpressionResults result = 219 process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); 220 if (result == eExpressionCompleted) { 221 returned_func = 222 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned( 223 LLDB_INVALID_ADDRESS); 224 225 if (process->GetAddressByteSize() == 4) { 226 if (returned_func == UINT32_MAX) 227 return false; 228 } else if (process->GetAddressByteSize() == 8) { 229 if (returned_func == UINT64_MAX) 230 return false; 231 } 232 return true; 233 } 234 } 235 } 236 237 return false; 238 } 239