OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / gdb / coregdbadapter.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "coregdbadapter.h"
34
35 #include "debuggerstartparameters.h"
36 #include "debuggercore.h"
37 #include "debuggeractions.h"
38 #include "debuggerstringutils.h"
39 #include "gdbmi.h"
40 #include "gdbengine.h"
41
42 #include <utils/qtcassert.h>
43
44 #include <QtCore/QDir>
45 #include <QtCore/QFileInfo>
46 #include <QtGui/QMessageBox>
47
48 namespace Debugger {
49 namespace Internal {
50
51 #define CB(callback) \
52     static_cast<GdbEngine::AdapterCallback>(&CoreGdbAdapter::callback), \
53     STRINGIFY(callback)
54
55 ///////////////////////////////////////////////////////////////////////
56 //
57 // CoreGdbAdapter
58 //
59 ///////////////////////////////////////////////////////////////////////
60
61 static QByteArray coreName(const DebuggerStartParameters &sp)
62 {
63     QFileInfo fi(sp.coreFile);
64     return fi.absoluteFilePath().toLocal8Bit();
65 }
66
67 CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
68   : AbstractGdbAdapter(engine, parent),
69     m_executable(startParameters().executable),
70     m_coreName(coreName(startParameters()))
71 {}
72
73 void CoreGdbAdapter::startAdapter()
74 {
75     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
76     showMessage(_("TRYING TO START ADAPTER"));
77
78     QStringList args;
79     args.append(_("-ex"));
80     args.append(_("set auto-solib-add off"));
81     if (!m_engine->startGdb(args, QString()))
82         return;
83
84     //if (m_executable.isEmpty()) {
85     //    showMessageBox(QMessageBox::Warning,
86     //        tr("Error Loading Symbols"),
87     //        tr("No executable to load symbols from specified."));
88     //}
89
90 #ifdef Q_OS_LINUX
91     const bool canUseExeFromCore = true;
92 #else
93     const bool canUseExeFromCore = false;
94 #endif
95
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.
102
103         // Quoting core name below fails in gdb 6.8-debian.
104         m_engine->postCommand("target core " + m_coreName,
105             CB(handleTemporaryTargetCore));
106     } else {
107         QString msg = tr("The name of the binary file cannot be extracted "
108             "from this core file.");
109         msg += _(" ");
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();
115     }
116 }
117
118 void CoreGdbAdapter::handleTemporaryTargetCore(const GdbResponse &response)
119 {
120     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
121     if (response.resultClass != GdbResultDone) {
122         showMessage(tr("Attach to core failed."), StatusBar);
123         m_engine->notifyEngineSetupFailed();
124         return;
125     }
126
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();
133         return;
134     }
135
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(' '));
139     if (idx >= 0)
140         m_executable.truncate(idx);
141     if (m_executable.isEmpty()) {
142         m_engine->postCommand("detach");
143         m_engine->notifyEngineSetupFailed();
144         return;
145     }
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));
150 }
151
152 void CoreGdbAdapter::handleTemporaryDetach(const GdbResponse &response)
153 {
154     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
155     if (response.resultClass == GdbResultDone) {
156         m_engine->notifyEngineSetupOk();
157     } else {
158         m_engine->notifyEngineSetupFailed();
159     }
160 }
161
162 void CoreGdbAdapter::setupInferior()
163 {
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));
170 }
171
172 void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
173 {
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));
179         return;
180     }
181     QString msg = tr("No symbols found in core file <i>%1</i>.")
182         .arg(startParameters().coreFile);
183     msg += _(" ");
184     msg += tr("This can be caused by a path length limitation in the "
185         "core file.");
186     msg += _(" ");
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);
190 }
191
192 void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
193 {
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));
204         return;
205     }
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);
210 }
211
212 void CoreGdbAdapter::handleModulesList(const GdbResponse &response)
213 {
214     m_engine->handleModulesList(response);
215     loadSymbolsForStack();
216 }
217
218 void CoreGdbAdapter::loadSymbolsForStack()
219 {
220     m_engine->loadSymbolsForStack();
221     QTimer::singleShot(1000, this, SLOT(loadAllSymbols()));
222 }
223
224 void CoreGdbAdapter::loadAllSymbols()
225 {
226     m_engine->loadAllSymbols();
227 }
228
229 void CoreGdbAdapter::runEngine()
230 {
231     QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
232     m_engine->notifyInferiorUnrunnable();
233     m_engine->updateAll();
234 }
235
236 void CoreGdbAdapter::interruptInferior()
237 {
238     // A core never runs, so this cannot be called.
239     QTC_ASSERT(false, /**/);
240 }
241
242 void CoreGdbAdapter::shutdownInferior()
243 {
244     m_engine->notifyInferiorShutdownOk();
245 }
246
247 void CoreGdbAdapter::shutdownAdapter()
248 {
249     m_engine->notifyAdapterShutdownOk();
250 }
251
252 } // namespace Internal
253 } // namespace Debugger