InferiorCallPOSIX.cpp revision 296417
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/Platform.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/ThreadPlanCallFunction.h"
21#include "lldb/Host/Config.h"
22
23#ifndef LLDB_DISABLE_POSIX
24#include <sys/mman.h>
25#else
26// define them
27#define PROT_NONE 0
28#define PROT_READ 1
29#define PROT_WRITE 2
30#define PROT_EXEC 4
31#endif
32
33using namespace lldb;
34using namespace lldb_private;
35
36bool
37lldb_private::InferiorCallMmap (Process *process,
38                                addr_t &allocated_addr,
39                                addr_t addr,
40                                addr_t length,
41                                unsigned prot,
42                                unsigned flags,
43                                addr_t fd,
44                                addr_t offset)
45{
46    Thread *thread = process->GetThreadList().GetSelectedThread().get();
47    if (thread == NULL)
48        return false;
49
50    const bool append = true;
51    const bool include_symbols = true;
52    const bool include_inlines = false;
53    SymbolContextList sc_list;
54    const uint32_t count
55      = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
56                                                        eFunctionNameTypeFull,
57                                                        include_symbols,
58                                                        include_inlines,
59                                                        append,
60                                                        sc_list);
61    if (count > 0)
62    {
63        SymbolContext sc;
64        if (sc_list.GetContextAtIndex(0, sc))
65        {
66            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
67            const bool use_inline_block_range = false;
68            EvaluateExpressionOptions options;
69            options.SetStopOthers(true);
70            options.SetUnwindOnError(true);
71            options.SetIgnoreBreakpoints(true);
72            options.SetTryAllThreads(true);
73            options.SetDebug (false);
74            options.SetTimeoutUsec(500000);
75            options.SetTrapExceptions(false);
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            const ArchSpec arch =  process->GetTarget().GetArchitecture();
91            flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags);
92
93            AddressRange mmap_range;
94            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
95            {
96                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
97                CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
98                lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
99                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
100                                                                             mmap_range.GetBaseAddress(),
101                                                                             clang_void_ptr_type,
102                                                                             args,
103                                                                             options));
104                if (call_plan_sp)
105                {
106                    StreamFile error_strm;
107
108                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
109                    if (frame)
110                    {
111                        ExecutionContext exe_ctx;
112                        frame->CalculateExecutionContext (exe_ctx);
113                        ExpressionResults result = process->RunThreadPlan (exe_ctx,
114                                                                          call_plan_sp,
115                                                                          options,
116                                                                          error_strm);
117                        if (result == eExpressionCompleted)
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
143lldb_private::InferiorCallMunmap (Process *process,
144                                  addr_t addr,
145                                  addr_t length)
146{
147   Thread *thread = process->GetThreadList().GetSelectedThread().get();
148   if (thread == NULL)
149       return false;
150
151   const bool append = true;
152   const bool include_symbols = true;
153   const bool include_inlines = false;
154   SymbolContextList sc_list;
155   const uint32_t count
156     = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
157                                                       eFunctionNameTypeFull,
158                                                       include_symbols,
159                                                       include_inlines,
160                                                       append,
161                                                       sc_list);
162   if (count > 0)
163   {
164       SymbolContext sc;
165       if (sc_list.GetContextAtIndex(0, sc))
166       {
167            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
168            const bool use_inline_block_range = false;
169            EvaluateExpressionOptions options;
170            options.SetStopOthers(true);
171            options.SetUnwindOnError(true);
172            options.SetIgnoreBreakpoints(true);
173            options.SetTryAllThreads(true);
174            options.SetDebug (false);
175            options.SetTimeoutUsec(500000);
176            options.SetTrapExceptions(false);
177
178            AddressRange munmap_range;
179            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
180            {
181                lldb::addr_t args[] = { addr, length };
182                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
183                                                                            munmap_range.GetBaseAddress(),
184                                                                            CompilerType(),
185                                                                            args,
186                                                                            options));
187                if (call_plan_sp)
188                {
189                    StreamFile error_strm;
190
191                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
192                    if (frame)
193                    {
194                        ExecutionContext exe_ctx;
195                        frame->CalculateExecutionContext (exe_ctx);
196                        ExpressionResults result = process->RunThreadPlan (exe_ctx,
197                                                                          call_plan_sp,
198                                                                          options,
199                                                                          error_strm);
200                        if (result == eExpressionCompleted)
201                        {
202                            return true;
203                        }
204                    }
205                }
206            }
207        }
208    }
209
210    return false;
211}
212
213// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a
214// function of the form "void * (*)(void)".  We should find a better place to put this.
215
216bool
217lldb_private::InferiorCall (Process *process,
218                            const Address *address,
219                            addr_t &returned_func,
220                            bool trap_exceptions)
221{
222    Thread *thread = process->GetThreadList().GetSelectedThread().get();
223    if (thread == NULL || address == NULL)
224        return false;
225
226    EvaluateExpressionOptions options;
227    options.SetStopOthers(true);
228    options.SetUnwindOnError(true);
229    options.SetIgnoreBreakpoints(true);
230    options.SetTryAllThreads(true);
231    options.SetDebug (false);
232    options.SetTimeoutUsec(500000);
233    options.SetTrapExceptions(trap_exceptions);
234
235    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
236    CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
237    lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
238                                                                 *address,
239                                                                 clang_void_ptr_type,
240                                                                 llvm::ArrayRef<addr_t>(),
241                                                                 options));
242    if (call_plan_sp)
243    {
244        StreamString error_strm;
245
246        StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
247        if (frame)
248        {
249            ExecutionContext exe_ctx;
250            frame->CalculateExecutionContext (exe_ctx);
251            ExpressionResults result = process->RunThreadPlan (exe_ctx,
252                                                              call_plan_sp,
253                                                              options,
254                                                              error_strm);
255            if (result == eExpressionCompleted)
256            {
257                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
258
259                if (process->GetAddressByteSize() == 4)
260                {
261                    if (returned_func == UINT32_MAX)
262                        return false;
263                }
264                else if (process->GetAddressByteSize() == 8)
265                {
266                    if (returned_func == UINT64_MAX)
267                        return false;
268                }
269                return true;
270            }
271        }
272    }
273
274    return false;
275}
276