1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "coregdbadapter.h"
35 #include "debuggerstartparameters.h"
36 #include "debuggercore.h"
37 #include "debuggeractions.h"
38 #include "debuggerstringutils.h"
40 #include "gdbengine.h"
42 #include <utils/qtcassert.h>
44 #include <QtCore/QDir>
45 #include <QtCore/QFileInfo>
46 #include <QtGui/QMessageBox>
51 #define CB(callback) \
52 static_cast<GdbEngine::AdapterCallback>(&CoreGdbAdapter::callback), \
55 ///////////////////////////////////////////////////////////////////////
59 ///////////////////////////////////////////////////////////////////////
61 static QByteArray coreName(const DebuggerStartParameters &sp)
63 QFileInfo fi(sp.coreFile);
64 return fi.absoluteFilePath().toLocal8Bit();
67 CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
68 : AbstractGdbAdapter(engine, parent),
69 m_executable(startParameters().executable),
70 m_coreName(coreName(startParameters()))
73 void CoreGdbAdapter::startAdapter()
75 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
76 showMessage(_("TRYING TO START ADAPTER"));
79 args.append(_("-ex"));
80 args.append(_("set auto-solib-add off"));
81 if (!m_engine->startGdb(args, QString()))
84 //if (m_executable.isEmpty()) {
85 // showMessageBox(QMessageBox::Warning,
86 // tr("Error Loading Symbols"),
87 // tr("No executable to load symbols from specified."));
91 const bool canUseExeFromCore = true;
93 const bool canUseExeFromCore = false;
96 if (!m_executable.isEmpty()) {
97 m_engine->notifyEngineSetupOk();
98 } else if (canUseExeFromCore) {
99 // Extra round trip to get executable name from core file.
100 // This is sometimes not the full name, so it can't be used
101 // as the generic solution.
103 // Quoting core name below fails in gdb 6.8-debian.
104 m_engine->postCommand("target core " + m_coreName,
105 CB(handleTemporaryTargetCore));
107 QString msg = tr("The name of the binary file cannot be extracted "
108 "from this core file.");
110 msg += tr("Try to specify the binary using the "
111 "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
112 showMessageBox(QMessageBox::Warning,
113 tr("Loading core file failed"), msg);
114 m_engine->notifyEngineSetupFailed();
118 void CoreGdbAdapter::handleTemporaryTargetCore(const GdbResponse &response)
120 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
121 if (response.resultClass != GdbResultDone) {
122 showMessage(tr("Attach to core failed."), StatusBar);
123 m_engine->notifyEngineSetupFailed();
127 GdbMi console = response.data.findChild("consolestreamoutput");
128 int pos1 = console.data().indexOf('`');
129 int pos2 = console.data().indexOf('\'');
130 if (pos1 == -1 || pos2 == -1) {
131 showMessage(tr("Attach to core failed."), StatusBar);
132 m_engine->notifyEngineSetupFailed();
136 m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
137 // Strip off command line arguments. FIXME: make robust.
138 int idx = m_executable.indexOf(_c(' '));
140 m_executable.truncate(idx);
141 if (m_executable.isEmpty()) {
142 m_engine->postCommand("detach");
143 m_engine->notifyEngineSetupFailed();
146 m_executable = QFileInfo(startParameters().coreFile).absoluteDir()
147 .absoluteFilePath(m_executable);
148 showMessage(tr("Attached to core temporarily."), StatusBar);
149 m_engine->postCommand("detach", CB(handleTemporaryDetach));
152 void CoreGdbAdapter::handleTemporaryDetach(const GdbResponse &response)
154 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
155 if (response.resultClass == GdbResultDone) {
156 m_engine->notifyEngineSetupOk();
158 m_engine->notifyEngineSetupFailed();
162 void CoreGdbAdapter::setupInferior()
164 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
165 // Do that first, otherwise no symbols are loaded.
166 QFileInfo fi(m_executable);
167 QByteArray path = fi.absoluteFilePath().toLocal8Bit();
168 m_engine->postCommand("-file-exec-and-symbols \"" + path + '"',
169 CB(handleFileExecAndSymbols));
172 void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
174 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
175 if (response.resultClass == GdbResultDone) {
176 showMessage(tr("Symbols found."), StatusBar);
177 m_engine->postCommand("target core " + m_coreName,
178 CB(handleTargetCore));
181 QString msg = tr("No symbols found in core file <i>%1</i>.")
182 .arg(startParameters().coreFile);
184 msg += tr("This can be caused by a path length limitation in the "
187 msg += tr("Try to specify the binary using the "
188 "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
189 m_engine->notifyInferiorSetupFailed(msg);
192 void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
194 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
195 if (response.resultClass == GdbResultDone) {
196 // HACK: The namespace is not accessible in the initial run.
197 m_engine->loadPythonDumpers();
198 showMessage(tr("Attached to core."), StatusBar);
199 m_engine->handleInferiorPrepared();
200 // Due to the auto-solib-add off setting, we don't have any
201 // symbols yet. Load them in order of importance.
202 m_engine->reloadStack(true);
203 m_engine->postCommand("info shared", CB(handleModulesList));
206 QString msg = tr("Attach to core \"%1\" failed:\n")
207 .arg(startParameters().coreFile)
208 + QString::fromLocal8Bit(response.data.findChild("msg").data());
209 m_engine->notifyInferiorSetupFailed(msg);
212 void CoreGdbAdapter::handleModulesList(const GdbResponse &response)
214 m_engine->handleModulesList(response);
215 loadSymbolsForStack();
218 void CoreGdbAdapter::loadSymbolsForStack()
220 m_engine->loadSymbolsForStack();
221 QTimer::singleShot(1000, this, SLOT(loadAllSymbols()));
224 void CoreGdbAdapter::loadAllSymbols()
226 m_engine->loadAllSymbols();
229 void CoreGdbAdapter::runEngine()
231 QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
232 m_engine->notifyInferiorUnrunnable();
233 m_engine->updateAll();
236 void CoreGdbAdapter::interruptInferior()
238 // A core never runs, so this cannot be called.
239 QTC_ASSERT(false, /**/);
242 void CoreGdbAdapter::shutdownInferior()
244 m_engine->notifyInferiorShutdownOk();
247 void CoreGdbAdapter::shutdownAdapter()
249 m_engine->notifyAdapterShutdownOk();
252 } // namespace Internal
253 } // namespace Debugger