summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2017-04-19 12:10:53 +0200
committerUlf Hermann <ulf.hermann@qt.io>2017-04-28 10:53:38 +0000
commit5520a6b95c2be5e7e2c865894ae2c6fae41d1067 (patch)
treec40c6fb32415e94da1cdf2dd54493e2c510ad106
parent4abd9df38adc6e324472730413885c0a194a499c (diff)
Use open, close, free, cxa_demangle from elfutils
We cannot handle resources passed to and from elfutils with a different C library. Change-Id: I47e789b016d13c249d82a7bd1091cd5fb769ce9d Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r--app/app.pro4
-rw-r--r--app/perfsymboltable.cpp50
-rw-r--r--app/perfsymboltable.h2
-rw-r--r--perfparser.pro2
4 files changed, 43 insertions, 15 deletions
diff --git a/app/app.pro b/app/app.pro
index 039c32c..626e801 100644
--- a/app/app.pro
+++ b/app/app.pro
@@ -29,6 +29,10 @@ include(../paths.pri)
}
LIBS += -ldw -lelf
+
+ win32 {
+ LIBS += -leu_compat
+ }
}
linux-g++*:!isEmpty(PERFPARSER_ELFUTILS_INSTALLDIR) {
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp
index a448f96..b9b2bbb 100644
--- a/app/perfsymboltable.cpp
+++ b/app/perfsymboltable.cpp
@@ -31,8 +31,26 @@
#include <QStack>
#include <cstring>
-#ifdef Q_OS_UNIX
+#include <fcntl.h>
+#ifdef Q_OS_WIN
+#include <io.h>
+extern "C" {
+ extern char *eu_compat_demangle(const char *mangled_name, char *output_buffer,
+ size_t *length, int *status);
+ extern int eu_compat_open(const char *, int);
+ extern int eu_compat_close(int);
+ extern void *eu_compat_malloc(size_t);
+ extern void eu_compat_free(void *);
+}
+#else
#include <cxxabi.h>
+#include <unistd.h>
+#define eu_compat_open open
+#define eu_compat_close close
+#define eu_compat_malloc malloc
+#define eu_compat_free free
+#define eu_compat_demangle abi::__cxa_demangle
+#define O_BINARY 0
#endif
PerfSymbolTable::PerfSymbolTable(quint32 pid, Dwfl_Callbacks *callbacks, PerfUnwind *parent) :
@@ -40,6 +58,7 @@ PerfSymbolTable::PerfSymbolTable(quint32 pid, Dwfl_Callbacks *callbacks, PerfUnw
+ QString::fromLatin1("perf-%1.map").arg(pid)),
m_cacheIsDirty(false),
m_unwind(parent),
+ m_firstElfFile(-1),
m_firstElf(nullptr),
m_callbacks(callbacks),
m_pid(pid)
@@ -51,6 +70,7 @@ PerfSymbolTable::~PerfSymbolTable()
{
dwfl_end(m_dwfl);
elf_end(m_firstElf);
+ eu_compat_close(m_firstElfFile);
}
static pid_t nextThread(Dwfl *dwfl, void *arg, void **threadArg)
@@ -271,19 +291,23 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QByteArray &
PerfUnwind::tr("Could not find ELF file for %1. "
"This can break stack unwinding "
"and lead to missing symbols.").arg(filePath));
- } else if (!m_firstElfFile.isOpen()) {
- m_firstElfFile.setFileName(fullPath.absoluteFilePath());
- if (!m_firstElfFile.open(QIODevice::ReadOnly)) {
- qWarning() << "Failed to open file:" << m_firstElfFile.errorString();
+ } else if (!m_firstElf) {
+ m_firstElfFile = eu_compat_open(fullPath.absoluteFilePath().toLocal8Bit().constData(),
+ O_RDONLY | O_BINARY);
+ if (m_firstElfFile == -1) {
+ qWarning() << "Failed to open file:" << fullPath.absoluteFilePath();
} else {
- m_firstElf = elf_begin(m_firstElfFile.handle(), ELF_C_READ, nullptr);
+ m_firstElf = elf_begin(m_firstElfFile, ELF_C_READ, nullptr);
if (!m_firstElf) {
qWarning() << "Failed to begin elf:" << elf_errmsg(elf_errno());
- m_firstElfFile.close();
- } else if (m_firstElf && elf_kind(m_firstElf) == ELF_K_NONE) {
+ eu_compat_close(m_firstElfFile);
+ m_firstElfFile = -1;
+ } else if (elf_kind(m_firstElf) == ELF_K_NONE) {
// not actually an elf object
+ elf_end(m_firstElf);
m_firstElf = nullptr;
- m_firstElfFile.close();
+ eu_compat_close(m_firstElfFile);
+ m_firstElfFile = -1;
}
}
}
@@ -317,7 +341,6 @@ static QByteArray dieName(Dwarf_Die *die)
static QByteArray demangle(const QByteArray &mangledName)
{
-#ifdef Q_OS_UNIX
if (mangledName.length() < 3) {
return mangledName;
} else {
@@ -327,13 +350,12 @@ static QByteArray demangle(const QByteArray &mangledName)
// Require GNU v3 ABI by the "_Z" prefix.
if (mangledName[0] == '_' && mangledName[1] == 'Z') {
int status = -1;
- char *dsymname = abi::__cxa_demangle(mangledName, demangleBuffer, &demangleBufferLength,
- &status);
+ char *dsymname = eu_compat_demangle(mangledName, demangleBuffer, &demangleBufferLength,
+ &status);
if (status == 0)
return demangleBuffer = dsymname;
}
}
-#endif
return mangledName;
}
@@ -540,7 +562,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
break;
}
}
- free(scopes);
+ eu_compat_free(scopes);
addressLocation.parentLocationId = m_unwind->lookupLocation(functionLocation);
if (die && !m_unwind->hasSymbol(addressLocation.parentLocationId))
diff --git a/app/perfsymboltable.h b/app/perfsymboltable.h
index 4f9503b..9478d1c 100644
--- a/app/perfsymboltable.h
+++ b/app/perfsymboltable.h
@@ -89,7 +89,7 @@ private:
PerfUnwind *m_unwind;
Dwfl *m_dwfl;
// elf used to detect architecture
- QFile m_firstElfFile;
+ int m_firstElfFile;
Elf *m_firstElf;
PerfElfMap m_elfs;
diff --git a/perfparser.pro b/perfparser.pro
index f37a0fe..1975846 100644
--- a/perfparser.pro
+++ b/perfparser.pro
@@ -24,6 +24,8 @@ defineReplace(elfutilsLibraryName) {
$$ELFUTILS_INSTALL_DIR/lib/$$elfutilsLibraryName(elf, 1) \
$$ELFUTILS_INSTALL_DIR/lib/$$elfutilsLibraryName(dw, 1)
+ win32: inst_elfutils.files += $$ELFUTILS_INSTALL_DIR/lib/eu_compat.dll
+
inst_elfutils.path = $$PERFPARSER_ELFUTILS_INSTALLDIR
inst_elfutils.CONFIG += no_check_exist no_default_install