InferiorCallPOSIX.cpp revision 258884
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            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
142bool 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
212bool 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