InferiorCallPOSIX.cpp revision e6bd142d9fa7ed149bd37efd8a75637375f165b7
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/StreamFile.h"
12#include "lldb/Core/Value.h"
13#include "lldb/Symbol/SymbolContext.h"
14#include "lldb/Target/ExecutionContext.h"
15#include "lldb/Target/Process.h"
16#include "lldb/Target/Target.h"
17#include "lldb/Target/ThreadPlanCallFunction.h"
18
19#include <sys/mman.h>
20
21using namespace lldb;
22using namespace lldb_private;
23
24bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
25                                    addr_t addr, addr_t length, unsigned prot,
26                                    unsigned flags, addr_t fd, addr_t offset) {
27    Thread *thread = process->GetThreadList().GetSelectedThread().get();
28    if (thread == NULL)
29        thread = process->GetThreadList().GetThreadAtIndex(0).get();
30    if (thread == NULL)
31        return false;
32
33    const bool append = true;
34    const bool include_symbols = true;
35    SymbolContextList sc_list;
36    const uint32_t count
37      = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
38                                                        eFunctionNameTypeFull,
39                                                        include_symbols,
40                                                        append,
41                                                        sc_list);
42    if (count > 0)
43    {
44        SymbolContext sc;
45        if (sc_list.GetContextAtIndex(0, sc))
46        {
47            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
48            const bool use_inline_block_range = false;
49            const bool stop_other_threads = true;
50            const bool discard_on_error = true;
51            const bool try_all_threads = true;
52            const uint32_t single_thread_timeout_usec = 500000;
53
54            addr_t prot_arg, flags_arg = 0;
55            if (prot == eMmapProtNone)
56              prot_arg = PROT_NONE;
57            else {
58              prot_arg = 0;
59              if (prot & eMmapProtExec)
60                prot_arg |= PROT_EXEC;
61              if (prot & eMmapProtRead)
62                prot_arg |= PROT_READ;
63              if (prot & eMmapProtWrite)
64                prot_arg |= PROT_WRITE;
65            }
66
67            if (flags & eMmapFlagsPrivate)
68              flags_arg |= MAP_PRIVATE;
69            if (flags & eMmapFlagsAnon)
70              flags_arg |= MAP_ANON;
71
72            AddressRange mmap_range;
73            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
74            {
75                ThreadPlanCallFunction *call_function_thread_plan
76                  = new ThreadPlanCallFunction (*thread,
77                                                mmap_range.GetBaseAddress(),
78                                                stop_other_threads,
79                                                discard_on_error,
80                                                &addr,
81                                                &length,
82                                                &prot_arg,
83                                                &flags_arg,
84                                                &fd,
85                                                &offset);
86                lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
87                if (call_plan_sp)
88                {
89                    ValueSP return_value_sp (new Value);
90                    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
91                    lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
92                    return_value_sp->SetValueType (Value::eValueTypeScalar);
93                    return_value_sp->SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
94                    call_function_thread_plan->RequestReturnValue (return_value_sp);
95
96                    StreamFile error_strm;
97                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
98                    if (frame)
99                    {
100                        ExecutionContext exe_ctx;
101                        frame->CalculateExecutionContext (exe_ctx);
102                        ExecutionResults result = process->RunThreadPlan (exe_ctx,
103                                                                          call_plan_sp,
104                                                                          stop_other_threads,
105                                                                          try_all_threads,
106                                                                          discard_on_error,
107                                                                          single_thread_timeout_usec,
108                                                                          error_strm);
109                        if (result == eExecutionCompleted)
110                        {
111                            allocated_addr = return_value_sp->GetScalar().ULongLong();
112                            if (process->GetAddressByteSize() == 4)
113                            {
114                                if (allocated_addr == UINT32_MAX)
115                                    return false;
116                            }
117                            return true;
118                        }
119                    }
120                }
121            }
122        }
123    }
124
125    return false;
126}
127
128bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
129                                      addr_t length) {
130   Thread *thread = process->GetThreadList().GetSelectedThread().get();
131   if (thread == NULL)
132       thread = process->GetThreadList().GetThreadAtIndex(0).get();
133
134   const bool append = true;
135   const bool include_symbols = true;
136   SymbolContextList sc_list;
137   const uint32_t count
138     = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
139                                                       eFunctionNameTypeFull,
140                                                       include_symbols,
141                                                       append,
142                                                       sc_list);
143   if (count > 0)
144   {
145       SymbolContext sc;
146       if (sc_list.GetContextAtIndex(0, sc))
147       {
148           const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
149           const bool use_inline_block_range = false;
150           const bool stop_other_threads = true;
151           const bool discard_on_error = true;
152           const bool try_all_threads = true;
153           const uint32_t single_thread_timeout_usec = 500000;
154
155           AddressRange munmap_range;
156           if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
157           {
158               lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
159                                                                            munmap_range.GetBaseAddress(),
160                                                                            stop_other_threads,
161                                                                            discard_on_error,
162                                                                            &addr,
163                                                                            &length));
164               if (call_plan_sp)
165               {
166                   StreamFile error_strm;
167                   StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
168                   if (frame)
169                   {
170                       ExecutionContext exe_ctx;
171                       frame->CalculateExecutionContext (exe_ctx);
172                       ExecutionResults result = process->RunThreadPlan (exe_ctx,
173                                                                         call_plan_sp,
174                                                                         stop_other_threads,
175                                                                         try_all_threads,
176                                                                         discard_on_error,
177                                                                         single_thread_timeout_usec,
178                                                                         error_strm);
179                       if (result == eExecutionCompleted)
180                       {
181                           return true;
182                       }
183                   }
184               }
185           }
186       }
187   }
188
189   return false;
190}
191