xref: /aosp_15_r20/external/pytorch/torch/csrc/profiler/unwind/eh_frame_hdr.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 #include <stdint.h>
3 #include <ostream>
4 
5 #include <torch/csrc/profiler/unwind/lexer.h>
6 #include <torch/csrc/profiler/unwind/unwind_error.h>
7 
8 // Overview of the format described in
9 // https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
10 namespace torch::unwind {
11 
12 struct EHFrameHdr {
EHFrameHdrEHFrameHdr13   EHFrameHdr(void* base) : base_(base) {
14     Lexer L(base, base);
15     version_ = L.read<uint8_t>();
16     eh_frame_ptr_enc_ = L.read<uint8_t>();
17     fde_count_enc_ = L.read<uint8_t>();
18     table_enc_ = L.read<uint8_t>();
19     if (table_enc_ == DW_EH_PE_omit) {
20       table_size_ = 0;
21     } else {
22       switch (table_enc_ & 0xF) {
23         case DW_EH_PE_udata2:
24         case DW_EH_PE_sdata2:
25           table_size_ = 2;
26           break;
27         case DW_EH_PE_udata4:
28         case DW_EH_PE_sdata4:
29           table_size_ = 4;
30           break;
31         case DW_EH_PE_udata8:
32         case DW_EH_PE_sdata8:
33           table_size_ = 8;
34           break;
35         case DW_EH_PE_uleb128:
36         case DW_EH_PE_sleb128:
37           throw UnwindError("uleb/sleb table encoding not supported");
38           break;
39         default:
40           throw UnwindError("unknown table encoding");
41       }
42     }
43     eh_frame_ = (void*)L.readEncodedOr(eh_frame_ptr_enc_, 0);
44     fde_count_ = L.readEncodedOr(fde_count_enc_, 0);
45     table_start_ = L.loc();
46   }
nentriesEHFrameHdr47   size_t nentries() const {
48     return fde_count_;
49   }
50 
lowpcEHFrameHdr51   uint64_t lowpc(size_t i) const {
52     return Lexer(table_start_, base_)
53         .skip(2 * i * table_size_)
54         .readEncoded(table_enc_);
55   }
fdeEHFrameHdr56   void* fde(size_t i) const {
57     return (void*)Lexer(table_start_, base_)
58         .skip((2 * i + 1) * table_size_)
59         .readEncoded(table_enc_);
60   }
61 
entryForAddrEHFrameHdr62   void* entryForAddr(uint64_t addr) const {
63     if (!table_size_ || !nentries()) {
64       throw UnwindError("search table not present");
65     }
66     uint64_t low = 0;
67     uint64_t high = nentries();
68     while (low + 1 < high) {
69       auto mid = (low + high) / 2;
70       if (addr < lowpc(mid)) {
71         high = mid;
72       } else {
73         low = mid;
74       }
75     }
76     return fde(low);
77   }
78 
79   friend std::ostream& operator<<(std::ostream& out, const EHFrameHdr& self) {
80     out << "EHFrameHeader(version=" << self.version_
81         << ",table_size=" << self.table_size_
82         << ",fde_count=" << self.fde_count_ << ")";
83     return out;
84   }
85 
86  private:
87   void* base_;
88   void* table_start_;
89   uint8_t version_;
90   uint8_t eh_frame_ptr_enc_;
91   uint8_t fde_count_enc_;
92   uint8_t table_enc_;
93   void* eh_frame_ = nullptr;
94   int64_t fde_count_;
95   uint32_t table_size_;
96 };
97 
98 } // namespace torch::unwind
99