Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,13 @@ set_package_properties(LibRustcDemangle PROPERTIES
URL "https://github.com/alexcrichton/rustc-demangle"
TYPE RUNTIME)

find_package(LibDDemangle)
set_package_properties(LibDDemangle PROPERTIES
DESCRIPTION "Demangling for D symbols, written in D."
PURPOSE "Demangling of D symbols"
URL "https://github.com/lievenhey/d_demangler"
TYPE RUNTIME)


add_subdirectory(app)
add_subdirectory(tests)
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ add_qtc_library(perfparser_lib STATIC
perftracingdata.cpp perftracingdata.h
perfdwarfdiecache.cpp perfdwarfdiecache.h
perfeucompat.h
demangler.cpp demangler.h
)

if (Zstd_FOUND)
Expand Down
79 changes: 79 additions & 0 deletions app/demangler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Lieven Hey <lieven.hey@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Enterprise Perf Profiler Add-on.
**
** GNU General Public License Usage
** This file may be used under the terms of the GNU General Public License
** version 3 as published by the Free Software Foundation and appearing in
** the file LICENSE.GPLv3 included in the packaging of this file. Please
** review the following information to ensure the GNU General Public License
** requirements will be met: https://www.gnu.org/licenses/gpl.html.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/

#include "demangler.h"

#include <QLibrary>
#include <QDebug>

/* Demangler specification
* int demangler(const char* mangledSymbol, char* demangledBuffer, size_t bufferSize)
*
* size_t is platform dependent (4 bytes on 32 bit, 8 bytes on 64 bit)
* */

namespace {
bool startsWith(const char* string, const QByteArray& prefix) {
return strcmp(string, prefix.constData()) == 0;
}
}

Demangler::Demangler()
{
loadDemangleLib(QStringLiteral("rustc_demangle"), "rustc_demangle", QByteArrayLiteral("_R"));
loadDemangleLib(QStringLiteral("d_demangle"), "demangle_symbol", QByteArrayLiteral("_D"));
}

bool Demangler::demangle(const char *mangledSymbol, char *demangleBuffer, size_t demangleBufferLength)
{
// fast path, some languages (like rust since 1.37 or d) share a common prefix
// try these first
for (const auto& demangler : m_demanglers) {
if (startsWith(mangledSymbol, demangler.prefix)) {
if (demangler.demangler(mangledSymbol, demangleBuffer, demangleBufferLength)) {
return true;
}
}
}

for (const auto& demangler : m_demanglers) {
if (demangler.demangler(mangledSymbol, demangleBuffer, demangleBufferLength)) {
return true;
}
}
return false;
}

void Demangler::loadDemangleLib(const QString &name, const char* function, const QByteArray& prefix)
{
QLibrary lib(name);
if (!lib.load()) {
qDebug() << QStringLiteral("failed to load %1 library").arg(name)
<< lib.errorString();
return;
}
const auto rawSymbol = lib.resolve(function);
if (!rawSymbol) {
qDebug() << QStringLiteral("failed to resolve %1 function in library").arg(function)
<< lib.fileName() << lib.errorString();
return;
}

m_demanglers.push_back({prefix, reinterpret_cast<Demangler::demangler_t>(rawSymbol)});
}
44 changes: 44 additions & 0 deletions app/demangler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/****************************************************************************
**
** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Lieven Hey <lieven.hey@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Enterprise Perf Profiler Add-on.
**
** GNU General Public License Usage
** This file may be used under the terms of the GNU General Public License
** version 3 as published by the Free Software Foundation and appearing in
** the file LICENSE.GPLv3 included in the packaging of this file. Please
** review the following information to ensure the GNU General Public License
** requirements will be met: https://www.gnu.org/licenses/gpl.html.
**
** If you have questions regarding the use of this file, please use
** contact form at http://www.qt.io/contact-us
**
****************************************************************************/

#ifndef DEMANGLER_H
#define DEMANGLER_H

#include <QVector>

class Demangler
{
public:
Demangler();

bool demangle(const char* mangledSymbol, char* demangleBuffer, size_t demangleBufferLength);

private:
void loadDemangleLib(const QString& name, const char* function, const QByteArray& prefix);

using demangler_t = int (*) (const char*, char *, size_t);
struct DemangleInfo {
QByteArray prefix;
demangler_t demangler;
};

QVector<DemangleInfo> m_demanglers;
};

#endif // DEMANGLER_H
32 changes: 4 additions & 28 deletions app/perfdwarfdiecache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,9 @@

#include <dwarf.h>

#include <QLibrary>
#include <QDebug>
#include "demangler.h"

namespace {
bool rustc_demangle(const char *symbol, char *buffer, size_t bufferSize)
{
using demangler_t = int (*) (const char*, char *, size_t);
static const auto demangler = []() -> demangler_t {
QLibrary lib(QStringLiteral("rustc_demangle"));
if (!lib.load()) {
qDebug() << "failed to load rustc_demangle library, rust demangling support is not available."
<< lib.errorString();
return nullptr;
}
const auto rawSymbol = lib.resolve("rustc_demangle");
if (!rawSymbol) {
qDebug() << "failed to resolve rustc_demangle function in library"
<< lib.fileName() << lib.errorString();
return nullptr;
}
return reinterpret_cast<demangler_t>(rawSymbol);
}();

if (demangler)
return demangler(symbol, buffer, bufferSize);
else
return false;
}

enum class WalkResult
{
Recurse,
Expand Down Expand Up @@ -251,9 +225,11 @@ QByteArray demangle(const QByteArray &mangledName)
} else {
static size_t demangleBufferLength = 1024;
static char *demangleBuffer = reinterpret_cast<char *>(eu_compat_malloc(demangleBufferLength));
static Demangler demangler;

if (rustc_demangle(mangledName.constData(), demangleBuffer, demangleBufferLength))
if (demangler.demangle(mangledName, demangleBuffer, demangleBufferLength)) {
return demangleBuffer;
}

// Require GNU v3 ABI by the "_Z" prefix.
if (mangledName[0] == '_' && mangledName[1] == 'Z') {
Expand Down
22 changes: 22 additions & 0 deletions cmake/FindLibDDemangle.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
if (LIBD_DEMANGLE_LIBRARIES)
set (LibDDemangle_FIND_QUIETLY TRUE)
endif()

find_library(LIBD_DEMANGLE_LIBRARIES
NAMES
d_demangle
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH)

include (FindPackageHandleStandardArgs)

# handle the QUIETLY and REQUIRED arguments and set LIBRUSTC_DEMANGLE_FOUND to TRUE if all listed variables are TRUE
find_package_handle_standard_args(LibDDemangle DEFAULT_MSG
LIBD_DEMANGLE_LIBRARIES)

mark_as_advanced(LIBD_DEMANGLE_LIBRARIES)
6 changes: 4 additions & 2 deletions tests/auto/perfdata/perfdata.pro
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ SOURCES += \
../../../app/perfsymboltable.cpp \
../../../app/perftracingdata.cpp \
../../../app/perfunwind.cpp \
../../../app/perfdwarfdiecache.cpp
../../../app/perfdwarfdiecache.cpp \
../../../app/demangle.cpp

HEADERS += \
../../../app/perfaddresscache.h \
Expand All @@ -39,7 +40,8 @@ HEADERS += \
../../../app/perfsymboltable.h \
../../../app/perftracingdata.h \
../../../app/perfunwind.h \
../../../app/perfdwarfdiecache.h
../../../app/perfdwarfdiecache.h \
../../../app/demangle.h

RESOURCES += \
perfdata.qrc
Expand Down
2 changes: 2 additions & 0 deletions tests/auto/perfdata/perfdata.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@ QtcAutotest {
"../../../app/perftracingdata.h",
"../../../app/perfunwind.cpp",
"../../../app/perfunwind.h",
"../../../app/demangle.cpp",
"../../../app/demangle.h"
]
}