Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ClangUtilityFunction.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 "ClangUtilityFunction.h"
10
#include "ClangExpressionDeclMap.h"
11
#include "ClangExpressionParser.h"
12
#include "ClangExpressionSourceCode.h"
13
#include "ClangPersistentVariables.h"
14
15
#include <cstdio>
16
#include <sys/types.h>
17
18
19
#include "lldb/Core/Module.h"
20
#include "lldb/Core/StreamFile.h"
21
#include "lldb/Expression/IRExecutionUnit.h"
22
#include "lldb/Host/Host.h"
23
#include "lldb/Target/ExecutionContext.h"
24
#include "lldb/Target/Target.h"
25
#include "lldb/Utility/ConstString.h"
26
#include "lldb/Utility/Log.h"
27
#include "lldb/Utility/Stream.h"
28
29
using namespace lldb_private;
30
31
char ClangUtilityFunction::ID;
32
33
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
34
                                           std::string text, std::string name,
35
                                           bool enable_debugging)
36
    : UtilityFunction(
37
          exe_scope,
38
          std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
39
              std::string(ClangExpressionSourceCode::g_expression_suffix),
40
3.41k
          std::move(name), enable_debugging) {
41
  // Write the source code to a file so that LLDB's source manager can display
42
  // it when debugging the code.
43
3.41k
  if (enable_debugging) {
44
0
    int temp_fd = -1;
45
0
    llvm::SmallString<128> result_path;
46
0
    llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
47
0
    if (temp_fd != -1) {
48
0
      lldb_private::NativeFile file(temp_fd, File::eOpenOptionWriteOnly, true);
49
0
      text = "#line 1 \"" + std::string(result_path) + "\"\n" + text;
50
0
      size_t bytes_written = text.size();
51
0
      file.Write(text.c_str(), bytes_written);
52
0
      if (bytes_written == text.size()) {
53
        // If we successfully wrote the source to a temporary file, replace the
54
        // function text with the next text containing the line directive.
55
0
        m_function_text =
56
0
            std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
57
0
            std::string(ClangExpressionSourceCode::g_expression_suffix);
58
0
      }
59
0
      file.Close();
60
0
    }
61
0
  }
62
3.41k
}
63
64
3.41k
ClangUtilityFunction::~ClangUtilityFunction() = default;
65
66
/// Install the utility function into a process
67
///
68
/// \param[in] diagnostic_manager
69
///     A diagnostic manager to report errors and warnings to.
70
///
71
/// \param[in] exe_ctx
72
///     The execution context to install the utility function to.
73
///
74
/// \return
75
///     True on success (no errors); false otherwise.
76
bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
77
3.41k
                                   ExecutionContext &exe_ctx) {
78
3.41k
  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
79
0
    diagnostic_manager.PutString(eDiagnosticSeverityWarning,
80
0
                                 "already installed");
81
0
    return false;
82
0
  }
83
84
  ////////////////////////////////////
85
  // Set up the target and compiler
86
  //
87
88
3.41k
  Target *target = exe_ctx.GetTargetPtr();
89
90
3.41k
  if (!target) {
91
0
    diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
92
0
    return false;
93
0
  }
94
95
3.41k
  Process *process = exe_ctx.GetProcessPtr();
96
97
3.41k
  if (!process) {
98
0
    diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid process");
99
0
    return false;
100
0
  }
101
102
  //////////////////////////
103
  // Parse the expression
104
  //
105
106
3.41k
  bool keep_result_in_memory = false;
107
108
3.41k
  ResetDeclMap(exe_ctx, keep_result_in_memory);
109
110
3.41k
  if (!DeclMap()->WillParse(exe_ctx, nullptr)) {
111
0
    diagnostic_manager.PutString(
112
0
        eDiagnosticSeverityError,
113
0
        "current process state is unsuitable for expression parsing");
114
0
    return false;
115
0
  }
116
117
3.41k
  const bool generate_debug_info = true;
118
3.41k
  ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
119
3.41k
                               generate_debug_info);
120
121
3.41k
  unsigned num_errors = parser.Parse(diagnostic_manager);
122
123
3.41k
  if (num_errors) {
124
0
    ResetDeclMap();
125
126
0
    return false;
127
0
  }
128
129
  //////////////////////////////////
130
  // JIT the output of the parser
131
  //
132
133
3.41k
  bool can_interpret = false; // should stay that way
134
135
3.41k
  Status jit_error = parser.PrepareForExecution(
136
3.41k
      m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
137
3.41k
      can_interpret, eExecutionPolicyAlways);
138
139
3.41k
  if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
140
3.41k
    m_jit_process_wp = process->shared_from_this();
141
3.41k
    if (parser.GetGenerateDebugInfo()) {
142
3.41k
      lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
143
144
3.41k
      if (jit_module_sp) {
145
3.41k
        ConstString const_func_name(FunctionName());
146
3.41k
        FileSpec jit_file;
147
3.41k
        jit_file.GetFilename() = const_func_name;
148
3.41k
        jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
149
3.41k
        m_jit_module_wp = jit_module_sp;
150
3.41k
        target->GetImages().Append(jit_module_sp);
151
3.41k
      }
152
3.41k
    }
153
3.41k
  }
154
155
3.41k
  DeclMap()->DidParse();
156
157
3.41k
  ResetDeclMap();
158
159
3.41k
  if (jit_error.Success()) {
160
3.41k
    return true;
161
3.41k
  } else {
162
0
    const char *error_cstr = jit_error.AsCString();
163
0
    if (error_cstr && error_cstr[0]) {
164
0
      diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
165
0
    } else {
166
0
      diagnostic_manager.PutString(eDiagnosticSeverityError,
167
0
                                   "expression can't be interpreted or run");
168
0
    }
169
0
    return false;
170
0
  }
171
3.41k
}
172
173
void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
174
3.41k
    ExecutionContext &exe_ctx, bool keep_result_in_memory) {
175
3.41k
  std::shared_ptr<ClangASTImporter> ast_importer;
176
3.41k
  auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
177
3.41k
      lldb::eLanguageTypeC);
178
3.41k
  if (state) {
179
3.41k
    auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
180
3.41k
    ast_importer = persistent_vars->GetClangASTImporter();
181
3.41k
  }
182
3.41k
  m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
183
3.41k
      keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(), ast_importer,
184
3.41k
      nullptr);
185
3.41k
}