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