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         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 
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