1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "coregdbadapter.h"
36 #include "debuggerstartparameters.h"
37 #include "debuggercore.h"
38 #include "debuggeractions.h"
39 #include "debuggerstringutils.h"
41 #include "gdbengine.h"
43 #include <utils/qtcassert.h>
45 #include <QtCore/QDir>
46 #include <QtCore/QFileInfo>
47 #include <QtGui/QMessageBox>
52 #define CB(callback) \
53 static_cast<GdbEngine::AdapterCallback>(&CoreGdbAdapter::callback), \
56 ///////////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////////
62 static QByteArray coreName(const DebuggerStartParameters &sp)
64 QFileInfo fi(sp.coreFile);
65 return fi.absoluteFilePath().toLocal8Bit();
68 CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
69 : AbstractGdbAdapter(engine, parent),
70 m_executable(startParameters().executable),
71 m_coreName(coreName(startParameters()))
74 void CoreGdbAdapter::startAdapter()
76 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
77 showMessage(_("TRYING TO START ADAPTER"));
80 args.append(_("-ex"));
81 args.append(_("set auto-solib-add off"));
82 if (!m_engine->startGdb(args))
85 //if (m_executable.isEmpty()) {
86 // showMessageBox(QMessageBox::Warning,
87 // tr("Error Loading Symbols"),
88 // tr("No executable to load symbols from specified."));
92 const bool canUseExeFromCore = true;
94 const bool canUseExeFromCore = false;
97 if (!m_executable.isEmpty()) {
98 m_engine->notifyEngineSetupOk();
99 } else if (canUseExeFromCore) {
100 // Extra round trip to get executable name from core file.
101 // This is sometimes not the full name, so it can't be used
102 // as the generic solution.
104 // Quoting core name below fails in gdb 6.8-debian.
105 m_engine->postCommand("target core " + m_coreName,
106 CB(handleTemporaryTargetCore));
108 QString msg = tr("The name of the binary file cannot be extracted "
109 "from this core file.");
111 msg += tr("Try to specify the binary using the "
112 "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
113 showMessageBox(QMessageBox::Warning,
114 tr("Loading core file failed"), msg);
115 m_engine->notifyEngineSetupFailed();
119 void CoreGdbAdapter::handleTemporaryTargetCore(const GdbResponse &response)
121 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
122 if (response.resultClass != GdbResultDone) {
123 showMessage(tr("Attach to core failed."), StatusBar);
124 m_engine->notifyEngineSetupFailed();
128 GdbMi console = response.data.findChild("consolestreamoutput");
129 int pos1 = console.data().indexOf('`');
130 int pos2 = console.data().indexOf('\'');
131 if (pos1 == -1 || pos2 == -1) {
132 showMessage(tr("Attach to core failed."), StatusBar);
133 m_engine->notifyEngineSetupFailed();
137 m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
138 // Strip off command line arguments. FIXME: make robust.
139 int idx = m_executable.indexOf(_c(' '));
141 m_executable.truncate(idx);
142 if (m_executable.isEmpty()) {
143 m_engine->postCommand("detach");
144 m_engine->notifyEngineSetupFailed();
147 m_executable = QFileInfo(startParameters().coreFile).absoluteDir()
148 .absoluteFilePath(m_executable);
149 showMessage(tr("Attached to core temporarily."), StatusBar);
150 m_engine->postCommand("detach", CB(handleTemporaryDetach));
153 void CoreGdbAdapter::handleTemporaryDetach(const GdbResponse &response)
155 QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
156 if (response.resultClass == GdbResultDone) {
157 m_engine->notifyEngineSetupOk();
159 m_engine->notifyEngineSetupFailed();
163 void CoreGdbAdapter::setupInferior()
165 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
166 // Do that first, otherwise no symbols are loaded.
167 QFileInfo fi(m_executable);
168 QByteArray path = fi.absoluteFilePath().toLocal8Bit();
169 m_engine->postCommand("-file-exec-and-symbols \"" + path + '"',
170 CB(handleFileExecAndSymbols));
173 void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
175 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
176 if (response.resultClass == GdbResultDone) {
177 showMessage(tr("Symbols found."), StatusBar);
178 m_engine->postCommand("target core " + m_coreName,
179 CB(handleTargetCore));
182 QString msg = tr("No symbols found in core file <i>%1</i>.")
183 .arg(startParameters().coreFile);
185 msg += tr("This can be caused by a path length limitation in the "
188 msg += tr("Try to specify the binary using the "
189 "<i>Debug->Start Debugging->Attach to Core</i> dialog.");
190 m_engine->notifyInferiorSetupFailed(msg);
193 void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
195 QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
196 if (response.resultClass == GdbResultDone) {
197 // HACK: The namespace is not accessible in the initial run.
198 m_engine->loadPythonDumpers();
199 showMessage(tr("Attached to core."), StatusBar);
200 m_engine->handleInferiorPrepared();
201 // Due to the auto-solib-add off setting, we don't have any
202 // symbols yet. Load them in order of importance.
203 m_engine->reloadStack(true);
204 m_engine->postCommand("info shared", CB(handleModulesList));
207 QString msg = tr("Attach to core \"%1\" failed:\n")
208 .arg(startParameters().coreFile)
209 + QString::fromLocal8Bit(response.data.findChild("msg").data());
210 m_engine->notifyInferiorSetupFailed(msg);
213 void CoreGdbAdapter::handleModulesList(const GdbResponse &response)
215 m_engine->handleModulesList(response);
216 loadSymbolsForStack();
219 void CoreGdbAdapter::loadSymbolsForStack()
221 m_engine->loadSymbolsForStack();
222 QTimer::singleShot(1000, this, SLOT(loadAllSymbols()));
225 void CoreGdbAdapter::loadAllSymbols()
227 m_engine->loadAllSymbols();
230 void CoreGdbAdapter::runEngine()
232 QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
233 m_engine->notifyInferiorUnrunnable();
234 m_engine->updateAll();
237 void CoreGdbAdapter::interruptInferior()
239 // A core never runs, so this cannot be called.
240 QTC_ASSERT(false, /**/);
243 void CoreGdbAdapter::shutdownInferior()
245 m_engine->notifyInferiorShutdownOk();
248 void CoreGdbAdapter::shutdownAdapter()
250 m_engine->notifyAdapterShutdownOk();
253 } // namespace Internal
254 } // namespace Debugger