xref: /aosp_15_r20/external/pytorch/torch/csrc/profiler/unwind/sections.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 #include <cxxabi.h>
3 #include <elf.h>
4 #include <torch/csrc/profiler/unwind/dwarf_enums.h>
5 #include <torch/csrc/profiler/unwind/dwarf_symbolize_enums.h>
6 #include <torch/csrc/profiler/unwind/mem_file.h>
7 #include <torch/csrc/profiler/unwind/range_table.h>
8 #include <torch/csrc/profiler/unwind/unwind_error.h>
9 #include <cstdint>
10 
11 namespace torch::unwind {
12 
demangle(const std::string & mangled_name)13 static std::string demangle(const std::string& mangled_name) {
14   int status = 0;
15   char* realname =
16       abi::__cxa_demangle(mangled_name.c_str(), nullptr, nullptr, &status);
17   if (status == 0) {
18     std::string demangled_name(realname);
19     // NOLINTNEXTLINE
20     free(realname);
21     return demangled_name;
22   } else {
23     return mangled_name;
24   }
25 }
26 
27 struct Sections {
28   Sections() = default;
parseSections29   void parse(const char* name) {
30     library_ = std::make_unique<MemFile>(name);
31     strtab = library_->getSection(".strtab", false);
32 
33     symtab = library_->getSection(".symtab", true);
34     debug_info = library_->getSection(".debug_info", true);
35     if (debug_info.size > 0) {
36       debug_abbrev = library_->getSection(".debug_abbrev", false);
37       debug_str = library_->getSection(".debug_str", false);
38       debug_line = library_->getSection(".debug_line", false);
39       // dwarf 5
40       debug_line_str = library_->getSection(".debug_line_str", true);
41       debug_rnglists = library_->getSection(".debug_rnglists", true);
42       debug_addr = library_->getSection(".debug_addr", true);
43       // dwarf 4
44       debug_ranges = library_->getSection(".debug_ranges", true);
45     }
46     parseSymtab();
47   }
48 
49   Section debug_info;
50   Section debug_abbrev;
51   Section debug_str;
52   Section debug_line;
53   Section debug_line_str;
54   Section debug_rnglists;
55   Section debug_ranges;
56   Section debug_addr;
57   Section symtab;
58   Section strtab;
59 
readStringSections60   const char* readString(CheckedLexer& data, uint64_t encoding, bool is_64bit) {
61     switch (encoding) {
62       case DW_FORM_string: {
63         return data.readCString();
64       }
65       case DW_FORM_strp: {
66         return debug_str.string(readSegmentOffset(data, is_64bit));
67       }
68       case DW_FORM_line_strp: {
69         return debug_line_str.string(readSegmentOffset(data, is_64bit));
70       }
71       default:
72         UNWIND_CHECK(false, "unsupported string encoding {:x}", encoding);
73     }
74   }
75 
readSegmentOffsetSections76   uint64_t readSegmentOffset(CheckedLexer& data, bool is_64bit) {
77     return is_64bit ? data.read<uint64_t>() : data.read<uint32_t>();
78   }
79 
findDebugInfoOffsetSections80   std::optional<uint64_t> findDebugInfoOffset(uint64_t address) {
81     return debug_info_offsets_.find(address);
82   }
compilationUnitCountSections83   size_t compilationUnitCount() {
84     return debug_info_offsets_.size() / 2;
85   }
addDebugInfoRangeSections86   void addDebugInfoRange(
87       uint64_t start,
88       uint64_t end,
89       uint64_t debug_info_offset) {
90     debug_info_offsets_.add(start, debug_info_offset, false);
91     debug_info_offsets_.add(end, std::nullopt, false);
92   }
findSubprogramNameSections93   std::optional<std::string> findSubprogramName(uint64_t address) {
94     if (auto e = symbol_table_.find(address)) {
95       return demangle(strtab.string(*e));
96     }
97     return std::nullopt;
98   }
99 
100  private:
parseSymtabSections101   void parseSymtab() {
102     auto L = symtab.lexer(0);
103     char* end = symtab.data + symtab.size;
104     while (L.loc() < end) {
105       auto symbol = L.read<Elf64_Sym>();
106       if (symbol.st_shndx == SHN_UNDEF ||
107           ELF64_ST_TYPE(symbol.st_info) != STT_FUNC) {
108         continue;
109       }
110       symbol_table_.add(symbol.st_value, symbol.st_name, false);
111       symbol_table_.add(symbol.st_value + symbol.st_size, std::nullopt, false);
112     }
113   }
114 
115   std::unique_ptr<MemFile> library_;
116   RangeTable<uint64_t> debug_info_offsets_;
117   RangeTable<uint64_t> symbol_table_;
118 };
119 
120 } // namespace torch::unwind
121