1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) 2007-2010 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
10 * Copyright (C) 2008 by Spencer Oliver *
11 * spen@spen-soft.co.uk *
12 ***************************************************************************/
20 #include "replacements.h"
21 #include "time_support.h"
22 #include <server/gdb_server.h>
23 #include <server/server.h>
27 #ifdef _DEBUG_FREE_SPACE_
31 #error "malloc.h is required to use --enable-malloc-logging"
35 int debug_level
= LOG_LVL_INFO
;
37 static FILE *log_output
;
38 static struct log_callback
*log_callbacks
;
40 static int64_t last_time
;
44 static const char * const log_strings
[6] = {
47 "Warn : ", /* want a space after each colon, all same width, colons aligned */
55 /* forward the log to the listeners */
56 static void log_forward(const char *file
, unsigned line
, const char *function
, const char *string
)
58 struct log_callback
*cb
, *next
;
60 /* DANGER!!!! the log callback can remove itself!!!! */
63 cb
->fn(cb
->priv
, file
, line
, function
, string
);
68 /* The log_puts() serves two somewhat different goals:
71 * - feeding low-level info to the user in GDB or Telnet
73 * The latter dictates that strings without newline are not logged, lest there
74 * will be *MANY log lines when sending one char at the time(e.g.
78 static void log_puts(enum log_levels level
,
87 /* log_init() not called yet; print on stderr */
88 fputs(string
, stderr
);
93 if (level
== LOG_LVL_OUTPUT
) {
94 /* do not prepend any headers, just print out what we were given and return */
95 fputs(string
, log_output
);
100 f
= strrchr(file
, '/');
104 if (debug_level
>= LOG_LVL_DEBUG
) {
105 /* print with count and time information */
106 int64_t t
= timeval_ms() - start
;
107 #ifdef _DEBUG_FREE_SPACE_
108 struct mallinfo info
;
111 fprintf(log_output
, "%s%d %" PRId64
" %s:%d %s()"
112 #ifdef _DEBUG_FREE_SPACE_
115 ": %s", log_strings
[level
+ 1], count
, t
, file
, line
, function
,
116 #ifdef _DEBUG_FREE_SPACE_
121 /* if we are using gdb through pipes then we do not want any output
122 * to the pipe otherwise we get repeated strings */
123 fprintf(log_output
, "%s%s",
124 (level
> LOG_LVL_USER
) ? log_strings
[level
+ 1] : "", string
);
129 /* Never forward LOG_LVL_DEBUG, too verbose and they can be found in the log if need be */
130 if (level
<= LOG_LVL_INFO
)
131 log_forward(file
, line
, function
, string
);
134 void log_printf(enum log_levels level
,
137 const char *function
,
145 if (level
> debug_level
)
148 va_start(ap
, format
);
150 string
= alloc_vprintf(format
, ap
);
152 log_puts(level
, file
, line
, function
, string
);
159 void log_vprintf_lf(enum log_levels level
, const char *file
, unsigned line
,
160 const char *function
, const char *format
, va_list args
)
166 if (level
> debug_level
)
169 tmp
= alloc_vprintf(format
, args
);
175 * Note: alloc_vprintf() guarantees that the buffer is at least one
179 log_puts(level
, file
, line
, function
, tmp
);
183 void log_printf_lf(enum log_levels level
,
186 const char *function
,
192 va_start(ap
, format
);
193 log_vprintf_lf(level
, file
, line
, function
, format
, ap
);
197 COMMAND_HANDLER(handle_debug_level_command
)
201 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], new_level
);
202 if ((new_level
> LOG_LVL_DEBUG_IO
) || (new_level
< LOG_LVL_SILENT
)) {
203 LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT
, LOG_LVL_DEBUG_IO
);
204 return ERROR_COMMAND_SYNTAX_ERROR
;
206 debug_level
= new_level
;
207 } else if (CMD_ARGC
> 1)
208 return ERROR_COMMAND_SYNTAX_ERROR
;
210 command_print(CMD
, "debug_level: %i", debug_level
);
215 COMMAND_HANDLER(handle_log_output_command
)
218 return ERROR_COMMAND_SYNTAX_ERROR
;
221 if (CMD_ARGC
== 1 && strcmp(CMD_ARGV
[0], "default") != 0) {
222 file
= fopen(CMD_ARGV
[0], "w");
224 command_print(CMD
, "failed to open output log \"%s\"", CMD_ARGV
[0]);
227 command_print(CMD
, "set log_output to \"%s\"", CMD_ARGV
[0]);
230 command_print(CMD
, "set log_output to default");
233 if (log_output
!= stderr
&& log_output
) {
234 /* Close previous log file, if it was open and wasn't stderr. */
241 static const struct command_registration log_command_handlers
[] = {
243 .name
= "log_output",
244 .handler
= handle_log_output_command
,
246 .help
= "redirect logging to a file (default: stderr)",
247 .usage
= "[file_name | 'default']",
250 .name
= "debug_level",
251 .handler
= handle_debug_level_command
,
253 .help
= "Sets the verbosity level of debugging output. "
254 "0 shows errors only; 1 adds warnings; "
255 "2 (default) adds other info; 3 adds debugging; "
256 "4 adds extra verbose debugging.",
259 COMMAND_REGISTRATION_DONE
262 int log_register_commands(struct command_context
*cmd_ctx
)
264 return register_commands(cmd_ctx
, NULL
, log_command_handlers
);
269 /* set defaults for daemon configuration,
270 * if not set by cmdline or cfgfile */
271 char *debug_env
= getenv("OPENOCD_DEBUG_LEVEL");
274 int retval
= parse_int(debug_env
, &value
);
275 if (retval
== ERROR_OK
&&
276 debug_level
>= LOG_LVL_SILENT
&&
277 debug_level
<= LOG_LVL_DEBUG_IO
)
284 start
= last_time
= timeval_ms();
289 if (log_output
&& log_output
!= stderr
) {
290 /* Close log file, if it was open and wasn't stderr. */
296 /* add/remove log callback handler */
297 int log_add_callback(log_callback_fn fn
, void *priv
)
299 struct log_callback
*cb
;
301 /* prevent the same callback to be registered more than once, just for sure */
302 for (cb
= log_callbacks
; cb
; cb
= cb
->next
) {
303 if (cb
->fn
== fn
&& cb
->priv
== priv
)
304 return ERROR_COMMAND_SYNTAX_ERROR
;
307 /* alloc memory, it is safe just to return in case of an error, no need for the caller to
309 cb
= malloc(sizeof(struct log_callback
));
311 return ERROR_BUF_TOO_SMALL
;
313 /* add item to the beginning of the linked list */
316 cb
->next
= log_callbacks
;
322 int log_remove_callback(log_callback_fn fn
, void *priv
)
324 struct log_callback
*cb
, **p
;
326 for (p
= &log_callbacks
; (cb
= *p
); p
= &(*p
)->next
) {
327 if (cb
->fn
== fn
&& cb
->priv
== priv
) {
335 return ERROR_COMMAND_SYNTAX_ERROR
;
338 /* return allocated string w/printf() result */
339 char *alloc_vprintf(const char *fmt
, va_list ap
)
345 /* determine the length of the buffer needed */
346 va_copy(ap_copy
, ap
);
347 len
= vsnprintf(NULL
, 0, fmt
, ap_copy
);
350 /* allocate and make room for terminating zero. */
351 /* FIXME: The old version always allocated at least one byte extra and
352 * other code depend on that. They should be probably be fixed, but for
353 * now reserve the extra byte. */
354 string
= malloc(len
+ 2);
358 /* do the real work */
359 vsnprintf(string
, len
+ 1, fmt
, ap
);
364 char *alloc_printf(const char *format
, ...)
368 va_start(ap
, format
);
369 string
= alloc_vprintf(format
, ap
);
374 /* Code must return to the server loop before 1000ms has returned or invoke
377 * The GDB connection will time out if it spends >2000ms and you'll get nasty
378 * error messages from GDB:
380 * Ignoring packet error, continuing...
381 * Reply contains invalid hex digit 116
383 * While it is possible use "set remotetimeout" to more than the default 2000ms
384 * in GDB, OpenOCD guarantees that it sends keep-alive packages on the
385 * GDB protocol and it is a bug in OpenOCD not to either return to the server
386 * loop or invoke keep_alive() every 1000ms.
388 * This function will send a keep alive packet if >500ms has passed since last time
391 * Note that this function can be invoked often, so it needs to be relatively
392 * fast when invoked more often than every 500ms.
395 #define KEEP_ALIVE_KICK_TIME_MS 500
396 #define KEEP_ALIVE_TIMEOUT_MS 1000
398 static void gdb_timeout_warning(int64_t delta_time
)
400 if (gdb_get_actual_connections())
401 LOG_WARNING("keep_alive() was not invoked in the "
402 "%d ms timelimit. GDB alive packet not "
403 "sent! (%" PRId64
" ms). Workaround: increase "
404 "\"set remotetimeout\" in GDB",
405 KEEP_ALIVE_TIMEOUT_MS
,
408 LOG_DEBUG("keep_alive() was not invoked in the "
409 "%d ms timelimit (%" PRId64
" ms). This may cause "
410 "trouble with GDB connections.",
411 KEEP_ALIVE_TIMEOUT_MS
,
415 void keep_alive(void)
417 int64_t current_time
= timeval_ms();
418 int64_t delta_time
= current_time
- last_time
;
420 if (delta_time
> KEEP_ALIVE_TIMEOUT_MS
) {
421 last_time
= current_time
;
423 gdb_timeout_warning(delta_time
);
426 if (delta_time
> KEEP_ALIVE_KICK_TIME_MS
) {
427 last_time
= current_time
;
429 /* this will keep the GDB connection alive */
430 server_keep_clients_alive();
432 /* DANGER!!!! do not add code to invoke e.g. target event processing,
433 * jim timer processing, etc. it can cause infinite recursion +
434 * jim event callbacks need to happen at a well defined time,
435 * not anywhere keep_alive() is invoked.
437 * These functions should be invoked at a well defined spot in server.c
442 /* reset keep alive timer without sending message */
443 void kept_alive(void)
445 int64_t current_time
= timeval_ms();
447 int64_t delta_time
= current_time
- last_time
;
449 last_time
= current_time
;
451 if (delta_time
> KEEP_ALIVE_TIMEOUT_MS
)
452 gdb_timeout_warning(delta_time
);
455 /* if we sleep for extended periods of time, we must invoke keep_alive() intermittently */
456 void alive_sleep(uint64_t ms
)
458 uint64_t nap_time
= 10;
459 for (uint64_t i
= 0; i
< ms
; i
+= nap_time
) {
460 uint64_t sleep_a_bit
= ms
- i
;
461 if (sleep_a_bit
> nap_time
)
462 sleep_a_bit
= nap_time
;
464 usleep(sleep_a_bit
* 1000);
469 void busy_sleep(uint64_t ms
)
471 uint64_t then
= timeval_ms();
472 while (timeval_ms() - then
< ms
) {
479 /* Maximum size of socket error message retrieved from operation system */
480 #define MAX_SOCKET_ERR_MSG_LENGTH 256
482 /* Provide log message for the last socket error.
483 Uses errno on *nix and WSAGetLastError() on Windows */
484 void log_socket_error(const char *socket_desc
)
488 error_code
= WSAGetLastError();
489 char error_message
[MAX_SOCKET_ERR_MSG_LENGTH
];
490 error_message
[0] = '\0';
491 DWORD retval
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error_code
, 0,
492 error_message
, MAX_SOCKET_ERR_MSG_LENGTH
, NULL
);
493 error_message
[MAX_SOCKET_ERR_MSG_LENGTH
- 1] = '\0';
494 const bool have_message
= (retval
!= 0) && (error_message
[0] != '\0');
495 LOG_ERROR("Error on socket '%s': WSAGetLastError==%d%s%s.", socket_desc
, error_code
,
496 (have_message
? ", message: " : ""),
497 (have_message
? error_message
: ""));
500 LOG_ERROR("Error on socket '%s': errno==%d, message: %s.", socket_desc
, error_code
, strerror(error_code
));
505 * Find the first non-printable character in the char buffer, return a pointer to it.
506 * If no such character exists, return NULL.
508 char *find_nonprint_char(char *buf
, unsigned buf_len
)
510 for (unsigned int i
= 0; i
< buf_len
; i
++) {
511 if (!isprint(buf
[i
]))
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)