diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 1da444113ea1f44d557d3ede56bffbf4cb2d6d55..ae006133509ba18acab7a459ae1d0ea56d50fa1e 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -68,6 +68,7 @@ int qtGhVersion = QT_VERSION; #include <ctype.h> #include <stdio.h> +#include <unistd.h> #ifdef Q_OS_WIN # include <windows.h> @@ -2484,6 +2485,7 @@ void qDumpObjectData440( int extraInt2, int extraInt3) { + //sleep(20); if (protocolVersion == 1) { QDumper d; d.protocolVersion = protocolVersion; diff --git a/src/plugins/coreplugin/html/welcome.html b/src/plugins/coreplugin/html/welcome.html index c4e47d62118a76b10c06e9800760f97055c50bc2..6275a7d314977f13e3c377e10986207a6c6a7386 100644 --- a/src/plugins/coreplugin/html/welcome.html +++ b/src/plugins/coreplugin/html/welcome.html @@ -40,8 +40,6 @@ developers to create graphically appealing applications for desktop, embedded, and mobile devices. Click on <strong>Getting Started</strong> to begin developing with Qt Creator.</p> - <!--<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p> - <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</p>--> <div class="get_started_container"> <a class="btn_getting_started img_link" href="gh:getting-started"> </a> diff --git a/src/plugins/coreplugin/welcomemode.h b/src/plugins/coreplugin/welcomemode.h index 56899a4463c290069cf17fffea66927d7d4f3b7e..e918f4ea065c9198d9995d8a0c7b6645cd213fd1 100644 --- a/src/plugins/coreplugin/welcomemode.h +++ b/src/plugins/coreplugin/welcomemode.h @@ -72,8 +72,8 @@ public: QString name() const; QIcon icon() const; int priority() const; - QWidget* widget(); - const char* uniqueModeName() const; + QWidget *widget(); + const char *uniqueModeName() const; QList<int> context() const; void activated(); QString contextHelpId() const { return QLatin1String("Qt Creator"); } diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index e4b859d6c198a7919808bea28a084373e3bf4e84..f6413db72f9259d181413948d7159b8bd0c01e52 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1181,7 +1181,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } - tryLoadCustomDumpers(); + //tryLoadCustomDumpers(); // jump over well-known frames static int stepCounter = 0; @@ -3338,7 +3338,7 @@ void GdbEngine::handleQueryDataDumper2(const GdbResultRecord &record) tr("The debugged binary does not contain information needed for " "nice display of Qt data types.\n\n" "You might want to try including the file\n\n" - ".../ide/main/bin/gdbmacros/gdbmacros.cpp'\n\n" + ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n" "into your project directly.") ); } else { @@ -3444,11 +3444,12 @@ void GdbEngine::handleEvaluateExpression(const GdbResultRecord &record, void GdbEngine::handleDumpCustomSetup(const GdbResultRecord &record) { - qDebug() << "CUSTOM SETUP RESULT: " << record.toString(); + //qDebug() << "CUSTOM SETUP RESULT: " << record.toString(); if (record.resultClass == GdbResultDone) { } else if (record.resultClass == GdbResultError) { QString msg = record.data.findChild("msg").data(); - qDebug() << "CUSTOM DUMPER SETUP ERROR MESSAGE: " << msg; + //qDebug() << "CUSTOM DUMPER SETUP ERROR MESSAGE: " << msg; + q->showStatusMessage(tr("Custom dumper setup: %1").arg(msg), 10000); } } @@ -3586,121 +3587,124 @@ void GdbEngine::handleDumpCustomValue2(const GdbResultRecord &record, void GdbEngine::updateLocals() { -setTokenBarrier(); + setTokenBarrier(); + + m_pendingRequests = 0; + + PENDING_DEBUG("\nRESET PENDING"); + m_toolTipCache.clear(); + m_toolTipExpression.clear(); + qq->watchHandler()->reinitializeWatchers(); -m_pendingRequests = 0; -PENDING_DEBUG("\nRESET PENDING"); -m_toolTipCache.clear(); -m_toolTipExpression.clear(); -qq->watchHandler()->reinitializeWatchers(); + int level = currentFrame(); + // '2' is 'list with type and value' + QString cmd = QString("-stack-list-arguments 2 %1 %2").arg(level).arg(level); + sendSynchronizedCommand(cmd, StackListArguments); // stage 1/2 + // '2' is 'list with type and value' + sendSynchronizedCommand("-stack-list-locals 2", StackListLocals); // stage 2/2 -int level = currentFrame(); -// '2' is 'list with type and value' -QString cmd = QString("-stack-list-arguments 2 %1 %2").arg(level).arg(level); -sendSynchronizedCommand(cmd, StackListArguments); // stage 1/2 -// '2' is 'list with type and value' -sendSynchronizedCommand("-stack-list-locals 2", StackListLocals); // stage 2/2 + tryLoadCustomDumpers(); } void GdbEngine::handleStackListArguments(const GdbResultRecord &record) { -// stage 1/2 - -// Linux: -// 12^done,stack-args= -// [frame={level="0",args=[ -// {name="argc",type="int",value="1"}, -// {name="argv",type="char **",value="(char **) 0x7..."}]}] -// Mac: -// 78^done,stack-args= -// {frame={level="0",args={ -// varobj= -// {exp="this",value="0x38a2fab0",name="var21",numchild="3", -// type="CurrentDocumentFind * const",typecode="PTR", -// dynamic_type="",in_scope="true",block_start_addr="0x3938e946", -// block_end_addr="0x3938eb2d"}, -// varobj= -// {exp="before",value="@0xbfffb9f8: {d = 0x3a7f2a70}", -// name="var22",numchild="1",type="const QString ...} }}} -// -// In both cases, iterating over the children of stack-args/frame/args -// is ok. -m_currentFunctionArgs.clear(); -if (record.resultClass == GdbResultDone) { - const GdbMi list = record.data.findChild("stack-args"); - const GdbMi frame = list.findChild("frame"); - const GdbMi args = frame.findChild("args"); - m_currentFunctionArgs = args.children(); -} else if (record.resultClass == GdbResultError) { - qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen"; -} + // stage 1/2 + + // Linux: + // 12^done,stack-args= + // [frame={level="0",args=[ + // {name="argc",type="int",value="1"}, + // {name="argv",type="char **",value="(char **) 0x7..."}]}] + // Mac: + // 78^done,stack-args= + // {frame={level="0",args={ + // varobj= + // {exp="this",value="0x38a2fab0",name="var21",numchild="3", + // type="CurrentDocumentFind * const",typecode="PTR", + // dynamic_type="",in_scope="true",block_start_addr="0x3938e946", + // block_end_addr="0x3938eb2d"}, + // varobj= + // {exp="before",value="@0xbfffb9f8: {d = 0x3a7f2a70}", + // name="var22",numchild="1",type="const QString ...} }}} + // + // In both cases, iterating over the children of stack-args/frame/args + // is ok. + m_currentFunctionArgs.clear(); + if (record.resultClass == GdbResultDone) { + const GdbMi list = record.data.findChild("stack-args"); + const GdbMi frame = list.findChild("frame"); + const GdbMi args = frame.findChild("args"); + m_currentFunctionArgs = args.children(); + } else if (record.resultClass == GdbResultError) { + qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen"; + } } void GdbEngine::handleStackListLocals(const GdbResultRecord &record) { -// stage 2/2 + // stage 2/2 -// There could be shadowed variables -QList<GdbMi> locals = record.data.findChild("locals").children(); -locals += m_currentFunctionArgs; + // There could be shadowed variables + QList<GdbMi> locals = record.data.findChild("locals").children(); + locals += m_currentFunctionArgs; -setLocals(locals); + setLocals(locals); } void GdbEngine::setLocals(const QList<GdbMi> &locals) { -//qDebug() << m_varToType; -QHash<QString, int> seen; - -foreach (const GdbMi &item, locals) { - // Local variables of inlined code are reported as - // 26^done,locals={varobj={exp="this",value="",name="var4",exp="this", - // numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..." - // We do not want these at all. Current hypotheses is that those - // "spurious" locals have _two_ "exp" field. Try to filter them: - #ifdef Q_OS_MAC - int numExps = 0; - foreach (const GdbMi &child, item.children()) - numExps += int(child.name() == "exp"); - if (numExps > 1) - continue; - QString name = item.findChild("exp").data(); - #else - QString name = item.findChild("name").data(); - #endif - int n = seen.value(name); - if (n) { - seen[name] = n + 1; - WatchData data; - data.iname = "local." + name + QString::number(n + 1); - data.name = name + QString(" <shadowed %1>").arg(n); - //data.setValue("<shadowed>"); - setWatchDataValue(data, item.findChild("value")); - data.setType("<shadowed>"); - data.setChildCount(0); - insertData(data); - } else { - seen[name] = 1; - WatchData data; - data.iname = "local." + name; - data.name = name; - data.exp = name; - data.framekey = m_currentFrame + data.name; - setWatchDataType(data, item.findChild("type")); - // set value only directly if it is simple enough, otherwise - // pass through the insertData() machinery - if (isIntOrFloatType(data.type) || isPointerType(data.type)) + //qDebug() << m_varToType; + QHash<QString, int> seen; + + foreach (const GdbMi &item, locals) { + // Local variables of inlined code are reported as + // 26^done,locals={varobj={exp="this",value="",name="var4",exp="this", + // numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..." + // We do not want these at all. Current hypotheses is that those + // "spurious" locals have _two_ "exp" field. Try to filter them: + #ifdef Q_OS_MAC + int numExps = 0; + foreach (const GdbMi &child, item.children()) + numExps += int(child.name() == "exp"); + if (numExps > 1) + continue; + QString name = item.findChild("exp").data(); + #else + QString name = item.findChild("name").data(); + #endif + int n = seen.value(name); + if (n) { + seen[name] = n + 1; + WatchData data; + data.iname = "local." + name + QString::number(n + 1); + data.name = name + QString(" <shadowed %1>").arg(n); + //data.setValue("<shadowed>"); setWatchDataValue(data, item.findChild("value")); - if (!qq->watchHandler()->isExpandedIName(data.iname)) - data.setChildrenUnneeded(); - if (isPointerType(data.type) || data.name == "this") - data.setChildCount(1); - if (0 && m_varToType.contains(data.framekey)) { - qDebug() << "RE-USING " << m_varToType.value(data.framekey); - data.setType(m_varToType.value(data.framekey)); + data.setType("<shadowed>"); + data.setChildCount(0); + insertData(data); + } else { + seen[name] = 1; + WatchData data; + data.iname = "local." + name; + data.name = name; + data.exp = name; + data.framekey = m_currentFrame + data.name; + setWatchDataType(data, item.findChild("type")); + // set value only directly if it is simple enough, otherwise + // pass through the insertData() machinery + if (isIntOrFloatType(data.type) || isPointerType(data.type)) + setWatchDataValue(data, item.findChild("value")); + if (!qq->watchHandler()->isExpandedIName(data.iname)) + data.setChildrenUnneeded(); + if (isPointerType(data.type) || data.name == "this") + data.setChildCount(1); + if (0 && m_varToType.contains(data.framekey)) { + qDebug() << "RE-USING " << m_varToType.value(data.framekey); + data.setType(m_varToType.value(data.framekey)); + } + insertData(data); } - insertData(data); - } } } @@ -3958,15 +3962,17 @@ void GdbEngine::tryLoadCustomDumpers() QString lib = q->m_buildDir + "/qtc-gdbmacros/libgdbmacros.so"; if (QFileInfo(lib).isExecutable()) { //sendCommand("p dlopen"); - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 0"); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 0"); QString flag = QString::number(RTLD_NOW); - sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")"); + sendSynchronizedCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")", + WatchDumpCustomSetup); // some older systems like CentOS 4.6 prefer this: - sendCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")"); - sendCommand("sharedlibrary " + dotEscape(lib)); - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 1"); + sendSynchronizedCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")", + WatchDumpCustomSetup); + sendSynchronizedCommand("sharedlibrary " + dotEscape(lib)); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 1"); } else { qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: " << lib << QFileInfo(lib).isExecutable(); @@ -3976,13 +3982,14 @@ void GdbEngine::tryLoadCustomDumpers() QString lib = q->m_buildDir + "/qtc-gdbmacros/libgdbmacros.dylib"; if (QFileInfo(lib).isExecutable()) { //sendCommand("p dlopen"); // FIXME: remove me - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 0"); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 0"); QString flag = QString::number(RTLD_NOW); - sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")"); - sendCommand("sharedlibrary " + dotEscape(lib)); - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 1"); + sendSynchronizedCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")", + WatchDumpCustomSetup); + sendSynchronizedCommand("sharedlibrary " + dotEscape(lib)); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 1"); } else { qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: " << lib << QFileInfo(lib).isExecutable(); @@ -3991,14 +3998,15 @@ void GdbEngine::tryLoadCustomDumpers() #if defined(Q_OS_WIN) QString lib = q->m_buildDir + "/qtc-gdbmacros/debug/gdbmacros.dll"; if (QFileInfo(lib).exists()) { - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 0"); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 0"); //sendCommand("handle SIGSEGV pass stop print"); //sendCommand("set unwindonsignal off"); - sendCommand("call LoadLibraryA(\"" + lib + "\")"); - sendCommand("sharedlibrary " + dotEscape(lib)); - if (qq->useFastStart()) - sendCommand("set stop-on-solib-events 1"); + sendSynchronizedCommand("call LoadLibraryA(\"" + lib + "\")", + WatchDumpCustomSetup); + sendSynchronizedCommand("sharedlibrary " + dotEscape(lib)); + //if (qq->useFastStart()) + // sendCommand("set stop-on-solib-events 1"); } else { qDebug() << "DEBUG HELPER LIBRARY IS NOT USABLE: " << lib << QFileInfo(lib).isExecutable(); @@ -4006,9 +4014,9 @@ void GdbEngine::tryLoadCustomDumpers() #endif // retreive list of dumpable classes - sendCommand("call qDumpObjectData440(1,%1+1,0,0,0,0,0,0)", + sendSynchronizedCommand("call qDumpObjectData440(1,%1+1,0,0,0,0,0,0)", GdbQueryDataDumper1); - sendCommand("p (char*)qDumpOutBuffer", GdbQueryDataDumper2); + sendSynchronizedCommand("p (char*)qDumpOutBuffer", GdbQueryDataDumper2); } diff --git a/src/plugins/debugger/procinterrupt.cpp b/src/plugins/debugger/procinterrupt.cpp index 08f7d39280584c9e0680e4a31e2ee63a27de3ef8..47a309deac8af5fb7bb1e2978969f698dc5e0e62 100644 --- a/src/plugins/debugger/procinterrupt.cpp +++ b/src/plugins/debugger/procinterrupt.cpp @@ -33,7 +33,8 @@ #include "procinterrupt.h" -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) + #include <windows.h> #include <Tlhelp32.h> @@ -75,7 +76,37 @@ DWORD findProcessId(DWORD parentId) CloseHandle(hProcList); return procId; } -#else + +bool Debugger::Internal::interruptProcess(int pID) +{ + DWORD pid = pID; + if (!pid) + return false; + + PtrCreateRemoteThread libFunc = resolveCreateRemoteThread(); + if (libFunc) { + DWORD dwThreadId = 0; + HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + HANDLE hthread = libFunc(hproc, NULL, 0, (LPTHREAD_START_ROUTINE)DebugBreak, 0, 0, &dwThreadId); + CloseHandle(hthread); + if (dwThreadId) + return true; + } + + return false; +} + +bool Debugger::Internal::interruptChildProcess(Q_PID parentPID) +{ + DWORD pid = findProcessId(parentPID->dwProcessId); + return interruptProcess(pid); +} + +#endif // defined(Q_OS_WIN) + + + +#if defined(Q_OS_LINUX) || defined(Q_OS_MAC) #include <QtCore/QLatin1String> #include <QtCore/QString> @@ -89,12 +120,14 @@ DWORD findProcessId(DWORD parentId) #include <sys/sysctl.h> -#define OPProcessValueUnknown UINT_MAX + +using namespace Debugger::Internal; /* Mac OS X int OPParentIDForProcessID(int pid) // Returns the parent process id for the given process id (pid) { + const uint OPProcessValueUnknown = UINT_MAX; struct kinfo_proc info; size_t length = sizeof(struct kinfo_proc); int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; @@ -140,44 +173,21 @@ int findChildProcess(int parentId) return -1; } -#endif - bool Debugger::Internal::interruptProcess(int pID) { -#ifdef Q_OS_WIN - DWORD pid = pID; - if (!pid) - return false; - - PtrCreateRemoteThread libFunc = resolveCreateRemoteThread(); - if (libFunc) { - DWORD dwThreadId = 0; - HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); - HANDLE hthread = libFunc(hproc, NULL, 0, (LPTHREAD_START_ROUTINE)DebugBreak, 0, 0, &dwThreadId); - CloseHandle(hthread); - if (dwThreadId) - return true; - } -#else int procId = pID; if (procId != -1) { - if (kill(procId, 2) == 0) + if (kill(procId, SIGINT) == 0) return true; } - -#endif - return false; } bool Debugger::Internal::interruptChildProcess(Q_PID parentPID) { -#ifdef WIN32 - DWORD pid = findProcessId(parentPID->dwProcessId); - return interruptProcess(pid); -#else int procId = findChildProcess(parentPID); //qDebug() << "INTERRUPTING PROCESS" << procId; return interruptProcess(procId); -#endif } + +#endif // defined(Q_OS_LINUX) || defined(Q_OS_MAC)