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