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