InferiorCallPOSIX.cpp revision 258054
1254721Semaste//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "InferiorCallPOSIX.h"
11254721Semaste#include "lldb/Core/Address.h"
12254721Semaste#include "lldb/Core/StreamFile.h"
13254721Semaste#include "lldb/Core/ValueObject.h"
14254721Semaste#include "lldb/Symbol/ClangASTContext.h"
15254721Semaste#include "lldb/Symbol/SymbolContext.h"
16254721Semaste#include "lldb/Target/ExecutionContext.h"
17254721Semaste#include "lldb/Target/Process.h"
18254721Semaste#include "lldb/Target/Target.h"
19254721Semaste#include "lldb/Target/ThreadPlanCallFunction.h"
20258054Semaste#include "lldb/Host/Config.h"
21254721Semaste
22258054Semaste#ifndef LLDB_DISABLE_POSIX
23254721Semaste#include <sys/mman.h>
24258054Semaste#else
25258054Semaste// define them
26258054Semaste#define PROT_NONE 0
27258054Semaste#define PROT_READ 1
28258054Semaste#define PROT_WRITE 2
29258054Semaste#define PROT_EXEC 4
30258054Semaste#define MAP_PRIVATE 2
31258054Semaste#define MAP_ANON 0x1000
32258054Semaste#endif
33254721Semaste
34254721Semasteusing namespace lldb;
35254721Semasteusing namespace lldb_private;
36254721Semaste
37254721Semastebool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
38254721Semaste                                    addr_t addr, addr_t length, unsigned prot,
39254721Semaste                                    unsigned flags, addr_t fd, addr_t offset) {
40254721Semaste    Thread *thread = process->GetThreadList().GetSelectedThread().get();
41254721Semaste    if (thread == NULL)
42254721Semaste        return false;
43254721Semaste
44254721Semaste    const bool append = true;
45254721Semaste    const bool include_symbols = true;
46254721Semaste    const bool include_inlines = false;
47254721Semaste    SymbolContextList sc_list;
48254721Semaste    const uint32_t count
49254721Semaste      = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
50254721Semaste                                                        eFunctionNameTypeFull,
51254721Semaste                                                        include_symbols,
52254721Semaste                                                        include_inlines,
53254721Semaste                                                        append,
54254721Semaste                                                        sc_list);
55254721Semaste    if (count > 0)
56254721Semaste    {
57254721Semaste        SymbolContext sc;
58254721Semaste        if (sc_list.GetContextAtIndex(0, sc))
59254721Semaste        {
60254721Semaste            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
61254721Semaste            const bool use_inline_block_range = false;
62254721Semaste            const bool stop_other_threads = true;
63254721Semaste            const bool unwind_on_error = true;
64254721Semaste            const bool ignore_breakpoints = true;
65254721Semaste            const bool try_all_threads = true;
66254721Semaste            const uint32_t timeout_usec = 500000;
67254721Semaste
68254721Semaste            addr_t prot_arg, flags_arg = 0;
69254721Semaste            if (prot == eMmapProtNone)
70254721Semaste              prot_arg = PROT_NONE;
71254721Semaste            else {
72254721Semaste              prot_arg = 0;
73254721Semaste              if (prot & eMmapProtExec)
74254721Semaste                prot_arg |= PROT_EXEC;
75254721Semaste              if (prot & eMmapProtRead)
76254721Semaste                prot_arg |= PROT_READ;
77254721Semaste              if (prot & eMmapProtWrite)
78254721Semaste                prot_arg |= PROT_WRITE;
79254721Semaste            }
80254721Semaste
81254721Semaste            if (flags & eMmapFlagsPrivate)
82254721Semaste              flags_arg |= MAP_PRIVATE;
83254721Semaste            if (flags & eMmapFlagsAnon)
84254721Semaste              flags_arg |= MAP_ANON;
85254721Semaste
86254721Semaste            AddressRange mmap_range;
87254721Semaste            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
88254721Semaste            {
89254721Semaste                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
90254721Semaste                ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
91254721Semaste                ThreadPlanCallFunction *call_function_thread_plan
92254721Semaste                  = new ThreadPlanCallFunction (*thread,
93254721Semaste                                                mmap_range.GetBaseAddress(),
94254721Semaste                                                clang_void_ptr_type,
95254721Semaste                                                stop_other_threads,
96254721Semaste                                                unwind_on_error,
97254721Semaste                                                ignore_breakpoints,
98254721Semaste                                                &addr,
99254721Semaste                                                &length,
100254721Semaste                                                &prot_arg,
101254721Semaste                                                &flags_arg,
102254721Semaste                                                &fd,
103254721Semaste                                                &offset);
104254721Semaste                lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
105254721Semaste                if (call_plan_sp)
106254721Semaste                {
107254721Semaste                    StreamFile error_strm;
108254721Semaste                    // This plan is a utility plan, so set it to discard itself when done.
109254721Semaste                    call_plan_sp->SetIsMasterPlan (true);
110254721Semaste                    call_plan_sp->SetOkayToDiscard(true);
111254721Semaste
112254721Semaste                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
113254721Semaste                    if (frame)
114254721Semaste                    {
115254721Semaste                        ExecutionContext exe_ctx;
116254721Semaste                        frame->CalculateExecutionContext (exe_ctx);
117254721Semaste                        ExecutionResults result = process->RunThreadPlan (exe_ctx,
118254721Semaste                                                                          call_plan_sp,
119254721Semaste                                                                          stop_other_threads,
120254721Semaste                                                                          try_all_threads,
121254721Semaste                                                                          unwind_on_error,
122254721Semaste                                                                          ignore_breakpoints,
123254721Semaste                                                                          timeout_usec,
124254721Semaste                                                                          error_strm);
125254721Semaste                        if (result == eExecutionCompleted)
126254721Semaste                        {
127254721Semaste
128254721Semaste                            allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
129254721Semaste                            if (process->GetAddressByteSize() == 4)
130254721Semaste                            {
131254721Semaste                                if (allocated_addr == UINT32_MAX)
132254721Semaste                                    return false;
133254721Semaste                            }
134254721Semaste                            else if (process->GetAddressByteSize() == 8)
135254721Semaste                            {
136254721Semaste                                if (allocated_addr == UINT64_MAX)
137254721Semaste                                    return false;
138254721Semaste                            }
139254721Semaste                            return true;
140254721Semaste                        }
141254721Semaste                    }
142254721Semaste                }
143254721Semaste            }
144254721Semaste        }
145254721Semaste    }
146254721Semaste
147254721Semaste    return false;
148254721Semaste}
149254721Semaste
150254721Semastebool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
151254721Semaste                                      addr_t length) {
152254721Semaste   Thread *thread = process->GetThreadList().GetSelectedThread().get();
153254721Semaste   if (thread == NULL)
154254721Semaste       return false;
155254721Semaste
156254721Semaste   const bool append = true;
157254721Semaste   const bool include_symbols = true;
158254721Semaste   const bool include_inlines = false;
159254721Semaste   SymbolContextList sc_list;
160254721Semaste   const uint32_t count
161254721Semaste     = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
162254721Semaste                                                       eFunctionNameTypeFull,
163254721Semaste                                                       include_symbols,
164254721Semaste                                                       include_inlines,
165254721Semaste                                                       append,
166254721Semaste                                                       sc_list);
167254721Semaste   if (count > 0)
168254721Semaste   {
169254721Semaste       SymbolContext sc;
170254721Semaste       if (sc_list.GetContextAtIndex(0, sc))
171254721Semaste       {
172254721Semaste           const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
173254721Semaste           const bool use_inline_block_range = false;
174254721Semaste           const bool stop_other_threads = true;
175254721Semaste           const bool unwind_on_error = true;
176254721Semaste           const bool ignore_breakpoints = true;
177254721Semaste           const bool try_all_threads = true;
178254721Semaste           const uint32_t timeout_usec = 500000;
179254721Semaste
180254721Semaste           AddressRange munmap_range;
181254721Semaste           if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
182254721Semaste           {
183254721Semaste               lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
184254721Semaste                                                                            munmap_range.GetBaseAddress(),
185254721Semaste                                                                            ClangASTType(),
186254721Semaste                                                                            stop_other_threads,
187254721Semaste                                                                            unwind_on_error,
188254721Semaste                                                                            ignore_breakpoints,
189254721Semaste                                                                            &addr,
190254721Semaste                                                                            &length));
191254721Semaste               if (call_plan_sp)
192254721Semaste               {
193254721Semaste                   StreamFile error_strm;
194254721Semaste                   // This plan is a utility plan, so set it to discard itself when done.
195254721Semaste                   call_plan_sp->SetIsMasterPlan (true);
196254721Semaste                   call_plan_sp->SetOkayToDiscard(true);
197254721Semaste
198254721Semaste                   StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
199254721Semaste                   if (frame)
200254721Semaste                   {
201254721Semaste                       ExecutionContext exe_ctx;
202254721Semaste                       frame->CalculateExecutionContext (exe_ctx);
203254721Semaste                       ExecutionResults result = process->RunThreadPlan (exe_ctx,
204254721Semaste                                                                         call_plan_sp,
205254721Semaste                                                                         stop_other_threads,
206254721Semaste                                                                         try_all_threads,
207254721Semaste                                                                         unwind_on_error,
208254721Semaste                                                                         ignore_breakpoints,
209254721Semaste                                                                         timeout_usec,
210254721Semaste                                                                         error_strm);
211254721Semaste                       if (result == eExecutionCompleted)
212254721Semaste                       {
213254721Semaste                           return true;
214254721Semaste                       }
215254721Semaste                   }
216254721Semaste               }
217254721Semaste           }
218254721Semaste       }
219254721Semaste   }
220254721Semaste
221254721Semaste   return false;
222254721Semaste}
223254721Semaste
224254721Semastebool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
225254721Semaste    Thread *thread = process->GetThreadList().GetSelectedThread().get();
226254721Semaste    if (thread == NULL || address == NULL)
227254721Semaste        return false;
228254721Semaste
229254721Semaste    const bool stop_other_threads = true;
230254721Semaste    const bool unwind_on_error = true;
231254721Semaste    const bool ignore_breakpoints = true;
232254721Semaste    const bool try_all_threads = true;
233254721Semaste    const uint32_t timeout_usec = 500000;
234254721Semaste
235254721Semaste    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
236254721Semaste    ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
237254721Semaste    ThreadPlanCallFunction *call_function_thread_plan
238254721Semaste        = new ThreadPlanCallFunction (*thread,
239254721Semaste                                      *address,
240254721Semaste                                      clang_void_ptr_type,
241254721Semaste                                      stop_other_threads,
242254721Semaste                                      unwind_on_error,
243254721Semaste                                      ignore_breakpoints);
244254721Semaste    lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
245254721Semaste    if (call_plan_sp)
246254721Semaste    {
247254721Semaste        StreamFile error_strm;
248254721Semaste        // This plan is a utility plan, so set it to discard itself when done.
249254721Semaste        call_plan_sp->SetIsMasterPlan (true);
250254721Semaste        call_plan_sp->SetOkayToDiscard(true);
251254721Semaste
252254721Semaste        StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
253254721Semaste        if (frame)
254254721Semaste        {
255254721Semaste            ExecutionContext exe_ctx;
256254721Semaste            frame->CalculateExecutionContext (exe_ctx);
257254721Semaste            ExecutionResults result = process->RunThreadPlan (exe_ctx,
258254721Semaste                                                              call_plan_sp,
259254721Semaste                                                              stop_other_threads,
260254721Semaste                                                              try_all_threads,
261254721Semaste                                                              unwind_on_error,
262254721Semaste                                                              ignore_breakpoints,
263254721Semaste                                                              timeout_usec,
264254721Semaste                                                              error_strm);
265254721Semaste            if (result == eExecutionCompleted)
266254721Semaste            {
267254721Semaste                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
268254721Semaste
269254721Semaste                if (process->GetAddressByteSize() == 4)
270254721Semaste                {
271254721Semaste                    if (returned_func == UINT32_MAX)
272254721Semaste                        return false;
273254721Semaste                }
274254721Semaste                else if (process->GetAddressByteSize() == 8)
275254721Semaste                {
276254721Semaste                    if (returned_func == UINT64_MAX)
277254721Semaste                        return false;
278254721Semaste                }
279254721Semaste                return true;
280254721Semaste            }
281254721Semaste        }
282254721Semaste    }
283254721Semaste
284254721Semaste    return false;
285254721Semaste}
286