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/StreamFile.h" 12 #include "lldb/Core/ValueObject.h" 13 #include "lldb/Symbol/SymbolContext.h" 14 #include "lldb/Target/ExecutionContext.h" 15 #include "lldb/Target/Process.h" 16 #include "lldb/Target/Target.h" 17 #include "lldb/Target/ThreadPlanCallFunction.h" 18 19 #include <sys/mman.h> 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, 25 addr_t addr, addr_t length, unsigned prot, 26 unsigned flags, addr_t fd, addr_t offset) { 27 Thread *thread = process->GetThreadList().GetSelectedThread().get(); 28 if (thread == NULL) 29 return false; 30 31 const bool append = true; 32 const bool include_symbols = true; 33 const bool include_inlines = false; 34 SymbolContextList sc_list; 35 const uint32_t count 36 = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 37 eFunctionNameTypeFull, 38 include_symbols, 39 include_inlines, 40 append, 41 sc_list); 42 if (count > 0) 43 { 44 SymbolContext sc; 45 if (sc_list.GetContextAtIndex(0, sc)) 46 { 47 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 48 const bool use_inline_block_range = false; 49 const bool stop_other_threads = true; 50 const bool discard_on_error = true; 51 const bool try_all_threads = true; 52 const uint32_t single_thread_timeout_usec = 500000; 53 54 addr_t prot_arg, flags_arg = 0; 55 if (prot == eMmapProtNone) 56 prot_arg = PROT_NONE; 57 else { 58 prot_arg = 0; 59 if (prot & eMmapProtExec) 60 prot_arg |= PROT_EXEC; 61 if (prot & eMmapProtRead) 62 prot_arg |= PROT_READ; 63 if (prot & eMmapProtWrite) 64 prot_arg |= PROT_WRITE; 65 } 66 67 if (flags & eMmapFlagsPrivate) 68 flags_arg |= MAP_PRIVATE; 69 if (flags & eMmapFlagsAnon) 70 flags_arg |= MAP_ANON; 71 72 AddressRange mmap_range; 73 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) 74 { 75 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 76 lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 77 ThreadPlanCallFunction *call_function_thread_plan 78 = new ThreadPlanCallFunction (*thread, 79 mmap_range.GetBaseAddress(), 80 ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type), 81 stop_other_threads, 82 discard_on_error, 83 &addr, 84 &length, 85 &prot_arg, 86 &flags_arg, 87 &fd, 88 &offset); 89 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); 90 if (call_plan_sp) 91 { 92 StreamFile error_strm; 93 // This plan is a utility plan, so set it to discard itself when done. 94 call_plan_sp->SetIsMasterPlan (true); 95 call_plan_sp->SetOkayToDiscard(true); 96 97 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 98 if (frame) 99 { 100 ExecutionContext exe_ctx; 101 frame->CalculateExecutionContext (exe_ctx); 102 ExecutionResults result = process->RunThreadPlan (exe_ctx, 103 call_plan_sp, 104 stop_other_threads, 105 try_all_threads, 106 discard_on_error, 107 single_thread_timeout_usec, 108 error_strm); 109 if (result == eExecutionCompleted) 110 { 111 112 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); 113 if (process->GetAddressByteSize() == 4) 114 { 115 if (allocated_addr == UINT32_MAX) 116 return false; 117 } 118 return true; 119 } 120 } 121 } 122 } 123 } 124 } 125 126 return false; 127 } 128 129 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, 130 addr_t length) { 131 Thread *thread = process->GetThreadList().GetSelectedThread().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 140 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 141 eFunctionNameTypeFull, 142 include_symbols, 143 include_inlines, 144 append, 145 sc_list); 146 if (count > 0) 147 { 148 SymbolContext sc; 149 if (sc_list.GetContextAtIndex(0, sc)) 150 { 151 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; 152 const bool use_inline_block_range = false; 153 const bool stop_other_threads = true; 154 const bool discard_on_error = true; 155 const bool try_all_threads = true; 156 const uint32_t single_thread_timeout_usec = 500000; 157 158 AddressRange munmap_range; 159 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) 160 { 161 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, 162 munmap_range.GetBaseAddress(), 163 ClangASTType(), 164 stop_other_threads, 165 discard_on_error, 166 &addr, 167 &length)); 168 if (call_plan_sp) 169 { 170 StreamFile error_strm; 171 // This plan is a utility plan, so set it to discard itself when done. 172 call_plan_sp->SetIsMasterPlan (true); 173 call_plan_sp->SetOkayToDiscard(true); 174 175 StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); 176 if (frame) 177 { 178 ExecutionContext exe_ctx; 179 frame->CalculateExecutionContext (exe_ctx); 180 ExecutionResults result = process->RunThreadPlan (exe_ctx, 181 call_plan_sp, 182 stop_other_threads, 183 try_all_threads, 184 discard_on_error, 185 single_thread_timeout_usec, 186 error_strm); 187 if (result == eExecutionCompleted) 188 { 189 return true; 190 } 191 } 192 } 193 } 194 } 195 } 196 197 return false; 198 } 199