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
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 == 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
InferiorCallMunmap(Process * process,addr_t addr,addr_t length)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