brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · e698306 Raw
192 lines · cpp
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-exception6//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 28using namespace lldb_private;29 30char ClangUtilityFunction::ID;31 32ClangUtilityFunction::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 display41  // 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 the53        // 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 63ClangUtilityFunction::~ClangUtilityFunction() = default;64 65/// Install the utility function into a process66///67/// \param[in] diagnostic_manager68///     A diagnostic manager to report errors and warnings to.69///70/// \param[in] exe_ctx71///     The execution context to install the utility function to.72///73/// \return74///     True on success (no errors); false otherwise.75bool 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 compiler84  //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 make101  // 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 expression108  //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, diagnostic_manager);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 parser135  //136 137  bool can_interpret = false; // should stay that way138 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 177char ClangUtilityFunction::ClangUtilityFunctionHelper::ID;178 179void 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