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