3983 lines
146 KiB
C
3983 lines
146 KiB
C
// SPDX-FileCopyrightText: 2009-2021 pancake <pancake@nopcode.org>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_core.h>
|
|
#include <rz_cons.h>
|
|
#include <rz_basefind.h>
|
|
#include <rz_th.h>
|
|
#include <rz_windows.h>
|
|
#include <rz_config.h>
|
|
#include <rz_util/rz_bits.h>
|
|
#include <rz_util/rz_str.h>
|
|
#include <rz_util/rz_bits.h>
|
|
|
|
#include "core_private.h"
|
|
|
|
#if RZ_SYS_ENDIAN == RZ_SYS_ENDIAN_LITTLE
|
|
#define CFG_DEFAULT_ENDIANNESS "false"
|
|
#else
|
|
#define CFG_DEFAULT_ENDIANNESS "true"
|
|
#endif
|
|
|
|
typedef struct config_opt_descr {
|
|
const char *option;
|
|
const char *description;
|
|
} ConfigOptDescr;
|
|
|
|
static bool boolify_var_cb(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value || rz_str_is_false(node->value)) {
|
|
free(node->value);
|
|
node->value = rz_str_dup(rz_str_bool(node->i_value));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void set_options(RzConfigNode *node, ...) {
|
|
va_list argp;
|
|
char *option = NULL;
|
|
va_start(argp, node);
|
|
option = va_arg(argp, char *);
|
|
while (option) {
|
|
rz_list_append(node->options, option);
|
|
option = va_arg(argp, char *);
|
|
}
|
|
va_end(argp);
|
|
}
|
|
|
|
static bool isGdbPlugin(RzCore *core) {
|
|
if (core->io && core->io->desc && core->io->desc->plugin) {
|
|
if (core->io->desc->plugin->name && !strcmp(core->io->desc->plugin->name, "gdb")) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void print_node_options(RzConfigNode *node) {
|
|
RzListIter *iter;
|
|
char *option;
|
|
rz_list_foreach (node->options, iter, option) {
|
|
rz_cons_printf("%s\n", option);
|
|
}
|
|
}
|
|
|
|
static int compareName(const RzAnalysisFunction *a, const RzAnalysisFunction *b, void *user) {
|
|
return (a && b && a->name && b->name ? strcmp(a->name, b->name) : 0);
|
|
}
|
|
|
|
static int compareNameLen(const RzAnalysisFunction *a, const RzAnalysisFunction *b, void *user) {
|
|
size_t la, lb;
|
|
if (!a || !b || !a->name || !b->name) {
|
|
return 0;
|
|
}
|
|
la = strlen(a->name);
|
|
lb = strlen(a->name);
|
|
return (la > lb) - (la < lb);
|
|
}
|
|
|
|
static int compareAddress(const RzAnalysisFunction *a, const RzAnalysisFunction *b, void *user) {
|
|
return (a && b && a->addr && b->addr ? (a->addr > b->addr) - (a->addr < b->addr) : 0);
|
|
}
|
|
|
|
static int compareSize(const RzAnalysisFunction *a, const RzAnalysisFunction *b, void *user) {
|
|
ut64 sa, sb;
|
|
// return a && b && a->_size < b->_size;
|
|
if (!a || !b) {
|
|
return 0;
|
|
}
|
|
sa = rz_analysis_function_realsize(a);
|
|
sb = rz_analysis_function_realsize(b);
|
|
return (sa > sb) - (sa < sb);
|
|
}
|
|
|
|
static void update_asmarch_options(RzCore *core, RzConfigNode *node) {
|
|
if (!core || !node) {
|
|
return;
|
|
}
|
|
|
|
RzAsmPlugin **val;
|
|
RzIterator *it = rz_asm_plugin_iterator(core->rasm);
|
|
rz_list_purge(node->options);
|
|
rz_iterator_foreach(it, val) {
|
|
RzAsmPlugin *h = *val;
|
|
SETOPTIONS(node, h->name, NULL);
|
|
}
|
|
rz_iterator_free(it);
|
|
}
|
|
|
|
static void update_asmbits_options(RzCore *core, RzConfigNode *node) {
|
|
if (!core || !node) {
|
|
return;
|
|
}
|
|
|
|
int bits = rz_asm_get_plugin_bits(core->rasm);
|
|
node->options->free = free;
|
|
rz_list_purge(node->options);
|
|
for (int i = 1; i <= bits; i <<= 1) {
|
|
if (i & bits) {
|
|
SETOPTIONS(node, rz_str_newf("%d", i), NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void update_asmfeatures_options(RzCore *core, RzConfigNode *node) {
|
|
if (!core || !node) {
|
|
return;
|
|
}
|
|
|
|
const char *features = rz_asm_get_plugin_features(core->rasm);
|
|
if (RZ_STR_ISEMPTY(features)) {
|
|
rz_list_purge(node->options);
|
|
return;
|
|
}
|
|
|
|
rz_list_free(node->options);
|
|
node->options = rz_str_split_duplist(features, ",", true);
|
|
}
|
|
|
|
static void update_asmplatforms_options(RzCore *core, RzConfigNode *node) {
|
|
if (!core || !node) {
|
|
return;
|
|
}
|
|
|
|
const char *platforms = rz_asm_get_plugin_platforms(core->rasm);
|
|
if (RZ_STR_ISEMPTY(platforms)) {
|
|
rz_list_purge(node->options);
|
|
return;
|
|
}
|
|
|
|
rz_list_free(node->options);
|
|
node->options = rz_str_split_duplist(platforms, ",", true);
|
|
}
|
|
|
|
static void update_asmparser_options(RzCore *core, RzConfigNode *node) {
|
|
RzListIter *iter;
|
|
RzParsePlugin *parser;
|
|
if (core && node && core->parser && core->parser->parsers) {
|
|
rz_list_purge(node->options);
|
|
rz_list_foreach (core->parser->parsers, iter, parser) {
|
|
SETOPTIONS(node, parser->name, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void update_asmcpu_options(RzCore *core, RzConfigNode *node) {
|
|
rz_return_if_fail(core && core->rasm);
|
|
|
|
const char *cpus = rz_asm_get_plugin_cpus(core->rasm);
|
|
if (RZ_STR_ISEMPTY(cpus)) {
|
|
rz_list_purge(node->options);
|
|
return;
|
|
}
|
|
|
|
rz_list_free(node->options);
|
|
node->options = rz_str_split_duplist(cpus, ",", true);
|
|
}
|
|
|
|
static bool cb_search_case_sensitive(void *_core, void *_node) {
|
|
RzConfigNode *node = _node;
|
|
const char *case_sensitive = node->value;
|
|
RzCore *core = _core;
|
|
if (case_sensitive) {
|
|
if (!strcmp(case_sensitive, "smart")) {
|
|
core->cons->grep_icase = RZ_CONS_SEARCH_CASE_SMART;
|
|
} else if (!strcmp(case_sensitive, "insensitive")) {
|
|
core->cons->grep_icase = RZ_CONS_SEARCH_CASE_INSENSITIVE;
|
|
} else if (!strcmp(case_sensitive, "sensitive")) {
|
|
core->cons->grep_icase = RZ_CONS_SEARCH_CASE_SENSITIVE;
|
|
} else {
|
|
goto err;
|
|
}
|
|
return true;
|
|
}
|
|
err:
|
|
RZ_LOG_ERROR("grep: search.sensitive: invalid value (%s), support only `smart, sensitive, insensitive`\n", case_sensitive);
|
|
return false;
|
|
}
|
|
|
|
static bool cb_diff_sort(void *_core, void *_node) {
|
|
RzConfigNode *node = _node;
|
|
const char *column = node->value;
|
|
RzCore *core = _core;
|
|
if (column && strcmp(column, "?")) {
|
|
if (!strcmp(column, "name")) {
|
|
rz_analysis_set_column_sort(core->analysis, (RzListComparator)compareName);
|
|
} else if (!strcmp(column, "namelen")) {
|
|
rz_analysis_set_column_sort(core->analysis, (RzListComparator)compareNameLen);
|
|
} else if (!strcmp(column, "addr")) {
|
|
rz_analysis_set_column_sort(core->analysis, (RzListComparator)compareAddress);
|
|
} else if (!strcmp(column, "size")) {
|
|
rz_analysis_set_column_sort(core->analysis, (RzListComparator)compareSize);
|
|
} else {
|
|
goto fail;
|
|
}
|
|
return true;
|
|
}
|
|
fail:
|
|
RZ_LOG_ERROR("core: diff.sort: invalid value (%s), supported only `name, namelen, addr, type, size, dist`\n", column);
|
|
return false;
|
|
}
|
|
|
|
static bool cb_asm_features_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
update_asmfeatures_options(core, node);
|
|
print_node_options(node);
|
|
return 0;
|
|
}
|
|
rz_asm_set_features(core->rasm, node->value);
|
|
return 1;
|
|
}
|
|
|
|
static bool cb_asm_parser_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
update_asmparser_options(core, node);
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
|
|
return rz_parse_use(core->parser, node->value);
|
|
}
|
|
|
|
static bool cb_asm_os_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
const char *value = node->value;
|
|
if (*value == '?') {
|
|
print_node_options(node);
|
|
return 0;
|
|
}
|
|
if (!value[0]) {
|
|
value = RZ_SYS_OS;
|
|
}
|
|
return rz_core_arch_configure(core, /*arch*/ NULL, /*bits*/ 0, /*cpu*/ NULL, /*os*/ value, /*platform*/ NULL);
|
|
}
|
|
|
|
static bool cb_asm_cpu_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
const char *value = node->value;
|
|
if (*value == '?') {
|
|
update_asmcpu_options(core, node);
|
|
/* print verbose help instead of plain option listing */
|
|
RzCmdStateOutput state = { 0 };
|
|
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_STANDARD, core);
|
|
rz_core_asm_cpu_plugin_print(core, &state, rz_config_get(core->config, "asm.arch"));
|
|
rz_cmd_state_output_print(&state);
|
|
rz_cmd_state_output_fini(&state);
|
|
return 0;
|
|
}
|
|
|
|
return rz_core_arch_configure(core, /*arch*/ NULL, /*bits*/ 0, /*cpu*/ value, /*os*/ NULL, /*platform*/ NULL);
|
|
}
|
|
|
|
static bool cb_asm_arch_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
const char *value = node->value;
|
|
if (value[0] == '?') {
|
|
update_asmarch_options(core, node);
|
|
if (strlen(value) > 1 && value[1] == '?') {
|
|
/* print more verbose help instead of plain option values */
|
|
RzCmdStateOutput state = { 0 };
|
|
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_STANDARD, core);
|
|
rz_core_asm_plugins_print(core, &state, NULL);
|
|
rz_cmd_state_output_print(&state);
|
|
rz_cmd_state_output_fini(&state);
|
|
return false;
|
|
} else {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return rz_core_arch_configure(core, /*arch*/ value, /*bits*/ 0, /*cpu*/ NULL, /*os*/ NULL, /*platform*/ NULL);
|
|
}
|
|
|
|
static bool cb_asm_platform_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
const char *value = node->value;
|
|
if (*value == '?') {
|
|
update_asmplatforms_options(core, node);
|
|
print_node_options(node);
|
|
return 0;
|
|
}
|
|
|
|
return rz_core_arch_configure(core, /*arch*/ NULL, /*bits*/ 0, /*cpu*/ NULL, /*os*/ NULL, /*platform*/ value);
|
|
}
|
|
|
|
static bool cb_asm_bits_set(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
int value = node->i_value;
|
|
if (node->value[0] == '?') {
|
|
update_asmbits_options(core, node);
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
|
|
return rz_core_arch_configure(core, /*arch*/ NULL, /*bits*/ value, /*cpu*/ NULL, /*os*/ NULL, /*platform*/ NULL);
|
|
}
|
|
|
|
static bool cb_debug_hitinfo(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->hitinfo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmpretpoline(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->retpoline = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_armthumb(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->armthumb = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_depth(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->depth = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_graphdepth(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->graph_depth = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_afterjmp(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->afterjmp = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_aftertrap(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->aftertrap = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_delay(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->delay = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_vars(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->vars = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_nonull(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->nonull = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_strings(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
rz_config_set(core->config, "bin.strings", "false");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_ignbithints(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->ignbithints = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_sleep(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_analysis_set_sleep(core->analysis, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_maxrefs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_analysis_set_max_reflines(core->analysis, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_norevisit(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->norevisit = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_nopskip(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->nopskip = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_hpskip(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->hpskip = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static void update_analysis_arch_options(RzCore *core, RzConfigNode *node) {
|
|
RzIterator *it = rz_analysis_plugin_iterator(core->analysis);
|
|
RzAnalysisPlugin **val;
|
|
if (core && core->analysis && node) {
|
|
rz_list_purge(node->options);
|
|
rz_iterator_foreach(it, val) {
|
|
RzAnalysisPlugin *h = *val;
|
|
SETOPTIONS(node, h->name, NULL);
|
|
}
|
|
}
|
|
rz_iterator_free(it);
|
|
}
|
|
|
|
static bool cb_analysis_recont(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->recont = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_ijmp(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->ijmp = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmsubvarmin(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->parser->minval = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmsubtail(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->parser->subtail = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrlast(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->context->lastEnabled = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_vi(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->line->enable_vi_mode = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_prompt_mode(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->line->prompt_mode = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_wideoff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->wide_offsets = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmpseudo(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_set_pseudo(core->rasm, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmsubsec(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_SECSUB;
|
|
} else {
|
|
core->print->flags &= (~RZ_PRINT_FLAGS_SECSUB);
|
|
}
|
|
rz_print_set_flags(core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmassembler(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_use_assembler(core->rasm, node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asm_varfold(void *core, void *node) {
|
|
char *choice[] = { "none", "group", "hide" };
|
|
RzConfigNode *n = node;
|
|
const char *user_choice = n->value;
|
|
for (int i = 0; i < sizeof(choice) / sizeof(choice[0]); i++) {
|
|
if (!strcmp(choice[i], user_choice)) {
|
|
return true;
|
|
}
|
|
}
|
|
RZ_LOG_ERROR("asm.var.fold: Invalid choice. Only support `none, group, hide`\n");
|
|
return false;
|
|
}
|
|
|
|
static bool cb_dbgbtdepth(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->btdepth = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_flag_realnames(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->flags->realnames = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmlineswidth(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_analysis_set_lines_width(core->analysis, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_emustr(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
rz_config_set(core->config, "asm.emu", "true");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_emuskip(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Concatenation of meta types encoded as characters:\n"
|
|
"'d': data\n'c': code\n's': string\n'f': format\n'm': magic\n"
|
|
"'h': hide\n'C': comment\n'r': run\n"
|
|
"(default is 'ds' to skip data and strings)\n");
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asm_immhash(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_set_show_immediate_hashtag(core->rasm, node->i_value ? true : false);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asm_invhex(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_set_invalid_as_hex_flag(core->rasm, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asm_pcalign(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
int align = node->i_value;
|
|
if (rz_bits_count_ones_ut64(align) != 1) {
|
|
RZ_LOG_ERROR("Alignment is only defined for '>0' and 'n^2'. Is = %" PFMT64d "\n", node->i_value);
|
|
return false;
|
|
}
|
|
rz_asm_set_pc_align(core->rasm, align);
|
|
rz_analysis_set_pc_align(core->analysis, align);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binfilter(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->bin->filter = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binat(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->binat = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_usextr(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->bin->use_xtr = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_strpurge(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
rz_cons_printf(
|
|
"There can be multiple entries separated by commas. No whitespace before/after entries.\n"
|
|
"Possible entries:\n"
|
|
" all : purge all strings\n"
|
|
" true : use the false_positive() classifier in cbin.c\n"
|
|
" addr : purge string at addr\n"
|
|
" addr1-addr2 : purge all strings in the range addr1-addr2 inclusive\n"
|
|
" !addr : prevent purge of string at addr by prev entries\n"
|
|
" !addr1-addr2 : prevent purge of strings in range addr1-addr2 inclusive by prev entries\n"
|
|
"Neither !true nor !false is supported.\n"
|
|
"\n"
|
|
"Examples:\n"
|
|
" e bin.str.purge=true,0-0xff,!0x1a\n"
|
|
" -- purge strings using the false_positive() classifier in cbin.c and also strings \n"
|
|
" with addresses in the range 0-0xff, but not the string at 0x1a.\n"
|
|
" e bin.str.purge=all,!0x1000-0x1fff\n"
|
|
" -- purge all strings except the strings with addresses in the range 0x1000-0x1fff.\n");
|
|
return false;
|
|
}
|
|
free(core->bin->strpurge);
|
|
core->bin->strpurge = !*node->value || !strcmp(node->value, "false")
|
|
? NULL
|
|
: rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_maxname(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
core->parser->maxflagnamelen = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_midflags(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_strfilter(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Valid values for bin.str.filter:\n"
|
|
"a only alphanumeric printable\n"
|
|
"8 only strings with utf8 chars\n"
|
|
"p file/directory paths\n"
|
|
"e email-like addresses\n"
|
|
"u urls\n"
|
|
"i IPv4 address-like strings\n"
|
|
"U only uppercase strings\n"
|
|
"f format-strings\n");
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
} else {
|
|
core->bin->strfilter = node->value[0];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binforce(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_bin_force_plugin(core->bin, node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_bindemangle(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->bin->demangle = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_bindemangle_flags(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
if (!strcmp(node->value, "all")) {
|
|
rz_bin_demangle_with_flags(core->bin, RZ_DEMANGLER_FLAG_ENABLE_ALL);
|
|
} else if (!strcmp(node->value, "base")) {
|
|
rz_bin_demangle_with_flags(core->bin, RZ_DEMANGLER_FLAG_BASE);
|
|
} else if (!strcmp(node->value, "simplify")) {
|
|
rz_bin_demangle_with_flags(core->bin, RZ_DEMANGLER_FLAG_SIMPLIFY);
|
|
} else {
|
|
RZ_LOG_ERROR("config: invalid option for bin.demangle.flags\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_asmsyntax(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
} else {
|
|
int syntax = rz_asm_syntax_from_string(node->value);
|
|
if (syntax == -1) {
|
|
return false;
|
|
}
|
|
rz_asm_set_syntax(core->rasm, syntax);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_bigendian(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
return rz_core_set_endianness(core, node->i_value);
|
|
}
|
|
|
|
static bool cb_cfgdatefmt(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
snprintf(core->print->datefmt, 32, "%s", node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_timezone(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->datezone = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cfgdebug(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!core) {
|
|
return false;
|
|
}
|
|
if (core->io) {
|
|
rz_config_set_b(core->config, "io.va", !node->i_value);
|
|
}
|
|
if (core->dbg && node->i_value) {
|
|
const char *dbgbackend = rz_config_get(core->config, "dbg.backend");
|
|
core->bin->is_debugger = true;
|
|
rz_debug_use(core->dbg, dbgbackend);
|
|
if (!strcmp(dbgbackend, "bf")) {
|
|
rz_config_set(core->config, "asm.arch", "bf");
|
|
}
|
|
if (core->file) {
|
|
rz_debug_select(core->dbg, rz_io_fd_get_pid(core->io, core->file->fd),
|
|
rz_io_fd_get_tid(core->io, core->file->fd));
|
|
}
|
|
} else {
|
|
rz_debug_use(core->dbg, NULL);
|
|
core->bin->is_debugger = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dirhome(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value) {
|
|
rz_sys_setenv(RZ_SYS_HOME, node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dirtmp(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
char *value = RZ_STR_ISNOTEMPTY(node->value) ? node->value : NULL;
|
|
rz_sys_setenv(RZ_SYS_TMP, value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dirsrc(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
free(core->bin->srcdir);
|
|
core->bin->srcdir = rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_str_escbslash(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->esc_bslash = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_max_threads(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
rz_cons_printf("Available cores: %d\n", rz_th_physical_core_number());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_to(void *user, void *data) {
|
|
RzCore *core = user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
ut64 from = rz_config_get_i(core->config, "search.from");
|
|
if (node->i_value < from) {
|
|
rz_cons_printf("search.to cannot be smaller than search.from.\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void check_reload_bin_str_search(RzCore *core) {
|
|
if (core->bin && rz_config_get_b(core->config, "str.search.reload")) {
|
|
RzBinFile *bf = rz_bin_cur(core->bin);
|
|
if (bf && bf->o) {
|
|
rz_bin_object_reset_strings(core->bin, bf, bf->o);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool cb_search_str_min_length(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value < 1) {
|
|
RZ_LOG_ERROR("search.str.min_length cannot be less than 1.\n");
|
|
return false;
|
|
} else if (node->i_value >= core->bin->str_search_cfg.max_length) {
|
|
RZ_LOG_ERROR("search.str.max_length cannot be greater or equal to %" PFMTSZu ".\n", core->bin->str_search_cfg.max_length);
|
|
return false;
|
|
}
|
|
|
|
core->bin->str_search_cfg.min_length = node->i_value;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_str_max_length(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
size_t min_buffer_size = RZ_MIN(core->bin->str_search_cfg.min_length, RZ_BIN_STRING_SEARCH_BUFFER_SIZE);
|
|
if (node->i_value < min_buffer_size) {
|
|
RZ_LOG_ERROR("search.str.max_length cannot be less than %" PFMTSZu ".\n", min_buffer_size);
|
|
return false;
|
|
}
|
|
|
|
core->bin->str_search_cfg.max_length = node->i_value;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_str_max_region_size(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value < RZ_BIN_STRING_SEARCH_MAX_REGION_SIZE) {
|
|
RZ_LOG_ERROR("search.str.max_region_size cannot be less than " RZ_STR(RZ_BIN_STRING_SEARCH_MAX_REGION_SIZE) ".\n");
|
|
return false;
|
|
}
|
|
core->bin->str_search_cfg.max_region_size = node->i_value;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_str_raw_alignment(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value < 8 || rz_bits_count_ones_ut64(node->i_value) != 1) {
|
|
RZ_LOG_ERROR("search.str.raw_alignment cannot be less than 8 and must be n^2.\n");
|
|
return false;
|
|
}
|
|
core->bin->str_search_cfg.raw_alignment = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_str_check_ascii_freq(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
rz_cons_printf("true\nfalse\n");
|
|
return false;
|
|
} else if (!rz_str_is_bool(node->value)) {
|
|
RZ_LOG_ERROR("Invalid value for search.str.check_ascii_freq (%s).\n", node->value);
|
|
return false;
|
|
}
|
|
core->bin->str_search_cfg.check_ascii_freq = rz_str_is_true(node->value);
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
static bool find_encoding(RzConfigNode *node, RzStrEnc *encoding) {
|
|
RzListIter *iter;
|
|
const char *option;
|
|
rz_list_foreach (node->options, iter, option) {
|
|
if (rz_str_casecmp(option, node->value)) {
|
|
continue;
|
|
}
|
|
free(node->value);
|
|
node->value = rz_str_dup(option);
|
|
*encoding = rz_str_enc_string_as_type(option);
|
|
return true;
|
|
}
|
|
if (rz_list_empty(node->options)) {
|
|
// Edge case when the node was just initialized but the options
|
|
// were not added yet.
|
|
*encoding = rz_str_enc_string_as_type(node->value);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool cb_str_encoding(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzStrEnc encoding = RZ_STRING_ENC_GUESS;
|
|
bool found_enc = find_encoding(node, &encoding);
|
|
if (node->value[0] == '?') {
|
|
print_node_options(node);
|
|
rz_cons_printf(" -- if string's 2nd & 4th bytes are 0 then utf16le else "
|
|
"if 2nd - 4th & 6th bytes are 0 & no char > 0x10ffff then utf32le else "
|
|
"if utf8 char detected then utf8 else 8bit\n");
|
|
return false;
|
|
} else if (RZ_STR_EQ("settings", node->value) || (!RZ_STR_EQ("guess", node->value) && !found_enc)) {
|
|
RZ_LOG_ERROR("Invalid value for str.encoding (%s).\n", node->value);
|
|
return false;
|
|
}
|
|
|
|
core->bin->str_search_cfg.string_encoding = encoding;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_str_unprintable(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
rz_cons_printf("Comma-separated list of Unicode code points treated as non-printable.\n");
|
|
rz_cons_printf("Examples:\n");
|
|
rz_cons_printf(" e str.unprintable=0x09,0x0a,0x0d,0x1b\n");
|
|
rz_cons_printf(" e str.unprintable=0x200B\n");
|
|
rz_cons_printf(" e str.unprintable=\n");
|
|
rz_cons_printf(" -- reset the list to empty.\n");
|
|
return false;
|
|
}
|
|
|
|
if (RZ_STR_ISEMPTY(node->value)) {
|
|
rz_vector_free(core->bin->str_search_cfg.user_unprintable);
|
|
core->bin->str_search_cfg.user_unprintable = NULL;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
}
|
|
|
|
RzVector *custom = NULL;
|
|
char *list = rz_str_dup(node->value);
|
|
if (!list) {
|
|
return false;
|
|
}
|
|
|
|
int argc = rz_str_split(list, ',');
|
|
if (argc < 1) {
|
|
goto error_free;
|
|
}
|
|
|
|
custom = rz_vector_new(sizeof(RzCodePoint), NULL, NULL);
|
|
if (!custom) {
|
|
goto error_free;
|
|
}
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
const char *word = rz_str_word_get0(list, i);
|
|
if (RZ_STR_ISEMPTY(word) || !rz_is_valid_input_num_value(core->num, word)) {
|
|
RZ_LOG_ERROR("Invalid value for str.unprintable (%s).\n", word ? word : "");
|
|
goto error_free;
|
|
}
|
|
ut64 cp = rz_num_math(core->num, word);
|
|
if (cp > RZ_UNICODE_LAST_CODE_POINT) {
|
|
RZ_LOG_ERROR("str.unprintable code point out of range (%s).\n", word);
|
|
goto error_free;
|
|
}
|
|
RzCodePoint point = (RzCodePoint)cp;
|
|
if (!rz_vector_push(custom, &point)) {
|
|
RZ_LOG_ERROR("Cannot append code point to str.unprintable (%s).\n", word);
|
|
goto error_free;
|
|
}
|
|
}
|
|
free(list);
|
|
|
|
rz_vector_free(core->bin->str_search_cfg.user_unprintable);
|
|
core->bin->str_search_cfg.user_unprintable = custom;
|
|
check_reload_bin_str_search(core);
|
|
return true;
|
|
|
|
error_free:
|
|
rz_vector_free(custom);
|
|
free(list);
|
|
return false;
|
|
}
|
|
|
|
static bool cb_str_search_mode(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
} else if (!rz_str_casecmp("auto", node->value)) {
|
|
core->bin->str_search_cfg.mode = RZ_BIN_STRING_SEARCH_MODE_AUTO;
|
|
return true;
|
|
} else if (!rz_str_casecmp("rosections", node->value)) {
|
|
core->bin->str_search_cfg.mode = RZ_BIN_STRING_SEARCH_MODE_READ_ONLY_SECTIONS;
|
|
return true;
|
|
} else if (!rz_str_casecmp("raw", node->value)) {
|
|
core->bin->str_search_cfg.mode = RZ_BIN_STRING_SEARCH_MODE_RAW_BINARY;
|
|
return true;
|
|
}
|
|
RZ_LOG_ERROR("Invalid value for str.search.mode (%s).\n", node->value);
|
|
check_reload_bin_str_search(core);
|
|
return false;
|
|
}
|
|
|
|
static bool cb_completion_maxtab(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->line->completion.args_limit = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cfg_fortunes(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
// TODO CN_BOOL option does not receive the right hand side of assignment as an argument
|
|
if (node->value[0] == '?') {
|
|
rz_core_fortune_list(core);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cfg_fortunes_file(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
rz_core_fortune_list_types();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmdtimes(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cmdtimes = node->value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmdrepeat(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cmdrepeat = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrnull(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->null = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool core_scr_color_set(void *user, const void *pvalue) {
|
|
RzCore *core = (RzCore *)user;
|
|
ut64 value = *((const ut64 *)pvalue);
|
|
|
|
// ensure is never greater than COLOR_MODE_16M
|
|
value = RZ_MIN(value, COLOR_MODE_16M);
|
|
|
|
if (value > 0) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_COLOR;
|
|
} else {
|
|
core->print->flags &= (~RZ_PRINT_FLAGS_COLOR);
|
|
}
|
|
|
|
core->cons->context->color_mode = value;
|
|
rz_cons_pal_update_event();
|
|
rz_print_set_flags(core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static bool core_scr_color_get(void *user, void *pvalue) {
|
|
RzCore *core = (RzCore *)user;
|
|
ut64 *value = (ut64 *)pvalue;
|
|
|
|
*value = core->cons->context->color_mode;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_decoff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_ADDRDEC;
|
|
} else {
|
|
core->print->flags &= (~RZ_PRINT_FLAGS_ADDRDEC);
|
|
}
|
|
rz_print_set_flags(core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbgbep(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_btalgo(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
free(core->dbg->btalgo);
|
|
core->dbg->btalgo = rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_libs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
free(core->dbg->glob_libs);
|
|
core->dbg->glob_libs = rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_unlibs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
free(core->dbg->glob_unlibs);
|
|
core->dbg->glob_unlibs = rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_bpinmaps(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->bp->bpinmaps = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_forks(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace_forks = node->i_value;
|
|
if (core->bin->is_debugger) {
|
|
rz_debug_attach(core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_gdb_page_size(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value < 64) { // 64 is hardcoded min packet size
|
|
return false;
|
|
}
|
|
if (isGdbPlugin(core)) {
|
|
char cmd[64];
|
|
snprintf(cmd, sizeof(cmd), "page_size %" PFMT64d, node->i_value);
|
|
free(rz_io_system(core->io, cmd));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_gdb_retries(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value <= 0) {
|
|
return false;
|
|
}
|
|
if (isGdbPlugin(core)) {
|
|
char cmd[64];
|
|
snprintf(cmd, sizeof(cmd), "retries %" PFMT64d, node->i_value);
|
|
free(rz_io_system(core->io, cmd));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_execs(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
#if __linux__
|
|
RzCore *core = (RzCore *)user;
|
|
core->dbg->trace_execs = node->i_value;
|
|
if (core->bin->is_debugger) {
|
|
rz_debug_attach(core->dbg, core->dbg->pid);
|
|
}
|
|
#else
|
|
if (node->i_value) {
|
|
RZ_LOG_WARN("core: dbg.execs: not supported in this platform.\n");
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_clone(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace_clone = node->i_value;
|
|
if (core->bin->is_debugger) {
|
|
rz_debug_attach(core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_follow_child(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->follow_child = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_create_new_console(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->create_new_console = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_trace_continue(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace_continue = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_aftersc(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace_aftersyscall = node->i_value;
|
|
if (core->bin->is_debugger) {
|
|
rz_debug_attach(core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_runprofile(void *user, void *data) {
|
|
RzCore *r = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
free((void *)r->io->runprofile);
|
|
if (!node || !*(node->value)) {
|
|
r->io->runprofile = NULL;
|
|
} else {
|
|
r->io->runprofile = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_args(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!node || !*(node->value)) {
|
|
core->io->args = NULL;
|
|
} else {
|
|
core->io->args = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbgbackend(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!strcmp(node->value, "?")) {
|
|
RzCmdStateOutput state = { 0 };
|
|
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_QUIET, core);
|
|
rz_core_debug_plugins_print(core, &state);
|
|
rz_cmd_state_output_print(&state);
|
|
rz_cmd_state_output_fini(&state);
|
|
return false;
|
|
}
|
|
if (!strcmp(node->value, "bf")) {
|
|
// hack
|
|
rz_config_set(core->config, "asm.arch", "bf");
|
|
}
|
|
rz_debug_use(core->dbg, node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_gotolimit(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->parse_goto_count = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_esilverbose(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->verbose = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_esilstackdepth(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value < 3) {
|
|
RZ_LOG_ERROR("core: esil.stack.depth: value must be greater than 2\n");
|
|
node->i_value = 32;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_fixrows(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->fix_rows = (int)node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_fixcolumns(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->fix_columns = atoi(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_rows(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->force_rows = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_hexcursor(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->cfmt = node->value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hexcompact(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_COMPACT;
|
|
} else {
|
|
core->print->flags &= (~RZ_PRINT_FLAGS_COMPACT);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_pairs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->pairs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_nodot(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_NODOT;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_NODOT;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_section(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_SECTION;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_SECTION;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_align(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_ALIGN;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_ALIGN;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_unalloc(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_UNALLOC;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_UNALLOC;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_unalloc_ch(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->io_unalloc_ch = *node->value ? node->value[0] : ' ';
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_header(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_HEADER;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_HEADER;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_bytes(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_NONHEX;
|
|
} else {
|
|
core->print->flags |= RZ_PRINT_FLAGS_NONHEX;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_ascii(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_NONASCII;
|
|
} else {
|
|
core->print->flags |= RZ_PRINT_FLAGS_NONASCII;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_style(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_STYLE;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_STYLE;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hex_hdroff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_HDROFF;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_HDROFF;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_log_events(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->log_events = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hexcomments(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_COMMENT;
|
|
} else {
|
|
core->print->flags &= ~RZ_PRINT_FLAGS_COMMENT;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_iopcache(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if ((bool)node->i_value) {
|
|
if (core) {
|
|
rz_config_set_b(core->config, "io.pcache.read", true);
|
|
rz_config_set_b(core->config, "io.pcache.write", true);
|
|
}
|
|
} else {
|
|
if (core && core->io) {
|
|
rz_io_desc_cache_fini_all(core->io);
|
|
rz_config_set_b(core->config, "io.pcache.read", false);
|
|
rz_config_set_b(core->config, "io.pcache.write", false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_iopcacheread(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if ((bool)node->i_value) {
|
|
if (core && core->io) {
|
|
core->io->p_cache |= 1;
|
|
}
|
|
} else {
|
|
if (core && core->io && core->io->p_cache) {
|
|
core->io->p_cache &= 2;
|
|
if (!(core->io->p_cache & 2)) {
|
|
rz_io_desc_cache_fini_all(core->io);
|
|
rz_config_set_b(core->config, "io.pcache", false);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_iopcachewrite(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if ((bool)node->i_value) {
|
|
if (core && core->io) {
|
|
core->io->p_cache |= 2;
|
|
}
|
|
} else {
|
|
if (core && core->io && core->io->p_cache) {
|
|
core->io->p_cache &= 1;
|
|
if (!(core->io->p_cache & 1)) {
|
|
rz_io_desc_cache_fini_all(core->io);
|
|
rz_config_set_b(core->config, "io.pcache", false);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void config_print_options_as_json(PJ *pj, const RzList /*<char *>*/ *options) {
|
|
RzListIter *iter;
|
|
const char *option;
|
|
pj_ka(pj, "options");
|
|
rz_list_foreach (options, iter, option) {
|
|
pj_s(pj, option);
|
|
}
|
|
pj_end(pj);
|
|
}
|
|
|
|
static void config_print_node_value_as_json(const RzConfigNode *node, PJ *pj, const char *key) {
|
|
if (rz_str_isnumber(node->value)) {
|
|
pj_kn(pj, key, rz_num_math(NULL, node->value));
|
|
return;
|
|
} else if (rz_str_is_bool(node->value)) {
|
|
pj_kb(pj, key, (node->value));
|
|
return;
|
|
} else {
|
|
pj_ks(pj, key, node->value);
|
|
}
|
|
}
|
|
|
|
static void config_print_long_json(PJ *pj, const char *name, const char *desc, ut32 flags) {
|
|
char *s_flags = rz_config_var_flags_as_string(flags);
|
|
pj_ks(pj, "name", name);
|
|
pj_ks(pj, "desc", rz_str_get(desc));
|
|
pj_ks(pj, "flags", rz_str_get(s_flags));
|
|
free(s_flags);
|
|
}
|
|
|
|
static void config_print_node_as_long_json(const RzConfigNode *node, PJ *pj) {
|
|
ut32 flags = rz_config_node_get_var_flags(node);
|
|
pj_o(pj);
|
|
config_print_long_json(pj, node->name, node->desc, flags);
|
|
config_print_options_as_json(pj, node->options);
|
|
config_print_node_value_as_json(node, pj, "value");
|
|
pj_end(pj);
|
|
}
|
|
|
|
static void config_print_var_as_long_json(const RzConfigVar *var, PJ *pj) {
|
|
const char *name = rz_config_var_get_name(var);
|
|
const char *desc = rz_config_var_get_desc(var);
|
|
const RzList *options = rz_config_var_get_options(var);
|
|
ut32 flags = rz_config_var_get_flags(var);
|
|
pj_o(pj);
|
|
config_print_long_json(pj, name, desc, flags);
|
|
config_print_options_as_json(pj, options);
|
|
rz_config_var_as_json(var, pj, "value");
|
|
pj_end(pj);
|
|
}
|
|
|
|
typedef struct core_config_print_s {
|
|
RzCmdStateOutput *state;
|
|
const char *str;
|
|
char color_name[32];
|
|
char color_value[32];
|
|
char color_meta[32];
|
|
char reset_str[32];
|
|
} CoreConfigPrint;
|
|
|
|
static void core_config_print_array_as_string(const RzList /*<char *>*/ *list, bool allow_empty) {
|
|
const char *entry;
|
|
const RzListIter *it;
|
|
if (rz_list_empty(list) && !allow_empty) {
|
|
return;
|
|
}
|
|
rz_cons_print("[");
|
|
rz_list_foreach (list, it, entry) {
|
|
if (rz_list_head(list) != it) {
|
|
rz_cons_printf(", %s", entry);
|
|
} else {
|
|
rz_cons_print(entry);
|
|
}
|
|
}
|
|
rz_cons_print("]");
|
|
}
|
|
|
|
static void core_config_print_var_as_string(const RzConfigEntry *entry, ut32 flags) {
|
|
if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_INT)) {
|
|
ut64 value = rz_config_entry_get_integer(entry);
|
|
if (value > 0x1000) {
|
|
rz_cons_printf("0x%" PFMT64x, value);
|
|
} else {
|
|
rz_cons_printf("%" PFMT64u, value);
|
|
}
|
|
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_BOOL)) {
|
|
bool value = rz_config_entry_get_bool(entry);
|
|
rz_cons_print(rz_str_bool(value));
|
|
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_STR)) {
|
|
const char *value = rz_config_entry_get_string(entry);
|
|
rz_cons_print(value);
|
|
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_LIST)) {
|
|
RzList *list = rz_config_var_get_list(&entry->var);
|
|
core_config_print_array_as_string(list, true);
|
|
rz_list_free(list);
|
|
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_ITV)) {
|
|
RzInterval itv = rz_config_var_get_interval(&entry->var);
|
|
rz_cons_printf("[0x%08" PFMT64x ",0x%08" PFMT64x "]", rz_itv_begin(itv), rz_itv_end(itv));
|
|
}
|
|
}
|
|
|
|
static bool core_config_print_iterator(const RzConfigEntry *entry, void *user) {
|
|
CoreConfigPrint *ccp = (CoreConfigPrint *)user;
|
|
const char *e_name = rz_config_entry_get_name(entry);
|
|
if (RZ_STR_ISNOTEMPTY(ccp->str) && !rz_str_startswith(e_name, ccp->str)) {
|
|
return true;
|
|
}
|
|
|
|
const char *name = NULL;
|
|
const char *desc = "";
|
|
const RzList *options = NULL;
|
|
ut32 e_flags = 0;
|
|
RzOutputMode mode = ccp->state->mode;
|
|
PJ *pj = ccp->state->d.pj;
|
|
|
|
if (entry->is_variable) {
|
|
name = rz_config_var_get_name(&entry->var);
|
|
desc = rz_config_var_get_desc(&entry->var);
|
|
options = rz_config_var_get_options(&entry->var);
|
|
e_flags = rz_config_var_get_flags(&entry->var);
|
|
} else {
|
|
name = entry->node.name;
|
|
desc = rz_str_get(entry->node.desc);
|
|
options = entry->node.options;
|
|
e_flags = rz_config_node_get_var_flags(&entry->node);
|
|
}
|
|
|
|
char *s_flags = rz_config_var_flags_as_string(e_flags);
|
|
|
|
switch (mode) {
|
|
case RZ_OUTPUT_MODE_JSON:
|
|
if (entry->is_variable) {
|
|
rz_config_var_as_json(&entry->var, pj, name);
|
|
} else {
|
|
config_print_node_value_as_json(&entry->node, pj, name);
|
|
}
|
|
break;
|
|
case RZ_OUTPUT_MODE_LONG_JSON:
|
|
if (entry->is_variable) {
|
|
config_print_var_as_long_json(&entry->var, pj);
|
|
} else {
|
|
config_print_node_as_long_json(&entry->node, pj);
|
|
}
|
|
break;
|
|
case RZ_OUTPUT_MODE_LONG: {
|
|
rz_cons_printf("%s%20s = %s", ccp->color_name, name, ccp->color_value);
|
|
core_config_print_var_as_string(entry, e_flags);
|
|
rz_cons_printf(" %s(%s); %s%s ", ccp->color_meta, s_flags, ccp->reset_str, desc);
|
|
core_config_print_array_as_string(options, false);
|
|
rz_cons_println("");
|
|
break;
|
|
}
|
|
case RZ_OUTPUT_MODE_QUIET:
|
|
rz_cons_printf("%s=", name);
|
|
core_config_print_var_as_string(entry, e_flags);
|
|
rz_cons_println("");
|
|
break;
|
|
case RZ_OUTPUT_MODE_STANDARD: {
|
|
rz_cons_printf("%s%20s: %s%s\n", ccp->color_name, name, ccp->reset_str, desc);
|
|
break;
|
|
}
|
|
case RZ_OUTPUT_MODE_STR_BUF:
|
|
rz_strbuf_appendf(ccp->state->d.sbuf, "%20s: %10s - %s\n", name, s_flags, desc);
|
|
break;
|
|
default:
|
|
rz_warn_if_reached();
|
|
break;
|
|
}
|
|
|
|
free(s_flags);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Prints the configuation variables with their description and its values
|
|
*
|
|
* \param cfg reference to RzConfig
|
|
* \param str reference to the key that can be passed to filter the output
|
|
* \param state reference to RzCmdStateOutput
|
|
*/
|
|
RZ_API void rz_core_config_print_all(RzConfig *cfg, const char *str, RzCmdStateOutput *state) {
|
|
rz_return_if_fail(cfg);
|
|
CoreConfigPrint ccp = { 0 };
|
|
ccp.state = state;
|
|
ccp.str = str;
|
|
const bool color_enabled = rz_config_get_i(cfg, "scr.color") > 0;
|
|
|
|
// begin
|
|
switch (state->mode) {
|
|
case RZ_OUTPUT_MODE_LONG_JSON:
|
|
pj_a(state->d.pj);
|
|
break;
|
|
case RZ_OUTPUT_MODE_JSON:
|
|
pj_o(state->d.pj);
|
|
break;
|
|
case RZ_OUTPUT_MODE_LONG:
|
|
if (color_enabled) {
|
|
RzColor color_name_val = rz_cons_pal_get("label");
|
|
RzColor color_value_val = rz_cons_pal_get("args");
|
|
RzColor color_meta_val = rz_cons_pal_get("comment");
|
|
RzColor reset_val = rz_cons_pal_get("help");
|
|
rz_cons_rgb_str(ccp.color_name, sizeof(ccp.color_name), &color_name_val);
|
|
rz_cons_rgb_str(ccp.color_value, sizeof(ccp.color_value), &color_value_val);
|
|
rz_cons_rgb_str(ccp.color_meta, sizeof(ccp.color_meta), &color_meta_val);
|
|
rz_cons_rgb_str(ccp.reset_str, sizeof(ccp.reset_str), &reset_val);
|
|
}
|
|
break;
|
|
case RZ_OUTPUT_MODE_STANDARD:
|
|
if (color_enabled) {
|
|
RzColor color_val = rz_cons_pal_get("label");
|
|
RzColor reset_val = rz_cons_pal_get("help");
|
|
rz_cons_rgb_str(ccp.color_name, sizeof(ccp.color_name), &color_val);
|
|
rz_cons_rgb_str(ccp.reset_str, sizeof(ccp.reset_str), &reset_val);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
rz_config_iterate_over(cfg, core_config_print_iterator, &ccp);
|
|
|
|
if (state->mode == RZ_OUTPUT_MODE_LONG_JSON || state->mode == RZ_OUTPUT_MODE_JSON) {
|
|
pj_end(state->d.pj);
|
|
}
|
|
}
|
|
|
|
static bool cb_cmd_esil_ioer(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_ioer);
|
|
esil->cmd_ioer = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_todo(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_todo);
|
|
esil->cmd_todo = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_intr(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_intr);
|
|
esil->cmd_intr = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_mdevrange(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->mdev_range);
|
|
esil->mdev_range = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_step(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_step);
|
|
esil->cmd_step = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_step_out(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_step_out);
|
|
esil->cmd_step_out = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_mdev(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
free(esil->cmd_mdev);
|
|
esil->cmd_mdev = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmd_esil_trap(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->cmd = rz_core_esil_cmd;
|
|
esil->cmd_trap = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_cmddepth(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
int c = RZ_MAX(((RzConfigNode *)data)->i_value, 0);
|
|
core->max_cmd_depth = c;
|
|
core->cons->context->cmd_depth = c;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hexcols(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
int c = RZ_MIN(1024, RZ_MAX(((RzConfigNode *)data)->i_value, 0));
|
|
core->print->cols = c; // & ~1;
|
|
core->dbg->regcols = c / 4;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_hexstride(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
((RzCore *)user)->print->stride = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_search_kwidx(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->search->n_kws = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_cache_mode(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cachemode = true;
|
|
} else {
|
|
core->io->cachemode = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_cache_read(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cached |= RZ_PERM_R;
|
|
} else {
|
|
core->io->cached &= ~RZ_PERM_R;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_cache_write(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cached |= RZ_PERM_W;
|
|
} else {
|
|
core->io->cached &= ~RZ_PERM_W;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_cache(void *user, void *data) {
|
|
(void)cb_io_cache_read(user, data);
|
|
(void)cb_io_cache_write(user, data);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_ioaslr(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value != core->io->aslr) {
|
|
core->io->aslr = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_pava(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->pava = node->i_value;
|
|
if (node->i_value && core->io->va) {
|
|
RZ_LOG_WARN("core: you may probably want to disable io.va too\n");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_iova(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value != core->io->va) {
|
|
core->io->va = node->i_value;
|
|
/* ugly fix for rizin -d ... "rizin is going to die soon ..." */
|
|
if (core->io->desc) {
|
|
rz_core_block_read(core);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_ioff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->io->ff = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_io_oxff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->io->Oxff = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_filepath(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
char *pikaboo = strstr(node->value, "://");
|
|
if (pikaboo) {
|
|
if (pikaboo[3] == '/') {
|
|
rz_config_set(core->config, "file.lastpath", node->value);
|
|
char *ovalue = node->value;
|
|
node->value = rz_str_dup(pikaboo + 3);
|
|
free(ovalue);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
rz_config_set(core->config, "file.lastpath", node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_ioautofd(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->io->autofd = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_color_grep(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
/* Let cons know we have a new pager. */
|
|
core->cons->grep_color = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_color_grep_highlight(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->grep_highlight = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_pager(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!strcmp(node->value, "?")) {
|
|
RZ_LOG_ERROR("usage: scr.pager must be '..' for internal less, or the path to a program in $PATH\n");
|
|
return false;
|
|
}
|
|
/* Let cons know we have a new pager. */
|
|
free(core->cons->pager);
|
|
core->cons->pager = rz_str_dup(node->value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_breaklines(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->break_lines = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_gadgets(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->scr_gadgets = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrbreakword(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value) {
|
|
rz_cons_breakword(node->value);
|
|
} else {
|
|
rz_cons_breakword(NULL);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrcolumns(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
int n = atoi(node->value);
|
|
core->cons->force_columns = n;
|
|
core->dbg->regcols = n / 20;
|
|
rz_cons_get_size(NULL);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrfgets(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->user_fgets = node->i_value
|
|
? NULL
|
|
: (void *)rz_core_fgets;
|
|
core->cons->user_fgets_user = core;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrhtml(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->is_html = node->i_value;
|
|
// TODO: control error and restore old value (return false?) show errormsg?
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrhighlight(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_highlight(node->value);
|
|
return true;
|
|
}
|
|
|
|
#if __WINDOWS__
|
|
static bool scr_vtmode(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (rz_str_is_true(node->value)) {
|
|
node->i_value = RZ_VIRT_TERM_MODE_OUTPUT_ONLY;
|
|
}
|
|
node->i_value = node->i_value > RZ_VIRT_TERM_MODE_COMPLETE ? RZ_VIRT_TERM_MODE_COMPLETE : node->i_value;
|
|
RzCons *cons = rz_cons_singleton();
|
|
cons->line->vtmode = cons->vtmode = node->i_value;
|
|
|
|
DWORD mode;
|
|
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
|
|
if (GetConsoleMode(input, &mode)) {
|
|
if (node->i_value == RZ_VIRT_TERM_MODE_COMPLETE) {
|
|
// Enabling VT input must preserve the rest of the console input flags.
|
|
SetConsoleMode(input, mode | ENABLE_VIRTUAL_TERMINAL_INPUT);
|
|
cons->term_raw |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
|
} else {
|
|
SetConsoleMode(input, mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT);
|
|
cons->term_raw &= ~ENABLE_VIRTUAL_TERMINAL_INPUT;
|
|
}
|
|
}
|
|
HANDLE streams[] = { GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE) };
|
|
int i;
|
|
if (node->i_value > RZ_VIRT_TERM_MODE_DISABLE) {
|
|
for (i = 0; i < RZ_ARRAY_SIZE(streams); i++) {
|
|
if (GetConsoleMode(streams[i], &mode)) {
|
|
// Output VT mode is an additive toggle on the current console output state.
|
|
SetConsoleMode(streams[i],
|
|
mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < RZ_ARRAY_SIZE(streams); i++) {
|
|
if (GetConsoleMode(streams[i], &mode)) {
|
|
// Disabling VT output should only clear the bits enabled by this callback.
|
|
SetConsoleMode(streams[i],
|
|
mode & ~(ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_WRAP_AT_EOL_OUTPUT));
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
static bool cb_screcho(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->echo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrlinesleep(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->linesleep = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrpagesize(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->pagesize = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrflush(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->flush = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrstrconv(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Valid values for scr.strconv:\n"
|
|
" asciiesc convert to ascii with non-ascii chars escaped\n"
|
|
" asciidot convert to ascii with non-ascii chars turned into a dot (except control chars stated below)\n"
|
|
"\n"
|
|
"Ascii chars are in the range 0x20-0x7e. Always escaped control chars are alert (\\a),\n"
|
|
"backspace (\\b), formfeed (\\f), newline (\\n), carriage return (\\r), horizontal tab (\\t)\n"
|
|
"and vertical tab (\\v). Also, double quotes (\\\") are always escaped, but backslashes (\\\\)\n"
|
|
"are only escaped if str.escbslash = true.\n");
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
} else {
|
|
free((char *)core->print->strconv_mode);
|
|
core->print->strconv_mode = rz_str_dup(node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_graphformat(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!strcmp(node->value, "?")) {
|
|
rz_cons_printf("png\njpg\npdf\nps\nsvg\njson\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_exectrap(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->exectrap = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_iotrap(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
RzAnalysisEsil *esil = rz_analysis_get_esil(core->analysis);
|
|
if (esil) {
|
|
esil->iotrap = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_bgfill(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_BGFILL;
|
|
} else {
|
|
core->print->flags &= (~RZ_PRINT_FLAGS_BGFILL);
|
|
}
|
|
rz_print_set_flags(core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrint(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->context->is_interactive = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrnkey(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!strcmp(node->value, "help") || *node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_histblock(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->histblock = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scrprompt(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->print->scr_prompt = node->i_value;
|
|
core->cons->line->echo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_contiguous(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->search->contiguous = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_searchalign(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (rz_bits_count_ones_ut64(node->i_value) != 1) {
|
|
RZ_LOG_ERROR("Alignment is only defined for '>0' and 'n^2'. Is = %" PFMT64d "\n", node->i_value);
|
|
return false;
|
|
}
|
|
core->search->align = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_segoff(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->print->flags |= RZ_PRINT_FLAGS_SEGOFF;
|
|
} else {
|
|
core->print->flags &= (((ut32)-1) & (~RZ_PRINT_FLAGS_SEGOFF));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_seggrn(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_set_segment_granularity(core->rasm, node->i_value);
|
|
rz_analysis_set_segment_granularity(core->analysis, node->i_value);
|
|
core->print->seggrn = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_stopthreads(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->stop_all_threads = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_scr_prompt_popup(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->show_autocomplete_widget = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool core_dbg_swstep_set(void *user, const void *pvalue) {
|
|
RzCore *core = (RzCore *)user;
|
|
core->dbg->swstep = *((const bool *)pvalue);
|
|
return true;
|
|
}
|
|
|
|
static bool core_dbg_swstep_get(void *user, void *pvalue) {
|
|
RzCore *core = (RzCore *)user;
|
|
bool *value = (bool *)pvalue;
|
|
*value = core->dbg->swstep;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_consbreak(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->consbreak = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_teefile(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_cons_singleton()->teefile = node->value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_trace(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace->enabled = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_tracetag(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->trace->tag = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_utf8(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
rz_asm_set_utf8(core->rasm, (bool)node->i_value);
|
|
rz_cons_set_utf8((bool)node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_utf8_curvy(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->use_utf8_curvy = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_visual_mode(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value > RZ_CORE_VISUAL_MODE_CD) {
|
|
node->i_value = RZ_CORE_VISUAL_MODE_PX;
|
|
}
|
|
RzCore *core = (RzCore *)user;
|
|
((RzCoreVisual *)core->visual)->printidx = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dotted(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->cons->dotted_lines = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_zoombyte(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
switch (*node->value) {
|
|
case 'p':
|
|
case 'f':
|
|
case 's':
|
|
case '0':
|
|
case 'F':
|
|
case 'e':
|
|
case 'h':
|
|
core->print->zoom->mode = *node->value;
|
|
break;
|
|
default:
|
|
RZ_LOG_ERROR("core: invalid zoom.byte value. See pz? for help\n");
|
|
rz_cons_printf("pzp\npzf\npzs\npz0\npzF\npze\npzh\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binverbose(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->bin->verbose = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binhashesdefault(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
rz_cons_printf("Multiple algorithms can be specified in a comma-separated list (no spaces).\n");
|
|
return false;
|
|
}
|
|
rz_list_free(core->bin->default_hashes);
|
|
core->bin->default_hashes = rz_str_split_duplist(node->value, ",", true);
|
|
if (!core->bin->default_hashes) {
|
|
core->bin->default_hashes = rz_list_new();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binstrings(void *user, void *data) {
|
|
const ut32 req = RZ_BIN_REQ_STRINGS;
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->bin->filter_rules |= req;
|
|
} else {
|
|
core->bin->filter_rules &= ~req;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_bindbginfo(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!core || !core->bin) {
|
|
return false;
|
|
}
|
|
core->bin->want_dbginfo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dwo_path(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!(core && core->bin && node)) {
|
|
return false;
|
|
}
|
|
if (RZ_STR_ISNOTEMPTY(node->value) && rz_bin_cur(core->bin)) {
|
|
rz_core_bin_apply_dwarf(core, rz_bin_cur(core->bin));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_binprefix(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (!core || !core->bin) {
|
|
return false;
|
|
}
|
|
if (node->value && *node->value) {
|
|
if (!strcmp(node->value, "auto")) {
|
|
if (!core->bin->file) {
|
|
return false;
|
|
}
|
|
char *name = (char *)rz_file_basename(core->bin->file);
|
|
if (name) {
|
|
rz_name_filter(name, strlen(name), true);
|
|
rz_str_filter(name);
|
|
core->bin->prefix = rz_str_dup(name);
|
|
free(name);
|
|
}
|
|
} else {
|
|
core->bin->prefix = node->value;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static ConfigOptDescr search_in_opts[] = {
|
|
{ "raw", "all raw memory (behaves as 'file')" },
|
|
{ "file", "all the file" },
|
|
{ "block", "current read block" },
|
|
{ "range", "search only within the range" },
|
|
{ "analysis.bb", "current basic-block" },
|
|
{ "analysis.fcn", "current function" },
|
|
{ "bin.section", "current section" },
|
|
{ "bin.sections[.rwx]", "all bin sections (with matching perm)" },
|
|
{ "bin.segment", "current segment" },
|
|
{ "bin.segments[.rwx]", "all bin segments (with matching perm)" },
|
|
{ "dbg.heap", "debugger heap" },
|
|
{ "dbg.stack", "debugger stack" },
|
|
{ "dbg.program", "debugger program (exec only)" },
|
|
{ "dbg.map", "current debugger memory map" },
|
|
{ "dbg.maps[.rwx]", "all debugger memory maps (with matching perm)" },
|
|
{ "io.map", "current io map" },
|
|
{ "io.maps[.rwx]", "all io maps (with matching perm)" },
|
|
{ "io.sky[.rwx]", "all skyline segments (with matching perm)" },
|
|
};
|
|
|
|
static bool cb_search_in(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzCore *core = (RzCore *)user;
|
|
RzInterval itv = {
|
|
.addr = rz_config_get_i(core->config, "search.from"),
|
|
.size = rz_config_get_i(core->config, "search.to")
|
|
};
|
|
if (node->value[0] != '?') {
|
|
RzList *bounds = rz_core_get_boundaries(core, itv, node->value);
|
|
if (!bounds) {
|
|
return false;
|
|
}
|
|
rz_list_free(bounds);
|
|
return true;
|
|
} else if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Valid values for search.in (depends on .from/.to and io.va):\n");
|
|
for (size_t i = 0; i < RZ_ARRAY_SIZE(search_in_opts); ++i) {
|
|
rz_cons_printf("%-18s - %s\n", search_in_opts[i].option, search_in_opts[i].description);
|
|
}
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool cb_search_show_progress(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (rz_str_is_false(node->value)) {
|
|
free(node->value);
|
|
node->value = rz_str_dup("false");
|
|
} else if (!rz_str_cmp_list("num_hits intervals", node->value, ' ')) {
|
|
RZ_LOG_ERROR("search.show_progress: invalid value (%s), supported only `false, num_hits, intervals`\n", node->value);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_in(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] != '?') {
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->noncode = (strchr(node->value, 'x') == NULL);
|
|
return true;
|
|
} else if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Valid values for analysis.in (depends on .from/.to and io.va):\n");
|
|
for (size_t i = 0; i < RZ_ARRAY_SIZE(search_in_opts); ++i) {
|
|
rz_cons_printf("%-18s - %s\n", search_in_opts[i].option, search_in_opts[i].description);
|
|
}
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool cb_zoom_in(void *user, void *data) {
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (node->value[0] != '?') {
|
|
return true;
|
|
} else if (strlen(node->value) > 1 && node->value[1] == '?') {
|
|
rz_cons_printf("Valid values for zoom.in (depends on .from/.to and io.va):\n");
|
|
for (size_t i = 0; i < RZ_ARRAY_SIZE(search_in_opts); ++i) {
|
|
rz_cons_printf("%-18s - %s\n", search_in_opts[i].option, search_in_opts[i].description);
|
|
}
|
|
} else {
|
|
print_node_options(node);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool cb_analysis_roregs(RzCore *core, RzConfigNode *node) {
|
|
RzReg *rreg = rz_analysis_get_reg(core->analysis);
|
|
if (rreg) {
|
|
rz_list_free(rreg->roregs);
|
|
rreg->roregs = rz_str_split_duplist(node->value, ",", true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysissyscc(RzCore *core, RzConfigNode *node) {
|
|
if (core && core->analysis) {
|
|
if (!strcmp(node->value, "?")) {
|
|
rz_core_types_calling_conventions_print(core, RZ_OUTPUT_MODE_STANDARD);
|
|
return false;
|
|
}
|
|
rz_analysis_set_syscc_default(core->analysis, node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysiscc(RzCore *core, RzConfigNode *node) {
|
|
if (core && core->analysis) {
|
|
if (!strcmp(node->value, "?")) {
|
|
rz_core_types_calling_conventions_print(core, RZ_OUTPUT_MODE_STANDARD);
|
|
return false;
|
|
}
|
|
rz_analysis_set_cc_default(core->analysis, node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_gp(RzCore *core, RzConfigNode *node) {
|
|
rz_analysis_set_gp(core->analysis, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_from(RzCore *core, RzConfigNode *node) {
|
|
if (rz_config_get_i(core->config, "analysis.limits")) {
|
|
ut64 to = rz_config_get_i(core->config, "analysis.to");
|
|
rz_analysis_set_limits(core->analysis, node->i_value, to);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_to(RzCore *core, RzConfigNode *node) {
|
|
if (rz_config_get_i(core->config, "analysis.limits")) {
|
|
ut64 from = rz_config_get_i(core->config, "analysis.from");
|
|
rz_analysis_set_limits(core->analysis, from, node->i_value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_limits(void *user, RzConfigNode *node) {
|
|
RzCore *core = (RzCore *)user;
|
|
if (node->i_value) {
|
|
rz_analysis_set_limits(core->analysis,
|
|
rz_config_get_i(core->config, "analysis.from"),
|
|
rz_config_get_i(core->config, "analysis.to"));
|
|
} else {
|
|
rz_analysis_unset_limits(core->analysis);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_rnr(void *user, RzConfigNode *node) {
|
|
RzCore *core = (RzCore *)user;
|
|
rz_analysis_set_recursive_noreturn(core->analysis, node->i_value);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmptbl(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmptbl = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmptblmax(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmptbl_maxcount = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmptblmaxoffset(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmptbl_maxoffset = node->i_value > UT32_MAX ? UT32_MAX : node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_cjmpref(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->cjmpref = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmpref(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmpref = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmpabove(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmpabove = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_loads(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->loads = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_followdatarefs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->followdatarefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_jmpmid(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->jmpmid = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_searchstringrefs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->searchstringrefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_pushret(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->pushret = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_brokenrefs(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->followbrokenfcnsrefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_trycatch(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->trycatch = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_bb_max_size(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->bb_max_size = RZ_MIN(node->i_value, RZ_ANALYSIS_BLOCK_MAX_SIZE);
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_fcn_max_size(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
RzAnalysisOptions *opt = rz_analysis_get_options(core->analysis);
|
|
opt->fcn_max_size = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_analysis_cpp_abi(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
|
|
if (*node->value) {
|
|
if (strcmp(node->value, "itanium") == 0) {
|
|
rz_analysis_set_cpp_abi(core->analysis, RZ_ANALYSIS_CPP_ABI_ITANIUM);
|
|
return true;
|
|
} else if (strcmp(node->value, "msvc") == 0) {
|
|
rz_analysis_set_cpp_abi(core->analysis, RZ_ANALYSIS_CPP_ABI_MSVC);
|
|
return true;
|
|
}
|
|
RZ_LOG_ERROR("core: analysis.cpp.abi: cannot find '%s'\n", node->value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool cb_malloc(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
|
|
if (node->value) {
|
|
if (!strcmp("jemalloc", node->value) || !strcmp("glibc", node->value)) {
|
|
if (core->dbg) {
|
|
core->dbg->malloc = data;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_log_config_level(void *coreptr, void *nodeptr) {
|
|
RzConfigNode *node = (RzConfigNode *)nodeptr;
|
|
rz_log_set_level(node->i_value);
|
|
return true;
|
|
}
|
|
|
|
#if RZ_BUILD_DEBUG
|
|
static bool cb_log_config_abortlevel(void *coreptr, void *nodeptr) {
|
|
RzConfigNode *node = (RzConfigNode *)nodeptr;
|
|
rz_log_set_abortlevel(node->i_value);
|
|
return true;
|
|
}
|
|
#endif /* RZ_BUILD_DEBUG */
|
|
|
|
static bool cb_log_file(void *coreptr, void *nodeptr) {
|
|
RzConfigNode *node = (RzConfigNode *)nodeptr;
|
|
if (!rz_log_set_file(node->value)) {
|
|
RZ_LOG_ERROR("log.file: cannot open '%s'\n", node->value);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_log_config_show_sources(void *coreptr, void *nodeptr) {
|
|
RzConfigNode *node = (RzConfigNode *)nodeptr;
|
|
const char *value = node->value;
|
|
if (rz_str_is_true(value)) {
|
|
rz_log_set_show_sources(true);
|
|
} else if (rz_str_is_false(value)) {
|
|
rz_log_set_show_sources(false);
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_log_config_colors(void *coreptr, void *nodeptr) {
|
|
RzConfigNode *node = (RzConfigNode *)nodeptr;
|
|
const char *value = node->value;
|
|
if (rz_str_is_true(value)) {
|
|
rz_log_set_colors(true);
|
|
} else if (rz_str_is_false(value)) {
|
|
rz_log_set_colors(false);
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cb_dbg_verbose(void *user, void *data) {
|
|
RzCore *core = (RzCore *)user;
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
core->dbg->verbose = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static bool cb_flirt(void *user, void *data) {
|
|
rz_return_val_if_fail(data, false);
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool rzil_halt_on_exec(void *user, void *data) {
|
|
rz_return_val_if_fail(data, false);
|
|
RzConfigNode *node = (RzConfigNode *)data;
|
|
if (*node->value == '?') {
|
|
print_node_options(node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
RZ_API int rz_core_config_init(RzCore *core) {
|
|
int i;
|
|
char buf[128], *p, *tmpdir;
|
|
RzConfigNode *n;
|
|
RzConfig *cfg = core->config = rz_config_new(core);
|
|
if (!cfg) {
|
|
return 0;
|
|
}
|
|
/* dir.prefix is used in other modules, set it first */
|
|
{
|
|
char *pfx = rz_sys_getenv("RZ_PREFIX");
|
|
if (!pfx) {
|
|
const char *pfx_const = rz_path_prefix(core->sys_path);
|
|
SETCB("dir.prefix", pfx_const, NULL, "Default prefix rizin was compiled for");
|
|
} else {
|
|
SETCB("dir.prefix", pfx, NULL, "Default prefix rizin was compiled for");
|
|
free(pfx);
|
|
}
|
|
}
|
|
#if __ANDROID__
|
|
{ // use dir.home and also adjust check for permissions in directory before choosing a home
|
|
char *h = rz_sys_getenv(RZ_SYS_HOME);
|
|
if (h) {
|
|
if (!strcmp(h, "/")) {
|
|
rz_sys_setenv(RZ_SYS_HOME, "/data/local/tmp");
|
|
}
|
|
free(h);
|
|
}
|
|
}
|
|
#endif
|
|
SETCB("cmd.times", "", &cb_cmdtimes, "Run when a command is repeated (number prefix)");
|
|
/* pdb */
|
|
SETPREF("pdb.server", "https://msdl.microsoft.com/download/symbols", "Semi-colon separated list of base URLs for Microsoft symbol servers");
|
|
{
|
|
char *pdb_path = rz_path_home_prefix(RZ_PDB);
|
|
SETPREF("pdb.symstore", pdb_path, "Path to downstream symbol store");
|
|
RZ_FREE(pdb_path);
|
|
}
|
|
SETI("pdb.extract", 1, "Avoid extract of the pdb file, just download");
|
|
SETI("pdb.autoload", false, "Automatically load the required pdb files for loaded DLLs");
|
|
|
|
/* elf */
|
|
SETBPREF("elf.checks.sections", "true", "Check elf sections during loading");
|
|
SETBPREF("elf.checks.segments", "true", "Check elf segments during loading");
|
|
SETBPREF("elf.load.sections", "true", "Automatically load elf sections");
|
|
|
|
/* analysis */
|
|
SETBPREF("analysis.detectwrites", "false", "Automatically reanalyze function after a write");
|
|
SETPREF("analysis.fcnprefix", "fcn", "Prefix new function names with this");
|
|
const char *analysiscc = rz_analysis_cc_default(core->analysis);
|
|
SETCB("analysis.cc", analysiscc ? analysiscc : "", (RzConfigCallback)&cb_analysiscc, "Specify default calling convention");
|
|
const char *analysissyscc = rz_analysis_syscc_default(core->analysis);
|
|
SETCB("analysis.syscc", analysissyscc ? analysissyscc : "", (RzConfigCallback)&cb_analysissyscc, "Specify default syscall calling convention");
|
|
SETCB("analysis.roregs", "gp,zero", (RzConfigCallback)&cb_analysis_roregs, "Comma separated list of register names to be readonly");
|
|
SETICB("analysis.gp", 0, (RzConfigCallback)&cb_analysis_gp, "Set the value of the GP register (MIPS)");
|
|
SETBPREF("analysis.gpfixed", "true", "Set gp register to analysis.gp before emulating each instruction in aae");
|
|
SETCB("analysis.limits", "false", (RzConfigCallback)&cb_analysis_limits, "Restrict analysis to address range [analysis.from:analysis.to]");
|
|
SETCB("analysis.rnr", "false", (RzConfigCallback)&cb_analysis_rnr, "Recursive no return checks (EXPERIMENTAL)");
|
|
SETCB("analysis.limits", "false", (RzConfigCallback)&cb_analysis_limits, "Restrict analysis to address range [analysis.from:analysis.to]");
|
|
SETICB("analysis.from", UT64_MAX, (RzConfigCallback)&cb_analysis_from, "Lower limit on the address range for analysis");
|
|
SETICB("analysis.to", UT64_MAX, (RzConfigCallback)&cb_analysis_to, "Upper limit on the address range for analysis");
|
|
n = NODECB("analysis.in", "io.maps.x", &cb_analysis_in);
|
|
SETDESC(n, "Specify search boundaries for analysis");
|
|
SETOPTIONS(n, "range", "block",
|
|
"bin.segment", "bin.segments", "bin.segments.x", "bin.segments.r", "bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
|
|
"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
|
|
"dbg.stack", "dbg.heap",
|
|
"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
|
|
"analysis.fcn", "analysis.bb",
|
|
NULL);
|
|
SETI("analysis.timeout", 0, "Stop analyzing after a couple of seconds");
|
|
SETCB("analysis.jmp.retpoline", "true", &cb_analysis_jmpretpoline, "Analyze retpolines, may be slower if not needed");
|
|
|
|
SETCB("analysis.armthumb", "false", &cb_analysis_armthumb, "aae computes arm/thumb changes (lot of false positives ahead)");
|
|
SETCB("analysis.jmp.after", "true", &cb_analysis_afterjmp, "Continue analysis after jmp/ujmp");
|
|
SETCB("analysis.trap.after", "false", &cb_analysis_aftertrap, "Continue analysis after trap instructions.");
|
|
SETCB("analysis.delay", "true", &cb_analysis_delay, "Enable delay slot analysis if supported by the architecture");
|
|
SETICB("analysis.depth", 64, &cb_analysis_depth, "Max depth at code analysis"); // XXX: warn if depth is > 50 .. can be problematic
|
|
SETICB("analysis.graph_depth", 256, &cb_analysis_graphdepth, "Max depth for path search");
|
|
SETICB("analysis.sleep", 0, &cb_analysis_sleep, "Sleep N usecs every so often during analysis. Avoid 100% CPU usage");
|
|
SETCB("analysis.ignbithints", "false", &cb_analysis_ignbithints, "Ignore the ahb hints (only obey asm.bits)");
|
|
SETBPREF("analysis.calls", "false", "Make basic af analysis walk into calls");
|
|
SETBPREF("analysis.autoname", "false", "Speculatively set a name for the functions, may result in some false positives");
|
|
SETBPREF("analysis.hasnext", "false", "Continue analysis after each function");
|
|
SETICB("analysis.nonull", 0, &cb_analysis_nonull, "Do not analyze regions of N null bytes");
|
|
SETBPREF("analysis.esil", "false", "Use the new ESIL code analysis");
|
|
SETCB("analysis.strings", "false", &cb_analysis_strings, "Identify and register strings during analysis (aar only)");
|
|
SETPREF("analysis.types.spec", "gcc", "Set profile for specifying format chars used in type analysis");
|
|
SETBPREF("analysis.types.verbose", "false", "Verbose output from type analysis");
|
|
SETBPREF("analysis.types.constraint", "true", "Enable constraint types analysis for variables");
|
|
SETCB("analysis.vars", "true", &cb_analysis_vars, "Analyze local variables and arguments");
|
|
SETBPREF("analysis.vinfun", "true", "Search values in functions (aav) (false by default to only find on non-code)");
|
|
SETBPREF("analysis.vinfunrange", "false", "Search values outside function ranges (requires analysis.vinfun=false)\n");
|
|
SETCB("analysis.norevisit", "false", &cb_analysis_norevisit, "Do not visit function analysis twice (EXPERIMENTAL)");
|
|
SETCB("analysis.nopskip", "true", &cb_analysis_nopskip, "Skip nops at the beginning of functions");
|
|
SETCB("analysis.hpskip", "false", &cb_analysis_hpskip, "Skip `mov reg, reg` and `lea reg, [reg] at the beginning of functions");
|
|
n = NODECB("analysis.arch", RZ_SYS_ARCH, &cb_asm_arch_set);
|
|
SETDESC(n, "Select the architecture to use");
|
|
update_analysis_arch_options(core, n);
|
|
SETCB("analysis.cpu", RZ_SYS_ARCH, &cb_asm_cpu_set, "Specify the analysis.cpu to use");
|
|
SETPREF("analysis.prelude", "", "Specify an hexpair to find preludes in code");
|
|
SETI("analysis.prelude.limit", 1024 * 1024 * 20, "Maximum size of the range to scan for preludes");
|
|
SETCB("analysis.recont", "false", &cb_analysis_recont, "End block after splitting a basic block instead of error"); // testing
|
|
SETCB("analysis.jmp.indir", "false", &cb_analysis_ijmp, "Follow the indirect jumps in function analysis"); // testing
|
|
SETI("analysis.ptrdepth", 3, "Maximum number of nested pointers to follow in analysis");
|
|
SETICB("asm.lines.maxref", 0, &cb_analysis_maxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
|
|
|
|
SETCB("analysis.jmp.tbl", "true", &cb_analysis_jmptbl, "Analyze jump tables in switch statements");
|
|
SETICB("analysis.jmp.tblmax", 512, &cb_analysis_jmptblmax, "Maximum amount of entries to analyze in jump tables");
|
|
SETICB("analysis.jmp.tblmaxoffset", 4096, &cb_analysis_jmptblmaxoffset, "Maximum offset from the jump table jump instruction to consider it valid");
|
|
|
|
SETCB("analysis.jmp.cref", "false", &cb_analysis_cjmpref, "Create references for conditional jumps");
|
|
SETCB("analysis.jmp.ref", "true", &cb_analysis_jmpref, "Create references for unconditional jumps");
|
|
|
|
SETCB("analysis.jmp.above", "true", &cb_analysis_jmpabove, "Jump above function pointer");
|
|
SETCB("analysis.loads", "false", &cb_analysis_loads, "Define as dword/string/qword when analyzing load instructions");
|
|
SETCB("analysis.datarefs", "false", &cb_analysis_followdatarefs, "Follow data references for code coverage");
|
|
SETCB("analysis.brokenrefs", "false", &cb_analysis_brokenrefs, "Follow function references as well if function analysis was failed");
|
|
SETCB("analysis.jmp.mid", "true", &cb_analysis_jmpmid, "Continue analysis after jump to middle of instruction (x86 only)");
|
|
|
|
SETCB("analysis.refstr", "false", &cb_analysis_searchstringrefs, "Search string references in data references");
|
|
SETCB("analysis.trycatch", "true", &cb_analysis_trycatch, "Honor try.X.Y.{from,to,catch} flags");
|
|
SETCB("analysis.bb.maxsize", "63K", &cb_analysis_bb_max_size, "Maximum basic block size");
|
|
SETCB("analysis.fcn_max_size", "256K", &cb_analysis_fcn_max_size, "Maximum function size (unspecified units)");
|
|
SETCB("analysis.pushret", "false", &cb_analysis_pushret, "Analyze push+ret as jmp");
|
|
|
|
n = NODECB("analysis.cpp.abi", "itanium", &cb_analysis_cpp_abi);
|
|
SETDESC(n, "Select C++ ABI (Compiler)");
|
|
SETOPTIONS(n, "itanium", "msvc", NULL);
|
|
SETB("analysis.apply.signature", true, "enables/disables auto-applying signatures to the loaded binary (see also flirt.sigdb.path)");
|
|
SETB("analysis.resolve.pointers", true, "enables/disables analysis of pointers to data sections.");
|
|
|
|
#if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
|
|
SETCB("dbg.malloc", "glibc", &cb_malloc, "Choose malloc structure parser");
|
|
#else
|
|
SETCB("dbg.malloc", "jemalloc", &cb_malloc, "Choose malloc structure parser");
|
|
#endif
|
|
#if __GLIBC_MINOR__ > 25
|
|
SETBPREF("dbg.glibc.tcache", "true", "Set glib tcache parsing");
|
|
#else
|
|
SETBPREF("dbg.glibc.tcache", "false", "Set glib tcache parsing");
|
|
#endif
|
|
#if __x86_64__
|
|
SETI("dbg.glibc.ma_offset", 0x000000, "Main_arena offset from his symbol");
|
|
SETI("dbg.glibc.fc_offset", 0x00280, "First chunk offset from brk_start");
|
|
#else
|
|
SETI("dbg.glibc.ma_offset", 0x1bb000, "Main_arena offset from his symbol");
|
|
SETI("dbg.glibc.fc_offset", 0x148, "First chunk offset from brk_start");
|
|
#endif
|
|
SETI("dbg.glibc.fastbinmax", 10, "Upper bound on the number of fastbins printed");
|
|
|
|
n = NODECB("dbg.glibc.version", "auto", NULL);
|
|
SETDESC(n, "Set glibc version for heap parsing (auto-detected if 'auto')");
|
|
SETOPTIONS(n, "auto", "2.23", "2.26", "2.27", "2.29", "2.30", "2.31", "2.32", "2.33", "2.34", "2.35", "2.36", "2.37", "2.38", "2.39", NULL);
|
|
|
|
n = NODECB("dbg.jemalloc.version", "auto", NULL);
|
|
SETDESC(n, "Select jemalloc version for heap parsing (auto-detected if 'auto')");
|
|
SETOPTIONS(n, "auto", "4.5.0", "5.3.0", NULL);
|
|
|
|
n = NODECB("dbg.jemalloc.page_size", "auto", NULL);
|
|
SETDESC(n, "Select page size for jemalloc heap parsing (auto-detected if 'auto')");
|
|
SETOPTIONS(n, "auto", "4k", "16k", "64k", NULL);
|
|
|
|
n = NODECB("dbg.windows.version", "auto", NULL);
|
|
SETDESC(n, "Set Windows 10 version for heap parsing (default '1511' if 'auto')");
|
|
SETOPTIONS(n, "auto",
|
|
"1511", "1607", "1703", "1709", "1803", "1809",
|
|
"1903", "1909", "2004", "20H2", "21H1", "21H2", "22H2", NULL);
|
|
|
|
SETBPREF("esil.prestep", "true", "Step before esil evaluation in `de` commands");
|
|
SETPREF("esil.fillstack", "", "Initialize ESIL stack with (random, debrujn, sequence, zeros, ...)");
|
|
SETICB("esil.verbose", 0, &cb_esilverbose, "Show ESIL verbose level (0, 1, 2)");
|
|
SETICB("esil.gotolimit", RZ_ANALYSIS_ESIL_GOTO_LIMIT, &cb_gotolimit, "Maximum number of gotos per ESIL expression");
|
|
SETICB("esil.stack.depth", 256, &cb_esilstackdepth, "Number of elements that can be pushed on the esilstack");
|
|
SETI("esil.stack.size", 0xf0000, "Set stack size in ESIL VM");
|
|
SETI("esil.stack.addr", 0x100000, "Set stack address in ESIL VM");
|
|
SETPREF("esil.stack.pattern", "0", "Specify fill pattern to initialize the stack (0, w, d, i)");
|
|
SETI("esil.addr.size", 64, "Maximum address size in accessed by the ESIL VM");
|
|
SETBPREF("esil.breakoninvalid", "false", "Break esil execution when instruction is invalid");
|
|
SETI("esil.timeout", 0, "A timeout (in seconds) for when we should give up emulating");
|
|
/* asm */
|
|
// asm.os needs to be first, since other asm.* depend on it
|
|
n = NODECB("asm.os", "none", &cb_asm_os_set);
|
|
SETDESC(n, "Select operating system (kernel)");
|
|
SETOPTIONS(n, "ios", "dos", "darwin", "linux", "freebsd", "openbsd", "netbsd", "windows", "s110", "none", NULL);
|
|
SETI("asm.xrefs.fold", 5, "Maximum number of xrefs to be displayed as list (use columns above)");
|
|
SETBPREF("asm.xrefs.code", "true", "Show the code xrefs (generated by jumps instead of calls)");
|
|
SETI("asm.xrefs.max", 20, "Maximum number of xrefs to be displayed without folding");
|
|
SETCB("asm.invhex", "false", &cb_asm_invhex, "Show invalid instructions as hexadecimal numbers");
|
|
SETBPREF("asm.instr", "true", "Display the disassembled instruction");
|
|
SETBPREF("asm.meta", "true", "Display the code/data/format conversions in disasm");
|
|
SETBPREF("asm.bytes", "false", "Display the bytes of each instruction");
|
|
SETBPREF("asm.bytes.right", "false", "Display the bytes at the right of the disassembly");
|
|
SETI("asm.types", 1, "Display the fcn types in calls (0=no,1=quiet,2=verbose)");
|
|
SETBPREF("asm.midcursor", "false", "Cursor in visual disasm mode breaks the instruction");
|
|
SETBPREF("asm.cmt.flgrefs", "true", "Show comment flags associated to branch reference");
|
|
SETBPREF("asm.cmt.right", "true", "Show comments at right of disassembly if they fit in screen");
|
|
SETBPREF("asm.cmt.esil", "false", "Show ESIL expressions as comments");
|
|
SETBPREF("asm.cmt.il", "false", "Show RzIL expressions as comments");
|
|
SETI("asm.cmt.col", 71, "Column to align comments");
|
|
SETICB("asm.pcalign", 1, &cb_asm_pcalign, "Only recognize as valid instructions aligned to this value");
|
|
// maybe rename to asm.cmt.calls
|
|
SETBPREF("asm.calls", "true", "Show callee function related info as comments in disasm");
|
|
SETBPREF("asm.comments", "true", "Show comments in disassembly view");
|
|
SETBPREF("asm.usercomments", "false", "Show user comments even if asm.comments is false");
|
|
SETBPREF("asm.sub.jmp", "true", "Always substitute jump, call and branch targets in disassembly");
|
|
SETBPREF("asm.hints", "true", "Disable all asm.hint* if false");
|
|
SETBPREF("asm.hint.jmp", "false", "Show jump hints [numbers] in disasm");
|
|
SETBPREF("asm.hint.call", "true", "Show call hints [numbers] in disasm");
|
|
SETBPREF("asm.hint.call.indirect", "true", "Hints for indirect call intructions go to the call destination");
|
|
SETBPREF("asm.hint.lea", "false", "Show LEA hints [numbers] in disasm");
|
|
SETBPREF("asm.hint.emu", "false", "Show asm.emu hints [numbers] in disasm");
|
|
SETBPREF("asm.hint.cdiv", "false", "Show CDIV hints optimization hint");
|
|
SETI("asm.hint.pos", 1, "Shortcut hint position (-1, 0, 1)");
|
|
SETBPREF("asm.slow", "true", "Perform slow analysis operations in disasm");
|
|
SETBPREF("asm.decode", "false", "Use code analysis as a disassembler");
|
|
SETICB("asm.imm.hash", 0, &cb_asm_immhash, "Display # for immediates in ARM and Hexagon (0 = on)");
|
|
SETBPREF("asm.imm.str", "true", "Show immediates values as strings");
|
|
SETBPREF("asm.imm.trim", "false", "Remove all offsets and constants from disassembly");
|
|
SETBPREF("asm.indent", "false", "Indent disassembly based on reflines depth");
|
|
SETI("asm.indentspace", 2, "How many spaces to indent the code");
|
|
SETBPREF("asm.debuginfo", "false", "Show debug information in disassembly");
|
|
SETBPREF("asm.debuginfo.abspath", "false", "Show absolute path from the debug information");
|
|
SETBPREF("asm.debuginfo.file", "true", "Show file name from the debug information in disassembly");
|
|
SETBPREF("asm.debuginfo.lines", "true", "Show source line information from debug metadata in disassembly");
|
|
SETBPREF("asm.esil", "false", "Show ESIL instead of mnemonic");
|
|
SETBPREF("asm.nodup", "false", "Do not show dupped instructions (collapse disasm)");
|
|
SETBPREF("asm.emu", "false", "Run ESIL emulation analysis on disasm");
|
|
SETBPREF("emu.pre", "false", "Run ESIL emulation starting at the closest flag in pd");
|
|
SETBPREF("asm.refptr", "true", "Show refpointer information in disasm");
|
|
SETBPREF("emu.lazy", "false", "Do not emulate all instructions with aae (optimization)");
|
|
SETBPREF("emu.stack", "false", "Create a temporary fake stack when emulating in disasm (asm.emu)");
|
|
SETCB("emu.str", "false", &cb_emustr, "Show only strings if any in the asm.emu output");
|
|
SETBPREF("emu.str.lea", "true", "Disable this in ARM64 code to remove some false positives");
|
|
SETBPREF("emu.str.off", "false", "Always show offset when printing asm.emu strings");
|
|
SETBPREF("emu.str.inv", "true", "Color-invert emu.str strings");
|
|
SETBPREF("emu.str.flag", "true", "Also show flag (if any) for asm.emu string");
|
|
SETBPREF("emu.write", "false", "Allow asm.emu to modify memory (WARNING)");
|
|
SETBPREF("emu.ssa", "false", "Perform SSA checks and show the ssa reg names as comments");
|
|
n = NODECB("emu.skip", "ds", &cb_emuskip);
|
|
SETDESC(n, "Skip metadata of given types in asm.emu");
|
|
SETOPTIONS(n, "d", "c", "s", "f", "m", "h", "C", "r", NULL);
|
|
SETBPREF("asm.sub.names", "true", "Replace numeric values by flags (e.g. 0x4003e0 -> sym.imp.printf)");
|
|
SETPREF("asm.strip", "", "strip all instructions given comma separated types");
|
|
SETBPREF("asm.optype", "false", "show opcode type next to the instruction bytes");
|
|
SETBPREF("asm.lines.fcn", "true", "Show function boundary lines");
|
|
SETBPREF("asm.flags", "true", "Show flags");
|
|
SETICB("asm.flags.maxname", 0, &cb_maxname, "Maximum length of flag name with smart chopping");
|
|
SETI("asm.flags.limit", 0, "Maximum number of flags to show in a single offset");
|
|
SETBPREF("asm.flags.offset", "false", "Show offset in flags");
|
|
SETBPREF("asm.flags.inbytes", "false", "Display flags inside the bytes space");
|
|
SETBPREF("asm.flags.inline", "false", "Display flags in line separated by commas instead of newlines");
|
|
n = NODEICB("asm.flags.middle", 2, &cb_midflags);
|
|
SETOPTIONS(n, "0 = do not show flag", "1 = show without realign", "2 = realign at middle flag",
|
|
"3 = realign at middle flag if sym.*", NULL);
|
|
SETDESC(n, "Realign disassembly if there is a flag in the middle of an instruction");
|
|
SETCB("asm.flags.real", "false", &cb_flag_realnames,
|
|
"Show flags' unfiltered realnames instead of names, except realnames from demangling");
|
|
SETBPREF("asm.bb.line", "false", "Show empty line after every basic block");
|
|
SETBPREF("asm.bb.middle", "true", "Realign disassembly if a basic block starts in the middle of an instruction");
|
|
SETBPREF("asm.lbytes", "true", "Align disasm bytes to left");
|
|
SETBPREF("asm.lines", "true", "Show ASCII-art lines at disassembly");
|
|
SETBPREF("asm.lines.bb", "true", "Show flow lines at jumps");
|
|
SETBPREF("asm.lines.call", "false", "Enable call lines");
|
|
SETBPREF("asm.lines.ret", "false", "Show separator lines after ret");
|
|
SETBPREF("asm.lines.out", "true", "Show out of block lines");
|
|
SETBPREF("asm.lines.right", "false", "Show lines before opcode instead of offset");
|
|
SETBPREF("asm.lines.wide", "false", "Put a space between lines");
|
|
SETBPREF("asm.fcn.signature", "true", "Show function signature in disasm");
|
|
SETBPREF("asm.fcn.size", "false", "Show function size in disasm");
|
|
SETICB("asm.lines.width", 7, &cb_asmlineswidth, "Number of columns for program flow arrows");
|
|
SETICB("asm.sub.varmin", 0x100, &cb_asmsubvarmin, "Minimum value to substitute in instructions (asm.sub.var)");
|
|
SETCB("asm.sub.tail", "false", &cb_asmsubtail, "Replace addresses with prefix .. syntax");
|
|
SETBPREF("asm.middle", "false", "Allow disassembling jumps in the middle of an instruction");
|
|
SETBPREF("asm.noisy", "true", "Show comments considered noisy but possibly useful");
|
|
SETBPREF("asm.offset", "true", "Show offsets in disassembly");
|
|
SETBPREF("hex.offset", "true", "Show offsets in hex-dump");
|
|
SETBPREF("scr.square", "true", "Use square pixels or not");
|
|
SETCB("scr.prompt.vi", "false", &cb_scr_vi, "Use vi mode for input prompt");
|
|
SETCB("scr.prompt.mode", "false", &cb_scr_prompt_mode, "Set prompt color based on vi mode");
|
|
SETCB("scr.wideoff", "false", &cb_scr_wideoff, "Adjust offsets to match asm.bits");
|
|
SETCB("scr.last", "true", &cb_scrlast, "Cache last output after flush to make _ command work (disable for performance)");
|
|
SETBPREF("asm.reloff", "false", "Show relative offsets instead of absolute address in disasm");
|
|
SETBPREF("asm.reloff.flags", "false", "Show relative offsets to flags (not only functions)");
|
|
SETBPREF("asm.section", "false", "Show section name before offset");
|
|
SETBPREF("asm.section.perm", "false", "Show section permissions in the disasm");
|
|
SETBPREF("asm.section.name", "true", "Show section name in the disasm");
|
|
SETI("asm.section.col", 30, "Columns width to show asm.section");
|
|
SETCB("asm.sub.section", "false", &cb_asmsubsec, "Show offsets in disasm prefixed with section/map name");
|
|
SETCB("asm.pseudo", "false", &cb_asmpseudo, "Enable pseudo syntax");
|
|
SETBPREF("asm.size", "false", "Show size of opcodes in disassembly (pd)");
|
|
SETBPREF("asm.stackptr", "false", "Show stack pointer at disassembly");
|
|
SETBPREF("asm.cyclespace", "false", "Indent instructions depending on CPU-cycles");
|
|
SETBPREF("asm.cycles", "false", "Show CPU-cycles taken by instruction at disassembly");
|
|
SETI("asm.tabs", 6, "Use tabs in disassembly");
|
|
SETBPREF("asm.tabs.once", "true", "Only tabulate the opcode, not the arguments");
|
|
SETI("asm.tabs.off", 0, "tabulate spaces after the offset");
|
|
SETBPREF("asm.trace", "false", "Show execution traces for each opcode");
|
|
SETBPREF("asm.tracespace", "false", "Indent disassembly with trace.count information");
|
|
SETBPREF("asm.ucase", "false", "Use uppercase syntax at disassembly");
|
|
SETBPREF("asm.capitalize", "false", "Use camelcase at disassembly");
|
|
SETBPREF("asm.var", "true", "Show local function variables in disassembly");
|
|
SETBPREF("asm.var.access", "false", "Show accesses of local variables");
|
|
SETBPREF("asm.sub.var", "true", "Substitute variables in disassembly");
|
|
SETI("asm.var.summary", 0, "Show variables summary instead of full list in disasm (0, 1, 2)");
|
|
n = NODECB("asm.var.fold", "none", &cb_asm_varfold);
|
|
SETDESC(n, "Fold same-typed variables (support none, group, hide)");
|
|
SETOPTIONS(n, "none", "group", "hide", NULL);
|
|
SETBPREF("asm.sub.varonly", "true", "Substitute the entire variable expression with the local variable name (e.g. [local10h] instead of [ebp+local10h])");
|
|
SETBPREF("asm.sub.reg", "false", "Substitute register names with their associated role name (drp~=)");
|
|
SETBPREF("asm.sub.rel", "true", "Substitute pc relative expressions in disasm");
|
|
SETBPREF("asm.family", "false", "Show family name in disasm");
|
|
SETBPREF("asm.symbol", "false", "Show symbol+delta instead of absolute offset");
|
|
SETBPREF("asm.analysis", "false", "Analyze code and refs while disassembling (see analysis.strings)");
|
|
SETI("asm.symbol.col", 40, "Columns width to show asm.section");
|
|
SETCB("asm.assembler", "", &cb_asmassembler, "Set the plugin name to use when assembling");
|
|
SETBPREF("asm.minicols", "false", "Only show the instruction in the column disasm");
|
|
RzConfigNode *asmcpu = NODECB("asm.cpu", RZ_SYS_ARCH, &cb_asm_cpu_set);
|
|
SETDESC(asmcpu, "Set the kind of asm.arch cpu");
|
|
RzConfigNode *asmarch = NODECB("asm.arch", RZ_SYS_ARCH, &cb_asm_arch_set);
|
|
SETDESC(asmarch, "Set the arch to be used by asm");
|
|
/* we need to have both asm.arch and asm.cpu defined before updating options */
|
|
update_asmarch_options(core, asmarch);
|
|
update_asmcpu_options(core, asmcpu);
|
|
n = NODECB("asm.features", "", &cb_asm_features_set);
|
|
SETDESC(n, "Specify supported features by the target CPU");
|
|
update_asmfeatures_options(core, n);
|
|
n = NODECB("asm.platform", "", &cb_asm_platform_set);
|
|
SETDESC(n, "Specify supported platforms by the target architecture");
|
|
update_asmplatforms_options(core, n);
|
|
n = NODECB("asm.parser", RZ_SYS_ARCH ".pseudo", &cb_asm_parser_set);
|
|
SETDESC(n, "Set the asm parser to use");
|
|
update_asmparser_options(core, n);
|
|
SETCB("asm.segoff", "false", &cb_segoff, "Show segmented address in prompt (x86-16)");
|
|
SETCB("asm.decoff", "false", &cb_decoff, "Show segmented address in prompt (x86-16)");
|
|
SETICB("asm.seggrn", 4, &cb_seggrn, "Segment granularity in bits (x86-16)");
|
|
n = NODECB("asm.syntax", "intel", &cb_asmsyntax);
|
|
SETDESC(n, "Select assembly syntax");
|
|
SETOPTIONS(n, "att", "intel", "masm", "jz", "regnum", NULL);
|
|
SETI("asm.nbytes", 6, "Number of bytes for each opcode at disassembly");
|
|
SETBPREF("asm.bytes.space", "false", "Separate hexadecimal bytes with a whitespace");
|
|
#if RZ_SYS_BITS == RZ_SYS_BITS_64
|
|
SETICB("asm.bits", 64, &cb_asm_bits_set, "Word size in bits at assembler");
|
|
#else
|
|
SETICB("asm.bits", 32, &cb_asm_bits_set, "Word size in bits at assembler");
|
|
#endif
|
|
n = rz_config_node_get(cfg, "asm.bits");
|
|
update_asmbits_options(core, n);
|
|
SETBPREF("asm.functions", "true", "Show functions in disassembly");
|
|
SETBPREF("asm.xrefs", "true", "Show xrefs in disassembly");
|
|
SETBPREF("asm.describe", "false", "Show opcode description");
|
|
SETPREF("asm.highlight", "", "Highlight current line");
|
|
SETBPREF("asm.marks", "true", "Show marks before the disassembly");
|
|
SETBPREF("asm.cmt.refs", "false", "Show flag and comments from refs in disasm");
|
|
SETBPREF("asm.cmt.patch", "false", "Show patch comments in disasm");
|
|
SETBPREF("asm.cmt.off", "nodup", "Show offset comment in disasm (true, false, nodup)");
|
|
SETBPREF("asm.payloads", "false", "Show payload bytes in disasm");
|
|
|
|
/* bin */
|
|
SETPREF("bin.hashlimit", "10M", "Only compute hash when opening a file if smaller than this size");
|
|
SETCB("bin.usextr", "true", &cb_usextr, "Use extract plugins when loading files");
|
|
SETCB("bin.str.purge", "", &cb_strpurge, "Purge strings (e bin.str.purge=? provides more detail)");
|
|
SETBPREF("bin.b64str", "false", "Try to debase64 the strings");
|
|
SETBPREF("bin.show.blocks", "true", "When true, appends the block type information to the string.");
|
|
SETCB("bin.at", "false", &cb_binat, "RzBin.cur depends on RzCore.offset");
|
|
SETBPREF("bin.libs", "false", "Try to load libraries after loading main binary");
|
|
n = NODECB("bin.str.filter", "", &cb_strfilter);
|
|
SETDESC(n, "Filter strings");
|
|
SETOPTIONS(n, "a", "8", "p", "e", "u", "i", "U", "f", NULL);
|
|
SETCB("bin.filter", "true", &cb_binfilter, "Filter symbol names to fix dupped names");
|
|
SETCB("bin.force", "", &cb_binforce, "Force that rbin plugin");
|
|
SETPREF("bin.lang", "", "Language for bin.demangle");
|
|
SETCB("bin.demangle", "true", &cb_bindemangle, "Demangles all symbols parsed via RzBin");
|
|
SETBPREF("bin.demangle.libs", "false", "Show library name on demangled symbols names");
|
|
n = NODECB("bin.demangle.flags", "base", &cb_bindemangle_flags);
|
|
SETDESC(n, "Sets the flags of the parsed symbols via RzBin");
|
|
SETOPTIONS(n, "base", "simplify", "all", NULL);
|
|
SETI("bin.baddr", -1, "Base address of the binary");
|
|
SETI("bin.laddr", 0, "Base address for loading library ('*.so')");
|
|
SETCB("bin.dbginfo", "true", &cb_bindbginfo, "Load debug information at startup if available");
|
|
SETCB("bin.dbginfo.dwo_path", "", &cb_dwo_path, "Load separate debug information (DWARF) file if available");
|
|
SETCB("bin.dbginfo.debug_file_directory", "/usr/lib/debug", NULL,
|
|
"Set the directories which searches for separate debugging information files to directory");
|
|
SETCB("bin.dbginfo.debuginfod", "false", NULL,
|
|
"Load debug file from bin.dbginfo.debuginfod_urls or DEBUGINFOD_URLS environment variable");
|
|
SETCB("bin.dbginfo.debuginfod_urls", "http://debuginfod.elfutils.org/", NULL,
|
|
"Looks for debug symbols on the debuginfod servers, the value is a string of a space separated URLs");
|
|
SETBPREF("bin.relocs", "true", "Load relocs information at startup if available");
|
|
SETCB("bin.prefix", "", &cb_binprefix, "Prefix all symbols/sections/relocs with a specific string");
|
|
SETCB("bin.strings", "true", &cb_binstrings, "Load strings from rbin on startup");
|
|
SETBPREF("bin.classes", "true", "Load classes from rbin on startup");
|
|
SETCB("bin.verbose", "false", &cb_binverbose, "Show RzBin warnings when loading binaries");
|
|
SETCB("bin.hashes.default", "md5,sha1,sha256,crc32,entropy,temperature", &cb_binhashesdefault, "Select hash algorithms");
|
|
|
|
/* prj */
|
|
SETPREF("prj.file", "", "Path of the currently opened project");
|
|
SETBPREF("prj.compress", "false", "Compress the project file while saving");
|
|
|
|
/* cfg */
|
|
SETBPREF("cfg.plugins", "true", "Load plugins at startup");
|
|
SETCB("time.fmt", "%Y-%m-%d %H:%M:%S %z", &cb_cfgdatefmt, "Date format (%Y-%m-%d %H:%M:%S %z)");
|
|
SETICB("time.zone", 0, &cb_timezone, "Time zone, in hours relative to GMT: +2, -1,..");
|
|
SETCB("cfg.debug", "false", &cb_cfgdebug, "Debugger mode");
|
|
p = rz_sys_getenv("EDITOR");
|
|
#if __WINDOWS__
|
|
rz_config_set(cfg, "cfg.editor", p ? p : "notepad");
|
|
#else
|
|
rz_config_set(cfg, "cfg.editor", p ? p : "vi");
|
|
#endif
|
|
free(p);
|
|
rz_config_desc(cfg, "cfg.editor", "Select default editor program");
|
|
SETPREF("cfg.user", rz_sys_whoami(buf), "Set current username/pid");
|
|
SETCB("cfg.fortunes", "true", &cb_cfg_fortunes, "If enabled show tips at start");
|
|
SETCB("cfg.fortunes.file", "tips", &cb_cfg_fortunes_file, "Type of fortunes to show (tips, fun)");
|
|
SETBPREF("cfg.fortunes.clippy", "false", "Use 'clippy' instead of 'echo'");
|
|
SETPREF("cfg.prefixdump", "dump", "Filename prefix for automated dumps");
|
|
SETBPREF("cfg.wseek", "false", "Seek after write");
|
|
SETICB("cfg.seek.histsize", 63, NULL, "Maximum size of the seek history");
|
|
SETCB("cfg.seek.silent", "false", NULL, "When true, seek movements are not logged in seek history");
|
|
SETCB("cfg.bigendian", CFG_DEFAULT_ENDIANNESS, &cb_bigendian, "Use little (false) or big (true) endianness");
|
|
SETI("cfg.cpuaffinity", 0, "Run on cpuid");
|
|
|
|
/* log */
|
|
// RZ_LOGLEVEL / log.level
|
|
p = rz_sys_getenv("RZ_LOGLEVEL");
|
|
const char *log_level_help = "Target log level/severity ("
|
|
#if RZ_BUILD_DEBUG
|
|
"0:DEBUG, "
|
|
#endif
|
|
"1:VERBOSE, 2:INFO, 3:WARN, 4:ERROR, 5:FATAL)";
|
|
SETICB("log.level", p ? atoi(p) : RZ_DEFAULT_LOGLVL, cb_log_config_level, log_level_help);
|
|
free(p);
|
|
|
|
#if RZ_BUILD_DEBUG
|
|
// RZ_ABORTLEVEL / log.abortlevel
|
|
p = rz_sys_getenv("RZ_ABORTLEVEL");
|
|
SETICB("log.abortlevel", p ? atoi(p) : RZ_DEFAULT_LOGLVL_ABORT, cb_log_config_abortlevel, "Target log level/severity when to abort."
|
|
" (0:DEBUG, 1:VERBOSE, 2:INFO, 3:WARN, 4:ERROR, 5:FATAL)");
|
|
free(p);
|
|
#endif /* RZ_BUILD_DEBUG */
|
|
|
|
// RZ_LOGFILE / log.file
|
|
p = rz_sys_getenv("RZ_LOGFILE");
|
|
SETCB("log.file", p ? p : "", cb_log_file, "Logging output filename / path");
|
|
free(p);
|
|
|
|
// RZ_LOGSHOWSOURCES / log.show.sources
|
|
p = rz_sys_getenv("RZ_LOGSHOWSOURCES");
|
|
SETCB("log.show.sources", p ? p : "false", cb_log_config_show_sources, "Should the log output contain src info (filename:lineno)");
|
|
free(p);
|
|
|
|
// RZ_LOGCOLORS / log.colors
|
|
p = rz_sys_getenv("RZ_LOGCOLORS");
|
|
SETCB("log.colors", p ? p : "false", cb_log_config_colors, "Should the log output use colors (TODO)");
|
|
free(p);
|
|
|
|
SETCB("log.events", "false", &cb_log_events, "Remote HTTP server to sync events with");
|
|
|
|
/* diff */
|
|
n = NODECB("diff.sort", "addr", &cb_diff_sort);
|
|
SETDESC(n, "Specify function diff sorting column");
|
|
SETOPTIONS(n, "name", "namelen", "addr", "size", NULL);
|
|
SETI("diff.from", 0, "Set source diffing address for px (uses cc command)");
|
|
SETI("diff.to", 0, "Set destination diffing address for px (uses cc command)");
|
|
SETBPREF("diff.bare", "false", "Never show function names in diff output");
|
|
|
|
/* dir */
|
|
SETI("dir.depth", 10, "Maximum depth when searching recursively for files");
|
|
{
|
|
char *path = rz_path_system(core->sys_path, RZ_SDB_MAGIC);
|
|
SETPREF("dir.magic", path, "Path to rz_magic files");
|
|
free(path);
|
|
path = rz_path_system(core->sys_path, RZ_PLUGINS);
|
|
SETPREF("dir.plugins", path, "Path to plugin files to be loaded at startup");
|
|
free(path);
|
|
}
|
|
SETCB("dir.source", "", &cb_dirsrc, "Path to find source files");
|
|
SETPREF("dir.types", "/usr/include", "Default path to look for cparse type files");
|
|
SETPREF("dir.libs", "", "Specify path to find libraries to load when bin.libs=true");
|
|
p = rz_sys_getenv(RZ_SYS_HOME);
|
|
SETCB("dir.home", p ? p : "/", &cb_dirhome, "Path for the home directory");
|
|
free(p);
|
|
p = rz_sys_getenv(RZ_SYS_TMP);
|
|
SETCB("dir.tmp", p ? p : "", &cb_dirtmp, "Path of the tmp directory");
|
|
free(p);
|
|
#if __ANDROID__
|
|
SETPREF("dir.projects", "/data/data/org.rizin.rizininstaller/rizin/projects", "Default path for projects");
|
|
#else
|
|
char *projects_dir = rz_path_home_prefix(RZ_PROJECTS);
|
|
SETPREF("dir.projects", projects_dir, "Default path for projects");
|
|
free(projects_dir);
|
|
#endif
|
|
SETPREF("stack.reg", "SP", "Which register to use as stack pointer in the visual debug");
|
|
SETBPREF("stack.bytes", "true", "Show bytes instead of words in stack");
|
|
SETBPREF("stack.anotated", "false", "Show anotated hexdump in visual debug");
|
|
SETI("stack.size", 64, "Size in bytes of stack hexdump in visual debug");
|
|
SETI("stack.delta", 0, "Delta for the stack dump");
|
|
|
|
SETCB("dbg.libs", "", &cb_dbg_libs, "If set stop when loading matching libname");
|
|
SETBPREF("dbg.skipover", "false", "Make dso perform a dss (same goes for esil and visual/graph");
|
|
SETB("dbg.hwbp", false, "Use hardware instead of software breakpoints by default");
|
|
SETCB("dbg.unlibs", "", &cb_dbg_unlibs, "If set stop when unloading matching libname");
|
|
SETCB("dbg.verbose", "false", &cb_dbg_verbose, "Verbose debug output");
|
|
SETBPREF("dbg.slow", "false", "Show stack and regs in visual mode in a slow but verbose mode");
|
|
SETBPREF("dbg.funcarg", "false", "Display arguments to function call in visual mode");
|
|
|
|
SETCB("dbg.bpinmaps", "true", &cb_dbg_bpinmaps, "Activate breakpoints only if they are inside a valid map");
|
|
SETCB("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
|
#if __WINDOWS__
|
|
n = NODECB("dbg.btalgo", "default", &cb_dbg_btalgo);
|
|
#else
|
|
n = NODECB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
|
|
#endif
|
|
SETDESC(n, "Select backtrace algorithm");
|
|
SETOPTIONS(n, "default", "fuzzy", "analysis", "trace", NULL);
|
|
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
|
|
SETCB("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
|
|
SETCB("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");
|
|
SETCB("dbg.profile", "", &cb_runprofile, "Path to RzRunProfile file");
|
|
SETCB("dbg.args", "", &cb_dbg_args, "Set the args of the program to debug");
|
|
SETCB("dbg.follow.child", "false", &cb_dbg_follow_child, "Continue tracing the child process on fork. By default the parent process is traced");
|
|
SETCB("dbg.trace_continue", "true", &cb_dbg_trace_continue, "Trace every instruction between the initial PC position and the PC position at the end of continue's execution");
|
|
SETCB("dbg.create_new_console", "true", &cb_dbg_create_new_console, "Create a new console window for the debugee on debug start");
|
|
/* debug */
|
|
SETBPREF("dbg.status", "false", "Set cmd.prompt to '.dr*' or '.dr*;drd;sr PC;pi 1;shu'");
|
|
#if DEBUGGER
|
|
SETCB("dbg.backend", "native", &cb_dbgbackend, "Select the debugger backend");
|
|
#else
|
|
SETCB("dbg.backend", "esil", &cb_dbgbackend, "Select the debugger backend");
|
|
#endif
|
|
n = NODECB("dbg.bep", "loader", &cb_dbgbep);
|
|
SETDESC(n, "Break on entrypoint");
|
|
SETOPTIONS(n, "loader", "entry", "constructor", "main", NULL);
|
|
if (core->cons->rows > 30) { // HACKY
|
|
rz_config_set_i(cfg, "dbg.follow", 64);
|
|
} else {
|
|
rz_config_set_i(cfg, "dbg.follow", 32);
|
|
}
|
|
rz_config_desc(cfg, "dbg.follow", "Follow program counter when pc >= core->offset + dbg.follow");
|
|
SETBPREF("dbg.rebase", "true", "Rebase analysis/meta/comments/flags when reopening file in debugger");
|
|
rz_config_add_bool_bind(cfg, "dbg.swstep", "Force use of software steps (code analysis+breakpoint)", core_dbg_swstep_get, core_dbg_swstep_set, NULL, core);
|
|
SETBPREF("dbg.trace.inrange", "false", "While tracing, avoid following calls outside specified range");
|
|
SETBPREF("dbg.trace.libs", "true", "Trace library code too");
|
|
SETBPREF("dbg.exitkills", "true", "Kill process on exit");
|
|
SETPREF("dbg.exe.path", "", "Path to binary being debugged");
|
|
SETCB("dbg.execs", "false", &cb_dbg_execs, "Stop execution if new thread is created");
|
|
SETICB("dbg.gdb.page_size", 4096, &cb_dbg_gdb_page_size, "Page size on gdb target (useful for QEMU)");
|
|
SETICB("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out");
|
|
SETCB("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes");
|
|
|
|
SETBPREF("dbg.bpsysign", "false", "Ignore system breakpoints");
|
|
SETICB("dbg.btdepth", 128, &cb_dbgbtdepth, "Depth of backtrace");
|
|
SETCB("dbg.trace", "false", &cb_trace, "Trace program execution (see asm.trace)");
|
|
SETICB("dbg.trace.tag", 0, &cb_tracetag, "Trace tag");
|
|
|
|
/* cmd */
|
|
SETICB("cmd.depth", 10, &cb_cmddepth, "Maximum command depth");
|
|
SETPREF("cmd.bp", "", "Run when a breakpoint is hit");
|
|
SETPREF("cmd.onsyscall", "", "Run when a syscall is hit");
|
|
SETICB("cmd.hitinfo", 1, &cb_debug_hitinfo, "Show info when a tracepoint/breakpoint is hit");
|
|
SETPREF("cmd.stack", "", "Command to display the stack in visual debug mode");
|
|
SETPREF("cmd.cprompt", "", "Column visual prompt commands");
|
|
SETPREF("cmd.gprompt", "", "Graph visual prompt commands");
|
|
SETPREF("cmd.hit", "", "Command to run on every search hit.");
|
|
SETPREF("cmd.open", "", "Run when file is opened");
|
|
SETPREF("cmd.load", "", "Run when binary is loaded");
|
|
SETPREF("cmd.prompt", "", "Prompt commands");
|
|
SETCB("cmd.repeat", "false", &cb_cmdrepeat, "Empty command an alias for '..' (repeat last command)");
|
|
SETPREF("cmd.fcn.new", "", "Run when new function is analyzed");
|
|
SETPREF("cmd.fcn.delete", "", "Run when a function is deleted");
|
|
SETPREF("cmd.fcn.rename", "", "Run when a function is renamed");
|
|
SETPREF("cmd.visual", "", "Replace current print mode");
|
|
SETPREF("cmd.vprompt", "", "Visual prompt commands");
|
|
|
|
SETCB("cmd.esil.step", "", &cb_cmd_esil_step, "Command to run before performing a step in the emulator");
|
|
SETCB("cmd.esil.stepout", "", &cb_cmd_esil_step_out, "Command to run after performing a step in the emulator");
|
|
SETCB("cmd.esil.mdev", "", &cb_cmd_esil_mdev, "Command to run when memory device address is accessed");
|
|
SETCB("cmd.esil.intr", "", &cb_cmd_esil_intr, "Command to run when an esil interrupt happens");
|
|
SETCB("cmd.esil.trap", "", &cb_cmd_esil_trap, "Command to run when an esil trap happens");
|
|
SETCB("cmd.esil.todo", "", &cb_cmd_esil_todo, "Command to run when the esil instruction contains TODO");
|
|
SETCB("cmd.esil.ioer", "", &cb_cmd_esil_ioer, "Command to run when esil fails to IO (invalid read/write)");
|
|
|
|
/* hexdump */
|
|
SETCB("hex.header", "true", &cb_hex_header, "Show header in hexdump");
|
|
SETCB("hex.bytes", "true", &cb_hex_bytes, "Show bytes column in hexdump");
|
|
SETCB("hex.ascii", "true", &cb_hex_ascii, "Show ascii column in hexdump");
|
|
SETCB("hex.hdroff", "false", &cb_hex_hdroff, "Show aligned 1 byte in header instead of delta nibble");
|
|
SETCB("hex.style", "false", &cb_hex_style, "Improve the hexdump header style");
|
|
SETCB("hex.pairs", "true", &cb_hex_pairs, "Show bytes paired in 'px' hexdump");
|
|
SETCB("hex.nodot", "false", &cb_hex_nodot, "Hide the dot before printable characters in HexII mode (pxi)");
|
|
SETCB("hex.align", "false", &cb_hex_align, "Align hexdump with flag + flagsize");
|
|
SETCB("hex.section", "false", &cb_hex_section, "Show section name before the offset");
|
|
SETCB("hex.compact", "false", &cb_hexcompact, "Show smallest 16 byte col hexdump (60 columns)");
|
|
SETCB("cmd.hexcursor", "", &cb_cmd_hexcursor, "If set and cursor is enabled display given pf format string");
|
|
SETI("hex.flagsz", 0, "If non zero, overrides the flag size in pxa");
|
|
SETICB("hex.cols", 16, &cb_hexcols, "Number of columns in hexdump");
|
|
SETI("hex.depth", 5, "Maximal level of recurrence while telescoping memory");
|
|
SETBPREF("hex.onechar", "false", "Number of columns in hexdump");
|
|
SETICB("hex.stride", 0, &cb_hexstride, "Line stride in hexdump (default is 0)");
|
|
SETCB("hex.comments", "true", &cb_hexcomments, "Show comments in 'px' hexdump");
|
|
|
|
/* http */
|
|
SETBPREF("http.log", "true", "Show HTTP requests processed");
|
|
SETBPREF("http.colon", "false", "Only accept the : command");
|
|
SETPREF("http.logfile", "", "Specify a log file instead of stderr for http requests");
|
|
SETBPREF("http.cors", "false", "Enable CORS");
|
|
SETPREF("http.referer", "", "CSFR protection if set");
|
|
SETBPREF("http.dirlist", "false", "Enable directory listing");
|
|
SETPREF("http.allow", "", "Only accept clients from the comma separated IP list");
|
|
#if __WINDOWS__
|
|
rz_config_set(cfg, "http.browser", "start");
|
|
#else
|
|
if (rz_file_exists("/usr/bin/openURL")) { // iOS ericautils
|
|
rz_config_set(cfg, "http.browser", "/usr/bin/openURL");
|
|
} else if (rz_file_exists("/system/bin/toolbox")) {
|
|
rz_config_set(cfg, "http.browser",
|
|
"LD_LIBRARY_PATH=/system/lib am start -a android.intent.action.VIEW -d");
|
|
} else if (rz_file_exists("/usr/bin/xdg-open")) {
|
|
rz_config_set(cfg, "http.browser", "xdg-open");
|
|
} else if (rz_file_exists("/usr/bin/open")) {
|
|
rz_config_set(cfg, "http.browser", "open");
|
|
} else {
|
|
rz_config_set(cfg, "http.browser", "firefox");
|
|
}
|
|
rz_config_desc(cfg, "http.browser", "Command to open HTTP URLs");
|
|
#endif
|
|
SETI("http.maxsize", 0, "Maximum file size for upload");
|
|
SETPREF("http.index", "index.html", "Main html file to check in directory");
|
|
SETPREF("http.bind", "localhost", "Server address");
|
|
char *wwwroot_dir = rz_path_home_prefix(RZ_WWWROOT);
|
|
SETPREF("http.homeroot", wwwroot_dir, "http home root directory");
|
|
free(wwwroot_dir);
|
|
#if __ANDROID__
|
|
SETPREF("http.root", "/data/data/org.rizin.rizininstaller/www", "http root directory");
|
|
#else
|
|
char *wwwroot = rz_path_system(core->sys_path, RZ_WWWROOT);
|
|
SETPREF("http.root", wwwroot, "http root directory");
|
|
free(wwwroot);
|
|
#endif
|
|
SETPREF("http.port", "9090", "HTTP server port");
|
|
SETI("http.timeout", 3, "Disconnect clients after N seconds of inactivity");
|
|
SETI("http.stop.after", 0, "Stops the http server after N seconds if there are no client connected");
|
|
SETBPREF("http.verbose", "false", "Output server logs to stdout");
|
|
SETBPREF("http.upget", "false", "/up/ answers GET requests, in addition to POST");
|
|
SETBPREF("http.upload", "false", "Enable file uploads to /up/<filename>");
|
|
SETPREF("http.uri", "", "Address of HTTP proxy");
|
|
SETBPREF("http.auth", "false", "Enable/Disable HTTP Authentification");
|
|
p = rz_sys_getenv("RZ_HTTP_AUTHFILE");
|
|
SETPREF("http.authfile", p ? p : "", "HTTP Authentification user file");
|
|
tmpdir = rz_file_tmpdir();
|
|
rz_config_set(cfg, "http.uproot", tmpdir);
|
|
free(tmpdir);
|
|
rz_config_desc(cfg, "http.uproot", "Path where files are uploaded");
|
|
|
|
/* tcp */
|
|
SETBPREF("tcp.islocal", "false", "Bind a loopback for tcp command server");
|
|
|
|
/* graph */
|
|
SETBPREF("graph.aeab", "false", "Show aeab info on each basic block instead of disasm");
|
|
SETBPREF("graph.trace", "false", "Fold all non-traced basic blocks");
|
|
SETBPREF("graph.dummy", "true", "Create dummy nodes in the graph for better layout (20% slower)");
|
|
SETBPREF("graph.few", "false", "Show few basic blocks in the graph");
|
|
SETBPREF("graph.comments", "true", "Show disasm comments in graph");
|
|
SETBPREF("graph.cmtright", "false", "Show comments at right");
|
|
SETCB("graph.gv.format", "gif", &cb_graphformat, "Graph image extension when using 'w' format (png, jpg, pdf, ps, svg, json)");
|
|
SETBPREF("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)");
|
|
SETBPREF("graph.json.usenames", "true", "Use names instead of addresses in Global Call Graph (agCj)");
|
|
SETI("graph.edges", 2, "0=no edges, 1=simple edges, 2=avoid collisions");
|
|
SETI("graph.layout", 0, "Graph layout (0=vertical, 1=horizontal)");
|
|
SETI("graph.linemode", 1, "Graph edges (0=diagonal, 1=square)");
|
|
SETPREF("graph.font", "Courier", "Font for dot graphs");
|
|
SETBPREF("graph.bytes", "false", "Show opcode bytes in graphs");
|
|
SETI("graph.from", UT64_MAX, "Lower bound address when drawing global graphs");
|
|
SETI("graph.to", UT64_MAX, "Upper bound address when drawing global graphs");
|
|
SETI("graph.scroll", 5, "Scroll speed in ascii-art graph");
|
|
SETBPREF("graph.invscroll", "false", "Invert scroll direction in ascii-art graph");
|
|
SETPREF("graph.title", "", "Title of the graph");
|
|
SETBPREF("graph.body", "true", "Show body of the nodes in the graph");
|
|
SETBPREF("graph.ntitles", "true", "Display title of node");
|
|
SETPREF("graph.gv.node", "", "Graphviz node style. (color=gray, style=filled shape=box)");
|
|
SETPREF("graph.gv.edge", "", "Graphviz edge style. (arrowhead=\"vee\")");
|
|
SETPREF("graph.gv.spline", "", "Graphviz spline style. (splines=\"ortho\")");
|
|
SETPREF("graph.gv.graph", "", "Graphviz global style attributes. (bgcolor=white)");
|
|
SETPREF("graph.gv.current", "false", "Highlight the current node in graphviz graph.");
|
|
SETBPREF("graph.nodejmps", "true", "Enables shortcuts for every node.");
|
|
SETBPREF("graph.hints", "true", "Show true (t) and false (f) hints for conditional edges in graph");
|
|
SETCB("graph.dotted", "false", &cb_dotted, "Dotted lines for conditional jumps in graph");
|
|
|
|
/* hud */
|
|
SETPREF("hud.path", "", "Set a custom path for the HUD file");
|
|
|
|
SETCB("esil.exectrap", "false", &cb_exectrap, "trap when executing code in non-executable memory");
|
|
SETCB("esil.iotrap", "true", &cb_iotrap, "invalid read or writes produce a trap exception");
|
|
SETBPREF("esil.romem", "false", "Set memory as read-only for ESIL");
|
|
SETBPREF("esil.stats", "false", "Statistics from ESIL emulation stored in sdb");
|
|
SETBPREF("esil.nonull", "false", "Prevent memory read, memory write at null pointer");
|
|
SETCB("esil.mdev.range", "", &cb_mdevrange, "Specify a range of memory to be handled by cmd.esil.mdev");
|
|
|
|
/* scr */
|
|
#if __EMSCRIPTEN__
|
|
rz_config_set_cb(cfg, "scr.fgets", "true", cb_scrfgets);
|
|
#else
|
|
rz_config_set_cb(cfg, "scr.fgets", "false", cb_scrfgets);
|
|
#endif
|
|
rz_config_desc(cfg, "scr.fgets", "Use fgets() instead of dietline for prompt input");
|
|
SETCB("scr.echo", "false", &cb_screcho, "Show rcons output in realtime to stderr and buffer");
|
|
SETICB("scr.linesleep", 0, &cb_scrlinesleep, "Flush sleeping some ms in every line");
|
|
SETICB("scr.maxtab", 4096, &cb_completion_maxtab, "Change max number of auto completion suggestions");
|
|
SETICB("scr.pagesize", 1, &cb_scrpagesize, "Flush in pages when scr.linesleep is != 0");
|
|
SETCB("scr.flush", "false", &cb_scrflush, "Force flush to console in realtime (breaks scripting)");
|
|
SETBPREF("scr.slow", "true", "Do slow stuff on visual mode like RzFlag.get_at(true)");
|
|
SETCB("scr.prompt.popup", "false", &cb_scr_prompt_popup, "Show widget dropdown for autocomplete");
|
|
#if __WINDOWS__
|
|
SETICB("scr.vtmode", rz_cons_singleton()->vtmode,
|
|
&scr_vtmode, "Use VT sequences on Windows (0: Disable, 1: Output, 2: Input & Output)");
|
|
#endif
|
|
#if __ANDROID__
|
|
SETBPREF("scr.responsive", "true", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
|
|
SETI("scr.wheel.speed", 1, "Mouse wheel speed");
|
|
#else
|
|
SETBPREF("scr.responsive", "false", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
|
|
SETI("scr.wheel.speed", 4, "Mouse wheel speed");
|
|
#endif
|
|
SETBPREF("scr.wheel.nkey", "false", "Use sn/sp and scr.nkey on wheel instead of scroll");
|
|
SETBPREF("scr.pf.short", "false", "Render pf offsets as +<delta> from the format base instead of absolute addresses");
|
|
// RENAME TO scr.mouse
|
|
SETBPREF("scr.wheel", "true", "Mouse wheel in Visual; temporaryly disable/reenable by right click/Enter)");
|
|
SETPREF("scr.layout", "", "Name of the selected layout");
|
|
// DEPRECATED: USES hex.cols now SETI ("scr.colpos", 80, "Column position of cmd.cprompt in visual");
|
|
SETCB("scr.breakword", "", &cb_scrbreakword, "Emulate console break (^C) when a word is printed (useful for pD)");
|
|
SETCB("scr.breaklines", "false", &cb_breaklines, "Break lines in Visual instead of truncating them");
|
|
SETCB("scr.gadgets", "true", &cb_scr_gadgets, "Run pg in prompt, visual and panels");
|
|
SETBPREF("scr.panelborder", "false", "Specify panels border active area (0 by default)");
|
|
SETICB("scr.columns", 0, &cb_scrcolumns, "Force console column count (width)");
|
|
SETBPREF("scr.dumpcols", "false", "Prefer pC commands before p ones");
|
|
SETICB("scr.rows", 0, &cb_rows, "Force console row count (height)");
|
|
SETICB("scr.fix.rows", 0, &cb_fixrows, "Workaround for Linux TTY");
|
|
SETICB("scr.fix.columns", 0, &cb_fixcolumns, "Workaround for Prompt iOS SSH client");
|
|
SETCB("scr.highlight", "", &cb_scrhighlight, "Highlight that word at RzCons level");
|
|
SETCB("scr.interactive", "true", &cb_scrint, "Start in interactive mode");
|
|
SETCB("scr.bgfill", "false", &cb_scr_bgfill, "Fill background for ascii art when possible");
|
|
SETI("scr.feedback", 1, "Set visual feedback level (1=arrow on jump, 2=every key (useful for videos))");
|
|
SETCB("scr.html", "false", &cb_scrhtml, "Disassembly uses HTML syntax");
|
|
n = NODECB("scr.nkey", "flag", &cb_scrnkey);
|
|
SETDESC(n, "Select visual seek mode (affects n/N visual commands)");
|
|
SETOPTIONS(n, "fun", "hit", "flag", NULL);
|
|
SETCB("scr.pager", "", &cb_pager, "System program (or '..') to use when output exceeds screen boundaries");
|
|
SETI("scr.scrollbar", 0, "Show flagzone (fz) scrollbar in visual mode (0=no,1=right,2=top,3=bottom)");
|
|
SETBPREF("scr.randpal", "false", "Random color palete or just get the next one from 'eco'");
|
|
SETCB("scr.highlight.grep", "false", &cb_scr_color_grep_highlight, "Highlight (INVERT) the grepped words");
|
|
SETBPREF("scr.prompt.file", "false", "Show user prompt file (used by rizin -q)");
|
|
SETBPREF("scr.prompt.flag", "false", "Show flag name in the prompt");
|
|
SETBPREF("scr.prompt.flag.only", "false", "Show the flag name only in the prompt");
|
|
SETBPREF("scr.prompt.sect", "false", "Show section name in the prompt");
|
|
SETCB("scr.hist.block", "true", &cb_scr_histblock, "Use blocks for histogram");
|
|
SETBPREF("scr.hist.ruler", "true", "Show histogram ruler");
|
|
SETBPREF("scr.hist.minimap", "true", "Show top minimap on visual histogram (p==v); auto-hides when data fits the screen");
|
|
SETI("scr.hist.width", 0, "Default width (in screen columns) of the horizontal histogram. 0 = auto-clamp to terminal width");
|
|
SETI("scr.hist.height", 0, "Default height (in screen rows) of the horizontal histogram. 0 = auto-clamp to terminal height");
|
|
SETCB("scr.prompt", "true", &cb_scrprompt, "Show user prompt (used by rizin -q)");
|
|
SETCB("scr.tee", "", &cb_teefile, "Pipe output to file of this name");
|
|
SETPREF("scr.seek", "", "Seek to the specified address on startup");
|
|
|
|
rz_config_add_integer_bind(cfg, "scr.color", "Enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)", core_scr_color_get, core_scr_color_set, NULL, core);
|
|
rz_config_set_i(cfg, "scr.color", (core->print->flags & RZ_PRINT_FLAGS_COLOR) ? COLOR_MODE_16 : COLOR_MODE_DISABLED);
|
|
|
|
SETCB("scr.color.grep", "false", &cb_scr_color_grep, "Enable colors when using ~grep");
|
|
SETBPREF("scr.color.pipe", "false", "Enable colors when using pipes");
|
|
SETBPREF("scr.color.ops", "true", "Colorize numbers and registers in opcodes");
|
|
SETBPREF("scr.color.args", "true", "Colorize arguments and variables of functions");
|
|
SETBPREF("scr.color.bytes", "true", "Colorize bytes that represent the opcodes of the instruction");
|
|
SETCB("scr.null", "false", &cb_scrnull, "Show no output");
|
|
SETCB("scr.utf8", rz_str_bool(rz_cons_is_utf8()), &cb_utf8, "Show UTF-8 characters instead of ANSI");
|
|
SETCB("scr.utf8.curvy", "false", &cb_utf8_curvy, "Show curved UTF-8 corners (requires scr.utf8)");
|
|
SETBPREF("scr.histsave", "true", "Always save history on exit");
|
|
n = NODECB("scr.strconv", "asciiesc", &cb_scrstrconv);
|
|
SETDESC(n, "Convert string before display. asciiesc = Escape non-printable ASCII characters. asciidot = Replace non-printable ASCII characters with '.'.");
|
|
SETOPTIONS(n, "asciiesc", "asciidot", NULL);
|
|
SETBPREF("scr.confirmquit", "false", "Confirm on quit");
|
|
SETICB("scr.visual.mode", RZ_CORE_VISUAL_MODE_PX, &cb_visual_mode, "Visual mode (0: hexdump, 1: disassembly, 2: debug, 3: color blocks, 4: strings)");
|
|
|
|
/* str */
|
|
SETCB("str.escbslash", "false", &cb_str_escbslash, "Escape the backslash.");
|
|
n = NODECB("str.encoding", "guess", &cb_str_encoding);
|
|
SETDESC(n, "The default string encoding type (when set to guess, it is automatically guessed).");
|
|
SETOPTIONS(n, "ascii", "8bit", "utf8", "utf16le", "utf32le", "utf16be", "utf32be", "ibm037", "ibm290", "ebcdices", "ebcdicuk", "ebcdicus", "guess", NULL);
|
|
SETCB("str.unprintable", "", &cb_str_unprintable, "Comma-separated hex code points treated as non-printable.");
|
|
|
|
/* string search options */
|
|
SETB("str.search.reload", true, "When enabled, any change to any option `str.search.*` will reload the bin strings.");
|
|
n = NODECB("str.search.mode", "auto", &cb_str_search_mode);
|
|
SETDESC(n, "String search mode which can override how strings are found (auto, rosections or raw)");
|
|
SETOPTIONS(n, "auto", "rosections", "raw", NULL);
|
|
|
|
/* search */
|
|
SETCB("search.contiguous", "true", &cb_contiguous, "Accept contiguous/adjacent search hits");
|
|
SETICB("search.align", 1, &cb_searchalign, "Only catch aligned search hits");
|
|
SETI("search.chunk", 0, "Chunk size for /+ (default size is asm.bits/8)");
|
|
SETI("search.esilcombo", 8, "Stop search after N consecutive hits");
|
|
SETI("search.distance", 0, "Search string distance");
|
|
SETBPREF("search.flags", "true", "All search results are flagged, otherwise only printed");
|
|
SETBPREF("search.overlap", "false", "Look for overlapped search hits");
|
|
SETI("search.maxhits", 0, "Maximum number of hits (0: no limit)");
|
|
SETICB("search.max_threads", RZ_THREAD_N_CORES_ALL_AVAILABLE, &cb_search_max_threads, "Maximum core number. '0' for all cores. '?' to show available.");
|
|
// Order matters for these. cb_search_to() checks if search.from is smaller or equal.
|
|
// Because those two are commonly used in calculations.
|
|
SETI("search.from", 0, "Search start address (inclusive)");
|
|
SETICB("search.to", UT64_MAX, &cb_search_to, "Search end address (exclusive)");
|
|
// Order end
|
|
n = NODECB("search.in", "io.maps", &cb_search_in);
|
|
SETDESC(n, "Specify search boundaries");
|
|
SETOPTIONS(n, "raw", "block",
|
|
"bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
|
|
"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
|
|
"dbg.stack", "dbg.heap",
|
|
"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
|
|
"analysis.fcn", "analysis.bb",
|
|
NULL);
|
|
SETPREF("search.prefix", "hit", "Prefix name in search hits label");
|
|
SETI("search.maxhits", 0, "Maximum number of hits ('0' means no limit)");
|
|
n = NODECB("search.show_progress", "num_hits", &cb_search_show_progress);
|
|
SETDESC(n, "Show the search process (false, num_hits, intervals)");
|
|
SETOPTIONS(n, "false", "num_hits", "intervals", NULL);
|
|
SETICB("search.str.min_length", RZ_BIN_STRING_SEARCH_MIN_STRING, &cb_search_str_min_length, "Smallest string length (in number of characters).");
|
|
SETICB("search.str.max_length", RZ_BIN_STRING_SEARCH_BUFFER_SIZE, &cb_search_str_max_length, "Maximum string length (in number of characters).");
|
|
SETICB("search.str.max_region_size", RZ_BIN_STRING_SEARCH_MAX_REGION_SIZE, &cb_search_str_max_region_size, "Maximum allowable size for the string search interval between two memory regions.");
|
|
SETICB("search.str.raw_alignment", RZ_BIN_STRING_SEARCH_RAW_FILE_ALIGNMENT, &cb_search_str_raw_alignment, "Memory search interval alignment used for the raw string search (RzBin only. Use search.align for /z).");
|
|
SETICB("search.str.check_ascii_freq", RZ_BIN_STRING_SEARCH_CHECK_ASCII_FREQ, &cb_search_str_check_ascii_freq, "If true, perform check on ASCII frequencies when looking for false positives during string search");
|
|
|
|
SETICB("search.align", 1, &cb_searchalign, "Address alignment (searches only if 'address % search.align == 0').");
|
|
SETI("search.esilcombo", 8, "Stop search after N consecutive hits");
|
|
SETI("search.distance", 0, "Search string distance");
|
|
SETBPREF("search.flags", "true", "All search results are flagged, otherwise only printed");
|
|
SETICB("search.kwidx", 0, &cb_search_kwidx, "Store last search index count");
|
|
SETBPREF("search.show", "true", "Show search results");
|
|
n = NODECB("search.case_sensitive", "smart", &cb_search_case_sensitive);
|
|
SETDESC(n, "Set grep(~) as case smart/sensitive/insensitive");
|
|
SETOPTIONS(n, "smart", "sensitive", "insensitive", NULL);
|
|
|
|
/* gadget */
|
|
SETI("gadget.len", 5, "Maximum number of instructions per gadget");
|
|
SETBPREF("gadget.cache", "true", "Cache gadget search results");
|
|
SETBPREF("gadget.subchains", "false", "Display every length gadget from gadget.len=X to 2");
|
|
SETBPREF("gadget.conditional", "false", "Include conditional jump, calls and returns in gadget search");
|
|
SETBPREF("gadget.comments", "false", "Display comments in gadget search output");
|
|
|
|
/* io */
|
|
SETCB("io.cache", "false", &cb_io_cache, "Change both of io.cache.{read,write}");
|
|
SETCB("io.cache.auto", "false", &cb_io_cache_mode, "Automatic cache all reads in the IO backend");
|
|
SETCB("io.cache.read", "false", &cb_io_cache_read, "Enable read cache for vaddr (or paddr when io.va=0)");
|
|
SETCB("io.cache.write", "false", &cb_io_cache_write, "Enable write cache for vaddr (or paddr when io.va=0)");
|
|
SETCB("io.pcache", "false", &cb_iopcache, "io.cache for p-level");
|
|
SETCB("io.pcache.write", "false", &cb_iopcachewrite, "Enable write-cache");
|
|
SETCB("io.pcache.read", "false", &cb_iopcacheread, "Enable read-cache");
|
|
SETCB("io.ff", "true", &cb_ioff, "Fill invalid buffers with 0xff instead of returning error");
|
|
SETBPREF("io.exec", "true", "See !!rizin -h~-x");
|
|
SETICB("io.0xff", 0xff, &cb_io_oxff, "Use this value instead of 0xff to fill unallocated areas");
|
|
SETCB("io.aslr", "false", &cb_ioaslr, "Disable ASLR for spawn and such");
|
|
SETCB("io.va", "true", &cb_iova, "Use virtual address layout");
|
|
SETCB("io.pava", "false", &cb_io_pava, "Use EXPERIMENTAL paddr -> vaddr address mode");
|
|
SETCB("io.autofd", "true", &cb_ioautofd, "Change fd when opening a new file");
|
|
SETCB("io.unalloc", "false", &cb_io_unalloc, "Check each byte if it's allocated");
|
|
SETCB("io.unalloc.ch", ".", &cb_io_unalloc_ch, "Char to display if byte is unallocated");
|
|
|
|
/* file */
|
|
SETBPREF("file.info", "true", "RzBin info loaded");
|
|
SETPREF("file.offset", "", "Offset where the file will be mapped at");
|
|
SETCB("file.path", "", &cb_filepath, "Path of current file");
|
|
SETPREF("file.lastpath", "", "Path of current file");
|
|
SETPREF("file.type", "", "Type of current file");
|
|
SETI("file.loadalign", 1024, "Alignment of load addresses");
|
|
SETI("file.openmany", 1, "Maximum number of files opened at once");
|
|
/* magic */
|
|
SETI("magic.depth", 100, "Recursivity depth in magic description strings");
|
|
|
|
/* rap */
|
|
SETBPREF("rap.loop", "true", "Run rap as a forever-listening daemon (=:9090)");
|
|
|
|
/* basefind */
|
|
SETB("basefind.progress", false, "Basefind threads progress (true: enable, false: disable)");
|
|
SETI("basefind.search.start", RZ_BASEFIND_BASE_MIN_ADDRESS, "Basefind start search address");
|
|
SETI("basefind.search.end", RZ_BASEFIND_BASE_MAX_ADDRESS, "Basefind end search address");
|
|
SETI("basefind.alignment", RZ_BASEFIND_BASE_ALIGNMENT, "Basefind alignment in bytes");
|
|
SETI("basefind.min.score", RZ_BASEFIND_SCORE_MIN_VALUE, "Basefind min score value to consider it valid");
|
|
SETI("basefind.min.string", RZ_BASEFIND_STRING_MIN_LENGTH, "Basefind min string size to find to consider it valid");
|
|
SETI("basefind.max.threads", RZ_THREAD_N_CORES_ALL_AVAILABLE, "Basefind max threads number (when 0 uses all available cores)");
|
|
|
|
/* nkeys */
|
|
SETPREF("key.s", "", "override step into action");
|
|
SETPREF("key.S", "", "override step over action");
|
|
for (i = 1; i < 13; i++) {
|
|
snprintf(buf, sizeof(buf), "key.f%d", i);
|
|
snprintf(buf + 10, sizeof(buf) - 10,
|
|
"Run this when F%d key is pressed in visual mode", i);
|
|
switch (i) {
|
|
default: p = ""; break;
|
|
}
|
|
rz_config_set(cfg, buf, p);
|
|
rz_config_desc(cfg, buf, buf + 10);
|
|
}
|
|
|
|
/* zoom */
|
|
SETCB("zoom.byte", "h", &cb_zoombyte, "Zoom callback to calculate each byte (See pz? for help)");
|
|
SETI("zoom.from", 0, "Zoom start address");
|
|
SETI("zoom.maxsz", 512, "Zoom max size of block");
|
|
SETI("zoom.to", 0, "Zoom end address");
|
|
n = NODECB("zoom.in", "io.map", &cb_zoom_in);
|
|
SETDESC(n, "Specify boundaries for zoom");
|
|
SETOPTIONS(n, "raw", "block",
|
|
"bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
|
|
"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
|
|
"dbg.stack", "dbg.heap",
|
|
"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
|
|
"analysis.fcn", "analysis.bb",
|
|
NULL);
|
|
|
|
/* RzIL config */
|
|
SETB("rzil.step.events.read", false, "enables/disables printing aezse read event");
|
|
SETB("rzil.step.events.write", true, "enables/disables printing aezse write event");
|
|
n = NODECB("rzil.step.events.halt_on_exc", "div0,fp_invalid_op", &rzil_halt_on_exec);
|
|
SETDESC(n, "Enables/disable exceptions the VM should halt if reached.");
|
|
SETOPTIONS(n, "div0", "fp_div0", "fp_inexact", "fp_underflow", "fp_overflow", "fp_invalid_op", "none", "all", NULL);
|
|
|
|
/* FLIRT config */
|
|
SETBPREF("flirt.sig.library", RZ_FLIRT_LIBRARY_NAME_DFL, "FLIRT library name for sig format");
|
|
SETI("flirt.sig.version", 10, "FLIRT version for sig format");
|
|
n = NODECB("flirt.sig.file", "all", &cb_flirt);
|
|
SETDESC(n, "FLIRT file list (comma separated) for sig format");
|
|
SETOPTIONS(n, "msdos", "win", "os2", "netware", "unix", "other", "all", "none", NULL);
|
|
n = NODECB("flirt.sig.os", "all", &cb_flirt);
|
|
SETDESC(n, "FLIRT operating system list (comma separated) for sig format");
|
|
SETOPTIONS(n,
|
|
"aixar", "aout", "ar", "bin", "coff", "dos:com", "dos:com:old", "dos:exe", "dos:exe:old",
|
|
"dosdrv", "elf", "intelhex", "le", "loader", "lx", "moshex", "ne", "nlm", "omf", "omflib",
|
|
"pe", "pilot", "srec", "w32run", "zip", "all", "none", NULL);
|
|
SETB("flirt.sig.deflate", false, "Enables/disables FLIRT zlib compression when creating a signature file (available only for .sig files)");
|
|
SETI("flirt.node.optimize", RZ_FLIRT_NODE_OPTIMIZE_MAX, "FLIRT optimization option when creating a signature file (none: 0, normal: 1, smallest: 2)");
|
|
SETB("flirt.ignore.unknown", true, "When enabled, on FLIRT creation it will ignore any function starting with `fcn.`");
|
|
SETPREF("flirt.sigdb.path", "", "Additional user defined rizin sigdb location to load on the filesystem.");
|
|
SETB("flirt.sigdb.load.system", true, "Load signatures from the system path");
|
|
SETB("flirt.sigdb.load.extra", true, "Load signatures from the extra path");
|
|
SETB("flirt.sigdb.load.home", true, "Load signatures from the home path");
|
|
|
|
return true;
|
|
}
|
|
|
|
RZ_API void rz_core_parse_rizinrc(RzCore *r) {
|
|
bool has_debug = rz_sys_getenv_asbool("RZ_DEBUG");
|
|
char *rcfile = rz_sys_getenv("RZ_RCFILE");
|
|
char *homerc = NULL;
|
|
if (!RZ_STR_ISEMPTY(rcfile)) {
|
|
homerc = rcfile;
|
|
} else {
|
|
free(rcfile);
|
|
homerc = rz_path_home_rc();
|
|
}
|
|
if (homerc && rz_file_is_regular(homerc)) {
|
|
if (has_debug) {
|
|
RZ_LOG_INFO("USER CONFIG loaded from %s\n", homerc);
|
|
}
|
|
rz_core_cmd_file(r, homerc);
|
|
}
|
|
free(homerc);
|
|
homerc = rz_path_home_config_rc();
|
|
if (homerc && rz_file_is_regular(homerc)) {
|
|
if (has_debug) {
|
|
RZ_LOG_INFO("USER CONFIG loaded from %s\n", homerc);
|
|
}
|
|
rz_core_cmd_file(r, homerc);
|
|
}
|
|
free(homerc);
|
|
homerc = rz_path_home_config_rcdir();
|
|
if (homerc) {
|
|
if (rz_file_is_directory(homerc)) {
|
|
char *file;
|
|
RzListIter *iter;
|
|
RzList *files = rz_sys_dir(homerc);
|
|
rz_list_foreach (files, iter, file) {
|
|
if (*file != '.') {
|
|
char *path = rz_str_newf("%s/%s", homerc, file);
|
|
if (rz_file_is_regular(path)) {
|
|
if (has_debug) {
|
|
RZ_LOG_INFO("USER CONFIG loaded from %s\n", homerc);
|
|
}
|
|
rz_core_cmd_file(r, path);
|
|
}
|
|
free(path);
|
|
}
|
|
}
|
|
rz_list_free(files);
|
|
}
|
|
free(homerc);
|
|
}
|
|
}
|
|
|
|
typedef struct cconfig_space_s {
|
|
RzList /*<char *>*/ *list;
|
|
const char *space;
|
|
} cconfig_space_t;
|
|
|
|
static bool core_config_in_space(const RzConfigEntry *entry, void *user) {
|
|
cconfig_space_t *ctx = user;
|
|
const char *e_name = rz_config_entry_get_name(entry);
|
|
|
|
char *name = rz_str_dup(e_name);
|
|
if (!name) {
|
|
return false;
|
|
}
|
|
|
|
char *dot = strchr(name, '.');
|
|
if (dot) {
|
|
*dot = 0;
|
|
}
|
|
|
|
if (RZ_STR_ISNOTEMPTY(ctx->space)) {
|
|
if (0 == strcmp(name, ctx->space) && dot && !rz_list_find(ctx->list, dot + 1, (RzListComparator)strcmp, NULL)) {
|
|
rz_list_append(ctx->list, rz_str_dup(dot + 1));
|
|
}
|
|
} else {
|
|
if (!rz_list_find(ctx->list, name, (RzListComparator)strcmp, NULL)) {
|
|
rz_list_append(ctx->list, rz_str_dup(name));
|
|
}
|
|
}
|
|
free(name);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Get config variable spaces
|
|
* \param core The RzCore instance
|
|
* \param space The config space
|
|
* \return RzList of config variable spaces
|
|
*/
|
|
RZ_API RZ_OWN RzList /*<char *>*/ *rz_core_config_in_space(RZ_NONNULL RzCore *core, RZ_NULLABLE const char *space) {
|
|
rz_return_val_if_fail(core && core->config, NULL);
|
|
RzList *list = rz_list_new();
|
|
if (!list) {
|
|
return NULL;
|
|
}
|
|
|
|
cconfig_space_t ctx = { list, space };
|
|
rz_config_iterate_over(core->config, core_config_in_space, &ctx);
|
|
|
|
return list;
|
|
}
|