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