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