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