InferiorCallPOSIX.cpp revision 353358
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"
15254721Semaste#include "lldb/Symbol/ClangASTContext.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
23258054Semaste#ifndef LLDB_DISABLE_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 append = true;
45314564Sdim  const bool include_symbols = true;
46314564Sdim  const bool include_inlines = false;
47314564Sdim  SymbolContextList sc_list;
48314564Sdim  const uint32_t count = process->GetTarget().GetImages().FindFunctions(
49314564Sdim      ConstString("mmap"), eFunctionNameTypeFull, include_symbols,
50314564Sdim      include_inlines, append, sc_list);
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)) {
82314564Sdim        ClangASTContext *clang_ast_context =
83314564Sdim            process->GetTarget().GetScratchClangASTContext();
84314564Sdim        CompilerType clang_void_ptr_type =
85314564Sdim            clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
86322326Semaste        const ArchSpec arch = process->GetTarget().GetArchitecture();
87322326Semaste        MmapArgList args =
88322326Semaste            process->GetTarget().GetPlatform()->GetMmapArgumentList(
89322326Semaste                arch, addr, length, prot_arg, flags, fd, offset);
90314564Sdim        lldb::ThreadPlanSP call_plan_sp(
91314564Sdim            new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
92314564Sdim                                       clang_void_ptr_type, args, options));
93314564Sdim        if (call_plan_sp) {
94314564Sdim          DiagnosticManager diagnostics;
95309124Sdim
96314564Sdim          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
97314564Sdim          if (frame) {
98314564Sdim            ExecutionContext exe_ctx;
99314564Sdim            frame->CalculateExecutionContext(exe_ctx);
100314564Sdim            ExpressionResults result = process->RunThreadPlan(
101314564Sdim                exe_ctx, call_plan_sp, options, diagnostics);
102314564Sdim            if (result == eExpressionCompleted) {
103309124Sdim
104314564Sdim              allocated_addr =
105314564Sdim                  call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
106314564Sdim                      LLDB_INVALID_ADDRESS);
107314564Sdim              if (process->GetAddressByteSize() == 4) {
108314564Sdim                if (allocated_addr == UINT32_MAX)
109314564Sdim                  return false;
110314564Sdim              } else if (process->GetAddressByteSize() == 8) {
111314564Sdim                if (allocated_addr == UINT64_MAX)
112314564Sdim                  return false;
113314564Sdim              }
114314564Sdim              return true;
115254721Semaste            }
116314564Sdim          }
117254721Semaste        }
118314564Sdim      }
119254721Semaste    }
120314564Sdim  }
121254721Semaste
122314564Sdim  return false;
123254721Semaste}
124254721Semaste
125314564Sdimbool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
126314564Sdim                                      addr_t length) {
127314564Sdim  Thread *thread =
128314564Sdim      process->GetThreadList().GetExpressionExecutionThread().get();
129353358Sdim  if (thread == nullptr)
130314564Sdim    return false;
131309124Sdim
132314564Sdim  const bool append = true;
133314564Sdim  const bool include_symbols = true;
134314564Sdim  const bool include_inlines = false;
135314564Sdim  SymbolContextList sc_list;
136314564Sdim  const uint32_t count = process->GetTarget().GetImages().FindFunctions(
137314564Sdim      ConstString("munmap"), eFunctionNameTypeFull, include_symbols,
138314564Sdim      include_inlines, append, sc_list);
139314564Sdim  if (count > 0) {
140314564Sdim    SymbolContext sc;
141314564Sdim    if (sc_list.GetContextAtIndex(0, sc)) {
142314564Sdim      const uint32_t range_scope =
143314564Sdim          eSymbolContextFunction | eSymbolContextSymbol;
144314564Sdim      const bool use_inline_block_range = false;
145314564Sdim      EvaluateExpressionOptions options;
146314564Sdim      options.SetStopOthers(true);
147314564Sdim      options.SetUnwindOnError(true);
148314564Sdim      options.SetIgnoreBreakpoints(true);
149314564Sdim      options.SetTryAllThreads(true);
150314564Sdim      options.SetDebug(false);
151353358Sdim      options.SetTimeout(process->GetUtilityExpressionTimeout());
152314564Sdim      options.SetTrapExceptions(false);
153314564Sdim
154314564Sdim      AddressRange munmap_range;
155314564Sdim      if (sc.GetAddressRange(range_scope, 0, use_inline_block_range,
156314564Sdim                             munmap_range)) {
157314564Sdim        lldb::addr_t args[] = {addr, length};
158314564Sdim        lldb::ThreadPlanSP call_plan_sp(
159314564Sdim            new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(),
160314564Sdim                                       CompilerType(), args, options));
161314564Sdim        if (call_plan_sp) {
162314564Sdim          DiagnosticManager diagnostics;
163314564Sdim
164314564Sdim          StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
165314564Sdim          if (frame) {
166314564Sdim            ExecutionContext exe_ctx;
167314564Sdim            frame->CalculateExecutionContext(exe_ctx);
168314564Sdim            ExpressionResults result = process->RunThreadPlan(
169314564Sdim                exe_ctx, call_plan_sp, options, diagnostics);
170314564Sdim            if (result == eExpressionCompleted) {
171314564Sdim              return true;
172258884Semaste            }
173314564Sdim          }
174258884Semaste        }
175314564Sdim      }
176258884Semaste    }
177314564Sdim  }
178254721Semaste
179314564Sdim  return false;
180254721Semaste}
181254721Semaste
182314564Sdim// FIXME: This has nothing to do with Posix, it is just a convenience function
183314564Sdim// that calls a
184314564Sdim// function of the form "void * (*)(void)".  We should find a better place to
185314564Sdim// put this.
186262528Semaste
187314564Sdimbool lldb_private::InferiorCall(Process *process, const Address *address,
188314564Sdim                                addr_t &returned_func, bool trap_exceptions) {
189314564Sdim  Thread *thread =
190314564Sdim      process->GetThreadList().GetExpressionExecutionThread().get();
191353358Sdim  if (thread == nullptr || address == nullptr)
192314564Sdim    return false;
193254721Semaste
194314564Sdim  EvaluateExpressionOptions options;
195314564Sdim  options.SetStopOthers(true);
196314564Sdim  options.SetUnwindOnError(true);
197314564Sdim  options.SetIgnoreBreakpoints(true);
198314564Sdim  options.SetTryAllThreads(true);
199314564Sdim  options.SetDebug(false);
200353358Sdim  options.SetTimeout(process->GetUtilityExpressionTimeout());
201314564Sdim  options.SetTrapExceptions(trap_exceptions);
202254721Semaste
203314564Sdim  ClangASTContext *clang_ast_context =
204314564Sdim      process->GetTarget().GetScratchClangASTContext();
205314564Sdim  CompilerType clang_void_ptr_type =
206314564Sdim      clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
207314564Sdim  lldb::ThreadPlanSP call_plan_sp(
208314564Sdim      new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type,
209314564Sdim                                 llvm::ArrayRef<addr_t>(), options));
210314564Sdim  if (call_plan_sp) {
211314564Sdim    DiagnosticManager diagnostics;
212254721Semaste
213314564Sdim    StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
214314564Sdim    if (frame) {
215314564Sdim      ExecutionContext exe_ctx;
216314564Sdim      frame->CalculateExecutionContext(exe_ctx);
217314564Sdim      ExpressionResults result =
218314564Sdim          process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);
219314564Sdim      if (result == eExpressionCompleted) {
220314564Sdim        returned_func =
221314564Sdim            call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(
222314564Sdim                LLDB_INVALID_ADDRESS);
223254721Semaste
224314564Sdim        if (process->GetAddressByteSize() == 4) {
225314564Sdim          if (returned_func == UINT32_MAX)
226314564Sdim            return false;
227314564Sdim        } else if (process->GetAddressByteSize() == 8) {
228314564Sdim          if (returned_func == UINT64_MAX)
229314564Sdim            return false;
230254721Semaste        }
231314564Sdim        return true;
232314564Sdim      }
233254721Semaste    }
234314564Sdim  }
235254721Semaste
236314564Sdim  return false;
237254721Semaste}
238