OSDN Git Service

Debugger: Expose which languages (QML, C++, Any) an engine supports
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / cdb / cdbengine.cpp
index 9d2d1e3..587662c 100644 (file)
@@ -316,7 +316,6 @@ static inline bool validMode(DebuggerStartMode sm)
 {
     switch (sm) {
     case NoStartMode:
-    case AttachCore:
     case StartRemoteGdb:
         return false;
     default:
@@ -353,19 +352,24 @@ bool isCdbEngineEnabled()
 #endif
 }
 
-static inline QString msgNoCdbBinaryForToolChain(const ProjectExplorer::Abi &tc)
+static inline QString msgNoCdbBinaryForToolChain(const Abi &tc)
 {
     return CdbEngine::tr("There is no CDB binary available for binaries in format '%1'").arg(tc.toString());
 }
 
+static inline bool isMsvcFlavor(Abi::OSFlavor osf)
+{
+  return osf == Abi::WindowsMsvc2005Flavor
+      || osf == Abi::WindowsMsvc2008Flavor
+      || osf == Abi::WindowsMsvc2010Flavor;
+}
+
 static QString cdbBinary(const DebuggerStartParameters &sp)
 {
     if (!sp.debuggerCommand.isEmpty()) {
         // Do not use a GDB binary if we got started for a project with MinGW runtime.
-        const bool abiMatch = sp.toolChainAbi.os() == ProjectExplorer::Abi::WindowsOS
-                    && (sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2005Flavor
-                        || sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2008Flavor
-                        || sp.toolChainAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2010Flavor);
+        const bool abiMatch = sp.toolChainAbi.os() == Abi::WindowsOS
+                   && isMsvcFlavor(sp.toolChainAbi.osFlavor());
         if (abiMatch)
             return sp.debuggerCommand;
     }
@@ -394,10 +398,15 @@ bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
         return false;
     }
 
+    if (sp.startMode == AttachCore && !isMsvcFlavor(sp.toolChainAbi.osFlavor())) {
+        check->errorDetails.push_back(CdbEngine::tr("The CDB debug engine cannot debug gdb core files."));
+        return false;
+    }
+
     if (cdbBinary(sp).isEmpty()) {
         check->errorDetails.push_back(msgNoCdbBinaryForToolChain(sp.toolChainAbi));
-        check->settingsCategory = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
-        check->settingsPage = QLatin1String(ProjectExplorer::Constants::TOOLCHAIN_SETTINGS_CATEGORY);
+        check->settingsCategory = QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
+        check->settingsPage = QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
         return false;
     }
 
@@ -427,7 +436,7 @@ static inline Utils::SavedAction *theAssemblerAction()
 
 CdbEngine::CdbEngine(const DebuggerStartParameters &sp,
         DebuggerEngine *masterEngine, const OptionsPtr &options) :
-    DebuggerEngine(sp, masterEngine),
+    DebuggerEngine(sp, CppLanguage, masterEngine),
     m_creatorExtPrefix("<qtcreatorcdbext>|"),
     m_tokenPrefix("<token>"),
     m_options(options),
@@ -479,6 +488,7 @@ void CdbEngine::init()
     m_pendingBreakpointMap.clear();
     m_customSpecialStopData.clear();
     m_symbolAddressCache.clear();
+    m_coreStopReason.reset();
 
     // Create local list of mappings in native separators
     m_sourcePathMappings.clear();
@@ -731,7 +741,7 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
     const QString extensionFileName = extensionFi.fileName();
     // Prepare arguments
     QStringList arguments;
-    const bool isRemote = sp.startMode == AttachToRemote;
+    const bool isRemote = sp.startMode == AttachToRemoteServer;
     if (isRemote) { // Must be first
         arguments << QLatin1String("-remote") << sp.remoteChannel;
     } else {
@@ -757,7 +767,7 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
             nativeArguments.push_back(blank);
         nativeArguments += QDir::toNativeSeparators(sp.executable);
         break;
-    case AttachToRemote:
+    case AttachToRemoteServer:
         break;
     case AttachExternal:
     case AttachCrashedExternal:
@@ -769,6 +779,9 @@ bool CdbEngine::launchCDB(const DebuggerStartParameters &sp, QString *errorMessa
                 arguments << QLatin1String("-pr") << QLatin1String("-pb");
         }
         break;
+    case AttachCore:
+        arguments << QLatin1String("-z") << sp.coreFile;
+        break;
     default:
         *errorMessage = QString::fromLatin1("Internal error: Unsupported start mode %1.").arg(sp.startMode);
         return false;
@@ -827,8 +840,9 @@ void CdbEngine::setupInferior()
 {
     if (debug)
         qDebug("setupInferior");
+    // QmlCppEngine expects the QML engine to be connected before any breakpoints are hit
+    // (attemptBreakpointSynchronization() will be directly called then)
     attemptBreakpointSynchronization();
-
     if (startParameters().breakOnMain) {
         const BreakpointParameters bp(BreakpointAtMain);
         postCommand(cdbAddBreakpointCommand(bp, m_sourcePathMappings,
@@ -845,7 +859,13 @@ void CdbEngine::runEngine()
         qDebug("runEngine");
     foreach (const QString &breakEvent, m_options->breakEvents)
             postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0);
-    postCommand("g", 0);
+    if (startParameters().startMode == AttachCore) {
+        QTC_ASSERT(!m_coreStopReason.isNull(), return; );
+        notifyInferiorUnrunnable();
+        processStop(*m_coreStopReason, false);
+    } else {
+        postCommand("g", 0);
+    }
 }
 
 bool CdbEngine::commandsPending() const
@@ -920,7 +940,7 @@ void CdbEngine::shutdownEngine()
         if (startParameters().startMode == AttachExternal || startParameters().startMode == AttachCrashedExternal)
             detachDebugger();
         // Remote requires a bit more force to quit.
-        if (m_effectiveStartMode == AttachToRemote) {
+        if (m_effectiveStartMode == AttachToRemoteServer) {
             postCommand(m_extensionCommandPrefixBA + "shutdownex", 0);
             postCommand("qq", 0);
         } else {
@@ -1074,7 +1094,7 @@ void CdbEngine::updateLocalVariable(const QByteArray &iname)
 unsigned CdbEngine::debuggerCapabilities() const
 {
     return DisassemblerCapability | RegisterCapability | ShowMemoryCapability
-           |WatchpointByAddressCapability|JumpToLineCapability|AddWatcherCapability
+           |WatchpointByAddressCapability|JumpToLineCapability|AddWatcherCapability|WatchWidgetsCapability
            |ReloadModuleCapability
            |BreakOnThrowAndCatchCapability // Sort-of: Can break on throw().
            |BreakConditionCapability|TracePointCapability
@@ -1130,7 +1150,7 @@ void CdbEngine::doContinueInferior()
 
 bool CdbEngine::canInterruptInferior() const
 {
-    return m_effectiveStartMode != AttachToRemote && inferiorPid();
+    return m_effectiveStartMode != AttachToRemoteServer && inferiorPid();
 }
 
 void CdbEngine::interruptInferior()
@@ -1646,7 +1666,7 @@ static inline quint64 findClosestFunctionAddress(const QList<quint64> &addresses
     for (int i = 0; i < size; i++) {
         if (addresses.at(i) <= needle) {
             const quint64 offset = needle - addresses.at(i);
-            if (offset < offset) {
+            if (offset < closestOffset) {
                 closestOffset = offset;
                 closestIndex = i;
             }
@@ -1766,8 +1786,10 @@ void CdbEngine::reloadFullStack()
 
 void CdbEngine::handlePid(const CdbExtensionCommandPtr &reply)
 {
-    if (reply->success) {
+    // Fails for core dumps.
+    if (reply->success)
         notifyInferiorPid(reply->reply.toULongLong());
+    if (reply->success || startParameters().startMode == AttachCore) {
         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSetupOk")
         notifyInferiorSetupOk();
     }  else {
@@ -1778,8 +1800,8 @@ void CdbEngine::handlePid(const CdbExtensionCommandPtr &reply)
     }
 }
 
-// Parse CDB gdbmi register syntax
-static inline Register parseRegister(const GdbMi &gdbmiReg)
+// Parse CDB gdbmi register syntax.
+static Register parseRegister(const GdbMi &gdbmiReg)
 {
     Register reg;
     reg.name = gdbmiReg.findChild("name").data();
@@ -1789,7 +1811,7 @@ static inline Register parseRegister(const GdbMi &gdbmiReg)
         reg.name += description.data();
         reg.name += ')';
     }
-    reg.value = QString::fromAscii(gdbmiReg.findChild("value").data());
+    reg.value = gdbmiReg.findChild("value").data();
     return reg;
 }
 
@@ -2107,8 +2129,14 @@ void CdbEngine::handleSessionIdle(const QByteArray &messageBA)
     if (state() == EngineSetupRequested) { // Temporary stop at beginning
         STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyEngineSetupOk")
         notifyEngineSetupOk();
+        // Store stop reason to be handled in runEngine().
+        if (startParameters().startMode == AttachCore) {
+            m_coreStopReason.reset(new GdbMi);
+            m_coreStopReason->fromString(messageBA);
+        }
         return;
     }
+
     GdbMi stopReason;
     stopReason.fromString(messageBA);
     processStop(stopReason, false);
@@ -2136,12 +2164,14 @@ void CdbEngine::processStop(const GdbMi &stopReason, bool conditionalBreakPointT
     }
     // Notify about state and send off command sequence to get stack, etc.
     if (stopFlags & StopNotifyStop) {
-        if (state() == InferiorStopRequested) {
-            STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorStopOk")
-            notifyInferiorStopOk();
-        } else {
-            STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSpontaneousStop")
-            notifyInferiorSpontaneousStop();
+        if (startParameters().startMode != AttachCore) {
+            if (state() == InferiorStopRequested) {
+                STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorStopOk")
+                        notifyInferiorStopOk();
+            } else {
+                STATE_DEBUG(state(), Q_FUNC_INFO, __LINE__, "notifyInferiorSpontaneousStop")
+                        notifyInferiorSpontaneousStop();
+            }
         }
         // Prevent further commands from being sent if shutdown is in progress
         if (stopFlags & StopShutdownInProgress) {
@@ -2520,6 +2550,8 @@ bool CdbEngine::acceptsBreakpoint(BreakpointModelId id) const
     case BreakpointAtFork:
     case WatchpointAtExpression:
     case BreakpointAtSysCall:
+    case BreakpointOnQmlSignalHandler:
+    case BreakpointAtJavaScriptThrow:
         return false;
     case WatchpointAtAddress:
     case BreakpointByFileAndLine:
@@ -2655,7 +2687,8 @@ void CdbEngine::attemptBreakpointSynchronization()
         }
         switch (handler->state(id)) {
         case BreakpointInsertRequested:
-            if (parameters.type == BreakpointByFileAndLine) {
+            if (parameters.type == BreakpointByFileAndLine
+                && m_options->breakpointCorrection) {
                 if (lineCorrection.isNull())
                     lineCorrection.reset(new BreakpointCorrectionContext(debuggerCore()->cppCodeModelSnapshot(),
                                                                          CPlusPlus::CppModelManagerInterface::instance()->workingCopy()));