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