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/Symbol/ClangASTContext.h"
15 #include "lldb/Symbol/SymbolContext.h"
16 #include "lldb/Target/ExecutionContext.h"
17 #include "lldb/Target/Process.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Target/ThreadPlanCallFunction.h"
20
21 #include <sys/mman.h>
22
23 using namespace lldb;
24 using namespace lldb_private;
25
InferiorCallMmap(Process * process,addr_t & allocated_addr,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)26 bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
27 addr_t addr, addr_t length, unsigned prot,
28 unsigned flags, addr_t fd, addr_t offset) {
29 Thread *thread = process->GetThreadList().GetSelectedThread().get();
30 if (thread == NULL)
31 return false;
32
33 const bool append = true;
34 const bool include_symbols = true;
35 const bool include_inlines = false;
36 SymbolContextList sc_list;
37 const uint32_t count
38 = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
39 eFunctionNameTypeFull,
40 include_symbols,
41 include_inlines,
42 append,
43 sc_list);
44 if (count > 0)
45 {
46 SymbolContext sc;
47 if (sc_list.GetContextAtIndex(0, sc))
48 {
49 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
50 const bool use_inline_block_range = false;
51 const bool stop_other_threads = true;
52 const bool unwind_on_error = true;
53 const bool ignore_breakpoints = true;
54 const bool try_all_threads = true;
55 const uint32_t timeout_usec = 500000;
56
57 addr_t prot_arg, flags_arg = 0;
58 if (prot == eMmapProtNone)
59 prot_arg = PROT_NONE;
60 else {
61 prot_arg = 0;
62 if (prot & eMmapProtExec)
63 prot_arg |= PROT_EXEC;
64 if (prot & eMmapProtRead)
65 prot_arg |= PROT_READ;
66 if (prot & eMmapProtWrite)
67 prot_arg |= PROT_WRITE;
68 }
69
70 if (flags & eMmapFlagsPrivate)
71 flags_arg |= MAP_PRIVATE;
72 if (flags & eMmapFlagsAnon)
73 flags_arg |= MAP_ANON;
74
75 AddressRange mmap_range;
76 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
77 {
78 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
79 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
80 ThreadPlanCallFunction *call_function_thread_plan
81 = new ThreadPlanCallFunction (*thread,
82 mmap_range.GetBaseAddress(),
83 clang_void_ptr_type,
84 stop_other_threads,
85 unwind_on_error,
86 ignore_breakpoints,
87 &addr,
88 &length,
89 &prot_arg,
90 &flags_arg,
91 &fd,
92 &offset);
93 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
94 if (call_plan_sp)
95 {
96 StreamFile error_strm;
97 // This plan is a utility plan, so set it to discard itself when done.
98 call_plan_sp->SetIsMasterPlan (true);
99 call_plan_sp->SetOkayToDiscard(true);
100
101 StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
102 if (frame)
103 {
104 ExecutionContext exe_ctx;
105 frame->CalculateExecutionContext (exe_ctx);
106 ExecutionResults result = process->RunThreadPlan (exe_ctx,
107 call_plan_sp,
108 stop_other_threads,
109 try_all_threads,
110 unwind_on_error,
111 ignore_breakpoints,
112 timeout_usec,
113 error_strm);
114 if (result == eExecutionCompleted)
115 {
116
117 allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
118 if (process->GetAddressByteSize() == 4)
119 {
120 if (allocated_addr == UINT32_MAX)
121 return false;
122 }
123 else if (process->GetAddressByteSize() == 8)
124 {
125 if (allocated_addr == UINT64_MAX)
126 return false;
127 }
128 return true;
129 }
130 }
131 }
132 }
133 }
134 }
135
136 return false;
137 }
138
InferiorCallMunmap(Process * process,addr_t addr,addr_t length)139 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
140 addr_t length) {
141 Thread *thread = process->GetThreadList().GetSelectedThread().get();
142 if (thread == NULL)
143 return false;
144
145 const bool append = true;
146 const bool include_symbols = true;
147 const bool include_inlines = false;
148 SymbolContextList sc_list;
149 const uint32_t count
150 = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
151 eFunctionNameTypeFull,
152 include_symbols,
153 include_inlines,
154 append,
155 sc_list);
156 if (count > 0)
157 {
158 SymbolContext sc;
159 if (sc_list.GetContextAtIndex(0, sc))
160 {
161 const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
162 const bool use_inline_block_range = false;
163 const bool stop_other_threads = true;
164 const bool unwind_on_error = true;
165 const bool ignore_breakpoints = true;
166 const bool try_all_threads = true;
167 const uint32_t timeout_usec = 500000;
168
169 AddressRange munmap_range;
170 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
171 {
172 lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
173 munmap_range.GetBaseAddress(),
174 ClangASTType(),
175 stop_other_threads,
176 unwind_on_error,
177 ignore_breakpoints,
178 &addr,
179 &length));
180 if (call_plan_sp)
181 {
182 StreamFile error_strm;
183 // This plan is a utility plan, so set it to discard itself when done.
184 call_plan_sp->SetIsMasterPlan (true);
185 call_plan_sp->SetOkayToDiscard(true);
186
187 StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
188 if (frame)
189 {
190 ExecutionContext exe_ctx;
191 frame->CalculateExecutionContext (exe_ctx);
192 ExecutionResults result = process->RunThreadPlan (exe_ctx,
193 call_plan_sp,
194 stop_other_threads,
195 try_all_threads,
196 unwind_on_error,
197 ignore_breakpoints,
198 timeout_usec,
199 error_strm);
200 if (result == eExecutionCompleted)
201 {
202 return true;
203 }
204 }
205 }
206 }
207 }
208 }
209
210 return false;
211 }
212
InferiorCall(Process * process,const Address * address,addr_t & returned_func)213 bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
214 Thread *thread = process->GetThreadList().GetSelectedThread().get();
215 if (thread == NULL || address == NULL)
216 return false;
217
218 const bool stop_other_threads = true;
219 const bool unwind_on_error = true;
220 const bool ignore_breakpoints = true;
221 const bool try_all_threads = true;
222 const uint32_t timeout_usec = 500000;
223
224 ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
225 ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
226 ThreadPlanCallFunction *call_function_thread_plan
227 = new ThreadPlanCallFunction (*thread,
228 *address,
229 clang_void_ptr_type,
230 stop_other_threads,
231 unwind_on_error,
232 ignore_breakpoints);
233 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
234 if (call_plan_sp)
235 {
236 StreamFile error_strm;
237 // This plan is a utility plan, so set it to discard itself when done.
238 call_plan_sp->SetIsMasterPlan (true);
239 call_plan_sp->SetOkayToDiscard(true);
240
241 StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
242 if (frame)
243 {
244 ExecutionContext exe_ctx;
245 frame->CalculateExecutionContext (exe_ctx);
246 ExecutionResults result = process->RunThreadPlan (exe_ctx,
247 call_plan_sp,
248 stop_other_threads,
249 try_all_threads,
250 unwind_on_error,
251 ignore_breakpoints,
252 timeout_usec,
253 error_strm);
254 if (result == eExecutionCompleted)
255 {
256 returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
257
258 if (process->GetAddressByteSize() == 4)
259 {
260 if (returned_func == UINT32_MAX)
261 return false;
262 }
263 else if (process->GetAddressByteSize() == 8)
264 {
265 if (returned_func == UINT64_MAX)
266 return false;
267 }
268 return true;
269 }
270 }
271 }
272
273 return false;
274 }
275