remote_gdb.cc (12125:0066d9926c1a) remote_gdb.cc (12449:2260f4a68210)
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/*
35 * Copyright (c) 1990, 1993 The Regents of the University of California
36 * All rights reserved
37 *
38 * This software was developed by the Computer Systems Engineering group
39 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40 * contributed to Berkeley.
41 *
42 * All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Lawrence Berkeley Laboratories.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
76 */
77
78/*-
79 * Copyright (c) 2001 The NetBSD Foundation, Inc.
80 * All rights reserved.
81 *
82 * This code is derived from software contributed to The NetBSD Foundation
83 * by Jason R. Thorpe.
84 *
85 * Redistribution and use in source and binary forms, with or without
86 * modification, are permitted provided that the following conditions
87 * are met:
88 * 1. Redistributions of source code must retain the above copyright
89 * notice, this list of conditions and the following disclaimer.
90 * 2. Redistributions in binary form must reproduce the above copyright
91 * notice, this list of conditions and the following disclaimer in the
92 * documentation and/or other materials provided with the distribution.
93 * 3. All advertising materials mentioning features or use of this software
94 * must display the following acknowledgement:
95 * This product includes software developed by the NetBSD
96 * Foundation, Inc. and its contributors.
97 * 4. Neither the name of The NetBSD Foundation nor the names of its
98 * contributors may be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 *
101 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
102 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
103 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
104 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
105 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
106 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
107 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
108 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
109 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
110 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
111 * POSSIBILITY OF SUCH DAMAGE.
112 */
113
114/*
115 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
116 *
117 * Taken from NetBSD
118 *
119 * "Stub" to allow remote cpu to debug over a serial line using gdb.
120 */
121
122#include "base/remote_gdb.hh"
123
124#include <sys/signal.h>
125#include <unistd.h>
126
127#include <csignal>
128#include <cstdint>
129#include <cstdio>
130#include <string>
131
132#include "arch/vtophys.hh"
133#include "base/intmath.hh"
134#include "base/socket.hh"
135#include "base/trace.hh"
136#include "config/the_isa.hh"
137#include "cpu/base.hh"
138#include "cpu/static_inst.hh"
139#include "cpu/thread_context.hh"
140#include "debug/GDBAll.hh"
141#include "mem/fs_translating_port_proxy.hh"
142#include "mem/port.hh"
143#include "mem/se_translating_port_proxy.hh"
144#include "sim/full_system.hh"
145#include "sim/system.hh"
146
147using namespace std;
148using namespace TheISA;
149
150static const char GDBStart = '$';
151static const char GDBEnd = '#';
152static const char GDBGoodP = '+';
153static const char GDBBadP = '-';
154
155static const int GDBPacketBufLen = 1024;
156
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/*
35 * Copyright (c) 1990, 1993 The Regents of the University of California
36 * All rights reserved
37 *
38 * This software was developed by the Computer Systems Engineering group
39 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40 * contributed to Berkeley.
41 *
42 * All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Lawrence Berkeley Laboratories.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by the University of
58 * California, Berkeley and its contributors.
59 * 4. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
76 */
77
78/*-
79 * Copyright (c) 2001 The NetBSD Foundation, Inc.
80 * All rights reserved.
81 *
82 * This code is derived from software contributed to The NetBSD Foundation
83 * by Jason R. Thorpe.
84 *
85 * Redistribution and use in source and binary forms, with or without
86 * modification, are permitted provided that the following conditions
87 * are met:
88 * 1. Redistributions of source code must retain the above copyright
89 * notice, this list of conditions and the following disclaimer.
90 * 2. Redistributions in binary form must reproduce the above copyright
91 * notice, this list of conditions and the following disclaimer in the
92 * documentation and/or other materials provided with the distribution.
93 * 3. All advertising materials mentioning features or use of this software
94 * must display the following acknowledgement:
95 * This product includes software developed by the NetBSD
96 * Foundation, Inc. and its contributors.
97 * 4. Neither the name of The NetBSD Foundation nor the names of its
98 * contributors may be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 *
101 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
102 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
103 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
104 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
105 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
106 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
107 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
108 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
109 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
110 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
111 * POSSIBILITY OF SUCH DAMAGE.
112 */
113
114/*
115 * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
116 *
117 * Taken from NetBSD
118 *
119 * "Stub" to allow remote cpu to debug over a serial line using gdb.
120 */
121
122#include "base/remote_gdb.hh"
123
124#include <sys/signal.h>
125#include <unistd.h>
126
127#include <csignal>
128#include <cstdint>
129#include <cstdio>
130#include <string>
131
132#include "arch/vtophys.hh"
133#include "base/intmath.hh"
134#include "base/socket.hh"
135#include "base/trace.hh"
136#include "config/the_isa.hh"
137#include "cpu/base.hh"
138#include "cpu/static_inst.hh"
139#include "cpu/thread_context.hh"
140#include "debug/GDBAll.hh"
141#include "mem/fs_translating_port_proxy.hh"
142#include "mem/port.hh"
143#include "mem/se_translating_port_proxy.hh"
144#include "sim/full_system.hh"
145#include "sim/system.hh"
146
147using namespace std;
148using namespace TheISA;
149
150static const char GDBStart = '$';
151static const char GDBEnd = '#';
152static const char GDBGoodP = '+';
153static const char GDBBadP = '-';
154
155static const int GDBPacketBufLen = 1024;
156
157#ifndef NDEBUG
158vector<BaseRemoteGDB *> debuggers;
159
157vector<BaseRemoteGDB *> debuggers;
158
160void
161debugger()
159class HardBreakpoint : public PCEvent
162{
160{
163 static int current_debugger = -1;
164 if (current_debugger >= 0 && current_debugger < (int)debuggers.size()) {
165 BaseRemoteGDB *gdb = debuggers[current_debugger];
166 if (!gdb->isattached())
167 gdb->listener->accept();
168 if (gdb->isattached())
169 gdb->trap(SIGILL);
161 private:
162 BaseRemoteGDB *gdb;
163
164 public:
165 int refcount;
166
167 public:
168 HardBreakpoint(BaseRemoteGDB *_gdb, PCEventQueue *q, Addr pc)
169 : PCEvent(q, "HardBreakpoint Event", pc),
170 gdb(_gdb), refcount(0)
171 {
172 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
170 }
173 }
171}
172#endif
173
174
174///////////////////////////////////////////////////////////
175//
176//
177//
175 const std::string name() const { return gdb->name() + ".hwbkpt"; }
178
176
179GDBListener::InputEvent::InputEvent(GDBListener *l, int fd, int e)
180 : PollEvent(fd, e), listener(l)
181{}
177 void
178 process(ThreadContext *tc) override
179 {
180 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
182
181
183void
184GDBListener::InputEvent::process(int revent)
182 if (tc == gdb->tc)
183 gdb->trap(SIGTRAP);
184 }
185};
186
187namespace {
188
189// Exception to throw when the connection to the client is broken.
190struct BadClient
185{
191{
186 listener->accept();
187}
192 const char *warning;
193 BadClient(const char *_warning=NULL) : warning(_warning)
194 {}
195};
188
196
189GDBListener::GDBListener(BaseRemoteGDB *g, int p)
190 : inputEvent(NULL), gdb(g), port(p)
197// Exception to throw when an error needs to be reported to the client.
198struct CmdError
191{
199{
192 assert(!gdb->listener);
193 gdb->listener = this;
194}
200 string error;
201 CmdError(std::string _error) : error(_error)
202 {}
203};
195
204
196GDBListener::~GDBListener()
205// Exception to throw when something isn't supported.
206class Unsupported {};
207
208// Convert a hex digit into an integer.
209// This returns -1 if the argument passed is no valid hex digit.
210int
211digit2i(char c)
197{
212{
198 delete inputEvent;
213 if (c >= '0' && c <= '9')
214 return (c - '0');
215 else if (c >= 'a' && c <= 'f')
216 return (c - 'a' + 10);
217 else if (c >= 'A' && c <= 'F')
218 return (c - 'A' + 10);
219 else
220 return (-1);
199}
200
221}
222
201string
202GDBListener::name()
223// Convert the low 4 bits of an integer into an hex digit.
224char
225i2digit(int n)
203{
226{
204 return gdb->name() + ".listener";
227 return ("0123456789abcdef"[n & 0x0f]);
205}
206
228}
229
230// Convert a byte array into an hex string.
207void
231void
208GDBListener::listen()
232mem2hex(char *vdst, const char *vsrc, int len)
209{
233{
210 if (ListenSocket::allDisabled()) {
211 warn_once("Sockets disabled, not accepting gdb connections");
212 return;
213 }
234 char *dst = vdst;
235 const char *src = vsrc;
214
236
215 while (!listener.listen(port, true)) {
216 DPRINTF(GDBMisc, "Can't bind port %d\n", port);
217 port++;
237 while (len--) {
238 *dst++ = i2digit(*src >> 4);
239 *dst++ = i2digit(*src++);
218 }
240 }
219
220 inputEvent = new InputEvent(this, listener.getfd(), POLLIN);
221 pollQueue.schedule(inputEvent);
222
223#ifndef NDEBUG
224 gdb->number = debuggers.size();
225 debuggers.push_back(gdb);
226#endif
227
228#ifndef NDEBUG
229 ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
230 curTick(), name(), gdb->number, port);
231#else
232 ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
233 curTick(), name(), port);
234#endif
241 *dst = '\0';
235}
236
242}
243
237void
238GDBListener::accept()
244// Convert an hex string into a byte array.
245// This returns a pointer to the character following the last valid
246// hex digit. If the string ends in the middle of a byte, NULL is
247// returned.
248const char *
249hex2mem(char *vdst, const char *src, int maxlen)
239{
250{
240 if (!listener.islistening())
241 panic("GDBListener::accept(): cannot accept if we're not listening!");
251 char *dst = vdst;
252 int msb, lsb;
242
253
243 int sfd = listener.accept(true);
244
245 if (sfd != -1) {
246 if (gdb->isattached())
247 close(sfd);
248 else
249 gdb->attach(sfd);
254 while (*src && maxlen--) {
255 msb = digit2i(*src++);
256 if (msb < 0)
257 return (src - 1);
258 lsb = digit2i(*src++);
259 if (lsb < 0)
260 return (NULL);
261 *dst++ = (msb << 4) | lsb;
250 }
262 }
263 return src;
251}
252
264}
265
253int
254GDBListener::getPort() const
266// Convert an hex string into an integer.
267// This returns a pointer to the character following the last valid
268// hex digit.
269Addr
270hex2i(const char **srcp)
255{
271{
256 panic_if(!listener.islistening(),
257 "Remote GDB port is unknown until GDBListener::listen() has "
258 "been called.\n");
272 const char *src = *srcp;
273 Addr r = 0;
274 int nibble;
259
275
260 return port;
276 while ((nibble = digit2i(*src)) >= 0) {
277 r *= 16;
278 r += nibble;
279 src++;
280 }
281 *srcp = src;
282 return r;
261}
262
283}
284
263BaseRemoteGDB::InputEvent::InputEvent(BaseRemoteGDB *g, int fd, int e)
264 : PollEvent(fd, e), gdb(g)
265{}
285enum GdbBreakpointType {
286 GdbSoftBp = '0',
287 GdbHardBp = '1',
288 GdbWriteWp = '2',
289 GdbReadWp = '3',
290 GdbAccWp = '4',
291};
266
292
267void
268BaseRemoteGDB::InputEvent::process(int revent)
293const char *
294break_type(char c)
269{
295{
270 if (gdb->trapEvent.scheduled()) {
271 warn("GDB trap event has already been scheduled! "
272 "Ignoring this input event.");
273 return;
296 switch(c) {
297 case GdbSoftBp: return "software breakpoint";
298 case GdbHardBp: return "hardware breakpoint";
299 case GdbWriteWp: return "write watchpoint";
300 case GdbReadWp: return "read watchpoint";
301 case GdbAccWp: return "access watchpoint";
302 default: return "unknown breakpoint/watchpoint";
274 }
303 }
275
276 if (revent & POLLIN) {
277 gdb->trapEvent.type(SIGILL);
278 gdb->scheduleInstCommitEvent(&gdb->trapEvent, 0);
279 } else if (revent & POLLNVAL) {
280 gdb->descheduleInstCommitEvent(&gdb->trapEvent);
281 gdb->detach();
282 }
283}
284
304}
305
285void
286BaseRemoteGDB::TrapEvent::process()
306std::map<Addr, HardBreakpoint *> hardBreakMap;
307
308EventQueue *
309getComInstEventQueue(ThreadContext *tc)
287{
310{
288 gdb->trap(_type);
311 return tc->getCpuPtr()->comInstEventQueue[tc->threadId()];
289}
290
312}
313
291void
292BaseRemoteGDB::processSingleStepEvent()
293{
294 if (!singleStepEvent.scheduled())
295 scheduleInstCommitEvent(&singleStepEvent, 1);
296 trap(SIGTRAP);
297}
298
314}
315
299BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c) :
300 inputEvent(NULL), trapEvent(this), listener(NULL), number(-1),
301 fd(-1), active(false), attached(false), system(_system),
302 context(c),
303 singleStepEvent([this]{ processSingleStepEvent(); }, name())
316BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c, int _port) :
317 connectEvent(nullptr), dataEvent(nullptr), _port(_port), fd(-1),
318 active(false), attached(false), sys(_system), tc(c),
319 trapEvent(this), singleStepEvent(*this)
304{
320{
321 debuggers.push_back(this);
305}
306
307BaseRemoteGDB::~BaseRemoteGDB()
308{
322}
323
324BaseRemoteGDB::~BaseRemoteGDB()
325{
309 if (inputEvent)
310 delete inputEvent;
326 delete connectEvent;
327 delete dataEvent;
311}
312
313string
314BaseRemoteGDB::name()
315{
328}
329
330string
331BaseRemoteGDB::name()
332{
316 return system->name() + ".remote_gdb";
333 return sys->name() + ".remote_gdb";
317}
318
334}
335
319bool
320BaseRemoteGDB::isattached()
321{ return attached; }
336void
337BaseRemoteGDB::listen()
338{
339 if (ListenSocket::allDisabled()) {
340 warn_once("Sockets disabled, not accepting gdb connections");
341 return;
342 }
322
343
344 while (!listener.listen(_port, true)) {
345 DPRINTF(GDBMisc, "Can't bind port %d\n", _port);
346 _port++;
347 }
348
349 connectEvent = new ConnectEvent(this, listener.getfd(), POLLIN);
350 pollQueue.schedule(connectEvent);
351
352 ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
353 curTick(), name(), _port);
354}
355
323void
356void
357BaseRemoteGDB::connect()
358{
359 panic_if(!listener.islistening(),
360 "Cannot accept GDB connections if we're not listening!");
361
362 int sfd = listener.accept(true);
363
364 if (sfd != -1) {
365 if (isAttached())
366 close(sfd);
367 else
368 attach(sfd);
369 }
370}
371
372int
373BaseRemoteGDB::port() const
374{
375 panic_if(!listener.islistening(),
376 "Remote GDB port is unknown until listen() has been called.\n");
377 return _port;
378}
379
380void
324BaseRemoteGDB::attach(int f)
325{
326 fd = f;
327
381BaseRemoteGDB::attach(int f)
382{
383 fd = f;
384
328 inputEvent = new InputEvent(this, fd, POLLIN);
329 pollQueue.schedule(inputEvent);
385 dataEvent = new DataEvent(this, fd, POLLIN);
386 pollQueue.schedule(dataEvent);
330
331 attached = true;
332 DPRINTFN("remote gdb attached\n");
333}
334
335void
336BaseRemoteGDB::detach()
337{
338 attached = false;
339 active = false;
340 clearSingleStep();
341 close(fd);
342 fd = -1;
343
387
388 attached = true;
389 DPRINTFN("remote gdb attached\n");
390}
391
392void
393BaseRemoteGDB::detach()
394{
395 attached = false;
396 active = false;
397 clearSingleStep();
398 close(fd);
399 fd = -1;
400
344 pollQueue.remove(inputEvent);
401 pollQueue.remove(dataEvent);
345 DPRINTFN("remote gdb detached\n");
346}
347
402 DPRINTFN("remote gdb detached\n");
403}
404
348/////////////////////////
349//
350//
405// This function does all command processing for interfacing to a
406// remote gdb. Note that the error codes are ignored by gdb at
407// present, but might eventually become meaningful. (XXX) It might
408// makes sense to use POSIX errno values, because that is what the
409// gdb/remote.c functions want to return.
410bool
411BaseRemoteGDB::trap(int type)
412{
351
413
414 if (!attached)
415 return false;
416
417 DPRINTF(GDBMisc, "trap: PC=%s\n", tc->pcState());
418
419 clearSingleStep();
420
421 /*
422 * The first entry to this function is normally through
423 * a breakpoint trap in kgdb_connect(), in which case we
424 * must advance past the breakpoint because gdb will not.
425 *
426 * On the first entry here, we expect that gdb is not yet
427 * listening to us, so just enter the interaction loop.
428 * After the debugger is "active" (connected) it will be
429 * waiting for a "signaled" message from us.
430 */
431 if (!active) {
432 active = true;
433 } else {
434 // Tell remote host that an exception has occurred.
435 send(csprintf("S%02x", type).c_str());
436 }
437
438 // Stick frame regs into our reg cache.
439 regCachePtr = gdbRegs();
440 regCachePtr->getRegs(tc);
441
442 char data[GDBPacketBufLen + 1];
443 GdbCommand::Context cmdCtx;
444 cmdCtx.type = type;
445 cmdCtx.data = &data[1];
446
447 for (;;) {
448 try {
449 size_t datalen = recv(data, sizeof(data));
450 if (datalen < 1)
451 throw BadClient();
452
453 data[datalen] = 0; // Sentinel
454 cmdCtx.cmd_byte = data[0];
455 cmdCtx.len = datalen - 1;
456
457 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
458 if (cmdIt == command_map.end()) {
459 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
460 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
461 throw Unsupported();
462 }
463 cmdCtx.cmd = &(cmdIt->second);
464
465 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
466 break;
467
468 } catch (BadClient &e) {
469 if (e.warning)
470 warn(e.warning);
471 detach();
472 break;
473 } catch (Unsupported &e) {
474 send("");
475 } catch (CmdError &e) {
476 send(e.error.c_str());
477 } catch (...) {
478 panic("Unrecognzied GDB exception.");
479 }
480 }
481
482 return true;
483}
484
485void
486BaseRemoteGDB::incomingData(int revent)
487{
488 if (trapEvent.scheduled()) {
489 warn("GDB trap event has already been scheduled!");
490 return;
491 }
492
493 if (revent & POLLIN) {
494 trapEvent.type(SIGILL);
495 scheduleInstCommitEvent(&trapEvent, 0);
496 } else if (revent & POLLNVAL) {
497 descheduleInstCommitEvent(&trapEvent);
498 detach();
499 }
500}
501
352uint8_t
353BaseRemoteGDB::getbyte()
354{
355 uint8_t b;
356 if (::read(fd, &b, sizeof(b)) == sizeof(b))
357 return b;
358
359 throw BadClient("Couldn't read data from debugger.");
360}
361
362void
363BaseRemoteGDB::putbyte(uint8_t b)
364{
365 if (::write(fd, &b, sizeof(b)) == sizeof(b))
366 return;
367
368 throw BadClient("Couldn't write data to the debugger.");
369}
370
502uint8_t
503BaseRemoteGDB::getbyte()
504{
505 uint8_t b;
506 if (::read(fd, &b, sizeof(b)) == sizeof(b))
507 return b;
508
509 throw BadClient("Couldn't read data from debugger.");
510}
511
512void
513BaseRemoteGDB::putbyte(uint8_t b)
514{
515 if (::write(fd, &b, sizeof(b)) == sizeof(b))
516 return;
517
518 throw BadClient("Couldn't write data to the debugger.");
519}
520
371// Send a packet to gdb
372void
373BaseRemoteGDB::send(const char *bp)
374{
375 const char *p;
376 uint8_t csum, c;
377
378 DPRINTF(GDBSend, "send: %s\n", bp);
379
380 do {
381 p = bp;
382 // Start sending a packet
383 putbyte(GDBStart);
384 // Send the contents, and also keep a check sum.
385 for (csum = 0; (c = *p); p++) {
386 putbyte(c);
387 csum += c;
388 }
389 // Send the ending character.
390 putbyte(GDBEnd);
391 // Send the checksum.
392 putbyte(i2digit(csum >> 4));
393 putbyte(i2digit(csum));
394 // Try transmitting over and over again until the other end doesn't
395 // send an error back.
396 c = getbyte();
397 } while ((c & 0x7f) == GDBBadP);
398}
399
400// Receive a packet from gdb
401int
402BaseRemoteGDB::recv(char *bp, int maxlen)
403{
404 char *p;
405 uint8_t c;
406 int csum;
407 int len;
408
409 do {
410 p = bp;
411 csum = len = 0;
412 // Find the beginning of a packet
413 while ((c = getbyte()) != GDBStart);
414
415 // Read until you find the end of the data in the packet, and keep
416 // track of the check sum.
417 while (len < maxlen) {
418 c = getbyte();
419 if (c == GDBEnd)
420 break;
421 c &= 0x7f;
422 csum += c;
423 *p++ = c;
424 len++;
425 }
426
427 // Mask the check sum, and terminate the command string.
428 csum &= 0xff;
429 *p = '\0';
430
431 // If the command was too long, report an error.
432 if (len >= maxlen) {
433 putbyte(GDBBadP);
434 continue;
435 }
436
437 // Bring in the checksum. If the check sum matches, csum will be 0.
438 csum -= digit2i(getbyte()) * 16;
439 csum -= digit2i(getbyte());
440
441 // If the check sum was correct
442 if (csum == 0) {
443 // Report that the packet was received correctly
444 putbyte(GDBGoodP);
445 // Sequence present?
446 if (bp[2] == ':') {
447 putbyte(bp[0]);
448 putbyte(bp[1]);
449 len -= 3;
450 memcpy(bp, bp+3, len);
451 }
452 break;
453 }
454 // Otherwise, report that there was a mistake.
455 putbyte(GDBBadP);
456 } while (1);
457
458 DPRINTF(GDBRecv, "recv: %s\n", bp);
459
460 return len;
461}
462
521// Receive a packet from gdb
522int
523BaseRemoteGDB::recv(char *bp, int maxlen)
524{
525 char *p;
526 uint8_t c;
527 int csum;
528 int len;
529
530 do {
531 p = bp;
532 csum = len = 0;
533 // Find the beginning of a packet
534 while ((c = getbyte()) != GDBStart);
535
536 // Read until you find the end of the data in the packet, and keep
537 // track of the check sum.
538 while (len < maxlen) {
539 c = getbyte();
540 if (c == GDBEnd)
541 break;
542 c &= 0x7f;
543 csum += c;
544 *p++ = c;
545 len++;
546 }
547
548 // Mask the check sum, and terminate the command string.
549 csum &= 0xff;
550 *p = '\0';
551
552 // If the command was too long, report an error.
553 if (len >= maxlen) {
554 putbyte(GDBBadP);
555 continue;
556 }
557
558 // Bring in the checksum. If the check sum matches, csum will be 0.
559 csum -= digit2i(getbyte()) * 16;
560 csum -= digit2i(getbyte());
561
562 // If the check sum was correct
563 if (csum == 0) {
564 // Report that the packet was received correctly
565 putbyte(GDBGoodP);
566 // Sequence present?
567 if (bp[2] == ':') {
568 putbyte(bp[0]);
569 putbyte(bp[1]);
570 len -= 3;
571 memcpy(bp, bp+3, len);
572 }
573 break;
574 }
575 // Otherwise, report that there was a mistake.
576 putbyte(GDBBadP);
577 } while (1);
578
579 DPRINTF(GDBRecv, "recv: %s\n", bp);
580
581 return len;
582}
583
584// Send a packet to gdb
585void
586BaseRemoteGDB::send(const char *bp)
587{
588 const char *p;
589 uint8_t csum, c;
590
591 DPRINTF(GDBSend, "send: %s\n", bp);
592
593 do {
594 p = bp;
595 // Start sending a packet
596 putbyte(GDBStart);
597 // Send the contents, and also keep a check sum.
598 for (csum = 0; (c = *p); p++) {
599 putbyte(c);
600 csum += c;
601 }
602 // Send the ending character.
603 putbyte(GDBEnd);
604 // Send the checksum.
605 putbyte(i2digit(csum >> 4));
606 putbyte(i2digit(csum));
607 // Try transmitting over and over again until the other end doesn't
608 // send an error back.
609 c = getbyte();
610 } while ((c & 0x7f) == GDBBadP);
611}
612
463// Read bytes from kernel address space for debugger.
464bool
465BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
466{
467 static Addr lastaddr = 0;
468 static size_t lastsize = 0;
469
470 if (vaddr < 10) {
471 DPRINTF(GDBRead, "read: reading memory location zero!\n");
472 vaddr = lastaddr + lastsize;
473 }
474
475 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
476
477 if (FullSystem) {
613// Read bytes from kernel address space for debugger.
614bool
615BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
616{
617 static Addr lastaddr = 0;
618 static size_t lastsize = 0;
619
620 if (vaddr < 10) {
621 DPRINTF(GDBRead, "read: reading memory location zero!\n");
622 vaddr = lastaddr + lastsize;
623 }
624
625 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
626
627 if (FullSystem) {
478 FSTranslatingPortProxy &proxy = context->getVirtProxy();
628 FSTranslatingPortProxy &proxy = tc->getVirtProxy();
479 proxy.readBlob(vaddr, (uint8_t*)data, size);
480 } else {
629 proxy.readBlob(vaddr, (uint8_t*)data, size);
630 } else {
481 SETranslatingPortProxy &proxy = context->getMemProxy();
631 SETranslatingPortProxy &proxy = tc->getMemProxy();
482 proxy.readBlob(vaddr, (uint8_t*)data, size);
483 }
484
485#if TRACING_ON
486 if (DTRACE(GDBRead)) {
487 if (DTRACE(GDBExtra)) {
488 char buf[1024];
489 mem2hex(buf, data, size);
490 DPRINTFNR(": %s\n", buf);
491 } else
492 DPRINTFNR("\n");
493 }
494#endif
495
496 return true;
497}
498
499// Write bytes to kernel address space for debugger.
500bool
501BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
502{
503 static Addr lastaddr = 0;
504 static size_t lastsize = 0;
505
506 if (vaddr < 10) {
507 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
508 vaddr = lastaddr + lastsize;
509 }
510
511 if (DTRACE(GDBWrite)) {
512 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
513 if (DTRACE(GDBExtra)) {
514 char buf[1024];
515 mem2hex(buf, data, size);
516 DPRINTFNR(": %s\n", buf);
517 } else
518 DPRINTFNR("\n");
519 }
520 if (FullSystem) {
632 proxy.readBlob(vaddr, (uint8_t*)data, size);
633 }
634
635#if TRACING_ON
636 if (DTRACE(GDBRead)) {
637 if (DTRACE(GDBExtra)) {
638 char buf[1024];
639 mem2hex(buf, data, size);
640 DPRINTFNR(": %s\n", buf);
641 } else
642 DPRINTFNR("\n");
643 }
644#endif
645
646 return true;
647}
648
649// Write bytes to kernel address space for debugger.
650bool
651BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
652{
653 static Addr lastaddr = 0;
654 static size_t lastsize = 0;
655
656 if (vaddr < 10) {
657 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
658 vaddr = lastaddr + lastsize;
659 }
660
661 if (DTRACE(GDBWrite)) {
662 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
663 if (DTRACE(GDBExtra)) {
664 char buf[1024];
665 mem2hex(buf, data, size);
666 DPRINTFNR(": %s\n", buf);
667 } else
668 DPRINTFNR("\n");
669 }
670 if (FullSystem) {
521 FSTranslatingPortProxy &proxy = context->getVirtProxy();
671 FSTranslatingPortProxy &proxy = tc->getVirtProxy();
522 proxy.writeBlob(vaddr, (uint8_t*)data, size);
523 } else {
672 proxy.writeBlob(vaddr, (uint8_t*)data, size);
673 } else {
524 SETranslatingPortProxy &proxy = context->getMemProxy();
674 SETranslatingPortProxy &proxy = tc->getMemProxy();
525 proxy.writeBlob(vaddr, (uint8_t*)data, size);
526 }
527
528 return true;
529}
530
531void
675 proxy.writeBlob(vaddr, (uint8_t*)data, size);
676 }
677
678 return true;
679}
680
681void
532BaseRemoteGDB::clearSingleStep()
682BaseRemoteGDB::singleStep()
533{
683{
534 descheduleInstCommitEvent(&singleStepEvent);
535}
536
537void
538BaseRemoteGDB::setSingleStep()
539{
540 if (!singleStepEvent.scheduled())
541 scheduleInstCommitEvent(&singleStepEvent, 1);
684 if (!singleStepEvent.scheduled())
685 scheduleInstCommitEvent(&singleStepEvent, 1);
686 trap(SIGTRAP);
542}
543
687}
688
544PCEventQueue *BaseRemoteGDB::getPcEventQueue()
545{
546 return &system->pcEventQueue;
547}
548
549EventQueue *
550BaseRemoteGDB::getComInstEventQueue()
551{
552 BaseCPU *cpu = context->getCpuPtr();
553 return cpu->comInstEventQueue[context->threadId()];
554}
555
556void
689void
557BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
690BaseRemoteGDB::clearSingleStep()
558{
691{
559 EventQueue *eq = getComInstEventQueue();
560 // Here "ticks" aren't simulator ticks which measure time, they're
561 // instructions committed by the CPU.
562 eq->schedule(ev, eq->getCurTick() + delta);
692 descheduleInstCommitEvent(&singleStepEvent);
563}
564
565void
693}
694
695void
566BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
696BaseRemoteGDB::setSingleStep()
567{
697{
568 if (ev->scheduled())
569 getComInstEventQueue()->deschedule(ev);
698 if (!singleStepEvent.scheduled())
699 scheduleInstCommitEvent(&singleStepEvent, 1);
570}
571
700}
701
572bool
573BaseRemoteGDB::checkBpLen(size_t len)
574{
575 return len == sizeof(MachInst);
576}
577
578BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc)
579 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
580 gdb(_gdb), refcount(0)
581{
582 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
583}
584
585void
702void
586BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc)
587{
588 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
589
590 if (tc == gdb->context)
591 gdb->trap(SIGTRAP);
592}
593
594void
595BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
596{
597 if (!checkBpLen(len))
598 throw BadClient("Invalid breakpoint length\n");
599
600 return insertHardBreak(addr, len);
601}
602
603void
604BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
605{
606 if (!checkBpLen(len))
607 throw BadClient("Invalid breakpoint length.\n");
608
609 return removeHardBreak(addr, len);
610}
611
612void
613BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
614{
615 if (!checkBpLen(len))
616 throw BadClient("Invalid breakpoint length\n");
617
618 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
619
620 HardBreakpoint *&bkpt = hardBreakMap[addr];
621 if (bkpt == 0)
703BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
704{
705 if (!checkBpLen(len))
706 throw BadClient("Invalid breakpoint length\n");
707
708 return insertHardBreak(addr, len);
709}
710
711void
712BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
713{
714 if (!checkBpLen(len))
715 throw BadClient("Invalid breakpoint length.\n");
716
717 return removeHardBreak(addr, len);
718}
719
720void
721BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
722{
723 if (!checkBpLen(len))
724 throw BadClient("Invalid breakpoint length\n");
725
726 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
727
728 HardBreakpoint *&bkpt = hardBreakMap[addr];
729 if (bkpt == 0)
622 bkpt = new HardBreakpoint(this, addr);
730 bkpt = new HardBreakpoint(this, &sys->pcEventQueue, addr);
623
624 bkpt->refcount++;
625}
626
627void
628BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
629{
630 if (!checkBpLen(len))
631 throw BadClient("Invalid breakpoint length\n");
632
633 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
634
731
732 bkpt->refcount++;
733}
734
735void
736BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
737{
738 if (!checkBpLen(len))
739 throw BadClient("Invalid breakpoint length\n");
740
741 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
742
635 break_iter_t i = hardBreakMap.find(addr);
743 auto i = hardBreakMap.find(addr);
636 if (i == hardBreakMap.end())
637 throw CmdError("E0C");
638
639 HardBreakpoint *hbp = (*i).second;
640 if (--hbp->refcount == 0) {
641 delete hbp;
642 hardBreakMap.erase(i);
643 }
644}
645
646void
744 if (i == hardBreakMap.end())
745 throw CmdError("E0C");
746
747 HardBreakpoint *hbp = (*i).second;
748 if (--hbp->refcount == 0) {
749 delete hbp;
750 hardBreakMap.erase(i);
751 }
752}
753
754void
755BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
756{
757 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
758 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
759 bkpt = 0;
760}
761
762void
647BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
648{
649 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
650 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
651}
652
653void
763BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
764{
765 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
766 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
767}
768
769void
654BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
770BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
655{
771{
656 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
657 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
658 bkpt = 0;
772 EventQueue *eq = getComInstEventQueue(tc);
773 // Here "ticks" aren't simulator ticks which measure time, they're
774 // instructions committed by the CPU.
775 eq->schedule(ev, eq->getCurTick() + delta);
659}
660
776}
777
661enum GdbBreakpointType {
662 GdbSoftBp = '0',
663 GdbHardBp = '1',
664 GdbWriteWp = '2',
665 GdbReadWp = '3',
666 GdbAccWp = '4',
667};
668
669const char *
670BaseRemoteGDB::break_type(char c)
778void
779BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
671{
780{
672 switch(c) {
673 case GdbSoftBp: return "software breakpoint";
674 case GdbHardBp: return "hardware breakpoint";
675 case GdbWriteWp: return "write watchpoint";
676 case GdbReadWp: return "read watchpoint";
677 case GdbAccWp: return "access watchpoint";
678 default: return "unknown breakpoint/watchpoint";
679 }
781 if (ev->scheduled())
782 getComInstEventQueue(tc)->deschedule(ev);
680}
681
783}
784
682std::map BaseRemoteGDB::command_map = {
785std::map<char, BaseRemoteGDB::GdbCommand> BaseRemoteGDB::command_map = {
683 // last signal
684 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
685 // set baud (deprecated)
686 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
687 // set breakpoint (deprecated)
688 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
689 // resume
690 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
691 // continue with signal
692 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
693 // toggle debug flags (deprecated)
694 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
695 // detach remote gdb
696 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
697 // read general registers
698 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
699 // write general registers
700 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
701 // set thread
702 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
703 // step a single cycle
704 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
705 // signal then cycle step
706 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
707 // kill program
708 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
709 // read memory
710 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
711 // write memory
712 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
713 // read register
714 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
715 // write register
716 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
717 // query variable
718 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
719 // set variable
720 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
721 // reset system (deprecated)
722 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
723 // step
724 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
725 // signal and step
726 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
727 // find out if the thread is alive
728 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
729 // target exited
730 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
731 // write memory
732 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
733 // remove breakpoint or watchpoint
734 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
735 // insert breakpoint or watchpoint
736 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
737};
738
786 // last signal
787 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
788 // set baud (deprecated)
789 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
790 // set breakpoint (deprecated)
791 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
792 // resume
793 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
794 // continue with signal
795 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
796 // toggle debug flags (deprecated)
797 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
798 // detach remote gdb
799 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
800 // read general registers
801 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
802 // write general registers
803 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
804 // set thread
805 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
806 // step a single cycle
807 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
808 // signal then cycle step
809 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
810 // kill program
811 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
812 // read memory
813 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
814 // write memory
815 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
816 // read register
817 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
818 // write register
819 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
820 // query variable
821 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
822 // set variable
823 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
824 // reset system (deprecated)
825 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
826 // step
827 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
828 // signal and step
829 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
830 // find out if the thread is alive
831 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
832 // target exited
833 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
834 // write memory
835 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
836 // remove breakpoint or watchpoint
837 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
838 // insert breakpoint or watchpoint
839 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
840};
841
842bool
843BaseRemoteGDB::checkBpLen(size_t len)
844{
845 return len == sizeof(MachInst);
846}
739
740bool
741BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
742{
743 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
744 DDUMP(GDBMisc, ctx.data, ctx.len);
745 throw Unsupported();
746}
747
748
749bool
750BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
751{
752 send(csprintf("S%02x", ctx.type).c_str());
753 return true;
754}
755
756bool
757BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
758{
759 const char *p = ctx.data;
760 if (ctx.len) {
761 Addr newPc = hex2i(&p);
847
848bool
849BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
850{
851 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
852 DDUMP(GDBMisc, ctx.data, ctx.len);
853 throw Unsupported();
854}
855
856
857bool
858BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
859{
860 send(csprintf("S%02x", ctx.type).c_str());
861 return true;
862}
863
864bool
865BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
866{
867 const char *p = ctx.data;
868 if (ctx.len) {
869 Addr newPc = hex2i(&p);
762 context->pcState(newPc);
870 tc->pcState(newPc);
763 }
764 clearSingleStep();
765 return false;
766}
767
768bool
769BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
770{
771 const char *p = ctx.data;
772 hex2i(&p);
773 if (*p++ == ';') {
774 Addr newPc = hex2i(&p);
871 }
872 clearSingleStep();
873 return false;
874}
875
876bool
877BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
878{
879 const char *p = ctx.data;
880 hex2i(&p);
881 if (*p++ == ';') {
882 Addr newPc = hex2i(&p);
775 context->pcState(newPc);
883 tc->pcState(newPc);
776 }
777 clearSingleStep();
778 return false;
779}
780
781bool
782BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
783{
784 detach();
785 return false;
786}
787
788bool
789BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
790{
791 char buf[2 * regCachePtr->size() + 1];
792 buf[2 * regCachePtr->size()] = '\0';
793 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
794 send(buf);
795 return true;
796}
797
798bool
799BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
800{
801 const char *p = ctx.data;
802 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
803 if (p == NULL || *p != '\0')
804 throw CmdError("E01");
805
884 }
885 clearSingleStep();
886 return false;
887}
888
889bool
890BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
891{
892 detach();
893 return false;
894}
895
896bool
897BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
898{
899 char buf[2 * regCachePtr->size() + 1];
900 buf[2 * regCachePtr->size()] = '\0';
901 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
902 send(buf);
903 return true;
904}
905
906bool
907BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
908{
909 const char *p = ctx.data;
910 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
911 if (p == NULL || *p != '\0')
912 throw CmdError("E01");
913
806 regCachePtr->setRegs(context);
914 regCachePtr->setRegs(tc);
807 send("OK");
808
809 return true;
810}
811
812bool
813BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
814{
815 const char *p = ctx.data + 1; // Ignore the subcommand byte.
816 if (hex2i(&p) != 0)
817 throw CmdError("E01");
818 send("OK");
819 return true;
820}
821
822bool
823BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
824{
825 const char *p = ctx.data;
826 Addr addr = hex2i(&p);
827 if (*p++ != ',')
828 throw CmdError("E02");
829 size_t len = hex2i(&p);
830 if (*p != '\0')
831 throw CmdError("E03");
832 if (!acc(addr, len))
833 throw CmdError("E05");
834
835 char buf[len];
836 if (!read(addr, len, buf))
837 throw CmdError("E05");
838
839 char temp[2 * len + 1];
840 temp[2 * len] = '\0';
841 mem2hex(temp, buf, len);
842 send(temp);
843 return true;
844}
845
846bool
847BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
848{
849 const char *p = ctx.data;
850 Addr addr = hex2i(&p);
851 if (*p++ != ',')
852 throw CmdError("E06");
853 size_t len = hex2i(&p);
854 if (*p++ != ':')
855 throw CmdError("E07");
856 if (len * 2 > ctx.len - (p - ctx.data))
857 throw CmdError("E08");
858 char buf[len];
859 p = (char *)hex2mem(buf, p, len);
860 if (p == NULL)
861 throw CmdError("E09");
862 if (!acc(addr, len))
863 throw CmdError("E0A");
864 if (!write(addr, len, buf))
865 throw CmdError("E0B");
866 send("OK");
867 return true;
868}
869
870bool
871BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
872{
873 if (string(ctx.data, ctx.len - 1) != "C")
874 throw Unsupported();
875 send("QC0");
876 return true;
877}
878
879bool
880BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
881{
882 const char *p = ctx.data;
883 hex2i(&p); // Ignore the subcommand byte.
884 if (*p++ == ';') {
885 Addr newPc = hex2i(&p);
915 send("OK");
916
917 return true;
918}
919
920bool
921BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
922{
923 const char *p = ctx.data + 1; // Ignore the subcommand byte.
924 if (hex2i(&p) != 0)
925 throw CmdError("E01");
926 send("OK");
927 return true;
928}
929
930bool
931BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
932{
933 const char *p = ctx.data;
934 Addr addr = hex2i(&p);
935 if (*p++ != ',')
936 throw CmdError("E02");
937 size_t len = hex2i(&p);
938 if (*p != '\0')
939 throw CmdError("E03");
940 if (!acc(addr, len))
941 throw CmdError("E05");
942
943 char buf[len];
944 if (!read(addr, len, buf))
945 throw CmdError("E05");
946
947 char temp[2 * len + 1];
948 temp[2 * len] = '\0';
949 mem2hex(temp, buf, len);
950 send(temp);
951 return true;
952}
953
954bool
955BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
956{
957 const char *p = ctx.data;
958 Addr addr = hex2i(&p);
959 if (*p++ != ',')
960 throw CmdError("E06");
961 size_t len = hex2i(&p);
962 if (*p++ != ':')
963 throw CmdError("E07");
964 if (len * 2 > ctx.len - (p - ctx.data))
965 throw CmdError("E08");
966 char buf[len];
967 p = (char *)hex2mem(buf, p, len);
968 if (p == NULL)
969 throw CmdError("E09");
970 if (!acc(addr, len))
971 throw CmdError("E0A");
972 if (!write(addr, len, buf))
973 throw CmdError("E0B");
974 send("OK");
975 return true;
976}
977
978bool
979BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
980{
981 if (string(ctx.data, ctx.len - 1) != "C")
982 throw Unsupported();
983 send("QC0");
984 return true;
985}
986
987bool
988BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
989{
990 const char *p = ctx.data;
991 hex2i(&p); // Ignore the subcommand byte.
992 if (*p++ == ';') {
993 Addr newPc = hex2i(&p);
886 context->pcState(newPc);
994 tc->pcState(newPc);
887 }
888 setSingleStep();
889 return false;
890}
891
892bool
893BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
894{
895 if (ctx.len) {
896 const char *p = ctx.data;
897 Addr newPc = hex2i(&p);
995 }
996 setSingleStep();
997 return false;
998}
999
1000bool
1001BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
1002{
1003 if (ctx.len) {
1004 const char *p = ctx.data;
1005 Addr newPc = hex2i(&p);
898 context->pcState(newPc);
1006 tc->pcState(newPc);
899 }
900 setSingleStep();
901 return false;
902}
903
904bool
905BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
906{
907 const char *p = ctx.data;
908 char subcmd = *p++;
909 if (*p++ != ',')
910 throw CmdError("E0D");
911 Addr addr = hex2i(&p);
912 if (*p++ != ',')
913 throw CmdError("E0D");
914 size_t len = hex2i(&p);
915
916 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
917 break_type(subcmd), addr, len);
918
919 switch (subcmd) {
920 case GdbSoftBp:
921 removeSoftBreak(addr, len);
922 break;
923 case GdbHardBp:
924 removeHardBreak(addr, len);
925 break;
926 case GdbWriteWp:
927 case GdbReadWp:
928 case GdbAccWp:
929 default: // unknown
930 throw Unsupported();
931 }
932 send("OK");
933
934 return true;
935}
936
937bool
938BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
939{
940 const char *p = ctx.data;
941 char subcmd = *p++;
942 if (*p++ != ',')
943 throw CmdError("E0D");
944 Addr addr = hex2i(&p);
945 if (*p++ != ',')
946 throw CmdError("E0D");
947 size_t len = hex2i(&p);
948
949 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
950 break_type(subcmd), addr, len);
951
952 switch (subcmd) {
953 case GdbSoftBp:
954 insertSoftBreak(addr, len);
955 break;
956 case GdbHardBp:
957 insertHardBreak(addr, len);
958 break;
959 case GdbWriteWp:
960 case GdbReadWp:
961 case GdbAccWp:
962 default: // unknown
963 throw Unsupported();
964 }
965 send("OK");
966
967 return true;
968}
1007 }
1008 setSingleStep();
1009 return false;
1010}
1011
1012bool
1013BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
1014{
1015 const char *p = ctx.data;
1016 char subcmd = *p++;
1017 if (*p++ != ',')
1018 throw CmdError("E0D");
1019 Addr addr = hex2i(&p);
1020 if (*p++ != ',')
1021 throw CmdError("E0D");
1022 size_t len = hex2i(&p);
1023
1024 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
1025 break_type(subcmd), addr, len);
1026
1027 switch (subcmd) {
1028 case GdbSoftBp:
1029 removeSoftBreak(addr, len);
1030 break;
1031 case GdbHardBp:
1032 removeHardBreak(addr, len);
1033 break;
1034 case GdbWriteWp:
1035 case GdbReadWp:
1036 case GdbAccWp:
1037 default: // unknown
1038 throw Unsupported();
1039 }
1040 send("OK");
1041
1042 return true;
1043}
1044
1045bool
1046BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
1047{
1048 const char *p = ctx.data;
1049 char subcmd = *p++;
1050 if (*p++ != ',')
1051 throw CmdError("E0D");
1052 Addr addr = hex2i(&p);
1053 if (*p++ != ',')
1054 throw CmdError("E0D");
1055 size_t len = hex2i(&p);
1056
1057 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
1058 break_type(subcmd), addr, len);
1059
1060 switch (subcmd) {
1061 case GdbSoftBp:
1062 insertSoftBreak(addr, len);
1063 break;
1064 case GdbHardBp:
1065 insertHardBreak(addr, len);
1066 break;
1067 case GdbWriteWp:
1068 case GdbReadWp:
1069 case GdbAccWp:
1070 default: // unknown
1071 throw Unsupported();
1072 }
1073 send("OK");
1074
1075 return true;
1076}
969
970
971// This function does all command processing for interfacing to a
972// remote gdb. Note that the error codes are ignored by gdb at
973// present, but might eventually become meaningful. (XXX) It might
974// makes sense to use POSIX errno values, because that is what the
975// gdb/remote.c functions want to return.
976bool
977BaseRemoteGDB::trap(int type)
978{
979
980 if (!attached)
981 return false;
982
983 DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState());
984
985 clearSingleStep();
986
987 /*
988 * The first entry to this function is normally through
989 * a breakpoint trap in kgdb_connect(), in which case we
990 * must advance past the breakpoint because gdb will not.
991 *
992 * On the first entry here, we expect that gdb is not yet
993 * listening to us, so just enter the interaction loop.
994 * After the debugger is "active" (connected) it will be
995 * waiting for a "signaled" message from us.
996 */
997 if (!active) {
998 active = true;
999 } else {
1000 // Tell remote host that an exception has occurred.
1001 send(csprintf("S%02x", type).c_str());
1002 }
1003
1004 // Stick frame regs into our reg cache.
1005 regCachePtr = gdbRegs();
1006 regCachePtr->getRegs(context);
1007
1008 char data[GDBPacketBufLen + 1];
1009 GdbCommand::Context cmdCtx;
1010 cmdCtx.type = type;
1011 cmdCtx.data = &data[1];
1012
1013 for (;;) {
1014 try {
1015 size_t datalen = recv(data, sizeof(data));
1016 if (datalen < 1)
1017 throw BadClient();
1018
1019 data[datalen] = 0; // Sentinel
1020 cmdCtx.cmd_byte = data[0];
1021 cmdCtx.len = datalen - 1;
1022
1023 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
1024 if (cmdIt == command_map.end()) {
1025 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
1026 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
1027 throw Unsupported();
1028 }
1029 cmdCtx.cmd = &(cmdIt->second);
1030
1031 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
1032 break;
1033
1034 } catch (BadClient &e) {
1035 if (e.warning)
1036 warn(e.warning);
1037 detach();
1038 break;
1039 } catch (Unsupported &e) {
1040 send("");
1041 } catch (CmdError &e) {
1042 send(e.error.c_str());
1043 } catch (...) {
1044 panic("Unrecognzied GDB exception.");
1045 }
1046 }
1047
1048 return true;
1049}
1050
1051// Convert a hex digit into an integer.
1052// This returns -1 if the argument passed is no valid hex digit.
1053int
1054BaseRemoteGDB::digit2i(char c)
1055{
1056 if (c >= '0' && c <= '9')
1057 return (c - '0');
1058 else if (c >= 'a' && c <= 'f')
1059 return (c - 'a' + 10);
1060 else if (c >= 'A' && c <= 'F')
1061 return (c - 'A' + 10);
1062 else
1063 return (-1);
1064}
1065
1066// Convert the low 4 bits of an integer into an hex digit.
1067char
1068BaseRemoteGDB::i2digit(int n)
1069{
1070 return ("0123456789abcdef"[n & 0x0f]);
1071}
1072
1073// Convert a byte array into an hex string.
1074void
1075BaseRemoteGDB::mem2hex(char *vdst, const char *vsrc, int len)
1076{
1077 char *dst = vdst;
1078 const char *src = vsrc;
1079
1080 while (len--) {
1081 *dst++ = i2digit(*src >> 4);
1082 *dst++ = i2digit(*src++);
1083 }
1084 *dst = '\0';
1085}
1086
1087// Convert an hex string into a byte array.
1088// This returns a pointer to the character following the last valid
1089// hex digit. If the string ends in the middle of a byte, NULL is
1090// returned.
1091const char *
1092BaseRemoteGDB::hex2mem(char *vdst, const char *src, int maxlen)
1093{
1094 char *dst = vdst;
1095 int msb, lsb;
1096
1097 while (*src && maxlen--) {
1098 msb = digit2i(*src++);
1099 if (msb < 0)
1100 return (src - 1);
1101 lsb = digit2i(*src++);
1102 if (lsb < 0)
1103 return (NULL);
1104 *dst++ = (msb << 4) | lsb;
1105 }
1106 return src;
1107}
1108
1109// Convert an hex string into an integer.
1110// This returns a pointer to the character following the last valid
1111// hex digit.
1112Addr
1113BaseRemoteGDB::hex2i(const char **srcp)
1114{
1115 const char *src = *srcp;
1116 Addr r = 0;
1117 int nibble;
1118
1119 while ((nibble = digit2i(*src)) >= 0) {
1120 r *= 16;
1121 r += nibble;
1122 src++;
1123 }
1124 *srcp = src;
1125 return r;
1126}