1 //===-- InferiorCallPOSIX.cpp ---------------------------------------------===//
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/Module.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/SymbolContext.h"
17 #include "lldb/Symbol/TypeSystem.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 #if LLDB_ENABLE_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 
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 == nullptr)
43     return false;
44 
45   ModuleFunctionSearchOptions function_options;
46   function_options.include_symbols = true;
47   function_options.include_inlines = false;
48 
49   SymbolContextList sc_list;
50   process->GetTarget().GetImages().FindFunctions(
51       ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list);
52   const uint32_t count = sc_list.GetSize();
53   if (count > 0) {
54     SymbolContext sc;
55     if (sc_list.GetContextAtIndex(0, sc)) {
56       const uint32_t range_scope =
57           eSymbolContextFunction | eSymbolContextSymbol;
58       const bool use_inline_block_range = false;
59       EvaluateExpressionOptions options;
60       options.SetStopOthers(true);
61       options.SetUnwindOnError(true);
62       options.SetIgnoreBreakpoints(true);
63       options.SetTryAllThreads(true);
64       options.SetDebug(false);
65       options.SetTimeout(process->GetUtilityExpressionTimeout());
66       options.SetTrapExceptions(false);
67 
68       addr_t prot_arg;
69       if (prot == eMmapProtNone)
70         prot_arg = PROT_NONE;
71       else {
72         prot_arg = 0;
73         if (prot & eMmapProtExec)
74           prot_arg |= PROT_EXEC;
75         if (prot & eMmapProtRead)
76           prot_arg |= PROT_READ;
77         if (prot & eMmapProtWrite)
78           prot_arg |= PROT_WRITE;
79       }
80 
81       AddressRange mmap_range;
82       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
83                              mmap_range)) {
84         auto type_system_or_err =
85             process->GetTarget().GetScratchTypeSystemForLanguage(
86                 eLanguageTypeC);
87         if (!type_system_or_err) {
88           llvm::consumeError(type_system_or_err.takeError());
89           return false;
90         }
91         CompilerType void_ptr_type =
92             type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid)
93                 .GetPointerType();
94         const ArchSpec arch = process->GetTarget().GetArchitecture();
95         MmapArgList args =
96             process->GetTarget().GetPlatform()->GetMmapArgumentList(
97                 arch, addr, length, prot_arg, flags, fd, offset);
98         lldb::ThreadPlanSP call_plan_sp(
99             new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
100                                        void_ptr_type, args, options));
101         if (call_plan_sp) {
102           DiagnosticManager diagnostics;
103 
104           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
105           if (frame) {
106             ExecutionContext exe_ctx;
107             frame->CalculateExecutionContext(exe_ctx);
108             ExpressionResults result = process->RunThreadPlan(
109                 exe_ctx, call_plan_sp, options, diagnostics);
110             if (result == eExpressionCompleted) {
111 
112               allocated_addr =
113                   call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
114                       LLDB_INVALID_ADDRESS);
115               if (process->GetAddressByteSize() == 4) {
116                 if (allocated_addr == UINT32_MAX)
117                   return false;
118               } else if (process->GetAddressByteSize() == 8) {
119                 if (allocated_addr == UINT64_MAX)
120                   return false;
121               }
122               return true;
123             }
124           }
125         }
126       }
127     }
128   }
129 
130   return false;
131 }
132 
133 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
134                                       addr_t length) {
135   Thread *thread =
136       process->GetThreadList().GetExpressionExecutionThread().get();
137   if (thread == nullptr)
138     return false;
139 
140   ModuleFunctionSearchOptions function_options;
141   function_options.include_symbols = true;
142   function_options.include_inlines = false;
143 
144   SymbolContextList sc_list;
145   process->GetTarget().GetImages().FindFunctions(
146       ConstString("munmap"), eFunctionNameTypeFull, function_options, sc_list);
147   const uint32_t count = sc_list.GetSize();
148   if (count > 0) {
149     SymbolContext sc;
150     if (sc_list.GetContextAtIndex(0, sc)) {
151       const uint32_t range_scope =
152           eSymbolContextFunction | eSymbolContextSymbol;
153       const bool use_inline_block_range = false;
154       EvaluateExpressionOptions options;
155       options.SetStopOthers(true);
156       options.SetUnwindOnError(true);
157       options.SetIgnoreBreakpoints(true);
158       options.SetTryAllThreads(true);
159       options.SetDebug(false);
160       options.SetTimeout(process->GetUtilityExpressionTimeout());
161       options.SetTrapExceptions(false);
162 
163       AddressRange munmap_range;
164       if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
165                              munmap_range)) {
166         lldb::addr_t args[] = {addr, length};
167         lldb::ThreadPlanSP call_plan_sp(
168             new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
169                                        CompilerType(), args, options));
170         if (call_plan_sp) {
171           DiagnosticManager diagnostics;
172 
173           StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
174           if (frame) {
175             ExecutionContext exe_ctx;
176             frame->CalculateExecutionContext(exe_ctx);
177             ExpressionResults result = process->RunThreadPlan(
178                 exe_ctx, call_plan_sp, options, diagnostics);
179             if (result == eExpressionCompleted) {
180               return true;
181             }
182           }
183         }
184       }
185     }
186   }
187 
188   return false;
189 }
190