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