1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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. *
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. *
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 ***************************************************************************/
24 #include "replacements.h"
26 #include "gdb_server.h"
30 #include "binarybuffer.h"
32 #include "breakpoints.h"
34 #include "target_request.h"
42 #define _DEBUG_GDB_IO_
45 static unsigned short gdb_port
;
55 /* target behaviour on gdb detach */
56 enum gdb_detach_mode detach_mode
= GDB_DETACH_RESUME
;
58 /* set if we are sending a memory map to gdb
59 * via qXfer:memory-map:read packet */
60 int gdb_use_memory_map
= 0;
61 int gdb_flash_program
= 0;
63 int gdb_last_signal(target_t
*target
)
65 switch (target
->debug_reason
)
67 case DBG_REASON_DBGRQ
:
68 return 0x2; /* SIGINT */
69 case DBG_REASON_BREAKPOINT
:
70 case DBG_REASON_WATCHPOINT
:
71 case DBG_REASON_WPTANDBKPT
:
72 return 0x05; /* SIGTRAP */
73 case DBG_REASON_SINGLESTEP
:
74 return 0x05; /* SIGTRAP */
75 case DBG_REASON_NOTHALTED
:
76 return 0x0; /* no signal... shouldn't happen */
78 ERROR("BUG: undefined debug reason");
83 int gdb_get_char(connection_t
*connection
, int* next_char
)
85 gdb_connection_t
*gdb_con
= connection
->priv
;
91 if (gdb_con
->buf_cnt
-- > 0)
93 *next_char
= *(gdb_con
->buf_p
++);
94 if (gdb_con
->buf_cnt
> 0)
95 connection
->input_pending
= 1;
97 connection
->input_pending
= 0;
100 DEBUG("returned char '%c' (0x%2.2x)", *next_char
, *next_char
);
106 while ((gdb_con
->buf_cnt
= read_socket(connection
->fd
, gdb_con
->buffer
, GDB_BUFFER_SIZE
)) <= 0)
108 if (gdb_con
->buf_cnt
== 0)
109 return ERROR_SERVER_REMOTE_CLOSED
;
112 errno
= WSAGetLastError();
119 case WSAECONNABORTED
:
120 return ERROR_SERVER_REMOTE_CLOSED
;
122 return ERROR_SERVER_REMOTE_CLOSED
;
124 ERROR("read: %d", errno
);
134 return ERROR_SERVER_REMOTE_CLOSED
;
136 return ERROR_SERVER_REMOTE_CLOSED
;
138 ERROR("read: %s", strerror(errno
));
144 #ifdef _DEBUG_GDB_IO_
145 debug_buffer
= malloc(gdb_con
->buf_cnt
+ 1);
146 memcpy(debug_buffer
, gdb_con
->buffer
, gdb_con
->buf_cnt
);
147 debug_buffer
[gdb_con
->buf_cnt
] = 0;
148 DEBUG("received '%s'", debug_buffer
);
152 gdb_con
->buf_p
= gdb_con
->buffer
;
154 *next_char
= *(gdb_con
->buf_p
++);
155 if (gdb_con
->buf_cnt
> 0)
156 connection
->input_pending
= 1;
158 connection
->input_pending
= 0;
159 #ifdef _DEBUG_GDB_IO_
160 DEBUG("returned char '%c' (0x%2.2x)", *next_char
, *next_char
);
166 int gdb_putback_char(connection_t
*connection
, int last_char
)
168 gdb_connection_t
*gdb_con
= connection
->priv
;
170 if (gdb_con
->buf_p
> gdb_con
->buffer
)
172 *(--gdb_con
->buf_p
) = last_char
;
177 ERROR("BUG: couldn't put character back");
183 int gdb_put_packet(connection_t
*connection
, char *buffer
, int len
)
186 unsigned char my_checksum
= 0;
188 #ifdef _DEBUG_GDB_IO_
193 gdb_connection_t
*gdb_con
= connection
->priv
;
195 for (i
= 0; i
< len
; i
++)
196 my_checksum
+= buffer
[i
];
200 #ifdef _DEBUG_GDB_IO_
201 debug_buffer
= malloc(len
+ 1);
202 memcpy(debug_buffer
, buffer
, len
);
203 debug_buffer
[len
] = 0;
204 DEBUG("sending packet '$%s#%2.2x'", debug_buffer
, my_checksum
);
207 write_socket(connection
->fd
, "$", 1);
209 write_socket(connection
->fd
, buffer
, len
);
210 write_socket(connection
->fd
, "#", 1);
212 snprintf(checksum
, 3, "%2.2x", my_checksum
);
214 write_socket(connection
->fd
, checksum
, 2);
216 if ((retval
= gdb_get_char(connection
, &reply
)) != ERROR_OK
)
221 else if (reply
== '-')
222 WARNING("negative reply, retrying");
223 else if (reply
== 0x3)
226 if ((retval
= gdb_get_char(connection
, &reply
)) != ERROR_OK
)
230 else if (reply
== '-')
231 WARNING("negative reply, retrying");
234 ERROR("unknown character 0x%2.2x in reply, dropping connection", reply
);
235 return ERROR_SERVER_REMOTE_CLOSED
;
240 ERROR("unknown character 0x%2.2x in reply, dropping connection", reply
);
241 return ERROR_SERVER_REMOTE_CLOSED
;
248 int gdb_get_packet(connection_t
*connection
, char *buffer
, int *len
)
254 unsigned char my_checksum
= 0;
255 gdb_connection_t
*gdb_con
= connection
->priv
;
261 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
264 #ifdef _DEBUG_GDB_IO_
265 DEBUG("character: '%c'", character
);
273 WARNING("acknowledgment received, but no packet pending");
276 WARNING("negative acknowledgment, but no packet pending");
283 WARNING("ignoring character 0x%x", character
);
286 } while (character
!= '$');
292 /* The common case is that we have an entire packet with no escape chars.
293 * We need to leave at least 2 bytes in the buffer to have
294 * gdb_get_char() update various bits and bobs correctly.
296 if ((gdb_con
->buf_cnt
> 2) && ((gdb_con
->buf_cnt
+count
) < *len
))
298 /* The compiler will struggle a bit with constant propagation and
299 * aliasing, so we help it by showing that these values do not
300 * change inside the loop
303 char *buf
= gdb_con
->buf_p
;
304 int run
= gdb_con
->buf_cnt
- 2;
311 if (character
== '#')
313 /* Danger! character can be '#' when esc is
314 * used so we need an explicit boolean for done here.
320 if (character
== '}')
322 /* data transmitted in binary mode (X packet)
323 * uses 0x7d as escape character */
324 my_checksum
+= character
& 0xff;
327 my_checksum
+= character
& 0xff;
328 buffer
[count
++] = (character
^ 0x20) & 0xff;
331 my_checksum
+= character
& 0xff;
332 buffer
[count
++] = character
& 0xff;
336 gdb_con
->buf_cnt
-= i
;
342 ERROR("packet buffer too small");
343 return ERROR_GDB_BUFFER_TOO_SMALL
;
346 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
349 if (character
== '#')
352 if (character
== '}')
354 /* data transmitted in binary mode (X packet)
355 * uses 0x7d as escape character */
356 my_checksum
+= character
& 0xff;
357 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
359 my_checksum
+= character
& 0xff;
360 buffer
[count
++] = (character
^ 0x20) & 0xff;
364 my_checksum
+= character
& 0xff;
365 buffer
[count
++] = character
& 0xff;
372 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
374 checksum
[0] = character
;
375 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
377 checksum
[1] = character
;
380 if (my_checksum
== strtoul(checksum
, NULL
, 16))
382 write_socket(connection
->fd
, "+", 1);
386 WARNING("checksum error, requesting retransmission");
387 write_socket(connection
->fd
, "-", 1);
393 int gdb_output(struct command_context_s
*context
, char* line
)
395 connection_t
*connection
= context
->output_handler_priv
;
396 gdb_connection_t
*gdb_connection
= connection
->priv
;
401 /* check if output is enabled */
402 if (gdb_connection
->output_disable
)
407 bin_size
= strlen(line
);
409 hex_buffer
= malloc(bin_size
*2 + 4);
412 for (i
=0; i
<bin_size
; i
++)
413 snprintf(hex_buffer
+ 1 + i
*2, 3, "%2.2x", line
[i
]);
414 hex_buffer
[bin_size
*2+1] = '0';
415 hex_buffer
[bin_size
*2+2] = 'a';
416 hex_buffer
[bin_size
*2+3] = 0x0;
418 gdb_put_packet(connection
, hex_buffer
, bin_size
*2 + 3);
424 int gdb_program_handler(struct target_s
*target
, enum target_event event
, void *priv
)
427 struct command_context_s
*cmd_ctx
= priv
;
429 if (target
->gdb_program_script
)
431 script
= fopen(target
->gdb_program_script
, "r");
434 ERROR("couldn't open script file %s", target
->gdb_program_script
);
438 INFO("executing gdb_program script '%s'", target
->gdb_program_script
);
439 command_run_file(cmd_ctx
, script
, COMMAND_EXEC
);
442 jtag_execute_queue();
448 int gdb_target_callback_event_handler(struct target_s
*target
, enum target_event event
, void *priv
)
450 connection_t
*connection
= priv
;
451 gdb_connection_t
*gdb_connection
= connection
->priv
;
457 case TARGET_EVENT_HALTED
:
458 if (gdb_connection
->frontend_state
== TARGET_RUNNING
)
460 if (gdb_connection
->ctrl_c
)
463 gdb_connection
->ctrl_c
= 0;
467 signal
= gdb_last_signal(target
);
470 snprintf(sig_reply
, 4, "T%2.2x", signal
);
471 gdb_put_packet(connection
, sig_reply
, 3);
472 gdb_connection
->frontend_state
= TARGET_HALTED
;
475 case TARGET_EVENT_RESUMED
:
476 if (gdb_connection
->frontend_state
== TARGET_HALTED
)
478 gdb_connection
->frontend_state
= TARGET_RUNNING
;
481 case TARGET_EVENT_GDB_PROGRAM
:
482 gdb_program_handler(target
, event
, connection
->cmd_ctx
);
491 int gdb_new_connection(connection_t
*connection
)
493 gdb_connection_t
*gdb_connection
= malloc(sizeof(gdb_connection_t
));
494 gdb_service_t
*gdb_service
= connection
->service
->priv
;
498 connection
->priv
= gdb_connection
;
500 /* initialize gdb connection information */
501 gdb_connection
->buf_p
= gdb_connection
->buffer
;
502 gdb_connection
->buf_cnt
= 0;
503 gdb_connection
->ctrl_c
= 0;
504 gdb_connection
->frontend_state
= TARGET_HALTED
;
505 gdb_connection
->vflash_image
= NULL
;
506 gdb_connection
->output_disable
= 0;
508 /* output goes through gdb connection */
509 command_set_output_handler(connection
->cmd_ctx
, gdb_output
, connection
);
511 /* register callback to be informed about target events */
512 target_register_event_callback(gdb_target_callback_event_handler
, connection
);
514 /* a gdb session just attached, put the target in halt mode */
515 if (((retval
= gdb_service
->target
->type
->halt(gdb_service
->target
)) != ERROR_OK
) &&
516 (retval
!= ERROR_TARGET_ALREADY_HALTED
))
518 ERROR("error when trying to halt target");
522 while (gdb_service
->target
->state
!= TARGET_HALTED
)
524 gdb_service
->target
->type
->poll(gdb_service
->target
);
527 /* remove the initial ACK from the incoming buffer */
528 if ((retval
= gdb_get_char(connection
, &initial_ack
)) != ERROR_OK
)
531 if (initial_ack
!= '+')
532 gdb_putback_char(connection
, initial_ack
);
537 int gdb_connection_closed(connection_t
*connection
)
539 gdb_service_t
*gdb_service
= connection
->service
->priv
;
540 gdb_connection_t
*gdb_connection
= connection
->priv
;
542 /* see if an image built with vFlash commands is left */
543 if (gdb_connection
->vflash_image
)
545 image_close(gdb_connection
->vflash_image
);
546 free(gdb_connection
->vflash_image
);
547 gdb_connection
->vflash_image
= NULL
;
550 /* if this connection registered a debug-message receiver delete it */
551 delete_debug_msg_receiver(connection
->cmd_ctx
, gdb_service
->target
);
553 if (connection
->priv
)
555 free(connection
->priv
);
556 connection
->priv
= NULL
;
560 ERROR("BUG: connection->priv == NULL");
563 target_unregister_event_callback(gdb_target_callback_event_handler
, connection
);
568 void gdb_send_error(connection_t
*connection
, u8 the_error
)
571 snprintf(err
, 4, "E%2.2X", the_error
);
572 gdb_put_packet(connection
, err
, 3);
575 int gdb_last_signal_packet(connection_t
*connection
, target_t
*target
, char* packet
, int packet_size
)
580 signal
= gdb_last_signal(target
);
582 snprintf(sig_reply
, 4, "S%2.2x", signal
);
583 gdb_put_packet(connection
, sig_reply
, 3);
588 /* Convert register to string of bits. NB! The # of bits in the
589 * register might be non-divisible by 8(a byte), in which
590 * case an entire byte is shown. */
591 void gdb_str_to_target(target_t
*target
, char *tstr
, reg_t
*reg
)
593 static const char *DIGITS
= "0123456789abcdef";
599 buf_len
= CEIL(reg
->size
, 8);
601 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
603 for (i
= 0; i
< buf_len
; i
++)
605 tstr
[i
*2] = DIGITS
[(buf
[i
]>>4) & 0xf];
606 tstr
[i
*2+1] = DIGITS
[buf
[i
]&0xf];
611 for (i
= 0; i
< buf_len
; i
++)
613 tstr
[(buf_len
-1-i
)*2] = DIGITS
[(buf
[i
]>>4)&0xf];
614 tstr
[(buf_len
-1-i
)*2+1] = DIGITS
[buf
[i
]&0xf];
619 void gdb_target_to_str(target_t
*target
, char *tstr
, char *str
)
621 int str_len
= strlen(tstr
);
626 ERROR("BUG: gdb value with uneven number of characters encountered");
630 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
632 for (i
= 0; i
< str_len
; i
+=2)
634 str
[str_len
- i
- 1] = tstr
[i
+ 1];
635 str
[str_len
- i
- 2] = tstr
[i
];
640 for (i
= 0; i
< str_len
; i
++)
647 int gdb_get_registers_packet(connection_t
*connection
, target_t
*target
, char* packet
, int packet_size
)
652 int reg_packet_size
= 0;
657 #ifdef _DEBUG_GDB_IO_
661 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
665 case ERROR_TARGET_NOT_HALTED
:
666 ERROR("gdb requested registers but we're not halted, dropping connection");
667 return ERROR_SERVER_REMOTE_CLOSED
;
669 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
670 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
675 for (i
= 0; i
< reg_list_size
; i
++)
677 reg_packet_size
+= reg_list
[i
]->size
;
680 reg_packet
= malloc(CEIL(reg_packet_size
, 8) * 2);
681 reg_packet_p
= reg_packet
;
683 for (i
= 0; i
< reg_list_size
; i
++)
685 gdb_str_to_target(target
, reg_packet_p
, reg_list
[i
]);
686 reg_packet_p
+= CEIL(reg_list
[i
]->size
, 8) * 2;
689 #ifdef _DEBUG_GDB_IO_
692 reg_packet_p
= strndup(reg_packet
, CEIL(reg_packet_size
, 8) * 2);
693 DEBUG("reg_packet: %s", reg_packet_p
);
698 gdb_put_packet(connection
, reg_packet
, CEIL(reg_packet_size
, 8) * 2);
706 int gdb_set_registers_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
714 #ifdef _DEBUG_GDB_IO_
718 /* skip command character */
724 WARNING("GDB set_registers packet with uneven characters received, dropping connection");
725 return ERROR_SERVER_REMOTE_CLOSED
;
728 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
732 case ERROR_TARGET_NOT_HALTED
:
733 ERROR("gdb tried to registers but we're not halted, dropping connection");
734 return ERROR_SERVER_REMOTE_CLOSED
;
736 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
737 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
743 for (i
= 0; i
< reg_list_size
; i
++)
747 reg_arch_type_t
*arch_type
;
749 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
750 hex_buf
= malloc(CEIL(reg_list
[i
]->size
, 8) * 2);
751 gdb_target_to_str(target
, packet_p
, hex_buf
);
753 /* convert hex-string to binary buffer */
754 bin_buf
= malloc(CEIL(reg_list
[i
]->size
, 8));
755 str_to_buf(hex_buf
, CEIL(reg_list
[i
]->size
, 8) * 2, bin_buf
, reg_list
[i
]->size
, 16);
757 /* get register arch_type, and call set method */
758 arch_type
= register_get_arch_type(reg_list
[i
]->arch_type
);
759 if (arch_type
== NULL
)
761 ERROR("BUG: encountered unregistered arch type");
764 arch_type
->set(reg_list
[i
], bin_buf
);
766 /* advance packet pointer */
767 packet_p
+= (CEIL(reg_list
[i
]->size
, 8) * 2);
773 /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
776 gdb_put_packet(connection
, "OK", 2);
781 int gdb_get_register_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
784 int reg_num
= strtoul(packet
+ 1, NULL
, 16);
789 #ifdef _DEBUG_GDB_IO_
793 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
797 case ERROR_TARGET_NOT_HALTED
:
798 ERROR("gdb requested registers but we're not halted, dropping connection");
799 return ERROR_SERVER_REMOTE_CLOSED
;
801 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
802 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
807 if (reg_list_size
<= reg_num
)
809 ERROR("gdb requested a non-existing register");
813 reg_packet
= malloc(CEIL(reg_list
[reg_num
]->size
, 8) * 2);
815 gdb_str_to_target(target
, reg_packet
, reg_list
[reg_num
]);
817 gdb_put_packet(connection
, reg_packet
, CEIL(reg_list
[reg_num
]->size
, 8) * 2);
825 int gdb_set_register_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
830 int reg_num
= strtoul(packet
+ 1, &separator
, 16);
834 reg_arch_type_t
*arch_type
;
838 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
842 case ERROR_TARGET_NOT_HALTED
:
843 ERROR("gdb tried to set a register but we're not halted, dropping connection");
844 return ERROR_SERVER_REMOTE_CLOSED
;
846 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
847 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
852 if (reg_list_size
< reg_num
)
854 ERROR("gdb requested a non-existing register");
855 return ERROR_SERVER_REMOTE_CLOSED
;
858 if (*separator
!= '=')
860 ERROR("GDB 'set register packet', but no '=' following the register number");
861 return ERROR_SERVER_REMOTE_CLOSED
;
864 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
865 hex_buf
= malloc(CEIL(reg_list
[reg_num
]->size
, 8) * 2);
866 gdb_target_to_str(target
, separator
+ 1, hex_buf
);
868 /* convert hex-string to binary buffer */
869 bin_buf
= malloc(CEIL(reg_list
[reg_num
]->size
, 8));
870 str_to_buf(hex_buf
, CEIL(reg_list
[reg_num
]->size
, 8) * 2, bin_buf
, reg_list
[reg_num
]->size
, 16);
872 /* get register arch_type, and call set method */
873 arch_type
= register_get_arch_type(reg_list
[reg_num
]->arch_type
);
874 if (arch_type
== NULL
)
876 ERROR("BUG: encountered unregistered arch type");
879 arch_type
->set(reg_list
[reg_num
], bin_buf
);
881 gdb_put_packet(connection
, "OK", 2);
890 int gdb_memory_packet_error(connection_t
*connection
, int retval
)
894 case ERROR_TARGET_NOT_HALTED
:
895 ERROR("gdb tried to read memory but we're not halted, dropping connection");
896 return ERROR_SERVER_REMOTE_CLOSED
;
898 case ERROR_TARGET_DATA_ABORT
:
899 gdb_send_error(connection
, EIO
);
901 case ERROR_TARGET_TRANSLATION_FAULT
:
902 gdb_send_error(connection
, EFAULT
);
904 case ERROR_TARGET_UNALIGNED_ACCESS
:
905 gdb_send_error(connection
, EFAULT
);
908 ERROR("BUG: unexpected error %i", retval
);
915 int gdb_read_memory_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
927 /* skip command character */
930 addr
= strtoul(packet
, &separator
, 16);
932 if (*separator
!= ',')
934 ERROR("incomplete read memory packet received, dropping connection");
935 return ERROR_SERVER_REMOTE_CLOSED
;
938 len
= strtoul(separator
+1, NULL
, 16);
940 buffer
= malloc(len
);
942 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
948 retval
= target
->type
->read_memory(target
, addr
, 4, 1, buffer
);
950 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
954 retval
= target
->type
->read_memory(target
, addr
, 2, 1, buffer
);
956 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
959 if (((addr
% 4) == 0) && ((len
% 4) == 0))
960 retval
= target
->type
->read_memory(target
, addr
, 4, len
/ 4, buffer
);
962 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
966 if (retval
== ERROR_TARGET_DATA_ABORT
)
968 /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
969 * At some point this might be fixed in GDB, in which case this code can be removed.
970 * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
972 memset(buffer
, 0, len
);
977 if (retval
== ERROR_OK
)
979 hex_buffer
= malloc(len
* 2 + 1);
981 for (i
=0; i
<len
; i
++)
982 snprintf(hex_buffer
+ 2*i
, 3, "%2.2x", buffer
[i
]);
984 gdb_put_packet(connection
, hex_buffer
, len
* 2);
990 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
999 int gdb_write_memory_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1010 /* skip command character */
1013 addr
= strtoul(packet
, &separator
, 16);
1015 if (*separator
!= ',')
1017 ERROR("incomplete write memory packet received, dropping connection");
1018 return ERROR_SERVER_REMOTE_CLOSED
;
1021 len
= strtoul(separator
+1, &separator
, 16);
1023 if (*(separator
++) != ':')
1025 ERROR("incomplete write memory packet received, dropping connection");
1026 return ERROR_SERVER_REMOTE_CLOSED
;
1029 buffer
= malloc(len
);
1031 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
1033 for (i
=0; i
<len
; i
++)
1036 sscanf(separator
+ 2*i
, "%2x", &tmp
);
1043 /* handle sized writes */
1045 if ((addr
% 4) == 0)
1046 retval
= target
->type
->write_memory(target
, addr
, 4, 1, buffer
);
1048 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1051 if ((addr
% 2) == 0)
1052 retval
= target
->type
->write_memory(target
, addr
, 2, 1, buffer
);
1054 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1058 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1060 /* handle bulk writes */
1062 retval
= target_write_buffer(target
, addr
, len
, buffer
);
1066 if (retval
== ERROR_OK
)
1068 gdb_put_packet(connection
, "OK", 2);
1072 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1081 int gdb_write_memory_binary_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1090 /* skip command character */
1093 addr
= strtoul(packet
, &separator
, 16);
1095 if (*separator
!= ',')
1097 ERROR("incomplete write memory binary packet received, dropping connection");
1098 return ERROR_SERVER_REMOTE_CLOSED
;
1101 len
= strtoul(separator
+1, &separator
, 16);
1103 if (*(separator
++) != ':')
1105 ERROR("incomplete write memory binary packet received, dropping connection");
1106 return ERROR_SERVER_REMOTE_CLOSED
;
1112 buffer
= malloc(len
);
1114 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
1116 memcpy( buffer
, separator
, len
);
1121 if ((addr
% 4) == 0)
1122 retval
= target
->type
->write_memory(target
, addr
, 4, 1, buffer
);
1124 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1127 if ((addr
% 2) == 0)
1128 retval
= target
->type
->write_memory(target
, addr
, 2, 1, buffer
);
1130 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1134 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1137 retval
= target_write_buffer(target
, addr
, len
, buffer
);
1144 if (retval
== ERROR_OK
)
1146 gdb_put_packet(connection
, "OK", 2);
1150 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1157 void gdb_step_continue_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1164 if (packet_size
> 1)
1166 packet
[packet_size
] = 0;
1167 address
= strtoul(packet
+ 1, NULL
, 16);
1174 if (packet
[0] == 'c')
1177 target
->type
->resume(target
, current
, address
, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
1179 else if (packet
[0] == 's')
1182 target
->type
->step(target
, current
, address
, 0); /* step at current or address, don't handle breakpoints */
1186 int gdb_bp_wp_packet_error(connection_t
*connection
, int retval
)
1190 case ERROR_TARGET_NOT_HALTED
:
1191 ERROR("gdb tried to set a breakpoint but we're not halted, dropping connection");
1192 return ERROR_SERVER_REMOTE_CLOSED
;
1194 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
1195 gdb_send_error(connection
, EBUSY
);
1198 ERROR("BUG: unexpected error %i", retval
);
1205 int gdb_breakpoint_watchpoint_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1208 enum breakpoint_type bp_type
= BKPT_SOFT
/* dummy init to avoid warning */;
1209 enum watchpoint_rw wp_type
;
1217 type
= strtoul(packet
+ 1, &separator
, 16);
1219 if (type
== 0) /* memory breakpoint */
1220 bp_type
= BKPT_SOFT
;
1221 else if (type
== 1) /* hardware breakpoint */
1222 bp_type
= BKPT_HARD
;
1223 else if (type
== 2) /* write watchpoint */
1224 wp_type
= WPT_WRITE
;
1225 else if (type
== 3) /* read watchpoint */
1227 else if (type
== 4) /* access watchpoint */
1228 wp_type
= WPT_ACCESS
;
1230 if (*separator
!= ',')
1232 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1233 return ERROR_SERVER_REMOTE_CLOSED
;
1236 address
= strtoul(separator
+1, &separator
, 16);
1238 if (*separator
!= ',')
1240 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1241 return ERROR_SERVER_REMOTE_CLOSED
;
1244 size
= strtoul(separator
+1, &separator
, 16);
1250 if (packet
[0] == 'Z')
1252 if ((retval
= breakpoint_add(target
, address
, size
, bp_type
)) != ERROR_OK
)
1254 if ((retval
= gdb_bp_wp_packet_error(connection
, retval
)) != ERROR_OK
)
1259 gdb_put_packet(connection
, "OK", 2);
1264 breakpoint_remove(target
, address
);
1265 gdb_put_packet(connection
, "OK", 2);
1272 if (packet
[0] == 'Z')
1274 if ((retval
= watchpoint_add(target
, address
, size
, type
-2, 0, 0xffffffffu
)) != ERROR_OK
)
1276 if ((retval
= gdb_bp_wp_packet_error(connection
, retval
)) != ERROR_OK
)
1281 gdb_put_packet(connection
, "OK", 2);
1286 watchpoint_remove(target
, address
);
1287 gdb_put_packet(connection
, "OK", 2);
1298 /* print out a string and allocate more space as needed, mainly used for XML at this point */
1299 void xml_printf(int *retval
, char **xml
, int *pos
, int *size
, const char *fmt
, ...)
1301 if (*retval
!= ERROR_OK
)
1309 if ((*xml
== NULL
) || (!first
))
1311 /* start by 0 to exercise all the code paths.
1312 * Need minimum 2 bytes to fit 1 char and 0 terminator. */
1314 *size
= *size
* 2 + 2;
1316 *xml
= realloc(*xml
, *size
);
1321 *retval
= ERROR_SERVER_REMOTE_CLOSED
;
1329 ret
= vsnprintf(*xml
+ *pos
, *size
- *pos
, fmt
, ap
);
1331 if ((ret
> 0) && ((ret
+ 1) < *size
- *pos
))
1336 /* there was just enough or not enough space, allocate more. */
1341 static int decode_xfer_read (char *buf
, char **annex
, int *ofs
, unsigned int *len
)
1345 /* Extract and NUL-terminate the annex. */
1347 while (*buf
&& *buf
!= ':')
1353 /* After the read marker and annex, qXfer looks like a
1354 * traditional 'm' packet. */
1356 *ofs
= strtoul(buf
, &separator
, 16);
1358 if (*separator
!= ',')
1361 *len
= strtoul(separator
+1, NULL
, 16);
1366 int gdb_query_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1368 command_context_t
*cmd_ctx
= connection
->cmd_ctx
;
1370 if (strstr(packet
, "qRcmd,"))
1372 if (packet_size
> 6)
1376 cmd
= malloc((packet_size
- 6)/2 + 1);
1377 for (i
=0; i
< (packet_size
- 6)/2; i
++)
1380 sscanf(packet
+ 6 + 2*i
, "%2x", &tmp
);
1383 cmd
[(packet_size
- 6)/2] = 0x0;
1384 target_call_timer_callbacks();
1385 command_run_line(cmd_ctx
, cmd
);
1388 gdb_put_packet(connection
, "OK", 2);
1391 else if (strstr(packet
, "qCRC:"))
1393 if (packet_size
> 5)
1402 /* skip command character */
1405 addr
= strtoul(packet
, &separator
, 16);
1407 if (*separator
!= ',')
1409 ERROR("incomplete read memory packet received, dropping connection");
1410 return ERROR_SERVER_REMOTE_CLOSED
;
1413 len
= strtoul(separator
+ 1, NULL
, 16);
1415 retval
= target_checksum_memory(target
, addr
, len
, &checksum
);
1417 if (retval
== ERROR_OK
)
1419 snprintf(gdb_reply
, 10, "C%8.8x", checksum
);
1420 gdb_put_packet(connection
, gdb_reply
, 9);
1424 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1431 else if (strstr(packet
, "qSupported"))
1433 /* we currently support packet size and qXfer:memory-map:read (if enabled)
1434 * disable qXfer:features:read for the moment */
1435 int retval
= ERROR_OK
;
1436 char *buffer
= NULL
;
1440 xml_printf(&retval
, &buffer
, &pos
, &size
,
1441 "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
1442 (GDB_BUFFER_SIZE
- 1), gdb_use_memory_map
== 1 ? '+' : '-');
1444 if (retval
!= ERROR_OK
)
1446 gdb_send_error(connection
, 01);
1450 gdb_put_packet(connection
, buffer
, strlen(buffer
));
1455 else if (strstr(packet
, "qXfer:memory-map:read::"))
1457 /* We get away with only specifying flash here. Regions that are not
1458 * specified are treated as if we provided no memory map(if not we
1459 * could detect the holes and mark them as RAM).
1460 * Normally we only execute this code once, but no big deal if we
1461 * have to regenerate it a couple of times. */
1467 int retval
= ERROR_OK
;
1473 /* skip command character */
1476 offset
= strtoul(packet
, &separator
, 16);
1477 length
= strtoul(separator
+ 1, &separator
, 16);
1479 xml_printf(&retval
, &xml
, &pos
, &size
, "<memory-map>\n");
1484 p
= get_flash_bank_by_num(i
);
1488 xml_printf(&retval
, &xml
, &pos
, &size
, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
1489 "<property name=\"blocksize\">0x%x</property>\n" \
1491 p
->base
, p
->size
, p
->size
/p
->num_sectors
);
1495 xml_printf(&retval
, &xml
, &pos
, &size
, "</memory-map>\n");
1497 if (retval
!= ERROR_OK
)
1499 gdb_send_error(connection
, retval
);
1503 if (offset
+ length
> pos
)
1505 length
= pos
- offset
;
1508 char *t
= malloc(length
+ 1);
1510 memcpy(t
+ 1, xml
+ offset
, length
);
1511 gdb_put_packet(connection
, t
, length
+ 1);
1517 else if (strstr(packet
, "qXfer:features:read:"))
1522 int retval
= ERROR_OK
;
1528 /* skip command character */
1531 if (decode_xfer_read( packet
, &annex
, &offset
, &length
) < 0)
1533 gdb_send_error(connection
, 01);
1537 if (strcmp(annex
, "target.xml") != 0)
1539 gdb_send_error(connection
, 01);
1543 xml_printf(&retval
, &xml
, &pos
, &size
, \
1544 "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
1546 if (retval
!= ERROR_OK
)
1548 gdb_send_error(connection
, retval
);
1552 gdb_put_packet(connection
, xml
, strlen(xml
) + 1);
1558 gdb_put_packet(connection
, "", 0);
1562 int gdb_v_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1564 gdb_connection_t
*gdb_connection
= connection
->priv
;
1565 gdb_service_t
*gdb_service
= connection
->service
->priv
;
1568 /* if flash programming disabled - send a empty reply */
1570 if (gdb_flash_program
== 0)
1572 gdb_put_packet(connection
, "", 0);
1576 if (strstr(packet
, "vFlashErase:"))
1579 unsigned long length
;
1581 char *parse
= packet
+ 12;
1584 ERROR("incomplete vFlashErase packet received, dropping connection");
1585 return ERROR_SERVER_REMOTE_CLOSED
;
1588 addr
= strtoul(parse
, &parse
, 16);
1590 if (*(parse
++) != ',' || *parse
== '\0')
1592 ERROR("incomplete vFlashErase packet received, dropping connection");
1593 return ERROR_SERVER_REMOTE_CLOSED
;
1596 length
= strtoul(parse
, &parse
, 16);
1600 ERROR("incomplete vFlashErase packet received, dropping connection");
1601 return ERROR_SERVER_REMOTE_CLOSED
;
1604 /* disable gdb output while programming */
1605 gdb_connection
->output_disable
= 1;
1607 /* assume all sectors need erasing - stops any problems
1608 * when flash_write is called multiple times */
1611 /* perform any target specific operations before the erase */
1612 target_call_event_callbacks(gdb_service
->target
, TARGET_EVENT_GDB_PROGRAM
);
1615 if ((result
= flash_erase_address_range(gdb_service
->target
, addr
, length
)) != ERROR_OK
)
1617 /* GDB doesn't evaluate the actual error number returned,
1618 * treat a failed erase as an I/O error
1620 gdb_send_error(connection
, EIO
);
1621 ERROR("flash_erase returned %i", result
);
1624 gdb_put_packet(connection
, "OK", 2);
1626 /* reenable gdb output */
1627 gdb_connection
->output_disable
= 0;
1632 if (strstr(packet
, "vFlashWrite:"))
1635 unsigned long length
;
1636 char *parse
= packet
+ 12;
1640 ERROR("incomplete vFlashErase packet received, dropping connection");
1641 return ERROR_SERVER_REMOTE_CLOSED
;
1643 addr
= strtoul(parse
, &parse
, 16);
1644 if (*(parse
++) != ':')
1646 ERROR("incomplete vFlashErase packet received, dropping connection");
1647 return ERROR_SERVER_REMOTE_CLOSED
;
1649 length
= packet_size
- (parse
- packet
);
1651 /* disable gdb output while programming */
1652 gdb_connection
->output_disable
= 1;
1654 /* create a new image if there isn't already one */
1655 if (gdb_connection
->vflash_image
== NULL
)
1657 gdb_connection
->vflash_image
= malloc(sizeof(image_t
));
1658 image_open(gdb_connection
->vflash_image
, "", "build");
1661 /* create new section with content from packet buffer */
1662 image_add_section(gdb_connection
->vflash_image
, addr
, length
, 0x0, (u8
*)parse
);
1664 gdb_put_packet(connection
, "OK", 2);
1666 /* reenable gdb output */
1667 gdb_connection
->output_disable
= 0;
1672 if (!strcmp(packet
, "vFlashDone"))
1677 /* disable gdb output while programming */
1678 gdb_connection
->output_disable
= 1;
1680 /* process the flashing buffer. No need to erase as GDB
1681 * always issues a vFlashErase first. */
1682 if ((result
= flash_write(gdb_service
->target
, gdb_connection
->vflash_image
, &written
, &error_str
, NULL
, 0)) != ERROR_OK
)
1684 if (result
== ERROR_FLASH_DST_OUT_OF_BANK
)
1685 gdb_put_packet(connection
, "E.memtype", 9);
1687 gdb_send_error(connection
, EIO
);
1691 ERROR("flash writing failed: %s", error_str
);
1697 DEBUG("wrote %u bytes from vFlash image to flash", written
);
1698 gdb_put_packet(connection
, "OK", 2);
1701 image_close(gdb_connection
->vflash_image
);
1702 free(gdb_connection
->vflash_image
);
1703 gdb_connection
->vflash_image
= NULL
;
1705 /* reenable gdb output */
1706 gdb_connection
->output_disable
= 0;
1711 gdb_put_packet(connection
, "", 0);
1715 int gdb_detach(connection_t
*connection
, target_t
*target
)
1717 switch( detach_mode
)
1719 case GDB_DETACH_RESUME
:
1720 target
->type
->resume(target
, 1, 0, 1, 0);
1723 case GDB_DETACH_RESET
:
1724 target_process_reset(connection
->cmd_ctx
);
1727 case GDB_DETACH_HALT
:
1728 target
->type
->halt(target
);
1731 case GDB_DETACH_NOTHING
:
1735 gdb_put_packet(connection
, "OK", 2);
1740 int gdb_input(connection_t
*connection
)
1742 gdb_service_t
*gdb_service
= connection
->service
->priv
;
1743 target_t
*target
= gdb_service
->target
;
1744 char packet
[GDB_BUFFER_SIZE
];
1747 gdb_connection_t
*gdb_con
= connection
->priv
;
1748 static int extended_protocol
= 0;
1750 /* drain input buffer */
1753 packet_size
= GDB_BUFFER_SIZE
-1;
1754 if ((retval
= gdb_get_packet(connection
, packet
, &packet_size
)) != ERROR_OK
)
1758 case ERROR_GDB_BUFFER_TOO_SMALL
:
1759 ERROR("BUG: buffer supplied for gdb packet was too small");
1761 case ERROR_SERVER_REMOTE_CLOSED
:
1762 return ERROR_SERVER_REMOTE_CLOSED
;
1764 ERROR("BUG: unexpected error");
1769 /* terminate with zero */
1770 packet
[packet_size
] = 0;
1772 DEBUG("received packet: '%s'", packet
);
1774 if (packet_size
> 0)
1780 /* Hct... -- set thread
1781 * we don't have threads, send empty reply */
1782 gdb_put_packet(connection
, NULL
, 0);
1785 retval
= gdb_query_packet(connection
, target
, packet
, packet_size
);
1788 retval
= gdb_get_registers_packet(connection
, target
, packet
, packet_size
);
1791 retval
= gdb_set_registers_packet(connection
, target
, packet
, packet_size
);
1794 retval
= gdb_get_register_packet(connection
, target
, packet
, packet_size
);
1797 retval
= gdb_set_register_packet(connection
, target
, packet
, packet_size
);
1800 retval
= gdb_read_memory_packet(connection
, target
, packet
, packet_size
);
1803 retval
= gdb_write_memory_packet(connection
, target
, packet
, packet_size
);
1807 retval
= gdb_breakpoint_watchpoint_packet(connection
, target
, packet
, packet_size
);
1810 gdb_last_signal_packet(connection
, target
, packet
, packet_size
);
1814 gdb_step_continue_packet(connection
, target
, packet
, packet_size
);
1817 retval
= gdb_v_packet(connection
, target
, packet
, packet_size
);
1820 retval
= gdb_detach(connection
, target
);
1821 extended_protocol
= 0;
1824 if ((retval
= gdb_write_memory_binary_packet(connection
, target
, packet
, packet_size
)) != ERROR_OK
)
1828 if (extended_protocol
!= 0)
1830 gdb_put_packet(connection
, "OK", 2);
1831 return ERROR_SERVER_REMOTE_CLOSED
;
1833 /* handle extended remote protocol */
1834 extended_protocol
= 1;
1835 gdb_put_packet(connection
, "OK", 2);
1838 /* handle extended restart packet */
1839 target_process_reset(connection
->cmd_ctx
);
1842 /* ignore unkown packets */
1843 DEBUG("ignoring 0x%2.2x packet", packet
[0]);
1844 gdb_put_packet(connection
, NULL
, 0);
1848 /* if a packet handler returned an error, exit input loop */
1849 if (retval
!= ERROR_OK
)
1853 if (gdb_con
->ctrl_c
)
1855 if (target
->state
== TARGET_RUNNING
)
1857 target
->type
->halt(target
);
1858 gdb_con
->ctrl_c
= 0;
1862 } while (gdb_con
->buf_cnt
> 0);
1869 gdb_service_t
*gdb_service
;
1870 target_t
*target
= targets
;
1875 WARNING("no gdb ports allocated as no target has been specified");
1881 WARNING("no gdb port specified, using default port 3333");
1887 char service_name
[8];
1889 snprintf(service_name
, 8, "gdb-%2.2i", i
);
1891 gdb_service
= malloc(sizeof(gdb_service_t
));
1892 gdb_service
->target
= target
;
1894 add_service("gdb", CONNECTION_GDB
, gdb_port
+ i
, 1, gdb_new_connection
, gdb_input
, gdb_connection_closed
, gdb_service
);
1896 DEBUG("gdb service for target %s at port %i", target
->type
->name
, gdb_port
+ i
);
1899 target
= target
->next
;
1905 /* daemon configuration command gdb_port */
1906 int handle_gdb_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1911 /* only if the port wasn't overwritten by cmdline */
1913 gdb_port
= strtoul(args
[0], NULL
, 0);
1918 int handle_gdb_detach_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1922 if (strcmp(args
[0], "resume") == 0)
1924 detach_mode
= GDB_DETACH_RESUME
;
1927 else if (strcmp(args
[0], "reset") == 0)
1929 detach_mode
= GDB_DETACH_RESET
;
1932 else if (strcmp(args
[0], "halt") == 0)
1934 detach_mode
= GDB_DETACH_HALT
;
1937 else if (strcmp(args
[0], "nothing") == 0)
1939 detach_mode
= GDB_DETACH_NOTHING
;
1944 WARNING("invalid gdb_detach configuration directive: %s", args
[0]);
1948 int handle_gdb_memory_map_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1952 if (strcmp(args
[0], "enable") == 0)
1954 gdb_use_memory_map
= 1;
1957 else if (strcmp(args
[0], "disable") == 0)
1959 gdb_use_memory_map
= 0;
1964 WARNING("invalid gdb_memory_map configuration directive: %s", args
[0]);
1968 int handle_gdb_flash_program_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1972 if (strcmp(args
[0], "enable") == 0)
1974 gdb_flash_program
= 1;
1977 else if (strcmp(args
[0], "disable") == 0)
1979 gdb_flash_program
= 0;
1984 WARNING("invalid gdb_memory_map configuration directive: %s", args
[0]);
1988 int gdb_register_commands(command_context_t
*command_context
)
1990 register_command(command_context
, NULL
, "gdb_port", handle_gdb_port_command
,
1991 COMMAND_CONFIG
, "");
1992 register_command(command_context
, NULL
, "gdb_detach", handle_gdb_detach_command
,
1993 COMMAND_CONFIG
, "");
1994 register_command(command_context
, NULL
, "gdb_memory_map", handle_gdb_memory_map_command
,
1995 COMMAND_CONFIG
, "");
1996 register_command(command_context
, NULL
, "gdb_flash_program", handle_gdb_flash_program_command
,
1997 COMMAND_CONFIG
, "");
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)