File: fast_symbolizer.h

package info (click to toggle)
pytorch-cuda 2.6.0%2Bdfsg-7
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid, trixie
  • size: 161,620 kB
  • sloc: python: 1,278,832; cpp: 900,322; ansic: 82,710; asm: 7,754; java: 3,363; sh: 2,811; javascript: 2,443; makefile: 597; ruby: 195; xml: 84; objc: 68
file content (108 lines) | stat: -rw-r--r-- 3,303 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
#pragma once

#include <fmt/format.h>
#include <sys/types.h>
#include <torch/csrc/profiler/unwind/debug_info.h>
#include <torch/csrc/profiler/unwind/line_number_program.h>
#include <torch/csrc/profiler/unwind/sections.h>
#include <torch/csrc/profiler/unwind/unwind.h>
#include <torch/csrc/profiler/unwind/unwind_error.h>
#include <memory>
#include <unordered_map>

namespace torch::unwind {

#define UNWIND_WARN(w, ...)                   \
  do {                                        \
    w.emplace_back(fmt::format(__VA_ARGS__)); \
    LOG_INFO("WARNING: {}\n", w.back());      \
  } while (0);

struct FastSymbolizer {
  FastSymbolizer() = default;
  Frame symbolize(const std::string& library, uint64_t offset) {
    LOG_INFO("symbolizing {} + 0x{:x}\n", library, offset);
    Frame frame;
    frame.funcname = "??";
    frame.filename = library;
    frame.lineno = offset;
    auto s = getOrCreateSections(library);
    if (auto e = s->findSubprogramName(offset)) {
      frame.funcname = *e;
    } else {
      UNWIND_WARN(
          warnings_,
          "failed to find subprogram name for {} 0x{:x}",
          library,
          offset);
    }
    if (auto e = findLine(s, offset)) {
      frame.filename = e->first;
      frame.lineno = e->second;
    } else {
      UNWIND_WARN(
          warnings_, "failed to find file/line for {} 0x{:x}", library, offset);
    }
    return frame;
  }
  const std::vector<std::string>& warnings() {
    return warnings_;
  }

 private:
  void parseDebugInfo(Sections* s) {
    uint64_t offset = 0;
    while (offset < s->debug_info.size) {
      DebugInfo info(*s);
      info.parse(offset);
      if (auto lnp_offset = info.lineNumberProgramOffset()) {
        for (auto r : info.ranges()) {
          s->addDebugInfoRange(r.first, r.second, line_number_programs_.size());
        }
        line_number_programs_.emplace_back(
            std::make_unique<LineNumberProgram>(*s, *lnp_offset));
      }
      offset = info.nextOffset();
    }
  }
  Sections* getOrCreateSections(const std::string& library) {
    auto it = libraries_.find(library);
    if (it == libraries_.end()) {
      it = libraries_.insert({library, std::make_unique<Sections>()}).first;
      try {
        Sections* s = it->second.get();
        s->parse(library.c_str());
        parseDebugInfo(s);
      } catch (UnwindError& err) {
        UNWIND_WARN(
            warnings_, "failed to parse library {}: {}", library, err.what());
      }
    }
    return it->second.get();
  }
  std::optional<std::pair<std::string, int64_t>> findLine(
      Sections* s,
      uint64_t offset) {
    if (auto idx = s->findDebugInfoOffset(offset)) {
      auto r = line_number_programs_.at(*idx).get();
      try {
        r->parse();
      } catch (UnwindError& err) {
        UNWIND_WARN(
            warnings_,
            "failed to read line number program [{:x}] {}",
            r->offset(),
            err.what());
      }
      if (auto e = r->find(offset)) {
        return std::make_pair(r->filename(e->file), e->line);
      }
    }
    return std::nullopt;
  }
  std::unordered_map<std::string, std::unique_ptr<Sections>> libraries_;
  std::vector<std::unique_ptr<LineNumberProgram>> line_number_programs_;
  std::vector<std::string> warnings_;
};

} // namespace torch::unwind