File indexing completed on 2024-05-19 05:44:10

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 "config-elf-dissector.h"
0019 #include "dwarfprinter.h"
0020 
0021 #if HAVE_DWARF
0022 #include <dwarf/dwarfexpression.h>
0023 #include <dwarf/dwarfranges.h>
0024 #include <dwarf/dwarfdie.h>
0025 
0026 #include <libdwarf.h>
0027 #endif
0028 
0029 #include <QMetaType>
0030 #include <QString>
0031 
0032 #include <cassert>
0033 #include <type_traits>
0034 
0035 const char* DwarfPrinter::virtuality(DwarfVirtuality v)
0036 {
0037 #if HAVE_DWARF
0038     const char *str = nullptr;
0039     const auto res = dwarf_get_VIRTUALITY_name(static_cast<int>(v), &str);
0040     if (res != DW_DLV_OK)
0041         return nullptr;
0042     return str;
0043 #else
0044     return nullptr;
0045 #endif
0046 }
0047 
0048 QByteArray DwarfPrinter::ranges(const DwarfRanges& ranges)
0049 {
0050 #if HAVE_DWARF
0051     QByteArray b;
0052     for (int i = 0; i < ranges.size(); ++i) {
0053         const auto r = ranges.entry(i);
0054         static_assert(std::is_same< decltype(r->dwr_addr1), Dwarf_Addr >::value, "Incompatible DWARFs");
0055         static_assert(std::is_same< decltype(r->dwr_addr2), Dwarf_Addr >::value, "Incompatible DWARFs");
0056         static_assert( std::is_convertible<Dwarf_Addr, qulonglong>::value, "Incompatible DWARFs" );
0057         if (r->dwr_type == DW_RANGES_ADDRESS_SELECTION) {
0058             if (r->dwr_addr2 != 0)
0059                 b += "base address: 0x" + QByteArray::number(static_cast<qulonglong>(r->dwr_addr2), 16) + ' ';
0060         } else {
0061             b += "[0x" + QByteArray::number(static_cast<qulonglong>(r->dwr_addr1), 16);
0062             b += ", 0x" + QByteArray::number(static_cast<qulonglong>(r->dwr_addr2), 16);
0063             b += "]\n";
0064         }
0065     }
0066     return b;
0067 #else
0068     return {};
0069 #endif
0070 }
0071 
0072 void DwarfPrinter::registerConverterFunctions()
0073 {
0074 #if HAVE_DWARF
0075     QMetaType::registerConverter<DwarfExpression, QString>(&DwarfExpression::displayString);
0076     QMetaType::registerConverter<DwarfVirtuality, QString>([](DwarfVirtuality v){
0077         return QString::fromLatin1(DwarfPrinter::virtuality(v));
0078     });
0079     QMetaType::registerConverter<DwarfRanges, QString>([](const DwarfRanges &r){
0080         return QString::fromLatin1(DwarfPrinter::ranges(r));
0081     });
0082 #endif
0083 }
0084 
0085 QString DwarfPrinter::dieRichText(DwarfDie* die)
0086 {
0087 #if HAVE_DWARF
0088     assert(die);
0089     QString s;
0090     s += "TAG: " + QLatin1String(die->tagName()) + "<br/>";
0091     s += "Name: " + QString::fromUtf8(die->name()).toHtmlEscaped() + "<br/>";
0092     s += "Offset: " + QString::number(die->offset()) + "<br/>";
0093     foreach (const auto attrType, die->attributes()) {
0094         const QVariant attrValue = die->attribute(attrType);
0095         QString attrValueStr;
0096         if (DwarfDie *die = attrValue.value<DwarfDie*>())
0097             attrValueStr = die->displayName();
0098         else
0099             attrValueStr = attrValue.toString();
0100         s += QLatin1String(die->attributeName(attrType)) + ": " + attrValueStr.toHtmlEscaped() + "<br/>";
0101     }
0102     return s;
0103 #else
0104     return {};
0105 #endif
0106 }