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