diff options
Diffstat (limited to 'lldb/source/Plugins')
6 files changed, 215 insertions, 7 deletions
diff --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp index ff37b48..a5547a4 100644 --- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp +++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp @@ -798,6 +798,8 @@ bool ABISysV_riscv::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {            .Cases({"f8", "f9", "f18", "f19", "f20", "f21", "f22", "f23"},                   is_hw_fp)            .Cases({"f24", "f25", "f26", "f27"}, is_hw_fp) +          // vlenb is constant and needed for vector unwinding. +          .Case("vlenb", true)            .Default(false);    return is_callee_saved; diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt index 1717b0a..a27bcef 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt @@ -1,5 +1,6 @@  add_lldb_library(lldbPluginCPPRuntime    CPPLanguageRuntime.cpp +  VerboseTrapFrameRecognizer.cpp    LINK_LIBS      lldbCore diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 21a5ebe..913678b 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -12,6 +12,7 @@  #include <memory>  #include "CPPLanguageRuntime.h" +#include "VerboseTrapFrameRecognizer.h"  #include "llvm/ADT/StringRef.h" @@ -107,12 +108,15 @@ public:  CPPLanguageRuntime::CPPLanguageRuntime(Process *process)      : LanguageRuntime(process) { -  if (process) +  if (process) {      process->GetTarget().GetFrameRecognizerManager().AddRecognizer(          StackFrameRecognizerSP(new LibCXXFrameRecognizer()), {},          std::make_shared<RegularExpression>("^std::__[^:]*::"),          /*mangling_preference=*/Mangled::ePreferDemangledWithoutArguments,          /*first_instruction_only=*/false); + +    RegisterVerboseTrapFrameRecognizer(*process); +  }  }  bool CPPLanguageRuntime::IsAllowedRuntimeValue(ConstString name) { diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.cpp new file mode 100644 index 0000000..730aba5 --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.cpp @@ -0,0 +1,156 @@ +#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 {}; + +  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, ®ex_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, +      Mangled::ePreferDemangled, false); +} + +} // namespace lldb_private diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.h new file mode 100644 index 0000000..7d7020f --- /dev/null +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/VerboseTrapFrameRecognizer.h @@ -0,0 +1,47 @@ +//===-- VerboseTrapFrameRecognizer.h --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_C_PLUS_PLUS_VERBOSETRAPFRAMERECOGNIZER_H +#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_C_PLUS_PLUS_VERBOSETRAPFRAMERECOGNIZER_H + +#include "lldb/Target/StackFrameRecognizer.h" + +namespace lldb_private { + +void RegisterVerboseTrapFrameRecognizer(Process &process); + +/// Holds the stack frame that caused the Verbose trap and the inlined stop +/// reason message. +class VerboseTrapRecognizedStackFrame : public RecognizedStackFrame { +public: +  VerboseTrapRecognizedStackFrame(lldb::StackFrameSP most_relevant_frame_sp, +                                  std::string stop_desc); + +  lldb::StackFrameSP GetMostRelevantFrame() override; + +private: +  lldb::StackFrameSP m_most_relevant_frame; +}; + +/// When a thread stops, it checks the current frame contains a +/// Verbose Trap diagnostic. If so, it returns a \a +/// VerboseTrapRecognizedStackFrame holding the diagnostic a stop reason +/// description with and the parent frame as the most relavant frame. +class VerboseTrapFrameRecognizer : public StackFrameRecognizer { +public: +  std::string GetName() override { +    return "Verbose Trap StackFrame Recognizer"; +  } + +  lldb::RecognizedStackFrameSP +  RecognizeFrame(lldb::StackFrameSP frame) override; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_C_PLUS_PLUS_VERBOSETRAPFRAMERECOGNIZER_H diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 49841e7..e06e69f 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2735,9 +2735,8 @@ static void ApplyELF64ABS64Relocation(Symtab *symtab, ELFRelocation &rel,      // ObjectFileELF creates a WritableDataBuffer in CreateInstance.      WritableDataBuffer *data_buffer =          llvm::cast<WritableDataBuffer>(data_buffer_sp.get()); -    uint64_t *dst = reinterpret_cast<uint64_t *>( -        data_buffer->GetBytes() + rel_section->GetFileOffset() + -        ELFRelocation::RelocOffset64(rel)); +    void *const dst = data_buffer->GetBytes() + rel_section->GetFileOffset() + +                      ELFRelocation::RelocOffset64(rel);      uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);      memcpy(dst, &val_offset, sizeof(uint64_t));    } @@ -2762,9 +2761,8 @@ static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel,      // ObjectFileELF creates a WritableDataBuffer in CreateInstance.      WritableDataBuffer *data_buffer =          llvm::cast<WritableDataBuffer>(data_buffer_sp.get()); -    uint32_t *dst = reinterpret_cast<uint32_t *>( -        data_buffer->GetBytes() + rel_section->GetFileOffset() + -        ELFRelocation::RelocOffset32(rel)); +    void *const dst = data_buffer->GetBytes() + rel_section->GetFileOffset() + +                      ELFRelocation::RelocOffset32(rel);      memcpy(dst, &truncated_addr, sizeof(uint32_t));    }  }  | 
