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/Expression/DiagnosticManager.h"
15 #include "lldb/Host/Config.h"
16 #include "lldb/Symbol/ClangASTContext.h"
17 #include "lldb/Symbol/SymbolContext.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/Platform.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/ThreadPlanCallFunction.h"
23 
24 #ifndef LLDB_DISABLE_POSIX
25 #include <sys/mman.h>
26 #else
27 // define them
28 #define PROT_NONE 0
29 #define PROT_READ 1
30 #define PROT_WRITE 2
31 #define PROT_EXEC 4
32 #endif
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
InferiorCallMmap(Process * process,addr_t & allocated_addr,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)37 bool 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 =
41       process->GetThreadList().GetExpressionExecutionThread().get();
42   if (thread == NULL)
43     return false;
44 
45   const bool append = true;
46   const bool include_symbols = true;
47   const bool include_inlines = false;
48   SymbolContextList sc_list;
49   const uint32_t count = process->GetTarget().GetImages().FindFunctions(
50       ConstString("mmap"), eFunctionNameTypeFull, include_symbols,
51       include_inlines, append, sc_list);
52   if (count > 0) {
53     SymbolContext sc;
54     if (sc_list.GetContextAtIndex(0, sc)) {
55       const uint32_t range_scope =
56           eSymbolContextFunction | eSymbolContextSymbol;
57       const bool use_inline_block_range = false;
58       EvaluateExpressionOptions options;
59       options.SetStopOthers(true);
60       options.SetUnwindOnError(true);
61       options.SetIgnoreBreakpoints(true);
62       options.SetTryAllThreads(true);
63       options.SetDebug(false);
64       options.SetTimeout(std::chrono::milliseconds(500));
65       options.SetTrapExceptions(false);
66 
67       addr_t prot_arg;
68       if (prot == eMmapProtNone)
69         prot_arg = PROT_NONE;
70       else {
71         prot_arg = 0;
72         if (prot & eMmapProtExec)
73           prot_arg |= PROT_EXEC;
74         if (prot & eMmapProtRead)
75           prot_arg |= PROT_READ;
76         if (prot & eMmapProtWrite)
77           prot_arg |= PROT_WRITE;
78       }
79 
80       AddressRange mmap_range;
81       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
82                              mmap_range)) {
83         ClangASTContext *clang_ast_context =
84             process->GetTarget().GetScratchClangASTContext();
85         CompilerType clang_void_ptr_type =
86             clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
87         const ArchSpec arch = process->GetTarget().GetArchitecture();
88         MmapArgList args =
89             process->GetTarget().GetPlatform()->GetMmapArgumentList(
90                 arch, addr, length, prot_arg, flags, fd, offset);
91         lldb::ThreadPlanSP call_plan_sp(
92             new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
93                                        clang_void_ptr_type, args, options));
94         if (call_plan_sp) {
95           DiagnosticManager diagnostics;
96 
97           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
98           if (frame) {
99             ExecutionContext exe_ctx;
100             frame->CalculateExecutionContext(exe_ctx);
101             ExpressionResults result = process->RunThreadPlan(
102                 exe_ctx, call_plan_sp, options, diagnostics);
103             if (result == eExpressionCompleted) {
104 
105               allocated_addr =
106                   call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
107                       LLDB_INVALID_ADDRESS);
108               if (process->GetAddressByteSize() == 4) {
109                 if (allocated_addr == UINT32_MAX)
110                   return false;
111               } else if (process->GetAddressByteSize() == 8) {
112                 if (allocated_addr == UINT64_MAX)
113                   return false;
114               }
115               return true;
116             }
117           }
118         }
119       }
120     }
121   }
122 
123   return false;
124 }
125 
InferiorCallMunmap(Process * process,addr_t addr,addr_t length)126 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
127                                       addr_t length) {
128   Thread *thread =
129       process->GetThreadList().GetExpressionExecutionThread().get();
130   if (thread == NULL)
131     return false;
132 
133   const bool append = true;
134   const bool include_symbols = true;
135   const bool include_inlines = false;
136   SymbolContextList sc_list;
137   const uint32_t count = process->GetTarget().GetImages().FindFunctions(
138       ConstString("munmap"), eFunctionNameTypeFull, include_symbols,
139       include_inlines, append, sc_list);
140   if (count > 0) {
141     SymbolContext sc;
142     if (sc_list.GetContextAtIndex(0, sc)) {
143       const uint32_t range_scope =
144           eSymbolContextFunction | eSymbolContextSymbol;
145       const bool use_inline_block_range = false;
146       EvaluateExpressionOptions options;
147       options.SetStopOthers(true);
148       options.SetUnwindOnError(true);
149       options.SetIgnoreBreakpoints(true);
150       options.SetTryAllThreads(true);
151       options.SetDebug(false);
152       options.SetTimeout(std::chrono::milliseconds(500));
153       options.SetTrapExceptions(false);
154 
155       AddressRange munmap_range;
156       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
157                              munmap_range)) {
158         lldb::addr_t args[] = {addr, length};
159         lldb::ThreadPlanSP call_plan_sp(
160             new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
161                                        CompilerType(), args, options));
162         if (call_plan_sp) {
163           DiagnosticManager diagnostics;
164 
165           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
166           if (frame) {
167             ExecutionContext exe_ctx;
168             frame->CalculateExecutionContext(exe_ctx);
169             ExpressionResults result = process->RunThreadPlan(
170                 exe_ctx, call_plan_sp, options, diagnostics);
171             if (result == eExpressionCompleted) {
172               return true;
173             }
174           }
175         }
176       }
177     }
178   }
179 
180   return false;
181 }
182 
183 // FIXME: This has nothing to do with Posix, it is just a convenience function
184 // that calls a
185 // function of the form "void * (*)(void)".  We should find a better place to
186 // put this.
187 
InferiorCall(Process * process,const Address * address,addr_t & returned_func,bool trap_exceptions)188 bool lldb_private::InferiorCall(Process *process, const Address *address,
189                                 addr_t &returned_func, bool trap_exceptions) {
190   Thread *thread =
191       process->GetThreadList().GetExpressionExecutionThread().get();
192   if (thread == NULL || address == NULL)
193     return false;
194 
195   EvaluateExpressionOptions options;
196   options.SetStopOthers(true);
197   options.SetUnwindOnError(true);
198   options.SetIgnoreBreakpoints(true);
199   options.SetTryAllThreads(true);
200   options.SetDebug(false);
201   options.SetTimeout(std::chrono::milliseconds(500));
202   options.SetTrapExceptions(trap_exceptions);
203 
204   ClangASTContext *clang_ast_context =
205       process->GetTarget().GetScratchClangASTContext();
206   CompilerType clang_void_ptr_type =
207       clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
208   lldb::ThreadPlanSP call_plan_sp(
209       new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type,
210                                  llvm::ArrayRef<addr_t>(), options));
211   if (call_plan_sp) {
212     DiagnosticManager diagnostics;
213 
214     StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
215     if (frame) {
216       ExecutionContext exe_ctx;
217       frame->CalculateExecutionContext(exe_ctx);
218       ExpressionResults result =
219           process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
220       if (result == eExpressionCompleted) {
221         returned_func =
222             call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
223                 LLDB_INVALID_ADDRESS);
224 
225         if (process->GetAddressByteSize() == 4) {
226           if (returned_func == UINT32_MAX)
227             return false;
228         } else if (process->GetAddressByteSize() == 8) {
229           if (returned_func == UINT64_MAX)
230             return false;
231         }
232         return true;
233       }
234     }
235   }
236 
237   return false;
238 }
239