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