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