| 165 | } |
| 166 | |
| 167 | bool MIDebugSession::startDebugger(ILaunchConfiguration *cfg) |
| 168 | { |
| 169 | qCDebug(DEBUGGERCOMMON) << "Starting new debugger instance"; |
| 170 | if (m_debugger) { |
| 171 | qCWarning(DEBUGGERCOMMON) << "m_debugger object still exists"; |
| 172 | delete m_debugger; |
| 173 | m_debugger = nullptr; |
| 174 | } |
| 175 | m_debugger = createDebugger(); |
| 176 | m_debugger->setParent(this); |
| 177 | |
| 178 | // output signals |
| 179 | connect(m_debugger, &MIDebugger::applicationOutput, this, [this](const QString& output) { |
| 180 | auto lines = output.split(QRegularExpression(QStringLiteral("[\r\n]")), Qt::SkipEmptyParts); |
| 181 | for (auto& line : lines) { |
| 182 | int p = line.length(); |
| 183 | while (p >= 1 && (line[p - 1] == QLatin1Char('\r') || line[p - 1] == QLatin1Char('\n'))) { |
| 184 | p--; |
| 185 | } |
| 186 | if (p != line.length()) |
| 187 | line.truncate(p); |
| 188 | } |
| 189 | emit inferiorStdoutLines(lines); |
| 190 | }); |
| 191 | connect(m_debugger, &MIDebugger::userCommandOutput, this, &MIDebugSession::debuggerUserCommandOutput); |
| 192 | connect(m_debugger, &MIDebugger::internalCommandOutput, this, &MIDebugSession::debuggerInternalCommandOutput); |
| 193 | connect(m_debugger, &MIDebugger::debuggerInternalOutput, this, &MIDebugSession::debuggerInternalOutput); |
| 194 | |
| 195 | // state signals |
| 196 | connect(m_debugger, &MIDebugger::programStopped, this, &MIDebugSession::inferiorStopped); |
| 197 | connect(m_debugger, &MIDebugger::programRunning, this, &MIDebugSession::inferiorRunning); |
| 198 | |
| 199 | // internal handlers |
| 200 | connect(m_debugger, &MIDebugger::ready, this, &MIDebugSession::slotDebuggerReady); |
| 201 | connect(m_debugger, &MIDebugger::exited, this, &MIDebugSession::slotDebuggerExited); |
| 202 | connect(m_debugger, &MIDebugger::programStopped, this, &MIDebugSession::slotInferiorStopped); |
| 203 | connect(m_debugger, &MIDebugger::programRunning, this, &MIDebugSession::slotInferiorRunning); |
| 204 | connect(m_debugger, &MIDebugger::notification, this, &MIDebugSession::processNotification); |
| 205 | |
| 206 | |
| 207 | // start the debugger. Do this after connecting all signals so that initial |
| 208 | // debugger output, and important events like the debugger died are reported. |
| 209 | QStringList extraArguments; |
| 210 | if (!m_sourceInitFile) |
| 211 | extraArguments << QStringLiteral("--nx"); |
| 212 | |
| 213 | auto config = cfg ? cfg->config() |
| 214 | // FIXME: this is only used when attachToProcess or examineCoreFile. |
| 215 | // Change to use a global launch configuration when calling |
| 216 | : KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("GDB Config")); |
| 217 | |
| 218 | if (!m_debugger->start(config, extraArguments)) { |
| 219 | // debugger failed to start, ensure debugger and session state are correctly updated. |
| 220 | setDebuggerStateOn(s_dbgFailedStart); |
| 221 | return false; |
| 222 | } |
| 223 | |
| 224 | // FIXME: here, we should wait until the debugger is up and waiting for input. |