summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLieven Hey <lieven.hey@kdab.com>2021-09-15 14:57:23 +0200
committerMilian Wolff <milian.wolff@kdab.com>2022-06-08 20:17:56 +0000
commite50bc913563e445888f08de03007ff91bcd5dd1e (patch)
treebef0a5d27399ca21c7e10ff172671948de7b44c0
parentf2e019928c5f6449724319f08bd5f0d8a1532ad1 (diff)
add support for d symbol demangling
I added a system that simplifies adding new demanglers and provides a fast path when demangling symbols Change-Id: Ie5ca43632b53e41c0a4214772193af09ca4593cc Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--CMakeLists.txt7
-rw-r--r--app/CMakeLists.txt1
-rw-r--r--app/demangler.cpp79
-rw-r--r--app/demangler.h44
-rw-r--r--app/perfdwarfdiecache.cpp32
-rw-r--r--cmake/FindLibDDemangle.cmake22
-rw-r--r--tests/auto/perfdata/perfdata.pro6
-rw-r--r--tests/auto/perfdata/perfdata.qbs2
8 files changed, 163 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d379096..3038294 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,5 +15,12 @@ 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)
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 6efe84b..4107a11 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -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)
diff --git a/app/demangler.cpp b/app/demangler.cpp
new file mode 100644
index 0000000..ce9d630
--- /dev/null
+++ b/app/demangler.cpp
@@ -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)});
+}
diff --git a/app/demangler.h b/app/demangler.h
new file mode 100644
index 0000000..edb1244
--- /dev/null
+++ b/app/demangler.h
@@ -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
diff --git a/app/perfdwarfdiecache.cpp b/app/perfdwarfdiecache.cpp
index dfc6f90..6f9243f 100644
--- a/app/perfdwarfdiecache.cpp
+++ b/app/perfdwarfdiecache.cpp
@@ -24,35 +24,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,
@@ -252,9 +226,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') {
diff --git a/cmake/FindLibDDemangle.cmake b/cmake/FindLibDDemangle.cmake
new file mode 100644
index 0000000..04f0ecc
--- /dev/null
+++ b/cmake/FindLibDDemangle.cmake
@@ -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)
diff --git a/tests/auto/perfdata/perfdata.pro b/tests/auto/perfdata/perfdata.pro
index 145ed79..2e32aa6 100644
--- a/tests/auto/perfdata/perfdata.pro
+++ b/tests/auto/perfdata/perfdata.pro
@@ -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 \
@@ -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
diff --git a/tests/auto/perfdata/perfdata.qbs b/tests/auto/perfdata/perfdata.qbs
index ef9bb3d..033a0a3 100644
--- a/tests/auto/perfdata/perfdata.qbs
+++ b/tests/auto/perfdata/perfdata.qbs
@@ -37,5 +37,7 @@ QtcAutotest {
"../../../app/perftracingdata.h",
"../../../app/perfunwind.cpp",
"../../../app/perfunwind.h",
+ "../../../app/demangle.cpp",
+ "../../../app/demangle.h"
]
}