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/ValueObject.h"
13#include "lldb/Expression/DiagnosticManager.h"
14#include "lldb/Host/Config.h"
15#include "lldb/Symbol/SymbolContext.h"
16#include "lldb/Symbol/TypeSystem.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#if LLDB_ENABLE_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
33using namespace lldb;
34using namespace lldb_private;
35
36bool 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 ModuleFunctionSearchOptions function_options;
45 function_options.include_symbols = true;
46 function_options.include_inlines = false;
47
48 SymbolContextList sc_list;
49 process->GetTarget().GetImages().FindFunctions(
50 name: ConstString("mmap"), name_type_mask: eFunctionNameTypeFull, options: function_options, sc_list);
51 const uint32_t count = sc_list.GetSize();
52 if (count > 0) {
53 SymbolContext sc;
54 if (sc_list.GetContextAtIndex(idx: 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(process->GetUtilityExpressionTimeout());
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(scope: range_scope, range_idx: 0, use_inline_block_range,
82 range&: mmap_range)) {
83 auto type_system_or_err =
84 process->GetTarget().GetScratchTypeSystemForLanguage(
85 language: eLanguageTypeC);
86 if (!type_system_or_err) {
87 llvm::consumeError(Err: type_system_or_err.takeError());
88 return false;
89 }
90 auto ts = *type_system_or_err;
91 if (!ts)
92 return false;
93 CompilerType void_ptr_type =
94 ts->GetBasicTypeFromAST(basic_type: eBasicTypeVoid).GetPointerType();
95 const ArchSpec arch = process->GetTarget().GetArchitecture();
96 MmapArgList args =
97 process->GetTarget().GetPlatform()->GetMmapArgumentList(
98 arch, addr, length, prot: prot_arg, flags, fd, offset);
99 lldb::ThreadPlanSP call_plan_sp(
100 new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
101 void_ptr_type, args, options));
102 if (call_plan_sp) {
103 DiagnosticManager diagnostics;
104
105 StackFrame *frame = thread->GetStackFrameAtIndex(idx: 0).get();
106 if (frame) {
107 ExecutionContext exe_ctx;
108 frame->CalculateExecutionContext(exe_ctx);
109 ExpressionResults result = process->RunThreadPlan(
110 exe_ctx, thread_plan_sp&: call_plan_sp, options, diagnostic_manager&: diagnostics);
111 if (result == eExpressionCompleted) {
112
113 allocated_addr =
114 call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
115 LLDB_INVALID_ADDRESS);
116 if (process->GetAddressByteSize() == 4) {
117 if (allocated_addr == UINT32_MAX)
118 return false;
119 } else if (process->GetAddressByteSize() == 8) {
120 if (allocated_addr == UINT64_MAX)
121 return false;
122 }
123 return true;
124 }
125 }
126 }
127 }
128 }
129 }
130
131 return false;
132}
133
134bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
135 addr_t length) {
136 Thread *thread =
137 process->GetThreadList().GetExpressionExecutionThread().get();
138 if (thread == nullptr)
139 return false;
140
141 ModuleFunctionSearchOptions function_options;
142 function_options.include_symbols = true;
143 function_options.include_inlines = false;
144
145 SymbolContextList sc_list;
146 process->GetTarget().GetImages().FindFunctions(
147 name: ConstString("munmap"), name_type_mask: eFunctionNameTypeFull, options: function_options, sc_list);
148 const uint32_t count = sc_list.GetSize();
149 if (count > 0) {
150 SymbolContext sc;
151 if (sc_list.GetContextAtIndex(idx: 0, sc)) {
152 const uint32_t range_scope =
153 eSymbolContextFunction | eSymbolContextSymbol;
154 const bool use_inline_block_range = false;
155 EvaluateExpressionOptions options;
156 options.SetStopOthers(true);
157 options.SetUnwindOnError(true);
158 options.SetIgnoreBreakpoints(true);
159 options.SetTryAllThreads(true);
160 options.SetDebug(false);
161 options.SetTimeout(process->GetUtilityExpressionTimeout());
162 options.SetTrapExceptions(false);
163
164 AddressRange munmap_range;
165 if (sc.GetAddressRange(scope: range_scope, range_idx: 0, use_inline_block_range,
166 range&: munmap_range)) {
167 lldb::addr_t args[] = {addr, length};
168 lldb::ThreadPlanSP call_plan_sp(
169 new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
170 CompilerType(), args, options));
171 if (call_plan_sp) {
172 DiagnosticManager diagnostics;
173
174 StackFrame *frame = thread->GetStackFrameAtIndex(idx: 0).get();
175 if (frame) {
176 ExecutionContext exe_ctx;
177 frame->CalculateExecutionContext(exe_ctx);
178 ExpressionResults result = process->RunThreadPlan(
179 exe_ctx, thread_plan_sp&: call_plan_sp, options, diagnostic_manager&: diagnostics);
180 if (result == eExpressionCompleted) {
181 return true;
182 }
183 }
184 }
185 }
186 }
187 }
188
189 return false;
190}
191

source code of lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp