OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / plugins / debugger / gdb / localplaingdbadapter.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 (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
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
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "localplaingdbadapter.h"
35
36 #include "gdbengine.h"
37 #include "debuggerstartparameters.h"
38 #include "procinterrupt.h"
39 #include "debuggercore.h"
40 #include "debuggerstringutils.h"
41
42 #include <utils/qtcassert.h>
43
44 #include <QtCore/QFileInfo>
45 #include <QtCore/QProcess>
46 #include <QtGui/QMessageBox>
47
48 namespace Debugger {
49 namespace Internal {
50
51 ///////////////////////////////////////////////////////////////////////
52 //
53 // PlainGdbAdapter
54 //
55 ///////////////////////////////////////////////////////////////////////
56
57 LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine, QObject *parent)
58     : AbstractPlainGdbAdapter(engine, parent)
59 {
60     // Output
61     connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
62         engine, SLOT(readDebugeeOutput(QByteArray)));
63 }
64
65 AbstractGdbAdapter::DumperHandling LocalPlainGdbAdapter::dumperHandling() const
66 {
67     // LD_PRELOAD fails for System-Qt on Mac.
68 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
69     return DumperLoadedByGdb;
70 #else
71     return DumperLoadedByGdbPreload;
72 #endif
73 }
74
75 void LocalPlainGdbAdapter::startAdapter()
76 {
77     QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
78     showMessage(_("TRYING TO START ADAPTER"));
79
80 #ifdef Q_OS_WIN
81     if (!prepareWinCommand())
82         return;
83 #endif
84
85     QStringList gdbArgs;
86
87     if (!m_outputCollector.listen()) {
88         m_engine->handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
89                 .arg(m_outputCollector.errorString()), QString());
90         return;
91     }
92     gdbArgs.append(_("--tty=") + m_outputCollector.serverName());
93
94     if (!startParameters().workingDirectory.isEmpty())
95         m_gdbProc.setWorkingDirectory(startParameters().workingDirectory);
96     if (startParameters().environment.size())
97         m_gdbProc.setEnvironment(startParameters().environment.toStringList());
98
99     if (!m_engine->startGdb(gdbArgs)) {
100         m_outputCollector.shutdown();
101         return;
102     }
103
104     checkForReleaseBuild();
105     m_engine->handleAdapterStarted();
106 }
107
108 void LocalPlainGdbAdapter::setupInferior()
109 {
110     AbstractPlainGdbAdapter::setupInferior();
111 }
112
113 void LocalPlainGdbAdapter::runEngine()
114 {
115     AbstractPlainGdbAdapter::runEngine();
116 }
117
118 void LocalPlainGdbAdapter::shutdownInferior()
119 {
120     m_engine->defaultInferiorShutdown("kill");
121 }
122
123 void LocalPlainGdbAdapter::shutdownAdapter()
124 {
125     showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
126     m_outputCollector.shutdown();
127     m_engine->notifyAdapterShutdownOk();
128 }
129
130 void LocalPlainGdbAdapter::checkForReleaseBuild()
131 {
132     // Quick check for a "release" build
133     QProcess proc;
134     QStringList args;
135     args.append(_("-h"));
136     args.append(_("-j"));
137     args.append(_(".debug_info"));
138     args.append(startParameters().executable);
139     proc.start(_("objdump"), args);
140     proc.closeWriteChannel();
141     if (!proc.waitForStarted()) {
142         showMessage(_("OBJDUMP PROCESS COULD NOT BE STARTED. "
143             "RELEASE BUILD CHECK WILL FAIL"));
144         return;
145     }
146     proc.waitForFinished();
147     QByteArray ba = proc.readAllStandardOutput();
148     // This should yield something like
149     // "debuggertest:     file format elf32-i386\n\n"
150     // "Sections:\nIdx Name          Size      VMA       LMA       File off  Algn\n"
151     // "30 .debug_info   00087d36  00000000  00000000  0006bbd5  2**0\n"
152     // " CONTENTS, READONLY, DEBUGGING"
153     if (ba.contains("Sections:") && !ba.contains(".debug_info")) {
154         showMessageBox(QMessageBox::Information, "Warning",
155            tr("This does not seem to be a \"Debug\" build.\n"
156               "Setting breakpoints by file name and line number may fail."));
157     }
158 }
159
160 void LocalPlainGdbAdapter::interruptInferior()
161 {
162     const qint64 attachedPID = m_engine->inferiorPid();
163     if (attachedPID <= 0) {
164         showMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
165         return;
166     }
167
168     if (interruptProcess(attachedPID)) {
169         showMessage(_("INTERRUPTED %1").arg(attachedPID));
170     } else {
171         showMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
172         m_engine->notifyInferiorStopFailed();
173     }
174 }
175
176 QByteArray LocalPlainGdbAdapter::execFilePath() const
177 {
178     return QFileInfo(startParameters().executable)
179             .absoluteFilePath().toLocal8Bit();
180 }
181
182 bool LocalPlainGdbAdapter::infoTargetNecessary() const
183 {
184 #ifdef Q_OS_LINUX
185     return true;
186 #else
187     return false;
188 #endif
189 }
190
191 QByteArray LocalPlainGdbAdapter::toLocalEncoding(const QString &s) const
192 {
193     return s.toLocal8Bit();
194 }
195
196 QString LocalPlainGdbAdapter::fromLocalEncoding(const QByteArray &b) const
197 {
198     return QString::fromLocal8Bit(b);
199 }
200
201 } // namespace Internal
202 } // namespace Debugger