aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/debugger/gdb/symbian.h
blob: d2ddad89e427523f7e44137d2c8d59bd6ceb6567 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#ifndef SYMBIANUTILS_H
#define SYMBIANUTILS_H

#include <QtCore/QMap>
#include <QtCore/QByteArray>
#include <QtCore/QMetaType>
#include <QtCore/QVector>
#include <QtCore/QPair>

QT_BEGIN_NAMESPACE
class QDebug;
QT_END_NAMESPACE

//#define DEBUG_MEMORY  1
#if DEBUG_MEMORY
#   define MEMORY_DEBUG(s) qDebug() << s
#else
#   define MEMORY_DEBUG(s)
#endif
#define MEMORY_DEBUGX(s) qDebug() << s

namespace Debugger {
namespace Internal {
class RegisterHandler;
class ThreadsHandler;
struct GdbResult {
    QByteArray data;
};

struct MemoryRange
{
    MemoryRange() : from(0), to(0) {}
    MemoryRange(uint f, uint t);
    void operator-=(const MemoryRange &other);
    bool intersects(const MemoryRange &other) const;
    quint64 hash() const { return (quint64(from) << 32) + to; }
    bool operator==(const MemoryRange &other) const { return hash() == other.hash(); }
    bool operator<(const MemoryRange &other) const { return hash() < other.hash(); }
    uint size() const { return to - from; }

    uint from; // Inclusive.
    uint to;   // Exclusive.
};

QDebug operator<<(QDebug d, const MemoryRange &range);

// Signals to be passed to gdb server as stop reason (2 digit hex)
enum GdbServerStopReason {
    gdbServerSignalTrap = 5,     // Trap/Breakpoint, etc.
    gdbServerSignalSegfault = 11 // Segfault
};

namespace Symbian {

enum CodeMode
{
    ArmMode = 0,
    ThumbMode
};

enum TargetConstants
{
    RegisterCount = 17,
    RegisterSP = 13, // Stack Pointer
    RegisterLR = 14, // Return address
    RegisterPC = 15, // Program counter
    RegisterPSGdb = 25, // gdb's view of the world
    RegisterPSTrk = 16, // TRK's view of the world

    MemoryChunkSize = 256
};

enum { KnownRegisters = RegisterPSGdb + 1};

const char *registerName(int i);
QByteArray dumpRegister(uint n, uint value);

inline bool isReadOnly(const MemoryRange &mr)
{
    return  mr.from >= 0x70000000 && mr.to < 0x80000000;
}

// Snapshot thread with cached registers
struct Thread {
    explicit Thread(unsigned id = 0);

    void resetRegisters();
    // Gdb helpers for reporting values
    QByteArray gdbReportRegisters() const;
    QByteArray registerContentsLogMessage() const;
    QByteArray gdbRegisterLogMessage(bool verbose) const;
    QByteArray gdbReportSingleRegister(unsigned i) const;
    QByteArray gdbSingleRegisterLogMessage(unsigned i) const;

    uint id;
    uint registers[RegisterCount];
    bool registerValid;
    QString state; // Stop reason, for qsThreadExtraInfo
};

struct Snapshot
{
    Snapshot();

    void reset(); // Leaves read-only memory cache and threads alive.
    void resetMemory(); // Completely clears memory, leaves threads alive.
    void fullReset(); // Clear everything.
    void insertMemory(const MemoryRange &range, const QByteArray &ba);
    QString toString() const;

    // Helpers to format gdb query packets
    QByteArray gdbQsThreadInfo() const;
    QByteArray gdbQThreadExtraInfo(const QByteArray &cmd) const;
    // Format a gdb T05 stop message with thread and register set
    QByteArray gdbStopMessage(uint threadId, int signalNumber, bool reportThreadId) const;
    // Format a log message for memory access with some smartness about registers
    QByteArray memoryReadLogMessage(uint addr, uint threadId, bool verbose, const QByteArray &ba) const;
    // Gdb command parse helpers: 'salnext'
    void parseGdbStepRange(const QByteArray &cmd, bool stepOver);

    void addThread(uint threadId);
    void removeThread(uint threadId);
    int indexOfThread(uint threadId) const;
    // Access registers by thread
    const uint *registers(uint threadId) const;
    uint *registers(uint threadId);
    uint registerValue(uint threadId, uint index);
    void setRegisterValue(uint threadId, uint index, uint value);
    bool registersValid(uint threadId) const;
    void setRegistersValid(uint threadId, bool e);
    void setThreadState(uint threadId, const QString&);

    // Debugger view helpers: Synchronize registers of thread with register handler.
    void syncRegisters(uint threadId, RegisterHandler *handler) const;
    // Debugger view helpers: Synchronize threads with threads handler.
    void syncThreads(ThreadsHandler *handler) const;

    QVector<Thread> threadInfo;

    typedef QMap<MemoryRange, QByteArray> Memory;
    Memory memory;

    // Current state.
    MemoryRange wantedMemory;

    // For next step.
    uint lineFromAddress;
    uint lineToAddress;
    bool stepOver;
};

struct Breakpoint
{
    Breakpoint(uint offset_ = 0)
    {
        number = 0;
        offset = offset_;
        mode = ArmMode;
    }
    uint offset;
    ushort number;
    CodeMode mode;
};

// Gdb helpers
extern const char *gdbQSupported;
extern const char *gdbArchitectureXml;

QVector<QByteArray> gdbStartupSequence();

// Look up in symbol file matching library name in local cache
QString localSymFileForLibrary(const QByteArray &libName,
                               const QString &standardSymDirectory = QString());
// Return a load command for a local symbol file for a library
QByteArray symFileLoadCommand(const QString &symFileName, quint64 code,
                              quint64 data = 0);
// Utility message
QString msgLoadLocalSymFile(const QString &symFileName,
                            const QByteArray &libName, quint64 code);

} // namespace Symbian

// Generic gdb server helpers: read 'm','X' commands.
QPair<quint64, unsigned> parseGdbReadMemoryRequest(const QByteArray &cmd);
// Parse 'register write' ('P') request, return register number/value
QPair<uint, uint> parseGdbWriteRegisterWriteRequest(const QByteArray &cmd);
// Parse 'set breakpoint' ('Z0') request, return address/length
QPair<quint64, unsigned> parseGdbSetBreakpointRequest(const QByteArray &cmd);

} // namespace Internal
} // namespace Debugger

Q_DECLARE_METATYPE(Debugger::Internal::MemoryRange)

#endif // SYMBIANUTILS_H