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 
33 using namespace lldb;
34 using namespace lldb_private;
35 
InferiorCallMmap(Process * process,addr_t & allocated_addr,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)36 bool 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       ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list);
51   const uint32_t count = sc_list.GetSize();
52   if (count > 0) {
53     SymbolContext sc;
54     if (sc_list.GetContextAtIndex(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(range_scope, 0, use_inline_block_range,
82                              mmap_range)) {
83         auto type_system_or_err =
84             process->GetTarget().GetScratchTypeSystemForLanguage(
85                 eLanguageTypeC);
86         if (!type_system_or_err) {
87           llvm::consumeError(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(eBasicTypeVoid).GetPointerType();
95         const ArchSpec arch = process->GetTarget().GetArchitecture();
96         MmapArgList args =
97             process->GetTarget().GetPlatform()->GetMmapArgumentList(
98                 arch, addr, length, 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(0).get();
106           if (frame) {
107             ExecutionContext exe_ctx;
108             frame->CalculateExecutionContext(exe_ctx);
109             ExpressionResults result = process->RunThreadPlan(
110                 exe_ctx, call_plan_sp, options, 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 
InferiorCallMunmap(Process * process,addr_t addr,addr_t length)134 bool 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       ConstString("munmap"), eFunctionNameTypeFull, function_options, sc_list);
148   const uint32_t count = sc_list.GetSize();
149   if (count > 0) {
150     SymbolContext sc;
151     if (sc_list.GetContextAtIndex(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(range_scope, 0, use_inline_block_range,
166                              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(0).get();
175           if (frame) {
176             ExecutionContext exe_ctx;
177             frame->CalculateExecutionContext(exe_ctx);
178             ExpressionResults result = process->RunThreadPlan(
179                 exe_ctx, call_plan_sp, options, diagnostics);
180             if (result == eExpressionCompleted) {
181               return true;
182             }
183           }
184         }
185       }
186     }
187   }
188 
189   return false;
190 }
191