forked from qt-creator/qt-creator
debugger: reshuffle sections in module data
Keep track of elf section headers, add a dumper for Utils::ElfSection etc. Change-Id: I06d01c0de01ffc6b827a4a79bdc91fdb3e761d75 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -2431,6 +2431,10 @@ def qdump__CPlusPlus__Internal__Value(d, value):
|
||||
d.putValue(value["l"])
|
||||
d.putPlainChildren(value)
|
||||
|
||||
def qdump__Utils__ElfSection(d, value):
|
||||
d.putByteArrayValue(value["name"])
|
||||
d.putPlainChildren(value)
|
||||
|
||||
def qdump__CPlusPlus__Token(d, value):
|
||||
k = value["f"]["kind"];
|
||||
if long(k) == 6:
|
||||
|
||||
@@ -225,6 +225,13 @@ ElfReader::Result ElfReader::parse(const char *dataStart, quint64 fdlen,
|
||||
section.index = strtab.name;
|
||||
section.offset = strtab.offset;
|
||||
section.size = strtab.size;
|
||||
if (section.name == ".gdb_index")
|
||||
sections->symbolsType = FastSymbols;
|
||||
else if (section.name == ".debug_info")
|
||||
sections->symbolsType = PlainSymbols;
|
||||
else if (section.name == ".gnu_debuglink")
|
||||
sections->symbolsType = SeparateSymbols;
|
||||
sections->sections.append(section);
|
||||
}
|
||||
|
||||
s += e_shentsize;
|
||||
|
||||
@@ -48,11 +48,22 @@
|
||||
#include "utils_global.h"
|
||||
|
||||
#include <qendian.h>
|
||||
#include <qlist.h>
|
||||
#include <qstring.h>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
class ElfSectionHeader;
|
||||
class ElfSections;
|
||||
|
||||
enum DebugSymbolsType
|
||||
{
|
||||
UnknownSymbols, // Unknown.
|
||||
NoSymbols, // No usable symbols.
|
||||
SeparateSymbols, // Symbols mentioned, but not in binary.
|
||||
PlainSymbols, // Ordinary symbols available.
|
||||
FastSymbols // Dwarf index available.
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT ElfSection
|
||||
{
|
||||
@@ -64,8 +75,6 @@ public:
|
||||
quint64 size;
|
||||
};
|
||||
|
||||
typedef QList<ElfSection> ElfSections;
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT ElfReader
|
||||
{
|
||||
public:
|
||||
@@ -86,6 +95,15 @@ private:
|
||||
ElfEndian m_endian;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT ElfSections
|
||||
{
|
||||
public:
|
||||
ElfSections() : symbolsType(UnknownSymbols) {}
|
||||
|
||||
QList<ElfSection> sections;
|
||||
DebugSymbolsType symbolsType;
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
#endif // UTILS_ELFREADER_H
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -499,8 +500,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
module.hostPath = _(result.findChild("host-name").data());
|
||||
module.modulePath = _(result.findChild("target-name").data());
|
||||
module.moduleName = QFileInfo(module.hostPath).baseName();
|
||||
examineModule(&module);
|
||||
modulesHandler()->addModule(module);
|
||||
modulesHandler()->updateModule(module);
|
||||
} else if (asyncClass == "library-unloaded") {
|
||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||
// target-name="/usr/lib/libdrm.so.2",
|
||||
@@ -730,7 +730,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
Task task(Task::Warning,
|
||||
tr("Missing debug information for %1\nTry: %2")
|
||||
.arg(m_lastMissingDebugInfo).arg(cmd),
|
||||
Utils::FileName(), 0, Core::Id("Debuginfo"));
|
||||
FileName(), 0, Core::Id("Debuginfo"));
|
||||
|
||||
taskHub()->addTask(task);
|
||||
|
||||
@@ -3479,7 +3479,6 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
||||
module.moduleName = nameFromPath(module.modulePath);
|
||||
module.symbolsRead =
|
||||
(symbolsRead == QLatin1String("Yes") ? Module::ReadOk : Module::ReadFailed);
|
||||
examineModule(&module);
|
||||
handler->updateModule(module);
|
||||
found = true;
|
||||
} else if (line.trimmed().startsWith(QLatin1String("No"))) {
|
||||
@@ -3490,7 +3489,6 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
||||
module.endAddress = 0;
|
||||
module.modulePath = ts.readLine().trimmed();
|
||||
module.moduleName = nameFromPath(module.modulePath);
|
||||
examineModule(&module);
|
||||
handler->updateModule(module);
|
||||
found = true;
|
||||
}
|
||||
@@ -3510,44 +3508,18 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
||||
module.startAddress =
|
||||
item.findChild("loaded_addr").data().toULongLong(0, 0);
|
||||
module.endAddress = 0; // FIXME: End address not easily available.
|
||||
examineModule(&module);
|
||||
handler->updateModule(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::examineModule(Module *module)
|
||||
{
|
||||
using namespace Utils;
|
||||
ElfReader reader(module->modulePath);
|
||||
ElfSections sections = reader.sections();
|
||||
module->symbolsType = Module::NoSymbols;
|
||||
for (int i = 0, n = sections.size(); i != n; ++i) {
|
||||
const QByteArray &name = sections.at(i).name;
|
||||
if (name == ".gdb_index") {
|
||||
module->symbolsType = Module::FastSymbols;
|
||||
break;
|
||||
}
|
||||
if (name == ".debug_info") {
|
||||
module->symbolsType = Module::PlainSymbols;
|
||||
break;
|
||||
}
|
||||
if (name == ".gnu_debuglink") {
|
||||
module->symbolsType = Module::SeparateSymbols;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::examineModules()
|
||||
{
|
||||
ModulesHandler *handler = modulesHandler();
|
||||
foreach (Module module, handler->modules()) {
|
||||
if (module.symbolsType == Module::UnknownSymbols) {
|
||||
examineModule(&module);
|
||||
modulesHandler()->updateModule(module);
|
||||
}
|
||||
if (module.sections.symbolsType == UnknownSymbols)
|
||||
handler->updateModule(module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5038,7 +5010,7 @@ void GdbEngine::handleAdapterStarted()
|
||||
module.endAddress = 0;
|
||||
module.modulePath = startParameters().executable;
|
||||
module.moduleName = QLatin1String("<executable>");
|
||||
modulesHandler()->addModule(module);
|
||||
modulesHandler()->updateModule(module);
|
||||
}
|
||||
|
||||
void GdbEngine::setupInferior()
|
||||
@@ -5380,7 +5352,6 @@ bool GdbEngine::attemptQuickStart() const
|
||||
|
||||
void GdbEngine::checkForReleaseBuild()
|
||||
{
|
||||
using namespace Utils;
|
||||
QString binary = startParameters().executable;
|
||||
ElfReader reader(binary);
|
||||
ElfSections sections = reader.sections();
|
||||
@@ -5404,7 +5375,7 @@ void GdbEngine::checkForReleaseBuild()
|
||||
}
|
||||
|
||||
QSet<QByteArray> seen;
|
||||
foreach (const ElfSection §ion, sections) {
|
||||
foreach (const ElfSection §ion, sections.sections) {
|
||||
msg.append(section.name);
|
||||
msg.append(' ');
|
||||
if (interesting.contains(section.name))
|
||||
@@ -5417,12 +5388,12 @@ void GdbEngine::checkForReleaseBuild()
|
||||
return;
|
||||
}
|
||||
|
||||
if (sections.isEmpty()) {
|
||||
if (sections.sections.isEmpty()) {
|
||||
showMessage(_("NO SECTION HEADERS FOUND. IS THIS AN EXECUTABLE?"));
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const ElfSection §ion, sections) {
|
||||
foreach (const ElfSection §ion, sections.sections) {
|
||||
if (section.name == ".debug_info")
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -514,7 +514,6 @@ private: ////////// View & Data Stuff //////////
|
||||
void requestModuleSymbols(const QString &moduleName);
|
||||
void reloadModules();
|
||||
void examineModules();
|
||||
void examineModule(Module *module);
|
||||
void reloadModulesInternal();
|
||||
void handleModulesList(const GdbResponse &response);
|
||||
void handleShowModuleSymbols(const GdbResponse &response);
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
|
||||
#include "moduleshandler.h"
|
||||
|
||||
#include <utils/elfreader.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -65,7 +67,6 @@ public:
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
void clearModel();
|
||||
void addModule(const Module &module);
|
||||
void removeModule(const QString &modulePath);
|
||||
void setModules(const Modules &modules);
|
||||
void updateModule(const Module &module);
|
||||
@@ -123,41 +124,41 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
||||
break;
|
||||
case 3:
|
||||
if (role == Qt::DisplayRole)
|
||||
switch (module.symbolsType) {
|
||||
case Module::UnknownSymbols:
|
||||
switch (module.sections.symbolsType) {
|
||||
case UnknownSymbols:
|
||||
return ModulesHandler::tr("unknown");
|
||||
case Module::NoSymbols:
|
||||
case NoSymbols:
|
||||
return ModulesHandler::tr("none");
|
||||
case Module::PlainSymbols:
|
||||
case PlainSymbols:
|
||||
return ModulesHandler::tr("plain");
|
||||
case Module::FastSymbols:
|
||||
case FastSymbols:
|
||||
return ModulesHandler::tr("fast");
|
||||
case Module::SeparateSymbols:
|
||||
case SeparateSymbols:
|
||||
return ModulesHandler::tr("separate");
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
switch (module.symbolsType) {
|
||||
case Module::UnknownSymbols:
|
||||
switch (module.sections.symbolsType) {
|
||||
case UnknownSymbols:
|
||||
return ModulesHandler::tr(
|
||||
"It is unknown whether this module contains debug "
|
||||
"information.\nUse \"Examine Symbols\" from the "
|
||||
"context menu to initiate a check.");
|
||||
case Module::NoSymbols:
|
||||
case NoSymbols:
|
||||
return ModulesHandler::tr(
|
||||
"This module neither contains nor references debug "
|
||||
"information.\nStepping into the module or setting "
|
||||
"breakpoints by file and line will not work.");
|
||||
case Module::PlainSymbols:
|
||||
case PlainSymbols:
|
||||
return ModulesHandler::tr(
|
||||
"This module contains debug information.\nStepping "
|
||||
"into the module or setting breakpoints by file and "
|
||||
"is expected to work.");
|
||||
case Module::FastSymbols:
|
||||
case FastSymbols:
|
||||
return ModulesHandler::tr(
|
||||
"This module contains debug information.\nStepping "
|
||||
"into the module or setting breakpoints by file and "
|
||||
"is expected to work.");
|
||||
case Module::SeparateSymbols:
|
||||
case SeparateSymbols:
|
||||
return ModulesHandler::tr(
|
||||
"This module does not contains debug information "
|
||||
"itself, but contains a reference to external "
|
||||
@@ -183,13 +184,6 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ModulesModel::addModule(const Module &m)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_modules.size(), m_modules.size());
|
||||
m_modules.push_back(m);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ModulesModel::setModules(const Modules &m)
|
||||
{
|
||||
m_modules = m;
|
||||
@@ -225,10 +219,17 @@ void ModulesModel::removeModule(const QString &modulePath)
|
||||
void ModulesModel::updateModule(const Module &module)
|
||||
{
|
||||
const int row = indexOfModule(module.modulePath);
|
||||
ElfReader reader(module.modulePath);
|
||||
ElfSections sections = reader.sections();
|
||||
if (row == -1) {
|
||||
addModule(module);
|
||||
const int n = m_modules.size();
|
||||
beginInsertRows(QModelIndex(), n, n);
|
||||
m_modules.push_back(module);
|
||||
m_modules.back().sections = sections;
|
||||
endInsertRows();
|
||||
} else {
|
||||
m_modules[row] = module;
|
||||
m_modules[row].sections = sections;
|
||||
dataChanged(index(row, 0, QModelIndex()), index(row, 4, QModelIndex()));
|
||||
}
|
||||
}
|
||||
@@ -256,11 +257,6 @@ void ModulesHandler::removeAll()
|
||||
m_model->clearModel();
|
||||
}
|
||||
|
||||
void ModulesHandler::addModule(const Module &module)
|
||||
{
|
||||
m_model->addModule(module);
|
||||
}
|
||||
|
||||
void ModulesHandler::removeModule(const QString &modulePath)
|
||||
{
|
||||
m_model->removeModule(modulePath);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#ifndef DEBUGGER_MODULESHANDLER_H
|
||||
#define DEBUGGER_MODULESHANDLER_H
|
||||
|
||||
#include <utils/elfreader.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
@@ -73,7 +75,7 @@ typedef QVector<Symbol> Symbols;
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
Module() : symbolsRead(UnknownReadState), symbolsType(UnknownSymbols) {}
|
||||
Module() : symbolsRead(UnknownReadState) {}
|
||||
|
||||
public:
|
||||
enum SymbolReadState {
|
||||
@@ -81,20 +83,14 @@ public:
|
||||
ReadFailed, // Tried to read, but failed.
|
||||
ReadOk // Dwarf index available.
|
||||
};
|
||||
enum SymbolType {
|
||||
UnknownSymbols, // Unknown.
|
||||
NoSymbols, // No usable symbols.
|
||||
SeparateSymbols, // Symbols mentioned, but not in binary.
|
||||
PlainSymbols, // Ordinary symbols available.
|
||||
FastSymbols // Dwarf index available.
|
||||
};
|
||||
QString moduleName;
|
||||
QString modulePath;
|
||||
QString hostPath;
|
||||
SymbolReadState symbolsRead;
|
||||
SymbolType symbolsType;
|
||||
quint64 startAddress;
|
||||
quint64 endAddress;
|
||||
|
||||
Utils::ElfSections sections;
|
||||
};
|
||||
|
||||
typedef QVector<Module> Modules;
|
||||
@@ -116,7 +112,6 @@ public:
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
void setModules(const Modules &modules);
|
||||
void addModule(const Module &module);
|
||||
void removeModule(const QString &modulePath);
|
||||
void updateModule(const Module &module);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user