You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
5.1 KiB
173 lines
5.1 KiB
4 months ago
|
//===-- ClangUtilityFunction.cpp ------------------------------------------===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "lldb/Host/Config.h"
|
||
|
|
||
|
#include "ClangUtilityFunction.h"
|
||
|
#include "ClangExpressionDeclMap.h"
|
||
|
#include "ClangExpressionParser.h"
|
||
|
#include "ClangExpressionSourceCode.h"
|
||
|
#include "ClangPersistentVariables.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#if HAVE_SYS_TYPES_H
|
||
|
#include <sys/types.h>
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#include "lldb/Core/Module.h"
|
||
|
#include "lldb/Core/StreamFile.h"
|
||
|
#include "lldb/Expression/IRExecutionUnit.h"
|
||
|
#include "lldb/Host/Host.h"
|
||
|
#include "lldb/Target/ExecutionContext.h"
|
||
|
#include "lldb/Target/Target.h"
|
||
|
#include "lldb/Utility/ConstString.h"
|
||
|
#include "lldb/Utility/Log.h"
|
||
|
#include "lldb/Utility/Stream.h"
|
||
|
|
||
|
using namespace lldb_private;
|
||
|
|
||
|
char ClangUtilityFunction::ID;
|
||
|
|
||
|
/// Constructor
|
||
|
///
|
||
|
/// \param[in] text
|
||
|
/// The text of the function. Must be a full translation unit.
|
||
|
///
|
||
|
/// \param[in] name
|
||
|
/// The name of the function, as used in the text.
|
||
|
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
|
||
|
std::string text, std::string name)
|
||
|
: UtilityFunction(
|
||
|
exe_scope,
|
||
|
std::string(ClangExpressionSourceCode::g_expression_prefix) + text,
|
||
|
std::move(name)) {}
|
||
|
|
||
|
ClangUtilityFunction::~ClangUtilityFunction() {}
|
||
|
|
||
|
/// Install the utility function into a process
|
||
|
///
|
||
|
/// \param[in] diagnostic_manager
|
||
|
/// A diagnostic manager to report errors and warnings to.
|
||
|
///
|
||
|
/// \param[in] exe_ctx
|
||
|
/// The execution context to install the utility function to.
|
||
|
///
|
||
|
/// \return
|
||
|
/// True on success (no errors); false otherwise.
|
||
|
bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
|
||
|
ExecutionContext &exe_ctx) {
|
||
|
if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
|
||
|
diagnostic_manager.PutString(eDiagnosticSeverityWarning,
|
||
|
"already installed");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////
|
||
|
// Set up the target and compiler
|
||
|
//
|
||
|
|
||
|
Target *target = exe_ctx.GetTargetPtr();
|
||
|
|
||
|
if (!target) {
|
||
|
diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Process *process = exe_ctx.GetProcessPtr();
|
||
|
|
||
|
if (!process) {
|
||
|
diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid process");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////
|
||
|
// Parse the expression
|
||
|
//
|
||
|
|
||
|
bool keep_result_in_memory = false;
|
||
|
|
||
|
ResetDeclMap(exe_ctx, keep_result_in_memory);
|
||
|
|
||
|
if (!DeclMap()->WillParse(exe_ctx, nullptr)) {
|
||
|
diagnostic_manager.PutString(
|
||
|
eDiagnosticSeverityError,
|
||
|
"current process state is unsuitable for expression parsing");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const bool generate_debug_info = true;
|
||
|
ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,
|
||
|
generate_debug_info);
|
||
|
|
||
|
unsigned num_errors = parser.Parse(diagnostic_manager);
|
||
|
|
||
|
if (num_errors) {
|
||
|
ResetDeclMap();
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
// JIT the output of the parser
|
||
|
//
|
||
|
|
||
|
bool can_interpret = false; // should stay that way
|
||
|
|
||
|
Status jit_error = parser.PrepareForExecution(
|
||
|
m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
|
||
|
can_interpret, eExecutionPolicyAlways);
|
||
|
|
||
|
if (m_jit_start_addr != LLDB_INVALID_ADDRESS) {
|
||
|
m_jit_process_wp = process->shared_from_this();
|
||
|
if (parser.GetGenerateDebugInfo()) {
|
||
|
lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
|
||
|
|
||
|
if (jit_module_sp) {
|
||
|
ConstString const_func_name(FunctionName());
|
||
|
FileSpec jit_file;
|
||
|
jit_file.GetFilename() = const_func_name;
|
||
|
jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
|
||
|
m_jit_module_wp = jit_module_sp;
|
||
|
target->GetImages().Append(jit_module_sp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DeclMap()->DidParse();
|
||
|
|
||
|
ResetDeclMap();
|
||
|
|
||
|
if (jit_error.Success()) {
|
||
|
return true;
|
||
|
} else {
|
||
|
const char *error_cstr = jit_error.AsCString();
|
||
|
if (error_cstr && error_cstr[0]) {
|
||
|
diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr);
|
||
|
} else {
|
||
|
diagnostic_manager.PutString(eDiagnosticSeverityError,
|
||
|
"expression can't be interpreted or run");
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
|
||
|
ExecutionContext &exe_ctx, bool keep_result_in_memory) {
|
||
|
std::shared_ptr<ClangASTImporter> ast_importer;
|
||
|
auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(
|
||
|
lldb::eLanguageTypeC);
|
||
|
if (state) {
|
||
|
auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
|
||
|
ast_importer = persistent_vars->GetClangASTImporter();
|
||
|
}
|
||
|
m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(
|
||
|
keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(), ast_importer,
|
||
|
nullptr);
|
||
|
}
|