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