dwarf_symbolizer.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #include <library/cpp/yt/backtrace/backtrace.h>
  2. #include <library/cpp/dwarf_backtrace/backtrace.h>
  3. #include <library/cpp/yt/string/raw_formatter.h>
  4. namespace NYT::NBacktrace {
  5. ////////////////////////////////////////////////////////////////////////////////
  6. void SymbolizeBacktrace(
  7. TBacktrace backtrace,
  8. const std::function<void(TStringBuf)>& frameCallback)
  9. {
  10. auto error = NDwarf::ResolveBacktrace({backtrace.begin(), backtrace.size()}, [&] (const NDwarf::TLineInfo& info) {
  11. TRawFormatter<1024> formatter;
  12. formatter.AppendNumber(info.Index + 1, 10, 2);
  13. formatter.AppendString(". ");
  14. formatter.AppendString("0x");
  15. const int width = (sizeof(void*) == 8 ? 12 : 8);
  16. // 12 for x86_64 because higher bits are always zeroed.
  17. formatter.AppendNumber(info.Address, 16, width, '0');
  18. formatter.AppendString(" in ");
  19. formatter.AppendString(info.FunctionName);
  20. const int bytesToAppendEstimate = 4 + info.FileName.Size() + 1 + 4 /* who cares about line numbers > 9999 */ + 1;
  21. if (formatter.GetBytesRemaining() < bytesToAppendEstimate) {
  22. const int offset = formatter.GetBytesRemaining() - bytesToAppendEstimate;
  23. if (formatter.GetBytesWritten() + offset >= 0) {
  24. formatter.Advance(offset);
  25. }
  26. }
  27. formatter.AppendString(" at ");
  28. formatter.AppendString(info.FileName);
  29. formatter.AppendChar(':');
  30. formatter.AppendNumber(info.Line);
  31. if (formatter.GetBytesRemaining() == 0) {
  32. formatter.Revert(1);
  33. }
  34. formatter.AppendString("\n");
  35. frameCallback(formatter.GetBuffer());
  36. // Call the callback exactly `frameCount` times,
  37. // even if there are inline functions and one frame resolved to several lines.
  38. // It needs for case when caller uses `frameCount` less than 100 for pretty formatting.
  39. if (info.Index + 1 == std::ssize(backtrace)) {
  40. return NDwarf::EResolving::Break;
  41. }
  42. return NDwarf::EResolving::Continue;
  43. });
  44. if (error) {
  45. TRawFormatter<1024> formatter;
  46. formatter.AppendString("*** Error symbolizing backtrace via Dwarf\n");
  47. formatter.AppendString("*** Code: ");
  48. formatter.AppendNumber(error->Code);
  49. formatter.AppendString("\n");
  50. formatter.AppendString("*** Message: ");
  51. formatter.AppendString(error->Message);
  52. formatter.AppendString("\n");
  53. frameCallback(formatter.GetBuffer());
  54. }
  55. }
  56. ////////////////////////////////////////////////////////////////////////////////
  57. } // namespace NYT::NBacktrace