File indexing completed on 2024-05-19 05:44:07
0001 /* 0002 Copyright (C) 2015 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "dwarfaddressranges.h" 0019 #include "dwarfinfo.h" 0020 #include "dwarfcudie.h" 0021 0022 #include <dwarf.h> 0023 0024 #include <cassert> 0025 0026 DwarfAddressRanges::DwarfAddressRanges(DwarfInfo* info) : 0027 m_aranges(nullptr), 0028 m_info(info) 0029 { 0030 assert(info); 0031 const auto res = dwarf_get_aranges(info->dwarfHandle(), &m_aranges, &m_arangesSize, nullptr); 0032 if (res != DW_DLV_OK) 0033 return; 0034 } 0035 0036 DwarfAddressRanges::~DwarfAddressRanges() 0037 { 0038 for (int i = 0; i < m_arangesSize; ++i) 0039 dwarf_dealloc(m_info->dwarfHandle(), m_aranges[i], DW_DLA_ARANGE); 0040 dwarf_dealloc(m_info->dwarfHandle(), m_aranges, DW_DLA_LIST); 0041 } 0042 0043 bool DwarfAddressRanges::isValid() const 0044 { 0045 return m_aranges; 0046 } 0047 0048 DwarfCuDie* DwarfAddressRanges::compilationUnitForAddress(uint64_t addr) const 0049 { 0050 if (!isValid()) 0051 return nullptr; 0052 0053 Dwarf_Arange arange; 0054 auto res = dwarf_get_arange(m_aranges, m_arangesSize, addr, &arange, nullptr); 0055 if (res != DW_DLV_OK) 0056 return nullptr; 0057 0058 Dwarf_Off offset; 0059 res = dwarf_get_cu_die_offset(arange, &offset, nullptr); 0060 if (res != DW_DLV_OK) 0061 return nullptr; 0062 0063 auto die = m_info->dieAtOffset(offset); 0064 if (!die) 0065 return nullptr; 0066 0067 assert(die->isCompilationUnit()); 0068 return static_cast<DwarfCuDie*>(die); 0069 } 0070 0071 static DwarfDie* findByLowPCRecursive(DwarfDie *die, uint64_t addr) 0072 { 0073 const auto lowPC = die->attribute(DW_AT_low_pc).toULongLong(); 0074 if (lowPC == addr) 0075 return die; 0076 0077 foreach (const auto child, die->children()) { 0078 auto res = findByLowPCRecursive(child, addr); 0079 if (res) 0080 return res; 0081 } 0082 0083 return nullptr; 0084 } 0085 0086 DwarfDie* DwarfAddressRanges::dieForAddress(uint64_t addr) const 0087 { 0088 const auto cu = compilationUnitForAddress(addr); 0089 if (!cu) 0090 return nullptr; 0091 0092 foreach (const auto die, cu->children()) { 0093 auto res = findByLowPCRecursive(die, addr); 0094 if (res) 0095 return res; 0096 } 0097 0098 return nullptr; 0099 }