Rizin
unix-like reverse engineering framework and cli tools
log.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007-2018 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2007-2018 ret2libc <sirmy15@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #define LOG_CONFIGSTR_SIZE 512
6 #define LOG_OUTPUTBUF_SIZE 512
7 
8 #include <rz_core.h>
9 #include <stdarg.h>
10 
11 // TODO: Use thread-local storage to make these variables thread-safe
12 static RzList *log_cbs = NULL; // Functions to call when outputting log string
13 static int cfg_loglvl = RZ_LOGLVL_WARN; // Log level output
14 static int cfg_logtraplvl = RZ_LOGLVL_FATAL; // Log trap level
15 static bool cfg_logsrcinfo = false; // Print out debug source info with the output
16 static bool cfg_logcolors = false; // Output colored log text based on level
17 static char cfg_logfile[LOG_CONFIGSTR_SIZE] = ""; // Output text to filename
18 static const char *level_tags[] = { // Log level to tag string lookup array
19  [RZ_LOGLVL_SILLY] = "SILLY",
20  [RZ_LOGLVL_VERBOSE] = "VERBOSE",
21  [RZ_LOGLVL_DEBUG] = "DEBUG",
22  [RZ_LOGLVL_INFO] = "INFO",
23  [RZ_LOGLVL_WARN] = "WARNING",
24  [RZ_LOGLVL_ERROR] = "ERROR",
25  [RZ_LOGLVL_FATAL] = "FATAL"
26 };
27 
28 // cconfig.c configuration callback functions below
30  cfg_loglvl = level;
31 }
32 
35 }
36 
37 RZ_API void rz_log_set_file(const char *filename) {
38  int value_len = rz_str_nlen(filename, LOG_CONFIGSTR_SIZE) + 1;
39  strncpy(cfg_logfile, filename, value_len);
40 }
41 
42 RZ_API void rz_log_set_srcinfo(bool show_info) {
43  cfg_logsrcinfo = show_info;
44 }
45 
46 RZ_API void rz_log_set_colors(bool show_info) {
47  cfg_logcolors = show_info;
48 }
49 
55  if (!log_cbs) {
56  log_cbs = rz_list_new();
57  }
58  if (!rz_list_contains(log_cbs, cbfunc)) {
59  rz_list_append(log_cbs, cbfunc);
60  }
61 }
62 
68  if (log_cbs) {
70  }
71 }
72 
73 RZ_API void rz_vlog(const char *funcname, const char *filename,
74  ut32 lineno, RzLogLevel level, const char *tag, const char *fmtstr, va_list args) {
75  va_list args_copy;
76  va_copy(args_copy, args);
77 
78  if (level < cfg_loglvl && level < cfg_logtraplvl) {
79  // Don't print if output level is lower than current level
80  // Don't ignore fatal/trap errors
81  va_end(args_copy);
82  return;
83  }
84 
85  // TODO: Colors
86 
87  // Build output string with src info, and formatted output
88  char output_buf[LOG_OUTPUTBUF_SIZE] = ""; // Big buffer for building the output string
89  if (!tag) {
91  }
92  int offset = snprintf(output_buf, LOG_OUTPUTBUF_SIZE, "%s: ", tag);
93  if (cfg_logsrcinfo) {
94  offset += snprintf(output_buf + offset, LOG_OUTPUTBUF_SIZE - offset, "%s in %s:%i: ", funcname, filename, lineno);
95  }
96  vsnprintf(output_buf + offset, LOG_OUTPUTBUF_SIZE - offset, fmtstr, args);
97 
98  // Actually print out the string with our callbacks
99  if (log_cbs && rz_list_length(log_cbs) > 0) {
100  RzListIter *it;
102 
103  rz_list_foreach (log_cbs, it, cb) {
104  cb(output_buf, funcname, filename, lineno, level, NULL, fmtstr, args_copy);
105  }
106  } else {
107  fprintf(stderr, "%s", output_buf);
108  }
109  va_end(args_copy);
110 
111  // Log to file if enabled
112  if (cfg_logfile[0] != 0x00) {
113  FILE *file = rz_sys_fopen(cfg_logfile, "a+"); // TODO: Optimize (static? Needs to remake on cfg change though)
114  if (!file) {
115  file = rz_sys_fopen(cfg_logfile, "w+");
116  }
117  if (file) {
118  fprintf(file, "%s", output_buf);
119  fclose(file);
120  } else {
121  eprintf("%s failed to write to file: %s\n", MACRO_LOG_FUNC, cfg_logfile);
122  }
123  }
124 
125  if (level >= cfg_logtraplvl && level != RZ_LOGLVL_NONE) {
126  fflush(stdout); // We're about to exit HARD, flush buffers before dying
127  fflush(stderr);
128  // TODO: call rz_cons_flush if librz_cons is being used
129  rz_sys_breakpoint(); // *oof*
130  }
131 }
132 
143 RZ_API void rz_log(const char *funcname, const char *filename,
144  ut32 lineno, RzLogLevel level, const char *tag, const char *fmtstr, ...) {
145  va_list args;
146 
147  va_start(args, fmtstr);
148  rz_vlog(funcname, filename, lineno, level, tag, fmtstr, args);
149  va_end(args);
150 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
snprintf
Definition: kernel.h:364
vsnprintf
Definition: kernel.h:366
RZ_API RZ_BORROW RzListIter * rz_list_contains(RZ_NONNULL const RzList *list, RZ_NONNULL const void *ptr)
Returns the RzListIter of the given pointer, if found.
Definition: list.c:592
RZ_API bool rz_list_delete_data(RZ_NONNULL RzList *list, void *ptr)
Deletes an entry in the list by searching for a pointer.
Definition: list.c:148
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_log_set_file(const char *filename)
Definition: log.c:37
static int cfg_loglvl
Definition: log.c:13
RZ_API void rz_log_set_level(RzLogLevel level)
Definition: log.c:29
RZ_API void rz_log_set_traplevel(RzLogLevel level)
Definition: log.c:33
static char cfg_logfile[LOG_CONFIGSTR_SIZE]
Definition: log.c:17
static bool cfg_logsrcinfo
Definition: log.c:15
static const char * level_tags[]
Definition: log.c:18
static RzList * log_cbs
Definition: log.c:12
RZ_API void rz_log_set_colors(bool show_info)
Definition: log.c:46
RZ_API void rz_log(const char *funcname, const char *filename, ut32 lineno, RzLogLevel level, const char *tag, const char *fmtstr,...)
Internal logging function used by preprocessor macros.
Definition: log.c:143
#define LOG_OUTPUTBUF_SIZE
Definition: log.c:6
RZ_API void rz_log_del_callback(RzLogCallback cbfunc)
Remove a logging callback.
Definition: log.c:67
static bool cfg_logcolors
Definition: log.c:16
RZ_API void rz_log_set_srcinfo(bool show_info)
Definition: log.c:42
RZ_API void rz_log_add_callback(RzLogCallback cbfunc)
Add a logging callback.
Definition: log.c:54
#define LOG_CONFIGSTR_SIZE
Definition: log.c:5
static int cfg_logtraplvl
Definition: log.c:14
RZ_API void rz_vlog(const char *funcname, const char *filename, ut32 lineno, RzLogLevel level, const char *tag, const char *fmtstr, va_list args)
Definition: log.c:73
int args
Definition: mipsasm.c:18
string FILE
Definition: benchmark.py:21
#define eprintf(x, y...)
Definition: rlcc.c:7
#define MACRO_LOG_FUNC
Definition: rz_log.h:13
enum rz_log_level RzLogLevel
@ RZ_LOGLVL_SILLY
Definition: rz_log.h:17
@ RZ_LOGLVL_NONE
Definition: rz_log.h:24
@ RZ_LOGLVL_WARN
Definition: rz_log.h:21
@ RZ_LOGLVL_INFO
Definition: rz_log.h:20
@ RZ_LOGLVL_ERROR
Definition: rz_log.h:22
@ RZ_LOGLVL_VERBOSE
Definition: rz_log.h:19
@ RZ_LOGLVL_FATAL
Definition: rz_log.h:23
@ RZ_LOGLVL_DEBUG
Definition: rz_log.h:18
void(* RzLogCallback)(const char *output, const char *funcname, const char *filename, ut32 lineno, RzLogLevel level, const char *tag, const char *fmtstr,...) RZ_PRINTF_CHECK(7
Definition: rz_log.h:33
RZ_API size_t rz_str_nlen(const char *s, size_t n)
Definition: str.c:1949
#define rz_sys_breakpoint()
Definition: rz_sys.h:178
RZ_API FILE * rz_sys_fopen(const char *path, const char *mode)
Definition: sys.c:1815
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_BETWEEN(x, y, z)
Definition: gzappend.c:170
static int level
Definition: vmenus.c:2424
static const char * cb[]
Definition: z80_tab.h:176