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 
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.SetTimeoutUsec(500000);
65       options.SetTrapExceptions(false);
66 
67       addr_t prot_arg, flags_arg = 0;
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       const ArchSpec arch = process->GetTarget().GetArchitecture();
81       flags_arg =
82           process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,
83                                                                          flags);
84 
85       AddressRange mmap_range;
86       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
87                              mmap_range)) {
88         ClangASTContext *clang_ast_context =
89             process->GetTarget().GetScratchClangASTContext();
90         CompilerType clang_void_ptr_type =
91             clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
92         lldb::addr_t args[] = {addr, length, prot_arg, flags_arg, fd, offset};
93         lldb::ThreadPlanSP call_plan_sp(
94             new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
95                                        clang_void_ptr_type, args, options));
96         if (call_plan_sp) {
97           DiagnosticManager diagnostics;
98 
99           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
100           if (frame) {
101             ExecutionContext exe_ctx;
102             frame->CalculateExecutionContext(exe_ctx);
103             ExpressionResults result = process->RunThreadPlan(
104                 exe_ctx, call_plan_sp, options, diagnostics);
105             if (result == eExpressionCompleted) {
106 
107               allocated_addr =
108                   call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
109                       LLDB_INVALID_ADDRESS);
110               if (process->GetAddressByteSize() == 4) {
111                 if (allocated_addr == UINT32_MAX)
112                   return false;
113               } else if (process->GetAddressByteSize() == 8) {
114                 if (allocated_addr == UINT64_MAX)
115                   return false;
116               }
117               return true;
118             }
119           }
120         }
121       }
122     }
123   }
124 
125   return false;
126 }
127 
128 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
129                                       addr_t length) {
130   Thread *thread =
131       process->GetThreadList().GetExpressionExecutionThread().get();
132   if (thread == NULL)
133     return false;
134 
135   const bool append = true;
136   const bool include_symbols = true;
137   const bool include_inlines = false;
138   SymbolContextList sc_list;
139   const uint32_t count = process->GetTarget().GetImages().FindFunctions(
140       ConstString("munmap"), eFunctionNameTypeFull, include_symbols,
141       include_inlines, append, sc_list);
142   if (count > 0) {
143     SymbolContext sc;
144     if (sc_list.GetContextAtIndex(0, sc)) {
145       const uint32_t range_scope =
146           eSymbolContextFunction | eSymbolContextSymbol;
147       const bool use_inline_block_range = false;
148       EvaluateExpressionOptions options;
149       options.SetStopOthers(true);
150       options.SetUnwindOnError(true);
151       options.SetIgnoreBreakpoints(true);
152       options.SetTryAllThreads(true);
153       options.SetDebug(false);
154       options.SetTimeoutUsec(500000);
155       options.SetTrapExceptions(false);
156 
157       AddressRange munmap_range;
158       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
159                              munmap_range)) {
160         lldb::addr_t args[] = {addr, length};
161         lldb::ThreadPlanSP call_plan_sp(
162             new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
163                                        CompilerType(), args, options));
164         if (call_plan_sp) {
165           DiagnosticManager diagnostics;
166 
167           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
168           if (frame) {
169             ExecutionContext exe_ctx;
170             frame->CalculateExecutionContext(exe_ctx);
171             ExpressionResults result = process->RunThreadPlan(
172                 exe_ctx, call_plan_sp, options, diagnostics);
173             if (result == eExpressionCompleted) {
174               return true;
175             }
176           }
177         }
178       }
179     }
180   }
181 
182   return false;
183 }
184 
185 // FIXME: This has nothing to do with Posix, it is just a convenience function
186 // that calls a
187 // function of the form "void * (*)(void)".  We should find a better place to
188 // put this.
189 
190 bool lldb_private::InferiorCall(Process *process, const Address *address,
191                                 addr_t &returned_func, bool trap_exceptions) {
192   Thread *thread =
193       process->GetThreadList().GetExpressionExecutionThread().get();
194   if (thread == NULL || address == NULL)
195     return false;
196 
197   EvaluateExpressionOptions options;
198   options.SetStopOthers(true);
199   options.SetUnwindOnError(true);
200   options.SetIgnoreBreakpoints(true);
201   options.SetTryAllThreads(true);
202   options.SetDebug(false);
203   options.SetTimeoutUsec(500000);
204   options.SetTrapExceptions(trap_exceptions);
205 
206   ClangASTContext *clang_ast_context =
207       process->GetTarget().GetScratchClangASTContext();
208   CompilerType clang_void_ptr_type =
209       clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
210   lldb::ThreadPlanSP call_plan_sp(
211       new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type,
212                                  llvm::ArrayRef<addr_t>(), options));
213   if (call_plan_sp) {
214     DiagnosticManager diagnostics;
215 
216     StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
217     if (frame) {
218       ExecutionContext exe_ctx;
219       frame->CalculateExecutionContext(exe_ctx);
220       ExpressionResults result =
221           process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
222       if (result == eExpressionCompleted) {
223         returned_func =
224             call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
225                 LLDB_INVALID_ADDRESS);
226 
227         if (process->GetAddressByteSize() == 4) {
228           if (returned_func == UINT32_MAX)
229             return false;
230         } else if (process->GetAddressByteSize() == 8) {
231           if (returned_func == UINT64_MAX)
232             return false;
233         }
234         return true;
235       }
236     }
237   }
238 
239   return false;
240 }
241