jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / helper / log.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2007-2010 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * Copyright (C) 2008 by Spencer Oliver *
11 * spen@spen-soft.co.uk *
12 ***************************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include "log.h"
19 #include "command.h"
20 #include "replacements.h"
21 #include "time_support.h"
22 #include <server/gdb_server.h>
23 #include <server/server.h>
24
25 #include <stdarg.h>
26
27 #ifdef _DEBUG_FREE_SPACE_
28 #ifdef HAVE_MALLOC_H
29 #include <malloc.h>
30 #else
31 #error "malloc.h is required to use --enable-malloc-logging"
32 #endif
33 #endif
34
35 int debug_level = LOG_LVL_INFO;
36
37 static FILE *log_output;
38 static struct log_callback *log_callbacks;
39
40 static int64_t last_time;
41
42 static int64_t start;
43
44 static const char * const log_strings[6] = {
45 "User : ",
46 "Error: ",
47 "Warn : ", /* want a space after each colon, all same width, colons aligned */
48 "Info : ",
49 "Debug: ",
50 "Debug: "
51 };
52
53 static int count;
54
55 /* forward the log to the listeners */
56 static void log_forward(const char *file, unsigned line, const char *function, const char *string)
57 {
58 struct log_callback *cb, *next;
59 cb = log_callbacks;
60 /* DANGER!!!! the log callback can remove itself!!!! */
61 while (cb) {
62 next = cb->next;
63 cb->fn(cb->priv, file, line, function, string);
64 cb = next;
65 }
66 }
67
68 /* The log_puts() serves two somewhat different goals:
69 *
70 * - logging
71 * - feeding low-level info to the user in GDB or Telnet
72 *
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.
75 * target_request.c).
76 *
77 */
78 static void log_puts(enum log_levels level,
79 const char *file,
80 int line,
81 const char *function,
82 const char *string)
83 {
84 char *f;
85
86 if (!log_output) {
87 /* log_init() not called yet; print on stderr */
88 fputs(string, stderr);
89 fflush(stderr);
90 return;
91 }
92
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);
96 fflush(log_output);
97 return;
98 }
99
100 f = strrchr(file, '/');
101 if (f)
102 file = f + 1;
103
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;
109 info = mallinfo();
110 #endif
111 fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()"
112 #ifdef _DEBUG_FREE_SPACE_
113 " %d"
114 #endif
115 ": %s", log_strings[level + 1], count, t, file, line, function,
116 #ifdef _DEBUG_FREE_SPACE_
117 info.fordblks,
118 #endif
119 string);
120 } else {
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);
125 }
126
127 fflush(log_output);
128
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);
132 }
133
134 void log_printf(enum log_levels level,
135 const char *file,
136 unsigned line,
137 const char *function,
138 const char *format,
139 ...)
140 {
141 char *string;
142 va_list ap;
143
144 count++;
145 if (level > debug_level)
146 return;
147
148 va_start(ap, format);
149
150 string = alloc_vprintf(format, ap);
151 if (string) {
152 log_puts(level, file, line, function, string);
153 free(string);
154 }
155
156 va_end(ap);
157 }
158
159 void log_vprintf_lf(enum log_levels level, const char *file, unsigned line,
160 const char *function, const char *format, va_list args)
161 {
162 char *tmp;
163
164 count++;
165
166 if (level > debug_level)
167 return;
168
169 tmp = alloc_vprintf(format, args);
170
171 if (!tmp)
172 return;
173
174 /*
175 * Note: alloc_vprintf() guarantees that the buffer is at least one
176 * character longer.
177 */
178 strcat(tmp, "\n");
179 log_puts(level, file, line, function, tmp);
180 free(tmp);
181 }
182
183 void log_printf_lf(enum log_levels level,
184 const char *file,
185 unsigned line,
186 const char *function,
187 const char *format,
188 ...)
189 {
190 va_list ap;
191
192 va_start(ap, format);
193 log_vprintf_lf(level, file, line, function, format, ap);
194 va_end(ap);
195 }
196
197 COMMAND_HANDLER(handle_debug_level_command)
198 {
199 if (CMD_ARGC == 1) {
200 int new_level;
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;
205 }
206 debug_level = new_level;
207 } else if (CMD_ARGC > 1)
208 return ERROR_COMMAND_SYNTAX_ERROR;
209
210 command_print(CMD, "debug_level: %i", debug_level);
211
212 return ERROR_OK;
213 }
214
215 COMMAND_HANDLER(handle_log_output_command)
216 {
217 if (CMD_ARGC > 1)
218 return ERROR_COMMAND_SYNTAX_ERROR;
219
220 FILE *file;
221 if (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") != 0) {
222 file = fopen(CMD_ARGV[0], "w");
223 if (!file) {
224 command_print(CMD, "failed to open output log \"%s\"", CMD_ARGV[0]);
225 return ERROR_FAIL;
226 }
227 command_print(CMD, "set log_output to \"%s\"", CMD_ARGV[0]);
228 } else {
229 file = stderr;
230 command_print(CMD, "set log_output to default");
231 }
232
233 if (log_output != stderr && log_output) {
234 /* Close previous log file, if it was open and wasn't stderr. */
235 fclose(log_output);
236 }
237 log_output = file;
238 return ERROR_OK;
239 }
240
241 static const struct command_registration log_command_handlers[] = {
242 {
243 .name = "log_output",
244 .handler = handle_log_output_command,
245 .mode = COMMAND_ANY,
246 .help = "redirect logging to a file (default: stderr)",
247 .usage = "[file_name | 'default']",
248 },
249 {
250 .name = "debug_level",
251 .handler = handle_debug_level_command,
252 .mode = COMMAND_ANY,
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.",
257 .usage = "number",
258 },
259 COMMAND_REGISTRATION_DONE
260 };
261
262 int log_register_commands(struct command_context *cmd_ctx)
263 {
264 return register_commands(cmd_ctx, NULL, log_command_handlers);
265 }
266
267 void log_init(void)
268 {
269 /* set defaults for daemon configuration,
270 * if not set by cmdline or cfgfile */
271 char *debug_env = getenv("OPENOCD_DEBUG_LEVEL");
272 if (debug_env) {
273 int value;
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)
278 debug_level = value;
279 }
280
281 if (!log_output)
282 log_output = stderr;
283
284 start = last_time = timeval_ms();
285 }
286
287 void log_exit(void)
288 {
289 if (log_output && log_output != stderr) {
290 /* Close log file, if it was open and wasn't stderr. */
291 fclose(log_output);
292 }
293 log_output = NULL;
294 }
295
296 /* add/remove log callback handler */
297 int log_add_callback(log_callback_fn fn, void *priv)
298 {
299 struct log_callback *cb;
300
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;
305 }
306
307 /* alloc memory, it is safe just to return in case of an error, no need for the caller to
308 *check this */
309 cb = malloc(sizeof(struct log_callback));
310 if (!cb)
311 return ERROR_BUF_TOO_SMALL;
312
313 /* add item to the beginning of the linked list */
314 cb->fn = fn;
315 cb->priv = priv;
316 cb->next = log_callbacks;
317 log_callbacks = cb;
318
319 return ERROR_OK;
320 }
321
322 int log_remove_callback(log_callback_fn fn, void *priv)
323 {
324 struct log_callback *cb, **p;
325
326 for (p = &log_callbacks; (cb = *p); p = &(*p)->next) {
327 if (cb->fn == fn && cb->priv == priv) {
328 *p = cb->next;
329 free(cb);
330 return ERROR_OK;
331 }
332 }
333
334 /* no such item */
335 return ERROR_COMMAND_SYNTAX_ERROR;
336 }
337
338 /* return allocated string w/printf() result */
339 char *alloc_vprintf(const char *fmt, va_list ap)
340 {
341 va_list ap_copy;
342 int len;
343 char *string;
344
345 /* determine the length of the buffer needed */
346 va_copy(ap_copy, ap);
347 len = vsnprintf(NULL, 0, fmt, ap_copy);
348 va_end(ap_copy);
349
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);
355 if (!string)
356 return NULL;
357
358 /* do the real work */
359 vsnprintf(string, len + 1, fmt, ap);
360
361 return string;
362 }
363
364 char *alloc_printf(const char *format, ...)
365 {
366 char *string;
367 va_list ap;
368 va_start(ap, format);
369 string = alloc_vprintf(format, ap);
370 va_end(ap);
371 return string;
372 }
373
374 /* Code must return to the server loop before 1000ms has returned or invoke
375 * this function.
376 *
377 * The GDB connection will time out if it spends >2000ms and you'll get nasty
378 * error messages from GDB:
379 *
380 * Ignoring packet error, continuing...
381 * Reply contains invalid hex digit 116
382 *
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.
387 *
388 * This function will send a keep alive packet if >500ms has passed since last time
389 * it was invoked.
390 *
391 * Note that this function can be invoked often, so it needs to be relatively
392 * fast when invoked more often than every 500ms.
393 *
394 */
395 #define KEEP_ALIVE_KICK_TIME_MS 500
396 #define KEEP_ALIVE_TIMEOUT_MS 1000
397
398 static void gdb_timeout_warning(int64_t delta_time)
399 {
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,
406 delta_time);
407 else
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,
412 delta_time);
413 }
414
415 void keep_alive(void)
416 {
417 int64_t current_time = timeval_ms();
418 int64_t delta_time = current_time - last_time;
419
420 if (delta_time > KEEP_ALIVE_TIMEOUT_MS) {
421 last_time = current_time;
422
423 gdb_timeout_warning(delta_time);
424 }
425
426 if (delta_time > KEEP_ALIVE_KICK_TIME_MS) {
427 last_time = current_time;
428
429 /* this will keep the GDB connection alive */
430 server_keep_clients_alive();
431
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.
436 *
437 * These functions should be invoked at a well defined spot in server.c
438 */
439 }
440 }
441
442 /* reset keep alive timer without sending message */
443 void kept_alive(void)
444 {
445 int64_t current_time = timeval_ms();
446
447 int64_t delta_time = current_time - last_time;
448
449 last_time = current_time;
450
451 if (delta_time > KEEP_ALIVE_TIMEOUT_MS)
452 gdb_timeout_warning(delta_time);
453 }
454
455 /* if we sleep for extended periods of time, we must invoke keep_alive() intermittently */
456 void alive_sleep(uint64_t ms)
457 {
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;
463
464 usleep(sleep_a_bit * 1000);
465 keep_alive();
466 }
467 }
468
469 void busy_sleep(uint64_t ms)
470 {
471 uint64_t then = timeval_ms();
472 while (timeval_ms() - then < ms) {
473 /*
474 * busy wait
475 */
476 }
477 }
478
479 /* Maximum size of socket error message retrieved from operation system */
480 #define MAX_SOCKET_ERR_MSG_LENGTH 256
481
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)
485 {
486 int error_code;
487 #ifdef _WIN32
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 : ""));
498 #else
499 error_code = errno;
500 LOG_ERROR("Error on socket '%s': errno==%d, message: %s.", socket_desc, error_code, strerror(error_code));
501 #endif
502 }
503
504 /**
505 * Find the first non-printable character in the char buffer, return a pointer to it.
506 * If no such character exists, return NULL.
507 */
508 char *find_nonprint_char(char *buf, unsigned buf_len)
509 {
510 for (unsigned int i = 0; i < buf_len; i++) {
511 if (!isprint(buf[i]))
512 return buf + i;
513 }
514 return NULL;
515 }

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)