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 auto ts = *type_system_or_err;
92 if (!ts)
93 return false;
94 CompilerType void_ptr_type =
95 ts->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
96 const ArchSpec arch = process->GetTarget().GetArchitecture();
97 MmapArgList args =
98 process->GetTarget().GetPlatform()->GetMmapArgumentList(
99 arch, addr, length, prot_arg, flags, fd, offset);
100 lldb::ThreadPlanSP call_plan_sp(
101 new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
102 void_ptr_type, args, options));
103 if (call_plan_sp) {
104 DiagnosticManager diagnostics;
105
106 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
107 if (frame) {
108 ExecutionContext exe_ctx;
109 frame->CalculateExecutionContext(exe_ctx);
110 ExpressionResults result = process->RunThreadPlan(
111 exe_ctx, call_plan_sp, options, diagnostics);
112 if (result == eExpressionCompleted) {
113
114 allocated_addr =
115 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
116 LLDB_INVALID_ADDRESS);
117 if (process->GetAddressByteSize() == 4) {
118 if (allocated_addr == UINT32_MAX)
119 return false;
120 } else if (process->GetAddressByteSize() == 8) {
121 if (allocated_addr == UINT64_MAX)
122 return false;
123 }
124 return true;
125 }
126 }
127 }
128 }
129 }
130 }
131
132 return false;
133 }
134
InferiorCallMunmap(Process * process,addr_t addr,addr_t length)135 bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
136 addr_t length) {
137 Thread *thread =
138 process->GetThreadList().GetExpressionExecutionThread().get();
139 if (thread == nullptr)
140 return false;
141
142 ModuleFunctionSearchOptions function_options;
143 function_options.include_symbols = true;
144 function_options.include_inlines = false;
145
146 SymbolContextList sc_list;
147 process->GetTarget().GetImages().FindFunctions(
148 ConstString("munmap"), eFunctionNameTypeFull, function_options, sc_list);
149 const uint32_t count = sc_list.GetSize();
150 if (count > 0) {
151 SymbolContext sc;
152 if (sc_list.GetContextAtIndex(0, sc)) {
153 const uint32_t range_scope =
154 eSymbolContextFunction | eSymbolContextSymbol;
155 const bool use_inline_block_range = false;
156 EvaluateExpressionOptions options;
157 options.SetStopOthers(true);
158 options.SetUnwindOnError(true);
159 options.SetIgnoreBreakpoints(true);
160 options.SetTryAllThreads(true);
161 options.SetDebug(false);
162 options.SetTimeout(process->GetUtilityExpressionTimeout());
163 options.SetTrapExceptions(false);
164
165 AddressRange munmap_range;
166 if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
167 munmap_range)) {
168 lldb::addr_t args[] = {addr, length};
169 lldb::ThreadPlanSP call_plan_sp(
170 new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
171 CompilerType(), args, options));
172 if (call_plan_sp) {
173 DiagnosticManager diagnostics;
174
175 StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
176 if (frame) {
177 ExecutionContext exe_ctx;
178 frame->CalculateExecutionContext(exe_ctx);
179 ExpressionResults result = process->RunThreadPlan(
180 exe_ctx, call_plan_sp, options, diagnostics);
181 if (result == eExpressionCompleted) {
182 return true;
183 }
184 }
185 }
186 }
187 }
188 }
189
190 return false;
191 }
192