CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
138 lines
4.2 KiB
C++
138 lines
4.2 KiB
C++
#include "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;
|
|
|
|
/// The 0th frame is the artificial inline frame generated to store
|
|
/// the verbose_trap message. So, starting with the current parent frame,
|
|
/// find the first frame that's not inside of the STL.
|
|
static StackFrameSP FindMostRelevantFrame(Thread &selected_thread) {
|
|
// Defensive upper-bound of when we stop walking up the frames in
|
|
// case we somehow ended up looking at an infinite recursion.
|
|
const size_t max_stack_depth = 128;
|
|
|
|
// Start at parent frame.
|
|
size_t stack_idx = 1;
|
|
StackFrameSP most_relevant_frame_sp =
|
|
selected_thread.GetStackFrameAtIndex(stack_idx);
|
|
|
|
while (most_relevant_frame_sp && stack_idx <= max_stack_depth) {
|
|
auto const &sc =
|
|
most_relevant_frame_sp->GetSymbolContext(eSymbolContextEverything);
|
|
ConstString frame_name = sc.GetFunctionName();
|
|
if (!frame_name)
|
|
return nullptr;
|
|
|
|
// Found a frame outside of the `std` namespace. That's the
|
|
// first frame in user-code that ended up triggering the
|
|
// verbose_trap. Hence that's the one we want to display.
|
|
if (!frame_name.GetStringRef().starts_with("std::"))
|
|
return most_relevant_frame_sp;
|
|
|
|
++stack_idx;
|
|
most_relevant_frame_sp = selected_thread.GetStackFrameAtIndex(stack_idx);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
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 = FindMostRelevantFrame(*thread_sp);
|
|
|
|
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 {};
|
|
|
|
auto maybe_trap_reason =
|
|
clang::CodeGen::DemangleTrapReasonInDebugInfo(func_name);
|
|
if (!maybe_trap_reason.has_value()) {
|
|
LLDB_LOGF(GetLog(LLDBLog::Unwind), "Failed to demangle '%s' as trap reason",
|
|
func_name.str().c_str());
|
|
return {};
|
|
}
|
|
auto [category, message] = maybe_trap_reason.value();
|
|
|
|
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,
|
|
Mangled::ePreferDemangled, false);
|
|
}
|
|
|
|
} // namespace lldb_private
|