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