forked from qt-creator/qt-creator
debugger: more modulehandler polishing
Change-Id: I2382a597783512b566118cccf772ff530cdf9026 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -117,18 +117,21 @@ QString DumperHelper::msgPtraceError(DebuggerStartMode sm)
|
|||||||
{
|
{
|
||||||
if (sm == StartInternal) {
|
if (sm == StartInternal) {
|
||||||
return QCoreApplication::translate("QtDumperHelper",
|
return QCoreApplication::translate("QtDumperHelper",
|
||||||
"ptrace: Operation not permitted.\n\n"
|
"ptrace: Operation not permitted.\n\n"
|
||||||
"Could not attach to the process. Check the settings of\n"
|
"Could not attach to the process. "
|
||||||
"/proc/sys/kernel/yama/ptrace_scope\n"
|
"Make sure no other debugger traces this process.\n"
|
||||||
"For more details, see/etc/sysctl.d/10-ptrace.conf\n");
|
"Check the settings of\n"
|
||||||
} else {
|
"/proc/sys/kernel/yama/ptrace_scope\n"
|
||||||
return QCoreApplication::translate("QtDumperHelper",
|
"For more details, see /etc/sysctl.d/10-ptrace.conf\n");
|
||||||
"ptrace: Operation not permitted.\n\n"
|
|
||||||
"Could not attach to the process. If your uid matches the uid\n"
|
|
||||||
"of the target process, check the settings of\n"
|
|
||||||
"/proc/sys/kernel/yama/ptrace_scope\n"
|
|
||||||
"For more details, see/etc/sysctl.d/10-ptrace.conf\n");
|
|
||||||
}
|
}
|
||||||
|
return QCoreApplication::translate("QtDumperHelper",
|
||||||
|
"ptrace: Operation not permitted.\n\n"
|
||||||
|
"Could not attach to the process. "
|
||||||
|
"Make sure no other debugger traces this process.\n"
|
||||||
|
"If your uid matches the uid\n"
|
||||||
|
"of the target process, check the settings of\n"
|
||||||
|
"/proc/sys/kernel/yama/ptrace_scope\n"
|
||||||
|
"For more details, see /etc/sysctl.d/10-ptrace.conf\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void formatQtVersion(int v, QTextStream &str)
|
static inline void formatQtVersion(int v, QTextStream &str)
|
||||||
|
|||||||
@@ -483,11 +483,24 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
// target-name="/usr/lib/libdrm.so.2",
|
// target-name="/usr/lib/libdrm.so.2",
|
||||||
// host-name="/usr/lib/libdrm.so.2",
|
// host-name="/usr/lib/libdrm.so.2",
|
||||||
// symbols-loaded="0"
|
// symbols-loaded="0"
|
||||||
|
|
||||||
|
// id="/lib/i386-linux-gnu/libc.so.6"
|
||||||
|
// target-name="/lib/i386-linux-gnu/libc.so.6"
|
||||||
|
// host-name="/lib/i386-linux-gnu/libc.so.6"
|
||||||
|
// symbols-loaded="0",thread-group="i1"
|
||||||
QByteArray id = result.findChild("id").data();
|
QByteArray id = result.findChild("id").data();
|
||||||
if (!id.isEmpty())
|
if (!id.isEmpty())
|
||||||
showStatusMessage(tr("Library %1 loaded").arg(_(id)), 1000);
|
showStatusMessage(tr("Library %1 loaded").arg(_(id)), 1000);
|
||||||
progressPing();
|
progressPing();
|
||||||
invalidateSourcesList();
|
invalidateSourcesList();
|
||||||
|
Module module;
|
||||||
|
module.startAddress = 0;
|
||||||
|
module.endAddress = 0;
|
||||||
|
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);
|
||||||
} else if (asyncClass == "library-unloaded") {
|
} else if (asyncClass == "library-unloaded") {
|
||||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||||
// target-name="/usr/lib/libdrm.so.2",
|
// target-name="/usr/lib/libdrm.so.2",
|
||||||
@@ -1676,10 +1689,6 @@ void GdbEngine::handleStop2(const GdbMi &data)
|
|||||||
isStopperThread = true;
|
isStopperThread = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is for display only.
|
|
||||||
if (m_modulesListOutdated)
|
|
||||||
reloadModulesInternal();
|
|
||||||
|
|
||||||
if (m_breakListOutdated) {
|
if (m_breakListOutdated) {
|
||||||
reloadBreakListInternal();
|
reloadBreakListInternal();
|
||||||
} else {
|
} else {
|
||||||
@@ -3353,7 +3362,7 @@ void GdbEngine::loadSymbolsForStack()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needUpdate) {
|
if (needUpdate) {
|
||||||
reloadModulesInternal();
|
//reloadModulesInternal();
|
||||||
reloadBreakListInternal();
|
reloadBreakListInternal();
|
||||||
reloadStack(true);
|
reloadStack(true);
|
||||||
updateLocals();
|
updateLocals();
|
||||||
@@ -3442,7 +3451,6 @@ void GdbEngine::reloadModules()
|
|||||||
|
|
||||||
void GdbEngine::reloadModulesInternal()
|
void GdbEngine::reloadModulesInternal()
|
||||||
{
|
{
|
||||||
m_modulesListOutdated = false;
|
|
||||||
postCommand("info shared", NeedsStop, CB(handleModulesList));
|
postCommand("info shared", NeedsStop, CB(handleModulesList));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3453,15 +3461,16 @@ static QString nameFromPath(const QString &path)
|
|||||||
|
|
||||||
void GdbEngine::handleModulesList(const GdbResponse &response)
|
void GdbEngine::handleModulesList(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
Modules modules;
|
|
||||||
if (response.resultClass == GdbResultDone) {
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
ModulesHandler *handler = modulesHandler();
|
||||||
|
Module module;
|
||||||
// That's console-based output, likely Linux or Windows,
|
// That's console-based output, likely Linux or Windows,
|
||||||
// but we can avoid the target dependency here.
|
// but we can avoid the target dependency here.
|
||||||
QString data = QString::fromLocal8Bit(response.consoleStreamOutput);
|
QString data = QString::fromLocal8Bit(response.consoleStreamOutput);
|
||||||
QTextStream ts(&data, QIODevice::ReadOnly);
|
QTextStream ts(&data, QIODevice::ReadOnly);
|
||||||
|
bool found = false;
|
||||||
while (!ts.atEnd()) {
|
while (!ts.atEnd()) {
|
||||||
QString line = ts.readLine();
|
QString line = ts.readLine();
|
||||||
Module module;
|
|
||||||
QString symbolsRead;
|
QString symbolsRead;
|
||||||
QTextStream ts(&line, QIODevice::ReadOnly);
|
QTextStream ts(&line, QIODevice::ReadOnly);
|
||||||
if (line.startsWith(QLatin1String("0x"))) {
|
if (line.startsWith(QLatin1String("0x"))) {
|
||||||
@@ -3470,7 +3479,9 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
|||||||
module.moduleName = nameFromPath(module.modulePath);
|
module.moduleName = nameFromPath(module.modulePath);
|
||||||
module.symbolsRead =
|
module.symbolsRead =
|
||||||
(symbolsRead == QLatin1String("Yes") ? Module::ReadOk : Module::ReadFailed);
|
(symbolsRead == QLatin1String("Yes") ? Module::ReadOk : Module::ReadFailed);
|
||||||
modules.append(module);
|
examineModule(&module);
|
||||||
|
handler->updateModule(module);
|
||||||
|
found = true;
|
||||||
} else if (line.trimmed().startsWith(QLatin1String("No"))) {
|
} else if (line.trimmed().startsWith(QLatin1String("No"))) {
|
||||||
// gdb 6.4 symbianelf
|
// gdb 6.4 symbianelf
|
||||||
ts >> symbolsRead;
|
ts >> symbolsRead;
|
||||||
@@ -3479,17 +3490,18 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
|||||||
module.endAddress = 0;
|
module.endAddress = 0;
|
||||||
module.modulePath = ts.readLine().trimmed();
|
module.modulePath = ts.readLine().trimmed();
|
||||||
module.moduleName = nameFromPath(module.modulePath);
|
module.moduleName = nameFromPath(module.modulePath);
|
||||||
modules.append(module);
|
examineModule(&module);
|
||||||
|
handler->updateModule(module);
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (modules.isEmpty()) {
|
if (!found) {
|
||||||
// Mac has^done,shlib-info={num="1",name="dyld",kind="-",
|
// Mac has^done,shlib-info={num="1",name="dyld",kind="-",
|
||||||
// dyld-addr="0x8fe00000",reason="dyld",requested-state="Y",
|
// dyld-addr="0x8fe00000",reason="dyld",requested-state="Y",
|
||||||
// state="Y",path="/usr/lib/dyld",description="/usr/lib/dyld",
|
// state="Y",path="/usr/lib/dyld",description="/usr/lib/dyld",
|
||||||
// loaded_addr="0x8fe00000",slide="0x0",prefix="__dyld_"},
|
// loaded_addr="0x8fe00000",slide="0x0",prefix="__dyld_"},
|
||||||
// shlib-info={...}...
|
// shlib-info={...}...
|
||||||
foreach (const GdbMi &item, response.data.children()) {
|
foreach (const GdbMi &item, response.data.children()) {
|
||||||
Module module;
|
|
||||||
module.modulePath =
|
module.modulePath =
|
||||||
QString::fromLocal8Bit(item.findChild("path").data());
|
QString::fromLocal8Bit(item.findChild("path").data());
|
||||||
module.moduleName = nameFromPath(module.modulePath);
|
module.moduleName = nameFromPath(module.modulePath);
|
||||||
@@ -3498,25 +3510,34 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
|||||||
module.startAddress =
|
module.startAddress =
|
||||||
item.findChild("loaded_addr").data().toULongLong(0, 0);
|
item.findChild("loaded_addr").data().toULongLong(0, 0);
|
||||||
module.endAddress = 0; // FIXME: End address not easily available.
|
module.endAddress = 0; // FIXME: End address not easily available.
|
||||||
modules.append(module);
|
examineModule(&module);
|
||||||
|
handler->updateModule(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modulesHandler()->setModules(modules);
|
}
|
||||||
|
|
||||||
|
void GdbEngine::examineModule(Module *module)
|
||||||
|
{
|
||||||
|
Utils::ElfReader reader(module->modulePath);
|
||||||
|
QList<QByteArray> names = reader.sectionNames();
|
||||||
|
if (names.contains(".gdb_index"))
|
||||||
|
module->symbolsType = Module::FastSymbols;
|
||||||
|
else if (names.contains(".debug_inf"))
|
||||||
|
module->symbolsType = Module::PlainSymbols;
|
||||||
|
else if (names.contains(".gnu_debuglink"))
|
||||||
|
module->symbolsType = Module::SeparateSymbols;
|
||||||
|
else
|
||||||
|
module->symbolsType = Module::NoSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::examineModules()
|
void GdbEngine::examineModules()
|
||||||
{
|
{
|
||||||
ModulesHandler *handler = modulesHandler();
|
ModulesHandler *handler = modulesHandler();
|
||||||
foreach (Module module, handler->modules()) {
|
foreach (Module module, handler->modules()) {
|
||||||
if (module.symbolsType == Module::UnknownType) {
|
if (module.symbolsType == Module::UnknownSymbols) {
|
||||||
Utils::ElfReader reader(module.modulePath);
|
examineModule(&module);
|
||||||
QList<QByteArray> names = reader.sectionNames();
|
modulesHandler()->updateModule(module);
|
||||||
if (names.contains(".gdb_index"))
|
|
||||||
module.symbolsType = Module::FastSymbols;
|
|
||||||
else
|
|
||||||
module.symbolsType = Module::PlainSymbols;
|
|
||||||
handler->updateModule(module);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3529,7 +3550,6 @@ void GdbEngine::examineModules()
|
|||||||
|
|
||||||
void GdbEngine::invalidateSourcesList()
|
void GdbEngine::invalidateSourcesList()
|
||||||
{
|
{
|
||||||
m_modulesListOutdated = true;
|
|
||||||
m_breakListOutdated = true;
|
m_breakListOutdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5003,6 +5023,13 @@ void GdbEngine::handleAdapterStarted()
|
|||||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||||
showMessage(_("ADAPTER SUCCESSFULLY STARTED"));
|
showMessage(_("ADAPTER SUCCESSFULLY STARTED"));
|
||||||
notifyEngineSetupOk();
|
notifyEngineSetupOk();
|
||||||
|
|
||||||
|
Module module;
|
||||||
|
module.startAddress = 0;
|
||||||
|
module.endAddress = 0;
|
||||||
|
module.modulePath = startParameters().executable;
|
||||||
|
module.moduleName = QLatin1String("<executable>");
|
||||||
|
modulesHandler()->addModule(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::setupInferior()
|
void GdbEngine::setupInferior()
|
||||||
@@ -5363,6 +5390,7 @@ void GdbEngine::checkForReleaseBuild()
|
|||||||
interesting.append(".gdb_index");
|
interesting.append(".gdb_index");
|
||||||
interesting.append(".note.gnu.build-id");
|
interesting.append(".note.gnu.build-id");
|
||||||
interesting.append(".gnu.hash");
|
interesting.append(".gnu.hash");
|
||||||
|
interesting.append(".gnu_debuglink");
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QByteArray> seen;
|
QSet<QByteArray> seen;
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ class DebugInfoTaskHandler;
|
|||||||
class GdbResponse;
|
class GdbResponse;
|
||||||
class GdbMi;
|
class GdbMi;
|
||||||
class GdbToolTipContext;
|
class GdbToolTipContext;
|
||||||
|
class Module;
|
||||||
|
|
||||||
class WatchData;
|
class WatchData;
|
||||||
class DisassemblerAgentCookie;
|
class DisassemblerAgentCookie;
|
||||||
@@ -513,12 +514,11 @@ private: ////////// View & Data Stuff //////////
|
|||||||
void requestModuleSymbols(const QString &moduleName);
|
void requestModuleSymbols(const QString &moduleName);
|
||||||
void reloadModules();
|
void reloadModules();
|
||||||
void examineModules();
|
void examineModules();
|
||||||
|
void examineModule(Module *module);
|
||||||
void reloadModulesInternal();
|
void reloadModulesInternal();
|
||||||
void handleModulesList(const GdbResponse &response);
|
void handleModulesList(const GdbResponse &response);
|
||||||
void handleShowModuleSymbols(const GdbResponse &response);
|
void handleShowModuleSymbols(const GdbResponse &response);
|
||||||
|
|
||||||
bool m_modulesListOutdated;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Snapshot specific stuff
|
// Snapshot specific stuff
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -124,15 +124,51 @@ QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
|||||||
case 3:
|
case 3:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
switch (module.symbolsType) {
|
switch (module.symbolsType) {
|
||||||
case Module::UnknownType: return ModulesHandler::tr("unknown");
|
case Module::UnknownSymbols:
|
||||||
case Module::PlainSymbols: return ModulesHandler::tr("plain");
|
return ModulesHandler::tr("unknown");
|
||||||
case Module::FastSymbols: return ModulesHandler::tr("fast");
|
case Module::NoSymbols:
|
||||||
|
return ModulesHandler::tr("none");
|
||||||
|
case Module::PlainSymbols:
|
||||||
|
return ModulesHandler::tr("plain");
|
||||||
|
case Module::FastSymbols:
|
||||||
|
return ModulesHandler::tr("fast");
|
||||||
|
case Module::SeparateSymbols:
|
||||||
|
return ModulesHandler::tr("separate");
|
||||||
|
}
|
||||||
|
else if (role == Qt::ToolTipRole)
|
||||||
|
switch (module.symbolsType) {
|
||||||
|
case Module::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:
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
return ModulesHandler::tr(
|
||||||
|
"This module does not contains debug information "
|
||||||
|
"itself, but contains a reference to external "
|
||||||
|
"debug information.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
return QString(QLatin1String("0x")
|
if (module.startAddress)
|
||||||
+ QString::number(module.startAddress, 16));
|
return QString(QLatin1String("0x")
|
||||||
|
+ QString::number(module.startAddress, 16));
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
@@ -189,9 +225,12 @@ void ModulesModel::removeModule(const QString &modulePath)
|
|||||||
void ModulesModel::updateModule(const Module &module)
|
void ModulesModel::updateModule(const Module &module)
|
||||||
{
|
{
|
||||||
const int row = indexOfModule(module.modulePath);
|
const int row = indexOfModule(module.modulePath);
|
||||||
QTC_ASSERT(row != -1, return);
|
if (row == -1) {
|
||||||
m_modules[row] = module;
|
addModule(module);
|
||||||
dataChanged(index(row, 0, QModelIndex()), index(row, 4, QModelIndex()));
|
} else {
|
||||||
|
m_modules[row] = module;
|
||||||
|
dataChanged(index(row, 0, QModelIndex()), index(row, 4, QModelIndex()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -73,21 +73,24 @@ typedef QVector<Symbol> Symbols;
|
|||||||
class Module
|
class Module
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Module() : symbolsRead(UnknownReadState), symbolsType(UnknownType) {}
|
Module() : symbolsRead(UnknownReadState), symbolsType(UnknownSymbols) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SymbolReadState {
|
enum SymbolReadState {
|
||||||
UnknownReadState, // Not tried.
|
UnknownReadState, // Not tried.
|
||||||
ReadFailed, // Tried to read, but failed.
|
ReadFailed, // Tried to read, but failed.
|
||||||
ReadOk // Dwarf index available.
|
ReadOk // Dwarf index available.
|
||||||
};
|
};
|
||||||
enum SymbolType {
|
enum SymbolType {
|
||||||
UnknownType, // Unknown.
|
UnknownSymbols, // Unknown.
|
||||||
|
NoSymbols, // No usable symbols.
|
||||||
|
SeparateSymbols, // Symbols mentioned, but not in binary.
|
||||||
PlainSymbols, // Ordinary symbols available.
|
PlainSymbols, // Ordinary symbols available.
|
||||||
FastSymbols // Dwarf index available.
|
FastSymbols // Dwarf index available.
|
||||||
};
|
};
|
||||||
QString moduleName;
|
QString moduleName;
|
||||||
QString modulePath;
|
QString modulePath;
|
||||||
|
QString hostPath;
|
||||||
SymbolReadState symbolsRead;
|
SymbolReadState symbolsRead;
|
||||||
SymbolType symbolsType;
|
SymbolType symbolsType;
|
||||||
quint64 startAddress;
|
quint64 startAddress;
|
||||||
|
|||||||
Reference in New Issue
Block a user