brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.2 KiB · 2b6bf2c Raw
138 lines · cpp
1#include "VerboseTrapFrameRecognizer.h"2 3#include "lldb/Core/Module.h"4#include "lldb/Symbol/Function.h"5#include "lldb/Symbol/SymbolContext.h"6#include "lldb/Target/Process.h"7#include "lldb/Target/StackFrameRecognizer.h"8#include "lldb/Target/Target.h"9 10#include "lldb/Utility/LLDBLog.h"11#include "lldb/Utility/Log.h"12 13#include "clang/CodeGen/ModuleBuilder.h"14 15using namespace llvm;16using namespace lldb;17using namespace lldb_private;18 19/// The 0th frame is the artificial inline frame generated to store20/// the verbose_trap message. So, starting with the current parent frame,21/// find the first frame that's not inside of the STL.22static StackFrameSP FindMostRelevantFrame(Thread &selected_thread) {23  // Defensive upper-bound of when we stop walking up the frames in24  // case we somehow ended up looking at an infinite recursion.25  const size_t max_stack_depth = 128;26 27  // Start at parent frame.28  size_t stack_idx = 1;29  StackFrameSP most_relevant_frame_sp =30      selected_thread.GetStackFrameAtIndex(stack_idx);31 32  while (most_relevant_frame_sp && stack_idx <= max_stack_depth) {33    auto const &sc =34        most_relevant_frame_sp->GetSymbolContext(eSymbolContextEverything);35    ConstString frame_name = sc.GetFunctionName();36    if (!frame_name)37      return nullptr;38 39    // Found a frame outside of the `std` namespace. That's the40    // first frame in user-code that ended up triggering the41    // verbose_trap. Hence that's the one we want to display.42    if (!frame_name.GetStringRef().starts_with("std::"))43      return most_relevant_frame_sp;44 45    ++stack_idx;46    most_relevant_frame_sp = selected_thread.GetStackFrameAtIndex(stack_idx);47  }48 49  return nullptr;50}51 52VerboseTrapRecognizedStackFrame::VerboseTrapRecognizedStackFrame(53    StackFrameSP most_relevant_frame_sp, std::string stop_desc)54    : m_most_relevant_frame(most_relevant_frame_sp) {55  m_stop_desc = std::move(stop_desc);56}57 58lldb::RecognizedStackFrameSP59VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {60  if (frame_sp->GetFrameIndex())61    return {};62 63  ThreadSP thread_sp = frame_sp->GetThread();64  ProcessSP process_sp = thread_sp->GetProcess();65 66  StackFrameSP most_relevant_frame_sp = FindMostRelevantFrame(*thread_sp);67 68  if (!most_relevant_frame_sp) {69    Log *log = GetLog(LLDBLog::Unwind);70    LLDB_LOG(71        log,72        "Failed to find most relevant frame: Hit unwinding bound (1 frame)!");73    return {};74  }75 76  SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);77 78  if (!sc.block)79    return {};80 81  // The runtime error is set as the function name in the inlined function info82  // of frame #0 by the compiler83  const InlineFunctionInfo *inline_info = nullptr;84  Block *inline_block = sc.block->GetContainingInlinedBlock();85 86  if (!inline_block)87    return {};88 89  inline_info = sc.block->GetInlinedFunctionInfo();90 91  if (!inline_info)92    return {};93 94  auto func_name = inline_info->GetName().GetStringRef();95  if (func_name.empty())96    return {};97 98  auto maybe_trap_reason =99      clang::CodeGen::DemangleTrapReasonInDebugInfo(func_name);100  if (!maybe_trap_reason.has_value()) {101    LLDB_LOGF(GetLog(LLDBLog::Unwind), "Failed to demangle '%s' as trap reason",102              func_name.str().c_str());103    return {};104  }105  auto [category, message] = maybe_trap_reason.value();106 107  std::string stop_reason =108      category.empty() ? "<empty category>" : category.str();109  if (!message.empty()) {110    stop_reason += ": ";111    stop_reason += message.str();112  }113 114  return std::make_shared<VerboseTrapRecognizedStackFrame>(115      most_relevant_frame_sp, std::move(stop_reason));116}117 118lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() {119  return m_most_relevant_frame;120}121 122namespace lldb_private {123 124void RegisterVerboseTrapFrameRecognizer(Process &process) {125  RegularExpressionSP module_regex_sp = nullptr;126  auto symbol_regex_sp = std::make_shared<RegularExpression>(127      llvm::formatv("^{0}", ClangTrapPrefix).str());128 129  StackFrameRecognizerSP srf_recognizer_sp =130      std::make_shared<VerboseTrapFrameRecognizer>();131 132  process.GetTarget().GetFrameRecognizerManager().AddRecognizer(133      srf_recognizer_sp, module_regex_sp, symbol_regex_sp,134      Mangled::ePreferDemangled, false);135}136 137} // namespace lldb_private138