Debugger: Make ElfReader work remotely

This does not use the mmap optimization so it might turn out to be
too expensive for large files and slow connections. For now it seems
good enough for docker and normal test cases.

Change-Id: I0ba09bdbd6aac977209494a33099479f1f8eec0a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
hjk
2021-09-06 18:20:26 +02:00
parent ea215d612d
commit 736820a1a0
4 changed files with 34 additions and 20 deletions

View File

@@ -28,12 +28,13 @@
#include <QDir> #include <QDir>
#include <QDebug> #include <QDebug>
#include <QtEndian>
#include <new> // std::bad_alloc #include <new> // std::bad_alloc
namespace Utils { namespace Utils {
quint16 getHalfWord(const unsigned char *&s, const ElfData &context) static quint16 getHalfWord(const unsigned char *&s, const ElfData &context)
{ {
quint16 res; quint16 res;
if (context.endian == Elf_ELFDATA2MSB) if (context.endian == Elf_ELFDATA2MSB)
@@ -44,7 +45,7 @@ quint16 getHalfWord(const unsigned char *&s, const ElfData &context)
return res; return res;
} }
quint32 getWord(const unsigned char *&s, const ElfData &context) static quint32 getWord(const unsigned char *&s, const ElfData &context)
{ {
quint32 res; quint32 res;
if (context.endian == Elf_ELFDATA2MSB) if (context.endian == Elf_ELFDATA2MSB)
@@ -55,7 +56,7 @@ quint32 getWord(const unsigned char *&s, const ElfData &context)
return res; return res;
} }
quint64 getAddress(const unsigned char *&s, const ElfData &context) static quint64 getAddress(const unsigned char *&s, const ElfData &context)
{ {
quint64 res; quint64 res;
if (context.elfclass == Elf_ELFCLASS32) { if (context.elfclass == Elf_ELFCLASS32) {
@@ -74,7 +75,7 @@ quint64 getAddress(const unsigned char *&s, const ElfData &context)
return res; return res;
} }
quint64 getOffset(const unsigned char *&s, const ElfData &context) static quint64 getOffset(const unsigned char *&s, const ElfData &context)
{ {
return getAddress(s, context); return getAddress(s, context);
} }
@@ -99,10 +100,20 @@ static void parseProgramHeader(const uchar *s, ElfProgramHeader *sh, const ElfDa
sh->memsz = getWord(s, context); sh->memsz = getWord(s, context);
} }
ElfMapper::ElfMapper(const ElfReader *reader) : file(reader->m_binary) {} ElfMapper::ElfMapper(const ElfReader *reader)
: binary(reader->m_binary)
{}
bool ElfMapper::map() bool ElfMapper::map()
{ {
if (binary.needsDevice()) {
raw = binary.fileContents();
start = raw.constData();
fdlen = raw.size();
return fdlen > 0;
}
file.setFileName(binary.fileName());
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
return false; return false;
@@ -121,7 +132,7 @@ bool ElfMapper::map()
return true; return true;
} }
ElfReader::ElfReader(const QString &binary) ElfReader::ElfReader(const FilePath &binary)
: m_binary(binary) : m_binary(binary)
{ {
} }
@@ -132,10 +143,10 @@ ElfData ElfReader::readHeaders()
return m_elfData; return m_elfData;
} }
static inline QString msgInvalidElfObject(const QString &binary, const QString &why) static QString msgInvalidElfObject(const FilePath &binary, const QString &why)
{ {
return ElfReader::tr("\"%1\" is an invalid ELF object (%2)") return ElfReader::tr("\"%1\" is an invalid ELF object (%2)")
.arg(QDir::toNativeSeparators(binary), why); .arg(binary.toUserOutput(), why);
} }
ElfReader::Result ElfReader::readIt() ElfReader::Result ElfReader::readIt()
@@ -152,12 +163,12 @@ ElfReader::Result ElfReader::readIt()
const quint64 fdlen = mapper.fdlen; const quint64 fdlen = mapper.fdlen;
if (fdlen < 64) { if (fdlen < 64) {
m_errorString = tr("\"%1\" is not an ELF object (file too small)").arg(QDir::toNativeSeparators(m_binary)); m_errorString = tr("\"%1\" is not an ELF object (file too small)").arg(m_binary.toUserOutput());
return NotElf; return NotElf;
} }
if (strncmp(mapper.start, "\177ELF", 4) != 0) { if (strncmp(mapper.start, "\177ELF", 4) != 0) {
m_errorString = tr("\"%1\" is not an ELF object").arg(QDir::toNativeSeparators(m_binary)); m_errorString = tr("\"%1\" is not an ELF object").arg(m_binary.toUserOutput());
return NotElf; return NotElf;
} }

View File

@@ -27,12 +27,13 @@
#include "utils_global.h" #include "utils_global.h"
#include <qbytearray.h> #include "filepath.h"
#include <qendian.h>
#include <qfile.h> #include <QByteArray>
#include <qvector.h> #include <QCoreApplication>
#include <qcoreapplication.h> #include <QFile>
#include <qsharedpointer.h> #include <QSharedPointer>
#include <QVector>
namespace Utils { namespace Utils {
@@ -156,8 +157,9 @@ public:
class QTCREATOR_UTILS_EXPORT ElfReader class QTCREATOR_UTILS_EXPORT ElfReader
{ {
Q_DECLARE_TR_FUNCTIONS(Utils::ElfReader) Q_DECLARE_TR_FUNCTIONS(Utils::ElfReader)
public: public:
explicit ElfReader(const QString &binary); explicit ElfReader(const FilePath &binary);
enum Result { Ok, NotElf, Corrupt }; enum Result { Ok, NotElf, Corrupt };
ElfData readHeaders(); ElfData readHeaders();
@@ -169,7 +171,7 @@ private:
friend class ElfMapper; friend class ElfMapper;
Result readIt(); Result readIt();
QString m_binary; FilePath m_binary;
QString m_errorString; QString m_errorString;
ElfData m_elfData; ElfData m_elfData;
}; };
@@ -185,6 +187,7 @@ public:
QByteArray raw; QByteArray raw;
union { const char *start; const uchar *ustart; }; union { const char *start; const uchar *ustart; };
quint64 fdlen = 0; quint64 fdlen = 0;
FilePath binary;
}; };
} // namespace Utils } // namespace Utils

View File

@@ -2778,7 +2778,7 @@ void CppDebuggerEngine::validateRunParameters(DebuggerRunParameters &rp)
break; break;
} }
Utils::ElfReader reader(rp.symbolFile.toString()); ElfReader reader(rp.symbolFile);
const ElfData elfData = reader.readHeaders(); const ElfData elfData = reader.readHeaders();
const QString error = reader.errorString(); const QString error = reader.errorString();

View File

@@ -305,7 +305,7 @@ void ModulesHandler::updateModule(const Module &module)
} }
try { // MinGW occasionallly throws std::bad_alloc. try { // MinGW occasionallly throws std::bad_alloc.
ElfReader reader(path); ElfReader reader(FilePath::fromString(path));
item->module.elfData = reader.readHeaders(); item->module.elfData = reader.readHeaders();
item->update(); item->update();
} catch(...) { } catch(...) {