fastmodel: Use a shared pointer to track PC events.
[gem5.git] / src / base / remote_gdb.hh
1 /*
2 * Copyright (c) 2018 ARM Limited
3 *
4 * The license below extends only to copyright in the software and shall
5 * not be construed as granting a license to any other intellectual
6 * property including but not limited to intellectual property relating
7 * to a hardware implementation of the functionality of the software
8 * licensed hereunder. You may use the software subject to the license
9 * terms below provided that you ensure that this notice is replicated
10 * unmodified and in its entirety in all distributions of the software,
11 * modified or unmodified, in source code or in binary form.
12 *
13 * Copyright 2015 LabWare
14 * Copyright 2014 Google, Inc.
15 * Copyright (c) 2002-2005 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #ifndef __REMOTE_GDB_HH__
43 #define __REMOTE_GDB_HH__
44
45 #include <sys/signal.h>
46
47 #include <exception>
48 #include <map>
49 #include <string>
50
51 #include "arch/types.hh"
52 #include "base/intmath.hh"
53 #include "base/pollevent.hh"
54 #include "base/socket.hh"
55 #include "cpu/pc_event.hh"
56
57 class System;
58 class ThreadContext;
59
60 class BaseRemoteGDB;
61 class HardBreakpoint;
62
63 /**
64 * Concrete subclasses of this abstract class represent how the
65 * register values are transmitted on the wire. Usually each
66 * architecture should define one subclass, but there can be more
67 * if there is more than one possible wire format. For example,
68 * ARM defines both AArch32GdbRegCache and AArch64GdbRegCache.
69 */
70 class BaseGdbRegCache
71 {
72 public:
73
74 /**
75 * Return the pointer to the raw bytes buffer containing the
76 * register values. Each byte of this buffer is literally
77 * encoded as two hex digits in the g or G RSP packet.
78 */
79 virtual char *data() const = 0;
80
81 /**
82 * Return the size of the raw buffer, in bytes
83 * (i.e., half of the number of digits in the g/G packet).
84 */
85 virtual size_t size() const = 0;
86
87 /**
88 * Fill the raw buffer from the registers in the ThreadContext.
89 */
90 virtual void getRegs(ThreadContext*) = 0;
91
92 /**
93 * Set the ThreadContext's registers from the values
94 * in the raw buffer.
95 */
96 virtual void setRegs(ThreadContext*) const = 0;
97
98 /**
99 * Return the name to use in places like DPRINTF.
100 * Having each concrete superclass redefine this member
101 * is useful in situations where the class of the regCache
102 * can change on the fly.
103 */
104 virtual const std::string name() const = 0;
105
106 BaseGdbRegCache(BaseRemoteGDB *g) : gdb(g)
107 {}
108 virtual ~BaseGdbRegCache()
109 {}
110
111 protected:
112 BaseRemoteGDB *gdb;
113 };
114
115 class BaseRemoteGDB
116 {
117 friend class HardBreakpoint;
118 public:
119
120 /*
121 * Interface to other parts of the simulator.
122 */
123 BaseRemoteGDB(System *system, ThreadContext *context, int _port);
124 virtual ~BaseRemoteGDB();
125
126 std::string name();
127
128 void listen();
129 void connect();
130
131 int port() const;
132
133 void attach(int fd);
134 void detach();
135 bool isAttached() { return attached; }
136
137 void replaceThreadContext(ThreadContext *_tc) { tc = _tc; }
138
139 bool trap(int type);
140 bool breakpoint() { return trap(SIGTRAP); }
141
142 private:
143 /*
144 * Connection to the external GDB.
145 */
146 void incomingData(int revent);
147 void connectWrapper(int revent) { connect(); }
148
149 template <void (BaseRemoteGDB::*F)(int revent)>
150 class SocketEvent : public PollEvent
151 {
152 protected:
153 BaseRemoteGDB *gdb;
154
155 public:
156 SocketEvent(BaseRemoteGDB *gdb, int fd, int e) :
157 PollEvent(fd, e), gdb(gdb)
158 {}
159
160 void process(int revent) { (gdb->*F)(revent); }
161 };
162
163 typedef SocketEvent<&BaseRemoteGDB::connectWrapper> ConnectEvent;
164 typedef SocketEvent<&BaseRemoteGDB::incomingData> DataEvent;
165
166 friend ConnectEvent;
167 friend DataEvent;
168
169 ConnectEvent *connectEvent;
170 DataEvent *dataEvent;
171
172 ListenSocket listener;
173 int _port;
174
175 // The socket commands come in through.
176 int fd;
177
178 // Transfer data to/from GDB.
179 uint8_t getbyte();
180 void putbyte(uint8_t b);
181
182 void recv(std::vector<char> &bp);
183 void send(const char *data);
184
185 /*
186 * Simulator side debugger state.
187 */
188 bool active;
189 bool attached;
190
191 System *sys;
192 ThreadContext *tc;
193
194 BaseGdbRegCache *regCachePtr;
195
196 class TrapEvent : public Event
197 {
198 protected:
199 int _type;
200 BaseRemoteGDB *gdb;
201
202 public:
203 TrapEvent(BaseRemoteGDB *g) : gdb(g)
204 {}
205
206 void type(int t) { _type = t; }
207 void process() { gdb->trap(_type); }
208 } trapEvent;
209
210 /*
211 * The interface to the simulated system.
212 */
213 // Machine memory.
214 bool read(Addr addr, size_t size, char *data);
215 bool write(Addr addr, size_t size, const char *data);
216
217 template <class T> T read(Addr addr);
218 template <class T> void write(Addr addr, T data);
219
220 // Single step.
221 void singleStep();
222 EventWrapper<BaseRemoteGDB, &BaseRemoteGDB::singleStep> singleStepEvent;
223
224 void clearSingleStep();
225 void setSingleStep();
226
227 /// Schedule an event which will be triggered "delta" instructions later.
228 void scheduleInstCommitEvent(Event *ev, int delta);
229 /// Deschedule an instruction count based event.
230 void descheduleInstCommitEvent(Event *ev);
231
232 // Breakpoints.
233 void insertSoftBreak(Addr addr, size_t len);
234 void removeSoftBreak(Addr addr, size_t len);
235 void insertHardBreak(Addr addr, size_t len);
236 void removeHardBreak(Addr addr, size_t len);
237
238 void clearTempBreakpoint(Addr &bkpt);
239 void setTempBreakpoint(Addr bkpt);
240
241 /*
242 * GDB commands.
243 */
244 struct GdbCommand
245 {
246 public:
247 struct Context
248 {
249 const GdbCommand *cmd;
250 char cmd_byte;
251 int type;
252 char *data;
253 int len;
254 };
255
256 typedef bool (BaseRemoteGDB::*Func)(Context &ctx);
257
258 const char * const name;
259 const Func func;
260
261 GdbCommand(const char *_name, Func _func) : name(_name), func(_func) {}
262 };
263
264 static std::map<char, GdbCommand> command_map;
265
266 bool cmd_unsupported(GdbCommand::Context &ctx);
267
268 bool cmd_signal(GdbCommand::Context &ctx);
269 bool cmd_cont(GdbCommand::Context &ctx);
270 bool cmd_async_cont(GdbCommand::Context &ctx);
271 bool cmd_detach(GdbCommand::Context &ctx);
272 bool cmd_reg_r(GdbCommand::Context &ctx);
273 bool cmd_reg_w(GdbCommand::Context &ctx);
274 bool cmd_set_thread(GdbCommand::Context &ctx);
275 bool cmd_mem_r(GdbCommand::Context &ctx);
276 bool cmd_mem_w(GdbCommand::Context &ctx);
277 bool cmd_query_var(GdbCommand::Context &ctx);
278 bool cmd_step(GdbCommand::Context &ctx);
279 bool cmd_async_step(GdbCommand::Context &ctx);
280 bool cmd_clr_hw_bkpt(GdbCommand::Context &ctx);
281 bool cmd_set_hw_bkpt(GdbCommand::Context &ctx);
282
283 protected:
284 ThreadContext *context() { return tc; }
285 System *system() { return sys; }
286
287 void encodeBinaryData(const std::string &unencoded,
288 std::string &encoded) const;
289
290 void encodeXferResponse(const std::string &unencoded,
291 std::string &encoded, size_t offset, size_t unencoded_length) const;
292
293 // To be implemented by subclasses.
294 virtual bool checkBpLen(size_t len);
295
296 virtual BaseGdbRegCache *gdbRegs() = 0;
297
298 virtual bool acc(Addr addr, size_t len) = 0;
299
300 virtual std::vector<std::string> availableFeatures() const;
301
302 /**
303 * Get an XML target description.
304 *
305 * @param[in] annex the XML filename
306 * @param[out] output set to the decoded XML
307 * @return true if the given annex was found
308 */
309 virtual bool getXferFeaturesRead(const std::string &annex,
310 std::string &output);
311 };
312
313 template <class T>
314 inline T
315 BaseRemoteGDB::read(Addr addr)
316 {
317 T temp;
318 read(addr, sizeof(T), (char *)&temp);
319 return temp;
320 }
321
322 template <class T>
323 inline void
324 BaseRemoteGDB::write(Addr addr, T data)
325 {
326 write(addr, sizeof(T), (const char *)&data);
327 }
328
329 #endif /* __REMOTE_GDB_H__ */