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