1//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===//
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/StreamFile.h"
12#include "lldb/Core/ValueObject.h"
13#include "lldb/Expression/DiagnosticManager.h"
14#include "lldb/Host/Config.h"
15#include "lldb/Symbol/TypeSystem.h"
16#include "lldb/Symbol/SymbolContext.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  const bool include_symbols = true;
45  const bool include_inlines = false;
46  SymbolContextList sc_list;
47  process->GetTarget().GetImages().FindFunctions(
48      ConstString("mmap"), eFunctionNameTypeFull, include_symbols,
49      include_inlines, sc_list);
50  const uint32_t count = sc_list.GetSize();
51  if (count > 0) {
52    SymbolContext sc;
53    if (sc_list.GetContextAtIndex(0, sc)) {
54      const uint32_t range_scope =
55          eSymbolContextFunction | eSymbolContextSymbol;
56      const bool use_inline_block_range = false;
57      EvaluateExpressionOptions options;
58      options.SetStopOthers(true);
59      options.SetUnwindOnError(true);
60      options.SetIgnoreBreakpoints(true);
61      options.SetTryAllThreads(true);
62      options.SetDebug(false);
63      options.SetTimeout(process->GetUtilityExpressionTimeout());
64      options.SetTrapExceptions(false);
65
66      addr_t prot_arg;
67      if (prot == eMmapProtNone)
68        prot_arg = PROT_NONE;
69      else {
70        prot_arg = 0;
71        if (prot & eMmapProtExec)
72          prot_arg |= PROT_EXEC;
73        if (prot & eMmapProtRead)
74          prot_arg |= PROT_READ;
75        if (prot & eMmapProtWrite)
76          prot_arg |= PROT_WRITE;
77      }
78
79      AddressRange mmap_range;
80      if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
81                             mmap_range)) {
82        auto type_system_or_err =
83            process->GetTarget().GetScratchTypeSystemForLanguage(
84                eLanguageTypeC);
85        if (!type_system_or_err) {
86          llvm::consumeError(type_system_or_err.takeError());
87          return false;
88        }
89        CompilerType void_ptr_type =
90            type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid)
91                .GetPointerType();
92        const ArchSpec arch = process->GetTarget().GetArchitecture();
93        MmapArgList args =
94            process->GetTarget().GetPlatform()->GetMmapArgumentList(
95                arch, addr, length, prot_arg, flags, fd, offset);
96        lldb::ThreadPlanSP call_plan_sp(
97            new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
98                                       void_ptr_type, args, options));
99        if (call_plan_sp) {
100          DiagnosticManager diagnostics;
101
102          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
103          if (frame) {
104            ExecutionContext exe_ctx;
105            frame->CalculateExecutionContext(exe_ctx);
106            ExpressionResults result = process->RunThreadPlan(
107                exe_ctx, call_plan_sp, options, diagnostics);
108            if (result == eExpressionCompleted) {
109
110              allocated_addr =
111                  call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
112                      LLDB_INVALID_ADDRESS);
113              if (process->GetAddressByteSize() == 4) {
114                if (allocated_addr == UINT32_MAX)
115                  return false;
116              } else if (process->GetAddressByteSize() == 8) {
117                if (allocated_addr == UINT64_MAX)
118                  return false;
119              }
120              return true;
121            }
122          }
123        }
124      }
125    }
126  }
127
128  return false;
129}
130
131bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
132                                      addr_t length) {
133  Thread *thread =
134      process->GetThreadList().GetExpressionExecutionThread().get();
135  if (thread == nullptr)
136    return false;
137
138  const bool include_symbols = true;
139  const bool include_inlines = false;
140  SymbolContextList sc_list;
141  process->GetTarget().GetImages().FindFunctions(
142      ConstString("munmap"), eFunctionNameTypeFull, include_symbols,
143      include_inlines, sc_list);
144  const uint32_t count = sc_list.GetSize();
145  if (count > 0) {
146    SymbolContext sc;
147    if (sc_list.GetContextAtIndex(0, sc)) {
148      const uint32_t range_scope =
149          eSymbolContextFunction | eSymbolContextSymbol;
150      const bool use_inline_block_range = false;
151      EvaluateExpressionOptions options;
152      options.SetStopOthers(true);
153      options.SetUnwindOnError(true);
154      options.SetIgnoreBreakpoints(true);
155      options.SetTryAllThreads(true);
156      options.SetDebug(false);
157      options.SetTimeout(process->GetUtilityExpressionTimeout());
158      options.SetTrapExceptions(false);
159
160      AddressRange munmap_range;
161      if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
162                             munmap_range)) {
163        lldb::addr_t args[] = {addr, length};
164        lldb::ThreadPlanSP call_plan_sp(
165            new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
166                                       CompilerType(), args, options));
167        if (call_plan_sp) {
168          DiagnosticManager diagnostics;
169
170          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
171          if (frame) {
172            ExecutionContext exe_ctx;
173            frame->CalculateExecutionContext(exe_ctx);
174            ExpressionResults result = process->RunThreadPlan(
175                exe_ctx, call_plan_sp, options, diagnostics);
176            if (result == eExpressionCompleted) {
177              return true;
178            }
179          }
180        }
181      }
182    }
183  }
184
185  return false;
186}
187