File indexing completed on 2024-05-05 05:44:15
0001 /* 0002 dwarfdiecache.h 0003 0004 SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.com> 0005 SPDX-FileContributor: Milian Wolff <milian.wolff@kdab.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #ifndef DWARFDIECACHE_H 0011 #define DWARFDIECACHE_H 0012 0013 #include <elfutils/libdwfl.h> 0014 0015 #include <tsl/robin_map.h> 0016 0017 #include <algorithm> 0018 #include <string> 0019 #include <vector> 0020 0021 /// @return the demangled symbol name 0022 std::string demangle(const std::string& mangledName); 0023 0024 /// @return the absolute source path for the potential @p path in the given @p cuDie 0025 std::string absoluteSourcePath(const char* path, Dwarf_Die* cuDie); 0026 0027 struct SourceLocation 0028 { 0029 std::string file; 0030 int line = 0; 0031 }; 0032 0033 /// @return the file and line location encoded in the DW_AT_call_{file,line} data of @p die 0034 SourceLocation callSourceLocation(Dwarf_Die* die, Dwarf_Files* files, Dwarf_Die* cuDie); 0035 0036 struct DwarfRange 0037 { 0038 Dwarf_Addr low; 0039 Dwarf_Addr high; 0040 0041 bool contains(Dwarf_Addr addr) const 0042 { 0043 return low <= addr && addr < high; 0044 } 0045 }; 0046 0047 /// cache of dwarf ranges for a given Dwarf_Die 0048 struct DieRanges 0049 { 0050 Dwarf_Die die; 0051 std::vector<DwarfRange> ranges; 0052 0053 bool contains(Dwarf_Addr addr) const 0054 { 0055 return std::any_of(ranges.begin(), ranges.end(), 0056 [addr](const DwarfRange& range) { return range.contains(addr); }); 0057 } 0058 }; 0059 0060 /// cache of sub program DIE, its ranges and the accompanying die name 0061 class SubProgramDie 0062 { 0063 public: 0064 SubProgramDie(Dwarf_Die die); 0065 0066 bool isEmpty() const 0067 { 0068 return m_ranges.ranges.empty(); 0069 } 0070 /// @p offset a bias-corrected offset 0071 bool contains(Dwarf_Addr offset) const 0072 { 0073 return m_ranges.contains(offset); 0074 } 0075 Dwarf_Die* die() 0076 { 0077 return &m_ranges.die; 0078 } 0079 0080 private: 0081 DieRanges m_ranges; 0082 }; 0083 0084 /// cache of dwarf ranges for a CU DIE and child sub programs 0085 class CuDieRangeMapping 0086 { 0087 public: 0088 CuDieRangeMapping(Dwarf_Die cudie, Dwarf_Addr bias); 0089 0090 bool isEmpty() const 0091 { 0092 return m_cuDieRanges.ranges.empty(); 0093 } 0094 bool contains(Dwarf_Addr addr) const 0095 { 0096 return m_cuDieRanges.contains(addr); 0097 } 0098 Dwarf_Addr bias() 0099 { 0100 return m_bias; 0101 } 0102 Dwarf_Die* cudie() 0103 { 0104 return &m_cuDieRanges.die; 0105 } 0106 0107 /// On first call this will visit the CU DIE to cache all subprograms 0108 /// @return the DW_TAG_subprogram DIE that contains @p offset 0109 /// @p offset a bias-corrected address to find a subprogram for 0110 SubProgramDie* findSubprogramDie(Dwarf_Addr offset); 0111 0112 /// @return a fully qualified, demangled symbol name for @p die 0113 const std::string& dieName(Dwarf_Die* die); 0114 0115 private: 0116 void addSubprograms(); 0117 0118 Dwarf_Addr m_bias = 0; 0119 DieRanges m_cuDieRanges; 0120 std::vector<SubProgramDie> m_subPrograms; 0121 tsl::robin_map<Dwarf_Off, std::string> m_dieNameCache; 0122 }; 0123 0124 /** 0125 * @return all DW_TAG_inlined_subroutine DIEs that contain @p offset 0126 * @p subprogram DIE sub tree that should be traversed to look for inlined scopes 0127 * @p offset bias-corrected address that is checked against the dwarf ranges of the DIEs 0128 */ 0129 std::vector<Dwarf_Die> findInlineScopes(Dwarf_Die* subprogram, Dwarf_Addr offset); 0130 0131 /** 0132 * This cache makes it easily possible to find a CU DIE (i.e. Compilation Unit Debugging Information Entry) 0133 * based on a 0134 */ 0135 class DwarfDieCache 0136 { 0137 public: 0138 DwarfDieCache(Dwfl_Module* mod = nullptr); 0139 0140 /// @p addr absolute address, not bias-corrected 0141 CuDieRangeMapping* findCuDie(Dwarf_Addr addr); 0142 0143 public: 0144 std::vector<CuDieRangeMapping> m_cuDieRanges; 0145 }; 0146 0147 #endif // DWARFDIECACHE_H