]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/gdb_stub/gdb.cc
update
[l4.git] / l4 / pkg / plr / server / src / gdb_stub / gdb.cc
1 /*
2  * gdb_stub/gdb.cc --
3  *
4  *     GDB stub implemented on top of the Romain framework
5  *
6  * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
7  *     economic rights: Technische Universität Dresden (Germany)
8  * This file is part of TUD:OS and distributed under the terms of the
9  * GNU General Public License 2.
10  * Please see the COPYING-GPL-2 file for details.
11  */
12
13 #include <stddef.h>
14 #include <l4/sys/thread>
15 #include <l4/util/util.h>
16 #include <string.h>
17
18 #include "../app_loading"
19 #include "gdbserver"
20 #include "lwip/inet.h"
21
22 #define GDB_BYTE_FORMAT(reg) ntohl((unsigned int)(reg))
23 #define SAVED_VCPU_REGS _saved_vcpu.r()
24
25 #define MSG() DEBUGf(Romain::Log::Gdb)
26
27 /*
28  * put a reply into the packet buffer
29  */
30 #define REPLY_PACKET(fmt, ...) \
31         do { \
32                 snprintf(_outbuf, sizeof(_outbuf), \
33                                  "$"fmt, ##__VA_ARGS__); \
34                 append_checksum(_outbuf+1); \
35                 MSG() << "\033[36;1m'" << _outbuf << "'\033[0m"; \
36         } while (0)
37
38 /*
39  * For any command not supported by the stub, an empty response (`$#00')
40  * should be returned. That way it is possible to extend the protocol.
41  * A newer GDB can tell if a packet is supported based on that response.
42  */
43 #define UNSUPPORTED() REPLY_PACKET("")
44
45 #define REPLY_OK REPLY_PACKET("OK");
46
47 extern struct netif ankh_netif;
48
49 void Romain::GDBServerObserver::status() const { }
50
51 /*
52  * GDB stub thread. Simply waits for commands to come in from the net and
53  * handles them. This handling requires synchronization with the other threads,
54  * which is done through internal signalling.
55  */
56 static void *gdb_stub_thread(void* data)
57 {
58         INFO() << "GDB Stub thread running.";
59
60         Romain::GDBServerObserver *stub = (Romain::GDBServerObserver*)data;
61
62         stub->connection()->setup_and_wait();
63         stub->notify_connect();
64
65         for (;;) {
66                 memset(stub->buffer(), 0, stub->maxbuffer());
67                 int num_bytes = stub->connection()->wait_for_cmd(stub->buffer(), stub->maxbuffer());
68                 if (num_bytes < 0) {
69                         stub->disconnect();
70                         stub->connection()->setup_and_wait();
71                         continue;
72                 }
73
74                 while (stub->handle_cmd() > 0)
75                         ;
76         }
77
78         return 0;
79 }
80
81
82 Romain::GDBServerObserver::GDBServerObserver(Connection* con)
83         : _con(con),
84           _connected(false),
85           _ack_mode(true),
86           _await_ack(true), // GDB sends an ACK first!
87           _bufptr(0),
88           _app_model(0),
89           _want_halt(true),
90           _singlestep(false)
91 {
92         int r;
93         
94         memset(_inbuf, 0, sizeof(_inbuf));
95         memset(_outbuf, 0, sizeof(_outbuf));
96         memset(_last_cmd, 0, sizeof(_last_cmd));
97         memset(&_saved_vcpu, 0, sizeof(_saved_vcpu));
98
99         r = sem_init(&_app_wait_signal, 0, 0);
100         _check(r != 0, "sem_init");
101         r = sem_init(&_gdb_wait_signal, 0, 0);
102         _check(r != 0, "sem_init");
103
104         r = pthread_create(&_thread, 0, gdb_stub_thread, this);
105         _check(r != 0, "pthread_create()");
106 }
107
108
109 Romain::GDBServerObserver::~GDBServerObserver()
110 {
111 }
112
113
114 /*
115  * Startup notification. We know that the first thread has been started and thus
116  * obtain an IP through DHCP and wait for a remote GDB to connect.
117  */
118 void Romain::GDBServerObserver::startup_notify(Romain::App_instance *,
119                                                Romain::App_thread *,
120                                                Romain::Thread_group *,
121                                                Romain::App_model *a)
122 {
123         _app_model = a;
124
125         while (!_connected) {
126                 INFO() << "waiting for GDB to connect...";
127                 sem_wait(&_app_wait_signal);
128         }
129 }
130
131
132 /*
133  * Trap notification.
134  */
135 Romain::Observer::ObserverReturnVal
136 Romain::GDBServerObserver::notify(Romain::App_instance *,
137                                   Romain::App_thread *t,
138                                   Romain::Thread_group *,
139                                   Romain::App_model *)
140 {
141 #if 0
142         MSG() << "want halt: " << _want_halt
143               << " trap: " << t->vcpu()->r()->trapno
144               << " pending: 0x" << std::hex << t->get_pending_trap();
145 #endif
146
147         /*
148          * Only handle traps 1 & 3. But we use _any_ trap notification
149          * to force the target thread into the debugger, e.g., in the
150          * case of an interrupt.
151          */
152         if (!t->events_pending() &&
153                 (t->vcpu()->r()->trapno != 1) &&
154                 (t->vcpu()->r()->trapno != 3)) {
155                 if (_want_halt) {
156                         t->set_pending_trap(3);
157                 }
158                 return Romain::Observer::Ignored;
159         }
160
161         save_vcpu(t);
162         
163         if (_want_halt) {
164                 _want_halt = false;
165         }
166
167         //MSG() << "received HLT from GDB. Waiting for command.";
168         notify_and_wait(&_gdb_wait_signal, &_app_wait_signal);
169
170         restore_vcpu(t);
171
172         return Romain::Observer::Continue;
173 }
174
175
176 /*
177  * Verify a GDB packet checksum, which by its definition is
178  * a sum of all text characters in the packet modulo 256.
179  */
180 bool Romain::GDBServerObserver::checksum_cmd(char const * const ptr, char const **end)
181 {
182         char const *c = ptr;
183         unsigned sum = 0;
184
185         for ( ; *c != '#'; sum += *c++)
186                 ;
187
188         *end = c;
189         return (sum & 0xff) == (unsigned)strtol(c+1, 0, 16);
190 }
191
192
193 /*
194  * Append checksum to a GDB packet.
195  */
196 void Romain::GDBServerObserver::append_checksum(char *p)
197 {
198         unsigned csum = 0;
199         while (*p != 0)
200                 csum += *p++;
201         snprintf(p, 4, "#%02x", csum & 0xFF);
202 }
203
204
205 bool Romain::GDBServerObserver::next_cmd()
206 {
207         /* New content in packet buf? */
208         if (!_bufptr) {
209                 _bufptr = _inbuf;
210         }
211
212         /* Out of buffer? */
213         if (_bufptr - _last_cmd > 1024) { // XXX
214                 _bufptr = 0;
215                 return false;
216         }
217
218         switch (*_bufptr) {
219                 case NoCmd: // end of read buffer
220                         //MSG() << "EOR";
221                         _bufptr = 0;
222                         return false;
223
224                 case GDBInterrupt:
225                         enter_kdebug("interrupt");
226                         break;
227
228                 case GDBAck:
229                         if (_await_ack) {
230                                 _await_ack = false;
231                                 ++_bufptr;
232                         } else {
233                                 MSG() << "Got ACK while not expecting one!";
234                                 ++_bufptr;
235                                 //enter_kdebug("ACK");
236                         }
237                         return next_cmd();
238
239                 case GDBRetry:
240                         // the last cmd is still in _last_cmd, so just
241                         // get back to it
242                         return true;
243
244                 case GDBCmdStart:
245                         _bufptr++; // skip the $ sign
246                         break;
247
248                 default:
249                         ERROR() << "invalid packet start: " << *_bufptr;
250                         enter_kdebug("error");
251                         break;
252         }
253
254         char const *eoc = 0;
255         if (!checksum_cmd(_bufptr, &eoc)) {
256                 ERROR() << "Wrong checksum.";
257                 enter_kdebug("csum");
258         }
259
260         _check(eoc - _bufptr <= 0, "cmd with 0 or negative size");
261
262         memset(_last_cmd, 0, sizeof(_last_cmd));
263         memcpy(_last_cmd, _bufptr, eoc - _bufptr);
264
265         // set bufptr to _after_ the current cmd. this is where
266         // we start searching for the next cmd then
267         _bufptr = const_cast<char*>(eoc) + 3; // # + 2 bytes checksum == 3
268
269         if (_ack_mode) {
270                 _check(_con->senddata("+", 2) != 2, "send ack");
271         }
272
273         return true;
274 }
275
276
277 /*
278  * GDB command dispatcher.
279  */
280 int Romain::GDBServerObserver::handle_cmd()
281 {
282         if (!next_cmd())
283                 return 0;
284
285         MSG() << "Need to handle cmd "
286               << "\033[35m" << _last_cmd << "\033[0m";
287
288         char *cmd = _last_cmd;
289
290         switch (*cmd) {
291                 case 'g': gdb_get_registers(cmd+1); break;
292                 case 'p': gdb_read_register(cmd+1); break;
293                 case 'P': gdb_write_register(cmd+1); break;
294
295                 case 'm': gdb_dump_mem(cmd+1); break;
296                 case 'M': gdb_write_mem(cmd+1, false); break;
297                 case 'H': gdb_select_thread(cmd+1); break;
298                 case 'k': disconnect(); return -1;
299                 case 'q': gdb_query(cmd+1); break;
300                 case 'Q': gdb_settings(cmd+1); break;
301
302                 case 'S': gdb_step(cmd+1, true); break;
303                 case 's': gdb_step(cmd+1, false); break;
304                 case 'C': gdb_continue(cmd+1, true); break;
305                 case 'c': gdb_continue(cmd+1, false); break;
306
307                 case 'v':
308                         if (strcmp(cmd, "vCont?") == 0)
309                                 UNSUPPORTED();
310                         break;
311
312                 case 'X': gdb_write_mem(cmd+1, true); break;
313                 case 'Z': gdb_breakpoint(cmd+1); break;
314
315                 /*
316                  * Queries the last stop reason. Initially, we return TARGET_SIGNAL_DEFAULT - 0x90
317                  * TODO: implement
318                  */
319                 case '?': REPLY_PACKET("S90"); break;
320                 
321                 default:
322                           INFO() << "Unhandled GDB command: " << cmd;
323                           enter_kdebug("Unhandled cmd");
324                           break;
325         }
326
327         _await_ack = _ack_mode;
328         int err    = _con->senddata(_outbuf, strlen(_outbuf));
329         _check(err <= 0, "send reply");
330
331         return 1;
332 }
333
334
335 /*
336  * Handle GDB settings modification.
337  *
338  * We only support StartNoAckMode so far.
339  */
340 void Romain::GDBServerObserver::gdb_settings(char const * const cmd)
341 {
342         //MSG() << "Q: " << cmd;
343
344         if (strcmp(cmd, "StartNoAckMode") == 0) {
345                 _ack_mode = false;
346                 REPLY_OK;
347         }
348         else {
349                 MSG() << "Unsupported Q cmd: " << cmd;
350                 UNSUPPORTED();
351         }
352 }
353
354
355 /*
356  * Handle remote query.
357  *
358  * Currently only returns supported features.
359  */
360 void Romain::GDBServerObserver::gdb_query(char const * const cmd)
361 {
362         //MSG() << "CMD: " << cmd;
363
364         if (strncmp(cmd, "Supported", (size_t)9) == 0) // feature query
365                 REPLY_PACKET("PacketSize=%d;QStartNoAckMode+;", sizeof(_outbuf));
366         else if (strncmp(cmd, "Symbol::", 8) == 0) {
367                 REPLY_OK;
368         }
369         else {
370                 MSG() << "Unsupported query cmd: " << cmd;
371                 UNSUPPORTED();
372         }
373 }
374
375
376 /*
377  * `H c thread-id' : Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
378  *    c depends on the operation to be performed: it should be `c' for step and continue
379  *    operations, `g' for other operations. The thread designator thread-id has the format
380  *    and interpretation described in thread-id syntax.
381  *
382  * Reply:
383  *  `OK'    for success
384  *  `E NN'  for an error
385  */
386 void Romain::GDBServerObserver::gdb_select_thread(char const * const cmd)
387 {
388         (void)cmd;
389         //MSG() << "CMD: " << cmd;
390
391 #if 0
392         if (*cmd == 'g') {
393             if (atoi(cmd+1) > 0) {
394                 ERROR() << "g cmd for thread" << atoi(cmd+1);
395                 enter_kdebug();
396             }
397                 REPLY_OK;
398         }
399         else if (*cmd == 'c') {
400         if (atoi(cmd+1) > 0) {
401                         ERROR() << "c cmd for thread" << atoi(cmd+1);
402                         enter_kdebug();
403             }
404             UNSUPPORTED();
405         }
406         else {
407                 ERROR() << "Unsupported H cmd: " << cmd;
408                 UNSUPPORTED();
409         }
410 #endif
411         UNSUPPORTED();
412 }
413
414
415 /*
416  * `g' Read general registers.
417  *
418  * Reply:
419  *
420  * `XX...'   Each byte of register data is described by two hex digits. The bytes
421  *           with the register are transmitted in target byte order. The size of
422  *           each register and their position within the `g' packet are determined
423  *           by the gdb internal gdbarch functions DEPRECATED_REGISTER_RAW_SIZE and
424  *           gdbarch_register_name. The specification of several standard `g'
425  *           packets is specified below.
426  *
427  * `E NN'    for an error.
428  */
429 void Romain::GDBServerObserver::gdb_get_registers(char const * const)
430 {
431         REPLY_PACKET("%08x%08x%08x%08x%08x%08x%08x%08x"
432                      "%08x%08x%08x%08x%08x%08x%08x%08x",
433                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->ax),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->cx),
434                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->dx),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->bx),
435                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->sp),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->bp),
436                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->si),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->di),
437                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->ip),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->flags),
438                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->dummy1), GDB_BYTE_FORMAT(SAVED_VCPU_REGS->ss),
439                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->ds),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->es),
440                      GDB_BYTE_FORMAT(SAVED_VCPU_REGS->fs),     GDB_BYTE_FORMAT(SAVED_VCPU_REGS->gs));
441 }
442
443 /*
444  * `m addr,length' Read length bytes of memory starting at address addr. Note that addr
445  *                 may not be aligned to any particular boundary. The stub need not use
446  *                 any particular size or alignment when gathering data from memory for
447  *                 the response; even if addr is word-aligned and length is a multiple of
448  *                 the word size, the stub is free to use byte accesses, or not. For this
449  *                 reason, this packet may not be suitable for accessing memory-mapped I/O
450  *                 devices.
451  *
452  * Reply:
453  *  `XX…' Memory contents; each byte is transmitted as a two-digit hexadecimal number. The
454  *        reply may contain fewer bytes than requested if the server was able to read only
455  *        part of the region of memory.
456  *
457  * `E NN' NN is errno
458  */
459 void Romain::GDBServerObserver::gdb_dump_mem(char const * const cmd)
460 {
461         unsigned addr, len;
462
463         if (sscanf(cmd, "%x,%x", &addr, &len) != 2) {
464                 ERROR() << "Incorrectly matching memory read cmd: " << cmd;
465                 enter_kdebug();
466         }
467
468         // XXX: so far we only support the gdb stub for the first running
469         //      instance XXX multi-instance support?
470         l4_addr_t local_addr = _app_model->rm()->remote_to_local(addr, 0);
471         if (local_addr == ~0UL) // nothing mapped?
472                 REPLY_PACKET("");
473         else {
474
475                 /*
476                  * Validate buffer length. The memory dump may cross a page boundary
477                  * and the next page might not be attached at all. To avoid unhandled
478                  * page faults here, we check the end address and if it does not resolve
479                  * successfully, we cut the length until the end of the first page.
480                  *
481                  * This assumes that GDB will never try to dump more than a page or even
482                  * regions with pages unmapped in between.
483                  */
484                 if (l4_trunc_page(local_addr) != l4_trunc_page(local_addr + len)) {
485                         // XXX: so far we only support the gdb stub for the first running
486                         //      instance XXX multi-instance support?
487                         l4_addr_t end_addr = _app_model->rm()->remote_to_local(local_addr + len, 0);
488                         if (end_addr == ~0UL) {
489                                 len = l4_round_page(local_addr) - local_addr;
490                         }
491                 }
492
493                 //MSG() << "local @ " << (void*)local_addr;
494                 _outbuf[0] = '$';
495                 // we print 2 characters at a time - representing one byte in hex; as long
496                 // as the length field tells us
497                 for (unsigned i = 0; i < len; ++i) {
498                         char *start = &_outbuf[1];
499                         start += 2*i;
500                         //MSG() << (void*)start << " <-> " << std::hex << (int)*(unsigned char*)(local_addr + i);
501                         snprintf(start, 3, "%02x", *(unsigned char*)(local_addr + i));
502                 }
503                 append_checksum(_outbuf+1);
504                 MSG() << "\033[36;1m'" << _outbuf << "'\033[0m";
505         }
506 }
507
508
509 void Romain::GDBServerObserver::gdb_continue(const char* cmd, bool withSignal)
510 {
511         /* XXX
512          * For the signal case, we simply assume for now that we are continuing
513          * from the last signal, in which case the command behaves the same as with
514          * no signal specified. Later, we should verify this.
515          * XXX */
516         if (withSignal || (strlen(cmd) == 0)) {
517                 // disable single-stepping just in case it was enabled
518                 _singlestep = false;
519                 SAVED_VCPU_REGS->flags &= ~(1 << 8);
520                 notify_and_wait(&_app_wait_signal, &_gdb_wait_signal);
521
522                 signal_return(/*_notifyThread*/);
523         } else {
524                 ERROR() << "continue from address? " << cmd;
525                 enter_kdebug("c");
526         }
527 }
528
529
530 void Romain::GDBServerObserver::gdb_step(const char* cmd, bool withSignal)
531 {
532         _want_halt = false;
533         if ((!withSignal && (strlen(cmd) == 0)) || 
534                 ( withSignal && (strcmp(cmd, "90") == 0))) {
535                 _singlestep = true;
536                 SAVED_VCPU_REGS->flags |= (1 << 8);
537
538                 notify_and_wait(&_app_wait_signal, &_gdb_wait_signal);
539                 signal_return(/*_notifyThread*/);
540         } else {
541                 printf("step: '%s'\n", cmd);
542                 ERROR() << "step from address not implemented!";
543                 enter_kdebug();
544         }
545 }
546
547
548 void Romain::GDBServerObserver::gdb_breakpoint(char const* cmd)
549 {
550         (void)cmd;
551         // XXX Handle breakpoints
552         UNSUPPORTED();
553 }
554
555
556 void Romain::GDBServerObserver::gdb_write_mem(char const* cmd, bool binaryData)
557 {
558         unsigned addr, len;
559         if (sscanf(cmd, "%x,%x", &addr, &len) != 2) {
560                 ERROR() << "Invalid memory write cmd: " << cmd;
561                 enter_kdebug();
562         }
563
564         if (!len) { // nothing to do
565                 REPLY_OK;
566                 return;
567         }
568
569         // XXX: so far we only support the gdb stub for the first running
570         //      instance XXX multi-instance support?
571         l4_addr_t local_addr = _app_model->rm()->remote_to_local(addr, 0);
572         MSG() << "local: " << std::hex << (void*)local_addr;
573         if (local_addr == ~0UL) {// nothing mapped?
574                 REPLY_PACKET("");
575         } else {
576                 unsigned char const* data_start;
577                 unsigned char const* data_end;
578                 unsigned char const *c = (unsigned char const*)cmd;
579
580                 MSG() << "local value: " << std::hex << *(unsigned char*)local_addr;
581                 // find first data byte
582                 while (*c != ':')
583                         ++c;
584                 data_start = ++c;
585
586                 // find last data byte
587                 // (note: dispatcher already removed the # before)
588                 while (*c != 0)
589                         ++c;
590                 data_end = c-1;
591
592 #if 0
593                 MSG() << "data start @ " << (void*)data_start
594                       << " data end @ "  << (void*)data_end
595                       << " cmd @ " << (void*)cmd;
596 #endif
597
598                 if (binaryData) {
599 #if 0
600                         for (c = data_start; c <= data_end; ++c) {
601                                 printf("%02X ", *c);
602                         }
603                         printf("\n");
604 #endif
605                         if ((unsigned)(data_end - data_start + 1) > len) {
606                                 ERROR() << "Packet says it contains more data than it really does?";
607                                 enter_kdebug();
608                         }
609                         
610                         MSG() << "memcpy(" << (void*)local_addr << ", "
611                                 << (void*)data_start << ", " << len << ");";
612                         memcpy((char*)local_addr, data_start, len);
613                 } else {
614                         enter_kdebug("M write");
615                 }
616
617                 REPLY_OK;
618         }
619 }
620
621
622 void Romain::GDBServerObserver::gdb_read_register(char const* cmd)
623 {
624         (void)cmd;
625         enter_kdebug("read_register");
626         UNSUPPORTED();
627 }
628
629
630 /*
631  * Write register n... with value r.... The register number n is in
632  * hexadecimal, and r... contains two hex digits for each byte in the register
633  * (target byte order).
634  *
635  * Reply:
636  *
637  * `OK'     for success
638  * `E NN'   for an error
639  */
640 void Romain::GDBServerObserver::gdb_write_register(char const *cmd)
641 {
642         unsigned regno, value;
643         MSG() << "write register: " << cmd;
644         sscanf(cmd, "%x=%x", &regno, &value);
645         MSG() << std::hex << value << " " << ntohl(value);
646
647         switch(regno) {
648 #define REGCASE(r) case Romain::r: SAVED_VCPU_REGS->r = ntohl(value); break
649
650                 REGCASE(ax); REGCASE(bx); REGCASE(cx); REGCASE(dx);
651                 REGCASE(sp); REGCASE(ip); REGCASE(flags);
652                 REGCASE(ss); REGCASE(ds); REGCASE(es); REGCASE(fs);
653                 REGCASE(gs);
654 #undef REGCASE
655
656                 default:
657                         MSG() << "Unhandled reg number: " << regno;
658                         //enter_kdebug("P");
659                         break;
660         }
661         REPLY_PACKET("OK");
662 }
663
664
665 void Romain::GDBServerObserver::signal_return(Romain::App_thread *t) {
666         if (!t) t = _notifyThread;
667
668         if (t->unhandled_pf()) {
669                 REPLY_PACKET("S0B"); // SEGV
670         } else {
671                 REPLY_PACKET("S05"); // Breakpoint trap
672         }
673 }