forked from qt-creator/qt-creator
debugger: make use of full source file list optional
(cherry picked from commit 8c52f5720c
)
This commit is contained in:
@@ -248,6 +248,14 @@ DebuggerSettings *DebuggerSettings::instance()
|
|||||||
item->setText(tr("Synchronize breakpoints"));
|
item->setText(tr("Synchronize breakpoints"));
|
||||||
instance->insertItem(SynchronizeBreakpoints, item);
|
instance->insertItem(SynchronizeBreakpoints, item);
|
||||||
|
|
||||||
|
item = new SavedAction(instance);
|
||||||
|
item->setText(tr("Use precise breakpoints"));
|
||||||
|
item->setCheckable(true);
|
||||||
|
item->setDefaultValue(true);
|
||||||
|
item->setValue(true);
|
||||||
|
item->setSettingsKey(debugModeGroup, QLatin1String("UsePreciseBreakpoints"));
|
||||||
|
instance->insertItem(UsePreciseBreakpoints, item);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Settings
|
// Settings
|
||||||
//
|
//
|
||||||
|
@@ -126,6 +126,7 @@ enum DebuggerActionCode
|
|||||||
SelectedPluginBreakpoints,
|
SelectedPluginBreakpoints,
|
||||||
NoPluginBreakpoints,
|
NoPluginBreakpoints,
|
||||||
SelectedPluginBreakpointsPattern,
|
SelectedPluginBreakpointsPattern,
|
||||||
|
UsePreciseBreakpoints
|
||||||
};
|
};
|
||||||
|
|
||||||
// singleton access
|
// singleton access
|
||||||
|
@@ -360,6 +360,7 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent)
|
|||||||
m_group.insert(theDebuggerAction(MaximalStackDepth),
|
m_group.insert(theDebuggerAction(MaximalStackDepth),
|
||||||
m_ui.spinBoxMaximalStackDepth);
|
m_ui.spinBoxMaximalStackDepth);
|
||||||
m_group.insert(theDebuggerAction(LogTimeStamps), 0);
|
m_group.insert(theDebuggerAction(LogTimeStamps), 0);
|
||||||
|
m_group.insert(theDebuggerAction(UsePreciseBreakpoints), 0);
|
||||||
|
|
||||||
#ifdef USE_REVERSE_DEBUGGING
|
#ifdef USE_REVERSE_DEBUGGING
|
||||||
m_ui.checkBoxEnableReverseDebugging->hide();
|
m_ui.checkBoxEnableReverseDebugging->hide();
|
||||||
|
@@ -271,8 +271,9 @@ void GdbEngine::initializeVariables()
|
|||||||
m_shortToFullName.clear();
|
m_shortToFullName.clear();
|
||||||
m_varToType.clear();
|
m_varToType.clear();
|
||||||
|
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
m_sourcesListUpdating = false;
|
m_sourcesListUpdating = false;
|
||||||
|
m_breakListUpdating = false;
|
||||||
m_oldestAcceptableToken = -1;
|
m_oldestAcceptableToken = -1;
|
||||||
m_outputCodec = QTextCodec::codecForLocale();
|
m_outputCodec = QTextCodec::codecForLocale();
|
||||||
m_pendingRequests = 0;
|
m_pendingRequests = 0;
|
||||||
@@ -439,14 +440,14 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
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)));
|
showStatusMessage(tr("Library %1 loaded.").arg(_(id)));
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
} 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",
|
||||||
// host-name="/usr/lib/libdrm.so.2"
|
// host-name="/usr/lib/libdrm.so.2"
|
||||||
QByteArray id = result.findChild("id").data();
|
QByteArray id = result.findChild("id").data();
|
||||||
showStatusMessage(tr("Library %1 unloaded.").arg(_(id)));
|
showStatusMessage(tr("Library %1 unloaded.").arg(_(id)));
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
} else if (asyncClass == "thread-group-created") {
|
} else if (asyncClass == "thread-group-created") {
|
||||||
// Archer has "{id="28902"}"
|
// Archer has "{id="28902"}"
|
||||||
QByteArray id = result.findChild("id").data();
|
QByteArray id = result.findChild("id").data();
|
||||||
@@ -475,7 +476,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
} else if (asyncClass == "shlibs-updated") {
|
} else if (asyncClass == "shlibs-updated") {
|
||||||
// MAC announces updated libs
|
// MAC announces updated libs
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
} else if (asyncClass == "shlibs-added") {
|
} else if (asyncClass == "shlibs-added") {
|
||||||
// MAC announces added libs
|
// MAC announces added libs
|
||||||
// {shlib-info={num="2", name="libmathCommon.A_debug.dylib",
|
// {shlib-info={num="2", name="libmathCommon.A_debug.dylib",
|
||||||
@@ -483,7 +484,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
// state="Y", path="/usr/lib/system/libmathCommon.A_debug.dylib",
|
// state="Y", path="/usr/lib/system/libmathCommon.A_debug.dylib",
|
||||||
// description="/usr/lib/system/libmathCommon.A_debug.dylib",
|
// description="/usr/lib/system/libmathCommon.A_debug.dylib",
|
||||||
// loaded_addr="0x7f000", slide="0x7f000", prefix=""}}
|
// loaded_addr="0x7f000", slide="0x7f000", prefix=""}}
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "IGNORED ASYNC OUTPUT"
|
qDebug() << "IGNORED ASYNC OUTPUT"
|
||||||
@@ -517,7 +518,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
// Show some messages to give the impression something happens.
|
// Show some messages to give the impression something happens.
|
||||||
if (data.startsWith("Reading symbols from ")) {
|
if (data.startsWith("Reading symbols from ")) {
|
||||||
showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))), 1000);
|
showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))), 1000);
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
} else if (data.startsWith("[New ") || data.startsWith("[Thread ")) {
|
} else if (data.startsWith("[New ") || data.startsWith("[Thread ")) {
|
||||||
if (data.endsWith('\n'))
|
if (data.endsWith('\n'))
|
||||||
data.chop(1);
|
data.chop(1);
|
||||||
@@ -988,6 +989,8 @@ void GdbEngine::updateAll()
|
|||||||
|
|
||||||
void GdbEngine::handleQuerySources(const GdbResponse &response)
|
void GdbEngine::handleQuerySources(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
|
m_sourcesListUpdating = false;
|
||||||
|
m_sourcesListOutdated = false;
|
||||||
if (response.resultClass == GdbResultDone) {
|
if (response.resultClass == GdbResultDone) {
|
||||||
QMap<QString, QString> oldShortToFull = m_shortToFullName;
|
QMap<QString, QString> oldShortToFull = m_shortToFullName;
|
||||||
m_shortToFullName.clear();
|
m_shortToFullName.clear();
|
||||||
@@ -1161,7 +1164,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
|||||||
// on Windows it simply forgets about it. Thus, we identify the response
|
// on Windows it simply forgets about it. Thus, we identify the response
|
||||||
// based on it having no frame information.
|
// based on it having no frame information.
|
||||||
if (!data.findChild("frame").isValid()) {
|
if (!data.findChild("frame").isValid()) {
|
||||||
m_modulesListOutdated = m_sourcesListOutdated = true;
|
invalidateSourcesList();
|
||||||
// Each stop causes a roundtrip and button flicker, so prevent
|
// Each stop causes a roundtrip and button flicker, so prevent
|
||||||
// a flood of useless stops. Will be automatically re-enabled.
|
// a flood of useless stops. Will be automatically re-enabled.
|
||||||
postCommand(_("set stop-on-solib-events 0"));
|
postCommand(_("set stop-on-solib-events 0"));
|
||||||
@@ -1273,14 +1276,17 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
|||||||
{
|
{
|
||||||
if (m_modulesListOutdated)
|
if (m_modulesListOutdated)
|
||||||
reloadModulesInternal(); // This is for display only
|
reloadModulesInternal(); // This is for display only
|
||||||
if (m_sourcesListOutdated)
|
if (m_sourcesListOutdated && theDebuggerBoolSetting(UsePreciseBreakpoints))
|
||||||
reloadSourceFilesInternal(); // This needs to be done before fullName() may need it
|
reloadSourceFilesInternal(); // This needs to be done before fullName() may need it
|
||||||
|
|
||||||
// Older gdb versions do not produce "library loaded" messages
|
if (m_breakListOutdated)
|
||||||
// so the breakpoint update is not triggered.
|
reloadBreakListInternal();
|
||||||
if (m_gdbVersion < 70000 && !m_isMacGdb && !m_sourcesListUpdating
|
else
|
||||||
&& manager()->breakHandler()->size() > 0)
|
// Older gdb versions do not produce "library loaded" messages
|
||||||
postCommand(_("-break-list"), CB(handleBreakList));
|
// so the breakpoint update is not triggered.
|
||||||
|
if (m_gdbVersion < 70000 && !m_isMacGdb && !m_breakListUpdating
|
||||||
|
&& manager()->breakHandler()->size() > 0)
|
||||||
|
reloadBreakListInternal();
|
||||||
|
|
||||||
QByteArray reason = data.findChild("reason").data();
|
QByteArray reason = data.findChild("reason").data();
|
||||||
if (reason == "breakpoint-hit") {
|
if (reason == "breakpoint-hit") {
|
||||||
@@ -1876,8 +1882,8 @@ void GdbEngine::breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt
|
|||||||
|
|
||||||
QString GdbEngine::breakLocation(const QString &file) const
|
QString GdbEngine::breakLocation(const QString &file) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!m_sourcesListOutdated, /* */)
|
QTC_ASSERT(!m_breakListOutdated, /* */)
|
||||||
QTC_ASSERT(!m_sourcesListUpdating, /* */)
|
QTC_ASSERT(!m_breakListUpdating, /* */)
|
||||||
QString where = m_fullToShortName.value(file);
|
QString where = m_fullToShortName.value(file);
|
||||||
if (where.isEmpty())
|
if (where.isEmpty())
|
||||||
return QFileInfo(file).fileName();
|
return QFileInfo(file).fileName();
|
||||||
@@ -1912,10 +1918,14 @@ void GdbEngine::sendInsertBreakpoint(int index)
|
|||||||
postCommand(cmd, NeedsStop, CB(handleBreakInsert), index);
|
postCommand(cmd, NeedsStop, CB(handleBreakInsert), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbEngine::reloadBreakListInternal()
|
||||||
|
{
|
||||||
|
m_breakListUpdating = true;
|
||||||
|
postCommand(_("-break-list"), CB(handleBreakList));
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::handleBreakList(const GdbResponse &response)
|
void GdbEngine::handleBreakList(const GdbResponse &response)
|
||||||
{
|
{
|
||||||
m_sourcesListUpdating = false;
|
|
||||||
|
|
||||||
// 45^done,BreakpointTable={nr_rows="2",nr_cols="6",hdr=[
|
// 45^done,BreakpointTable={nr_rows="2",nr_cols="6",hdr=[
|
||||||
// {width="3",alignment="-1",col_name="number",colhdr="Num"}, ...
|
// {width="3",alignment="-1",col_name="number",colhdr="Num"}, ...
|
||||||
// body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",
|
// body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",
|
||||||
@@ -1962,6 +1972,8 @@ void GdbEngine::handleBreakList(const GdbMi &table)
|
|||||||
//qDebug() << "CANNOT HANDLE RESPONSE" << bkpts.at(index).toString();
|
//qDebug() << "CANNOT HANDLE RESPONSE" << bkpts.at(index).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_breakListUpdating = false;
|
||||||
|
m_breakListOutdated = false;
|
||||||
attemptBreakpointSynchronization();
|
attemptBreakpointSynchronization();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2118,6 +2130,11 @@ void GdbEngine::handleBreakInsert1(const GdbResponse &response)
|
|||||||
|
|
||||||
void GdbEngine::attemptBreakpointSynchronization()
|
void GdbEngine::attemptBreakpointSynchronization()
|
||||||
{
|
{
|
||||||
|
//QTC_ASSERT(!m_breakListUpdating,
|
||||||
|
// qDebug() << "BREAK LIST CURRENTLY UPDATING"; return);
|
||||||
|
QTC_ASSERT(!m_sourcesListUpdating,
|
||||||
|
qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
|
||||||
|
|
||||||
switch (state()) {
|
switch (state()) {
|
||||||
case InferiorStarting:
|
case InferiorStarting:
|
||||||
case InferiorRunningRequested:
|
case InferiorRunningRequested:
|
||||||
@@ -2132,10 +2149,13 @@ void GdbEngine::attemptBreakpointSynchronization()
|
|||||||
|
|
||||||
// For best results, we rely on an up-to-date fullname mapping.
|
// For best results, we rely on an up-to-date fullname mapping.
|
||||||
// The listing completion will retrigger us, so no futher action is needed.
|
// The listing completion will retrigger us, so no futher action is needed.
|
||||||
if (m_sourcesListOutdated) {
|
if (m_sourcesListOutdated && theDebuggerBoolSetting(UsePreciseBreakpoints)) {
|
||||||
reloadSourceFilesInternal();
|
reloadSourceFilesInternal();
|
||||||
|
reloadBreakListInternal();
|
||||||
return;
|
return;
|
||||||
} else if (m_sourcesListUpdating) {
|
}
|
||||||
|
if (m_breakListOutdated) {
|
||||||
|
reloadBreakListInternal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2318,6 +2338,13 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
|
|||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void GdbEngine::invalidateSourcesList()
|
||||||
|
{
|
||||||
|
m_modulesListOutdated = true;
|
||||||
|
m_sourcesListOutdated = true;
|
||||||
|
m_breakListOutdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
void GdbEngine::reloadSourceFiles()
|
void GdbEngine::reloadSourceFiles()
|
||||||
{
|
{
|
||||||
if ((state() == InferiorRunning || state() == InferiorStopped)
|
if ((state() == InferiorRunning || state() == InferiorStopped)
|
||||||
@@ -2327,10 +2354,9 @@ void GdbEngine::reloadSourceFiles()
|
|||||||
|
|
||||||
void GdbEngine::reloadSourceFilesInternal()
|
void GdbEngine::reloadSourceFilesInternal()
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(!m_sourcesListUpdating, /**/);
|
||||||
m_sourcesListUpdating = true;
|
m_sourcesListUpdating = true;
|
||||||
m_sourcesListOutdated = false;
|
|
||||||
postCommand(_("-file-list-exec-source-files"), NeedsStop, CB(handleQuerySources));
|
postCommand(_("-file-list-exec-source-files"), NeedsStop, CB(handleQuerySources));
|
||||||
postCommand(_("-break-list"), CB(handleBreakList));
|
|
||||||
#if 0
|
#if 0
|
||||||
if (m_gdbVersion < 70000 && !m_isMacGdb)
|
if (m_gdbVersion < 70000 && !m_isMacGdb)
|
||||||
postCommand(_("set stop-on-solib-events 1"));
|
postCommand(_("set stop-on-solib-events 1"));
|
||||||
@@ -4192,7 +4218,8 @@ QString GdbEngine::parseDisassembler(const GdbMi &lines)
|
|||||||
// mixed mode
|
// mixed mode
|
||||||
if (!fileLoaded) {
|
if (!fileLoaded) {
|
||||||
QString fileName = QFile::decodeName(child.findChild("file").data());
|
QString fileName = QFile::decodeName(child.findChild("file").data());
|
||||||
QFile file(fullName(fileName));
|
fileName = cleanupFullName(fileName);
|
||||||
|
QFile file(fileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
fileContents = file.readAll().split('\n');
|
fileContents = file.readAll().split('\n');
|
||||||
fileLoaded = true;
|
fileLoaded = true;
|
||||||
|
@@ -328,6 +328,7 @@ private: ////////// View & Data Stuff //////////
|
|||||||
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
||||||
void sendInsertBreakpoint(int index);
|
void sendInsertBreakpoint(int index);
|
||||||
QString breakLocation(const QString &file) const;
|
QString breakLocation(const QString &file) const;
|
||||||
|
void reloadBreakListInternal();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Modules specific stuff
|
// Modules specific stuff
|
||||||
@@ -379,8 +380,11 @@ private: ////////// View & Data Stuff //////////
|
|||||||
QMap<QString, QString> m_shortToFullName;
|
QMap<QString, QString> m_shortToFullName;
|
||||||
QMap<QString, QString> m_fullToShortName;
|
QMap<QString, QString> m_fullToShortName;
|
||||||
|
|
||||||
|
void invalidateSourcesList();
|
||||||
bool m_sourcesListOutdated;
|
bool m_sourcesListOutdated;
|
||||||
bool m_sourcesListUpdating;
|
bool m_sourcesListUpdating;
|
||||||
|
bool m_breakListOutdated;
|
||||||
|
bool m_breakListUpdating;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Stack specific stuff
|
// Stack specific stuff
|
||||||
|
@@ -50,6 +50,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent)
|
|||||||
m_ui.scriptFileChooser);
|
m_ui.scriptFileChooser);
|
||||||
m_group.insert(theDebuggerAction(GdbEnvironment),
|
m_group.insert(theDebuggerAction(GdbEnvironment),
|
||||||
m_ui.environmentEdit);
|
m_ui.environmentEdit);
|
||||||
|
m_group.insert(theDebuggerAction(UsePreciseBreakpoints),
|
||||||
|
m_ui.checkBoxUsePreciseBreakpoints);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
m_ui.groupBoxPluginDebugging->hide();
|
m_ui.groupBoxPluginDebugging->hide();
|
||||||
|
@@ -62,6 +62,19 @@
|
|||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="Utils::PathChooser" name="gdbLocationChooser" native="true"/>
|
<widget class="Utils::PathChooser" name="gdbLocationChooser" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="checkBoxUsePreciseBreakpoints">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use full path information to set breakpoints</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>When this option is checked, the debugger plugin attempts
|
||||||
|
to extract full path information for all source files from gdb. This is a
|
||||||
|
slow process but enables setting breakpoints in files with the same file
|
||||||
|
name in different directories.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
Reference in New Issue
Block a user