remote_gdb.cc (12031:46116545e745) remote_gdb.cc (12122:20512f6810d7)
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
160void
161debugger()
162{
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);
170 }
171}
172#endif
173
174///////////////////////////////////////////////////////////
175//
176//
177//
178
179GDBListener::InputEvent::InputEvent(GDBListener *l, int fd, int e)
180 : PollEvent(fd, e), listener(l)
181{}
182
183void
184GDBListener::InputEvent::process(int revent)
185{
186 listener->accept();
187}
188
189GDBListener::GDBListener(BaseRemoteGDB *g, int p)
190 : inputEvent(NULL), gdb(g), port(p)
191{
192 assert(!gdb->listener);
193 gdb->listener = this;
194}
195
196GDBListener::~GDBListener()
197{
198 delete inputEvent;
199}
200
201string
202GDBListener::name()
203{
204 return gdb->name() + ".listener";
205}
206
207void
208GDBListener::listen()
209{
210 if (ListenSocket::allDisabled()) {
211 warn_once("Sockets disabled, not accepting gdb connections");
212 return;
213 }
214
215 while (!listener.listen(port, true)) {
216 DPRINTF(GDBMisc, "Can't bind port %d\n", port);
217 port++;
218 }
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
235}
236
237void
238GDBListener::accept()
239{
240 if (!listener.islistening())
241 panic("GDBListener::accept(): cannot accept if we're not listening!");
242
243 int sfd = listener.accept(true);
244
245 if (sfd != -1) {
246 if (gdb->isattached())
247 close(sfd);
248 else
249 gdb->attach(sfd);
250 }
251}
252
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
160void
161debugger()
162{
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);
170 }
171}
172#endif
173
174///////////////////////////////////////////////////////////
175//
176//
177//
178
179GDBListener::InputEvent::InputEvent(GDBListener *l, int fd, int e)
180 : PollEvent(fd, e), listener(l)
181{}
182
183void
184GDBListener::InputEvent::process(int revent)
185{
186 listener->accept();
187}
188
189GDBListener::GDBListener(BaseRemoteGDB *g, int p)
190 : inputEvent(NULL), gdb(g), port(p)
191{
192 assert(!gdb->listener);
193 gdb->listener = this;
194}
195
196GDBListener::~GDBListener()
197{
198 delete inputEvent;
199}
200
201string
202GDBListener::name()
203{
204 return gdb->name() + ".listener";
205}
206
207void
208GDBListener::listen()
209{
210 if (ListenSocket::allDisabled()) {
211 warn_once("Sockets disabled, not accepting gdb connections");
212 return;
213 }
214
215 while (!listener.listen(port, true)) {
216 DPRINTF(GDBMisc, "Can't bind port %d\n", port);
217 port++;
218 }
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
235}
236
237void
238GDBListener::accept()
239{
240 if (!listener.islistening())
241 panic("GDBListener::accept(): cannot accept if we're not listening!");
242
243 int sfd = listener.accept(true);
244
245 if (sfd != -1) {
246 if (gdb->isattached())
247 close(sfd);
248 else
249 gdb->attach(sfd);
250 }
251}
252
253int
254GDBListener::getPort() const
255{
256 panic_if(!listener.islistening(),
257 "Remote GDB port is unknown until GDBListener::listen() has "
258 "been called.\n");
259
260 return port;
261}
262
253BaseRemoteGDB::InputEvent::InputEvent(BaseRemoteGDB *g, int fd, int e)
254 : PollEvent(fd, e), gdb(g)
255{}
256
257void
258BaseRemoteGDB::InputEvent::process(int revent)
259{
260 if (gdb->trapEvent.scheduled()) {
261 warn("GDB trap event has already been scheduled! "
262 "Ignoring this input event.");
263 return;
264 }
265
266 if (revent & POLLIN) {
267 gdb->trapEvent.type(SIGILL);
268 gdb->scheduleInstCommitEvent(&gdb->trapEvent, 0);
269 } else if (revent & POLLNVAL) {
270 gdb->descheduleInstCommitEvent(&gdb->trapEvent);
271 gdb->detach();
272 }
273}
274
275void
276BaseRemoteGDB::TrapEvent::process()
277{
278 gdb->trap(_type);
279}
280
281void
282BaseRemoteGDB::SingleStepEvent::process()
283{
284 if (!gdb->singleStepEvent.scheduled())
285 gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1);
286 gdb->trap(SIGTRAP);
287}
288
289BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c) :
290 inputEvent(NULL), trapEvent(this), listener(NULL),
291 number(-1), fd(-1), active(false), attached(false), system(_system),
292 context(c), singleStepEvent(this)
293{
294}
295
296BaseRemoteGDB::~BaseRemoteGDB()
297{
298 if (inputEvent)
299 delete inputEvent;
300}
301
302string
303BaseRemoteGDB::name()
304{
305 return system->name() + ".remote_gdb";
306}
307
308bool
309BaseRemoteGDB::isattached()
310{ return attached; }
311
312void
313BaseRemoteGDB::attach(int f)
314{
315 fd = f;
316
317 inputEvent = new InputEvent(this, fd, POLLIN);
318 pollQueue.schedule(inputEvent);
319
320 attached = true;
321 DPRINTFN("remote gdb attached\n");
322}
323
324void
325BaseRemoteGDB::detach()
326{
327 attached = false;
328 active = false;
329 clearSingleStep();
330 close(fd);
331 fd = -1;
332
333 pollQueue.remove(inputEvent);
334 DPRINTFN("remote gdb detached\n");
335}
336
337/////////////////////////
338//
339//
340
341uint8_t
342BaseRemoteGDB::getbyte()
343{
344 uint8_t b;
345 if (::read(fd, &b, sizeof(b)) == sizeof(b))
346 return b;
347
348 throw BadClient("Couldn't read data from debugger.");
349}
350
351void
352BaseRemoteGDB::putbyte(uint8_t b)
353{
354 if (::write(fd, &b, sizeof(b)) == sizeof(b))
355 return;
356
357 throw BadClient("Couldn't write data to the debugger.");
358}
359
360// Send a packet to gdb
361void
362BaseRemoteGDB::send(const char *bp)
363{
364 const char *p;
365 uint8_t csum, c;
366
367 DPRINTF(GDBSend, "send: %s\n", bp);
368
369 do {
370 p = bp;
371 // Start sending a packet
372 putbyte(GDBStart);
373 // Send the contents, and also keep a check sum.
374 for (csum = 0; (c = *p); p++) {
375 putbyte(c);
376 csum += c;
377 }
378 // Send the ending character.
379 putbyte(GDBEnd);
380 // Send the checksum.
381 putbyte(i2digit(csum >> 4));
382 putbyte(i2digit(csum));
383 // Try transmitting over and over again until the other end doesn't
384 // send an error back.
385 c = getbyte();
386 } while ((c & 0x7f) == GDBBadP);
387}
388
389// Receive a packet from gdb
390int
391BaseRemoteGDB::recv(char *bp, int maxlen)
392{
393 char *p;
394 uint8_t c;
395 int csum;
396 int len;
397
398 do {
399 p = bp;
400 csum = len = 0;
401 // Find the beginning of a packet
402 while ((c = getbyte()) != GDBStart);
403
404 // Read until you find the end of the data in the packet, and keep
405 // track of the check sum.
406 while (len < maxlen) {
407 c = getbyte();
408 if (c == GDBEnd)
409 break;
410 c &= 0x7f;
411 csum += c;
412 *p++ = c;
413 len++;
414 }
415
416 // Mask the check sum, and terminate the command string.
417 csum &= 0xff;
418 *p = '\0';
419
420 // If the command was too long, report an error.
421 if (len >= maxlen) {
422 putbyte(GDBBadP);
423 continue;
424 }
425
426 // Bring in the checksum. If the check sum matches, csum will be 0.
427 csum -= digit2i(getbyte()) * 16;
428 csum -= digit2i(getbyte());
429
430 // If the check sum was correct
431 if (csum == 0) {
432 // Report that the packet was received correctly
433 putbyte(GDBGoodP);
434 // Sequence present?
435 if (bp[2] == ':') {
436 putbyte(bp[0]);
437 putbyte(bp[1]);
438 len -= 3;
439 memcpy(bp, bp+3, len);
440 }
441 break;
442 }
443 // Otherwise, report that there was a mistake.
444 putbyte(GDBBadP);
445 } while (1);
446
447 DPRINTF(GDBRecv, "recv: %s\n", bp);
448
449 return len;
450}
451
452// Read bytes from kernel address space for debugger.
453bool
454BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
455{
456 static Addr lastaddr = 0;
457 static size_t lastsize = 0;
458
459 if (vaddr < 10) {
460 DPRINTF(GDBRead, "read: reading memory location zero!\n");
461 vaddr = lastaddr + lastsize;
462 }
463
464 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
465
466 if (FullSystem) {
467 FSTranslatingPortProxy &proxy = context->getVirtProxy();
468 proxy.readBlob(vaddr, (uint8_t*)data, size);
469 } else {
470 SETranslatingPortProxy &proxy = context->getMemProxy();
471 proxy.readBlob(vaddr, (uint8_t*)data, size);
472 }
473
474#if TRACING_ON
475 if (DTRACE(GDBRead)) {
476 if (DTRACE(GDBExtra)) {
477 char buf[1024];
478 mem2hex(buf, data, size);
479 DPRINTFNR(": %s\n", buf);
480 } else
481 DPRINTFNR("\n");
482 }
483#endif
484
485 return true;
486}
487
488// Write bytes to kernel address space for debugger.
489bool
490BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
491{
492 static Addr lastaddr = 0;
493 static size_t lastsize = 0;
494
495 if (vaddr < 10) {
496 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
497 vaddr = lastaddr + lastsize;
498 }
499
500 if (DTRACE(GDBWrite)) {
501 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
502 if (DTRACE(GDBExtra)) {
503 char buf[1024];
504 mem2hex(buf, data, size);
505 DPRINTFNR(": %s\n", buf);
506 } else
507 DPRINTFNR("\n");
508 }
509 if (FullSystem) {
510 FSTranslatingPortProxy &proxy = context->getVirtProxy();
511 proxy.writeBlob(vaddr, (uint8_t*)data, size);
512 } else {
513 SETranslatingPortProxy &proxy = context->getMemProxy();
514 proxy.writeBlob(vaddr, (uint8_t*)data, size);
515 }
516
517 return true;
518}
519
520void
521BaseRemoteGDB::clearSingleStep()
522{
523 descheduleInstCommitEvent(&singleStepEvent);
524}
525
526void
527BaseRemoteGDB::setSingleStep()
528{
529 if (!singleStepEvent.scheduled())
530 scheduleInstCommitEvent(&singleStepEvent, 1);
531}
532
533PCEventQueue *BaseRemoteGDB::getPcEventQueue()
534{
535 return &system->pcEventQueue;
536}
537
538EventQueue *
539BaseRemoteGDB::getComInstEventQueue()
540{
541 BaseCPU *cpu = context->getCpuPtr();
542 return cpu->comInstEventQueue[context->threadId()];
543}
544
545void
546BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
547{
548 EventQueue *eq = getComInstEventQueue();
549 // Here "ticks" aren't simulator ticks which measure time, they're
550 // instructions committed by the CPU.
551 eq->schedule(ev, eq->getCurTick() + delta);
552}
553
554void
555BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
556{
557 if (ev->scheduled())
558 getComInstEventQueue()->deschedule(ev);
559}
560
561bool
562BaseRemoteGDB::checkBpLen(size_t len)
563{
564 return len == sizeof(MachInst);
565}
566
567BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc)
568 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
569 gdb(_gdb), refcount(0)
570{
571 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
572}
573
574void
575BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc)
576{
577 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
578
579 if (tc == gdb->context)
580 gdb->trap(SIGTRAP);
581}
582
583void
584BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
585{
586 if (!checkBpLen(len))
587 throw BadClient("Invalid breakpoint length\n");
588
589 return insertHardBreak(addr, len);
590}
591
592void
593BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
594{
595 if (!checkBpLen(len))
596 throw BadClient("Invalid breakpoint length.\n");
597
598 return removeHardBreak(addr, len);
599}
600
601void
602BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
603{
604 if (!checkBpLen(len))
605 throw BadClient("Invalid breakpoint length\n");
606
607 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
608
609 HardBreakpoint *&bkpt = hardBreakMap[addr];
610 if (bkpt == 0)
611 bkpt = new HardBreakpoint(this, addr);
612
613 bkpt->refcount++;
614}
615
616void
617BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
618{
619 if (!checkBpLen(len))
620 throw BadClient("Invalid breakpoint length\n");
621
622 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
623
624 break_iter_t i = hardBreakMap.find(addr);
625 if (i == hardBreakMap.end())
626 throw CmdError("E0C");
627
628 HardBreakpoint *hbp = (*i).second;
629 if (--hbp->refcount == 0) {
630 delete hbp;
631 hardBreakMap.erase(i);
632 }
633}
634
635void
636BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
637{
638 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
639 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
640}
641
642void
643BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
644{
645 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
646 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
647 bkpt = 0;
648}
649
650enum GdbBreakpointType {
651 GdbSoftBp = '0',
652 GdbHardBp = '1',
653 GdbWriteWp = '2',
654 GdbReadWp = '3',
655 GdbAccWp = '4',
656};
657
658const char *
659BaseRemoteGDB::break_type(char c)
660{
661 switch(c) {
662 case GdbSoftBp: return "software breakpoint";
663 case GdbHardBp: return "hardware breakpoint";
664 case GdbWriteWp: return "write watchpoint";
665 case GdbReadWp: return "read watchpoint";
666 case GdbAccWp: return "access watchpoint";
667 default: return "unknown breakpoint/watchpoint";
668 }
669}
670
671std::map<char, GdbCommand> BaseRemoteGDB::command_map = {
672 // last signal
673 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
674 // set baud (deprecated)
675 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
676 // set breakpoint (deprecated)
677 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
678 // resume
679 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
680 // continue with signal
681 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
682 // toggle debug flags (deprecated)
683 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
684 // detach remote gdb
685 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
686 // read general registers
687 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
688 // write general registers
689 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
690 // set thread
691 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
692 // step a single cycle
693 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
694 // signal then cycle step
695 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
696 // kill program
697 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
698 // read memory
699 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
700 // write memory
701 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
702 // read register
703 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
704 // write register
705 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
706 // query variable
707 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
708 // set variable
709 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
710 // reset system (deprecated)
711 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
712 // step
713 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
714 // signal and step
715 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
716 // find out if the thread is alive
717 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
718 // target exited
719 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
720 // write memory
721 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
722 // remove breakpoint or watchpoint
723 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
724 // insert breakpoint or watchpoint
725 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
726};
727
728
729bool
730BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
731{
732 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
733 DDUMP(GDBMisc, ctx.data, ctx.len);
734 throw Unsupported();
735}
736
737
738bool
739BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
740{
741 send(csprintf("S%02x", ctx.type).c_str());
742 return true;
743}
744
745bool
746BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
747{
748 const char *p = ctx.data;
749 if (ctx.len) {
750 Addr newPc = hex2i(&p);
751 context->pcState(newPc);
752 }
753 clearSingleStep();
754 return false;
755}
756
757bool
758BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
759{
760 const char *p = ctx.data;
761 hex2i(&p);
762 if (*p++ == ';') {
763 Addr newPc = hex2i(&p);
764 context->pcState(newPc);
765 }
766 clearSingleStep();
767 return false;
768}
769
770bool
771BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
772{
773 detach();
774 return false;
775}
776
777bool
778BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
779{
780 char buf[2 * regCachePtr->size() + 1];
781 buf[2 * regCachePtr->size()] = '\0';
782 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
783 send(buf);
784 return true;
785}
786
787bool
788BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
789{
790 const char *p = ctx.data;
791 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
792 if (p == NULL || *p != '\0')
793 throw CmdError("E01");
794
795 regCachePtr->setRegs(context);
796 send("OK");
797
798 return true;
799}
800
801bool
802BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
803{
804 const char *p = ctx.data + 1; // Ignore the subcommand byte.
805 if (hex2i(&p) != 0)
806 throw CmdError("E01");
807 send("OK");
808 return true;
809}
810
811bool
812BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
813{
814 const char *p = ctx.data;
815 Addr addr = hex2i(&p);
816 if (*p++ != ',')
817 throw CmdError("E02");
818 size_t len = hex2i(&p);
819 if (*p != '\0')
820 throw CmdError("E03");
821 if (!acc(addr, len))
822 throw CmdError("E05");
823
824 char buf[len];
825 if (!read(addr, len, buf))
826 throw CmdError("E05");
827
828 char temp[2 * len + 1];
829 temp[2 * len] = '\0';
830 mem2hex(temp, buf, len);
831 send(temp);
832 return true;
833}
834
835bool
836BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
837{
838 const char *p = ctx.data;
839 Addr addr = hex2i(&p);
840 if (*p++ != ',')
841 throw CmdError("E06");
842 size_t len = hex2i(&p);
843 if (*p++ != ':')
844 throw CmdError("E07");
845 if (len * 2 > ctx.len - (p - ctx.data))
846 throw CmdError("E08");
847 char buf[len];
848 p = (char *)hex2mem(buf, p, len);
849 if (p == NULL)
850 throw CmdError("E09");
851 if (!acc(addr, len))
852 throw CmdError("E0A");
853 if (!write(addr, len, buf))
854 throw CmdError("E0B");
855 send("OK");
856 return true;
857}
858
859bool
860BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
861{
862 if (string(ctx.data, ctx.len - 1) != "C")
863 throw Unsupported();
864 send("QC0");
865 return true;
866}
867
868bool
869BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
870{
871 const char *p = ctx.data;
872 hex2i(&p); // Ignore the subcommand byte.
873 if (*p++ == ';') {
874 Addr newPc = hex2i(&p);
875 context->pcState(newPc);
876 }
877 setSingleStep();
878 return false;
879}
880
881bool
882BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
883{
884 if (ctx.len) {
885 const char *p = ctx.data;
886 Addr newPc = hex2i(&p);
887 context->pcState(newPc);
888 }
889 setSingleStep();
890 return false;
891}
892
893bool
894BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
895{
896 const char *p = ctx.data;
897 char subcmd = *p++;
898 if (*p++ != ',')
899 throw CmdError("E0D");
900 Addr addr = hex2i(&p);
901 if (*p++ != ',')
902 throw CmdError("E0D");
903 size_t len = hex2i(&p);
904
905 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
906 break_type(subcmd), addr, len);
907
908 switch (subcmd) {
909 case GdbSoftBp:
910 removeSoftBreak(addr, len);
911 break;
912 case GdbHardBp:
913 removeHardBreak(addr, len);
914 break;
915 case GdbWriteWp:
916 case GdbReadWp:
917 case GdbAccWp:
918 default: // unknown
919 throw Unsupported();
920 }
921 send("OK");
922
923 return true;
924}
925
926bool
927BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
928{
929 const char *p = ctx.data;
930 char subcmd = *p++;
931 if (*p++ != ',')
932 throw CmdError("E0D");
933 Addr addr = hex2i(&p);
934 if (*p++ != ',')
935 throw CmdError("E0D");
936 size_t len = hex2i(&p);
937
938 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
939 break_type(subcmd), addr, len);
940
941 switch (subcmd) {
942 case GdbSoftBp:
943 insertSoftBreak(addr, len);
944 break;
945 case GdbHardBp:
946 insertHardBreak(addr, len);
947 break;
948 case GdbWriteWp:
949 case GdbReadWp:
950 case GdbAccWp:
951 default: // unknown
952 throw Unsupported();
953 }
954 send("OK");
955
956 return true;
957}
958
959
960// This function does all command processing for interfacing to a
961// remote gdb. Note that the error codes are ignored by gdb at
962// present, but might eventually become meaningful. (XXX) It might
963// makes sense to use POSIX errno values, because that is what the
964// gdb/remote.c functions want to return.
965bool
966BaseRemoteGDB::trap(int type)
967{
968
969 if (!attached)
970 return false;
971
972 DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState());
973
974 clearSingleStep();
975
976 /*
977 * The first entry to this function is normally through
978 * a breakpoint trap in kgdb_connect(), in which case we
979 * must advance past the breakpoint because gdb will not.
980 *
981 * On the first entry here, we expect that gdb is not yet
982 * listening to us, so just enter the interaction loop.
983 * After the debugger is "active" (connected) it will be
984 * waiting for a "signaled" message from us.
985 */
986 if (!active) {
987 active = true;
988 } else {
989 // Tell remote host that an exception has occurred.
990 send(csprintf("S%02x", type).c_str());
991 }
992
993 // Stick frame regs into our reg cache.
994 regCachePtr = gdbRegs();
995 regCachePtr->getRegs(context);
996
997 char data[GDBPacketBufLen + 1];
998 GdbCommand::Context cmdCtx;
999 cmdCtx.type = type;
1000 cmdCtx.data = &data[1];
1001
1002 for (;;) {
1003 try {
1004 size_t datalen = recv(data, sizeof(data));
1005 if (datalen < 1)
1006 throw BadClient();
1007
1008 data[datalen] = 0; // Sentinel
1009 cmdCtx.cmd_byte = data[0];
1010 cmdCtx.len = datalen - 1;
1011
1012 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
1013 if (cmdIt == command_map.end()) {
1014 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
1015 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
1016 throw Unsupported();
1017 }
1018 cmdCtx.cmd = &(cmdIt->second);
1019
1020 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
1021 break;
1022
1023 } catch (BadClient &e) {
1024 if (e.warning)
1025 warn(e.warning);
1026 detach();
1027 break;
1028 } catch (Unsupported &e) {
1029 send("");
1030 } catch (CmdError &e) {
1031 send(e.error.c_str());
1032 } catch (...) {
1033 panic("Unrecognzied GDB exception.");
1034 }
1035 }
1036
1037 return true;
1038}
1039
1040// Convert a hex digit into an integer.
1041// This returns -1 if the argument passed is no valid hex digit.
1042int
1043BaseRemoteGDB::digit2i(char c)
1044{
1045 if (c >= '0' && c <= '9')
1046 return (c - '0');
1047 else if (c >= 'a' && c <= 'f')
1048 return (c - 'a' + 10);
1049 else if (c >= 'A' && c <= 'F')
1050 return (c - 'A' + 10);
1051 else
1052 return (-1);
1053}
1054
1055// Convert the low 4 bits of an integer into an hex digit.
1056char
1057BaseRemoteGDB::i2digit(int n)
1058{
1059 return ("0123456789abcdef"[n & 0x0f]);
1060}
1061
1062// Convert a byte array into an hex string.
1063void
1064BaseRemoteGDB::mem2hex(char *vdst, const char *vsrc, int len)
1065{
1066 char *dst = vdst;
1067 const char *src = vsrc;
1068
1069 while (len--) {
1070 *dst++ = i2digit(*src >> 4);
1071 *dst++ = i2digit(*src++);
1072 }
1073 *dst = '\0';
1074}
1075
1076// Convert an hex string into a byte array.
1077// This returns a pointer to the character following the last valid
1078// hex digit. If the string ends in the middle of a byte, NULL is
1079// returned.
1080const char *
1081BaseRemoteGDB::hex2mem(char *vdst, const char *src, int maxlen)
1082{
1083 char *dst = vdst;
1084 int msb, lsb;
1085
1086 while (*src && maxlen--) {
1087 msb = digit2i(*src++);
1088 if (msb < 0)
1089 return (src - 1);
1090 lsb = digit2i(*src++);
1091 if (lsb < 0)
1092 return (NULL);
1093 *dst++ = (msb << 4) | lsb;
1094 }
1095 return src;
1096}
1097
1098// Convert an hex string into an integer.
1099// This returns a pointer to the character following the last valid
1100// hex digit.
1101Addr
1102BaseRemoteGDB::hex2i(const char **srcp)
1103{
1104 const char *src = *srcp;
1105 Addr r = 0;
1106 int nibble;
1107
1108 while ((nibble = digit2i(*src)) >= 0) {
1109 r *= 16;
1110 r += nibble;
1111 src++;
1112 }
1113 *srcp = src;
1114 return r;
1115}
1116
263BaseRemoteGDB::InputEvent::InputEvent(BaseRemoteGDB *g, int fd, int e)
264 : PollEvent(fd, e), gdb(g)
265{}
266
267void
268BaseRemoteGDB::InputEvent::process(int revent)
269{
270 if (gdb->trapEvent.scheduled()) {
271 warn("GDB trap event has already been scheduled! "
272 "Ignoring this input event.");
273 return;
274 }
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
285void
286BaseRemoteGDB::TrapEvent::process()
287{
288 gdb->trap(_type);
289}
290
291void
292BaseRemoteGDB::SingleStepEvent::process()
293{
294 if (!gdb->singleStepEvent.scheduled())
295 gdb->scheduleInstCommitEvent(&gdb->singleStepEvent, 1);
296 gdb->trap(SIGTRAP);
297}
298
299BaseRemoteGDB::BaseRemoteGDB(System *_system, ThreadContext *c) :
300 inputEvent(NULL), trapEvent(this), listener(NULL),
301 number(-1), fd(-1), active(false), attached(false), system(_system),
302 context(c), singleStepEvent(this)
303{
304}
305
306BaseRemoteGDB::~BaseRemoteGDB()
307{
308 if (inputEvent)
309 delete inputEvent;
310}
311
312string
313BaseRemoteGDB::name()
314{
315 return system->name() + ".remote_gdb";
316}
317
318bool
319BaseRemoteGDB::isattached()
320{ return attached; }
321
322void
323BaseRemoteGDB::attach(int f)
324{
325 fd = f;
326
327 inputEvent = new InputEvent(this, fd, POLLIN);
328 pollQueue.schedule(inputEvent);
329
330 attached = true;
331 DPRINTFN("remote gdb attached\n");
332}
333
334void
335BaseRemoteGDB::detach()
336{
337 attached = false;
338 active = false;
339 clearSingleStep();
340 close(fd);
341 fd = -1;
342
343 pollQueue.remove(inputEvent);
344 DPRINTFN("remote gdb detached\n");
345}
346
347/////////////////////////
348//
349//
350
351uint8_t
352BaseRemoteGDB::getbyte()
353{
354 uint8_t b;
355 if (::read(fd, &b, sizeof(b)) == sizeof(b))
356 return b;
357
358 throw BadClient("Couldn't read data from debugger.");
359}
360
361void
362BaseRemoteGDB::putbyte(uint8_t b)
363{
364 if (::write(fd, &b, sizeof(b)) == sizeof(b))
365 return;
366
367 throw BadClient("Couldn't write data to the debugger.");
368}
369
370// Send a packet to gdb
371void
372BaseRemoteGDB::send(const char *bp)
373{
374 const char *p;
375 uint8_t csum, c;
376
377 DPRINTF(GDBSend, "send: %s\n", bp);
378
379 do {
380 p = bp;
381 // Start sending a packet
382 putbyte(GDBStart);
383 // Send the contents, and also keep a check sum.
384 for (csum = 0; (c = *p); p++) {
385 putbyte(c);
386 csum += c;
387 }
388 // Send the ending character.
389 putbyte(GDBEnd);
390 // Send the checksum.
391 putbyte(i2digit(csum >> 4));
392 putbyte(i2digit(csum));
393 // Try transmitting over and over again until the other end doesn't
394 // send an error back.
395 c = getbyte();
396 } while ((c & 0x7f) == GDBBadP);
397}
398
399// Receive a packet from gdb
400int
401BaseRemoteGDB::recv(char *bp, int maxlen)
402{
403 char *p;
404 uint8_t c;
405 int csum;
406 int len;
407
408 do {
409 p = bp;
410 csum = len = 0;
411 // Find the beginning of a packet
412 while ((c = getbyte()) != GDBStart);
413
414 // Read until you find the end of the data in the packet, and keep
415 // track of the check sum.
416 while (len < maxlen) {
417 c = getbyte();
418 if (c == GDBEnd)
419 break;
420 c &= 0x7f;
421 csum += c;
422 *p++ = c;
423 len++;
424 }
425
426 // Mask the check sum, and terminate the command string.
427 csum &= 0xff;
428 *p = '\0';
429
430 // If the command was too long, report an error.
431 if (len >= maxlen) {
432 putbyte(GDBBadP);
433 continue;
434 }
435
436 // Bring in the checksum. If the check sum matches, csum will be 0.
437 csum -= digit2i(getbyte()) * 16;
438 csum -= digit2i(getbyte());
439
440 // If the check sum was correct
441 if (csum == 0) {
442 // Report that the packet was received correctly
443 putbyte(GDBGoodP);
444 // Sequence present?
445 if (bp[2] == ':') {
446 putbyte(bp[0]);
447 putbyte(bp[1]);
448 len -= 3;
449 memcpy(bp, bp+3, len);
450 }
451 break;
452 }
453 // Otherwise, report that there was a mistake.
454 putbyte(GDBBadP);
455 } while (1);
456
457 DPRINTF(GDBRecv, "recv: %s\n", bp);
458
459 return len;
460}
461
462// Read bytes from kernel address space for debugger.
463bool
464BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
465{
466 static Addr lastaddr = 0;
467 static size_t lastsize = 0;
468
469 if (vaddr < 10) {
470 DPRINTF(GDBRead, "read: reading memory location zero!\n");
471 vaddr = lastaddr + lastsize;
472 }
473
474 DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
475
476 if (FullSystem) {
477 FSTranslatingPortProxy &proxy = context->getVirtProxy();
478 proxy.readBlob(vaddr, (uint8_t*)data, size);
479 } else {
480 SETranslatingPortProxy &proxy = context->getMemProxy();
481 proxy.readBlob(vaddr, (uint8_t*)data, size);
482 }
483
484#if TRACING_ON
485 if (DTRACE(GDBRead)) {
486 if (DTRACE(GDBExtra)) {
487 char buf[1024];
488 mem2hex(buf, data, size);
489 DPRINTFNR(": %s\n", buf);
490 } else
491 DPRINTFNR("\n");
492 }
493#endif
494
495 return true;
496}
497
498// Write bytes to kernel address space for debugger.
499bool
500BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
501{
502 static Addr lastaddr = 0;
503 static size_t lastsize = 0;
504
505 if (vaddr < 10) {
506 DPRINTF(GDBWrite, "write: writing memory location zero!\n");
507 vaddr = lastaddr + lastsize;
508 }
509
510 if (DTRACE(GDBWrite)) {
511 DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
512 if (DTRACE(GDBExtra)) {
513 char buf[1024];
514 mem2hex(buf, data, size);
515 DPRINTFNR(": %s\n", buf);
516 } else
517 DPRINTFNR("\n");
518 }
519 if (FullSystem) {
520 FSTranslatingPortProxy &proxy = context->getVirtProxy();
521 proxy.writeBlob(vaddr, (uint8_t*)data, size);
522 } else {
523 SETranslatingPortProxy &proxy = context->getMemProxy();
524 proxy.writeBlob(vaddr, (uint8_t*)data, size);
525 }
526
527 return true;
528}
529
530void
531BaseRemoteGDB::clearSingleStep()
532{
533 descheduleInstCommitEvent(&singleStepEvent);
534}
535
536void
537BaseRemoteGDB::setSingleStep()
538{
539 if (!singleStepEvent.scheduled())
540 scheduleInstCommitEvent(&singleStepEvent, 1);
541}
542
543PCEventQueue *BaseRemoteGDB::getPcEventQueue()
544{
545 return &system->pcEventQueue;
546}
547
548EventQueue *
549BaseRemoteGDB::getComInstEventQueue()
550{
551 BaseCPU *cpu = context->getCpuPtr();
552 return cpu->comInstEventQueue[context->threadId()];
553}
554
555void
556BaseRemoteGDB::scheduleInstCommitEvent(Event *ev, int delta)
557{
558 EventQueue *eq = getComInstEventQueue();
559 // Here "ticks" aren't simulator ticks which measure time, they're
560 // instructions committed by the CPU.
561 eq->schedule(ev, eq->getCurTick() + delta);
562}
563
564void
565BaseRemoteGDB::descheduleInstCommitEvent(Event *ev)
566{
567 if (ev->scheduled())
568 getComInstEventQueue()->deschedule(ev);
569}
570
571bool
572BaseRemoteGDB::checkBpLen(size_t len)
573{
574 return len == sizeof(MachInst);
575}
576
577BaseRemoteGDB::HardBreakpoint::HardBreakpoint(BaseRemoteGDB *_gdb, Addr pc)
578 : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
579 gdb(_gdb), refcount(0)
580{
581 DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
582}
583
584void
585BaseRemoteGDB::HardBreakpoint::process(ThreadContext *tc)
586{
587 DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
588
589 if (tc == gdb->context)
590 gdb->trap(SIGTRAP);
591}
592
593void
594BaseRemoteGDB::insertSoftBreak(Addr addr, size_t len)
595{
596 if (!checkBpLen(len))
597 throw BadClient("Invalid breakpoint length\n");
598
599 return insertHardBreak(addr, len);
600}
601
602void
603BaseRemoteGDB::removeSoftBreak(Addr addr, size_t len)
604{
605 if (!checkBpLen(len))
606 throw BadClient("Invalid breakpoint length.\n");
607
608 return removeHardBreak(addr, len);
609}
610
611void
612BaseRemoteGDB::insertHardBreak(Addr addr, size_t len)
613{
614 if (!checkBpLen(len))
615 throw BadClient("Invalid breakpoint length\n");
616
617 DPRINTF(GDBMisc, "Inserting hardware breakpoint at %#x\n", addr);
618
619 HardBreakpoint *&bkpt = hardBreakMap[addr];
620 if (bkpt == 0)
621 bkpt = new HardBreakpoint(this, addr);
622
623 bkpt->refcount++;
624}
625
626void
627BaseRemoteGDB::removeHardBreak(Addr addr, size_t len)
628{
629 if (!checkBpLen(len))
630 throw BadClient("Invalid breakpoint length\n");
631
632 DPRINTF(GDBMisc, "Removing hardware breakpoint at %#x\n", addr);
633
634 break_iter_t i = hardBreakMap.find(addr);
635 if (i == hardBreakMap.end())
636 throw CmdError("E0C");
637
638 HardBreakpoint *hbp = (*i).second;
639 if (--hbp->refcount == 0) {
640 delete hbp;
641 hardBreakMap.erase(i);
642 }
643}
644
645void
646BaseRemoteGDB::setTempBreakpoint(Addr bkpt)
647{
648 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
649 insertHardBreak(bkpt, sizeof(TheISA::MachInst));
650}
651
652void
653BaseRemoteGDB::clearTempBreakpoint(Addr &bkpt)
654{
655 DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", bkpt);
656 removeHardBreak(bkpt, sizeof(TheISA::MachInst));
657 bkpt = 0;
658}
659
660enum GdbBreakpointType {
661 GdbSoftBp = '0',
662 GdbHardBp = '1',
663 GdbWriteWp = '2',
664 GdbReadWp = '3',
665 GdbAccWp = '4',
666};
667
668const char *
669BaseRemoteGDB::break_type(char c)
670{
671 switch(c) {
672 case GdbSoftBp: return "software breakpoint";
673 case GdbHardBp: return "hardware breakpoint";
674 case GdbWriteWp: return "write watchpoint";
675 case GdbReadWp: return "read watchpoint";
676 case GdbAccWp: return "access watchpoint";
677 default: return "unknown breakpoint/watchpoint";
678 }
679}
680
681std::map<char, GdbCommand> BaseRemoteGDB::command_map = {
682 // last signal
683 { '?', { "KGDB_SIGNAL", &BaseRemoteGDB::cmd_signal } },
684 // set baud (deprecated)
685 { 'b', { "KGDB_SET_BAUD", &BaseRemoteGDB::cmd_unsupported } },
686 // set breakpoint (deprecated)
687 { 'B', { "KGDB_SET_BREAK", &BaseRemoteGDB::cmd_unsupported } },
688 // resume
689 { 'c', { "KGDB_CONT", &BaseRemoteGDB::cmd_cont } },
690 // continue with signal
691 { 'C', { "KGDB_ASYNC_CONT", &BaseRemoteGDB::cmd_async_cont } },
692 // toggle debug flags (deprecated)
693 { 'd', { "KGDB_DEBUG", &BaseRemoteGDB::cmd_unsupported } },
694 // detach remote gdb
695 { 'D', { "KGDB_DETACH", &BaseRemoteGDB::cmd_detach } },
696 // read general registers
697 { 'g', { "KGDB_REG_R", &BaseRemoteGDB::cmd_reg_r } },
698 // write general registers
699 { 'G', { "KGDB_REG_W", &BaseRemoteGDB::cmd_reg_w } },
700 // set thread
701 { 'H', { "KGDB_SET_THREAD", &BaseRemoteGDB::cmd_set_thread } },
702 // step a single cycle
703 { 'i', { "KGDB_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
704 // signal then cycle step
705 { 'I', { "KGDB_SIG_CYCLE_STEP", &BaseRemoteGDB::cmd_unsupported } },
706 // kill program
707 { 'k', { "KGDB_KILL", &BaseRemoteGDB::cmd_detach } },
708 // read memory
709 { 'm', { "KGDB_MEM_R", &BaseRemoteGDB::cmd_mem_r } },
710 // write memory
711 { 'M', { "KGDB_MEM_W", &BaseRemoteGDB::cmd_mem_w } },
712 // read register
713 { 'p', { "KGDB_READ_REG", &BaseRemoteGDB::cmd_unsupported } },
714 // write register
715 { 'P', { "KGDB_SET_REG", &BaseRemoteGDB::cmd_unsupported } },
716 // query variable
717 { 'q', { "KGDB_QUERY_VAR", &BaseRemoteGDB::cmd_query_var } },
718 // set variable
719 { 'Q', { "KGDB_SET_VAR", &BaseRemoteGDB::cmd_unsupported } },
720 // reset system (deprecated)
721 { 'r', { "KGDB_RESET", &BaseRemoteGDB::cmd_unsupported } },
722 // step
723 { 's', { "KGDB_STEP", &BaseRemoteGDB::cmd_step } },
724 // signal and step
725 { 'S', { "KGDB_ASYNC_STEP", &BaseRemoteGDB::cmd_async_step } },
726 // find out if the thread is alive
727 { 'T', { "KGDB_THREAD_ALIVE", &BaseRemoteGDB::cmd_unsupported } },
728 // target exited
729 { 'W', { "KGDB_TARGET_EXIT", &BaseRemoteGDB::cmd_unsupported } },
730 // write memory
731 { 'X', { "KGDB_BINARY_DLOAD", &BaseRemoteGDB::cmd_unsupported } },
732 // remove breakpoint or watchpoint
733 { 'z', { "KGDB_CLR_HW_BKPT", &BaseRemoteGDB::cmd_clr_hw_bkpt } },
734 // insert breakpoint or watchpoint
735 { 'Z', { "KGDB_SET_HW_BKPT", &BaseRemoteGDB::cmd_set_hw_bkpt } },
736};
737
738
739bool
740BaseRemoteGDB::cmd_unsupported(GdbCommand::Context &ctx)
741{
742 DPRINTF(GDBMisc, "Unsupported command: %s\n", ctx.cmd->name);
743 DDUMP(GDBMisc, ctx.data, ctx.len);
744 throw Unsupported();
745}
746
747
748bool
749BaseRemoteGDB::cmd_signal(GdbCommand::Context &ctx)
750{
751 send(csprintf("S%02x", ctx.type).c_str());
752 return true;
753}
754
755bool
756BaseRemoteGDB::cmd_cont(GdbCommand::Context &ctx)
757{
758 const char *p = ctx.data;
759 if (ctx.len) {
760 Addr newPc = hex2i(&p);
761 context->pcState(newPc);
762 }
763 clearSingleStep();
764 return false;
765}
766
767bool
768BaseRemoteGDB::cmd_async_cont(GdbCommand::Context &ctx)
769{
770 const char *p = ctx.data;
771 hex2i(&p);
772 if (*p++ == ';') {
773 Addr newPc = hex2i(&p);
774 context->pcState(newPc);
775 }
776 clearSingleStep();
777 return false;
778}
779
780bool
781BaseRemoteGDB::cmd_detach(GdbCommand::Context &ctx)
782{
783 detach();
784 return false;
785}
786
787bool
788BaseRemoteGDB::cmd_reg_r(GdbCommand::Context &ctx)
789{
790 char buf[2 * regCachePtr->size() + 1];
791 buf[2 * regCachePtr->size()] = '\0';
792 mem2hex(buf, regCachePtr->data(), regCachePtr->size());
793 send(buf);
794 return true;
795}
796
797bool
798BaseRemoteGDB::cmd_reg_w(GdbCommand::Context &ctx)
799{
800 const char *p = ctx.data;
801 p = hex2mem(regCachePtr->data(), p, regCachePtr->size());
802 if (p == NULL || *p != '\0')
803 throw CmdError("E01");
804
805 regCachePtr->setRegs(context);
806 send("OK");
807
808 return true;
809}
810
811bool
812BaseRemoteGDB::cmd_set_thread(GdbCommand::Context &ctx)
813{
814 const char *p = ctx.data + 1; // Ignore the subcommand byte.
815 if (hex2i(&p) != 0)
816 throw CmdError("E01");
817 send("OK");
818 return true;
819}
820
821bool
822BaseRemoteGDB::cmd_mem_r(GdbCommand::Context &ctx)
823{
824 const char *p = ctx.data;
825 Addr addr = hex2i(&p);
826 if (*p++ != ',')
827 throw CmdError("E02");
828 size_t len = hex2i(&p);
829 if (*p != '\0')
830 throw CmdError("E03");
831 if (!acc(addr, len))
832 throw CmdError("E05");
833
834 char buf[len];
835 if (!read(addr, len, buf))
836 throw CmdError("E05");
837
838 char temp[2 * len + 1];
839 temp[2 * len] = '\0';
840 mem2hex(temp, buf, len);
841 send(temp);
842 return true;
843}
844
845bool
846BaseRemoteGDB::cmd_mem_w(GdbCommand::Context &ctx)
847{
848 const char *p = ctx.data;
849 Addr addr = hex2i(&p);
850 if (*p++ != ',')
851 throw CmdError("E06");
852 size_t len = hex2i(&p);
853 if (*p++ != ':')
854 throw CmdError("E07");
855 if (len * 2 > ctx.len - (p - ctx.data))
856 throw CmdError("E08");
857 char buf[len];
858 p = (char *)hex2mem(buf, p, len);
859 if (p == NULL)
860 throw CmdError("E09");
861 if (!acc(addr, len))
862 throw CmdError("E0A");
863 if (!write(addr, len, buf))
864 throw CmdError("E0B");
865 send("OK");
866 return true;
867}
868
869bool
870BaseRemoteGDB::cmd_query_var(GdbCommand::Context &ctx)
871{
872 if (string(ctx.data, ctx.len - 1) != "C")
873 throw Unsupported();
874 send("QC0");
875 return true;
876}
877
878bool
879BaseRemoteGDB::cmd_async_step(GdbCommand::Context &ctx)
880{
881 const char *p = ctx.data;
882 hex2i(&p); // Ignore the subcommand byte.
883 if (*p++ == ';') {
884 Addr newPc = hex2i(&p);
885 context->pcState(newPc);
886 }
887 setSingleStep();
888 return false;
889}
890
891bool
892BaseRemoteGDB::cmd_step(GdbCommand::Context &ctx)
893{
894 if (ctx.len) {
895 const char *p = ctx.data;
896 Addr newPc = hex2i(&p);
897 context->pcState(newPc);
898 }
899 setSingleStep();
900 return false;
901}
902
903bool
904BaseRemoteGDB::cmd_clr_hw_bkpt(GdbCommand::Context &ctx)
905{
906 const char *p = ctx.data;
907 char subcmd = *p++;
908 if (*p++ != ',')
909 throw CmdError("E0D");
910 Addr addr = hex2i(&p);
911 if (*p++ != ',')
912 throw CmdError("E0D");
913 size_t len = hex2i(&p);
914
915 DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
916 break_type(subcmd), addr, len);
917
918 switch (subcmd) {
919 case GdbSoftBp:
920 removeSoftBreak(addr, len);
921 break;
922 case GdbHardBp:
923 removeHardBreak(addr, len);
924 break;
925 case GdbWriteWp:
926 case GdbReadWp:
927 case GdbAccWp:
928 default: // unknown
929 throw Unsupported();
930 }
931 send("OK");
932
933 return true;
934}
935
936bool
937BaseRemoteGDB::cmd_set_hw_bkpt(GdbCommand::Context &ctx)
938{
939 const char *p = ctx.data;
940 char subcmd = *p++;
941 if (*p++ != ',')
942 throw CmdError("E0D");
943 Addr addr = hex2i(&p);
944 if (*p++ != ',')
945 throw CmdError("E0D");
946 size_t len = hex2i(&p);
947
948 DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
949 break_type(subcmd), addr, len);
950
951 switch (subcmd) {
952 case GdbSoftBp:
953 insertSoftBreak(addr, len);
954 break;
955 case GdbHardBp:
956 insertHardBreak(addr, len);
957 break;
958 case GdbWriteWp:
959 case GdbReadWp:
960 case GdbAccWp:
961 default: // unknown
962 throw Unsupported();
963 }
964 send("OK");
965
966 return true;
967}
968
969
970// This function does all command processing for interfacing to a
971// remote gdb. Note that the error codes are ignored by gdb at
972// present, but might eventually become meaningful. (XXX) It might
973// makes sense to use POSIX errno values, because that is what the
974// gdb/remote.c functions want to return.
975bool
976BaseRemoteGDB::trap(int type)
977{
978
979 if (!attached)
980 return false;
981
982 DPRINTF(GDBMisc, "trap: PC=%s\n", context->pcState());
983
984 clearSingleStep();
985
986 /*
987 * The first entry to this function is normally through
988 * a breakpoint trap in kgdb_connect(), in which case we
989 * must advance past the breakpoint because gdb will not.
990 *
991 * On the first entry here, we expect that gdb is not yet
992 * listening to us, so just enter the interaction loop.
993 * After the debugger is "active" (connected) it will be
994 * waiting for a "signaled" message from us.
995 */
996 if (!active) {
997 active = true;
998 } else {
999 // Tell remote host that an exception has occurred.
1000 send(csprintf("S%02x", type).c_str());
1001 }
1002
1003 // Stick frame regs into our reg cache.
1004 regCachePtr = gdbRegs();
1005 regCachePtr->getRegs(context);
1006
1007 char data[GDBPacketBufLen + 1];
1008 GdbCommand::Context cmdCtx;
1009 cmdCtx.type = type;
1010 cmdCtx.data = &data[1];
1011
1012 for (;;) {
1013 try {
1014 size_t datalen = recv(data, sizeof(data));
1015 if (datalen < 1)
1016 throw BadClient();
1017
1018 data[datalen] = 0; // Sentinel
1019 cmdCtx.cmd_byte = data[0];
1020 cmdCtx.len = datalen - 1;
1021
1022 auto cmdIt = command_map.find(cmdCtx.cmd_byte);
1023 if (cmdIt == command_map.end()) {
1024 DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
1025 cmdCtx.cmd_byte, cmdCtx.cmd_byte);
1026 throw Unsupported();
1027 }
1028 cmdCtx.cmd = &(cmdIt->second);
1029
1030 if (!(this->*(cmdCtx.cmd->func))(cmdCtx))
1031 break;
1032
1033 } catch (BadClient &e) {
1034 if (e.warning)
1035 warn(e.warning);
1036 detach();
1037 break;
1038 } catch (Unsupported &e) {
1039 send("");
1040 } catch (CmdError &e) {
1041 send(e.error.c_str());
1042 } catch (...) {
1043 panic("Unrecognzied GDB exception.");
1044 }
1045 }
1046
1047 return true;
1048}
1049
1050// Convert a hex digit into an integer.
1051// This returns -1 if the argument passed is no valid hex digit.
1052int
1053BaseRemoteGDB::digit2i(char c)
1054{
1055 if (c >= '0' && c <= '9')
1056 return (c - '0');
1057 else if (c >= 'a' && c <= 'f')
1058 return (c - 'a' + 10);
1059 else if (c >= 'A' && c <= 'F')
1060 return (c - 'A' + 10);
1061 else
1062 return (-1);
1063}
1064
1065// Convert the low 4 bits of an integer into an hex digit.
1066char
1067BaseRemoteGDB::i2digit(int n)
1068{
1069 return ("0123456789abcdef"[n & 0x0f]);
1070}
1071
1072// Convert a byte array into an hex string.
1073void
1074BaseRemoteGDB::mem2hex(char *vdst, const char *vsrc, int len)
1075{
1076 char *dst = vdst;
1077 const char *src = vsrc;
1078
1079 while (len--) {
1080 *dst++ = i2digit(*src >> 4);
1081 *dst++ = i2digit(*src++);
1082 }
1083 *dst = '\0';
1084}
1085
1086// Convert an hex string into a byte array.
1087// This returns a pointer to the character following the last valid
1088// hex digit. If the string ends in the middle of a byte, NULL is
1089// returned.
1090const char *
1091BaseRemoteGDB::hex2mem(char *vdst, const char *src, int maxlen)
1092{
1093 char *dst = vdst;
1094 int msb, lsb;
1095
1096 while (*src && maxlen--) {
1097 msb = digit2i(*src++);
1098 if (msb < 0)
1099 return (src - 1);
1100 lsb = digit2i(*src++);
1101 if (lsb < 0)
1102 return (NULL);
1103 *dst++ = (msb << 4) | lsb;
1104 }
1105 return src;
1106}
1107
1108// Convert an hex string into an integer.
1109// This returns a pointer to the character following the last valid
1110// hex digit.
1111Addr
1112BaseRemoteGDB::hex2i(const char **srcp)
1113{
1114 const char *src = *srcp;
1115 Addr r = 0;
1116 int nibble;
1117
1118 while ((nibble = digit2i(*src)) >= 0) {
1119 r *= 16;
1120 r += nibble;
1121 src++;
1122 }
1123 *srcp = src;
1124 return r;
1125}
1126