1*0fca6ea1SDimitry Andric #include "lldb/Target/VerboseTrapFrameRecognizer.h" 2*0fca6ea1SDimitry Andric 3*0fca6ea1SDimitry Andric #include "lldb/Core/Module.h" 4*0fca6ea1SDimitry Andric #include "lldb/Symbol/Function.h" 5*0fca6ea1SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 6*0fca6ea1SDimitry Andric #include "lldb/Target/Process.h" 7*0fca6ea1SDimitry Andric #include "lldb/Target/StackFrameRecognizer.h" 8*0fca6ea1SDimitry Andric #include "lldb/Target/Target.h" 9*0fca6ea1SDimitry Andric 10*0fca6ea1SDimitry Andric #include "lldb/Utility/LLDBLog.h" 11*0fca6ea1SDimitry Andric #include "lldb/Utility/Log.h" 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h" 14*0fca6ea1SDimitry Andric 15*0fca6ea1SDimitry Andric using namespace llvm; 16*0fca6ea1SDimitry Andric using namespace lldb; 17*0fca6ea1SDimitry Andric using namespace lldb_private; 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric VerboseTrapRecognizedStackFrame::VerboseTrapRecognizedStackFrame( 20*0fca6ea1SDimitry Andric StackFrameSP most_relevant_frame_sp, std::string stop_desc) 21*0fca6ea1SDimitry Andric : m_most_relevant_frame(most_relevant_frame_sp) { 22*0fca6ea1SDimitry Andric m_stop_desc = std::move(stop_desc); 23*0fca6ea1SDimitry Andric } 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric lldb::RecognizedStackFrameSP 26*0fca6ea1SDimitry Andric VerboseTrapFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) { 27*0fca6ea1SDimitry Andric if (frame_sp->GetFrameIndex()) 28*0fca6ea1SDimitry Andric return {}; 29*0fca6ea1SDimitry Andric 30*0fca6ea1SDimitry Andric ThreadSP thread_sp = frame_sp->GetThread(); 31*0fca6ea1SDimitry Andric ProcessSP process_sp = thread_sp->GetProcess(); 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric StackFrameSP most_relevant_frame_sp = thread_sp->GetStackFrameAtIndex(1); 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric if (!most_relevant_frame_sp) { 36*0fca6ea1SDimitry Andric Log *log = GetLog(LLDBLog::Unwind); 37*0fca6ea1SDimitry Andric LLDB_LOG( 38*0fca6ea1SDimitry Andric log, 39*0fca6ea1SDimitry Andric "Failed to find most relevant frame: Hit unwinding bound (1 frame)!"); 40*0fca6ea1SDimitry Andric return {}; 41*0fca6ea1SDimitry Andric } 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextEverything); 44*0fca6ea1SDimitry Andric 45*0fca6ea1SDimitry Andric if (!sc.block) 46*0fca6ea1SDimitry Andric return {}; 47*0fca6ea1SDimitry Andric 48*0fca6ea1SDimitry Andric // The runtime error is set as the function name in the inlined function info 49*0fca6ea1SDimitry Andric // of frame #0 by the compiler 50*0fca6ea1SDimitry Andric const InlineFunctionInfo *inline_info = nullptr; 51*0fca6ea1SDimitry Andric Block *inline_block = sc.block->GetContainingInlinedBlock(); 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric if (!inline_block) 54*0fca6ea1SDimitry Andric return {}; 55*0fca6ea1SDimitry Andric 56*0fca6ea1SDimitry Andric inline_info = sc.block->GetInlinedFunctionInfo(); 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric if (!inline_info) 59*0fca6ea1SDimitry Andric return {}; 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric auto func_name = inline_info->GetName().GetStringRef(); 62*0fca6ea1SDimitry Andric if (func_name.empty()) 63*0fca6ea1SDimitry Andric return {}; 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric static auto trap_regex = 66*0fca6ea1SDimitry Andric llvm::Regex(llvm::formatv("^{0}\\$(.*)\\$(.*)$", ClangTrapPrefix).str()); 67*0fca6ea1SDimitry Andric SmallVector<llvm::StringRef, 3> matches; 68*0fca6ea1SDimitry Andric std::string regex_err_msg; 69*0fca6ea1SDimitry Andric if (!trap_regex.match(func_name, &matches, ®ex_err_msg)) { 70*0fca6ea1SDimitry Andric LLDB_LOGF(GetLog(LLDBLog::Unwind), 71*0fca6ea1SDimitry Andric "Failed to parse match trap regex for '%s': %s", func_name.data(), 72*0fca6ea1SDimitry Andric regex_err_msg.c_str()); 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric return {}; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric // For `__clang_trap_msg$category$message$` we expect 3 matches: 78*0fca6ea1SDimitry Andric // 1. entire string 79*0fca6ea1SDimitry Andric // 2. category 80*0fca6ea1SDimitry Andric // 3. message 81*0fca6ea1SDimitry Andric if (matches.size() != 3) { 82*0fca6ea1SDimitry Andric LLDB_LOGF(GetLog(LLDBLog::Unwind), 83*0fca6ea1SDimitry Andric "Unexpected function name format. Expected '<trap prefix>$<trap " 84*0fca6ea1SDimitry Andric "category>$<trap message>'$ but got: '%s'.", 85*0fca6ea1SDimitry Andric func_name.data()); 86*0fca6ea1SDimitry Andric 87*0fca6ea1SDimitry Andric return {}; 88*0fca6ea1SDimitry Andric } 89*0fca6ea1SDimitry Andric 90*0fca6ea1SDimitry Andric auto category = matches[1]; 91*0fca6ea1SDimitry Andric auto message = matches[2]; 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric std::string stop_reason = 94*0fca6ea1SDimitry Andric category.empty() ? "<empty category>" : category.str(); 95*0fca6ea1SDimitry Andric if (!message.empty()) { 96*0fca6ea1SDimitry Andric stop_reason += ": "; 97*0fca6ea1SDimitry Andric stop_reason += message.str(); 98*0fca6ea1SDimitry Andric } 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric return std::make_shared<VerboseTrapRecognizedStackFrame>( 101*0fca6ea1SDimitry Andric most_relevant_frame_sp, std::move(stop_reason)); 102*0fca6ea1SDimitry Andric } 103*0fca6ea1SDimitry Andric 104*0fca6ea1SDimitry Andric lldb::StackFrameSP VerboseTrapRecognizedStackFrame::GetMostRelevantFrame() { 105*0fca6ea1SDimitry Andric return m_most_relevant_frame; 106*0fca6ea1SDimitry Andric } 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric namespace lldb_private { 109*0fca6ea1SDimitry Andric 110*0fca6ea1SDimitry Andric void RegisterVerboseTrapFrameRecognizer(Process &process) { 111*0fca6ea1SDimitry Andric RegularExpressionSP module_regex_sp = nullptr; 112*0fca6ea1SDimitry Andric auto symbol_regex_sp = std::make_shared<RegularExpression>( 113*0fca6ea1SDimitry Andric llvm::formatv("^{0}", ClangTrapPrefix).str()); 114*0fca6ea1SDimitry Andric 115*0fca6ea1SDimitry Andric StackFrameRecognizerSP srf_recognizer_sp = 116*0fca6ea1SDimitry Andric std::make_shared<VerboseTrapFrameRecognizer>(); 117*0fca6ea1SDimitry Andric 118*0fca6ea1SDimitry Andric process.GetTarget().GetFrameRecognizerManager().AddRecognizer( 119*0fca6ea1SDimitry Andric srf_recognizer_sp, module_regex_sp, symbol_regex_sp, false); 120*0fca6ea1SDimitry Andric } 121*0fca6ea1SDimitry Andric 122*0fca6ea1SDimitry Andric } // namespace lldb_private 123