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