Merge commit 'origin/1.3'

Conflicts:
	src/plugins/debugger/debuggermanager.h
	src/plugins/qmleditor/qmleditorplugin.cpp
	src/plugins/qt4projectmanager/qt4runconfiguration.cpp
This commit is contained in:
con
2009-11-11 16:14:29 +01:00
75 changed files with 786 additions and 608 deletions

View File

@@ -1034,9 +1034,16 @@ static inline QString msgStepFailed(unsigned long executionStatus, int threadId,
return QString::fromLatin1("Thread %1: Unable to step into: %2").arg(threadId).arg(why);
}
// Step with DEBUG_STATUS_STEP_OVER ('p'-command) or
// Step out has to be done via executing 'gu'. TODO: Remove once it is
// accessible via normal API for SetExecutionStatus().
enum { CdbExtendedExecutionStatusStepOut = 7452347 };
// Step with DEBUG_STATUS_STEP_OVER ('p'-command),
// DEBUG_STATUS_STEP_INTO ('t'-trace-command) or
// CdbExtendedExecutionStatusStepOut ("gu"-command)
// its reverse equivalents in the case of single threads.
bool CdbDebugEngine::step(unsigned long executionStatus)
{
if (debugCDBExecution)
@@ -1068,7 +1075,7 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
m_d->setCodeLevel(); // Step by instruction or source line
setState(InferiorRunningRequested, Q_FUNC_INFO, __LINE__);
bool success = false;
if (sameThread) { // Step event-triggering thread, use fast API
if (sameThread && executionStatus != CdbExtendedExecutionStatusStepOut) { // Step event-triggering thread, use fast API
const HRESULT hr = m_d->m_cif.debugControl->SetExecutionStatus(executionStatus);
success = SUCCEEDED(hr);
if (!success)
@@ -1077,8 +1084,18 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
// Need to use a command to explicitly specify the current thread
QString command;
QTextStream str(&command);
str << '~' << m_d->m_currentThreadId << ' '
<< (executionStatus == DEBUG_STATUS_STEP_OVER ? 'p' : 't');
str << '~' << m_d->m_currentThreadId << ' ';
switch (executionStatus) {
case DEBUG_STATUS_STEP_OVER:
str << 'p';
break;
case DEBUG_STATUS_STEP_INTO:
str << 't';
break;
case CdbExtendedExecutionStatusStepOut:
str << "gu";
break;
}
manager()->showDebuggerOutput(tr("Stepping %1").arg(command));
const HRESULT hr = m_d->m_cif.debugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, command.toLatin1().constData(), DEBUG_EXECUTE_ECHO);
success = SUCCEEDED(hr);
@@ -1121,44 +1138,8 @@ void CdbDebugEngine::nextIExec()
void CdbDebugEngine::stepOutExec()
{
if (debugCDBExecution)
qDebug() << "stepOutExec";
// emulate gdb 'exec-finish' (exec until return of current function)
// by running up to address of the above stack frame (mostly works).
const StackHandler* sh = manager()->stackHandler();
const int idx = sh->currentIndex() + 1;
const QList<StackFrame> stackframes = sh->frames();
if (idx < 0 || idx >= stackframes.size()) {
warning(QString::fromLatin1("Cannot step out of stack frame %1.").arg(idx));
return;
}
// Set a temporary breakpoint and continue
const StackFrame& frame = stackframes.at(idx);
bool success = false;
QString errorMessage;
do {
const ULONG64 address = frame.address.toULongLong(&success, 16);
if (!success) {
errorMessage = QLatin1String("Cannot obtain address from stack frame");
break;
}
manager()->showDebuggerOutput(LogMisc, tr("Running to 0x%1...").arg(address, 0, 16));
IDebugBreakpoint2* pBP;
HRESULT hr = m_d->m_cif.debugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
if (FAILED(hr) || !pBP) {
errorMessage = QString::fromLatin1("Cannot create temporary breakpoint: %1").arg(msgDebugEngineComResult(hr));
break;
}
pBP->SetOffset(address);
pBP->AddFlags(DEBUG_BREAKPOINT_ENABLED);
pBP->AddFlags(DEBUG_BREAKPOINT_ONE_SHOT);
if (!m_d->continueInferior(&errorMessage))
break;
success = true;
} while (false);
if (!success)
warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
if (!manager()->isReverseDebugging())
step(CdbExtendedExecutionStatusStepOut);
}
void CdbDebugEngine::continueInferior()

View File

@@ -120,7 +120,6 @@ private:
void startWatchTimer();
void killWatchTimer();
void processTerminated(unsigned long exitCode);
bool executeDebuggerCommand(const QString &command, QString *errorMessage);
bool evaluateExpression(const QString &expression, QString *value, QString *type, QString *errorMessage);
void evaluateWatcher(WatchData *wd);
QString editorToolTip(const QString &exp, const QString &function);

View File

@@ -233,8 +233,8 @@ DebuggerSettings *DebuggerSettings::instance()
item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel"));
item->setText(tr("Use code model"));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
item->setDefaultValue(true);
item->setValue(true);
instance->insertItem(UseCodeModel, item);
item = new SavedAction(instance);

View File

@@ -121,6 +121,7 @@ public:
QString debuggerCommand;
int toolChainType;
QString remoteDumperLib;
QString qtInstallPath;
QString dumperLibrary;
QStringList dumperLibraryLocations;

View File

@@ -31,6 +31,7 @@
#include "debuggermanager.h"
#include <projectexplorer/debugginghelper.h>
#include <projectexplorer/environment.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -139,6 +140,21 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager,
runConfiguration->dumperLibrary();
m_startParameters->dumperLibraryLocations =
runConfiguration->dumperLibraryLocations();
QString qmakePath = ProjectExplorer::DebuggingHelperLibrary::findSystemQt(
runConfiguration->environment());
if (!qmakePath.isEmpty()) {
QProcess proc;
QStringList args;
args.append(QLatin1String("-query"));
args.append(QLatin1String("QT_INSTALL_HEADERS"));
proc.start(qmakePath, args);
proc.waitForFinished();
QByteArray ba = proc.readAllStandardOutput().trimmed();
QFileInfo fi(QString::fromLocal8Bit(ba) + "/..");
m_startParameters->qtInstallPath = fi.absoluteFilePath();
}
}
DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, const DebuggerStartParametersPtr &startParameters)

View File

@@ -285,6 +285,8 @@ void GdbEngine::initializeVariables()
m_inbuffer.clear();
m_commandTimer->stop();
// ConverterState has no reset() function.
m_outputCodecState.~ConverterState();
new (&m_outputCodecState) QTextCodec::ConverterState();
@@ -425,6 +427,8 @@ void GdbEngine::handleResponse(const QByteArray &buff)
}
if (asyncClass == "stopped") {
handleStopResponse(result);
m_pendingLogStreamOutput.clear();
m_pendingConsoleStreamOutput.clear();
} else if (asyncClass == "running") {
// Archer has 'thread-id="all"' here
} else if (asyncClass == "library-loaded") {
@@ -1157,42 +1161,52 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
}
setState(InferiorStopped);
#ifdef Q_OS_LINUX
// For some reason, attaching to a stopped process causes *two* stops
// when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
// Interestingly enough, on MacOSX no signal is delivered at all.
if (!m_entryPoint.isEmpty()) {
if (reason == "signal-received"
&& data.findChild("signal-name").data() == "SIGSTOP") {
GdbMi frameData = data.findChild("frame");
if (frameData.findChild("addr").data() == m_entryPoint) {
continueInferiorInternal();
return;
}
}
// We are past the initial stops. No need to waste time on further checks.
m_entryPoint.clear();
}
#endif
// Due to LD_PRELOADing the dumpers, these events can occur even before
// reaching the entry point. So handle it before the entry point hacks below.
if (reason.isEmpty() && m_gdbVersion < 70000 && !m_isMacGdb) {
// On Linux it reports "Stopped due to shared library event\n", but
// on Windows it simply forgets about it. Thus, we identify the response
// based on it having no frame information.
if (!data.findChild("frame").isValid()) {
m_modulesListOutdated = m_sourcesListOutdated = true;
// Each stop causes a roundtrip and button flicker, so prevent
// a flood of useless stops. Will be automatically re-enabled.
postCommand(_("set stop-on-solib-events 0"));
#if 0
// The related code (handleAqcuiredInferior()) is disabled as well.
// When re-enabling, try something to avoid spurious source list updates
// due to unrelated no-reason stops.
const QByteArray &msg = data.findChild("consolestreamoutput").data();
if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) {
m_modulesListOutdated = m_sourcesListOutdated = true;
if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) {
QString dataStr = _(data.toString());
debugMessage(_("SHARED LIBRARY EVENT: ") + dataStr);
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
debugMessage(_("PATTERN: ") + pat);
postCommand(_("sharedlibrary ") + pat);
// The related code (handleAqcuiredInferior()) is disabled as well.
if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) {
QString dataStr = _(data.toString());
debugMessage(_("SHARED LIBRARY EVENT: ") + dataStr);
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
debugMessage(_("PATTERN: ") + pat);
postCommand(_("sharedlibrary ") + pat);
showStatusMessage(tr("Loading %1...").arg(dataStr));
}
#endif
continueInferiorInternal();
showStatusMessage(tr("Loading %1...").arg(dataStr));
return;
}
// fall through
}
#ifdef Q_OS_LINUX
if (!m_entryPoint.isEmpty()) {
GdbMi frameData = data.findChild("frame");
if (frameData.findChild("addr").data() == m_entryPoint) {
// There are two expected reasons for getting here:
// 1) For some reason, attaching to a stopped process causes *two* SIGSTOPs
// when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
// Interestingly enough, on MacOSX no signal is delivered at all.
// 2) The explicit tbreak at the entry point we set to query the PID.
// Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports everything.
// The case of the user really setting a breakpoint at _start is simply
// unsupported.
if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8.
postCommand(_("info proc"), CB(handleInfoProc));
continueInferiorInternal();
return;
}
// We are past the initial stop(s). No need to waste time on further checks.
m_entryPoint.clear();
}
#endif
@@ -1270,11 +1284,6 @@ void GdbEngine::handleStop1(const GdbMi &data)
if (m_sourcesListOutdated)
reloadSourceFilesInternal(); // This needs to be done before fullName() may need it
// Older gdb versions do not produce "library loaded" messages
// so the breakpoint update is not triggered.
if (m_gdbVersion < 70000 && !m_isMacGdb)
postCommand(_("-break-list"), CB(handleBreakList));
QByteArray reason = data.findChild("reason").data();
if (reason == "breakpoint-hit") {
showStatusMessage(tr("Stopped at breakpoint."));
@@ -1292,8 +1301,8 @@ void GdbEngine::handleStop1(const GdbMi &data)
"signal from the Operating System.<p>"
"<table><tr><td>Signal name : </td><td>%1</td></tr>"
"<tr><td>Signal meaning : </td><td>%2</td></tr></table>")
.arg(name.isEmpty() ? tr(" <Unknown> ") : _(name))
.arg(meaning.isEmpty() ? tr(" <Unknown> ") : _(meaning));
.arg(name.isEmpty() ? tr(" <Unknown> ", "name") : _(name))
.arg(meaning.isEmpty() ? tr(" <Unknown> ", "meaning") : _(meaning));
showMessageBox(QMessageBox::Information,
tr("Signal received"), msg);
}
@@ -1337,6 +1346,18 @@ void GdbEngine::handleStop1(const GdbMi &data)
manager()->reloadRegisters();
}
#ifdef Q_OS_LINUX
void GdbEngine::handleInfoProc(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
static QRegExp re(_("\\bprocess ([0-9]+)\n"));
QTC_ASSERT(re.isValid(), return);
if (re.indexIn(_(response.data.findChild("consolestreamoutput").data())) != -1)
maybeHandleInferiorPidChanged(re.cap(1));
}
}
#endif
void GdbEngine::handleShowVersion(const GdbResponse &response)
{
//qDebug () << "VERSION 2:" << response.data.findChild("consolestreamoutput").data();
@@ -1399,7 +1420,6 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
} else {
if (state() == InferiorRunningRequested_Kill) {
setState(InferiorStopped);
m_commandsToRunOnTemporaryBreak.clear();
shutdown();
return;
}
@@ -1416,7 +1436,6 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
} else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
m_commandsToRunOnTemporaryBreak.clear();
shutdown();
}
}
@@ -1461,6 +1480,7 @@ void GdbEngine::shutdown()
// fall-through
case AdapterStartFailed: // Adapter "did something", but it did not help
if (m_gdbProc.state() == QProcess::Running) {
m_commandsToRunOnTemporaryBreak.clear();
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
} else {
setState(DebuggerNotReady);
@@ -1470,6 +1490,7 @@ void GdbEngine::shutdown()
case InferiorRunning:
case InferiorStopping:
case InferiorStopped:
m_commandsToRunOnTemporaryBreak.clear();
postCommand(_(m_gdbAdapter->inferiorShutdownCommand()),
NeedsStop | LosesChild, CB(handleInferiorShutdown));
break;
@@ -1478,6 +1499,7 @@ void GdbEngine::shutdown()
case InferiorShutDown:
case InferiorShutdownFailed: // Whatever
case InferiorUnrunnable:
m_commandsToRunOnTemporaryBreak.clear();
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
setState(EngineShuttingDown); // Do it after posting the command!
break;
@@ -1510,6 +1532,7 @@ void GdbEngine::handleGdbExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultExit) {
debugMessage(_("GDB CLAIMS EXIT; WAITING"));
m_commandsDoneCallback = 0;
// don't set state here, this will be handled in handleGdbFinished()
} else {
QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data()));
@@ -2238,6 +2261,8 @@ void GdbEngine::reloadModulesInternal()
{
m_modulesListOutdated = false;
postCommand(_("info shared"), NeedsStop, CB(handleModulesList));
if (m_gdbVersion < 70000 && !m_isMacGdb)
postCommand(_("set stop-on-solib-events 1"));
}
void GdbEngine::handleModulesList(const GdbResponse &response)
@@ -2278,7 +2303,7 @@ void GdbEngine::handleModulesList(const GdbResponse &response)
module.symbolsRead = (item.findChild("state").data() == "Y");
module.startAddress = _(item.findChild("loaded_addr").data());
//: End address of loaded module
module.endAddress = tr("<unknown>");
module.endAddress = tr("<unknown>", "address");
modules.append(module);
}
}
@@ -2306,6 +2331,8 @@ void GdbEngine::reloadSourceFilesInternal()
m_sourcesListOutdated = false;
postCommand(_("-file-list-exec-source-files"), NeedsStop, CB(handleQuerySources));
postCommand(_("-break-list"), CB(handleBreakList));
if (m_gdbVersion < 70000 && !m_isMacGdb)
postCommand(_("set stop-on-solib-events 1"));
}
@@ -4450,6 +4477,21 @@ void GdbEngine::handleAdapterStarted()
void GdbEngine::handleInferiorPrepared()
{
const QString qtInstallPath = m_startParameters->qtInstallPath;
if (!qtInstallPath.isEmpty()) {
QString qtBuildPath =
#if defined(Q_OS_WIN)
_("C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.6/qt");
#elif defined(Q_OS_MAC)
QString();
#else
_("/var/tmp/qt-x11-src-4.6.0");
#endif
if (!qtBuildPath.isEmpty())
postCommand(_("set substitute-path %1 %2")
.arg(qtBuildPath).arg(qtInstallPath));
}
// Initial attempt to set breakpoints
showStatusMessage(tr("Setting breakpoints..."));
attemptBreakpointSynchronization();

View File

@@ -302,6 +302,8 @@ private: ////////// Inferior Management //////////
void maybeHandleInferiorPidChanged(const QString &pid);
#ifdef Q_OS_LINUX
void handleInfoProc(const GdbResponse &response);
QByteArray m_entryPoint;
#endif

View File

@@ -110,6 +110,13 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
#ifdef Q_OS_LINUX
// Old gdbs do not announce the PID for programs without pthreads.
// Note that successfully preloading the debugging helpers will
// automatically load pthreads, so this will be unnecessary.
if (m_engine->m_gdbVersion < 70000)
m_engine->postCommand(_("info target"), CB(handleInfoTarget));
#endif
emit inferiorPrepared();
} else {
QString msg = tr("Starting executable failed:\n") +
@@ -118,6 +125,29 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
}
}
#ifdef Q_OS_LINUX
void PlainGdbAdapter::handleInfoTarget(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// [some leading stdout here]
// >&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
// [some trailing stdout here]
QString msg = _(response.data.findChild("consolestreamoutput").data());
QRegExp needle(_("\\bEntry point: 0x([0-9a-f]+)\\b"));
if (needle.indexIn(msg) != -1) {
m_engine->m_entryPoint =
"0x" + needle.cap(1).toLatin1().rightJustified(sizeof(void *) * 2, '0');
m_engine->postCommand(_("tbreak *0x") + needle.cap(1));
// Do nothing here - inferiorPrepared handles the sequencing.
} else {
emit inferiorStartFailed(_("Parsing start address failed"));
}
} else if (response.resultClass == GdbResultError) {
emit inferiorStartFailed(_("Fetching start address failed"));
}
}
#endif
void PlainGdbAdapter::startInferiorPhase2()
{
setState(InferiorRunningRequested);

View File

@@ -62,6 +62,9 @@ public:
private:
void handleFileExecAndSymbols(const GdbResponse &response);
void handleExecRun(const GdbResponse &response);
#ifdef Q_OS_LINUX
void handleInfoTarget(const GdbResponse &response);
#endif
OutputCollector m_outputCollector;
};

View File

@@ -197,9 +197,17 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
m_running(false),
m_trkDevice(new trk::TrkDevice),
m_gdbAckMode(true),
m_verbose(2),
m_verbose(0),
m_bufferedMemoryRead(true)
{
const QByteArray trkVerbose = qgetenv("QTC_TRK_VERBOSE");
if (!trkVerbose.isEmpty()) {
bool ok;
m_verbose = trkVerbose.toInt(&ok);
if (!ok)
m_verbose = 1;
}
m_gdbServer = 0;
m_gdbConnection = 0;
#ifdef Q_OS_WIN