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