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
!= '$');
293 /* The common case is that we have an entire packet with no escape chars.
294 * We need to leave at least 2 bytes in the buffer to have
295 * gdb_get_char() update various bits and bobs correctly.
297 if ((gdb_con
->buf_cnt
> 2) && ((gdb_con
->buf_cnt
+count
) < *len
))
299 /* The compiler will struggle a bit with constant propagation and
300 * aliasing, so we help it by showing that these values do not
301 * change inside the loop
304 char *buf
= gdb_con
->buf_p
;
305 int run
= gdb_con
->buf_cnt
- 2;
312 if (character
== '#')
314 /* Danger! character can be '#' when esc is
315 * used so we need an explicit boolean for done here.
321 if (character
== '}')
323 /* data transmitted in binary mode (X packet)
324 * uses 0x7d as escape character */
325 my_checksum
+= character
& 0xff;
328 my_checksum
+= character
& 0xff;
329 buffer
[count
++] = (character
^ 0x20) & 0xff;
332 my_checksum
+= character
& 0xff;
333 buffer
[count
++] = character
& 0xff;
337 gdb_con
->buf_cnt
-= i
;
343 ERROR("packet buffer too small");
344 return ERROR_GDB_BUFFER_TOO_SMALL
;
347 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
350 if (character
== '#')
353 if (character
== '}')
355 /* data transmitted in binary mode (X packet)
356 * uses 0x7d as escape character */
357 my_checksum
+= character
& 0xff;
358 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
360 my_checksum
+= character
& 0xff;
361 buffer
[count
++] = (character
^ 0x20) & 0xff;
365 my_checksum
+= character
& 0xff;
366 buffer
[count
++] = character
& 0xff;
373 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
375 checksum
[0] = character
;
376 if ((retval
= gdb_get_char(connection
, &character
)) != ERROR_OK
)
378 checksum
[1] = character
;
381 if (my_checksum
== strtoul(checksum
, NULL
, 16))
383 write_socket(connection
->fd
, "+", 1);
387 WARNING("checksum error, requesting retransmission");
388 write_socket(connection
->fd
, "-", 1);
394 int gdb_output(struct command_context_s
*context
, char* line
)
396 connection_t
*connection
= context
->output_handler_priv
;
397 gdb_connection_t
*gdb_connection
= connection
->priv
;
402 /* check if output is enabled */
403 if (gdb_connection
->output_disable
)
408 bin_size
= strlen(line
);
410 hex_buffer
= malloc(bin_size
*2 + 4);
413 for (i
=0; i
<bin_size
; i
++)
414 snprintf(hex_buffer
+ 1 + i
*2, 3, "%2.2x", line
[i
]);
415 hex_buffer
[bin_size
*2+1] = '0';
416 hex_buffer
[bin_size
*2+2] = 'a';
417 hex_buffer
[bin_size
*2+3] = 0x0;
419 gdb_put_packet(connection
, hex_buffer
, bin_size
*2 + 3);
425 int gdb_program_handler(struct target_s
*target
, enum target_event event
, void *priv
)
428 struct command_context_s
*cmd_ctx
= priv
;
430 if (target
->gdb_program_script
)
432 script
= fopen(target
->gdb_program_script
, "r");
435 ERROR("couldn't open script file %s", target
->gdb_program_script
);
439 INFO("executing gdb_program script '%s'", target
->gdb_program_script
);
440 command_run_file(cmd_ctx
, script
, COMMAND_EXEC
);
443 jtag_execute_queue();
449 int gdb_target_callback_event_handler(struct target_s
*target
, enum target_event event
, void *priv
)
451 connection_t
*connection
= priv
;
452 gdb_connection_t
*gdb_connection
= connection
->priv
;
458 case TARGET_EVENT_HALTED
:
459 if (gdb_connection
->frontend_state
== TARGET_RUNNING
)
461 if (gdb_connection
->ctrl_c
)
464 gdb_connection
->ctrl_c
= 0;
468 signal
= gdb_last_signal(target
);
471 snprintf(sig_reply
, 4, "T%2.2x", signal
);
472 gdb_put_packet(connection
, sig_reply
, 3);
473 gdb_connection
->frontend_state
= TARGET_HALTED
;
476 case TARGET_EVENT_RESUMED
:
477 if (gdb_connection
->frontend_state
== TARGET_HALTED
)
479 gdb_connection
->frontend_state
= TARGET_RUNNING
;
482 case TARGET_EVENT_GDB_PROGRAM
:
483 gdb_program_handler(target
, event
, connection
->cmd_ctx
);
492 int gdb_new_connection(connection_t
*connection
)
494 gdb_connection_t
*gdb_connection
= malloc(sizeof(gdb_connection_t
));
495 gdb_service_t
*gdb_service
= connection
->service
->priv
;
499 connection
->priv
= gdb_connection
;
501 /* initialize gdb connection information */
502 gdb_connection
->buf_p
= gdb_connection
->buffer
;
503 gdb_connection
->buf_cnt
= 0;
504 gdb_connection
->ctrl_c
= 0;
505 gdb_connection
->frontend_state
= TARGET_HALTED
;
506 gdb_connection
->vflash_image
= NULL
;
507 gdb_connection
->output_disable
= 0;
509 /* output goes through gdb connection */
510 command_set_output_handler(connection
->cmd_ctx
, gdb_output
, connection
);
512 /* register callback to be informed about target events */
513 target_register_event_callback(gdb_target_callback_event_handler
, connection
);
515 /* a gdb session just attached, put the target in halt mode */
516 if (((retval
= gdb_service
->target
->type
->halt(gdb_service
->target
)) != ERROR_OK
) &&
517 (retval
!= ERROR_TARGET_ALREADY_HALTED
))
519 ERROR("error when trying to halt target");
523 while (gdb_service
->target
->state
!= TARGET_HALTED
)
525 gdb_service
->target
->type
->poll(gdb_service
->target
);
528 /* remove the initial ACK from the incoming buffer */
529 if ((retval
= gdb_get_char(connection
, &initial_ack
)) != ERROR_OK
)
532 if (initial_ack
!= '+')
533 gdb_putback_char(connection
, initial_ack
);
538 int gdb_connection_closed(connection_t
*connection
)
540 gdb_service_t
*gdb_service
= connection
->service
->priv
;
541 gdb_connection_t
*gdb_connection
= connection
->priv
;
543 /* see if an image built with vFlash commands is left */
544 if (gdb_connection
->vflash_image
)
546 image_close(gdb_connection
->vflash_image
);
547 free(gdb_connection
->vflash_image
);
548 gdb_connection
->vflash_image
= NULL
;
551 /* if this connection registered a debug-message receiver delete it */
552 delete_debug_msg_receiver(connection
->cmd_ctx
, gdb_service
->target
);
554 if (connection
->priv
)
556 free(connection
->priv
);
557 connection
->priv
= NULL
;
561 ERROR("BUG: connection->priv == NULL");
564 target_unregister_event_callback(gdb_target_callback_event_handler
, connection
);
569 void gdb_send_error(connection_t
*connection
, u8 the_error
)
572 snprintf(err
, 4, "E%2.2X", the_error
);
573 gdb_put_packet(connection
, err
, 3);
576 int gdb_last_signal_packet(connection_t
*connection
, target_t
*target
, char* packet
, int packet_size
)
581 signal
= gdb_last_signal(target
);
583 snprintf(sig_reply
, 4, "S%2.2x", signal
);
584 gdb_put_packet(connection
, sig_reply
, 3);
589 /* Convert register to string of bits. NB! The # of bits in the
590 * register might be non-divisible by 8(a byte), in which
591 * case an entire byte is shown. */
592 void gdb_str_to_target(target_t
*target
, char *tstr
, reg_t
*reg
)
594 static const char *DIGITS
= "0123456789abcdef";
600 buf_len
= CEIL(reg
->size
, 8);
602 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
604 for (i
= 0; i
< buf_len
; i
++)
606 tstr
[i
*2] = DIGITS
[(buf
[i
]>>4) & 0xf];
607 tstr
[i
*2+1] = DIGITS
[buf
[i
]&0xf];
612 for (i
= 0; i
< buf_len
; i
++)
614 tstr
[(buf_len
-1-i
)*2] = DIGITS
[(buf
[i
]>>4)&0xf];
615 tstr
[(buf_len
-1-i
)*2+1] = DIGITS
[buf
[i
]&0xf];
620 void gdb_target_to_str(target_t
*target
, char *tstr
, char *str
)
622 int str_len
= strlen(tstr
);
627 ERROR("BUG: gdb value with uneven number of characters encountered");
631 if (target
->endianness
== TARGET_LITTLE_ENDIAN
)
633 for (i
= 0; i
< str_len
; i
+=2)
635 str
[str_len
- i
- 1] = tstr
[i
+ 1];
636 str
[str_len
- i
- 2] = tstr
[i
];
641 for (i
= 0; i
< str_len
; i
++)
648 int gdb_get_registers_packet(connection_t
*connection
, target_t
*target
, char* packet
, int packet_size
)
653 int reg_packet_size
= 0;
658 #ifdef _DEBUG_GDB_IO_
662 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
666 case ERROR_TARGET_NOT_HALTED
:
667 ERROR("gdb requested registers but we're not halted, dropping connection");
668 return ERROR_SERVER_REMOTE_CLOSED
;
670 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
671 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
676 for (i
= 0; i
< reg_list_size
; i
++)
678 reg_packet_size
+= reg_list
[i
]->size
;
681 reg_packet
= malloc(CEIL(reg_packet_size
, 8) * 2);
682 reg_packet_p
= reg_packet
;
684 for (i
= 0; i
< reg_list_size
; i
++)
686 gdb_str_to_target(target
, reg_packet_p
, reg_list
[i
]);
687 reg_packet_p
+= CEIL(reg_list
[i
]->size
, 8) * 2;
690 #ifdef _DEBUG_GDB_IO_
693 reg_packet_p
= strndup(reg_packet
, CEIL(reg_packet_size
, 8) * 2);
694 DEBUG("reg_packet: %s", reg_packet_p
);
699 gdb_put_packet(connection
, reg_packet
, CEIL(reg_packet_size
, 8) * 2);
707 int gdb_set_registers_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
715 #ifdef _DEBUG_GDB_IO_
719 /* skip command character */
725 WARNING("GDB set_registers packet with uneven characters received, dropping connection");
726 return ERROR_SERVER_REMOTE_CLOSED
;
729 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
733 case ERROR_TARGET_NOT_HALTED
:
734 ERROR("gdb tried to registers but we're not halted, dropping connection");
735 return ERROR_SERVER_REMOTE_CLOSED
;
737 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
738 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
744 for (i
= 0; i
< reg_list_size
; i
++)
748 reg_arch_type_t
*arch_type
;
750 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
751 hex_buf
= malloc(CEIL(reg_list
[i
]->size
, 8) * 2);
752 gdb_target_to_str(target
, packet_p
, hex_buf
);
754 /* convert hex-string to binary buffer */
755 bin_buf
= malloc(CEIL(reg_list
[i
]->size
, 8));
756 str_to_buf(hex_buf
, CEIL(reg_list
[i
]->size
, 8) * 2, bin_buf
, reg_list
[i
]->size
, 16);
758 /* get register arch_type, and call set method */
759 arch_type
= register_get_arch_type(reg_list
[i
]->arch_type
);
760 if (arch_type
== NULL
)
762 ERROR("BUG: encountered unregistered arch type");
765 arch_type
->set(reg_list
[i
], bin_buf
);
767 /* advance packet pointer */
768 packet_p
+= (CEIL(reg_list
[i
]->size
, 8) * 2);
774 /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
777 gdb_put_packet(connection
, "OK", 2);
782 int gdb_get_register_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
785 int reg_num
= strtoul(packet
+ 1, NULL
, 16);
790 #ifdef _DEBUG_GDB_IO_
794 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
798 case ERROR_TARGET_NOT_HALTED
:
799 ERROR("gdb requested registers but we're not halted, dropping connection");
800 return ERROR_SERVER_REMOTE_CLOSED
;
802 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
803 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
808 if (reg_list_size
<= reg_num
)
810 ERROR("gdb requested a non-existing register");
814 reg_packet
= malloc(CEIL(reg_list
[reg_num
]->size
, 8) * 2);
816 gdb_str_to_target(target
, reg_packet
, reg_list
[reg_num
]);
818 gdb_put_packet(connection
, reg_packet
, CEIL(reg_list
[reg_num
]->size
, 8) * 2);
826 int gdb_set_register_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
831 int reg_num
= strtoul(packet
+ 1, &separator
, 16);
835 reg_arch_type_t
*arch_type
;
839 if ((retval
= target
->type
->get_gdb_reg_list(target
, ®_list
, ®_list_size
)) != ERROR_OK
)
843 case ERROR_TARGET_NOT_HALTED
:
844 ERROR("gdb tried to set a register but we're not halted, dropping connection");
845 return ERROR_SERVER_REMOTE_CLOSED
;
847 /* this is a bug condition - get_gdb_reg_list() may not return any other error */
848 ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
853 if (reg_list_size
< reg_num
)
855 ERROR("gdb requested a non-existing register");
856 return ERROR_SERVER_REMOTE_CLOSED
;
859 if (*separator
!= '=')
861 ERROR("GDB 'set register packet', but no '=' following the register number");
862 return ERROR_SERVER_REMOTE_CLOSED
;
865 /* convert from GDB-string (target-endian) to hex-string (big-endian) */
866 hex_buf
= malloc(CEIL(reg_list
[reg_num
]->size
, 8) * 2);
867 gdb_target_to_str(target
, separator
+ 1, hex_buf
);
869 /* convert hex-string to binary buffer */
870 bin_buf
= malloc(CEIL(reg_list
[reg_num
]->size
, 8));
871 str_to_buf(hex_buf
, CEIL(reg_list
[reg_num
]->size
, 8) * 2, bin_buf
, reg_list
[reg_num
]->size
, 16);
873 /* get register arch_type, and call set method */
874 arch_type
= register_get_arch_type(reg_list
[reg_num
]->arch_type
);
875 if (arch_type
== NULL
)
877 ERROR("BUG: encountered unregistered arch type");
880 arch_type
->set(reg_list
[reg_num
], bin_buf
);
882 gdb_put_packet(connection
, "OK", 2);
891 int gdb_memory_packet_error(connection_t
*connection
, int retval
)
895 case ERROR_TARGET_NOT_HALTED
:
896 ERROR("gdb tried to read memory but we're not halted, dropping connection");
897 return ERROR_SERVER_REMOTE_CLOSED
;
899 case ERROR_TARGET_DATA_ABORT
:
900 gdb_send_error(connection
, EIO
);
902 case ERROR_TARGET_TRANSLATION_FAULT
:
903 gdb_send_error(connection
, EFAULT
);
905 case ERROR_TARGET_UNALIGNED_ACCESS
:
906 gdb_send_error(connection
, EFAULT
);
909 ERROR("BUG: unexpected error %i", retval
);
916 int gdb_read_memory_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
928 /* skip command character */
931 addr
= strtoul(packet
, &separator
, 16);
933 if (*separator
!= ',')
935 ERROR("incomplete read memory packet received, dropping connection");
936 return ERROR_SERVER_REMOTE_CLOSED
;
939 len
= strtoul(separator
+1, NULL
, 16);
941 buffer
= malloc(len
);
943 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
949 retval
= target
->type
->read_memory(target
, addr
, 4, 1, buffer
);
951 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
955 retval
= target
->type
->read_memory(target
, addr
, 2, 1, buffer
);
957 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
960 if (((addr
% 4) == 0) && ((len
% 4) == 0))
961 retval
= target
->type
->read_memory(target
, addr
, 4, len
/ 4, buffer
);
963 retval
= target
->type
->read_memory(target
, addr
, 1, len
, buffer
);
967 if (retval
== ERROR_TARGET_DATA_ABORT
)
969 /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
970 * At some point this might be fixed in GDB, in which case this code can be removed.
971 * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
973 memset(buffer
, 0, len
);
978 if (retval
== ERROR_OK
)
980 hex_buffer
= malloc(len
* 2 + 1);
982 for (i
=0; i
<len
; i
++)
983 snprintf(hex_buffer
+ 2*i
, 3, "%2.2x", buffer
[i
]);
985 gdb_put_packet(connection
, hex_buffer
, len
* 2);
991 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1000 int gdb_write_memory_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1011 /* skip command character */
1014 addr
= strtoul(packet
, &separator
, 16);
1016 if (*separator
!= ',')
1018 ERROR("incomplete write memory packet received, dropping connection");
1019 return ERROR_SERVER_REMOTE_CLOSED
;
1022 len
= strtoul(separator
+1, &separator
, 16);
1024 if (*(separator
++) != ':')
1026 ERROR("incomplete write memory packet received, dropping connection");
1027 return ERROR_SERVER_REMOTE_CLOSED
;
1030 buffer
= malloc(len
);
1032 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
1034 for (i
=0; i
<len
; i
++)
1037 sscanf(separator
+ 2*i
, "%2x", &tmp
);
1044 /* handle sized writes */
1046 if ((addr
% 4) == 0)
1047 retval
= target
->type
->write_memory(target
, addr
, 4, 1, buffer
);
1049 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1052 if ((addr
% 2) == 0)
1053 retval
= target
->type
->write_memory(target
, addr
, 2, 1, buffer
);
1055 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1059 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1061 /* handle bulk writes */
1063 retval
= target_write_buffer(target
, addr
, len
, buffer
);
1067 if (retval
== ERROR_OK
)
1069 gdb_put_packet(connection
, "OK", 2);
1073 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1082 int gdb_write_memory_binary_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1091 /* skip command character */
1094 addr
= strtoul(packet
, &separator
, 16);
1096 if (*separator
!= ',')
1098 ERROR("incomplete write memory binary packet received, dropping connection");
1099 return ERROR_SERVER_REMOTE_CLOSED
;
1102 len
= strtoul(separator
+1, &separator
, 16);
1104 if (*(separator
++) != ':')
1106 ERROR("incomplete write memory binary packet received, dropping connection");
1107 return ERROR_SERVER_REMOTE_CLOSED
;
1113 buffer
= malloc(len
);
1115 DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr
, len
);
1117 memcpy( buffer
, separator
, len
);
1122 if ((addr
% 4) == 0)
1123 retval
= target
->type
->write_memory(target
, addr
, 4, 1, buffer
);
1125 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1128 if ((addr
% 2) == 0)
1129 retval
= target
->type
->write_memory(target
, addr
, 2, 1, buffer
);
1131 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1135 retval
= target
->type
->write_memory(target
, addr
, 1, len
, buffer
);
1138 retval
= target_write_buffer(target
, addr
, len
, buffer
);
1145 if (retval
== ERROR_OK
)
1147 gdb_put_packet(connection
, "OK", 2);
1151 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1158 void gdb_step_continue_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1165 if (packet_size
> 1)
1167 packet
[packet_size
] = 0;
1168 address
= strtoul(packet
+ 1, NULL
, 16);
1175 if (packet
[0] == 'c')
1178 target
->type
->resume(target
, current
, address
, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
1180 else if (packet
[0] == 's')
1183 target
->type
->step(target
, current
, address
, 0); /* step at current or address, don't handle breakpoints */
1187 int gdb_bp_wp_packet_error(connection_t
*connection
, int retval
)
1191 case ERROR_TARGET_NOT_HALTED
:
1192 ERROR("gdb tried to set a breakpoint but we're not halted, dropping connection");
1193 return ERROR_SERVER_REMOTE_CLOSED
;
1195 case ERROR_TARGET_RESOURCE_NOT_AVAILABLE
:
1196 gdb_send_error(connection
, EBUSY
);
1199 ERROR("BUG: unexpected error %i", retval
);
1206 int gdb_breakpoint_watchpoint_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1209 enum breakpoint_type bp_type
= BKPT_SOFT
/* dummy init to avoid warning */;
1210 enum watchpoint_rw wp_type
;
1218 type
= strtoul(packet
+ 1, &separator
, 16);
1220 if (type
== 0) /* memory breakpoint */
1221 bp_type
= BKPT_SOFT
;
1222 else if (type
== 1) /* hardware breakpoint */
1223 bp_type
= BKPT_HARD
;
1224 else if (type
== 2) /* write watchpoint */
1225 wp_type
= WPT_WRITE
;
1226 else if (type
== 3) /* read watchpoint */
1228 else if (type
== 4) /* access watchpoint */
1229 wp_type
= WPT_ACCESS
;
1231 if (*separator
!= ',')
1233 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1234 return ERROR_SERVER_REMOTE_CLOSED
;
1237 address
= strtoul(separator
+1, &separator
, 16);
1239 if (*separator
!= ',')
1241 ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
1242 return ERROR_SERVER_REMOTE_CLOSED
;
1245 size
= strtoul(separator
+1, &separator
, 16);
1251 if (packet
[0] == 'Z')
1253 if ((retval
= breakpoint_add(target
, address
, size
, bp_type
)) != ERROR_OK
)
1255 if ((retval
= gdb_bp_wp_packet_error(connection
, retval
)) != ERROR_OK
)
1260 gdb_put_packet(connection
, "OK", 2);
1265 breakpoint_remove(target
, address
);
1266 gdb_put_packet(connection
, "OK", 2);
1273 if (packet
[0] == 'Z')
1275 if ((retval
= watchpoint_add(target
, address
, size
, type
-2, 0, 0xffffffffu
)) != ERROR_OK
)
1277 if ((retval
= gdb_bp_wp_packet_error(connection
, retval
)) != ERROR_OK
)
1282 gdb_put_packet(connection
, "OK", 2);
1287 watchpoint_remove(target
, address
);
1288 gdb_put_packet(connection
, "OK", 2);
1299 /* print out a string and allocate more space as needed, mainly used for XML at this point */
1300 void xml_printf(int *retval
, char **xml
, int *pos
, int *size
, const char *fmt
, ...)
1302 if (*retval
!= ERROR_OK
)
1310 if ((*xml
== NULL
) || (!first
))
1312 /* start by 0 to exercise all the code paths.
1313 * Need minimum 2 bytes to fit 1 char and 0 terminator. */
1315 *size
= *size
* 2 + 2;
1317 *xml
= realloc(*xml
, *size
);
1322 *retval
= ERROR_SERVER_REMOTE_CLOSED
;
1330 ret
= vsnprintf(*xml
+ *pos
, *size
- *pos
, fmt
, ap
);
1332 if ((ret
> 0) && ((ret
+ 1) < *size
- *pos
))
1337 /* there was just enough or not enough space, allocate more. */
1342 static int decode_xfer_read (char *buf
, char **annex
, int *ofs
, unsigned int *len
)
1346 /* Extract and NUL-terminate the annex. */
1348 while (*buf
&& *buf
!= ':')
1354 /* After the read marker and annex, qXfer looks like a
1355 * traditional 'm' packet. */
1357 *ofs
= strtoul(buf
, &separator
, 16);
1359 if (*separator
!= ',')
1362 *len
= strtoul(separator
+1, NULL
, 16);
1367 int gdb_query_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1369 command_context_t
*cmd_ctx
= connection
->cmd_ctx
;
1371 if (strstr(packet
, "qRcmd,"))
1373 if (packet_size
> 6)
1377 cmd
= malloc((packet_size
- 6)/2 + 1);
1378 for (i
=0; i
< (packet_size
- 6)/2; i
++)
1381 sscanf(packet
+ 6 + 2*i
, "%2x", &tmp
);
1384 cmd
[(packet_size
- 6)/2] = 0x0;
1385 target_call_timer_callbacks();
1386 command_run_line(cmd_ctx
, cmd
);
1389 gdb_put_packet(connection
, "OK", 2);
1392 else if (strstr(packet
, "qCRC:"))
1394 if (packet_size
> 5)
1403 /* skip command character */
1406 addr
= strtoul(packet
, &separator
, 16);
1408 if (*separator
!= ',')
1410 ERROR("incomplete read memory packet received, dropping connection");
1411 return ERROR_SERVER_REMOTE_CLOSED
;
1414 len
= strtoul(separator
+ 1, NULL
, 16);
1416 retval
= target_checksum_memory(target
, addr
, len
, &checksum
);
1418 if (retval
== ERROR_OK
)
1420 snprintf(gdb_reply
, 10, "C%8.8x", checksum
);
1421 gdb_put_packet(connection
, gdb_reply
, 9);
1425 if ((retval
= gdb_memory_packet_error(connection
, retval
)) != ERROR_OK
)
1432 else if (strstr(packet
, "qSupported"))
1434 /* we currently support packet size and qXfer:memory-map:read (if enabled)
1435 * disable qXfer:features:read for the moment */
1436 int retval
= ERROR_OK
;
1437 char *buffer
= NULL
;
1441 xml_printf(&retval
, &buffer
, &pos
, &size
,
1442 "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
1443 (GDB_BUFFER_SIZE
- 1), gdb_use_memory_map
== 1 ? '+' : '-');
1445 if (retval
!= ERROR_OK
)
1447 gdb_send_error(connection
, 01);
1451 gdb_put_packet(connection
, buffer
, strlen(buffer
));
1456 else if (strstr(packet
, "qXfer:memory-map:read::"))
1458 /* We get away with only specifying flash here. Regions that are not
1459 * specified are treated as if we provided no memory map(if not we
1460 * could detect the holes and mark them as RAM).
1461 * Normally we only execute this code once, but no big deal if we
1462 * have to regenerate it a couple of times. */
1468 int retval
= ERROR_OK
;
1474 /* skip command character */
1477 offset
= strtoul(packet
, &separator
, 16);
1478 length
= strtoul(separator
+ 1, &separator
, 16);
1480 xml_printf(&retval
, &xml
, &pos
, &size
, "<memory-map>\n");
1485 p
= get_flash_bank_by_num(i
);
1489 xml_printf(&retval
, &xml
, &pos
, &size
, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
1490 "<property name=\"blocksize\">0x%x</property>\n" \
1492 p
->base
, p
->size
, p
->size
/p
->num_sectors
);
1496 xml_printf(&retval
, &xml
, &pos
, &size
, "</memory-map>\n");
1498 if (retval
!= ERROR_OK
)
1500 gdb_send_error(connection
, retval
);
1504 if (offset
+ length
> pos
)
1506 length
= pos
- offset
;
1509 char *t
= malloc(length
+ 1);
1511 memcpy(t
+ 1, xml
+ offset
, length
);
1512 gdb_put_packet(connection
, t
, length
+ 1);
1518 else if (strstr(packet
, "qXfer:features:read:"))
1523 int retval
= ERROR_OK
;
1529 /* skip command character */
1532 if (decode_xfer_read( packet
, &annex
, &offset
, &length
) < 0)
1534 gdb_send_error(connection
, 01);
1538 if (strcmp(annex
, "target.xml") != 0)
1540 gdb_send_error(connection
, 01);
1544 xml_printf(&retval
, &xml
, &pos
, &size
, \
1545 "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
1547 if (retval
!= ERROR_OK
)
1549 gdb_send_error(connection
, retval
);
1553 gdb_put_packet(connection
, xml
, strlen(xml
) + 1);
1559 gdb_put_packet(connection
, "", 0);
1563 int gdb_v_packet(connection_t
*connection
, target_t
*target
, char *packet
, int packet_size
)
1565 gdb_connection_t
*gdb_connection
= connection
->priv
;
1566 gdb_service_t
*gdb_service
= connection
->service
->priv
;
1569 /* if flash programming disabled - send a empty reply */
1571 if (gdb_flash_program
== 0)
1573 gdb_put_packet(connection
, "", 0);
1577 if (strstr(packet
, "vFlashErase:"))
1580 unsigned long length
;
1582 char *parse
= packet
+ 12;
1585 ERROR("incomplete vFlashErase packet received, dropping connection");
1586 return ERROR_SERVER_REMOTE_CLOSED
;
1589 addr
= strtoul(parse
, &parse
, 16);
1591 if (*(parse
++) != ',' || *parse
== '\0')
1593 ERROR("incomplete vFlashErase packet received, dropping connection");
1594 return ERROR_SERVER_REMOTE_CLOSED
;
1597 length
= strtoul(parse
, &parse
, 16);
1601 ERROR("incomplete vFlashErase packet received, dropping connection");
1602 return ERROR_SERVER_REMOTE_CLOSED
;
1605 /* disable gdb output while programming */
1606 gdb_connection
->output_disable
= 1;
1608 /* assume all sectors need erasing - stops any problems
1609 * when flash_write is called multiple times */
1612 /* perform any target specific operations before the erase */
1613 target_call_event_callbacks(gdb_service
->target
, TARGET_EVENT_GDB_PROGRAM
);
1616 if ((result
= flash_erase_address_range(gdb_service
->target
, addr
, length
)) != ERROR_OK
)
1618 /* GDB doesn't evaluate the actual error number returned,
1619 * treat a failed erase as an I/O error
1621 gdb_send_error(connection
, EIO
);
1622 ERROR("flash_erase returned %i", result
);
1625 gdb_put_packet(connection
, "OK", 2);
1627 /* reenable gdb output */
1628 gdb_connection
->output_disable
= 0;
1633 if (strstr(packet
, "vFlashWrite:"))
1636 unsigned long length
;
1637 char *parse
= packet
+ 12;
1641 ERROR("incomplete vFlashErase packet received, dropping connection");
1642 return ERROR_SERVER_REMOTE_CLOSED
;
1644 addr
= strtoul(parse
, &parse
, 16);
1645 if (*(parse
++) != ':')
1647 ERROR("incomplete vFlashErase packet received, dropping connection");
1648 return ERROR_SERVER_REMOTE_CLOSED
;
1650 length
= packet_size
- (parse
- packet
);
1652 /* disable gdb output while programming */
1653 gdb_connection
->output_disable
= 1;
1655 /* create a new image if there isn't already one */
1656 if (gdb_connection
->vflash_image
== NULL
)
1658 gdb_connection
->vflash_image
= malloc(sizeof(image_t
));
1659 image_open(gdb_connection
->vflash_image
, "", "build");
1662 /* create new section with content from packet buffer */
1663 image_add_section(gdb_connection
->vflash_image
, addr
, length
, 0x0, (u8
*)parse
);
1665 gdb_put_packet(connection
, "OK", 2);
1667 /* reenable gdb output */
1668 gdb_connection
->output_disable
= 0;
1673 if (!strcmp(packet
, "vFlashDone"))
1678 /* disable gdb output while programming */
1679 gdb_connection
->output_disable
= 1;
1681 /* process the flashing buffer. No need to erase as GDB
1682 * always issues a vFlashErase first. */
1683 if ((result
= flash_write(gdb_service
->target
, gdb_connection
->vflash_image
, &written
, &error_str
, NULL
, 0)) != ERROR_OK
)
1685 if (result
== ERROR_FLASH_DST_OUT_OF_BANK
)
1686 gdb_put_packet(connection
, "E.memtype", 9);
1688 gdb_send_error(connection
, EIO
);
1692 ERROR("flash writing failed: %s", error_str
);
1698 DEBUG("wrote %u bytes from vFlash image to flash", written
);
1699 gdb_put_packet(connection
, "OK", 2);
1702 image_close(gdb_connection
->vflash_image
);
1703 free(gdb_connection
->vflash_image
);
1704 gdb_connection
->vflash_image
= NULL
;
1706 /* reenable gdb output */
1707 gdb_connection
->output_disable
= 0;
1712 gdb_put_packet(connection
, "", 0);
1716 int gdb_detach(connection_t
*connection
, target_t
*target
)
1718 switch( detach_mode
)
1720 case GDB_DETACH_RESUME
:
1721 target
->type
->resume(target
, 1, 0, 1, 0);
1724 case GDB_DETACH_RESET
:
1725 target_process_reset(connection
->cmd_ctx
);
1728 case GDB_DETACH_HALT
:
1729 target
->type
->halt(target
);
1732 case GDB_DETACH_NOTHING
:
1736 gdb_put_packet(connection
, "OK", 2);
1741 int gdb_input(connection_t
*connection
)
1743 gdb_service_t
*gdb_service
= connection
->service
->priv
;
1744 target_t
*target
= gdb_service
->target
;
1745 char packet
[GDB_BUFFER_SIZE
];
1748 gdb_connection_t
*gdb_con
= connection
->priv
;
1749 static int extended_protocol
= 0;
1751 /* drain input buffer */
1754 packet_size
= GDB_BUFFER_SIZE
-1;
1755 if ((retval
= gdb_get_packet(connection
, packet
, &packet_size
)) != ERROR_OK
)
1759 case ERROR_GDB_BUFFER_TOO_SMALL
:
1760 ERROR("BUG: buffer supplied for gdb packet was too small");
1762 case ERROR_SERVER_REMOTE_CLOSED
:
1763 return ERROR_SERVER_REMOTE_CLOSED
;
1765 ERROR("BUG: unexpected error");
1770 /* terminate with zero */
1771 packet
[packet_size
] = 0;
1773 DEBUG("received packet: '%s'", packet
);
1775 if (packet_size
> 0)
1781 /* Hct... -- set thread
1782 * we don't have threads, send empty reply */
1783 gdb_put_packet(connection
, NULL
, 0);
1786 retval
= gdb_query_packet(connection
, target
, packet
, packet_size
);
1789 retval
= gdb_get_registers_packet(connection
, target
, packet
, packet_size
);
1792 retval
= gdb_set_registers_packet(connection
, target
, packet
, packet_size
);
1795 retval
= gdb_get_register_packet(connection
, target
, packet
, packet_size
);
1798 retval
= gdb_set_register_packet(connection
, target
, packet
, packet_size
);
1801 retval
= gdb_read_memory_packet(connection
, target
, packet
, packet_size
);
1804 retval
= gdb_write_memory_packet(connection
, target
, packet
, packet_size
);
1808 retval
= gdb_breakpoint_watchpoint_packet(connection
, target
, packet
, packet_size
);
1811 gdb_last_signal_packet(connection
, target
, packet
, packet_size
);
1815 gdb_step_continue_packet(connection
, target
, packet
, packet_size
);
1818 retval
= gdb_v_packet(connection
, target
, packet
, packet_size
);
1821 retval
= gdb_detach(connection
, target
);
1822 extended_protocol
= 0;
1825 if ((retval
= gdb_write_memory_binary_packet(connection
, target
, packet
, packet_size
)) != ERROR_OK
)
1829 if (extended_protocol
!= 0)
1831 gdb_put_packet(connection
, "OK", 2);
1832 return ERROR_SERVER_REMOTE_CLOSED
;
1834 /* handle extended remote protocol */
1835 extended_protocol
= 1;
1836 gdb_put_packet(connection
, "OK", 2);
1839 /* handle extended restart packet */
1840 target_process_reset(connection
->cmd_ctx
);
1843 /* ignore unkown packets */
1844 DEBUG("ignoring 0x%2.2x packet", packet
[0]);
1845 gdb_put_packet(connection
, NULL
, 0);
1849 /* if a packet handler returned an error, exit input loop */
1850 if (retval
!= ERROR_OK
)
1854 if (gdb_con
->ctrl_c
)
1856 if (target
->state
== TARGET_RUNNING
)
1858 target
->type
->halt(target
);
1859 gdb_con
->ctrl_c
= 0;
1863 } while (gdb_con
->buf_cnt
> 0);
1870 gdb_service_t
*gdb_service
;
1871 target_t
*target
= targets
;
1876 WARNING("no gdb ports allocated as no target has been specified");
1882 WARNING("no gdb port specified, using default port 3333");
1888 char service_name
[8];
1890 snprintf(service_name
, 8, "gdb-%2.2i", i
);
1892 gdb_service
= malloc(sizeof(gdb_service_t
));
1893 gdb_service
->target
= target
;
1895 add_service("gdb", CONNECTION_GDB
, gdb_port
+ i
, 1, gdb_new_connection
, gdb_input
, gdb_connection_closed
, gdb_service
);
1897 DEBUG("gdb service for target %s at port %i", target
->type
->name
, gdb_port
+ i
);
1900 target
= target
->next
;
1906 /* daemon configuration command gdb_port */
1907 int handle_gdb_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1912 /* only if the port wasn't overwritten by cmdline */
1914 gdb_port
= strtoul(args
[0], NULL
, 0);
1919 int handle_gdb_detach_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1923 if (strcmp(args
[0], "resume") == 0)
1925 detach_mode
= GDB_DETACH_RESUME
;
1928 else if (strcmp(args
[0], "reset") == 0)
1930 detach_mode
= GDB_DETACH_RESET
;
1933 else if (strcmp(args
[0], "halt") == 0)
1935 detach_mode
= GDB_DETACH_HALT
;
1938 else if (strcmp(args
[0], "nothing") == 0)
1940 detach_mode
= GDB_DETACH_NOTHING
;
1945 WARNING("invalid gdb_detach configuration directive: %s", args
[0]);
1949 int handle_gdb_memory_map_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1953 if (strcmp(args
[0], "enable") == 0)
1955 gdb_use_memory_map
= 1;
1958 else if (strcmp(args
[0], "disable") == 0)
1960 gdb_use_memory_map
= 0;
1965 WARNING("invalid gdb_memory_map configuration directive: %s", args
[0]);
1969 int handle_gdb_flash_program_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
1973 if (strcmp(args
[0], "enable") == 0)
1975 gdb_flash_program
= 1;
1978 else if (strcmp(args
[0], "disable") == 0)
1980 gdb_flash_program
= 0;
1985 WARNING("invalid gdb_memory_map configuration directive: %s", args
[0]);
1989 int gdb_register_commands(command_context_t
*command_context
)
1991 register_command(command_context
, NULL
, "gdb_port", handle_gdb_port_command
,
1992 COMMAND_CONFIG
, "");
1993 register_command(command_context
, NULL
, "gdb_detach", handle_gdb_detach_command
,
1994 COMMAND_CONFIG
, "");
1995 register_command(command_context
, NULL
, "gdb_memory_map", handle_gdb_memory_map_command
,
1996 COMMAND_CONFIG
, "");
1997 register_command(command_context
, NULL
, "gdb_flash_program", handle_gdb_flash_program_command
,
1998 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)