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