InferiorCallPOSIX.cpp revision 254729
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
23using namespace lldb;
24using namespace lldb_private;
25
26bool 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
139bool 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
213bool 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