1254721Semaste//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "InferiorCallPOSIX.h"
10254721Semaste#include "lldb/Core/Address.h"
11254721Semaste#include "lldb/Core/StreamFile.h"
12254721Semaste#include "lldb/Core/ValueObject.h"
13309124Sdim#include "lldb/Expression/DiagnosticManager.h"
14309124Sdim#include "lldb/Host/Config.h"
15360784Sdim#include "lldb/Symbol/TypeSystem.h"
16254721Semaste#include "lldb/Symbol/SymbolContext.h"
17254721Semaste#include "lldb/Target/ExecutionContext.h"
18288943Sdim#include "lldb/Target/Platform.h"
19254721Semaste#include "lldb/Target/Process.h"
20254721Semaste#include "lldb/Target/Target.h"
21254721Semaste#include "lldb/Target/ThreadPlanCallFunction.h"
22254721Semaste
23360784Sdim#if LLDB_ENABLE_POSIX
24254721Semaste#include <sys/mman.h>
25258054Semaste#else
26258054Semaste// define them
27258054Semaste#define PROT_NONE 0
28258054Semaste#define PROT_READ 1
29258054Semaste#define PROT_WRITE 2
30258054Semaste#define PROT_EXEC 4
31258054Semaste#endif
32254721Semaste
33254721Semasteusing namespace lldb;
34254721Semasteusing namespace lldb_private;
35254721Semaste
36314564Sdimbool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
37314564Sdim                                    addr_t addr, addr_t length, unsigned prot,
38314564Sdim                                    unsigned flags, addr_t fd, addr_t offset) {
39314564Sdim  Thread *thread =
40314564Sdim      process->GetThreadList().GetExpressionExecutionThread().get();
41353358Sdim  if (thread == nullptr)
42314564Sdim    return false;
43254721Semaste
44314564Sdim  const bool include_symbols = true;
45314564Sdim  const bool include_inlines = false;
46314564Sdim  SymbolContextList sc_list;
47360784Sdim  process->GetTarget().GetImages().FindFunctions(
48314564Sdim      ConstString("mmap"), eFunctionNameTypeFull, include_symbols,
49360784Sdim      include_inlines, sc_list);
50360784Sdim  const uint32_t count = sc_list.GetSize();
51314564Sdim  if (count > 0) {
52314564Sdim    SymbolContext sc;
53314564Sdim    if (sc_list.GetContextAtIndex(0, sc)) {
54314564Sdim      const uint32_t range_scope =
55314564Sdim          eSymbolContextFunction | eSymbolContextSymbol;
56314564Sdim      const bool use_inline_block_range = false;
57314564Sdim      EvaluateExpressionOptions options;
58314564Sdim      options.SetStopOthers(true);
59314564Sdim      options.SetUnwindOnError(true);
60314564Sdim      options.SetIgnoreBreakpoints(true);
61314564Sdim      options.SetTryAllThreads(true);
62314564Sdim      options.SetDebug(false);
63353358Sdim      options.SetTimeout(process->GetUtilityExpressionTimeout());
64314564Sdim      options.SetTrapExceptions(false);
65254721Semaste
66322326Semaste      addr_t prot_arg;
67314564Sdim      if (prot == eMmapProtNone)
68314564Sdim        prot_arg = PROT_NONE;
69314564Sdim      else {
70314564Sdim        prot_arg = 0;
71314564Sdim        if (prot & eMmapProtExec)
72314564Sdim          prot_arg |= PROT_EXEC;
73314564Sdim        if (prot & eMmapProtRead)
74314564Sdim          prot_arg |= PROT_READ;
75314564Sdim        if (prot & eMmapProtWrite)
76314564Sdim          prot_arg |= PROT_WRITE;
77314564Sdim      }
78254721Semaste
79314564Sdim      AddressRange mmap_range;
80314564Sdim      if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
81314564Sdim                             mmap_range)) {
82360784Sdim        auto type_system_or_err =
83360784Sdim            process->GetTarget().GetScratchTypeSystemForLanguage(
84360784Sdim                eLanguageTypeC);
85360784Sdim        if (!type_system_or_err) {
86360784Sdim          llvm::consumeError(type_system_or_err.takeError());
87360784Sdim          return false;
88360784Sdim        }
89360784Sdim        CompilerType void_ptr_type =
90360784Sdim            type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid)
91360784Sdim                .GetPointerType();
92322326Semaste        const ArchSpec arch = process->GetTarget().GetArchitecture();
93322326Semaste        MmapArgList args =
94322326Semaste            process->GetTarget().GetPlatform()->GetMmapArgumentList(
95322326Semaste                arch, addr, length, prot_arg, flags, fd, offset);
96314564Sdim        lldb::ThreadPlanSP call_plan_sp(
97314564Sdim            new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
98360784Sdim                                       void_ptr_type, args, options));
99314564Sdim        if (call_plan_sp) {
100314564Sdim          DiagnosticManager diagnostics;
101309124Sdim
102314564Sdim          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
103314564Sdim          if (frame) {
104314564Sdim            ExecutionContext exe_ctx;
105314564Sdim            frame->CalculateExecutionContext(exe_ctx);
106314564Sdim            ExpressionResults result = process->RunThreadPlan(
107314564Sdim                exe_ctx, call_plan_sp, options, diagnostics);
108314564Sdim            if (result == eExpressionCompleted) {
109309124Sdim
110314564Sdim              allocated_addr =
111314564Sdim                  call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
112314564Sdim                      LLDB_INVALID_ADDRESS);
113314564Sdim              if (process->GetAddressByteSize() == 4) {
114314564Sdim                if (allocated_addr == UINT32_MAX)
115314564Sdim                  return false;
116314564Sdim              } else if (process->GetAddressByteSize() == 8) {
117314564Sdim                if (allocated_addr == UINT64_MAX)
118314564Sdim                  return false;
119314564Sdim              }
120314564Sdim              return true;
121254721Semaste            }
122314564Sdim          }
123254721Semaste        }
124314564Sdim      }
125254721Semaste    }
126314564Sdim  }
127254721Semaste
128314564Sdim  return false;
129254721Semaste}
130254721Semaste
131314564Sdimbool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
132314564Sdim                                      addr_t length) {
133314564Sdim  Thread *thread =
134314564Sdim      process->GetThreadList().GetExpressionExecutionThread().get();
135353358Sdim  if (thread == nullptr)
136314564Sdim    return false;
137309124Sdim
138314564Sdim  const bool include_symbols = true;
139314564Sdim  const bool include_inlines = false;
140314564Sdim  SymbolContextList sc_list;
141360784Sdim  process->GetTarget().GetImages().FindFunctions(
142314564Sdim      ConstString("munmap"), eFunctionNameTypeFull, include_symbols,
143360784Sdim      include_inlines, sc_list);
144360784Sdim  const uint32_t count = sc_list.GetSize();
145314564Sdim  if (count > 0) {
146314564Sdim    SymbolContext sc;
147314564Sdim    if (sc_list.GetContextAtIndex(0, sc)) {
148314564Sdim      const uint32_t range_scope =
149314564Sdim          eSymbolContextFunction | eSymbolContextSymbol;
150314564Sdim      const bool use_inline_block_range = false;
151314564Sdim      EvaluateExpressionOptions options;
152314564Sdim      options.SetStopOthers(true);
153314564Sdim      options.SetUnwindOnError(true);
154314564Sdim      options.SetIgnoreBreakpoints(true);
155314564Sdim      options.SetTryAllThreads(true);
156314564Sdim      options.SetDebug(false);
157353358Sdim      options.SetTimeout(process->GetUtilityExpressionTimeout());
158314564Sdim      options.SetTrapExceptions(false);
159314564Sdim
160314564Sdim      AddressRange munmap_range;
161314564Sdim      if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
162314564Sdim                             munmap_range)) {
163314564Sdim        lldb::addr_t args[] = {addr, length};
164314564Sdim        lldb::ThreadPlanSP call_plan_sp(
165314564Sdim            new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
166314564Sdim                                       CompilerType(), args, options));
167314564Sdim        if (call_plan_sp) {
168314564Sdim          DiagnosticManager diagnostics;
169314564Sdim
170314564Sdim          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
171314564Sdim          if (frame) {
172314564Sdim            ExecutionContext exe_ctx;
173314564Sdim            frame->CalculateExecutionContext(exe_ctx);
174314564Sdim            ExpressionResults result = process->RunThreadPlan(
175314564Sdim                exe_ctx, call_plan_sp, options, diagnostics);
176314564Sdim            if (result == eExpressionCompleted) {
177314564Sdim              return true;
178258884Semaste            }
179314564Sdim          }
180258884Semaste        }
181314564Sdim      }
182258884Semaste    }
183314564Sdim  }
184254721Semaste
185314564Sdim  return false;
186254721Semaste}
187