File: VerboseTrapFrameRecognizer.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (122 lines) | stat: -rw-r--r-- 3,551 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "lldb/Target/VerboseTrapFrameRecognizer.h"

#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"

#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"

#include "clang/CodeGen/ModuleBuilder.h"

using namespace llvm;
using namespace lldb;
using namespace lldb_private;

VerboseTrapRecognizedStackFrame::VerboseTrapRecognizedStackFrame(
    StackFrameSP most_relevant_frame_sp, std::string stop_desc)
    : m_most_relevant_frame(most_relevant_frame_sp) {
  m_stop_desc = std::move(stop_desc);
}

lldb::RecognizedStackFrameSP
VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
  if (frame_sp->GetFrameIndex())
    return {};

  ThreadSP thread_sp = frame_sp->GetThread();
  ProcessSP process_sp = thread_sp->GetProcess();

  StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1);

  if (!most_relevant_frame_sp) {
    Log *log = GetLog(LLDBLog::Unwind);
    LLDB_LOG(
        log,
        "Failed to find most relevant frame: Hit unwinding bound (1 frame)!");
    return {};
  }

  SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything);

  if (!sc.block)
    return {};

  // The runtime error is set as the function name in the inlined function info
  // of frame #0 by the compiler
  const InlineFunctionInfo *inline_info = nullptr;
  Block *inline_block = sc.block->GetContainingInlinedBlock();

  if (!inline_block)
    return {};

  inline_info = sc.block->GetInlinedFunctionInfo();

  if (!inline_info)
    return {};

  auto func_name = inline_info->GetName().GetStringRef();
  if (func_name.empty())
    return {};

  static auto trap_regex =
      llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str());
  SmallVector<llvm::StringRef, 3> matches;
  std::string regex_err_msg;
  if (!trap_regex.match(func_name, &matches, &regex_err_msg)) {
    LLDB_LOGF(GetLog(LLDBLog::Unwind),
              "Failed to parse match trap regex for '%s': %s", func_name.data(),
              regex_err_msg.c_str());

    return {};
  }

  // For `__clang_trap_msg$category$message$` we expect 3 matches:
  // 1. entire string
  // 2. category
  // 3. message
  if (matches.size() != 3) {
    LLDB_LOGF(GetLog(LLDBLog::Unwind),
              "Unexpected function name format. Expected '<trap prefix>$<trap "
              "category>$<trap message>'$ but got: '%s'.",
              func_name.data());

    return {};
  }

  auto category = matches[1];
  auto message = matches[2];

  std::string stop_reason =
      category.empty() ? "<empty category>" : category.str();
  if (!message.empty()) {
    stop_reason += ": ";
    stop_reason += message.str();
  }

  return std::make_shared<VerboseTrapRecognizedStackFrame>(
      most_relevant_frame_sp, std::move(stop_reason));
}

lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() {
  return m_most_relevant_frame;
}

namespace lldb_private {

void RegisterVerboseTrapFrameRecognizer(Process &process) {
  RegularExpressionSP module_regex_sp = nullptr;
  auto symbol_regex_sp = std::make_shared<RegularExpression>(
      llvm::formatv("^{0}", ClangTrapPrefix).str());

  StackFrameRecognizerSP srf_recognizer_sp =
      std::make_shared<VerboseTrapFrameRecognizer>();

  process.GetTarget().GetFrameRecognizerManager().AddRecognizer(
      srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false);
}

} // namespace lldb_private