mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-01 11:11:56 +00:00
4823451497
* Fix one x86-64-specific test to pass everywhere
200 lines
4.3 KiB
C
200 lines
4.3 KiB
C
/* radare - LGPL - Copyright 2010-2022 - pancake, ret2libc */
|
|
|
|
#define R_LOG_ORIGIN "util.log"
|
|
|
|
#include <r_core.h>
|
|
#include <stdarg.h>
|
|
|
|
static const char *level_tags[] = { // Log level to tag string lookup array
|
|
[R_LOGLVL_FATAL] = "FATAL",
|
|
[R_LOGLVL_ERROR] = "ERROR",
|
|
[R_LOGLVL_INFO] = "INFO",
|
|
[R_LOGLVL_WARN] = "WARN",
|
|
[R_LOGLVL_DEBUG] = "DEBUG",
|
|
};
|
|
|
|
static const char *level_name(int i) {
|
|
if (i >= 0 && i < R_LOGLVL_LAST) {
|
|
return level_tags[i];
|
|
}
|
|
return "UNKN";
|
|
}
|
|
|
|
static R_TH_LOCAL RLog *rlog = NULL;
|
|
|
|
// shouldnt be necessary as global thread-local instance
|
|
R_API void r_log_init(void) {
|
|
if (!rlog) {
|
|
rlog = R_NEW0 (RLog);
|
|
}
|
|
}
|
|
|
|
R_API void r_log_fini(void) {
|
|
if (rlog) {
|
|
free (rlog->file);
|
|
free (rlog->filter);
|
|
free (rlog);
|
|
rlog = NULL;
|
|
}
|
|
}
|
|
|
|
R_API void r_log_show_ts(bool ts) {
|
|
r_log_init ();
|
|
rlog->show_ts = ts;
|
|
}
|
|
|
|
R_API void r_log_set_level(RLogLevel level) {
|
|
r_log_init ();
|
|
rlog->level = level;
|
|
}
|
|
|
|
R_API void r_log_set_traplevel(RLogLevel level) {
|
|
r_log_init ();
|
|
rlog->traplevel = level;
|
|
}
|
|
|
|
R_API void r_log_set_filter(const char *s) {
|
|
r_log_init ();
|
|
R_FREE (rlog->filter);
|
|
if (R_STR_ISNOTEMPTY (s)) {
|
|
rlog->filter = strdup (s);
|
|
}
|
|
}
|
|
|
|
R_API void r_log_set_file(const char *filename) {
|
|
r_log_init ();
|
|
free (rlog->file);
|
|
rlog->file = strdup (filename);
|
|
}
|
|
|
|
R_API void r_log_show_origin(bool show_origin) {
|
|
r_log_init ();
|
|
rlog->show_origin = show_origin;
|
|
}
|
|
|
|
R_API void r_log_set_colors(bool color) {
|
|
r_log_init ();
|
|
rlog->color = color;
|
|
}
|
|
|
|
R_API void r_log_set_quiet(bool bq) {
|
|
r_log_init ();
|
|
rlog->quiet = bq;
|
|
}
|
|
|
|
R_API bool r_log_match(int level, const char *origin) { // , const char *sub_origin, const char *fmt, ...) {
|
|
r_log_init ();
|
|
if (R_STR_ISNOTEMPTY (rlog->filter)) {
|
|
if (strstr (origin, rlog->filter)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (rlog->cbs) {
|
|
RListIter *iter;
|
|
RLogCallback cb;
|
|
r_list_foreach (rlog->cbs, iter, cb) {
|
|
if (cb (rlog->user, level, origin, NULL)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return level < rlog->level;
|
|
}
|
|
|
|
R_API void r_log_vmessage(RLogLevel level, const char *origin, const char *fmt, va_list ap) {
|
|
char out[512];
|
|
r_log_init ();
|
|
int type = 3;
|
|
vsnprintf (out, sizeof (out), fmt, ap);
|
|
if (rlog->cbs) {
|
|
RListIter *iter;
|
|
RLogCallback cb;
|
|
r_list_foreach (rlog->cbs, iter, cb) {
|
|
cb (rlog->user, type, NULL, out);
|
|
}
|
|
}
|
|
RStrBuf *sb = r_strbuf_new ("");
|
|
if (rlog->color) {
|
|
const char *k = Color_YELLOW;
|
|
switch (level) {
|
|
case R_LOGLVL_FATAL:
|
|
case R_LOGLVL_ERROR:
|
|
k = Color_RED;
|
|
break;
|
|
case R_LOGLVL_INFO:
|
|
k = Color_YELLOW;
|
|
break;
|
|
case R_LOGLVL_WARN:
|
|
k = Color_MAGENTA;
|
|
break;
|
|
case R_LOGLVL_DEBUG:
|
|
k = Color_GREEN;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
r_strbuf_appendf (sb, "%s%s: ", k, level_name (level));
|
|
if (rlog->show_origin) {
|
|
r_strbuf_appendf (sb, Color_YELLOW "[%s] " Color_RESET, origin);
|
|
} else {
|
|
r_strbuf_appendf (sb, Color_RESET);
|
|
}
|
|
} else {
|
|
r_strbuf_appendf (sb, "%s: ", level_name (level));
|
|
if (rlog->show_origin) {
|
|
r_strbuf_appendf (sb, "[%s] ", origin);
|
|
}
|
|
}
|
|
char ts[32] = {0};
|
|
if (rlog->show_ts) {
|
|
ut64 now = r_time_now ();
|
|
if (rlog->color) {
|
|
r_strbuf_appendf (sb, ts, sizeof (ts), Color_CYAN "[ts:%" PFMT64u "] " Color_RESET, now);
|
|
} else {
|
|
r_strbuf_appendf (sb, ts, sizeof (ts), "[ts:%" PFMT64u "] ", now);
|
|
}
|
|
}
|
|
r_strbuf_appendf (sb, "%s%s\n", ts, out);
|
|
char * s = r_strbuf_drain (sb);
|
|
sb = NULL;
|
|
if (!rlog->quiet) {
|
|
eprintf ("%s", s);
|
|
}
|
|
if (R_STR_ISNOTEMPTY (rlog->file)) {
|
|
r_file_dump (rlog->file, (const ut8*)s, strlen (s), true);
|
|
}
|
|
if (rlog->traplevel && (level >= rlog->traplevel || level == R_LOGLVL_FATAL)) {
|
|
r_sys_backtrace ();
|
|
r_sys_breakpoint ();
|
|
}
|
|
}
|
|
|
|
R_API void r_log_message(RLogLevel level, const char *origin, const char *fmt, ...) {
|
|
va_list ap;
|
|
va_start (ap, fmt);
|
|
r_log_vmessage (level, origin, fmt, ap);
|
|
va_end (ap);
|
|
}
|
|
|
|
R_API void r_log_add_callback(RLogCallback cb) {
|
|
r_log_init ();
|
|
if (!rlog->cbs) {
|
|
rlog->cbs = r_list_new ();
|
|
}
|
|
if (!r_list_contains (rlog->cbs, cb)) {
|
|
r_list_append (rlog->cbs, cb);
|
|
}
|
|
}
|
|
|
|
R_API void r_log_del_callback(RLogCallback cb) {
|
|
r_log_init ();
|
|
r_list_delete_data (rlog->cbs, cb);
|
|
}
|
|
|
|
R_API void r_log(const char *funcname, const char *filename, ut32 lineno, RLogLevel level, const char *origin, const char *fmtstr, ...) {
|
|
va_list args;
|
|
va_start (args, fmtstr);
|
|
r_log_vmessage (level, origin, fmtstr, args);
|
|
va_end (args);
|
|
}
|