cd7e327f22a7054c4e3d6ebae8de88141f394e6d
[openocd.git] / src / server / gdb_server.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25
26 #include "gdb_server.h"
27
28 #include "server.h"
29 #include "log.h"
30 #include "binarybuffer.h"
31 #include "breakpoints.h"
32 #include "flash.h"
33 #include "target_request.h"
34
35 #define __USE_GNU
36 #include <string.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40
41 #if 0
42 #define _DEBUG_GDB_IO_
43 #endif
44
45 static unsigned short gdb_port;
46
47 enum gdb_detach_mode
48 {
49 GDB_DETACH_RESUME,
50 GDB_DETACH_RESET,
51 GDB_DETACH_HALT,
52 GDB_DETACH_NOTHING
53 };
54
55 enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
56
57 int gdb_last_signal(target_t *target)
58 {
59 switch (target->debug_reason)
60 {
61 case DBG_REASON_DBGRQ:
62 return 0x2; /* SIGINT */
63 case DBG_REASON_BREAKPOINT:
64 case DBG_REASON_WATCHPOINT:
65 case DBG_REASON_WPTANDBKPT:
66 return 0x05; /* SIGTRAP */
67 case DBG_REASON_SINGLESTEP:
68 return 0x05; /* SIGTRAP */
69 case DBG_REASON_NOTHALTED:
70 return 0x0; /* no signal... shouldn't happen */
71 default:
72 ERROR("BUG: undefined debug reason");
73 exit(-1);
74 }
75 }
76
77 int gdb_get_char(connection_t *connection, int* next_char)
78 {
79 gdb_connection_t *gdb_con = connection->priv;
80 char *debug_buffer;
81
82 if (gdb_con->buf_cnt-- > 0)
83 {
84 *next_char = *(gdb_con->buf_p++);
85 if (gdb_con->buf_cnt > 0)
86 connection->input_pending = 1;
87 else
88 connection->input_pending = 0;
89
90 #ifdef _DEBUG_GDB_IO_
91 DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
92 #endif
93
94 return ERROR_OK;
95 }
96
97 while ((gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE)) <= 0)
98 {
99 if (gdb_con->buf_cnt == 0)
100 return ERROR_SERVER_REMOTE_CLOSED;
101
102 #ifdef _WIN32
103 errno = WSAGetLastError();
104
105 switch(errno)
106 {
107 case WSAEWOULDBLOCK:
108 usleep(1000);
109 break;
110 case WSAECONNABORTED:
111 return ERROR_SERVER_REMOTE_CLOSED;
112 default:
113 ERROR("read: %d", errno);
114 exit(-1);
115 }
116 #else
117 switch(errno)
118 {
119 case EAGAIN:
120 usleep(1000);
121 break;
122 case ECONNABORTED:
123 return ERROR_SERVER_REMOTE_CLOSED;
124 case ECONNRESET:
125 return ERROR_SERVER_REMOTE_CLOSED;
126 default:
127 ERROR("read: %s", strerror(errno));
128 exit(-1);
129 }
130 #endif
131 }
132
133 debug_buffer = malloc(gdb_con->buf_cnt + 1);
134 memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
135 debug_buffer[gdb_con->buf_cnt] = 0;
136 DEBUG("received '%s'", debug_buffer);
137 free(debug_buffer);
138
139 gdb_con->buf_p = gdb_con->buffer;
140 gdb_con->buf_cnt--;
141 *next_char = *(gdb_con->buf_p++);
142 if (gdb_con->buf_cnt > 0)
143 connection->input_pending = 1;
144 else
145 connection->input_pending = 0;
146 #ifdef _DEBUG_GDB_IO_
147 DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
148 #endif
149
150 return ERROR_OK;
151 }
152
153 int gdb_putback_char(connection_t *connection, int last_char)
154 {
155 gdb_connection_t *gdb_con = connection->priv;
156
157 if (gdb_con->buf_p > gdb_con->buffer)
158 {
159 *(--gdb_con->buf_p) = last_char;
160 gdb_con->buf_cnt++;
161 }
162 else
163 {
164 ERROR("BUG: couldn't put character back");
165 }
166
167 return ERROR_OK;
168 }
169
170 int gdb_put_packet(connection_t *connection, char *buffer, int len)
171 {
172 int i;
173 unsigned char my_checksum = 0;
174 char checksum[3];
175 char *debug_buffer;
176 int reply;
177 int retval;
178 gdb_connection_t *gdb_con = connection->priv;
179
180 for (i = 0; i < len; i++)
181 my_checksum += buffer[i];
182
183 while (1)
184 {
185 debug_buffer = malloc(len + 1);
186 memcpy(debug_buffer, buffer, len);
187 debug_buffer[len] = 0;
188 DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
189 free(debug_buffer);
190
191 write_socket(connection->fd, "$", 1);
192 if (len > 0)
193 write_socket(connection->fd, buffer, len);
194 write_socket(connection->fd, "#", 1);
195
196 snprintf(checksum, 3, "%2.2x", my_checksum);
197
198 write_socket(connection->fd, checksum, 2);
199
200 if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
201 return retval;
202
203 if (reply == '+')
204 break;
205 else if (reply == '-')
206 WARNING("negative reply, retrying");
207 else if (reply == 0x3)
208 {
209 gdb_con->ctrl_c = 1;
210 if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
211 return retval;
212 if (reply == '+')
213 break;
214 else if (reply == '-')
215 WARNING("negative reply, retrying");
216 else
217 {
218 ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
219 return ERROR_SERVER_REMOTE_CLOSED;
220 }
221 }
222 else
223 {
224 ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
225 return ERROR_SERVER_REMOTE_CLOSED;
226 }
227 }
228
229 return ERROR_OK;
230 }
231
232 int gdb_get_packet(connection_t *connection, char *buffer, int *len)
233 {
234 int character;
235 int count = 0;
236 int retval;
237 char checksum[3];
238 unsigned char my_checksum = 0;
239 gdb_connection_t *gdb_con = connection->priv;
240
241 while (1)
242 {
243 do
244 {
245 if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
246 return retval;
247
248 DEBUG("character: '%c'", character);
249
250 switch (character)
251 {
252 case '$':
253 break;
254 case '+':
255 WARNING("acknowledgment received, but no packet pending");
256 break;
257 case '-':
258 WARNING("negative acknowledgment, but no packet pending");
259 break;
260 case 0x3:
261 gdb_con->ctrl_c = 1;
262 *len = 0;
263 return ERROR_OK;
264 default:
265 WARNING("ignoring character 0x%x", character);
266 break;
267 }
268 } while (character != '$');
269
270 my_checksum = 0;
271
272 do
273 {
274 if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
275 return retval;
276
277 if (character == '#') break;
278
279 if (character == '}')
280 {
281 /* data transmitted in binary mode (X packet)
282 * uses 0x7d as escape character */
283 my_checksum += character & 0xff;
284 if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
285 return retval;
286 my_checksum += character & 0xff;
287 buffer[count++] = (character ^ 0x20) & 0xff;
288 }
289 else
290 {
291 my_checksum += character & 0xff;
292 buffer[count++] = character & 0xff;
293 }
294
295 if (count > *len)
296 {
297 ERROR("packet buffer too small");
298 return ERROR_GDB_BUFFER_TOO_SMALL;
299 }
300 } while (1);
301
302 *len = count;
303
304 if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
305 return retval;
306 checksum[0] = character;
307 if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
308 return retval;
309 checksum[1] = character;
310 checksum[2] = 0;
311
312 if (my_checksum == strtoul(checksum, NULL, 16))
313 {
314 write_socket(connection->fd, "+", 1);
315 break;
316 }
317
318 WARNING("checksum error, requesting retransmission");
319 write_socket(connection->fd, "-", 1);
320 }
321
322 return ERROR_OK;
323 }
324
325 int gdb_output(struct command_context_s *context, char* line)
326 {
327 connection_t *connection = context->output_handler_priv;
328 char *hex_buffer;
329 int i, bin_size;
330
331 bin_size = strlen(line);
332
333 hex_buffer = malloc(bin_size*2 + 4);
334
335 hex_buffer[0] = 'O';
336 for (i=0; i<bin_size; i++)
337 snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);
338 hex_buffer[bin_size*2+1] = '0';
339 hex_buffer[bin_size*2+2] = 'a';
340 hex_buffer[bin_size*2+3] = 0x0;
341
342 gdb_put_packet(connection, hex_buffer, bin_size*2 + 3);
343
344 free(hex_buffer);
345 return ERROR_OK;
346 }
347
348 int gdb_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)
349 {
350 connection_t *connection = priv;
351 gdb_connection_t *gdb_connection = connection->priv;
352 char sig_reply[4];
353 int signal;
354
355 switch (event)
356 {
357 case TARGET_EVENT_HALTED:
358 if (gdb_connection->frontend_state == TARGET_RUNNING)
359 {
360 if (gdb_connection->ctrl_c)
361 {
362 signal = 0x2;
363 gdb_connection->ctrl_c = 0;
364 }
365 else
366 {
367 signal = gdb_last_signal(target);
368 }
369
370 snprintf(sig_reply, 4, "T%2.2x", signal);
371 gdb_put_packet(connection, sig_reply, 3);
372 gdb_connection->frontend_state = TARGET_HALTED;
373 }
374 break;
375 case TARGET_EVENT_RESUMED:
376 if (gdb_connection->frontend_state == TARGET_HALTED)
377 {
378 gdb_connection->frontend_state = TARGET_RUNNING;
379 }
380 break;
381 default:
382 break;
383 }
384
385 return ERROR_OK;
386 }
387
388 int gdb_new_connection(connection_t *connection)
389 {
390 gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t));
391 gdb_service_t *gdb_service = connection->service->priv;
392 int retval;
393 int initial_ack;
394
395 connection->priv = gdb_connection;
396
397 /* initialize gdb connection information */
398 gdb_connection->buf_p = gdb_connection->buffer;
399 gdb_connection->buf_cnt = 0;
400 gdb_connection->ctrl_c = 0;
401 gdb_connection->frontend_state = TARGET_HALTED;
402 gdb_connection->vflash_image = NULL;
403
404 /* output goes through gdb connection */
405 command_set_output_handler(connection->cmd_ctx, gdb_output, connection);
406
407 /* register callback to be informed about target events */
408 target_register_event_callback(gdb_target_callback_event_handler, connection);
409
410 /* a gdb session just attached, put the target in halt mode */
411 if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) &&
412 (retval != ERROR_TARGET_ALREADY_HALTED))
413 {
414 ERROR("error when trying to halt target");
415 exit(-1);
416 }
417
418 while (gdb_service->target->state != TARGET_HALTED)
419 {
420 gdb_service->target->type->poll(gdb_service->target);
421 }
422
423 /* remove the initial ACK from the incoming buffer */
424 if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
425 return retval;
426
427 if (initial_ack != '+')
428 gdb_putback_char(connection, initial_ack);
429
430 return ERROR_OK;
431 }
432
433 int gdb_connection_closed(connection_t *connection)
434 {
435 gdb_service_t *gdb_service = connection->service->priv;
436 gdb_connection_t *gdb_connection = connection->priv;
437
438 /* see if an image built with vFlash commands is left */
439 if (gdb_connection->vflash_image)
440 {
441 image_close(gdb_connection->vflash_image);
442 free(gdb_connection->vflash_image);
443 gdb_connection->vflash_image = NULL;
444 }
445
446 /* if this connection registered a debug-message receiver delete it */
447 delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);
448
449 if (connection->priv)
450 {
451 free(connection->priv);
452 connection->priv = NULL;
453 }
454 else
455 {
456 ERROR("BUG: connection->priv == NULL");
457 }
458
459 target_unregister_event_callback(gdb_target_callback_event_handler, connection);
460
461 return ERROR_OK;
462 }
463
464 void gdb_send_error(connection_t *connection, u8 the_error)
465 {
466 char err[4];
467 snprintf(err, 4, "E%2.2X", the_error );
468 gdb_put_packet(connection, err, 3);
469 }
470
471 int gdb_last_signal_packet(connection_t *connection, target_t *target, char* packet, int packet_size)
472 {
473 char sig_reply[4];
474 int signal;
475
476 signal = gdb_last_signal(target);
477
478 snprintf(sig_reply, 4, "S%2.2x", signal);
479 gdb_put_packet(connection, sig_reply, 3);
480
481 return ERROR_OK;
482 }
483
484 void gdb_str_to_target(target_t *target, char *str, char *tstr)
485 {
486 int str_len = strlen(str);
487 int i;
488
489 if (str_len % 2)
490 {
491 ERROR("BUG: gdb value with uneven number of characters encountered: %s", str);
492 exit(-1);
493 }
494
495 if (target->endianness == TARGET_LITTLE_ENDIAN)
496 {
497 for (i = 0; i < str_len; i+=2)
498 {
499 tstr[str_len - i - 1] = str[i + 1];
500 tstr[str_len - i - 2] = str[i];
501 }
502 }
503 else
504 {
505 for (i = 0; i < str_len; i++)
506 {
507 tstr[i] = str[i];
508 }
509 }
510 }
511
512 void gdb_target_to_str(target_t *target, char *tstr, char *str)
513 {
514 int str_len = strlen(tstr);
515 int i;
516
517 if (str_len % 2)
518 {
519 ERROR("BUG: gdb value with uneven number of characters encountered");
520 exit(-1);
521 }
522
523 if (target->endianness == TARGET_LITTLE_ENDIAN)
524 {
525 for (i = 0; i < str_len; i+=2)
526 {
527 str[str_len - i - 1] = tstr[i + 1];
528 str[str_len - i - 2] = tstr[i];
529 }
530 }
531 else
532 {
533 for (i = 0; i < str_len; i++)
534 {
535 str[i] = tstr[i];
536 }
537 }
538 }
539
540 int gdb_get_registers_packet(connection_t *connection, target_t *target, char* packet, int packet_size)
541 {
542 reg_t **reg_list;
543 int reg_list_size;
544 int retval;
545 int reg_packet_size = 0;
546 char *reg_packet;
547 char *reg_packet_p;
548 int i;
549
550 DEBUG("-");
551
552 if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
553 {
554 switch (retval)
555 {
556 case ERROR_TARGET_NOT_HALTED:
557 ERROR("gdb requested registers but we're not halted, dropping connection");
558 return ERROR_SERVER_REMOTE_CLOSED;
559 default:
560 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
561 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
562 exit(-1);
563 }
564 }
565
566 for (i = 0; i < reg_list_size; i++)
567 {
568 reg_packet_size += reg_list[i]->size;
569 }
570
571 reg_packet = malloc(CEIL(reg_packet_size, 8) * 2);
572 reg_packet_p = reg_packet;
573
574 for (i = 0; i < reg_list_size; i++)
575 {
576 char *hex_buf = buf_to_str(reg_list[i]->value, reg_list[i]->size, 16);
577 DEBUG("hex_buf: %s", hex_buf);
578 gdb_str_to_target(target, hex_buf, reg_packet_p);
579 reg_packet_p += CEIL(reg_list[i]->size, 8) * 2;
580 free(hex_buf);
581 }
582
583 reg_packet_p = strndup(reg_packet, CEIL(reg_packet_size, 8) * 2);
584 DEBUG("reg_packet: %s", reg_packet_p);
585 free(reg_packet_p);
586
587 gdb_put_packet(connection, reg_packet, CEIL(reg_packet_size, 8) * 2);
588 free(reg_packet);
589
590 free(reg_list);
591
592 return ERROR_OK;
593 }
594
595 int gdb_set_registers_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
596 {
597 int i;
598 reg_t **reg_list;
599 int reg_list_size;
600 int retval;
601 char *packet_p;
602
603 DEBUG("-");
604
605 /* skip command character */
606 packet++;
607 packet_size--;
608
609 if (packet_size % 2)
610 {
611 WARNING("GDB set_registers packet with uneven characters received, dropping connection");
612 return ERROR_SERVER_REMOTE_CLOSED;
613 }
614
615 if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
616 {
617 switch (retval)
618 {
619 case ERROR_TARGET_NOT_HALTED:
620 ERROR("gdb tried to registers but we're not halted, dropping connection");
621 return ERROR_SERVER_REMOTE_CLOSED;
622 default:
623 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
624 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
625 exit(-1);
626 }
627 }
628
629 packet_p = packet;
630 for (i = 0; i < reg_list_size; i++)
631 {
632 u8 *bin_buf;
633 char *hex_buf;
634 reg_arch_type_t *arch_type;
635
636 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
637 hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2);
638 gdb_target_to_str(target, packet_p, hex_buf);
639
640 /* convert hex-string to binary buffer */
641 bin_buf = malloc(CEIL(reg_list[i]->size, 8));
642 str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);
643
644 /* get register arch_type, and call set method */
645 arch_type = register_get_arch_type(reg_list[i]->arch_type);
646 if (arch_type == NULL)
647 {
648 ERROR("BUG: encountered unregistered arch type");
649 exit(-1);
650 }
651 arch_type->set(reg_list[i], bin_buf);
652
653 /* advance packet pointer */
654 packet_p += (CEIL(reg_list[i]->size, 8) * 2);
655
656 free(bin_buf);
657 free(hex_buf);
658 }
659
660 /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
661 free(reg_list);
662
663 gdb_put_packet(connection, "OK", 2);
664
665 return ERROR_OK;
666 }
667
668 int gdb_get_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
669 {
670 char *reg_packet;
671 int reg_num = strtoul(packet + 1, NULL, 16);
672 reg_t **reg_list;
673 int reg_list_size;
674 int retval;
675 char *hex_buf;
676
677 DEBUG("-");
678
679 if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
680 {
681 switch (retval)
682 {
683 case ERROR_TARGET_NOT_HALTED:
684 ERROR("gdb requested registers but we're not halted, dropping connection");
685 return ERROR_SERVER_REMOTE_CLOSED;
686 default:
687 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
688 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
689 exit(-1);
690 }
691 }
692
693 if (reg_list_size <= reg_num)
694 {
695 ERROR("gdb requested a non-existing register");
696 exit(-1);
697 }
698
699 reg_packet = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
700
701 hex_buf = buf_to_str(reg_list[reg_num]->value, reg_list[reg_num]->size, 16);
702
703 gdb_str_to_target(target, hex_buf, reg_packet);
704
705 gdb_put_packet(connection, reg_packet, CEIL(reg_list[reg_num]->size, 8) * 2);
706
707 free(reg_list);
708 free(reg_packet);
709 free(hex_buf);
710
711 return ERROR_OK;
712 }
713
714 int gdb_set_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
715 {
716 char *separator;
717 char *hex_buf;
718 u8 *bin_buf;
719 int reg_num = strtoul(packet + 1, &separator, 16);
720 reg_t **reg_list;
721 int reg_list_size;
722 int retval;
723 reg_arch_type_t *arch_type;
724
725 DEBUG("-");
726
727 if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
728 {
729 switch (retval)
730 {
731 case ERROR_TARGET_NOT_HALTED:
732 ERROR("gdb tried to set a register but we're not halted, dropping connection");
733 return ERROR_SERVER_REMOTE_CLOSED;
734 default:
735 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
736 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
737 exit(-1);
738 }
739 }
740
741 if (reg_list_size < reg_num)
742 {
743 ERROR("gdb requested a non-existing register");
744 return ERROR_SERVER_REMOTE_CLOSED;
745 }
746
747 if (*separator != '=')
748 {
749 ERROR("GDB 'set register packet', but no '=' following the register number");
750 return ERROR_SERVER_REMOTE_CLOSED;
751 }
752
753 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
754 hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
755 gdb_target_to_str(target, separator + 1, hex_buf);
756
757 /* convert hex-string to binary buffer */
758 bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));
759 str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);
760
761 /* get register arch_type, and call set method */
762 arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);
763 if (arch_type == NULL)
764 {
765 ERROR("BUG: encountered unregistered arch type");
766 exit(-1);
767 }
768 arch_type->set(reg_list[reg_num], bin_buf);
769
770 gdb_put_packet(connection, "OK", 2);
771
772 free(bin_buf);
773 free(hex_buf);
774 free(reg_list);
775
776 return ERROR_OK;
777 }
778
779 int gdb_memory_packet_error(connection_t *connection, int retval)
780 {
781 switch (retval)
782 {
783 case ERROR_TARGET_NOT_HALTED:
784 ERROR("gdb tried to read memory but we're not halted, dropping connection");
785 return ERROR_SERVER_REMOTE_CLOSED;
786 break;
787 case ERROR_TARGET_DATA_ABORT:
788 gdb_send_error(connection, EIO);
789 break;
790 case ERROR_TARGET_TRANSLATION_FAULT:
791 gdb_send_error(connection, EFAULT);
792 break;
793 case ERROR_TARGET_UNALIGNED_ACCESS:
794 gdb_send_error(connection, EFAULT);
795 break;
796 default:
797 ERROR("BUG: unexpected error %i", retval);
798 exit(-1);
799 }
800
801 return ERROR_OK;
802 }
803
804 int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
805 {
806 char *separator;
807 u32 addr = 0;
808 u32 len = 0;
809
810 u8 *buffer;
811 char *hex_buffer;
812
813 int i;
814 int retval;
815
816 /* skip command character */
817 packet++;
818
819 addr = strtoul(packet, &separator, 16);
820
821 if (*separator != ',')
822 {
823 ERROR("incomplete read memory packet received, dropping connection");
824 return ERROR_SERVER_REMOTE_CLOSED;
825 }
826
827 len = strtoul(separator+1, NULL, 16);
828
829 buffer = malloc(len);
830
831 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
832
833 switch (len)
834 {
835 case 4:
836 if ((addr % 4) == 0)
837 retval = target->type->read_memory(target, addr, 4, 1, buffer);
838 else
839 retval = target->type->read_memory(target, addr, 1, len, buffer);
840 break;
841 case 2:
842 if ((addr % 2) == 0)
843 retval = target->type->read_memory(target, addr, 2, 1, buffer);
844 else
845 retval = target->type->read_memory(target, addr, 1, len, buffer);
846 break;
847 default:
848 if (((addr % 4) == 0) && ((len % 4) == 0))
849 retval = target->type->read_memory(target, addr, 4, len / 4, buffer);
850 else
851 retval = target->type->read_memory(target, addr, 1, len, buffer);
852 }
853
854 if (retval == ERROR_OK)
855 {
856 hex_buffer = malloc(len * 2 + 1);
857
858 for (i=0; i<len; i++)
859 snprintf(hex_buffer + 2*i, 3, "%2.2x", buffer[i]);
860
861 gdb_put_packet(connection, hex_buffer, len * 2);
862
863 free(hex_buffer);
864 }
865 else
866 {
867 if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
868 return retval;
869 }
870
871 free(buffer);
872
873 return ERROR_OK;
874 }
875
876 int gdb_write_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
877 {
878 char *separator;
879 u32 addr = 0;
880 u32 len = 0;
881
882 u8 *buffer;
883
884 int i;
885 int retval;
886
887 /* skip command character */
888 packet++;
889
890 addr = strtoul(packet, &separator, 16);
891
892 if (*separator != ',')
893 {
894 ERROR("incomplete write memory packet received, dropping connection");
895 return ERROR_SERVER_REMOTE_CLOSED;
896 }
897
898 len = strtoul(separator+1, &separator, 16);
899
900 if (*(separator++) != ':')
901 {
902 ERROR("incomplete write memory packet received, dropping connection");
903 return ERROR_SERVER_REMOTE_CLOSED;
904 }
905
906 buffer = malloc(len);
907
908 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
909
910 for (i=0; i<len; i++)
911 {
912 u32 tmp;
913 sscanf(separator + 2*i, "%2x", &tmp);
914 buffer[i] = tmp;
915 }
916
917 retval = ERROR_OK;
918 switch (len)
919 {
920 /* handle sized writes */
921 case 4:
922 if ((addr % 4) == 0)
923 retval = target->type->write_memory(target, addr, 4, 1, buffer);
924 else
925 retval = target->type->write_memory(target, addr, 1, len, buffer);
926 break;
927 case 2:
928 if ((addr % 2) == 0)
929 retval = target->type->write_memory(target, addr, 2, 1, buffer);
930 else
931 retval = target->type->write_memory(target, addr, 1, len, buffer);
932 break;
933 case 3:
934 case 1:
935 retval = target->type->write_memory(target, addr, 1, len, buffer);
936 break;
937 /* handle bulk writes */
938 default:
939 retval = target_write_buffer(target, addr, len, buffer);
940 break;
941 }
942
943 if (retval == ERROR_OK)
944 {
945 gdb_put_packet(connection, "OK", 2);
946 }
947 else
948 {
949 if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
950 return retval;
951 }
952
953 free(buffer);
954
955 return ERROR_OK;
956 }
957
958 int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
959 {
960 char *separator;
961 u32 addr = 0;
962 u32 len = 0;
963
964 u8 *buffer;
965 int retval;
966
967 /* skip command character */
968 packet++;
969
970 addr = strtoul(packet, &separator, 16);
971
972 if (*separator != ',')
973 {
974 ERROR("incomplete write memory binary packet received, dropping connection");
975 return ERROR_SERVER_REMOTE_CLOSED;
976 }
977
978 len = strtoul(separator+1, &separator, 16);
979
980 if (*(separator++) != ':')
981 {
982 ERROR("incomplete write memory binary packet received, dropping connection");
983 return ERROR_SERVER_REMOTE_CLOSED;
984 }
985
986 retval = ERROR_OK;
987 if( len ) {
988
989 buffer = malloc(len);
990
991 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
992
993 memcpy( buffer, separator, len );
994
995 switch (len)
996 {
997 case 4:
998 if ((addr % 4) == 0)
999 retval = target->type->write_memory(target, addr, 4, 1, buffer);
1000 else
1001 retval = target->type->write_memory(target, addr, 1, len, buffer);
1002 break;
1003 case 2:
1004 if ((addr % 2) == 0)
1005 retval = target->type->write_memory(target, addr, 2, 1, buffer);
1006 else
1007 retval = target->type->write_memory(target, addr, 1, len, buffer);
1008 break;
1009 case 3:
1010 case 1:
1011 retval = target->type->write_memory(target, addr, 1, len, buffer);
1012 break;
1013 default:
1014 retval = target_write_buffer(target, addr, len, buffer);
1015 break;
1016 }
1017
1018 free(buffer);
1019 }
1020
1021 if (retval == ERROR_OK)
1022 {
1023 gdb_put_packet(connection, "OK", 2);
1024 }
1025 else
1026 {
1027 if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
1028 return retval;
1029 }
1030
1031 return ERROR_OK;
1032 }
1033
1034 void gdb_step_continue_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
1035 {
1036 int current = 0;
1037 u32 address = 0x0;
1038
1039 DEBUG("-");
1040
1041 if (packet_size > 1)
1042 {
1043 packet[packet_size] = 0;
1044 address = strtoul(packet + 1, NULL, 16);
1045 }
1046 else
1047 {
1048 current = 1;
1049 }
1050
1051 if (packet[0] == 'c')
1052 {
1053 DEBUG("continue");
1054 target->type->resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
1055 }
1056 else if (packet[0] == 's')
1057 {
1058 DEBUG("step");
1059 target->type->step(target, current, address, 0); /* step at current or address, don't handle breakpoints */
1060 }
1061 }
1062
1063 int gdb_bp_wp_packet_error(connection_t *connection, int retval)
1064 {
1065 switch (retval)
1066 {
1067 case ERROR_TARGET_NOT_HALTED:
1068 ERROR("gdb tried to set a breakpoint but we're not halted, dropping connection");
1069 return ERROR_SERVER_REMOTE_CLOSED;
1070 break;
1071 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
1072 gdb_send_error(connection, EBUSY);
1073 break;
1074 default:
1075 ERROR("BUG: unexpected error %i", retval);
1076 exit(-1);
1077 }
1078
1079 return ERROR_OK;
1080 }
1081
1082 int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
1083 {
1084 int type;
1085 enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
1086 enum watchpoint_rw wp_type;
1087 u32 address;
1088 u32 size;
1089 char *separator;
1090 int retval;
1091
1092 DEBUG("-");
1093
1094 type = strtoul(packet + 1, &separator, 16);
1095
1096 if (type == 0) /* memory breakpoint */
1097 bp_type = BKPT_SOFT;
1098 else if (type == 1) /* hardware breakpoint */
1099 bp_type = BKPT_HARD;
1100 else if (type == 2) /* write watchpoint */
1101 wp_type = WPT_WRITE;
1102 else if (type == 3) /* read watchpoint */
1103 wp_type = WPT_READ;
1104 else if (type == 4) /* access watchpoint */
1105 wp_type = WPT_ACCESS;
1106
1107 if (*separator != ',')
1108 {
1109 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1110 return ERROR_SERVER_REMOTE_CLOSED;
1111 }
1112
1113 address = strtoul(separator+1, &separator, 16);
1114
1115 if (*separator != ',')
1116 {
1117 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1118 return ERROR_SERVER_REMOTE_CLOSED;
1119 }
1120
1121 size = strtoul(separator+1, &separator, 16);
1122
1123 switch (type)
1124 {
1125 case 0:
1126 case 1:
1127 if (packet[0] == 'Z')
1128 {
1129 if ((retval = breakpoint_add(target, address, size, bp_type)) != ERROR_OK)
1130 {
1131 if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)
1132 return retval;
1133 }
1134 else
1135 {
1136 gdb_put_packet(connection, "OK", 2);
1137 }
1138 }
1139 else
1140 {
1141 breakpoint_remove(target, address);
1142 gdb_put_packet(connection, "OK", 2);
1143 }
1144 break;
1145 case 2:
1146 case 3:
1147 case 4:
1148 {
1149 if (packet[0] == 'Z')
1150 {
1151 if ((retval = watchpoint_add(target, address, size, type-2, 0, 0xffffffffu)) != ERROR_OK)
1152 {
1153 if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)
1154 return retval;
1155 }
1156 else
1157 {
1158 gdb_put_packet(connection, "OK", 2);
1159 }
1160 }
1161 else
1162 {
1163 watchpoint_remove(target, address);
1164 gdb_put_packet(connection, "OK", 2);
1165 }
1166 break;
1167 }
1168 default:
1169 break;
1170 }
1171
1172 return ERROR_OK;
1173 }
1174
1175 int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
1176 {
1177 command_context_t *cmd_ctx = connection->cmd_ctx;
1178
1179 if (strstr(packet, "qRcmd,"))
1180 {
1181 if (packet_size > 6)
1182 {
1183 char *cmd;
1184 int i;
1185 cmd = malloc((packet_size - 6)/2 + 1);
1186 for (i=0; i < (packet_size - 6)/2; i++)
1187 {
1188 u32 tmp;
1189 sscanf(packet + 6 + 2*i, "%2x", &tmp);
1190 cmd[i] = tmp;
1191 }
1192 cmd[(packet_size - 6)/2] = 0x0;
1193 command_run_line(cmd_ctx, cmd);
1194 free(cmd);
1195 }
1196 gdb_put_packet(connection, "OK", 2);
1197 return ERROR_OK;
1198 }
1199
1200 if (strstr(packet, "qCRC:"))
1201 {
1202 if (packet_size > 5)
1203 {
1204 int retval;
1205 u8 gdb_reply[9];
1206 char *separator;
1207 u32 checksum;
1208 u32 addr = 0;
1209 u32 len = 0;
1210
1211 /* skip command character */
1212 packet += 5;
1213
1214 addr = strtoul(packet, &separator, 16);
1215
1216 if (*separator != ',')
1217 {
1218 ERROR("incomplete read memory packet received, dropping connection");
1219 return ERROR_SERVER_REMOTE_CLOSED;
1220 }
1221
1222 len = strtoul(separator+1, NULL, 16);
1223
1224 retval = target_checksum_memory(target, addr, len, &checksum);
1225
1226 if (retval == ERROR_OK)
1227 {
1228 snprintf(gdb_reply, 9, "C%2.2x", checksum);
1229 gdb_put_packet(connection, gdb_reply, 9);
1230 }
1231 else
1232 {
1233 if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
1234 return retval;
1235 }
1236
1237 return ERROR_OK;
1238 }
1239 }
1240
1241 gdb_put_packet(connection, "", 0);
1242 return ERROR_OK;
1243 }
1244
1245 int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
1246 {
1247 gdb_connection_t *gdb_connection = connection->priv;
1248 gdb_service_t *gdb_service = connection->service->priv;
1249 int result;
1250
1251 if (strstr(packet, "vFlashErase:"))
1252 {
1253 unsigned long addr;
1254 unsigned long length;
1255 char *parse = packet + 12;
1256 if (*parse == '\0')
1257 {
1258 ERROR("incomplete vFlashErase packet received, dropping connection");
1259 return ERROR_SERVER_REMOTE_CLOSED;
1260 }
1261
1262 addr = strtoul(parse, &parse, 16);
1263
1264 if (*(parse++) != ',' || *parse == '\0')
1265 {
1266 ERROR("incomplete vFlashErase packet received, dropping connection");
1267 return ERROR_SERVER_REMOTE_CLOSED;
1268 }
1269
1270 length = strtoul(parse, &parse, 16);
1271
1272 if (*parse != '\0')
1273 {
1274 ERROR("incomplete vFlashErase packet received, dropping connection");
1275 return ERROR_SERVER_REMOTE_CLOSED;
1276 }
1277
1278 /* perform erase */
1279 if ((result = flash_erase(gdb_service->target, addr, length)) != ERROR_OK)
1280 {
1281 /* GDB doesn't evaluate the actual error number returned,
1282 * treat a failed erase as an I/O error
1283 */
1284 gdb_send_error(connection, EIO);
1285 ERROR("flash_erase returned %i", result);
1286 }
1287 else
1288 gdb_put_packet(connection, "OK", 2);
1289
1290 return ERROR_OK;
1291 }
1292
1293 if (strstr(packet, "vFlashWrite:"))
1294 {
1295 unsigned long addr;
1296 unsigned long length;
1297 char *parse = packet + 12;
1298
1299 if (*parse == '\0')
1300 {
1301 ERROR("incomplete vFlashErase packet received, dropping connection");
1302 return ERROR_SERVER_REMOTE_CLOSED;
1303 }
1304 addr = strtoul(parse, &parse, 16);
1305 if (*(parse++) != ':')
1306 {
1307 ERROR("incomplete vFlashErase packet received, dropping connection");
1308 return ERROR_SERVER_REMOTE_CLOSED;
1309 }
1310 length = packet_size - (parse - packet);
1311
1312 /* create a new image if there isn't already one */
1313 if (gdb_connection->vflash_image == NULL)
1314 {
1315 gdb_connection->vflash_image = malloc(sizeof(image_t));
1316 image_open(gdb_connection->vflash_image, "", "build");
1317 }
1318
1319 /* create new section with content from packet buffer */
1320 image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (u8*)parse);
1321
1322 gdb_put_packet(connection, "OK", 2);
1323
1324 return ERROR_OK;
1325 }
1326
1327 if (!strcmp(packet, "vFlashDone"))
1328 {
1329 u32 written;
1330 char *error_str;
1331
1332 /* process the flashing buffer */
1333 if ((result = flash_image_operation(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, flash_image_op_write)) != ERROR_OK)
1334 {
1335 if (result == ERROR_FLASH_DST_OUT_OF_BANK)
1336 gdb_put_packet(connection, "E.memtype", 9);
1337 else
1338 gdb_send_error(connection, EIO);
1339
1340 if (error_str)
1341 {
1342 ERROR("flash writing failed: %s", error_str);
1343 free(error_str);
1344 }
1345 }
1346 else
1347 {
1348 DEBUG("wrote %u bytes from vFlash image to flash", written);
1349 gdb_put_packet(connection, "OK", 2);
1350 }
1351
1352 image_close(gdb_connection->vflash_image);
1353 free(gdb_connection->vflash_image);
1354 gdb_connection->vflash_image = NULL;
1355
1356 return ERROR_OK;
1357 }
1358
1359 gdb_put_packet(connection, "", 0);
1360 return ERROR_OK;
1361 }
1362
1363 int gdb_detach(connection_t *connection, target_t *target)
1364 {
1365 switch( detach_mode )
1366 {
1367 case GDB_DETACH_RESUME:
1368 target->type->resume(target, 1, 0, 1, 0);
1369 break;
1370
1371 case GDB_DETACH_RESET:
1372 target_process_reset(connection->cmd_ctx);
1373 break;
1374
1375 case GDB_DETACH_HALT:
1376 target->type->halt(target);
1377 break;
1378
1379 case GDB_DETACH_NOTHING:
1380 break;
1381 }
1382
1383 gdb_put_packet(connection, "OK", 2);
1384
1385 return ERROR_OK;
1386 }
1387
1388 int gdb_input(connection_t *connection)
1389 {
1390 gdb_service_t *gdb_service = connection->service->priv;
1391 target_t *target = gdb_service->target;
1392 char packet[GDB_BUFFER_SIZE];
1393 int packet_size;
1394 int retval;
1395 gdb_connection_t *gdb_con = connection->priv;
1396
1397 /* drain input buffer */
1398 do
1399 {
1400 packet_size = GDB_BUFFER_SIZE-1;
1401 if ((retval = gdb_get_packet(connection, packet, &packet_size)) != ERROR_OK)
1402 {
1403 switch (retval)
1404 {
1405 case ERROR_GDB_BUFFER_TOO_SMALL:
1406 ERROR("BUG: buffer supplied for gdb packet was too small");
1407 exit(-1);
1408 case ERROR_SERVER_REMOTE_CLOSED:
1409 return ERROR_SERVER_REMOTE_CLOSED;
1410 default:
1411 ERROR("BUG: unexpected error");
1412 exit(-1);
1413 }
1414 }
1415
1416 /* terminate with zero */
1417 packet[packet_size] = 0;
1418
1419 DEBUG("received packet: '%s'", packet);
1420
1421 if (packet_size > 0)
1422 {
1423 retval = ERROR_OK;
1424 switch (packet[0])
1425 {
1426 case 'H':
1427 /* Hct... -- set thread
1428 * we don't have threads, send empty reply */
1429 gdb_put_packet(connection, NULL, 0);
1430 break;
1431 case 'q':
1432 retval = gdb_query_packet(connection, target, packet, packet_size);
1433 break;
1434 case 'g':
1435 retval = gdb_get_registers_packet(connection, target, packet, packet_size);
1436 break;
1437 case 'G':
1438 retval = gdb_set_registers_packet(connection, target, packet, packet_size);
1439 break;
1440 case 'p':
1441 retval = gdb_get_register_packet(connection, target, packet, packet_size);
1442 break;
1443 case 'P':
1444 retval = gdb_set_register_packet(connection, target, packet, packet_size);
1445 break;
1446 case 'm':
1447 retval = gdb_read_memory_packet(connection, target, packet, packet_size);
1448 break;
1449 case 'M':
1450 retval = gdb_write_memory_packet(connection, target, packet, packet_size);
1451 break;
1452 case 'z':
1453 case 'Z':
1454 retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size);
1455 break;
1456 case '?':
1457 gdb_last_signal_packet(connection, target, packet, packet_size);
1458 break;
1459 case 'c':
1460 case 's':
1461 gdb_step_continue_packet(connection, target, packet, packet_size);
1462 break;
1463 case 'v':
1464 retval = gdb_v_packet(connection, target, packet, packet_size);
1465 break;
1466 case 'D':
1467 retval = gdb_detach(connection, target);
1468 break;
1469 case 'X':
1470 if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK)
1471 return retval;
1472 break;
1473 case 'k':
1474 gdb_put_packet(connection, "OK", 2);
1475 return ERROR_SERVER_REMOTE_CLOSED;
1476 default:
1477 /* ignore unkown packets */
1478 DEBUG("ignoring 0x%2.2x packet", packet[0]);
1479 gdb_put_packet(connection, NULL, 0);
1480 break;
1481 }
1482
1483 /* if a packet handler returned an error, exit input loop */
1484 if (retval != ERROR_OK)
1485 return retval;
1486 }
1487
1488 if (gdb_con->ctrl_c)
1489 {
1490 if (target->state == TARGET_RUNNING)
1491 {
1492 target->type->halt(target);
1493 gdb_con->ctrl_c = 0;
1494 }
1495 }
1496
1497 } while (gdb_con->buf_cnt > 0);
1498
1499 return ERROR_OK;
1500 }
1501
1502 int gdb_init()
1503 {
1504 gdb_service_t *gdb_service;
1505 target_t *target = targets;
1506 int i = 0;
1507
1508 if (!target)
1509 {
1510 WARNING("no gdb ports allocated as no target has been specified");
1511 return ERROR_OK;
1512 }
1513
1514 if (gdb_port == 0)
1515 {
1516 WARNING("no gdb port specified, using default port 3333");
1517 gdb_port = 3333;
1518 }
1519
1520 while (target)
1521 {
1522 char service_name[8];
1523
1524 snprintf(service_name, 8, "gdb-%2.2i", i);
1525
1526 gdb_service = malloc(sizeof(gdb_service_t));
1527 gdb_service->target = target;
1528
1529 add_service("gdb", CONNECTION_GDB, gdb_port + i, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
1530
1531 DEBUG("gdb service for target %s at port %i", target->type->name, gdb_port + i);
1532
1533 i++;
1534 target = target->next;
1535 }
1536
1537 return ERROR_OK;
1538 }
1539
1540 /* daemon configuration command gdb_port */
1541 int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1542 {
1543 if (argc == 0)
1544 return ERROR_OK;
1545
1546 /* only if the port wasn't overwritten by cmdline */
1547 if (gdb_port == 0)
1548 gdb_port = strtoul(args[0], NULL, 0);
1549
1550 return ERROR_OK;
1551 }
1552
1553 int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1554 {
1555 if (argc == 1)
1556 {
1557 if (strcmp(args[0], "resume") == 0)
1558 {
1559 detach_mode = GDB_DETACH_RESUME;
1560 return ERROR_OK;
1561 }
1562 else if (strcmp(args[0], "reset") == 0)
1563 {
1564 detach_mode = GDB_DETACH_RESET;
1565 return ERROR_OK;
1566 }
1567 else if (strcmp(args[0], "halt") == 0)
1568 {
1569 detach_mode = GDB_DETACH_HALT;
1570 return ERROR_OK;
1571 }
1572 else if (strcmp(args[0], "nothing") == 0)
1573 {
1574 detach_mode = GDB_DETACH_NOTHING;
1575 return ERROR_OK;
1576 }
1577 }
1578
1579 WARNING("invalid gdb_detach configuration directive: %s", args[0]);
1580 return ERROR_OK;
1581 }
1582
1583 int gdb_register_commands(command_context_t *command_context)
1584 {
1585 register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
1586 COMMAND_CONFIG, "");
1587 register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
1588 COMMAND_CONFIG, "");
1589
1590 return ERROR_OK;
1591 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)