1 /* radare - LGPL - Copyright 2009-2021 - pancake */
2
3 #include <r_core.h>
4 #include <r_types_base.h>
5
6 #define NODECB(w,x,y) r_config_set_cb (cfg,w,x,y)
7 #define NODEICB(w,x,y) r_config_set_i_cb (cfg,w,x,y)
8 #define SETDESC(x,y) r_config_node_desc (x,y)
9 #define SETOPTIONS(x, ...) set_options (x, __VA_ARGS__)
10 #define SETI(x,y,z) SETDESC (r_config_set_i (cfg,x,y), z)
11 #define SETICB(w,x,y,z) SETDESC (NODEICB (w,x,y), z)
12 #define SETPREF(x,y,z) SETDESC (r_config_set (cfg,x,y), z)
13 #define SETCB(w,x,y,z) SETDESC (NODECB (w,x,y), z)
14 #define SETBPREF(x,y,z) SETDESC (NODECB (x,y,boolify_var_cb), z)
15
boolify_var_cb(void * user,void * data)16 static bool boolify_var_cb(void *user, void *data) {
17 RConfigNode *node = (RConfigNode *) data;
18 if (node->i_value || r_str_is_false (node->value)) {
19 free (node->value);
20 node->value = strdup (r_str_bool (node->i_value));
21 }
22 return true;
23 }
24
set_options(RConfigNode * node,...)25 static void set_options(RConfigNode *node, ...) {
26 va_list argp;
27 char *option = NULL;
28 va_start (argp, node);
29 option = va_arg (argp, char *);
30 while (option) {
31 r_config_node_add_option (node, option);
32 option = va_arg (argp, char *);
33 }
34 va_end (argp);
35 }
36
isGdbPlugin(RCore * core)37 static bool isGdbPlugin(RCore *core) {
38 if (core->io && core->io->desc && core->io->desc->plugin) {
39 if (core->io->desc->plugin->name && !strcmp (core->io->desc->plugin->name, "gdb")) {
40 return true;
41 }
42 }
43 return false;
44 }
45
print_node_options(RConfigNode * node)46 static void print_node_options(RConfigNode *node) {
47 if (node->options) {
48 RListIter *iter;
49 char *option;
50 r_list_foreach (node->options, iter, option) {
51 r_cons_printf ("%s\n", option);
52 }
53 }
54 }
55
compareName(const RAnalFunction * a,const RAnalFunction * b)56 static int compareName(const RAnalFunction *a, const RAnalFunction *b) {
57 return (a && b && a->name && b->name ? strcmp (a->name, b->name) : 0);
58 }
59
compareNameLen(const RAnalFunction * a,const RAnalFunction * b)60 static int compareNameLen(const RAnalFunction *a, const RAnalFunction *b) {
61 size_t la, lb;
62 if (!a || !b || !a->name || !b->name) {
63 return 0;
64 }
65 la = strlen (a->name);
66 lb = strlen (a->name);
67 return (la > lb) - (la < lb);
68 }
69
compareAddress(const RAnalFunction * a,const RAnalFunction * b)70 static int compareAddress(const RAnalFunction *a, const RAnalFunction *b) {
71 return (a && b && a->addr && b->addr ? (a->addr > b->addr) - (a->addr < b->addr) : 0);
72 }
73
compareType(const RAnalFunction * a,const RAnalFunction * b)74 static int compareType(const RAnalFunction *a, const RAnalFunction *b) {
75 return (a && b && a->diff->type && b->diff->type ?
76 (a->diff->type > b->diff->type) - (a->diff->type < b->diff->type) : 0);
77 }
78
compareSize(const RAnalFunction * a,const RAnalFunction * b)79 static int compareSize(const RAnalFunction *a, const RAnalFunction *b) {
80 ut64 sa, sb;
81 // return a && b && a->_size < b->_size;
82 if (!a || !b) {
83 return 0;
84 }
85 sa = r_anal_function_realsize (a);
86 sb = r_anal_function_realsize (b);
87 return (sa > sb) - (sa < sb);
88 }
89
compareDist(const RAnalFunction * a,const RAnalFunction * b)90 static int compareDist(const RAnalFunction *a, const RAnalFunction *b) {
91 return (a && b && a->diff->dist && b->diff->dist ?
92 (a->diff->dist > b->diff->dist) - (a->diff->dist < b->diff->dist) : 0);
93 }
94
cb_diff_sort(void * _core,void * _node)95 static bool cb_diff_sort(void *_core, void *_node) {
96 RConfigNode *node = _node;
97 const char *column = node->value;
98 RCore *core = _core;
99 if (column && *column != '?') {
100 if (!strcmp (column, "name")) {
101 core->anal->columnSort = (RListComparator)compareName;
102 } else if (!strcmp (column, "namelen")) {
103 core->anal->columnSort = (RListComparator)compareNameLen;
104 } else if (!strcmp (column, "addr")) {
105 core->anal->columnSort = (RListComparator)compareAddress;
106 } else if (!strcmp (column, "type")) {
107 core->anal->columnSort = (RListComparator)compareType;
108 } else if (!strcmp (column, "size")) {
109 core->anal->columnSort = (RListComparator)compareSize;
110 } else if (!strcmp (column, "dist")) {
111 core->anal->columnSort = (RListComparator)compareDist;
112 } else {
113 goto fail;
114 }
115 return true;
116 }
117 fail:
118 eprintf ("e diff.sort = [name, namelen, addr, type, size, dist]\n");
119 return false;
120 }
121
has_esil(RCore * core,const char * name)122 static const char *has_esil(RCore *core, const char *name) {
123 RListIter *iter;
124 RAnalPlugin *h;
125 r_return_val_if_fail (core && core->anal && name, NULL);
126 r_list_foreach (core->anal->plugins, iter, h) {
127 if (h->name && !strcmp (name, h->name)) {
128 return h->esil? "Ae": "A_";
129 }
130 }
131 return "__";
132 }
133
134 // copypasta from binr/rasm2/rasm2.c
rasm2_list(RCore * core,const char * arch,int fmt)135 static void rasm2_list(RCore *core, const char *arch, int fmt) {
136 int i;
137 const char *feat2, *feat;
138 RAsm *a = core->rasm;
139 char bits[32];
140 RAsmPlugin *h;
141 RListIter *iter;
142 PJ *pj = NULL;
143 if (fmt == 'j') {
144 pj = pj_new ();
145 if (!pj) {
146 return;
147 }
148 pj_o (pj);
149 }
150 r_list_foreach (a->plugins, iter, h) {
151 if (arch && *arch) {
152 if (h->cpus && !strcmp (arch, h->name)) {
153 char *c = strdup (h->cpus);
154 int n = r_str_split (c, ',');
155 for (i = 0; i < n; i++) {
156 r_cons_println (r_str_word_get0 (c, i));
157 }
158 free (c);
159 break;
160 }
161 } else {
162 bits[0] = 0;
163 /* The underscore makes it easier to distinguish the
164 * columns */
165 if (h->bits & 8) {
166 strcat (bits, "_8");
167 }
168 if (h->bits & 16) {
169 strcat (bits, "_16");
170 }
171 if (h->bits & 32) {
172 strcat (bits, "_32");
173 }
174 if (h->bits & 64) {
175 strcat (bits, "_64");
176 }
177 if (!*bits) {
178 strcat (bits, "_0");
179 }
180 feat = "__";
181 if (h->assemble && h->disassemble) {
182 feat = "ad";
183 }
184 if (h->assemble && !h->disassemble) {
185 feat = "a_";
186 }
187 if (!h->assemble && h->disassemble) {
188 feat = "_d";
189 }
190 feat2 = has_esil (core, h->name);
191 if (fmt == 'q') {
192 r_cons_println (h->name);
193 } else if (fmt == 'j') {
194 const char *license = "GPL";
195 pj_k (pj, h->name);
196 pj_o (pj);
197 pj_k (pj, "bits");
198 pj_a (pj);
199 pj_i (pj, 32);
200 pj_i (pj, 64);
201 pj_end (pj);
202 pj_ks (pj, "license", license);
203 pj_ks (pj, "description", h->desc);
204 pj_ks (pj, "features", feat);
205 pj_end (pj);
206 } else {
207 r_cons_printf ("%s%s %-9s %-11s %-7s %s\n",
208 feat, feat2, bits, h->name,
209 r_str_get_fail (h->license, "unknown"), h->desc);
210 }
211 }
212 }
213 if (fmt == 'j') {
214 pj_end (pj);
215 r_cons_println (pj_string (pj));
216 pj_free (pj);
217 }
218 }
219
__setsegoff(RConfig * cfg,const char * asmarch,int asmbits)220 static inline void __setsegoff(RConfig *cfg, const char *asmarch, int asmbits) {
221 int autoseg = (!strncmp (asmarch, "x86", 3) && asmbits == 16);
222 r_config_set (cfg, "asm.segoff", r_str_bool (autoseg));
223 }
224
cb_debug_hitinfo(void * user,void * data)225 static bool cb_debug_hitinfo(void *user, void *data) {
226 RCore *core = (RCore*) user;
227 RConfigNode *node = (RConfigNode*) data;
228 core->dbg->hitinfo = node->i_value;
229 return true;
230 }
231
cb_anal_jmpretpoline(void * user,void * data)232 static bool cb_anal_jmpretpoline(void *user, void *data) {
233 RCore *core = (RCore*) user;
234 RConfigNode *node = (RConfigNode*) data;
235 core->anal->opt.retpoline = node->i_value;
236 return true;
237 }
cb_anal_jmptailcall(void * user,void * data)238 static bool cb_anal_jmptailcall(void *user, void *data) {
239 RCore *core = (RCore*) user;
240 RConfigNode *node = (RConfigNode*) data;
241 core->anal->opt.tailcall = node->i_value;
242 return true;
243 }
244
cb_analarmthumb(void * user,void * data)245 static bool cb_analarmthumb(void *user, void *data) {
246 RCore *core = (RCore*) user;
247 RConfigNode *node = (RConfigNode*) data;
248 core->anal->opt.armthumb = node->i_value;
249 return true;
250 }
251
cb_analdepth(void * user,void * data)252 static bool cb_analdepth(void *user, void *data) {
253 RCore *core = (RCore*) user;
254 RConfigNode *node = (RConfigNode*) data;
255 core->anal->opt.depth = node->i_value;
256 return true;
257 }
258
cb_analgraphdepth(void * user,void * data)259 static bool cb_analgraphdepth(void *user, void *data) {
260 RCore *core = (RCore *)user;
261 RConfigNode *node = (RConfigNode *)data;
262 core->anal->opt.graph_depth = node->i_value;
263 return true;
264 }
265
cb_analafterjmp(void * user,void * data)266 static bool cb_analafterjmp(void *user, void *data) {
267 RCore *core = (RCore*) user;
268 RConfigNode *node = (RConfigNode*) data;
269 core->anal->opt.afterjmp = node->i_value;
270 return true;
271 }
272
cb_anal_delay(void * user,void * data)273 static bool cb_anal_delay(void *user, void *data) {
274 RCore *core = (RCore*) user;
275 RConfigNode *node = (RConfigNode*) data;
276 core->anal->opt.delay = node->i_value;
277 return true;
278 }
279
cb_anal_endsize(void * user,void * data)280 static bool cb_anal_endsize(void *user, void *data) {
281 RCore *core = (RCore*) user;
282 RConfigNode *node = (RConfigNode*) data;
283 core->anal->opt.endsize = node->i_value;
284 return true;
285 }
286
cb_analvars(void * user,void * data)287 static bool cb_analvars(void *user, void *data) {
288 RCore *core = (RCore*) user;
289 RConfigNode *node = (RConfigNode*) data;
290 core->anal->opt.vars = node->i_value;
291 return true;
292 }
293
cb_analvars_stackname(void * user,void * data)294 static bool cb_analvars_stackname(void *user, void *data) {
295 RCore *core = (RCore *)user;
296 RConfigNode *node = (RConfigNode *)data;
297 core->anal->opt.varname_stack = node->i_value;
298 return true;
299 }
300
cb_anal_nonull(void * user,void * data)301 static bool cb_anal_nonull(void *user, void *data) {
302 RCore *core = (RCore*) user;
303 RConfigNode *node = (RConfigNode*) data;
304 core->anal->opt.nonull = node->i_value;
305 return true;
306 }
307
cb_analstrings(void * user,void * data)308 static bool cb_analstrings(void *user, void *data) {
309 RCore *core = (RCore*) user;
310 RConfigNode *node = (RConfigNode*) data;
311 if (node->i_value) {
312 r_config_set (core->config, "bin.strings", "false");
313 }
314 return true;
315 }
316
cb_anal_ignbithints(void * user,void * data)317 static bool cb_anal_ignbithints(void *user, void *data) {
318 RCore *core = (RCore*) user;
319 RConfigNode *node = (RConfigNode*) data;
320 core->anal->opt.ignbithints = node->i_value;
321 return true;
322 }
323
cb_analsleep(void * user,void * data)324 static bool cb_analsleep(void *user, void *data) {
325 RCore *core = (RCore*) user;
326 RConfigNode *node = (RConfigNode*) data;
327 core->anal->sleep = node->i_value;
328 return true;
329 }
330
cb_analmaxrefs(void * user,void * data)331 static bool cb_analmaxrefs(void *user, void *data) {
332 RCore *core = (RCore*) user;
333 RConfigNode *node = (RConfigNode*) data;
334 core->anal->maxreflines = node->i_value;
335 return true;
336 }
337
cb_analnorevisit(void * user,void * data)338 static bool cb_analnorevisit(void *user, void *data) {
339 RCore *core = (RCore*) user;
340 RConfigNode *node = (RConfigNode*) data;
341 core->anal->opt.norevisit = node->i_value;
342 return true;
343 }
344
cb_analnopskip(void * user,void * data)345 static bool cb_analnopskip(void *user, void *data) {
346 RCore *core = (RCore*) user;
347 RConfigNode *node = (RConfigNode*) data;
348 core->anal->opt.nopskip = node->i_value;
349 return true;
350 }
351
cb_analhpskip(void * user,void * data)352 static bool cb_analhpskip(void *user, void *data) {
353 RCore *core = (RCore*) user;
354 RConfigNode *node = (RConfigNode*) data;
355 core->anal->opt.hpskip = node->i_value;
356 return true;
357 }
358
update_analarch_options(RCore * core,RConfigNode * node)359 static void update_analarch_options(RCore *core, RConfigNode *node) {
360 RAnalPlugin *h;
361 RListIter *it;
362 if (core && core->anal && node) {
363 r_config_node_purge_options (node);
364 r_list_foreach (core->anal->plugins, it, h) {
365 if (h->name) {
366 SETOPTIONS (node, h->name, NULL);
367 }
368 }
369 }
370 }
371
cb_analarch(void * user,void * data)372 static bool cb_analarch(void *user, void *data) {
373 RCore *core = (RCore*) user;
374 RConfigNode *node = (RConfigNode*) data;
375 if (*node->value == '?') {
376 update_analarch_options (core, node);
377 print_node_options (node);
378 return false;
379 }
380 if (*node->value) {
381 if (r_anal_use (core->anal, node->value)) {
382 return true;
383 }
384 char *p = strchr (node->value, '.');
385 if (p) {
386 char *arch = strdup (node->value);
387 arch[p - node->value] = 0;
388 free (node->value);
389 node->value = arch;
390 if (r_anal_use (core->anal, node->value)) {
391 return true;
392 }
393 }
394 const char *aa = r_config_get (core->config, "asm.arch");
395 if (!aa || strcmp (aa, node->value)) {
396 eprintf ("anal.arch: cannot find '%s'\n", node->value);
397 } else {
398 r_config_set (core->config, "anal.arch", "null");
399 return true;
400 }
401 }
402 return false;
403 }
404
cb_analcpu(void * user,void * data)405 static bool cb_analcpu(void *user, void *data) {
406 RCore *core = (RCore *) user;
407 RConfigNode *node = (RConfigNode *) data;
408 r_anal_set_cpu (core->anal, node->value);
409 /* set pcalign */
410 {
411 int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
412 r_config_set_i (core->config, "asm.pcalign", (v != -1)? v: 0);
413 }
414 return true;
415 }
416
cb_analrecont(void * user,void * data)417 static bool cb_analrecont(void *user, void *data) {
418 RCore *core = (RCore*) user;
419 RConfigNode *node = (RConfigNode*) data;
420 core->anal->opt.recont = node->i_value;
421 return true;
422 }
423
cb_analijmp(void * user,void * data)424 static bool cb_analijmp(void *user, void *data) {
425 RCore *core = (RCore*) user;
426 RConfigNode *node = (RConfigNode*) data;
427 core->anal->opt.ijmp = node->i_value;
428 return true;
429 }
430
cb_asmsubvarmin(void * user,void * data)431 static bool cb_asmsubvarmin(void *user, void *data) {
432 RCore *core = (RCore *) user;
433 RConfigNode *node = (RConfigNode *) data;
434 core->parser->minval = node->i_value;
435 return true;
436 }
437
cb_asmsubtail(void * user,void * data)438 static bool cb_asmsubtail(void *user, void *data) {
439 RCore *core = (RCore *) user;
440 RConfigNode *node = (RConfigNode *) data;
441 core->parser->subtail = node->i_value;
442 return true;
443 }
444
cb_scrlast(void * user,void * data)445 static bool cb_scrlast(void *user, void *data) {
446 RConfigNode *node = (RConfigNode *) data;
447 r_cons_singleton ()->context->lastEnabled = node->i_value;
448 return true;
449 }
450
cb_scr_vi(void * user,void * data)451 static bool cb_scr_vi(void *user, void *data) {
452 RCore *core = (RCore *) user;
453 RConfigNode *node = (RConfigNode *) data;
454 core->cons->line->enable_vi_mode = node->i_value;
455 return true;
456 }
457
cb_scr_prompt_mode(void * user,void * data)458 static bool cb_scr_prompt_mode(void *user, void *data) {
459 RCore *core = (RCore *) user;
460 RConfigNode *node = (RConfigNode *) data;
461 core->cons->line->prompt_mode = node->i_value;
462 return true;
463 }
464
cb_scr_wideoff(void * user,void * data)465 static bool cb_scr_wideoff(void *user, void *data) {
466 RCore *core = (RCore *) user;
467 RConfigNode *node = (RConfigNode *) data;
468 core->print->wide_offsets = node->i_value;
469 return true;
470 }
471
cb_scrrainbow(void * user,void * data)472 static bool cb_scrrainbow(void *user, void *data) {
473 RCore *core = (RCore *) user;
474 RConfigNode *node = (RConfigNode *) data;
475 if (node->i_value) {
476 core->print->flags |= R_PRINT_FLAGS_RAINBOW;
477 r_core_cmd0 (core, "ecr");
478 } else {
479 core->print->flags &= (~R_PRINT_FLAGS_RAINBOW);
480 r_core_cmd0 (core, "ecoo");
481 }
482 r_print_set_flags (core->print, core->print->flags);
483 return true;
484 }
485
cb_asmpseudo(void * user,void * data)486 static bool cb_asmpseudo (void *user, void *data) {
487 RCore *core = (RCore *) user;
488 RConfigNode *node = (RConfigNode *) data;
489 core->rasm->pseudo = node->i_value;
490 return true;
491 }
492
cb_asmsubsec(void * user,void * data)493 static bool cb_asmsubsec(void *user, void *data) {
494 RCore *core = (RCore *) user;
495 RConfigNode *node = (RConfigNode *) data;
496 if (node->i_value) {
497 core->print->flags |= R_PRINT_FLAGS_SECSUB;
498 } else {
499 core->print->flags &= (~R_PRINT_FLAGS_SECSUB);
500 }
501 r_print_set_flags (core->print, core->print->flags);
502 return true;
503 }
504
cb_asmassembler(void * user,void * data)505 static bool cb_asmassembler(void *user, void *data) {
506 RCore *core = (RCore *) user;
507 RConfigNode *node = (RConfigNode *) data;
508 r_asm_use_assembler (core->rasm, node->value);
509 return true;
510 }
511
update_cmdpdc_options(RCore * core,RConfigNode * node)512 static void update_cmdpdc_options(RCore *core, RConfigNode *node) {
513 r_return_if_fail (core && core->rasm && node);
514 RListIter *iter;
515 r_config_node_purge_options (node);
516 char *opts = r_core_cmd_str (core, "e cmd.pdc=?");
517 RList *optl = r_str_split_list (opts, "\n", 0);
518 char *opt;
519 r_list_foreach (optl, iter, opt) {
520 SETOPTIONS (node, opt, NULL);
521 }
522 r_list_free (optl);
523 free (opts);
524 }
525
update_asmcpu_options(RCore * core,RConfigNode * node)526 static void update_asmcpu_options(RCore *core, RConfigNode *node) {
527 RAsmPlugin *h;
528 RListIter *iter;
529 r_return_if_fail (core && core->rasm);
530 const char *arch = r_config_get (core->config, "asm.arch");
531 if (!arch || !*arch) {
532 return;
533 }
534 r_config_node_purge_options (node);
535 r_list_foreach (core->rasm->plugins, iter, h) {
536 if (h->cpus && !strcmp (arch, h->name)) {
537 char *c = strdup (h->cpus);
538 int i, n = r_str_split (c, ',');
539 for (i = 0; i < n; i++) {
540 const char *word = r_str_word_get0 (c, i);
541 if (word && *word) {
542 node->options->free = free;
543 SETOPTIONS (node, word, NULL);
544 }
545 }
546 free (c);
547 }
548 }
549 }
550
cb_asmcpu(void * user,void * data)551 static bool cb_asmcpu(void *user, void *data) {
552 RCore *core = (RCore *) user;
553 RConfigNode *node = (RConfigNode *) data;
554 if (*node->value == '?') {
555 update_asmcpu_options (core, node);
556 /* print verbose help instead of plain option listing */
557 rasm2_list (core, r_config_get (core->config, "asm.arch"), node->value[1]);
558 return 0;
559 }
560 r_asm_set_cpu (core->rasm, node->value);
561 r_config_set (core->config, "anal.cpu", node->value);
562 return true;
563 }
564
update_asmarch_options(RCore * core,RConfigNode * node)565 static void update_asmarch_options(RCore *core, RConfigNode *node) {
566 RAsmPlugin *h;
567 RListIter *iter;
568 if (core && node && core->rasm) {
569 r_config_node_purge_options (node);
570 r_list_foreach (core->rasm->plugins, iter, h) {
571 if (h->name) {
572 SETOPTIONS (node, h->name, NULL);
573 }
574 }
575 }
576 }
577
update_asmbits_options(RCore * core,RConfigNode * node)578 static void update_asmbits_options(RCore *core, RConfigNode *node) {
579 if (core && core->rasm && core->rasm->cur && node) {
580 int bits = core->rasm->cur->bits;
581 int i;
582 r_config_node_purge_options (node);
583 for (i = 1; i <= bits; i <<= 1) {
584 if (i & bits) {
585 char *a = r_str_newf ("%d", i);
586 SETOPTIONS (node, a, NULL);
587 free (a);
588 }
589 }
590 }
591 }
592
cb_asmarch(void * user,void * data)593 static bool cb_asmarch(void *user, void *data) {
594 char asmparser[32];
595 RCore *core = (RCore *) user;
596 RConfigNode *node = (RConfigNode *) data;
597 const char *asmos = NULL;
598 int bits = R_SYS_BITS;
599 if (!*node->value || !core || !core->rasm) {
600 return false;
601 }
602 asmos = r_config_get (core->config, "asm.os");
603 if (core && core->anal && core->anal->bits) {
604 bits = core->anal->bits;
605 }
606 if (*node->value == '?') {
607 update_asmarch_options (core, node);
608 if (strlen (node->value) > 1 && node->value[1] == '?') {
609 /* print more verbose help instead of plain option values */
610 rasm2_list (core, NULL, node->value[1]);
611 return false;
612 } else {
613 print_node_options (node);
614 return false;
615 }
616 }
617 r_egg_setup (core->egg, node->value, bits, 0, R_SYS_OS);
618
619 if (!r_asm_use (core->rasm, node->value)) {
620 eprintf ("asm.arch: cannot find (%s)\n", node->value);
621 return false;
622 }
623 //we should strdup here otherwise will crash if any r_config_set
624 //free the old value
625 char *asm_cpu = strdup (r_config_get (core->config, "asm.cpu"));
626 if (core->rasm->cur) {
627 const char *newAsmCPU = core->rasm->cur->cpus;
628 if (newAsmCPU) {
629 if (*newAsmCPU) {
630 char *nac = strdup (newAsmCPU);
631 char *comma = strchr (nac, ',');
632 if (comma) {
633 if (!*asm_cpu || (*asm_cpu && !strstr(nac, asm_cpu))) {
634 *comma = 0;
635 r_config_set (core->config, "asm.cpu", nac);
636 }
637 }
638 free (nac);
639 } else {
640 r_config_set (core->config, "asm.cpu", "");
641 }
642 }
643 bits = core->rasm->cur->bits;
644 if (8 & bits) {
645 bits = 8;
646 } else if (16 & bits) {
647 bits = 16;
648 } else if (32 & bits) {
649 bits = 32;
650 } else {
651 bits = 64;
652 }
653 update_asmbits_options (core, r_config_node_get (core->config, "asm.bits"));
654 }
655 snprintf (asmparser, sizeof (asmparser), "%s.pseudo", node->value);
656 r_config_set (core->config, "asm.parser", asmparser);
657 if (core->rasm->cur && core->anal &&
658 !(core->rasm->cur->bits & core->anal->bits)) {
659 r_config_set_i (core->config, "asm.bits", bits);
660 }
661
662 //r_debug_set_arch (core->dbg, r_sys_arch_id (node->value), bits);
663 r_debug_set_arch (core->dbg, node->value, bits);
664 if (!r_config_set (core->config, "anal.arch", node->value)) {
665 char *p, *s = strdup (node->value);
666 if (s) {
667 p = strchr (s, '.');
668 if (p) {
669 *p = 0;
670 }
671 if (!r_config_set (core->config, "anal.arch", s)) {
672 /* fall back to the anal.null plugin */
673 r_config_set (core->config, "anal.arch", "null");
674 }
675 free (s);
676 }
677 }
678 // set pcalign
679 if (core->anal) {
680 const char *asmcpu = r_config_get (core->config, "asm.cpu");
681 if (!r_syscall_setup (core->anal->syscall, node->value, core->anal->bits, asmcpu, asmos)) {
682 //eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
683 // node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
684 }
685 }
686 //if (!strcmp (node->value, "bf"))
687 // r_config_set (core->config, "dbg.backend", "bf");
688 __setsegoff (core->config, node->value, core->rasm->bits);
689
690 // set a default endianness
691 int bigbin = r_bin_is_big_endian (core->bin);
692 if (bigbin == -1 /* error: no endianness detected in binary */) {
693 bigbin = r_config_get_i (core->config, "cfg.bigendian");
694 }
695
696 // try to set endian of RAsm to match binary
697 r_asm_set_big_endian (core->rasm, bigbin);
698 // set endian of display to match binary
699 core->print->big_endian = bigbin;
700
701 r_asm_set_cpu (core->rasm, asm_cpu);
702 free (asm_cpu);
703 RConfigNode *asmcpu = r_config_node_get (core->config, "asm.cpu");
704 if (asmcpu) {
705 update_asmcpu_options (core, asmcpu);
706 }
707 {
708 int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
709 if (v != -1) {
710 r_config_set_i (core->config, "asm.pcalign", v);
711 } else {
712 r_config_set_i (core->config, "asm.pcalign", 0);
713 }
714 }
715 /* reload types and cc info */
716 // changing asm.arch changes anal.arch
717 // changing anal.arch sets types db
718 // so ressetting is redundant and may lead to bugs
719 // 1 case this is usefull is when sdb_types is null
720 if (!core->anal || !core->anal->sdb_types) {
721 r_core_anal_type_init (core);
722 }
723 r_core_anal_cc_init (core);
724
725 return true;
726 }
727
cb_dbgbpsize(void * user,void * data)728 static bool cb_dbgbpsize(void *user, void *data) {
729 RCore *core = (RCore *) user;
730 RConfigNode *node = (RConfigNode *) data;
731 core->dbg->bpsize = node->i_value;
732 return true;
733 }
734
cb_dbgbtdepth(void * user,void * data)735 static bool cb_dbgbtdepth(void *user, void *data) {
736 RCore *core = (RCore *) user;
737 RConfigNode *node = (RConfigNode *) data;
738 core->dbg->btdepth = node->i_value;
739 return true;
740 }
741
cb_asmbits(void * user,void * data)742 static bool cb_asmbits(void *user, void *data) {
743 RCore *core = (RCore *) user;
744 RConfigNode *node = (RConfigNode *) data;
745
746 if (*node->value == '?') {
747 update_asmbits_options (core, node);
748 print_node_options (node);
749 return false;
750 }
751
752 bool ret = false;
753 if (!core) {
754 eprintf ("user can't be NULL\n");
755 return false;
756 }
757
758 int bits = node->i_value;
759 #if 0
760 // TODO: pretty good optimization, but breaks many tests when arch is different i think
761 if (bits == core->rasm->bits && bits == core->anal->bits && bits == core->dbg->bits) {
762 // early optimization
763 return true;
764 }
765 #endif
766 if (bits > 0) {
767 ret = r_asm_set_bits (core->rasm, bits);
768 if (!ret) {
769 RAsmPlugin *h = core->rasm->cur;
770 if (!h) {
771 eprintf ("e asm.bits: Cannot set value, no plugins defined yet\n");
772 ret = true;
773 }
774 // else { eprintf ("Cannot set bits %d to '%s'\n", bits, h->name); }
775 }
776 if (!r_anal_set_bits (core->anal, bits)) {
777 eprintf ("asm.arch: Cannot setup '%d' bits analysis engine\n", bits);
778 ret = false;
779 }
780 core->print->bits = bits;
781 }
782 if (core->dbg && core->anal && core->anal->cur) {
783 r_debug_set_arch (core->dbg, core->anal->cur->arch, bits);
784 bool load_from_debug = r_config_get_i (core->config, "cfg.debug");
785 if (load_from_debug) {
786 if (core->dbg->h && core->dbg->h->reg_profile) {
787 // XXX. that should depend on the plugin, not the host os
788 #if __WINDOWS__
789 #if !defined(_WIN64)
790 core->dbg->bits = R_SYS_BITS_32;
791 #else
792 core->dbg->bits = R_SYS_BITS_64;
793 #endif
794 #endif
795 char *rp = core->dbg->h->reg_profile (core->dbg);
796 r_reg_set_profile_string (core->dbg->reg, rp);
797 r_reg_set_profile_string (core->anal->reg, rp);
798 free (rp);
799 }
800 } else {
801 (void)r_anal_set_reg_profile (core->anal);
802 }
803 }
804 r_core_anal_cc_init (core);
805 const char *asmos = r_config_get (core->config, "asm.os");
806 const char *asmarch = r_config_get (core->config, "asm.arch");
807 const char *asmcpu = r_config_get (core->config, "asm.cpu");
808 if (core->anal) {
809 if (!r_syscall_setup (core->anal->syscall, asmarch, bits, asmcpu, asmos)) {
810 //eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
811 // node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
812 }
813 __setsegoff (core->config, asmarch, core->anal->bits);
814 if (core->dbg) {
815 r_bp_use (core->dbg->bp, asmarch, core->anal->bits);
816 r_config_set_i (core->config, "dbg.bpsize", r_bp_size (core->dbg->bp));
817 }
818 /* set pcalign */
819 int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
820 r_config_set_i (core->config, "asm.pcalign", (v != -1)? v: 0);
821 }
822 return ret;
823 }
824
update_asmfeatures_options(RCore * core,RConfigNode * node)825 static void update_asmfeatures_options(RCore *core, RConfigNode *node) {
826 int i, argc;
827
828 if (core && core->rasm && core->rasm->cur) {
829 if (core->rasm->cur->features) {
830 char *features = strdup (core->rasm->cur->features);
831 argc = r_str_split (features, ',');
832 for (i = 0; i < argc; i++) {
833 const char *feature = r_str_word_get0 (features, i);
834 if (feature) {
835 r_config_node_add_option (node, feature);
836 }
837 }
838 free (features);
839 }
840 }
841 }
842
cb_flag_realnames(void * user,void * data)843 static bool cb_flag_realnames(void *user, void *data) {
844 RCore *core = (RCore *) user;
845 RConfigNode *node = (RConfigNode *) data;
846 core->flags->realnames = node->i_value;
847 return true;
848 }
849
cb_asmfeatures(void * user,void * data)850 static bool cb_asmfeatures(void *user, void *data) {
851 RCore *core = (RCore *) user;
852 RConfigNode *node = (RConfigNode *) data;
853 if (*node->value == '?') {
854 update_asmfeatures_options (core, node);
855 print_node_options (node);
856 return 0;
857 }
858 R_FREE (core->rasm->features);
859 if (node->value[0]) {
860 core->rasm->features = strdup (node->value);
861 }
862 return 1;
863 }
864
cb_asmlineswidth(void * user,void * data)865 static bool cb_asmlineswidth(void *user, void *data) {
866 RCore *core = (RCore *) user;
867 RConfigNode *node = (RConfigNode *) data;
868 core->anal->lineswidth = node->i_value;
869 return true;
870 }
871
cb_emustr(void * user,void * data)872 static bool cb_emustr(void *user, void *data) {
873 RCore *core = (RCore *) user;
874 RConfigNode *node = (RConfigNode *) data;
875 if (node->i_value) {
876 r_config_set (core->config, "asm.emu", "true");
877 }
878 return true;
879 }
880
cb_emuskip(void * user,void * data)881 static bool cb_emuskip(void *user, void *data) {
882 RConfigNode *node = (RConfigNode*) data;
883 if (*node->value == '?') {
884 if (strlen (node->value) > 1 && node->value[1] == '?') {
885 r_cons_printf ("Concatenation of meta types encoded as characters:\n" \
886 "'d': data\n'c': code\n's': string\n'f': format\n'm': magic\n" \
887 "'h': hide\n'C': comment\n'r': run\n" \
888 "(default is 'ds' to skip data and strings)\n");
889 } else {
890 print_node_options (node);
891 }
892 return false;
893 }
894 return true;
895 }
896
cb_jsonencoding(void * user,void * data)897 static bool cb_jsonencoding(void *user, void *data) {
898 RConfigNode *node = (RConfigNode*) data;
899 if (*node->value == '?') {
900 if (node->value[1] && node->value[1] == '?') {
901 r_cons_printf ("choose either: \n"\
902 "none (default)\n" \
903 "base64 - encode the json string values as base64\n" \
904 "hex - convert the string to a string of hexpairs\n" \
905 "array - convert the string to an array of chars\n" \
906 "strip - strip non-printable characters\n");
907 } else {
908 print_node_options (node);
909 }
910 return false;
911 }
912 return true;
913 }
914
cb_jsonencoding_numbers(void * user,void * data)915 static bool cb_jsonencoding_numbers(void *user, void *data) {
916 RConfigNode *node = (RConfigNode*) data;
917 if (*node->value == '?') {
918 if (node->value[1] && node->value[1] == '?') {
919 r_cons_printf ("choose either: \n"\
920 "none (default)\n" \
921 "string - encode the json number values as strings\n" \
922 "hex - encode the number values as hex, then as a string\n");
923 } else {
924 print_node_options (node);
925 }
926 return false;
927 }
928 return true;
929 }
930
cb_asm_armimm(void * user,void * data)931 static bool cb_asm_armimm(void *user, void *data) {
932 RCore *core = (RCore *) user;
933 RConfigNode *node = (RConfigNode *) data;
934 core->rasm->immdisp = node->i_value ? true : false;
935 return true;
936 }
937
cb_asm_invhex(void * user,void * data)938 static bool cb_asm_invhex(void *user, void *data) {
939 RCore *core = (RCore *) user;
940 RConfigNode *node = (RConfigNode *) data;
941 core->rasm->invhex = node->i_value;
942 return true;
943 }
944
cb_asm_pcalign(void * user,void * data)945 static bool cb_asm_pcalign(void *user, void *data) {
946 RCore *core = (RCore *) user;
947 RConfigNode *node = (RConfigNode *) data;
948 int align = node->i_value;
949 if (align < 0) {
950 align = 0;
951 }
952 core->rasm->pcalign = align;
953 core->anal->pcalign = align;
954 return true;
955 }
956
cb_asmos(void * user,void * data)957 static bool cb_asmos(void *user, void *data) {
958 RCore *core = (RCore*) user;
959 int asmbits = r_config_get_i (core->config, "asm.bits");
960 RConfigNode *asmarch, *node = (RConfigNode*) data;
961
962 if (*node->value == '?') {
963 print_node_options (node);
964 return 0;
965 }
966 if (!node->value[0]) {
967 free (node->value);
968 node->value = strdup (R_SYS_OS);
969 }
970 asmarch = r_config_node_get (core->config, "asm.arch");
971 if (asmarch) {
972 const char *asmcpu = r_config_get (core->config, "asm.cpu");
973 r_syscall_setup (core->anal->syscall, asmarch->value, core->anal->bits, asmcpu, node->value);
974 __setsegoff (core->config, asmarch->value, asmbits);
975 }
976 r_anal_set_os (core->anal, node->value);
977 r_core_anal_cc_init (core);
978 return true;
979 }
980
update_asmparser_options(RCore * core,RConfigNode * node)981 static void update_asmparser_options(RCore *core, RConfigNode *node) {
982 RListIter *iter;
983 RParsePlugin *parser;
984 if (core && node && core->parser && core->parser->parsers) {
985 r_config_node_purge_options (node);
986 r_list_foreach (core->parser->parsers, iter, parser) {
987 SETOPTIONS (node, parser->name, NULL);
988 }
989 }
990 }
991
cb_asmparser(void * user,void * data)992 static bool cb_asmparser(void *user, void *data) {
993 RCore *core = (RCore*) user;
994 RConfigNode *node = (RConfigNode*) data;
995 if (*node->value == '?') {
996 update_asmparser_options (core, node);
997 print_node_options (node);
998 return false;
999 }
1000
1001 return r_parse_use (core->parser, node->value);
1002 }
1003
1004 typedef struct {
1005 const char *name;
1006 const char *aliases;
1007 } namealiases_pair;
1008
cb_binstrenc(void * user,void * data)1009 static bool cb_binstrenc (void *user, void *data) {
1010 RCore *core = (RCore*) user;
1011 RConfigNode *node = (RConfigNode *)data;
1012 if (*node->value == '?') {
1013 print_node_options (node);
1014 r_cons_printf (" -- if string's 2nd & 4th bytes are 0 then utf16le else "
1015 "if 2nd - 4th & 6th bytes are 0 & no char > 0x10ffff then utf32le else "
1016 "if utf8 char detected then utf8 else latin1\n");
1017 return false;
1018 }
1019 const namealiases_pair names[] = {
1020 { "guess", NULL },
1021 { "latin1", "ascii" },
1022 { "utf8", "utf-8" },
1023 { "utf16le", "utf-16le,utf16-le" },
1024 { "utf32le", "utf-32le,utf32-le" },
1025 { "utf16be", "utf-16be,utf16-be" },
1026 { "utf32be", "utf-32be,utf32-be" } };
1027 int i;
1028 char *enc = strdup (node->value);
1029 if (!enc) {
1030 return false;
1031 }
1032 r_str_case (enc, false);
1033 for (i = 0; i < R_ARRAY_SIZE (names); i++) {
1034 const namealiases_pair *pair = &names[i];
1035 if (!strcmp (pair->name, enc) || r_str_cmp_list (pair->aliases, enc, ',')) {
1036 free (node->value);
1037 node->value = strdup (pair->name);
1038 free (enc);
1039 if (core->bin) {
1040 free (core->bin->strenc);
1041 core->bin->strenc = !strcmp (node->value, "guess") ? NULL : strdup (node->value);
1042 r_bin_reset_strings (core->bin);
1043 }
1044 return true;
1045 }
1046 }
1047 eprintf ("Unknown encoding: %s\n", node->value);
1048 free (enc);
1049 return false;
1050 }
1051
cb_binfilter(void * user,void * data)1052 static bool cb_binfilter(void *user, void *data) {
1053 RCore *core = (RCore*) user;
1054 RConfigNode *node = (RConfigNode*) data;
1055 core->bin->filter = node->i_value;
1056 return true;
1057 }
1058
1059 /* BinDemangleCmd */
cb_bdc(void * user,void * data)1060 static bool cb_bdc(void *user, void *data) {
1061 RCore *core = (RCore*) user;
1062 RConfigNode *node = (RConfigNode*) data;
1063 core->bin->demanglercmd = node->i_value;
1064 return true;
1065 }
1066
cb_useldr(void * user,void * data)1067 static bool cb_useldr(void *user, void *data) {
1068 RCore *core = (RCore*) user;
1069 RConfigNode *node = (RConfigNode*) data;
1070 core->bin->use_ldr = node->i_value;
1071 return true;
1072 }
1073
cb_binat(void * user,void * data)1074 static bool cb_binat(void *user, void *data) {
1075 RCore *core = (RCore*) user;
1076 RConfigNode *node = (RConfigNode*) data;
1077 core->binat = node->i_value;
1078 return true;
1079 }
1080
cb_usextr(void * user,void * data)1081 static bool cb_usextr(void *user, void *data) {
1082 RCore *core = (RCore*) user;
1083 RConfigNode *node = (RConfigNode*) data;
1084 core->bin->use_xtr = node->i_value;
1085 return true;
1086 }
1087
cb_strpurge(void * user,void * data)1088 static bool cb_strpurge(void *user, void *data) {
1089 RCore *core = (RCore*) user;
1090 RConfigNode *node = (RConfigNode*) data;
1091 if (*node->value == '?') {
1092 r_cons_printf (
1093 "There can be multiple entries separated by commas. No whitespace before/after entries.\n"
1094 "Possible entries:\n"
1095 " all : purge all strings\n"
1096 " true : use the false_positive() classifier in cbin.c\n"
1097 " addr : purge string at addr\n"
1098 " addr1-addr2 : purge all strings in the range addr1-addr2 inclusive\n"
1099 " !addr : prevent purge of string at addr by prev entries\n"
1100 " !addr1-addr2 : prevent purge of strings in range addr1-addr2 inclusive by prev entries\n"
1101 "Neither !true nor !false is supported.\n"
1102 "\n"
1103 "Examples:\n"
1104 " e bin.str.purge=true,0-0xff,!0x1a\n"
1105 " -- purge strings using the false_positive() classifier in cbin.c and also strings \n"
1106 " with addresses in the range 0-0xff, but not the string at 0x1a.\n"
1107 " e bin.str.purge=all,!0x1000-0x1fff\n"
1108 " -- purge all strings except the strings with addresses in the range 0x1000-0x1fff.\n");
1109 return false;
1110 }
1111 free (core->bin->strpurge);
1112 core->bin->strpurge = !*node->value || !strcmp (node->value, "false")
1113 ? NULL : strdup (node->value);
1114 return true;
1115 }
1116
cb_maxname(void * user,void * data)1117 static bool cb_maxname (void *user, void *data) {
1118 RConfigNode *node = (RConfigNode *)data;
1119 RCore *core = (RCore *) user;
1120 core->parser->maxflagnamelen = node->i_value;
1121 return true;
1122 }
1123
cb_midflags(void * user,void * data)1124 static bool cb_midflags (void *user, void *data) {
1125 RConfigNode *node = (RConfigNode *)data;
1126 if (*node->value == '?') {
1127 print_node_options (node);
1128 return false;
1129 }
1130 return true;
1131 }
1132
cb_strfilter(void * user,void * data)1133 static bool cb_strfilter(void *user, void *data) {
1134 RCore *core = (RCore*) user;
1135 RConfigNode *node = (RConfigNode*) data;
1136 if (*node->value == '?') {
1137 if (strlen (node->value) > 1 && node->value[1] == '?') {
1138 r_cons_printf ("Valid values for bin.str.filter:\n"
1139 "a only alphanumeric printable\n"
1140 "8 only strings with utf8 chars\n"
1141 "p file/directory paths\n"
1142 "e email-like addresses\n"
1143 "u urls\n"
1144 "i IPv4 address-like strings\n"
1145 "U only uppercase strings\n"
1146 "f format-strings\n");
1147 } else {
1148 print_node_options (node);
1149 }
1150 return false;
1151 } else {
1152 core->bin->strfilter = node->value[0];
1153 }
1154 return true;
1155 }
1156
cb_binforce(void * user,void * data)1157 static bool cb_binforce(void *user, void *data) {
1158 RCore *core = (RCore*) user;
1159 RConfigNode *node = (RConfigNode*) data;
1160 r_bin_force_plugin (core->bin, node->value);
1161 return true;
1162 }
1163
cb_asmsyntax(void * user,void * data)1164 static bool cb_asmsyntax(void *user, void *data) {
1165 RCore *core = (RCore*) user;
1166 RConfigNode *node = (RConfigNode*) data;
1167 if (*node->value == '?') {
1168 print_node_options (node);
1169 return false;
1170 } else {
1171 int syntax = r_asm_syntax_from_string (node->value);
1172 if (syntax == -1) {
1173 return false;
1174 }
1175 r_asm_set_syntax (core->rasm, syntax);
1176 }
1177 return true;
1178 }
1179
cb_dirzigns(void * user,void * data)1180 static bool cb_dirzigns(void *user, void *data) {
1181 RCore *core = (RCore*) user;
1182 RConfigNode *node = (RConfigNode*) data;
1183 free (core->anal->zign_path);
1184 core->anal->zign_path = strdup (node->value);
1185 return true;
1186 }
1187
cb_bigendian(void * user,void * data)1188 static bool cb_bigendian(void *user, void *data) {
1189 RCore *core = (RCore *) user;
1190 RConfigNode *node = (RConfigNode *) data;
1191 // Try to set endian based on preference, restrict by RAsmPlugin
1192 bool isbig = r_asm_set_big_endian (core->rasm, node->i_value);
1193 // Set anal endianness the same as asm
1194 r_anal_set_big_endian (core->anal, isbig);
1195 // the big endian should also be assigned to dbg->bp->endian
1196 if (core->dbg && core->dbg->bp) {
1197 core->dbg->bp->endian = isbig;
1198 }
1199 // Set printing endian to user's choice
1200 core->print->big_endian = node->i_value;
1201 return true;
1202 }
1203
list_available_plugins(const char * path)1204 static void list_available_plugins(const char *path) {
1205 RListIter *iter;
1206 const char *fn;
1207 RList *files = r_sys_dir (path);
1208 r_list_sort (files, (RListComparator)strcmp);
1209 r_list_foreach (files, iter, fn) {
1210 if (*fn && *fn != '.' && r_str_endswith (fn, ".sdb")) {
1211 char *f = strdup (fn);
1212 f[strlen (f) - 4] = 0;
1213 r_cons_println (f);
1214 free (f);
1215 }
1216 }
1217 r_list_free (files);
1218 }
1219
cb_cfgcharset(void * user,void * data)1220 static bool cb_cfgcharset(void *user, void *data) {
1221 RCore *core = (RCore*) user;
1222 RConfigNode *node = (RConfigNode*) data;
1223 const char *cf = r_str_trim_head_ro (node->value);
1224 if (!*cf) {
1225 return true;
1226 }
1227
1228 const char *cs = R2_PREFIX R_SYS_DIR R2_SDB R_SYS_DIR "charsets" R_SYS_DIR;
1229 bool rc = false;
1230 if (*cf == '?') {
1231 list_available_plugins (cs);
1232 } else {
1233 char *syscs = r_str_newf ("%s%s.sdb", cs, cf);
1234 if (r_file_exists (syscs)) {
1235 rc = r_charset_open (core->print->charset, syscs);
1236 }
1237 if (!rc) {
1238 eprintf ("Warning: Cannot load charset file '%s' '%s'.\n", syscs, cf);
1239 }
1240 free (syscs);
1241 }
1242 return rc;
1243 }
1244
cb_cfgdatefmt(void * user,void * data)1245 static bool cb_cfgdatefmt(void *user, void *data) {
1246 RCore *core = (RCore*) user;
1247 RConfigNode *node = (RConfigNode*) data;
1248 snprintf (core->print->datefmt, 32, "%s", node->value);
1249 return true;
1250 }
1251
cb_timezone(void * user,void * data)1252 static bool cb_timezone(void *user, void *data) {
1253 RCore *core = (RCore*) user;
1254 RConfigNode *node = (RConfigNode*) data;
1255 core->print->datezone = node->i_value;
1256 return true;
1257 }
1258
cb_cfgcorelog(void * user,void * data)1259 static bool cb_cfgcorelog(void *user, void *data) {
1260 RCore *core = (RCore *) user;
1261 RConfigNode *node = (RConfigNode *) data;
1262 core->cfglog = node->i_value;
1263 return true;
1264 }
1265
cb_cfgdebug(void * user,void * data)1266 static bool cb_cfgdebug(void *user, void *data) {
1267 RCore *core = (RCore*) user;
1268 RConfigNode *node = (RConfigNode*) data;
1269 if (!core) {
1270 return false;
1271 }
1272 if (core->io) {
1273 core->io->va = !node->i_value;
1274 }
1275 if (core->dbg && node->i_value) {
1276 const char *dbgbackend = r_config_get (core->config, "dbg.backend");
1277 r_debug_use (core->dbg, dbgbackend);
1278 if (!strcmp (r_config_get (core->config, "cmd.prompt"), "")) {
1279 r_config_set (core->config, "cmd.prompt", ".dr*");
1280 }
1281 if (!strcmp (dbgbackend, "bf")) {
1282 r_config_set (core->config, "asm.arch", "bf");
1283 }
1284 if (core->io->desc) {
1285 r_debug_select (core->dbg, r_io_fd_get_pid (core->io, core->io->desc->fd),
1286 r_io_fd_get_tid (core->io, core->io->desc->fd));
1287 }
1288 } else {
1289 r_debug_use (core->dbg, NULL);
1290 }
1291 return true;
1292 }
1293
cb_dirhome(void * user,void * data)1294 static bool cb_dirhome(void *user, void *data) {
1295 RConfigNode *node = (RConfigNode*) data;
1296 if (node->value) {
1297 r_sys_setenv (R_SYS_HOME, node->value);
1298 }
1299 return true;
1300 }
1301
cb_dir_projects(void * user,void * data)1302 static bool cb_dir_projects(void *user, void *data) {
1303 RConfigNode *node = (RConfigNode *)data;
1304 char *value = R_STR_ISNOTEMPTY (node->value)? node->value: NULL;
1305 if (value) {
1306 char *newva = r_file_abspath (value);
1307 free (node->value);
1308 node->value = newva;
1309 }
1310 return true;
1311 }
1312
cb_dirtmp(void * user,void * data)1313 static bool cb_dirtmp(void *user, void *data) {
1314 RConfigNode *node = (RConfigNode *)data;
1315 char *value = R_STR_ISNOTEMPTY (node->value)? node->value: NULL;
1316 if (value) {
1317 char *newva = r_file_abspath (value);
1318 free (node->value);
1319 node->value = newva;
1320 }
1321 return true;
1322 }
1323
cb_dirsrc(void * user,void * data)1324 static bool cb_dirsrc(void *user, void *data) {
1325 RConfigNode *node = (RConfigNode*) data;
1326 RCore *core = (RCore *)user;
1327 free (core->bin->srcdir);
1328 core->bin->srcdir = strdup (node->value);
1329 return true;
1330 }
1331
cb_cfgsanbox(void * user,void * data)1332 static bool cb_cfgsanbox(void *user, void *data) {
1333 RConfigNode *node = (RConfigNode*) data;
1334 int ret = r_sandbox_enable (node->i_value);
1335 if (node->i_value != ret) {
1336 eprintf ("Cannot disable sandbox\n");
1337 }
1338 return (!node->i_value && ret)? 0: 1;
1339 }
1340
cb_str_escbslash(void * user,void * data)1341 static bool cb_str_escbslash(void *user, void *data) {
1342 RCore *core = (RCore*) user;
1343 RConfigNode *node = (RConfigNode*) data;
1344 core->print->esc_bslash = node->i_value;
1345 return true;
1346 }
1347
cb_completion_maxtab(void * user,void * data)1348 static bool cb_completion_maxtab (void *user, void *data) {
1349 RCore *core = (RCore*) user;
1350 RConfigNode *node = (RConfigNode*) data;
1351 core->cons->line->completion.args_limit = node->i_value;
1352 return true;
1353 }
1354
cb_cfg_fortunes(void * user,void * data)1355 static bool cb_cfg_fortunes(void *user, void *data) {
1356 RCore *core = (RCore *)user;
1357 RConfigNode *node = (RConfigNode *)data;
1358 // TODO CN_BOOL option does not receive the right hand side of assignment as an argument
1359 if (*node->value == '?') {
1360 r_core_fortune_list (core);
1361 return false;
1362 }
1363 return true;
1364 }
1365
cb_cfg_fortunes_type(void * user,void * data)1366 static bool cb_cfg_fortunes_type(void *user, void *data) {
1367 RConfigNode *node = (RConfigNode *)data;
1368 if (*node->value == '?') {
1369 r_core_fortune_list_types ();
1370 return false;
1371 }
1372 return true;
1373 }
1374
check_decompiler(const char * name)1375 static void check_decompiler(const char* name) {
1376 char *path = r_file_path (name);
1377 if (path && path[0] == '/') {
1378 r_cons_printf ("!*%s\n", name);
1379 }
1380 free (path);
1381 }
1382
cb_cmdpdc(void * user,void * data)1383 static bool cb_cmdpdc(void *user, void *data) {
1384 RCore *core = (RCore *) user;
1385 RConfigNode *node = (RConfigNode *)data;
1386 if (*node->value == '?') {
1387 r_cons_printf ("pdc\n");
1388 // spaguetti
1389 check_decompiler ("r2retdec");
1390 RListIter *iter;
1391 RCorePlugin *cp;
1392 r_list_foreach (core->rcmd->plist, iter, cp) {
1393 if (!strcmp (cp->name, "r2ghidra")) {
1394 r_cons_printf ("pdg\n");
1395 }
1396 }
1397 check_decompiler ("r2ghidra");
1398 check_decompiler ("r2jadx");
1399 check_decompiler ("r2snow");
1400 RConfigNode *r2dec = r_config_node_get (core->config, "r2dec.asm");
1401 if (r2dec) {
1402 r_cons_printf ("pdd\n");
1403 }
1404 return false;
1405 }
1406 return true;
1407 }
1408
cb_cmdlog(void * user,void * data)1409 static bool cb_cmdlog(void *user, void *data) {
1410 RCore *core = (RCore *) user;
1411 RConfigNode *node = (RConfigNode *) data;
1412 R_FREE (core->cmdlog);
1413 core->cmdlog = strdup (node->value);
1414 return true;
1415 }
1416
cb_cmdtimes(void * user,void * data)1417 static bool cb_cmdtimes(void *user, void *data) {
1418 RCore *core = (RCore *) user;
1419 RConfigNode *node = (RConfigNode *) data;
1420 core->cmdtimes = node->value;
1421 return true;
1422 }
1423
cb_cmdrepeat(void * user,void * data)1424 static bool cb_cmdrepeat(void *user, void *data) {
1425 RCore *core = (RCore *) user;
1426 RConfigNode *node = (RConfigNode *) data;
1427 core->cmdrepeat = node->i_value;
1428 return true;
1429 }
1430
cb_screrrmode(void * user,void * data)1431 static bool cb_screrrmode(void *user, void *data) {
1432 RConfigNode *node = (RConfigNode *) data;
1433 if (*node->value == '?') {
1434 r_cons_printf ("Valid values: null, echo, buffer, quiet, flush\n");
1435 return false;
1436 }
1437 r_cons_errmodes (node->value);
1438 return true;
1439 }
1440
cb_scrnull(void * user,void * data)1441 static bool cb_scrnull(void *user, void *data) {
1442 RCore *core = (RCore *) user;
1443 RConfigNode *node = (RConfigNode *) data;
1444 core->cons->null = node->i_value;
1445 return true;
1446 }
1447
cb_color(void * user,void * data)1448 static bool cb_color(void *user, void *data) {
1449 RCore *core = (RCore *) user;
1450 RConfigNode *node = (RConfigNode *) data;
1451 if (node->i_value) {
1452 core->print->flags |= R_PRINT_FLAGS_COLOR;
1453 } else {
1454 core->print->flags &= (~R_PRINT_FLAGS_COLOR);
1455 }
1456 if (!strcmp (node->value, "true")) {
1457 node->i_value = 1;
1458 } else if (!strcmp (node->value, "false")) {
1459 node->i_value = 0;
1460 }
1461 r_cons_singleton ()->context->color_mode = (node->i_value > COLOR_MODE_16M)
1462 ? COLOR_MODE_16M: node->i_value;
1463 r_cons_pal_update_event ();
1464 r_print_set_flags (core->print, core->print->flags);
1465 return true;
1466 }
1467
cb_color_getter(void * user,RConfigNode * node)1468 static bool cb_color_getter(void *user, RConfigNode *node) {
1469 (void)user;
1470 node->i_value = r_cons_singleton ()->context->color_mode;
1471 char buf[128];
1472 r_config_node_value_format_i (buf, sizeof (buf), r_cons_singleton ()->context->color_mode, node);
1473 if (!node->value || strcmp (node->value, buf) != 0) {
1474 free (node->value);
1475 node->value = strdup (buf);
1476 }
1477 return true;
1478 }
1479
cb_decoff(void * user,void * data)1480 static bool cb_decoff(void *user, void *data) {
1481 RCore *core = (RCore *) user;
1482 RConfigNode *node = (RConfigNode *) data;
1483 if (node->i_value) {
1484 core->print->flags |= R_PRINT_FLAGS_ADDRDEC;
1485 } else {
1486 core->print->flags &= (~R_PRINT_FLAGS_ADDRDEC);
1487 }
1488 r_print_set_flags (core->print, core->print->flags);
1489 return true;
1490 }
1491
cb_dbgbep(void * user,void * data)1492 static bool cb_dbgbep(void *user, void *data) {
1493 RConfigNode *node = (RConfigNode*) data;
1494 if (*node->value == '?') {
1495 print_node_options (node);
1496 return false;
1497 }
1498 return true;
1499 }
1500
cb_dbg_btalgo(void * user,void * data)1501 static bool cb_dbg_btalgo(void *user, void *data) {
1502 RCore *core = (RCore*) user;
1503 RConfigNode *node = (RConfigNode*) data;
1504 if (*node->value == '?') {
1505 print_node_options (node);
1506 return false;
1507 }
1508 free (core->dbg->btalgo);
1509 core->dbg->btalgo = strdup (node->value);
1510 return true;
1511 }
1512
cb_dbg_libs(void * user,void * data)1513 static bool cb_dbg_libs(void *user, void *data) {
1514 RCore *core = (RCore*) user;
1515 RConfigNode *node = (RConfigNode*) data;
1516 free (core->dbg->glob_libs);
1517 core->dbg->glob_libs = strdup (node->value);
1518 return true;
1519 }
1520
cb_dbg_unlibs(void * user,void * data)1521 static bool cb_dbg_unlibs(void *user, void *data) {
1522 RCore *core = (RCore*) user;
1523 RConfigNode *node = (RConfigNode*) data;
1524 free (core->dbg->glob_unlibs);
1525 core->dbg->glob_unlibs = strdup (node->value);
1526 return true;
1527 }
1528
cb_dbg_bpinmaps(void * user,void * data)1529 static bool cb_dbg_bpinmaps(void *user, void *data) {
1530 RCore *core = (RCore *) user;
1531 RConfigNode *node = (RConfigNode *) data;
1532 core->dbg->bp->bpinmaps = node->i_value;
1533 return true;
1534 }
1535
cb_dbg_forks(void * user,void * data)1536 static bool cb_dbg_forks(void *user, void *data) {
1537 RCore *core = (RCore*) user;
1538 RConfigNode *node = (RConfigNode*) data;
1539 core->dbg->trace_forks = node->i_value;
1540 if (r_config_get_i (core->config, "cfg.debug")) {
1541 r_debug_attach (core->dbg, core->dbg->pid);
1542 }
1543 return true;
1544 }
1545
cb_dbg_gdb_page_size(void * user,void * data)1546 static bool cb_dbg_gdb_page_size(void *user, void *data) {
1547 RCore *core = (RCore*) user;
1548 RConfigNode *node = (RConfigNode*) data;
1549 if (node->i_value < 64) { // 64 is hardcoded min packet size
1550 return false;
1551 }
1552 if (isGdbPlugin (core)) {
1553 char cmd[64];
1554 snprintf (cmd, sizeof (cmd), "page_size %"PFMT64d, node->i_value);
1555 free (r_io_system (core->io, cmd));
1556 }
1557 return true;
1558 }
1559
cb_dbg_gdb_retries(void * user,void * data)1560 static bool cb_dbg_gdb_retries(void *user, void *data) {
1561 RCore *core = (RCore*) user;
1562 RConfigNode *node = (RConfigNode*) data;
1563 if (node->i_value <= 0) {
1564 return false;
1565 }
1566 if (isGdbPlugin (core)) {
1567 char cmd[64];
1568 snprintf (cmd, sizeof (cmd), "retries %"PFMT64d, node->i_value);
1569 free (r_io_system (core->io, cmd));
1570 }
1571 return true;
1572 }
1573
cb_dbg_execs(void * user,void * data)1574 static bool cb_dbg_execs(void *user, void *data) {
1575 RConfigNode *node = (RConfigNode*) data;
1576 #if __linux__
1577 RCore *core = (RCore*) user;
1578 core->dbg->trace_execs = node->i_value;
1579 if (r_config_get_i (core->config, "cfg.debug")) {
1580 r_debug_attach (core->dbg, core->dbg->pid);
1581 }
1582 #else
1583 if (node->i_value) {
1584 eprintf ("Warning: dbg.execs is not supported in this platform.\n");
1585 }
1586 #endif
1587 return true;
1588 }
1589
cb_dbg_clone(void * user,void * data)1590 static bool cb_dbg_clone(void *user, void *data) {
1591 RCore *core = (RCore*) user;
1592 RConfigNode *node = (RConfigNode*) data;
1593 core->dbg->trace_clone = node->i_value;
1594 if (r_config_get_i (core->config, "cfg.debug")) {
1595 r_debug_attach (core->dbg, core->dbg->pid);
1596 }
1597 return true;
1598 }
1599
cb_dbg_follow_child(void * user,void * data)1600 static bool cb_dbg_follow_child(void *user, void *data) {
1601 RCore *core = (RCore*) user;
1602 RConfigNode *node = (RConfigNode*) data;
1603 core->dbg->follow_child = node->i_value;
1604 return true;
1605 }
1606
cb_dbg_trace_continue(void * user,void * data)1607 static bool cb_dbg_trace_continue(void *user, void *data) {
1608 RCore *core = (RCore*)user;
1609 RConfigNode *node = (RConfigNode*)data;
1610 core->dbg->trace_continue = node->i_value;
1611 return true;
1612 }
1613
cb_dbg_aftersc(void * user,void * data)1614 static bool cb_dbg_aftersc(void *user, void *data) {
1615 RCore *core = (RCore*) user;
1616 RConfigNode *node = (RConfigNode*) data;
1617 core->dbg->trace_aftersyscall = node->i_value;
1618 if (r_config_get_i (core->config, "cfg.debug")) {
1619 r_debug_attach (core->dbg, core->dbg->pid);
1620 }
1621 return true;
1622 }
1623
cb_runprofile(void * user,void * data)1624 static bool cb_runprofile(void *user, void *data) {
1625 RCore *r = (RCore*) user;
1626 RConfigNode *node = (RConfigNode*) data;
1627 free ((void*)r->io->runprofile);
1628 if (!node || !*(node->value)) {
1629 r->io->runprofile = NULL;
1630 } else {
1631 r->io->runprofile = strdup (node->value);
1632 }
1633 return true;
1634 }
1635
cb_dbg_args(void * user,void * data)1636 static bool cb_dbg_args(void *user, void *data) {
1637 RCore *core = (RCore *)user;
1638 RConfigNode *node = (RConfigNode*) data;
1639 if (!node || !*(node->value)) {
1640 core->io->args = NULL;
1641 } else {
1642 core->io->args = strdup (node->value);
1643 }
1644 return true;
1645 }
1646
cb_dbgstatus(void * user,void * data)1647 static bool cb_dbgstatus(void *user, void *data) {
1648 RCore *r = (RCore*) user;
1649 RConfigNode *node = (RConfigNode*) data;
1650 if (r_config_get_i (r->config, "cfg.debug")) {
1651 if (node->i_value) {
1652 r_config_set (r->config, "cmd.prompt",
1653 ".dr*; drd; sr PC;pi 1;s-");
1654 } else {
1655 r_config_set (r->config, "cmd.prompt", ".dr*");
1656 }
1657 }
1658 return true;
1659 }
1660
cb_dbgbackend(void * user,void * data)1661 static bool cb_dbgbackend(void *user, void *data) {
1662 RCore *core = (RCore*) user;
1663 RConfigNode *node = (RConfigNode*) data;
1664 if (*node->value == '?') {
1665 r_debug_plugin_list (core->dbg, 'q');
1666 return false;
1667 }
1668 if (!strcmp (node->value, "bf")) {
1669 // hack
1670 r_config_set (core->config, "asm.arch", "bf");
1671 }
1672 r_debug_use (core->dbg, node->value);
1673 return true;
1674 }
1675
cb_gotolimit(void * user,void * data)1676 static bool cb_gotolimit(void *user, void *data) {
1677 RCore *core = (RCore *) user;
1678 RConfigNode *node = (RConfigNode*) data;
1679 if (r_sandbox_enable (0)) {
1680 eprintf ("Cannot change gotolimit\n");
1681 return false;
1682 }
1683 if (core->anal->esil) {
1684 core->anal->esil_goto_limit = node->i_value;
1685 }
1686 return true;
1687 }
1688
cb_esilverbose(void * user,void * data)1689 static bool cb_esilverbose (void *user, void *data) {
1690 RCore *core = (RCore *) user;
1691 RConfigNode *node = (RConfigNode*) data;
1692 if (core->anal->esil) {
1693 core->anal->esil->verbose = node->i_value;
1694 }
1695 return true;
1696 }
1697
cb_esilstackdepth(void * user,void * data)1698 static bool cb_esilstackdepth (void *user, void *data) {
1699 RConfigNode *node = (RConfigNode*) data;
1700 if (node->i_value < 3) {
1701 eprintf ("esil.stack.depth must be greater than 2\n");
1702 node->i_value = 32;
1703 }
1704 return true;
1705 }
1706
cb_fixrows(void * user,void * data)1707 static bool cb_fixrows(void *user, void *data) {
1708 RConfigNode *node = (RConfigNode *) data;
1709 r_cons_singleton ()->fix_rows = (int)node->i_value;
1710 return true;
1711 }
1712
cb_fixcolumns(void * user,void * data)1713 static bool cb_fixcolumns(void *user, void *data) {
1714 RConfigNode *node = (RConfigNode *) data;
1715 r_cons_singleton ()->fix_columns = atoi (node->value);
1716 return true;
1717 }
1718
cb_rows(void * user,void * data)1719 static bool cb_rows(void *user, void *data) {
1720 RConfigNode *node = (RConfigNode *) data;
1721 r_cons_singleton ()->force_rows = node->i_value;
1722 return true;
1723 }
1724
cb_cmd_hexcursor(void * user,void * data)1725 static bool cb_cmd_hexcursor(void *user, void *data) {
1726 RCore *core = (RCore *) user;
1727 RConfigNode *node = (RConfigNode *) data;
1728 core->print->cfmt = node->value;
1729 return true;
1730 }
1731
cb_hexcompact(void * user,void * data)1732 static bool cb_hexcompact(void *user, void *data) {
1733 RCore *core = (RCore *) user;
1734 RConfigNode *node = (RConfigNode *) data;
1735 if (node->i_value) {
1736 core->print->flags |= R_PRINT_FLAGS_COMPACT;
1737 } else {
1738 core->print->flags &= (~R_PRINT_FLAGS_COMPACT);
1739 }
1740 return true;
1741 }
1742
cb_hex_pairs(void * user,void * data)1743 static bool cb_hex_pairs(void *user, void *data) {
1744 RCore *core = (RCore *) user;
1745 RConfigNode *node = (RConfigNode *) data;
1746 core->print->pairs = node->i_value;
1747 return true;
1748 }
1749
cb_hex_section(void * user,void * data)1750 static bool cb_hex_section(void *user, void *data) {
1751 RCore *core = (RCore *) user;
1752 RConfigNode *node = (RConfigNode *) data;
1753 if (node->i_value) {
1754 core->print->flags |= R_PRINT_FLAGS_SECTION;
1755 } else {
1756 core->print->flags &= ~R_PRINT_FLAGS_SECTION;
1757 }
1758 return true;
1759 }
1760
cb_hex_align(void * user,void * data)1761 static bool cb_hex_align(void *user, void *data) {
1762 RCore *core = (RCore *) user;
1763 RConfigNode *node = (RConfigNode *) data;
1764 if (node->i_value) {
1765 core->print->flags |= R_PRINT_FLAGS_ALIGN;
1766 } else {
1767 core->print->flags &= ~R_PRINT_FLAGS_ALIGN;
1768 }
1769 return true;
1770 }
1771
cb_io_unalloc(void * user,void * data)1772 static bool cb_io_unalloc(void *user, void *data) {
1773 RCore *core = (RCore *) user;
1774 RConfigNode *node = (RConfigNode *) data;
1775 if (node->i_value) {
1776 core->print->flags |= R_PRINT_FLAGS_UNALLOC;
1777 } else {
1778 core->print->flags &= ~R_PRINT_FLAGS_UNALLOC;
1779 }
1780 return true;
1781 }
1782
cb_io_unalloc_ch(void * user,void * data)1783 static bool cb_io_unalloc_ch(void *user, void *data) {
1784 RCore *core = (RCore *) user;
1785 RConfigNode *node = (RConfigNode *) data;
1786 core->print->io_unalloc_ch = *node->value ? node->value[0] : ' ';
1787 return true;
1788 }
1789
cb_hex_header(void * user,void * data)1790 static bool cb_hex_header(void *user, void *data) {
1791 RCore *core = (RCore *) user;
1792 RConfigNode *node = (RConfigNode *) data;
1793 if (node->i_value) {
1794 core->print->flags |= R_PRINT_FLAGS_HEADER;
1795 } else {
1796 core->print->flags &= ~R_PRINT_FLAGS_HEADER;
1797 }
1798 return true;
1799 }
1800
cb_hex_bytes(void * user,void * data)1801 static bool cb_hex_bytes(void *user, void *data) {
1802 RCore *core = (RCore *) user;
1803 RConfigNode *node = (RConfigNode *) data;
1804 if (node->i_value) {
1805 core->print->flags &= ~R_PRINT_FLAGS_NONHEX;
1806 } else {
1807 core->print->flags |= R_PRINT_FLAGS_NONHEX;
1808 }
1809 return true;
1810 }
1811
cb_hex_ascii(void * user,void * data)1812 static bool cb_hex_ascii(void *user, void *data) {
1813 RCore *core = (RCore *) user;
1814 RConfigNode *node = (RConfigNode *) data;
1815 if (node->i_value) {
1816 core->print->flags &= ~R_PRINT_FLAGS_NONASCII;
1817 } else {
1818 core->print->flags |= R_PRINT_FLAGS_NONASCII;
1819 }
1820 return true;
1821 }
1822
cb_hex_style(void * user,void * data)1823 static bool cb_hex_style(void *user, void *data) {
1824 RCore *core = (RCore *) user;
1825 RConfigNode *node = (RConfigNode *) data;
1826 if (node->i_value) {
1827 core->print->flags |= R_PRINT_FLAGS_STYLE;
1828 } else {
1829 core->print->flags &= ~R_PRINT_FLAGS_STYLE;
1830 }
1831 return true;
1832 }
1833
cb_hex_hdroff(void * user,void * data)1834 static bool cb_hex_hdroff(void *user, void *data) {
1835 RCore *core = (RCore *) user;
1836 RConfigNode *node = (RConfigNode *) data;
1837 if (node->i_value) {
1838 core->print->flags |= R_PRINT_FLAGS_HDROFF;
1839 } else {
1840 core->print->flags &= ~R_PRINT_FLAGS_HDROFF;
1841 }
1842 return true;
1843 }
1844
cb_log_events(void * user,void * data)1845 static bool cb_log_events (void *user, void *data) {
1846 RCore *core = (RCore *) user;
1847 RConfigNode *node = (RConfigNode *) data;
1848 core->log_events = node->i_value;
1849 return true;
1850 }
1851
cb_hexcomments(void * user,void * data)1852 static bool cb_hexcomments(void *user, void *data) {
1853 RCore *core = (RCore *) user;
1854 RConfigNode *node = (RConfigNode *) data;
1855 if (node->i_value) {
1856 core->print->flags |= R_PRINT_FLAGS_COMMENT;
1857 } else {
1858 core->print->flags &= ~R_PRINT_FLAGS_COMMENT;
1859 }
1860 return true;
1861 }
1862
cb_iopcache(void * user,void * data)1863 static bool cb_iopcache(void *user, void *data) {
1864 RCore *core = (RCore *) user;
1865 RConfigNode *node = (RConfigNode *) data;
1866 if ((bool)node->i_value) {
1867 if (core) {
1868 r_config_set_b (core->config, "io.pcache.read", true);
1869 r_config_set_b (core->config, "io.pcache.write", true);
1870 }
1871 } else {
1872 if (core && core->io) {
1873 r_io_desc_cache_fini_all (core->io);
1874 r_config_set_b (core->config, "io.pcache.read", false);
1875 r_config_set_b (core->config, "io.pcache.write", false);
1876 }
1877 }
1878 return true;
1879 }
1880
cb_iopcacheread(void * user,void * data)1881 static bool cb_iopcacheread(void *user, void *data) {
1882 RCore *core = (RCore *) user;
1883 RConfigNode *node = (RConfigNode *) data;
1884 if ((bool)node->i_value) {
1885 if (core && core->io) {
1886 core->io->p_cache |= 1;
1887 }
1888 } else {
1889 if (core && core->io && core->io->p_cache) {
1890 core->io->p_cache &= 2;
1891 if (!(core->io->p_cache & 2)) {
1892 r_io_desc_cache_fini_all (core->io);
1893 r_config_set_b (core->config, "io.pcache", false);
1894 }
1895 }
1896 }
1897 return true;
1898 }
1899
cb_iopcachewrite(void * user,void * data)1900 static bool cb_iopcachewrite(void *user, void *data) {
1901 RCore *core = (RCore *) user;
1902 RConfigNode *node = (RConfigNode *) data;
1903 if ((bool)node->i_value) {
1904 if (core && core->io) {
1905 core->io->p_cache |= 2;
1906 }
1907 } else {
1908 if (core && core->io && core->io->p_cache) {
1909 core->io->p_cache &= 1;
1910 if (!(core->io->p_cache & 1)) {
1911 r_io_desc_cache_fini_all (core->io);
1912 r_config_set_b (core->config, "io.pcache", false);
1913 }
1914 }
1915 }
1916 return true;
1917 }
1918
r_core_esil_cmd(RAnalEsil * esil,const char * cmd,ut64 a1,ut64 a2)1919 R_API bool r_core_esil_cmd(RAnalEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
1920 if (cmd && *cmd) {
1921 RCore *core = esil->anal->user;
1922 r_core_cmdf (core, "%s %"PFMT64d" %" PFMT64d, cmd, a1, a2);
1923 return core->num->value;
1924 }
1925 return false;
1926 }
1927
cb_cmd_esil_ioer(void * user,void * data)1928 static bool cb_cmd_esil_ioer(void *user, void *data) {
1929 RCore *core = (RCore *) user;
1930 RConfigNode *node = (RConfigNode *) data;
1931 if (core && core->anal && core->anal->esil) {
1932 core->anal->esil->cmd = r_core_esil_cmd;
1933 free (core->anal->esil->cmd_ioer);
1934 core->anal->esil->cmd_ioer = strdup (node->value);
1935 }
1936 return true;
1937 }
1938
cb_cmd_esil_todo(void * user,void * data)1939 static bool cb_cmd_esil_todo(void *user, void *data) {
1940 RCore *core = (RCore *) user;
1941 RConfigNode *node = (RConfigNode *) data;
1942 if (core && core->anal && core->anal->esil) {
1943 core->anal->esil->cmd = r_core_esil_cmd;
1944 free (core->anal->esil->cmd_todo);
1945 core->anal->esil->cmd_todo = strdup (node->value);
1946 }
1947 return true;
1948 }
1949
cb_cmd_esil_intr(void * user,void * data)1950 static bool cb_cmd_esil_intr(void *user, void *data) {
1951 RCore *core = (RCore *) user;
1952 RConfigNode *node = (RConfigNode *) data;
1953 if (core && core->anal && core->anal->esil) {
1954 core->anal->esil->cmd = r_core_esil_cmd;
1955 free (core->anal->esil->cmd_intr);
1956 core->anal->esil->cmd_intr = strdup (node->value);
1957 }
1958 return true;
1959 }
1960
cb_mdevrange(void * user,void * data)1961 static bool cb_mdevrange(void *user, void *data) {
1962 RCore *core = (RCore *) user;
1963 RConfigNode *node = (RConfigNode *) data;
1964 if (core && core->anal && core->anal->esil) {
1965 core->anal->esil->cmd = r_core_esil_cmd;
1966 free (core->anal->esil->mdev_range);
1967 core->anal->esil->mdev_range = strdup (node->value);
1968 }
1969 return true;
1970 }
1971
cb_cmd_esil_step(void * user,void * data)1972 static bool cb_cmd_esil_step(void *user, void *data) {
1973 RCore *core = (RCore *) user;
1974 RConfigNode *node = (RConfigNode *) data;
1975 if (core && core->anal && core->anal->esil) {
1976 core->anal->esil->cmd = r_core_esil_cmd;
1977 free (core->anal->esil->cmd_step);
1978 core->anal->esil->cmd_step = strdup (node->value);
1979 }
1980 return true;
1981 }
1982
cb_cmd_esil_step_out(void * user,void * data)1983 static bool cb_cmd_esil_step_out(void *user, void *data) {
1984 RCore *core = (RCore *) user;
1985 RConfigNode *node = (RConfigNode *) data;
1986 if (core && core->anal && core->anal->esil) {
1987 core->anal->esil->cmd = r_core_esil_cmd;
1988 free (core->anal->esil->cmd_step_out);
1989 core->anal->esil->cmd_step_out = strdup (node->value);
1990 }
1991 return true;
1992 }
1993
cb_cmd_esil_mdev(void * user,void * data)1994 static bool cb_cmd_esil_mdev(void *user, void *data) {
1995 RCore *core = (RCore *) user;
1996 RConfigNode *node = (RConfigNode *) data;
1997 if (core && core->anal && core->anal->esil) {
1998 core->anal->esil->cmd = r_core_esil_cmd;
1999 free (core->anal->esil->cmd_mdev);
2000 core->anal->esil->cmd_mdev = strdup (node->value);
2001 }
2002 return true;
2003 }
2004
cb_cmd_esil_trap(void * user,void * data)2005 static bool cb_cmd_esil_trap(void *user, void *data) {
2006 RCore *core = (RCore *) user;
2007 RConfigNode *node = (RConfigNode *) data;
2008 if (core && core->anal && core->anal->esil) {
2009 core->anal->esil->cmd = r_core_esil_cmd;
2010 core->anal->esil->cmd_trap = strdup (node->value);
2011 }
2012 return true;
2013 }
2014
cb_fsview(void * user,void * data)2015 static bool cb_fsview(void *user, void *data) {
2016 int type = R_FS_VIEW_NORMAL;
2017 RCore *core = (RCore *) user;
2018 RConfigNode *node = (RConfigNode *) data;
2019 if (*node->value == '?') {
2020 print_node_options (node);
2021 return false;
2022 }
2023 if (!strcmp (node->value, "all")) {
2024 type = R_FS_VIEW_ALL;
2025 }
2026 if (!strstr (node->value, "del")) {
2027 type |= R_FS_VIEW_DELETED;
2028 }
2029 if (!strstr (node->value, "spe")) {
2030 type |= R_FS_VIEW_SPECIAL;
2031 }
2032 r_fs_view (core->fs, type);
2033 return true;
2034 }
2035
cb_cmddepth(void * user,void * data)2036 static bool cb_cmddepth(void *user, void *data) {
2037 RCore *core = (RCore *)user;
2038 int c = R_MAX (((RConfigNode*)data)->i_value, 0);
2039 core->max_cmd_depth = c;
2040 core->cons->context->cmd_depth = c;
2041 return true;
2042 }
2043
cb_hexcols(void * user,void * data)2044 static bool cb_hexcols(void *user, void *data) {
2045 RCore *core = (RCore *)user;
2046 int c = R_MIN (1024, R_MAX (((RConfigNode*)data)->i_value, 0));
2047 core->print->cols = c; // & ~1;
2048 core->dbg->regcols = c/4;
2049 return true;
2050 }
2051
cb_hexstride(void * user,void * data)2052 static bool cb_hexstride(void *user, void *data) {
2053 RConfigNode *node = (RConfigNode*) data;
2054 ((RCore *)user)->print->stride = node->i_value;
2055 return true;
2056 }
2057
cb_search_kwidx(void * user,void * data)2058 static bool cb_search_kwidx(void *user, void *data) {
2059 RCore *core = (RCore *) user;
2060 RConfigNode *node = (RConfigNode *) data;
2061 core->search->n_kws = node->i_value;
2062 return true;
2063 }
2064
cb_io_cache_mode(void * user,void * data)2065 static bool cb_io_cache_mode(void *user, void *data) {
2066 RCore *core = (RCore *)user;
2067 RConfigNode *node = (RConfigNode *)data;
2068 if (node->i_value) {
2069 core->io->cachemode = true;
2070 } else {
2071 core->io->cachemode = false;
2072 }
2073 return true;
2074 }
2075
cb_io_cache_read(void * user,void * data)2076 static bool cb_io_cache_read(void *user, void *data) {
2077 RCore *core = (RCore *)user;
2078 RConfigNode *node = (RConfigNode *)data;
2079 if (node->i_value) {
2080 core->io->cached |= R_PERM_R;
2081 } else {
2082 core->io->cached &= ~R_PERM_R;
2083 }
2084 return true;
2085 }
2086
cb_io_cache_write(void * user,void * data)2087 static bool cb_io_cache_write(void *user, void *data) {
2088 RCore *core = (RCore *)user;
2089 RConfigNode *node = (RConfigNode *)data;
2090 if (node->i_value) {
2091 core->io->cached |= R_PERM_W;
2092 } else {
2093 core->io->cached &= ~R_PERM_W;
2094 }
2095 return true;
2096 }
2097
cb_io_cache(void * user,void * data)2098 static bool cb_io_cache(void *user, void *data) {
2099 (void)cb_io_cache_read (user, data);
2100 (void)cb_io_cache_write (user, data);
2101 return true;
2102 }
2103
cb_ioaslr(void * user,void * data)2104 static bool cb_ioaslr(void *user, void *data) {
2105 RCore *core = (RCore *) user;
2106 RConfigNode *node = (RConfigNode *) data;
2107 if (node->i_value != core->io->aslr) {
2108 core->io->aslr = node->i_value;
2109 }
2110 return true;
2111 }
2112
cb_io_pava(void * user,void * data)2113 static bool cb_io_pava(void *user, void *data) {
2114 RCore *core = (RCore *) user;
2115 RConfigNode *node = (RConfigNode *) data;
2116 core->print->pava = node->i_value;
2117 if (node->i_value && core->io->va) {
2118 eprintf ("WARNING: You may probably want to disable io.va too\n");
2119 }
2120 return true;
2121 }
2122
cb_iova(void * user,void * data)2123 static bool cb_iova(void *user, void *data) {
2124 RCore *core = (RCore *) user;
2125 RConfigNode *node = (RConfigNode *) data;
2126 if (node->i_value != core->io->va) {
2127 core->io->va = node->i_value;
2128 /* ugly fix for r2 -d ... "r2 is going to die soon ..." */
2129 if (core->io->desc) {
2130 r_core_block_read (core);
2131 }
2132 #if 0
2133 /* reload symbol information */
2134 if (r_list_length (r_bin_get_sections (core->bin)) > 0) {
2135 r_core_cmd0 (core, ".ia*");
2136 }
2137 #endif
2138 }
2139 return true;
2140 }
2141
cb_ioff(void * user,void * data)2142 static bool cb_ioff(void *user, void *data) {
2143 RCore *core = (RCore *) user;
2144 RConfigNode *node = (RConfigNode *) data;
2145 core->io->ff = node->i_value;
2146 return true;
2147 }
2148
cb_io_oxff(void * user,void * data)2149 static bool cb_io_oxff(void *user, void *data) {
2150 RCore *core = (RCore *) user;
2151 RConfigNode *node = (RConfigNode *) data;
2152 core->io->Oxff = node->i_value;
2153 return true;
2154 }
2155
cb_ioautofd(void * user,void * data)2156 static bool cb_ioautofd(void *user, void *data) {
2157 RCore *core = (RCore *) user;
2158 RConfigNode *node = (RConfigNode *) data;
2159 core->io->autofd = node->i_value;
2160 return true;
2161 }
2162
cb_scr_color_grep(void * user,void * data)2163 static bool cb_scr_color_grep(void *user, void *data) {
2164 RCore *core = (RCore *) user;
2165 RConfigNode *node = (RConfigNode *) data;
2166
2167 /* Let cons know we have a new pager. */
2168 core->cons->grep_color = node->i_value;
2169 return true;
2170 }
2171
cb_scr_color_grep_highlight(void * user,void * data)2172 static bool cb_scr_color_grep_highlight(void *user, void *data) {
2173 RCore *core = (RCore *) user;
2174 RConfigNode *node = (RConfigNode *) data;
2175 core->cons->grep_highlight = node->i_value;
2176 return true;
2177 }
2178
cb_pager(void * user,void * data)2179 static bool cb_pager(void *user, void *data) {
2180 RCore *core = (RCore *) user;
2181 RConfigNode *node = (RConfigNode *) data;
2182 if (*node->value == '?') {
2183 eprintf ("Usage: scr.pager must be '..' for internal less, or the path to a program in $PATH");
2184 return false;
2185 }
2186 /* Let cons know we have a new pager. */
2187 free (core->cons->pager);
2188 core->cons->pager = strdup (node->value);
2189 return true;
2190 }
2191
cb_breaklines(void * user,void * data)2192 static bool cb_breaklines(void *user, void *data) {
2193 RConfigNode *node = (RConfigNode *) data;
2194 r_cons_singleton ()->break_lines = node->i_value;
2195 return true;
2196 }
2197
cb_scr_gadgets(void * user,void * data)2198 static bool cb_scr_gadgets(void *user, void *data) {
2199 RCore *core = (RCore*) user;
2200 RConfigNode *node = (RConfigNode *) data;
2201 core->scr_gadgets = node->i_value;
2202 return true;
2203 }
2204
cb_fps(void * user,void * data)2205 static bool cb_fps(void *user, void *data) {
2206 RConfigNode *node = (RConfigNode *) data;
2207 r_cons_singleton ()->fps = node->i_value;
2208 return true;
2209 }
2210
cb_scrbreakword(void * user,void * data)2211 static bool cb_scrbreakword(void* user, void* data) {
2212 RConfigNode *node = (RConfigNode*) data;
2213 if (*node->value) {
2214 r_cons_breakword (node->value);
2215 } else {
2216 r_cons_breakword (NULL);
2217 }
2218 return true;
2219 }
2220
cb_scrcolumns(void * user,void * data)2221 static bool cb_scrcolumns(void* user, void* data) {
2222 RConfigNode *node = (RConfigNode*) data;
2223 RCore *core = (RCore*) user;
2224 int n = atoi (node->value);
2225 core->cons->force_columns = n;
2226 core->dbg->regcols = n / 20;
2227 return true;
2228 }
2229
cb_scrfgets(void * user,void * data)2230 static bool cb_scrfgets(void* user, void* data) {
2231 RCore *core = (RCore *) user;
2232 RConfigNode *node = (RConfigNode*) data;
2233 core->cons->user_fgets = node->i_value
2234 ? NULL : (void *)r_core_fgets;
2235 return true;
2236 }
2237
cb_scrhtml(void * user,void * data)2238 static bool cb_scrhtml(void *user, void *data) {
2239 RConfigNode *node = (RConfigNode *) data;
2240 r_cons_singleton ()->is_html = node->i_value;
2241 // TODO: control error and restore old value (return false?) show errormsg?
2242 return true;
2243 }
2244
cb_newshell(void * user,void * data)2245 static bool cb_newshell(void *user, void *data) {
2246 RConfigNode *node = (RConfigNode *)data;
2247 RCore *core = (RCore *)user;
2248 core->use_tree_sitter_r2cmd = node->i_value;
2249 return true;
2250 }
2251
cb_scrhighlight(void * user,void * data)2252 static bool cb_scrhighlight(void *user, void *data) {
2253 RConfigNode *node = (RConfigNode *) data;
2254 r_cons_highlight (node->value);
2255 return true;
2256 }
2257
2258 #if __WINDOWS__
scr_vtmode(void * user,void * data)2259 static bool scr_vtmode(void *user, void *data) {
2260 RConfigNode *node = (RConfigNode *) data;
2261 if (r_str_is_true (node->value)) {
2262 node->i_value = 1;
2263 }
2264 node->i_value = node->i_value > 2 ? 2 : node->i_value;
2265 r_line_singleton ()->vtmode = r_cons_singleton ()->vtmode = node->i_value;
2266
2267 DWORD mode;
2268 HANDLE input = GetStdHandle (STD_INPUT_HANDLE);
2269 GetConsoleMode (input, &mode);
2270 if (node->i_value == 2) {
2271 SetConsoleMode (input, mode & ENABLE_VIRTUAL_TERMINAL_INPUT);
2272 r_cons_singleton ()->term_raw = ENABLE_VIRTUAL_TERMINAL_INPUT;
2273 } else {
2274 SetConsoleMode (input, mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT);
2275 r_cons_singleton ()->term_raw = 0;
2276 }
2277 HANDLE streams[] = { GetStdHandle (STD_OUTPUT_HANDLE), GetStdHandle (STD_ERROR_HANDLE) };
2278 int i;
2279 if (node->i_value > 0) {
2280 for (i = 0; i < R_ARRAY_SIZE (streams); i++) {
2281 GetConsoleMode (streams[i], &mode);
2282 SetConsoleMode (streams[i],
2283 mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
2284 }
2285 } else {
2286 for (i = 0; i < R_ARRAY_SIZE (streams); i++) {
2287 GetConsoleMode (streams[i], &mode);
2288 SetConsoleMode (streams[i],
2289 mode & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING & ~ENABLE_WRAP_AT_EOL_OUTPUT);
2290 }
2291 }
2292 return true;
2293 }
2294 #endif
2295
cb_screcho(void * user,void * data)2296 static bool cb_screcho(void *user, void *data) {
2297 RConfigNode *node = (RConfigNode *) data;
2298 r_cons_singleton ()->echo = node->i_value;
2299 return true;
2300 }
2301
cb_scrlinesleep(void * user,void * data)2302 static bool cb_scrlinesleep(void *user, void *data) {
2303 RConfigNode *node = (RConfigNode *) data;
2304 r_cons_singleton ()->linesleep = node->i_value;
2305 return true;
2306 }
2307
cb_scrpagesize(void * user,void * data)2308 static bool cb_scrpagesize(void *user, void *data) {
2309 RConfigNode *node = (RConfigNode *) data;
2310 r_cons_singleton ()->pagesize= node->i_value;
2311 return true;
2312 }
2313
cb_scrflush(void * user,void * data)2314 static bool cb_scrflush(void *user, void *data) {
2315 RConfigNode *node = (RConfigNode *) data;
2316 r_cons_singleton ()->flush = node->i_value;
2317 return true;
2318 }
2319
cb_scrstrconv(void * user,void * data)2320 static bool cb_scrstrconv(void *user, void *data) {
2321 RCore *core = (RCore*) user;
2322 RConfigNode *node = (RConfigNode*) data;
2323 if (*node->value == '?') {
2324 if (strlen (node->value) > 1 && node->value[1] == '?') {
2325 r_cons_printf ("Valid values for scr.strconv:\n"
2326 " asciiesc convert to ascii with non-ascii chars escaped\n"
2327 " asciidot convert to ascii with non-ascii chars turned into a dot (except control chars stated below)\n"
2328 "\n"
2329 "Ascii chars are in the range 0x20-0x7e. Always escaped control chars are alert (\\a),\n"
2330 "backspace (\\b), formfeed (\\f), newline (\\n), carriage return (\\r), horizontal tab (\\t)\n"
2331 "and vertical tab (\\v). Also, double quotes (\\\") are always escaped, but backslashes (\\\\)\n"
2332 "are only escaped if str.escbslash = true.\n");
2333 } else {
2334 print_node_options (node);
2335 }
2336 return false;
2337 } else {
2338 free ((char *)core->print->strconv_mode);
2339 core->print->strconv_mode = strdup (node->value);
2340 }
2341 return true;
2342 }
2343
cb_graphformat(void * user,void * data)2344 static bool cb_graphformat(void *user, void *data) {
2345 RConfigNode *node = (RConfigNode *) data;
2346 if (*node->value == '?') {
2347 r_cons_printf ("png\njpg\npdf\nps\nsvg\njson\n");
2348 return false;
2349 }
2350 return true;
2351 }
2352
cb_exectrap(void * user,void * data)2353 static bool cb_exectrap(void *user, void *data) {
2354 RConfigNode *node = (RConfigNode *) data;
2355 RCore *core = (RCore*) user;
2356 if (core->anal && core->anal->esil) {
2357 core->anal->esil->exectrap = node->i_value;
2358 }
2359 return true;
2360 }
2361
cb_iotrap(void * user,void * data)2362 static bool cb_iotrap(void *user, void *data) {
2363 RConfigNode *node = (RConfigNode *) data;
2364 RCore *core = (RCore*) user;
2365 if (core->anal && core->anal->esil) {
2366 core->anal->esil->iotrap = node->i_value;
2367 }
2368 return true;
2369 }
2370
cb_scr_bgfill(void * user,void * data)2371 static bool cb_scr_bgfill(void *user, void *data) {
2372 RCore *core = (RCore*) user;
2373 RConfigNode *node = (RConfigNode *) data;
2374 if (node->i_value) {
2375 core->print->flags |= R_PRINT_FLAGS_BGFILL;
2376 } else {
2377 core->print->flags &= (~R_PRINT_FLAGS_BGFILL);
2378 }
2379 r_print_set_flags (core->print, core->print->flags);
2380 return true;
2381 }
2382
cb_scrint(void * user,void * data)2383 static bool cb_scrint(void *user, void *data) {
2384 RConfigNode *node = (RConfigNode *) data;
2385 if (node->i_value && r_sandbox_enable (0)) {
2386 return false;
2387 }
2388 r_cons_singleton ()->context->is_interactive = node->i_value;
2389 return true;
2390 }
2391
cb_scrnkey(void * user,void * data)2392 static bool cb_scrnkey(void *user, void *data) {
2393 RConfigNode *node = (RConfigNode*) data;
2394 if (!strcmp (node->value, "help") || *node->value == '?') {
2395 print_node_options (node);
2396 return false;
2397 }
2398 return true;
2399 }
2400
cb_scr_histblock(void * user,void * data)2401 static bool cb_scr_histblock(void *user, void *data) {
2402 RCore *core = (RCore *) user;
2403 RConfigNode *node = (RConfigNode *) data;
2404 core->print->histblock = node->i_value;
2405 return true;
2406 }
2407
cb_scrprompt(void * user,void * data)2408 static bool cb_scrprompt(void *user, void *data) {
2409 RCore *core = (RCore *)user;
2410 RConfigNode *node = (RConfigNode *) data;
2411 core->print->scr_prompt = node->i_value;
2412 r_line_singleton ()->echo = node->i_value;
2413 return true;
2414 }
2415
cb_scrrows(void * user,void * data)2416 static bool cb_scrrows(void* user, void* data) {
2417 RConfigNode *node = (RConfigNode*) data;
2418 int n = atoi (node->value);
2419 ((RCore *)user)->cons->force_rows = n;
2420 return true;
2421 }
2422
cb_contiguous(void * user,void * data)2423 static bool cb_contiguous(void *user, void *data) {
2424 RCore *core = (RCore *)user;
2425 RConfigNode *node = (RConfigNode *) data;
2426 core->search->contiguous = node->i_value;
2427 return true;
2428 }
2429
cb_searchalign(void * user,void * data)2430 static bool cb_searchalign(void *user, void *data) {
2431 RCore *core = (RCore *)user;
2432 RConfigNode *node = (RConfigNode *) data;
2433 core->search->align = node->i_value;
2434 core->print->addrmod = node->i_value;
2435 return true;
2436 }
2437
cb_segoff(void * user,void * data)2438 static bool cb_segoff(void *user, void *data) {
2439 RCore *core = (RCore *) user;
2440 RConfigNode *node = (RConfigNode *) data;
2441 if (node->i_value) {
2442 core->print->flags |= R_PRINT_FLAGS_SEGOFF;
2443 } else {
2444 core->print->flags &= (((ut32)-1) & (~R_PRINT_FLAGS_SEGOFF));
2445 }
2446 return true;
2447 }
2448
cb_seggrn(void * user,void * data)2449 static bool cb_seggrn(void *user, void *data) {
2450 RCore *core = (RCore *) user;
2451 RConfigNode *node = (RConfigNode *) data;
2452 core->rasm->seggrn = node->i_value;
2453 core->anal->seggrn = node->i_value;
2454 core->print->seggrn = node->i_value;
2455 return true;
2456 }
2457
cb_stopthreads(void * user,void * data)2458 static bool cb_stopthreads(void *user, void *data) {
2459 RCore *core = (RCore *) user;
2460 RConfigNode *node = (RConfigNode *) data;
2461 core->dbg->stop_all_threads = node->i_value;
2462 return true;
2463 }
2464
cb_scr_prompt_popup(void * user,void * data)2465 static bool cb_scr_prompt_popup(void *user, void *data) {
2466 RCore *core = (RCore *) user;
2467 RConfigNode *node = (RConfigNode *) data;
2468 core->cons->show_autocomplete_widget = node->i_value;
2469 return true;
2470 }
2471
cb_swstep(void * user,void * data)2472 static bool cb_swstep(void *user, void *data) {
2473 RCore *core = (RCore *) user;
2474 RConfigNode *node = (RConfigNode *) data;
2475 core->dbg->swstep = node->i_value;
2476 return true;
2477 }
2478
cb_consbreak(void * user,void * data)2479 static bool cb_consbreak(void *user, void *data) {
2480 RCore *core = (RCore *) user;
2481 RConfigNode *node = (RConfigNode *) data;
2482 core->dbg->consbreak = node->i_value;
2483 return true;
2484 }
2485
cb_teefile(void * user,void * data)2486 static bool cb_teefile(void *user, void *data) {
2487 RConfigNode *node = (RConfigNode *) data;
2488 r_cons_singleton ()->teefile = node->value;
2489 return true;
2490 }
2491
cb_trace(void * user,void * data)2492 static bool cb_trace(void *user, void *data) {
2493 RCore *core = (RCore *) user;
2494 RConfigNode *node = (RConfigNode *) data;
2495 core->dbg->trace->enabled = node->i_value;
2496 return true;
2497 }
2498
cb_tracetag(void * user,void * data)2499 static bool cb_tracetag(void *user, void *data) {
2500 RCore *core = (RCore *) user;
2501 RConfigNode *node = (RConfigNode *) data;
2502 core->dbg->trace->tag = node->i_value;
2503 return true;
2504 }
2505
cb_utf8(void * user,void * data)2506 static bool cb_utf8(void *user, void *data) {
2507 RConfigNode *node = (RConfigNode *) data;
2508 r_cons_set_utf8 ((bool)node->i_value);
2509 return true;
2510 }
2511
cb_utf8_curvy(void * user,void * data)2512 static bool cb_utf8_curvy(void *user, void *data) {
2513 RCore *core = (RCore *) user;
2514 RConfigNode *node = (RConfigNode *) data;
2515 core->cons->use_utf8_curvy = node->i_value;
2516 return true;
2517 }
2518
cb_dotted(void * user,void * data)2519 static bool cb_dotted(void *user, void *data) {
2520 RCore *core = (RCore *) user;
2521 RConfigNode *node = (RConfigNode *) data;
2522 core->cons->dotted_lines = node->i_value;
2523 return true;
2524 }
2525
cb_zoombyte(void * user,void * data)2526 static bool cb_zoombyte(void *user, void *data) {
2527 RCore *core = (RCore *) user;
2528 RConfigNode *node = (RConfigNode *) data;
2529 switch (*node->value) {
2530 case 'p': case 'f': case 's': case '0':
2531 case 'F': case 'e': case 'h':
2532 core->print->zoom->mode = *node->value;
2533 break;
2534 default:
2535 eprintf ("Invalid zoom.byte value. See pz? for help\n");
2536 r_cons_printf ("pzp\npzf\npzs\npz0\npzF\npze\npzh\n");
2537 return false;
2538 }
2539 return true;
2540 }
2541
cb_analverbose(void * user,void * data)2542 static bool cb_analverbose(void *user, void *data) {
2543 RCore *core = (RCore *) user;
2544 RConfigNode *node = (RConfigNode *) data;
2545 core->anal->verbose = node->i_value;
2546 return true;
2547 }
2548
cb_binverbose(void * user,void * data)2549 static bool cb_binverbose(void *user, void *data) {
2550 RCore *core = (RCore *) user;
2551 RConfigNode *node = (RConfigNode *) data;
2552 core->bin->verbose = node->i_value;
2553 return true;
2554 }
2555
cb_prjname(void * user,void * data)2556 static bool cb_prjname(void *user, void *data) {
2557 RCore *core = (RCore *) user;
2558 RConfigNode *node = (RConfigNode *) data;
2559 const char *prjname = node->value;
2560 if (*prjname == '?') {
2561 r_core_project_list (core, 0);
2562 return false;
2563 }
2564 if (r_project_is_loaded (core->prj)) {
2565 if (*prjname) {
2566 if (!strcmp (prjname, core->prj->name)) {
2567 return true;
2568 }
2569 if (r_project_rename (core->prj, prjname)) {
2570 return true;
2571 }
2572 eprintf ("Cannot rename project.\n");
2573 } else {
2574 r_project_close (core->prj);
2575 }
2576 } else {
2577 if (*prjname) {
2578 if (r_project_open (core->prj, prjname, NULL)) {
2579 return true;
2580 }
2581 eprintf ("Cannot open project.\n");
2582 }
2583 }
2584 return false;
2585 }
2586
cb_rawstr(void * user,void * data)2587 static bool cb_rawstr(void *user, void *data) {
2588 RCore *core = (RCore *) user;
2589 RConfigNode *node = (RConfigNode *) data;
2590 core->bin->rawstr = node->i_value;
2591 return true;
2592 }
2593
cb_debase64(void * user,void * data)2594 static bool cb_debase64(void *user, void *data) {
2595 RCore *core = (RCore *) user;
2596 RConfigNode *node = (RConfigNode *) data;
2597 core->bin->debase64 = node->i_value;
2598 return true;
2599 }
2600
cb_binstrings(void * user,void * data)2601 static bool cb_binstrings(void *user, void *data) {
2602 const ut32 req = R_BIN_REQ_STRINGS;
2603 RCore *core = (RCore *) user;
2604 RConfigNode *node = (RConfigNode *) data;
2605 if (node->i_value) {
2606 core->bin->filter_rules |= req;
2607 } else {
2608 core->bin->filter_rules &= ~req;
2609 }
2610 return true;
2611 }
2612
cb_bindbginfo(void * user,void * data)2613 static bool cb_bindbginfo(void *user, void *data) {
2614 RCore *core = (RCore *) user;
2615 RConfigNode *node = (RConfigNode *) data;
2616 if (!core || !core->bin) {
2617 return false;
2618 }
2619 core->bin->want_dbginfo = node->i_value;
2620 return true;
2621 }
2622
cb_binprefix(void * user,void * data)2623 static bool cb_binprefix(void *user, void *data) {
2624 RCore *core = (RCore *) user;
2625 RConfigNode *node = (RConfigNode *) data;
2626 if (!core || !core->bin) {
2627 return false;
2628 }
2629 if (node->value && *node->value) {
2630 if (!strcmp (node->value, "auto")) {
2631 if (!core->bin->file) {
2632 return false;
2633 }
2634 char *name = (char *)r_file_basename (core->bin->file);
2635 if (name) {
2636 r_name_filter (name, strlen (name));
2637 r_str_filter (name, strlen (name));
2638 core->bin->prefix = strdup (name);
2639 free (name);
2640 }
2641 } else {
2642 core->bin->prefix = node->value;
2643 }
2644 }
2645 return true;
2646 }
2647
cb_binmaxstrbuf(void * user,void * data)2648 static bool cb_binmaxstrbuf(void *user, void *data) {
2649 RCore *core = (RCore *) user;
2650 RConfigNode *node = (RConfigNode *) data;
2651 if (core->bin) {
2652 int v = node->i_value;
2653 ut64 old_v = core->bin->maxstrbuf;
2654 if (v < 1) {
2655 v = 4; // HACK
2656 }
2657 core->bin->maxstrbuf = v;
2658 if (v>old_v) {
2659 r_bin_reset_strings (core->bin);
2660 }
2661 return true;
2662 }
2663 return true;
2664 }
2665
cb_binmaxstr(void * user,void * data)2666 static bool cb_binmaxstr(void *user, void *data) {
2667 RCore *core = (RCore *) user;
2668 RConfigNode *node = (RConfigNode *) data;
2669 if (core->bin) {
2670 int v = node->i_value;
2671 if (v < 1) {
2672 v = 4; // HACK
2673 }
2674 core->bin->maxstrlen = v;
2675 r_bin_reset_strings (core->bin);
2676 return true;
2677 }
2678 return true;
2679 }
2680
cb_binminstr(void * user,void * data)2681 static bool cb_binminstr(void *user, void *data) {
2682 RCore *core = (RCore *) user;
2683 RConfigNode *node = (RConfigNode *) data;
2684 if (core->bin) {
2685 int v = node->i_value;
2686 if (v < 1) {
2687 v = 4; // HACK
2688 }
2689 core->bin->minstrlen = v;
2690 r_bin_reset_strings (core->bin);
2691 return true;
2692 }
2693 return true;
2694 }
2695
cb_searchin(void * user,void * data)2696 static bool cb_searchin(void *user, void *data) {
2697 RCore *core = (RCore*)user;
2698 RConfigNode *node = (RConfigNode*) data;
2699 if (*node->value == '?') {
2700 if (strlen (node->value) > 1 && node->value[1] == '?') {
2701 r_cons_printf ("Valid values for search.in (depends on .from/.to and io.va):\n"
2702 "raw search in raw io (ignoring bounds)\n"
2703 "block search in the current block\n"
2704 "io.map search in current map\n"
2705 "io.sky.[rwx] search in all skyline segments\n"
2706 "io.maps search in all maps\n"
2707 "io.maps.[rwx] search in all r-w-x io maps\n"
2708 "bin.segment search in current mapped segment\n"
2709 "bin.segments search in all mapped segments\n"
2710 "bin.segments.[rwx] search in all r-w-x segments\n"
2711 "bin.section search in current mapped section\n"
2712 "bin.sections search in all mapped sections\n"
2713 "bin.sections.[rwx] search in all r-w-x sections\n"
2714 "dbg.stack search in the stack\n"
2715 "dbg.heap search in the heap\n"
2716 "dbg.map search in current memory map\n"
2717 "dbg.maps search in all memory maps\n"
2718 "dbg.maps.[rwx] search in all executable marked memory maps\n"
2719 "anal.fcn search in the current function\n"
2720 "anal.bb search in the current basic-block\n");
2721 } else {
2722 print_node_options (node);
2723 }
2724 return false;
2725 }
2726 // Set anal.noncode if exec bit set in anal.in
2727 if (r_str_startswith (node->name, "anal")) {
2728 core->anal->opt.noncode = (strchr (node->value, 'x') == NULL);
2729 }
2730 return true;
2731 }
2732
__dbg_swstep_getter(void * user,RConfigNode * node)2733 static int __dbg_swstep_getter(void *user, RConfigNode *node) {
2734 RCore *core = (RCore*)user;
2735 node->i_value = core->dbg->swstep;
2736 return true;
2737 }
2738
cb_dirpfx(RCore * core,RConfigNode * node)2739 static bool cb_dirpfx(RCore *core, RConfigNode *node) {
2740 r_sys_prefix (node->value);
2741 return true;
2742 }
2743
cb_analsyscc(RCore * core,RConfigNode * node)2744 static bool cb_analsyscc(RCore *core, RConfigNode *node) {
2745 if (core && core->anal) {
2746 if (*node->value == '?') {
2747 r_core_cmd0 (core, "afcl");
2748 return false;
2749 }
2750 r_anal_set_syscc_default (core->anal, node->value);
2751 }
2752 return true;
2753 }
2754
cb_analcc_getter(RCore * core,RConfigNode * node)2755 static bool cb_analcc_getter(RCore *core, RConfigNode *node) {
2756 const char *cc = r_anal_cc_default (core->anal);
2757 if (cc) {
2758 free (node->value);
2759 node->value = strdup (cc);
2760 }
2761 return true;
2762 }
2763
cb_analcc(RCore * core,RConfigNode * node)2764 static bool cb_analcc(RCore *core, RConfigNode *node) {
2765 if (core && core->anal) {
2766 node->getter = (RConfigCallback)cb_analcc_getter;
2767 if (*node->value == '?') {
2768 r_core_cmd0 (core, "afcl");
2769 return false;
2770 }
2771 r_anal_set_cc_default (core->anal, node->value);
2772 }
2773 return true;
2774 }
2775
cb_anal_roregs(RCore * core,RConfigNode * node)2776 static bool cb_anal_roregs(RCore *core, RConfigNode *node) {
2777 if (core && core->anal && core->anal->reg) {
2778 r_list_free (core->anal->reg->roregs);
2779 core->anal->reg->roregs = r_str_split_duplist (node->value, ",", true);
2780 }
2781 return true;
2782 }
2783
cb_anal_gp(RCore * core,RConfigNode * node)2784 static bool cb_anal_gp(RCore *core, RConfigNode *node) {
2785 core->anal->gp = node->i_value;
2786 return true;
2787 }
2788
cb_anal_from(RCore * core,RConfigNode * node)2789 static bool cb_anal_from(RCore *core, RConfigNode *node) {
2790 if (r_config_get_i (core->config, "anal.limits")) {
2791 r_anal_set_limits (core->anal,
2792 r_config_get_i (core->config, "anal.from"),
2793 r_config_get_i (core->config, "anal.to"));
2794 }
2795 return true;
2796 }
2797
cb_anal_limits(void * user,RConfigNode * node)2798 static bool cb_anal_limits(void *user, RConfigNode *node) {
2799 RCore *core = (RCore*)user;
2800 if (node->i_value) {
2801 r_anal_set_limits (core->anal,
2802 r_config_get_i (core->config, "anal.from"),
2803 r_config_get_i (core->config, "anal.to"));
2804 } else {
2805 r_anal_unset_limits (core->anal);
2806 }
2807 return 1;
2808 }
2809
cb_anal_rnr(void * user,RConfigNode * node)2810 static bool cb_anal_rnr(void *user, RConfigNode *node) {
2811 RCore *core = (RCore*)user;
2812 core->anal->recursive_noreturn = node->i_value;
2813 return 1;
2814 }
2815
cb_anal_jmptbl(void * user,void * data)2816 static bool cb_anal_jmptbl(void *user, void *data) {
2817 RCore *core = (RCore*) user;
2818 RConfigNode *node = (RConfigNode*) data;
2819 core->anal->opt.jmptbl = node->i_value;
2820 return true;
2821 }
2822
cb_anal_cjmpref(void * user,void * data)2823 static bool cb_anal_cjmpref(void *user, void *data) {
2824 RCore *core = (RCore*) user;
2825 RConfigNode *node = (RConfigNode*) data;
2826 core->anal->opt.cjmpref = node->i_value;
2827 return true;
2828 }
2829
cb_anal_jmpref(void * user,void * data)2830 static bool cb_anal_jmpref(void *user, void *data) {
2831 RCore *core = (RCore*) user;
2832 RConfigNode *node = (RConfigNode*) data;
2833 core->anal->opt.jmpref = node->i_value;
2834 return true;
2835 }
2836
cb_anal_jmpabove(void * user,void * data)2837 static bool cb_anal_jmpabove(void *user, void *data) {
2838 RCore *core = (RCore*) user;
2839 RConfigNode *node = (RConfigNode*) data;
2840 core->anal->opt.jmpabove = node->i_value;
2841 return true;
2842 }
2843
cb_anal_loads(void * user,void * data)2844 static bool cb_anal_loads(void *user, void *data) {
2845 RCore *core = (RCore*) user;
2846 RConfigNode *node = (RConfigNode*) data;
2847 core->anal->opt.loads = node->i_value;
2848 return true;
2849 }
2850
cb_anal_followdatarefs(void * user,void * data)2851 static bool cb_anal_followdatarefs(void *user, void *data) {
2852 RCore *core = (RCore*) user;
2853 RConfigNode *node = (RConfigNode*) data;
2854 core->anal->opt.followdatarefs = node->i_value;
2855 return true;
2856 }
2857
cb_anal_jmpmid(void * user,void * data)2858 static bool cb_anal_jmpmid(void *user, void *data) {
2859 RCore *core = (RCore*) user;
2860 RConfigNode *node = (RConfigNode*) data;
2861 core->anal->opt.jmpmid = node->i_value;
2862 return true;
2863 }
2864
cb_anal_searchstringrefs(void * user,void * data)2865 static bool cb_anal_searchstringrefs(void *user, void *data) {
2866 RCore *core = (RCore*) user;
2867 RConfigNode *node = (RConfigNode*) data;
2868 core->anal->opt.searchstringrefs = node->i_value;
2869 return true;
2870 }
2871
cb_anal_pushret(void * user,void * data)2872 static bool cb_anal_pushret(void *user, void *data) {
2873 RCore *core = (RCore*) user;
2874 RConfigNode *node = (RConfigNode*) data;
2875 core->anal->opt.pushret = node->i_value;
2876 return true;
2877 }
2878
cb_anal_brokenrefs(void * user,void * data)2879 static bool cb_anal_brokenrefs(void *user, void *data) {
2880 RCore *core = (RCore*) user;
2881 RConfigNode *node = (RConfigNode*) data;
2882 core->anal->opt.followbrokenfcnsrefs = node->i_value;
2883 return true;
2884 }
2885
cb_anal_trycatch(void * user,void * data)2886 static bool cb_anal_trycatch(void *user, void *data) {
2887 RCore *core = (RCore*) user;
2888 RConfigNode *node = (RConfigNode*) data;
2889 core->anal->opt.trycatch = node->i_value;
2890 return true;
2891 }
2892
cb_anal_bb_max_size(void * user,void * data)2893 static bool cb_anal_bb_max_size(void *user, void *data) {
2894 RCore *core = (RCore*) user;
2895 RConfigNode *node = (RConfigNode*) data;
2896 core->anal->opt.bb_max_size = node->i_value;
2897 return true;
2898 }
2899
cb_anal_cpp_abi(void * user,void * data)2900 static bool cb_anal_cpp_abi(void *user, void *data) {
2901 RCore *core = (RCore*) user;
2902 RConfigNode *node = (RConfigNode*) data;
2903
2904 if (*node->value == '?') {
2905 print_node_options (node);
2906 return false;
2907 }
2908
2909 if (*node->value) {
2910 if (strcmp (node->value, "itanium") == 0) {
2911 core->anal->cpp_abi = R_ANAL_CPP_ABI_ITANIUM;
2912 return true;
2913 } else if (strcmp (node->value, "msvc") == 0) {
2914 core->anal->cpp_abi = R_ANAL_CPP_ABI_MSVC;
2915 return true;
2916 }
2917 eprintf ("anal.cpp.abi: cannot find '%s'\n", node->value);
2918 }
2919 return false;
2920 }
2921
cb_linesto(void * user,void * data)2922 static bool cb_linesto(void *user, void *data) {
2923 RCore *core = (RCore*) user;
2924 RConfigNode *node = (RConfigNode*) data;
2925 ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
2926 int io_sz = r_io_size (core->io);
2927 ut64 to = r_num_math (core->num, node->value);
2928 if (to == 0) {
2929 core->print->lines_cache_sz = -1; //r_core_lines_initcache (core, from, to);
2930 return true;
2931 }
2932 if (to > from + io_sz) {
2933 eprintf ("ERROR: \"lines.to\" can't exceed addr 0x%08"PFMT64x
2934 " 0x%08"PFMT64x" %d\n", from, to, io_sz);
2935 return true;
2936 }
2937 if (to > from) {
2938 core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
2939 //if (core->print->lines_cache_sz == -1) { eprintf ("ERROR: Can't allocate memory\n"); }
2940 } else {
2941 eprintf ("Invalid range 0x%08"PFMT64x" .. 0x%08"PFMT64x"\n", from, to);
2942 }
2943 return true;
2944 }
2945
cb_linesabs(void * user,void * data)2946 static bool cb_linesabs(void *user, void *data) {
2947 RCore *core = (RCore*) user;
2948 RConfigNode *node = (RConfigNode*) data;
2949 core->print->lines_abs = node->i_value;
2950 if (core->print->lines_abs && core->print->lines_cache_sz <= 0) {
2951 ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
2952 const char *to_str = r_config_get (core->config, "lines.to");
2953 ut64 to = r_num_math (core->num, (to_str && *to_str) ? to_str : "$s");
2954 core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
2955 if (core->print->lines_cache_sz == -1) {
2956 eprintf ("ERROR: \"lines.from\" and \"lines.to\" must be set\n");
2957 } else {
2958 eprintf ("Found %d lines\n", core->print->lines_cache_sz-1);
2959 }
2960 }
2961 return true;
2962 }
2963
cb_malloc(void * user,void * data)2964 static bool cb_malloc(void *user, void *data) {
2965 RCore *core = (RCore*) user;
2966 RConfigNode *node = (RConfigNode*) data;
2967
2968 if (node->value) {
2969 if (!strcmp ("jemalloc", node->value) || !strcmp ("glibc", node->value)) {
2970 if (core->dbg) {
2971 core->dbg->malloc = data;
2972 }
2973 }
2974
2975 }
2976 return true;
2977 }
2978
cb_log_config_level(void * coreptr,void * nodeptr)2979 static bool cb_log_config_level(void *coreptr, void *nodeptr) {
2980 RConfigNode *node = (RConfigNode *)nodeptr;
2981 r_log_set_level (node->i_value);
2982 return true;
2983 }
2984
cb_log_config_traplevel(void * coreptr,void * nodeptr)2985 static bool cb_log_config_traplevel(void *coreptr, void *nodeptr) {
2986 RConfigNode *node = (RConfigNode *)nodeptr;
2987 r_log_set_traplevel (node->i_value);
2988 return true;
2989 }
2990
cb_log_config_file(void * coreptr,void * nodeptr)2991 static bool cb_log_config_file(void *coreptr, void *nodeptr) {
2992 RConfigNode *node = (RConfigNode *)nodeptr;
2993 const char *value = node->value;
2994 r_log_set_file (value);
2995 return true;
2996 }
2997
cb_log_config_srcinfo(void * coreptr,void * nodeptr)2998 static bool cb_log_config_srcinfo(void *coreptr, void *nodeptr) {
2999 RConfigNode *node = (RConfigNode *)nodeptr;
3000 const char *value = node->value;
3001 switch (value[0]) {
3002 case 't':
3003 case 'T':
3004 r_log_set_srcinfo (true);
3005 break;
3006 default:
3007 r_log_set_srcinfo (false);
3008 }
3009 return true;
3010 }
3011
cb_log_config_colors(void * coreptr,void * nodeptr)3012 static bool cb_log_config_colors(void *coreptr, void *nodeptr) {
3013 RConfigNode *node = (RConfigNode *)nodeptr;
3014 const char *value = node->value;
3015 switch (value[0]) {
3016 case 't':
3017 case 'T':
3018 r_log_set_colors (true);
3019 break;
3020 default:
3021 r_log_set_colors (false);
3022 }
3023 return true;
3024 }
3025
cb_dbg_verbose(void * user,void * data)3026 static bool cb_dbg_verbose(void *user, void *data) {
3027 RCore *core = (RCore *)user;
3028 RConfigNode *node = (RConfigNode *)data;
3029 const char *value = node->value;
3030 switch (value[0]) {
3031 case 't':
3032 case 'T':
3033 core->dbg->verbose = true;
3034 break;
3035 default:
3036 core->dbg->verbose = false;
3037 }
3038 return true;
3039 }
3040
r_core_config_init(RCore * core)3041 R_API int r_core_config_init(RCore *core) {
3042 int i;
3043 char buf[128], *p, *tmpdir;
3044 RConfigNode *n;
3045 RConfig *cfg = core->config = r_config_new (core);
3046 if (!cfg) {
3047 return 0;
3048 }
3049 cfg->cb_printf = r_cons_printf;
3050 cfg->num = core->num;
3051 /* dir.prefix is used in other modules, set it first */
3052 {
3053 char *pfx = r_sys_getenv("R2_PREFIX");
3054 #if __WINDOWS__
3055 const char *invoke_dir = r_sys_prefix (NULL);
3056 if (!pfx && invoke_dir) {
3057 pfx = strdup (invoke_dir);
3058 }
3059 #endif
3060 if (!pfx) {
3061 pfx = strdup (R2_PREFIX);
3062 }
3063 SETCB ("dir.prefix", pfx, (RConfigCallback)&cb_dirpfx, "Default prefix r2 was compiled for");
3064 free (pfx);
3065 }
3066 #if __ANDROID__
3067 { // use dir.home and also adjust check for permissions in directory before choosing a home
3068 char *h = r_sys_getenv (R_SYS_HOME);
3069 if (h) {
3070 if (!strcmp (h, "/")) {
3071 r_sys_setenv (R_SYS_HOME, "/data/local/tmp");
3072 }
3073 free (h);
3074 }
3075 }
3076 #endif
3077 SETCB ("cmd.times", "", &cb_cmdtimes, "Run when a command is repeated (number prefix)");
3078 /* pdb */
3079 SETPREF ("pdb.useragent", "Microsoft-Symbol-Server/6.11.0001.402", "User agent for Microsoft symbol server");
3080 SETPREF ("pdb.server", "https://msdl.microsoft.com/download/symbols", "Semi-colon separated list of base URLs for Microsoft symbol servers");
3081 {
3082 char *pdb_path = r_str_home (R2_HOME_PDB);
3083 SETPREF ("pdb.symstore", pdb_path, "Path to downstream symbol store");
3084 R_FREE(pdb_path);
3085 }
3086 SETI ("pdb.extract", 1, "Avoid extract of the pdb file, just download");
3087 SETI ("pdb.autoload", false, "Automatically load the required pdb files for loaded DLLs");
3088
3089 /* anal */
3090 SETBPREF ("anal.detectwrites", "false", "Automatically reanalyze function after a write");
3091 SETPREF ("anal.fcnprefix", "fcn", "Prefix new function names with this");
3092 const char *analcc = r_anal_cc_default (core->anal);
3093 SETCB ("anal.cc", analcc? analcc: "", (RConfigCallback)&cb_analcc, "Specify default calling convention");
3094 const char *analsyscc = r_anal_syscc_default (core->anal);
3095 SETCB ("anal.syscc", analsyscc? analsyscc: "", (RConfigCallback)&cb_analsyscc, "Specify default syscall calling convention");
3096 SETCB ("anal.verbose", "false", &cb_analverbose, "Show RAnal warnings when analyzing code");
3097 SETBPREF ("anal.a2f", "false", "Use the new WIP analysis algorithm (core/p/a2f), anal.depth ignored atm");
3098 SETCB ("anal.roregs", "gp,zero", (RConfigCallback)&cb_anal_roregs, "Comma separated list of register names to be readonly");
3099 SETICB ("anal.gp", 0, (RConfigCallback)&cb_anal_gp, "Set the value of the GP register (MIPS)");
3100 SETBPREF ("anal.gpfixed", "true", "Set gp register to anal.gp before emulating each instruction in aae");
3101 SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
3102 SETCB ("anal.rnr", "false", (RConfigCallback)&cb_anal_rnr, "Recursive no return checks (EXPERIMENTAL)");
3103 SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
3104 SETICB ("anal.from", -1, (RConfigCallback)&cb_anal_from, "Lower limit on the address range for analysis");
3105 SETICB ("anal.to", -1, (RConfigCallback)&cb_anal_from, "Upper limit on the address range for analysis");
3106 n = NODECB ("anal.in", "io.maps.x", &cb_searchin);
3107 SETDESC (n, "Specify search boundaries for analysis");
3108 SETOPTIONS (n, "range", "block",
3109 "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",
3110 "io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3111 "dbg.stack", "dbg.heap",
3112 "dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3113 "anal.fcn", "anal.bb",
3114 NULL);
3115 SETI ("anal.timeout", 0, "Stop analyzing after a couple of seconds");
3116 SETCB ("anal.jmp.retpoline", "true", &cb_anal_jmpretpoline, "Analyze retpolines, may be slower if not needed");
3117 SETICB ("anal.jmp.tailcall", 0, &cb_anal_jmptailcall, "Consume a branch as a call if delta is big");
3118
3119 SETCB ("anal.armthumb", "false", &cb_analarmthumb, "aae computes arm/thumb changes (lot of false positives ahead)");
3120 SETCB ("anal.jmp.after", "true", &cb_analafterjmp, "Continue analysis after jmp/ujmp");
3121 SETCB ("anal.endsize", "true", &cb_anal_endsize, "Adjust function size at the end of the analysis (known to be buggy)");
3122 SETCB ("anal.delay", "true", &cb_anal_delay, "Enable delay slot analysis if supported by the architecture");
3123 SETICB ("anal.depth", 64, &cb_analdepth, "Max depth at code analysis"); // XXX: warn if depth is > 50 .. can be problematic
3124 SETICB ("anal.graph_depth", 256, &cb_analgraphdepth, "Max depth for path search");
3125 SETICB ("anal.sleep", 0, &cb_analsleep, "Sleep N usecs every so often during analysis. Avoid 100% CPU usage");
3126 SETCB ("anal.ignbithints", "false", &cb_anal_ignbithints, "Ignore the ahb hints (only obey asm.bits)");
3127 SETBPREF ("anal.calls", "false", "Make basic af analysis walk into calls");
3128 SETBPREF ("anal.autoname", "false", "Speculatively set a name for the functions, may result in some false positives");
3129 SETBPREF ("anal.hasnext", "false", "Continue analysis after each function");
3130 SETICB ("anal.nonull", 0, &cb_anal_nonull, "Do not analyze regions of N null bytes");
3131 SETBPREF ("anal.esil", "false", "Use the new ESIL code analysis");
3132 SETCB ("anal.strings", "false", &cb_analstrings, "Identify and register strings during analysis (aar only)");
3133 SETPREF ("anal.types.spec", "gcc", "Set profile for specifying format chars used in type analysis");
3134 SETBPREF ("anal.types.verbose", "false", "Verbose output from type analysis");
3135 SETBPREF ("anal.types.constraint", "false", "Enable constraint types analysis for variables");
3136 SETCB ("anal.vars", "true", &cb_analvars, "Analyze local variables and arguments");
3137 SETCB ("anal.vars.stackname", "false", &cb_analvars_stackname, "Name variables based on their offset on the stack");
3138 SETBPREF ("anal.vinfun", "true", "Search values in functions (aav) (false by default to only find on non-code)");
3139 SETBPREF ("anal.vinfunrange", "false", "Search values outside function ranges (requires anal.vinfun=false)\n");
3140 SETCB ("anal.norevisit", "false", &cb_analnorevisit, "Do not visit function analysis twice (EXPERIMENTAL)");
3141 SETCB ("anal.nopskip", "true", &cb_analnopskip, "Skip nops at the beginning of functions");
3142 SETCB ("anal.hpskip", "false", &cb_analhpskip, "Skip `mov reg, reg` and `lea reg, [reg] at the beginning of functions");
3143 n = NODECB ("anal.arch", R_SYS_ARCH, &cb_analarch);
3144 SETDESC (n, "Select the architecture to use");
3145 update_analarch_options (core, n);
3146 SETCB ("anal.cpu", R_SYS_ARCH, &cb_analcpu, "Specify the anal.cpu to use");
3147 SETPREF ("anal.prelude", "", "Specify an hexpair to find preludes in code");
3148 SETCB ("anal.recont", "false", &cb_analrecont, "End block after splitting a basic block instead of error"); // testing
3149 SETCB ("anal.jmp.indir", "false", &cb_analijmp, "Follow the indirect jumps in function analysis"); // testing
3150 SETI ("anal.ptrdepth", 3, "Maximum number of nested pointers to follow in analysis");
3151 SETICB ("asm.lines.maxref", 0, &cb_analmaxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
3152
3153 SETCB ("anal.jmp.tbl", "true", &cb_anal_jmptbl, "Analyze jump tables in switch statements");
3154
3155 SETCB ("anal.jmp.cref", "false", &cb_anal_cjmpref, "Create references for conditional jumps");
3156 SETCB ("anal.jmp.ref", "true", &cb_anal_jmpref, "Create references for unconditional jumps");
3157
3158 SETCB ("anal.jmp.above", "true", &cb_anal_jmpabove, "Jump above function pointer");
3159 SETCB ("anal.loads", "false", &cb_anal_loads, "Define as dword/string/qword when analyzing load instructions");
3160 SETCB ("anal.datarefs", "false", &cb_anal_followdatarefs, "Follow data references for code coverage");
3161 SETCB ("anal.brokenrefs", "false", &cb_anal_brokenrefs, "Follow function references as well if function analysis was failed");
3162 SETCB ("anal.jmp.mid", "true", &cb_anal_jmpmid, "Continue analysis after jump to middle of instruction (x86 only)");
3163
3164 SETCB ("anal.refstr", "false", &cb_anal_searchstringrefs, "Search string references in data references");
3165 SETCB ("anal.trycatch", "false", &cb_anal_trycatch, "Honor try.X.Y.{from,to,catch} flags");
3166 SETCB ("anal.bb.maxsize", "512K", &cb_anal_bb_max_size, "Maximum basic block size");
3167 SETCB ("anal.pushret", "false", &cb_anal_pushret, "Analyze push+ret as jmp");
3168
3169 n = NODECB ("anal.cpp.abi", "itanium", &cb_anal_cpp_abi);
3170 SETDESC (n, "Select C++ ABI (Compiler)");
3171 SETOPTIONS (n, "itanium", "msvc", NULL);
3172
3173 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
3174 SETCB ("dbg.malloc", "glibc", &cb_malloc, "Choose malloc structure parser");
3175 #else
3176 SETCB ("dbg.malloc", "jemalloc", &cb_malloc, "Choose malloc structure parser");
3177 #endif
3178 #if __GLIBC_MINOR__ > 25
3179 SETBPREF ("dbg.glibc.tcache", "true", "Set glib tcache parsing");
3180 #else
3181 SETBPREF ("dbg.glibc.tcache", "false", "Set glib tcache parsing");
3182 #endif
3183 #if __x86_64__
3184 SETI ("dbg.glibc.ma_offset", 0x000000, "Main_arena offset from his symbol");
3185 SETI ("dbg.glibc.fc_offset", 0x00280, "First chunk offset from brk_start");
3186 #else
3187 SETI ("dbg.glibc.ma_offset", 0x1bb000, "Main_arena offset from his symbol");
3188 SETI ("dbg.glibc.fc_offset", 0x148, "First chunk offset from brk_start");
3189 #endif
3190 SETBPREF ("dbg.glibc.demangle", "false", "Demangle linked-lists pointers introduced in glibc 2.32");
3191 SETBPREF ("esil.prestep", "true", "Step before esil evaluation in `de` commands");
3192 SETPREF ("esil.fillstack", "", "Initialize ESIL stack with (random, debrujn, sequence, zeros, ...)");
3193 SETICB ("esil.verbose", 0, &cb_esilverbose, "Show ESIL verbose level (0, 1, 2)");
3194 SETICB ("esil.gotolimit", core->anal->esil_goto_limit, &cb_gotolimit, "Maximum number of gotos per ESIL expression");
3195 SETICB ("esil.stack.depth", 256, &cb_esilstackdepth, "Number of elements that can be pushed on the esilstack");
3196 SETI ("esil.stack.size", 0xf0000, "Set stack size in ESIL VM");
3197 SETI ("esil.stack.addr", 0x100000, "Set stack address in ESIL VM");
3198 SETPREF ("esil.stack.pattern", "0", "Specify fill pattern to initialize the stack (0, w, d, i)");
3199 SETI ("esil.addr.size", 64, "Maximum address size in accessed by the ESIL VM");
3200 SETBPREF ("esil.breakoninvalid", "false", "Break esil execution when instruction is invalid");
3201 SETI ("esil.timeout", 0, "A timeout (in seconds) for when we should give up emulating");
3202 /* asm */
3203 //asm.os needs to be first, since other asm.* depend on it
3204 n = NODECB ("asm.os", R_SYS_OS, &cb_asmos);
3205 SETDESC (n, "Select operating system (kernel)");
3206 SETOPTIONS (n, "ios", "dos", "darwin", "linux", "freebsd", "openbsd", "netbsd", "windows", "s110", NULL);
3207 SETI ("asm.xrefs.fold", 5, "Maximum number of xrefs to be displayed as list (use columns above)");
3208 SETBPREF ("asm.xrefs.code", "true", "Show the code xrefs (generated by jumps instead of calls)");
3209 SETI ("asm.xrefs.max", 20, "Maximum number of xrefs to be displayed without folding");
3210 SETCB ("asm.invhex", "false", &cb_asm_invhex, "Show invalid instructions as hexadecimal numbers");
3211 SETBPREF ("asm.instr", "true", "Display the disassembled instruction");
3212 SETBPREF ("asm.meta", "true", "Display the code/data/format conversions in disasm");
3213 SETBPREF ("asm.bytes", "true", "Display the bytes of each instruction");
3214 SETBPREF ("asm.bytes.right", "false", "Display the bytes at the right of the disassembly");
3215 SETI ("asm.types", 1, "Display the fcn types in calls (0=no,1=quiet,2=verbose)");
3216 SETBPREF ("asm.midcursor", "false", "Cursor in visual disasm mode breaks the instruction");
3217 SETBPREF ("asm.cmt.flgrefs", "true", "Show comment flags associated to branch reference");
3218 SETBPREF ("asm.cmt.right", "true", "Show comments at right of disassembly if they fit in screen");
3219 SETBPREF ("asm.cmt.esil", "false", "Show ESIL expressions as comments");
3220 SETI ("asm.cmt.col", 71, "Column to align comments");
3221 SETICB ("asm.pcalign", 0, &cb_asm_pcalign, "Only recognize as valid instructions aligned to this value");
3222 // maybe rename to asm.cmt.calls
3223 SETBPREF ("asm.calls", "true", "Show callee function related info as comments in disasm");
3224 SETBPREF ("asm.comments", "true", "Show comments in disassembly view");
3225 SETBPREF ("asm.usercomments", "false", "Show user comments even if asm.comments is false");
3226 SETBPREF ("asm.sub.jmp", "true", "Always substitute jump, call and branch targets in disassembly");
3227 SETBPREF ("asm.hints", "true", "Disable all asm.hint* if false");
3228 SETBPREF ("asm.hint.jmp", "false", "Show jump hints [numbers] in disasm");
3229 SETBPREF ("asm.hint.call", "true", "Show call hints [numbers] in disasm");
3230 SETBPREF ("asm.hint.call.indirect", "true", "Hints for indirect call intructions go to the call destination");
3231 SETBPREF ("asm.hint.lea", "false", "Show LEA hints [numbers] in disasm");
3232 SETBPREF ("asm.hint.emu", "false", "Show asm.emu hints [numbers] in disasm");
3233 SETBPREF ("asm.hint.cdiv", "false", "Show CDIV hints optimization hint");
3234 SETI ("asm.hint.pos", 1, "Shortcut hint position (-1, 0, 1)");
3235 SETBPREF ("asm.slow", "true", "Perform slow analysis operations in disasm");
3236 SETBPREF ("asm.decode", "false", "Use code analysis as a disassembler");
3237 SETICB ("asm.imm.arm", false, &cb_asm_armimm, "Display # for immediates in ARM");
3238 SETBPREF ("asm.imm.str", "true", "Show immediates values as strings");
3239 SETBPREF ("asm.imm.trim", "false", "Remove all offsets and constants from disassembly");
3240 SETBPREF ("asm.indent", "false", "Indent disassembly based on reflines depth");
3241 SETI ("asm.indentspace", 2, "How many spaces to indent the code");
3242 SETBPREF ("asm.dwarf", "false", "Show dwarf comment at disassembly");
3243 SETBPREF ("asm.dwarf.abspath", "false", "Show absolute path in asm.dwarf");
3244 SETBPREF ("asm.dwarf.file", "true", "Show filename of asm.dwarf in pd");
3245 SETBPREF ("asm.esil", "false", "Show ESIL instead of mnemonic");
3246 SETBPREF ("asm.nodup", "false", "Do not show dupped instructions (collapse disasm)");
3247 SETBPREF ("asm.emu", "false", "Run ESIL emulation analysis on disasm");
3248 SETBPREF ("emu.pre", "false", "Run ESIL emulation starting at the closest flag in pd");
3249 SETBPREF ("asm.refptr", "true", "Show refpointer information in disasm");
3250 SETBPREF ("emu.lazy", "false", "Do not emulate all instructions with aae (optimization)");
3251 SETBPREF ("emu.stack", "false", "Create a temporary fake stack when emulating in disasm (asm.emu)");
3252 SETCB ("emu.str", "false", &cb_emustr, "Show only strings if any in the asm.emu output");
3253 SETBPREF ("emu.str.lea", "true", "Disable this in ARM64 code to remove some false positives");
3254 SETBPREF ("emu.str.off", "false", "Always show offset when printing asm.emu strings");
3255 SETBPREF ("emu.str.inv", "true", "Color-invert emu.str strings");
3256 SETBPREF ("emu.str.flag", "true", "Also show flag (if any) for asm.emu string");
3257 SETBPREF ("emu.write", "false", "Allow asm.emu to modify memory (WARNING)");
3258 SETBPREF ("emu.ssa", "false", "Perform SSA checks and show the ssa reg names as comments");
3259 n = NODECB ("emu.skip", "ds", &cb_emuskip);
3260 SETDESC (n, "Skip metadata of given types in asm.emu");
3261 SETOPTIONS (n, "d", "c", "s", "f", "m", "h", "C", "r", NULL);
3262 SETBPREF ("asm.sub.names", "true", "Replace numeric values by flags (e.g. 0x4003e0 -> sym.imp.printf)");
3263 SETPREF ("asm.strip", "", "strip all instructions given comma separated types");
3264 SETBPREF ("asm.optype", "false", "show opcode type next to the instruction bytes");
3265 SETBPREF ("asm.lines.fcn", "true", "Show function boundary lines");
3266 SETBPREF ("asm.flags", "true", "Show flags");
3267 SETICB ("asm.flags.maxname", 0, &cb_maxname, "Maximum length of flag name with smart chopping");
3268 SETI ("asm.flags.limit", 0, "Maximum number of flags to show in a single offset");
3269 SETBPREF ("asm.flags.offset", "false", "Show offset in flags");
3270 SETBPREF ("asm.flags.inbytes", "false", "Display flags inside the bytes space");
3271 SETBPREF ("asm.flags.inline", "false", "Display flags in line separated by commas instead of newlines");
3272 n = NODEICB ("asm.flags.middle", 2, &cb_midflags);
3273 SETOPTIONS (n, "0 = do not show flag", "1 = show without realign", "2 = realign at middle flag",
3274 "3 = realign at middle flag if sym.*", NULL);
3275 SETDESC (n, "Realign disassembly if there is a flag in the middle of an instruction");
3276 SETCB ("asm.flags.real", "false", &cb_flag_realnames,
3277 "Show flags' unfiltered realnames instead of names, except realnames from demangling");
3278 SETBPREF ("asm.bb.line", "false", "Show empty line after every basic block");
3279 SETBPREF ("asm.bb.middle", "true", "Realign disassembly if a basic block starts in the middle of an instruction");
3280 SETBPREF ("asm.lbytes", "true", "Align disasm bytes to left");
3281 SETBPREF ("asm.lines", "true", "Show ASCII-art lines at disassembly");
3282 SETBPREF ("asm.lines.bb", "true", "Show flow lines at jumps");
3283 SETBPREF ("asm.lines.call", "false", "Enable call lines");
3284 SETBPREF ("asm.lines.ret", "false", "Show separator lines after ret");
3285 SETBPREF ("asm.lines.out", "true", "Show out of block lines");
3286 SETBPREF ("asm.lines.right", "false", "Show lines before opcode instead of offset");
3287 SETBPREF ("asm.lines.wide", "false", "Put a space between lines");
3288 SETBPREF ("asm.fcnsig", "true", "Show function signature in disasm");
3289 SETICB ("asm.lines.width", 7, &cb_asmlineswidth, "Number of columns for program flow arrows");
3290 SETICB ("asm.sub.varmin", 0x100, &cb_asmsubvarmin, "Minimum value to substitute in instructions (asm.sub.var)");
3291 SETCB ("asm.sub.tail", "false", &cb_asmsubtail, "Replace addresses with prefix .. syntax");
3292 SETBPREF ("asm.middle", "false", "Allow disassembling jumps in the middle of an instruction");
3293 SETBPREF ("asm.noisy", "true", "Show comments considered noisy but possibly useful");
3294 SETBPREF ("asm.offset", "true", "Show offsets in disassembly");
3295 SETBPREF ("hex.offset", "true", "Show offsets in hex-dump");
3296 SETBPREF ("scr.square", "true", "Use square pixels or not");
3297 SETCB ("scr.prompt.vi", "false", &cb_scr_vi, "Use vi mode for input prompt");
3298 SETCB ("scr.prompt.mode", "false", &cb_scr_prompt_mode, "Set prompt color based on vi mode");
3299 SETCB ("scr.wideoff", "false", &cb_scr_wideoff, "Adjust offsets to match asm.bits");
3300 SETCB ("scr.rainbow", "false", &cb_scrrainbow, "Shows rainbow colors depending of address");
3301 SETCB ("scr.last", "true", &cb_scrlast, "Cache last output after flush to make _ command work (disable for performance)");
3302 SETBPREF ("asm.reloff", "false", "Show relative offsets instead of absolute address in disasm");
3303 SETBPREF ("asm.reloff.flags", "false", "Show relative offsets to flags (not only functions)");
3304 SETBPREF ("asm.section", "false", "Show section name before offset");
3305 SETBPREF ("asm.section.perm", "false", "Show section permissions in the disasm");
3306 SETBPREF ("asm.section.name", "true", "Show section name in the disasm");
3307 SETI ("asm.section.col", 20, "Columns width to show asm.section");
3308 SETCB ("asm.sub.section", "false", &cb_asmsubsec, "Show offsets in disasm prefixed with section/map name");
3309 SETCB ("asm.pseudo", "false", &cb_asmpseudo, "Enable pseudo syntax");
3310 SETBPREF ("asm.size", "false", "Show size of opcodes in disassembly (pd)");
3311 SETBPREF ("asm.stackptr", "false", "Show stack pointer at disassembly");
3312 SETBPREF ("asm.cyclespace", "false", "Indent instructions depending on CPU-cycles");
3313 SETBPREF ("asm.cycles", "false", "Show CPU-cycles taken by instruction at disassembly");
3314 SETI ("asm.tabs", 0, "Use tabs in disassembly");
3315 SETBPREF ("asm.tabs.once", "false", "Only tabulate the opcode, not the arguments");
3316 SETI ("asm.tabs.off", 0, "tabulate spaces after the offset");
3317 SETBPREF ("asm.trace", "false", "Show execution traces for each opcode");
3318 SETBPREF ("asm.tracespace", "false", "Indent disassembly with trace.count information");
3319 SETBPREF ("asm.ucase", "false", "Use uppercase syntax at disassembly");
3320 SETBPREF ("asm.capitalize", "false", "Use camelcase at disassembly");
3321 SETBPREF ("asm.var", "true", "Show local function variables in disassembly");
3322 SETBPREF ("asm.var.access", "false", "Show accesses of local variables");
3323 SETBPREF ("asm.sub.var", "true", "Substitute variables in disassembly");
3324 SETI ("asm.var.summary", 0, "Show variables summary instead of full list in disasm (0, 1, 2)");
3325 SETBPREF ("asm.sub.varonly", "true", "Substitute the entire variable expression with the local variable name (e.g. [local10h] instead of [ebp+local10h])");
3326 SETBPREF ("asm.sub.reg", "false", "Substitute register names with their associated role name (drp~=)");
3327 SETBPREF ("asm.sub.rel", "true", "Substitute pc relative expressions in disasm");
3328 SETBPREF ("asm.cmt.fold", "false", "Fold comments, toggle with Vz");
3329 SETBPREF ("asm.family", "false", "Show family name in disasm");
3330 SETBPREF ("asm.symbol", "false", "Show symbol+delta instead of absolute offset");
3331 SETBPREF ("asm.anal", "false", "Analyze code and refs while disassembling (see anal.strings)");
3332 SETI ("asm.symbol.col", 40, "Columns width to show asm.section");
3333 SETCB ("asm.assembler", "", &cb_asmassembler, "Set the plugin name to use when assembling");
3334 SETBPREF ("asm.minicols", "false", "Only show the instruction in the column disasm");
3335 RConfigNode *asmcpu = NODECB ("asm.cpu", R_SYS_ARCH, &cb_asmcpu);
3336 SETDESC (asmcpu, "Set the kind of asm.arch cpu");
3337 RConfigNode *asmarch = NODECB ("asm.arch", R_SYS_ARCH, &cb_asmarch);
3338 SETDESC (asmarch, "Set the arch to be used by asm");
3339 /* we need to have both asm.arch and asm.cpu defined before updating options */
3340 update_asmarch_options (core, asmarch);
3341 update_asmcpu_options (core, asmcpu);
3342 n = NODECB ("asm.features", "", &cb_asmfeatures);
3343 SETDESC (n, "Specify supported features by the target CPU");
3344 update_asmfeatures_options (core, n);
3345 n = NODECB ("asm.parser", "x86.pseudo", &cb_asmparser);
3346 SETDESC (n, "Set the asm parser to use");
3347 update_asmparser_options (core, n);
3348 SETCB ("asm.segoff", "false", &cb_segoff, "Show segmented address in prompt (x86-16)");
3349 SETCB ("asm.decoff", "false", &cb_decoff, "Show segmented address in prompt (x86-16)");
3350 SETICB ("asm.seggrn", 4, &cb_seggrn, "Segment granularity in bits (x86-16)");
3351 n = NODECB ("asm.syntax", "intel", &cb_asmsyntax);
3352 SETDESC (n, "Select assembly syntax");
3353 SETOPTIONS (n, "att", "intel", "masm", "jz", "regnum", NULL);
3354 SETI ("asm.nbytes", 6, "Number of bytes for each opcode at disassembly");
3355 SETBPREF ("asm.bytes.space", "false", "Separate hexadecimal bytes with a whitespace");
3356 #if R_SYS_BITS == R_SYS_BITS_64
3357 SETICB ("asm.bits", 64, &cb_asmbits, "Word size in bits at assembler");
3358 #else
3359 SETICB ("asm.bits", 32, &cb_asmbits, "Word size in bits at assembler");
3360 #endif
3361 n = r_config_node_get(cfg, "asm.bits");
3362 update_asmbits_options (core, n);
3363 SETBPREF ("asm.functions", "true", "Show functions in disassembly");
3364 SETBPREF ("asm.xrefs", "true", "Show xrefs in disassembly");
3365 SETBPREF ("asm.demangle", "true", "Show demangled symbols in disasm");
3366 SETBPREF ("asm.describe", "false", "Show opcode description");
3367 SETPREF ("asm.highlight", "", "Highlight current line");
3368 SETBPREF ("asm.marks", "true", "Show marks before the disassembly");
3369 SETBPREF ("asm.cmt.refs", "false", "Show flag and comments from refs in disasm");
3370 SETBPREF ("asm.cmt.patch", "false", "Show patch comments in disasm");
3371 SETBPREF ("asm.cmt.off", "nodup", "Show offset comment in disasm (true, false, nodup)");
3372 SETBPREF ("asm.payloads", "false", "Show payload bytes in disasm");
3373
3374 /* bin */
3375 SETPREF ("bin.hashlimit", "10M", "Only compute hash when opening a file if smaller than this size");
3376 SETCB ("bin.usextr", "true", &cb_usextr, "Use extract plugins when loading files");
3377 SETCB ("bin.useldr", "true", &cb_useldr, "Use loader plugins when loading files");
3378 SETCB ("bin.str.purge", "", &cb_strpurge, "Purge strings (e bin.str.purge=? provides more detail)");
3379 SETPREF ("bin.str.real", "false", "Set the realname in rbin.strings for better disasm (EXPERIMENTAL)");
3380 SETBPREF ("bin.b64str", "false", "Try to debase64 the strings");
3381 SETCB ("bin.at", "false", &cb_binat, "RBin.cur depends on RCore.offset");
3382 SETBPREF ("bin.libs", "false", "Try to load libraries after loading main binary");
3383 n = NODECB ("bin.str.filter", "", &cb_strfilter);
3384 SETDESC (n, "Filter strings");
3385 SETOPTIONS (n, "a", "8", "p", "e", "u", "i", "U", "f", NULL);
3386 SETCB ("bin.filter", "true", &cb_binfilter, "Filter symbol names to fix dupped names");
3387 SETCB ("bin.force", "", &cb_binforce, "Force that rbin plugin");
3388 SETPREF ("bin.cache", "false", "Enable io.cache and fall to io.cache.read if bin needs to patch relocs");
3389 SETPREF ("bin.lang", "", "Language for bin.demangle");
3390 SETBPREF ("bin.demangle", "true", "Import demangled symbols from RBin");
3391 SETBPREF ("bin.demangle.libs", "false", "Show library name on demangled symbols names");
3392 SETI ("bin.baddr", -1, "Base address of the binary");
3393 SETI ("bin.laddr", 0, "Base address for loading library ('*.so')");
3394 SETCB ("bin.dbginfo", "true", &cb_bindbginfo, "Load debug information at startup if available");
3395 SETBPREF ("bin.relocs", "true", "Load relocs information at startup if available");
3396 SETICB ("bin.minstr", 0, &cb_binminstr, "Minimum string length for r_bin");
3397 SETICB ("bin.maxstr", 0, &cb_binmaxstr, "Maximum string length for r_bin");
3398 SETICB ("bin.maxstrbuf", 1024*1024*10, & cb_binmaxstrbuf, "Maximum size of range to load strings from");
3399 n = NODECB ("bin.str.enc", "guess", &cb_binstrenc);
3400 SETDESC (n, "Default string encoding of binary");
3401 SETOPTIONS (n, "ascii", "latin1", "utf8", "utf16le", "utf32le", "utf16be", "utf32be", "guess", NULL);
3402 SETCB ("bin.prefix", "", &cb_binprefix, "Prefix all symbols/sections/relocs with a specific string");
3403 SETCB ("bin.rawstr", "false", &cb_rawstr, "Load strings from raw binaries");
3404 SETCB ("bin.strings", "true", &cb_binstrings, "Load strings from rbin on startup");
3405 SETCB ("bin.debase64", "false", &cb_debase64, "Try to debase64 all strings");
3406 SETBPREF ("bin.classes", "true", "Load classes from rbin on startup");
3407 SETCB ("bin.verbose", "false", &cb_binverbose, "Show RBin warnings when loading binaries");
3408
3409 /* prj */
3410 SETCB ("prj.name", "", &cb_prjname, "Name of current project");
3411 SETBPREF ("prj.files", "false", "Save the target binary inside the project directory");
3412 {
3413 char *p = r_file_path ("git");
3414 bool found = (p && *p == '/');
3415 SETBPREF ("prj.git", r_str_bool (found), "Use git to share your project and version changes");
3416 free (p);
3417 }
3418 SETBPREF ("prj.zip", "false", "Use ZIP format for project files");
3419 SETBPREF ("prj.gpg", "false", "TODO: Encrypt project with GnuPGv2");
3420
3421 /* cfg */
3422 SETCB ("cfg.charset", "", &cb_cfgcharset, "Specify encoding to use when printing strings");
3423 SETBPREF ("cfg.r2wars", "false", "Enable some tweaks for the r2wars game");
3424 SETBPREF ("cfg.plugins", "true", "Load plugins at startup");
3425 SETCB ("time.fmt", "%Y-%m-%d %H:%M:%S %z", &cb_cfgdatefmt, "Date format (%Y-%m-%d %H:%M:%S %z)");
3426 SETICB ("time.zone", 0, &cb_timezone, "Time zone, in hours relative to GMT: +2, -1,..");
3427 SETCB ("cfg.corelog", "false", &cb_cfgcorelog, "Log changes using the T api needed for realtime syncing");
3428 SETBPREF ("cfg.newtab", "false", "Show descriptions in command completion");
3429 SETCB ("cfg.debug", "false", &cb_cfgdebug, "Debugger mode");
3430 p = r_sys_getenv ("EDITOR");
3431 #if __WINDOWS__
3432 r_config_set (cfg, "cfg.editor", r_str_get_fail (p, "notepad"));
3433 #else
3434 r_config_set (cfg, "cfg.editor", r_str_get_fail (p, "vi"));
3435 #endif
3436 free (p);
3437 r_config_desc (cfg, "cfg.editor", "Select default editor program");
3438 char *whoami = r_sys_whoami ();
3439 SETPREF ("cfg.user", whoami, "Set current username/pid");
3440 free (whoami);
3441 SETCB ("cfg.fortunes", "true", &cb_cfg_fortunes, "If enabled show tips at start");
3442 SETCB ("cfg.fortunes.type", "tips,fun", &cb_cfg_fortunes_type, "Type of fortunes to show (tips, fun)");
3443 SETBPREF ("cfg.fortunes.clippy", "false", "Use ?E instead of ?e");
3444 SETBPREF ("cfg.fortunes.tts", "false", "Speak out the fortune");
3445 SETPREF ("cfg.prefixdump", "dump", "Filename prefix for automated dumps");
3446 SETCB ("cfg.sandbox", "false", &cb_cfgsanbox, "Sandbox mode disables systems and open on upper directories");
3447 SETBPREF ("cfg.wseek", "false", "Seek after write");
3448 SETCB ("cfg.bigendian", "false", &cb_bigendian, "Use little (false) or big (true) endianness");
3449 p = r_sys_getenv ("R2_CFG_NEWSHELL");
3450 SETCB ("cfg.newshell", r_str_bool (p && atoi (p)), &cb_newshell, "Use new commands parser");
3451 free (p);
3452 SETI ("cfg.cpuaffinity", 0, "Run on cpuid");
3453
3454 /* log */
3455 // R2_LOGLEVEL / log.level
3456 p = r_sys_getenv ("R2_LOGLEVEL");
3457 SETICB ("log.level", p? atoi(p): R_DEFAULT_LOGLVL, cb_log_config_level, "Target log level/severity"\
3458 " (0:SILLY, 1:DEBUG, 2:VERBOSE, 3:INFO, 4:WARN, 5:ERROR, 6:FATAL)"
3459 );
3460 free (p);
3461 // R2_LOGTRAP_LEVEL / log.traplevel
3462 p = r_sys_getenv ("R2_LOGTRAPLEVEL");
3463 SETICB ("log.traplevel", p ? atoi(p) : R_LOGLVL_FATAL, cb_log_config_traplevel, "Log level for trapping R2 when hit"\
3464 " (0:SILLY, 1:VERBOSE, 2:DEBUG, 3:INFO, 4:WARN, 5:ERROR, 6:FATAL)"
3465 );
3466 free (p);
3467 // R2_LOGFILE / log.file
3468 p = r_sys_getenv ("R2_LOGFILE");
3469 SETCB ("log.file", r_str_get (p), cb_log_config_file, "Logging output filename / path");
3470 free (p);
3471 // R2_LOGSRCINFO / log.srcinfo
3472 p = r_sys_getenv ("R2_LOGSRCINFO");
3473 SETCB ("log.srcinfo", r_str_get_fail (p, "false"), cb_log_config_srcinfo, "Should the log output contain src info (filename:lineno)");
3474 free (p);
3475 // R2_LOGCOLORS / log.colors
3476 p = r_sys_getenv ("R2_LOGCOLORS");
3477 SETCB ("log.colors", r_str_get_fail (p, "false"), cb_log_config_colors, "Should the log output use colors (TODO)");
3478 free (p);
3479
3480 SETCB ("log.events", "false", &cb_log_events, "Remote HTTP server to sync events with");
3481
3482 // zign
3483 SETPREF ("zign.prefix", "sign", "Default prefix for zignatures matches");
3484 SETI ("zign.maxsz", 500, "Maximum zignature length");
3485 SETI ("zign.minsz", 16, "Minimum zignature length for matching");
3486 SETI ("zign.mincc", 10, "Minimum cyclomatic complexity for matching");
3487 SETBPREF ("zign.graph", "true", "Use graph metrics for matching");
3488 SETBPREF ("zign.bytes", "true", "Use bytes patterns for matching");
3489 SETBPREF ("zign.offset", "false", "Use original offset for matching");
3490 SETBPREF ("zign.refs", "true", "Use references for matching");
3491 SETBPREF ("zign.hash", "true", "Use Hash for matching");
3492 SETBPREF ("zign.types", "true", "Use types for matching");
3493 SETBPREF ("zign.autoload", "false", "Autoload all zignatures located in " R_JOIN_2_PATHS ("~", R2_HOME_ZIGNS));
3494 SETPREF ("zign.diff.bthresh", "1.0", "Threshold for diffing zign bytes [0, 1] (see zc?)");
3495 SETPREF ("zign.diff.gthresh", "1.0", "Threshold for diffing zign graphs [0, 1] (see zc?)");
3496 SETPREF ("zign.threshold", "0.0", "Minimum similarity required for inclusion in zb output");
3497
3498 /* diff */
3499 SETCB ("diff.sort", "addr", &cb_diff_sort, "Specify function diff sorting column see (e diff.sort=?)");
3500 SETI ("diff.from", 0, "Set source diffing address for px (uses cc command)");
3501 SETI ("diff.to", 0, "Set destination diffing address for px (uses cc command)");
3502 SETBPREF ("diff.bare", "false", "Never show function names in diff output");
3503 SETBPREF ("diff.levenstein", "false", "Use faster (and buggy) levenstein algorithm for buffer distance diffing");
3504
3505 /* dir */
3506 SETI ("dir.depth", 10, "Maximum depth when searching recursively for files");
3507 {
3508 char *path = r_str_newf (R_JOIN_2_PATHS ("%s", R2_SDB_MAGIC), r_config_get (core->config, "dir.prefix"));
3509 SETPREF ("dir.magic", path, "Path to r_magic files");
3510 free (path);
3511 path = r_str_newf (R_JOIN_2_PATHS ("%s", R2_PLUGINS), r_config_get (core->config, "dir.prefix"));
3512 SETPREF ("dir.plugins", path, "Path to plugin files to be loaded at startup");
3513 free (path);
3514 }
3515 SETCB ("dir.source", "", &cb_dirsrc, "Path to find source files");
3516 SETPREF ("dir.types", "/usr/include", "Default path to look for cparse type files");
3517 SETPREF ("dir.libs", "", "Specify path to find libraries to load when bin.libs=true");
3518 p = r_sys_getenv (R_SYS_HOME);
3519 SETCB ("dir.home", r_str_get_fail (p, "/"), &cb_dirhome, "Path for the home directory");
3520 free (p);
3521 p = r_sys_getenv (R_SYS_TMP);
3522 SETCB ("dir.tmp", r_str_get (p), &cb_dirtmp, "Path of the tmp directory");
3523 free (p);
3524 #if __ANDROID__
3525 SETCB ("dir.projects", "/data/data/org.radare.radare2installer/radare2/projects", &cb_dir_projects, "Default path for projects");
3526 #else
3527 SETCB ("dir.projects", R_JOIN_2_PATHS ("~", R2_HOME_PROJECTS), &cb_dir_projects, "Default path for projects");
3528 #endif
3529 SETCB ("dir.zigns", R_JOIN_2_PATHS ("~", R2_HOME_ZIGNS), &cb_dirzigns, "Default path for zignatures (see zo command)");
3530 SETPREF ("stack.reg", "SP", "Which register to use as stack pointer in the visual debug");
3531 SETBPREF ("stack.bytes", "true", "Show bytes instead of words in stack");
3532 SETBPREF ("stack.anotated", "false", "Show anotated hexdump in visual debug");
3533 SETI ("stack.size", 64, "Size in bytes of stack hexdump in visual debug");
3534 SETI ("stack.delta", 0, "Delta for the stack dump");
3535
3536 SETCB ("dbg.libs", "", &cb_dbg_libs, "If set stop when loading matching libname");
3537 SETBPREF ("dbg.skipover", "false", "Make dso perform a dss (same goes for esil and visual/graph");
3538 SETI ("dbg.hwbp", 0, "Set HW or SW breakpoints");
3539 SETCB ("dbg.unlibs", "", &cb_dbg_unlibs, "If set stop when unloading matching libname");
3540 SETCB ("dbg.verbose", "true", &cb_dbg_verbose, "Verbose debug output");
3541 SETBPREF ("dbg.slow", "false", "Show stack and regs in visual mode in a slow but verbose mode");
3542 SETBPREF ("dbg.funcarg", "false", "Display arguments to function call in visual mode");
3543
3544 SETCB ("dbg.bpinmaps", "true", &cb_dbg_bpinmaps, "Activate breakpoints only if they are inside a valid map");
3545 SETCB ("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
3546 n = NODECB ("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
3547 SETDESC (n, "Select backtrace algorithm");
3548 SETOPTIONS (n, "default", "fuzzy", "anal", "trace", NULL);
3549 SETCB ("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
3550 SETCB ("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
3551 SETCB ("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");
3552 SETCB ("dbg.profile", "", &cb_runprofile, "Path to RRunProfile file");
3553 SETCB ("dbg.args", "", &cb_dbg_args, "Set the args of the program to debug");
3554 SETCB ("dbg.follow.child", "false", &cb_dbg_follow_child, "Continue tracing the child process on fork. By default the parent process is traced");
3555 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");
3556 /* debug */
3557 SETCB ("dbg.status", "false", &cb_dbgstatus, "Set cmd.prompt to '.dr*' or '.dr*;drd;sr PC;pi 1;s-'");
3558 #if DEBUGGER
3559 SETCB ("dbg.backend", "native", &cb_dbgbackend, "Select the debugger backend");
3560 #else
3561 SETCB ("dbg.backend", "esil", &cb_dbgbackend, "Select the debugger backend");
3562 #endif
3563 n = NODECB ("dbg.bep", "loader", &cb_dbgbep);
3564 SETDESC (n, "Break on entrypoint");
3565 SETOPTIONS (n, "loader", "entry", "constructor", "main", NULL);
3566 if (core->cons->rows > 30) { // HACKY
3567 r_config_set_i (cfg, "dbg.follow", 64);
3568 } else {
3569 r_config_set_i (cfg, "dbg.follow", 32);
3570 }
3571 r_config_desc (cfg, "dbg.follow", "Follow program counter when pc > core->offset + dbg.follow");
3572 SETBPREF ("dbg.rebase", "true", "Rebase anal/meta/comments/flags when reopening file in debugger");
3573 SETCB ("dbg.swstep", "false", &cb_swstep, "Force use of software steps (code analysis+breakpoint)");
3574 SETBPREF ("dbg.trace.inrange", "false", "While tracing, avoid following calls outside specified range");
3575 SETBPREF ("dbg.trace.libs", "true", "Trace library code too");
3576 SETBPREF ("dbg.exitkills", "true", "Kill process on exit");
3577 SETPREF ("dbg.exe.path", "", "Path to binary being debugged");
3578 SETCB ("dbg.execs", "false", &cb_dbg_execs, "Stop execution if new thread is created");
3579 SETICB ("dbg.gdb.page_size", 4096, &cb_dbg_gdb_page_size, "Page size on gdb target (useful for QEMU)");
3580 SETICB ("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out");
3581 SETCB ("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes");
3582
3583 r_config_set_getter (cfg, "dbg.swstep", (RConfigCallback)__dbg_swstep_getter);
3584
3585 // TODO: This should be specified at first by the debug backend when attaching
3586 #if __arm__ || __mips__
3587 SETICB ("dbg.bpsize", 4, &cb_dbgbpsize, "Size of software breakpoints");
3588 #else
3589 SETICB ("dbg.bpsize", 1, &cb_dbgbpsize, "Size of software breakpoints");
3590 #endif
3591 SETBPREF ("dbg.bpsysign", "false", "Ignore system breakpoints");
3592 SETICB ("dbg.btdepth", 128, &cb_dbgbtdepth, "Depth of backtrace");
3593 SETCB ("dbg.trace", "false", &cb_trace, "Trace program execution (see asm.trace)");
3594 SETICB ("dbg.trace.tag", 0, &cb_tracetag, "Trace tag");
3595
3596
3597 /* cmd */
3598 SETCB ("cmd.demangle", "false", &cb_bdc, "run xcrun swift-demangle and similar if available (SLOW)");
3599 SETICB ("cmd.depth", 10, &cb_cmddepth, "Maximum command depth");
3600 SETPREF ("cmd.bp", "", "Run when a breakpoint is hit");
3601 SETPREF ("cmd.onsyscall", "", "Run when a syscall is hit");
3602 SETICB ("cmd.hitinfo", 1, &cb_debug_hitinfo, "Show info when a tracepoint/breakpoint is hit");
3603 SETPREF ("cmd.stack", "", "Command to display the stack in visual debug mode");
3604 SETPREF ("cmd.cprompt", "", "Column visual prompt commands");
3605 SETPREF ("cmd.gprompt", "", "Graph visual prompt commands");
3606 SETPREF ("cmd.hit", "", "Run when a search hit is found");
3607 SETPREF ("cmd.open", "", "Run when file is opened");
3608 SETPREF ("cmd.load", "", "Run when binary is loaded");
3609 RConfigNode *cmdpdc = NODECB ("cmd.pdc", "", &cb_cmdpdc);
3610 SETDESC (cmdpdc, "Select pseudo-decompiler command to run after pdc");
3611 update_cmdpdc_options (core, cmdpdc);
3612 SETCB ("cmd.log", "", &cb_cmdlog, "Every time a new T log is added run this command");
3613 SETPREF ("cmd.prompt", "", "Prompt commands");
3614 SETCB ("cmd.repeat", "false", &cb_cmdrepeat, "Empty command an alias for '..' (repeat last command)");
3615 SETPREF ("cmd.fcn.new", "", "Run when new function is analyzed");
3616 SETPREF ("cmd.fcn.delete", "", "Run when a function is deleted");
3617 SETPREF ("cmd.fcn.rename", "", "Run when a function is renamed");
3618 SETPREF ("cmd.visual", "", "Replace current print mode");
3619 SETPREF ("cmd.vprompt", "", "Visual prompt commands");
3620
3621 SETCB ("cmd.esil.step", "", &cb_cmd_esil_step, "Command to run before performing a step in the emulator");
3622 SETCB ("cmd.esil.stepout", "", &cb_cmd_esil_step_out, "Command to run after performing a step in the emulator");
3623 SETCB ("cmd.esil.mdev", "", &cb_cmd_esil_mdev, "Command to run when memory device address is accessed");
3624 SETCB ("cmd.esil.intr", "", &cb_cmd_esil_intr, "Command to run when an esil interrupt happens");
3625 SETCB ("cmd.esil.trap", "", &cb_cmd_esil_trap, "Command to run when an esil trap happens");
3626 SETCB ("cmd.esil.todo", "", &cb_cmd_esil_todo, "Command to run when the esil instruction contains TODO");
3627 SETCB ("cmd.esil.ioer", "", &cb_cmd_esil_ioer, "Command to run when esil fails to IO (invalid read/write)");
3628
3629 /* filesystem */
3630 n = NODECB ("fs.view", "normal", &cb_fsview);
3631 SETDESC (n, "Set visibility options for filesystems");
3632 SETOPTIONS (n, "all", "deleted", "special", NULL);
3633
3634 /* hexdump */
3635 SETCB ("hex.header", "true", &cb_hex_header, "Show header in hexdump");
3636 SETCB ("hex.bytes", "true", &cb_hex_bytes, "Show bytes column in hexdump");
3637 SETCB ("hex.ascii", "true", &cb_hex_ascii, "Show ascii column in hexdump");
3638 SETCB ("hex.hdroff", "false", &cb_hex_hdroff, "Show aligned 1 byte in header instead of delta nibble");
3639 SETCB ("hex.style", "false", &cb_hex_style, "Improve the hexdump header style");
3640 SETCB ("hex.pairs", "true", &cb_hex_pairs, "Show bytes paired in 'px' hexdump");
3641 SETCB ("hex.align", "false", &cb_hex_align, "Align hexdump with flag + flagsize");
3642 SETCB ("hex.section", "false", &cb_hex_section, "Show section name before the offset");
3643 SETCB ("hex.compact", "false", &cb_hexcompact, "Show smallest 16 byte col hexdump (60 columns)");
3644 SETCB ("cmd.hexcursor", "", &cb_cmd_hexcursor, "If set and cursor is enabled display given pf format string");
3645 SETI ("hex.flagsz", 0, "If non zero, overrides the flag size in pxa");
3646 SETICB ("hex.cols", 16, &cb_hexcols, "Number of columns in hexdump");
3647 SETI ("hex.depth", 5, "Maximal level of recurrence while telescoping memory");
3648 SETBPREF ("hex.onechar", "false", "Number of columns in hexdump");
3649 SETICB ("hex.stride", 0, &cb_hexstride, "Line stride in hexdump (default is 0)");
3650 SETCB ("hex.comments", "true", &cb_hexcomments, "Show comments in 'px' hexdump");
3651
3652 /* http */
3653 SETBPREF ("http.log", "true", "Show HTTP requests processed");
3654 SETPREF ("http.sync", "", "Remote HTTP server to sync events with");
3655 SETBPREF ("http.colon", "false", "Only accept the : command");
3656 SETPREF ("http.logfile", "", "Specify a log file instead of stderr for http requests");
3657 SETBPREF ("http.cors", "false", "Enable CORS");
3658 SETPREF ("http.referer", "", "CSFR protection if set");
3659 SETBPREF ("http.dirlist", "false", "Enable directory listing");
3660 SETPREF ("http.allow", "", "Only accept clients from the comma separated IP list");
3661 #if __WINDOWS__
3662 r_config_set (cfg, "http.browser", "start");
3663 #else
3664 if (r_file_exists ("/usr/bin/openURL")) { // iOS ericautils
3665 r_config_set (cfg, "http.browser", "/usr/bin/openURL");
3666 } else if (r_file_exists ("/system/bin/toolbox")) {
3667 r_config_set (cfg, "http.browser",
3668 "LD_LIBRARY_PATH=/system/lib am start -a android.intent.action.VIEW -d");
3669 } else if (r_file_exists ("/usr/bin/xdg-open")) {
3670 r_config_set (cfg, "http.browser", "xdg-open");
3671 } else if (r_file_exists ("/usr/bin/open")) {
3672 r_config_set (cfg, "http.browser", "open");
3673 } else {
3674 r_config_set (cfg, "http.browser", "firefox");
3675 }
3676 r_config_desc (cfg, "http.browser", "Command to open HTTP URLs");
3677 #endif
3678 SETI ("http.maxsize", 0, "Maximum file size for upload");
3679 SETPREF ("http.index", "index.html", "Main html file to check in directory");
3680 SETPREF ("http.bind", "localhost", "Server address");
3681 SETPREF ("http.homeroot", R_JOIN_2_PATHS ("~", R2_HOME_WWWROOT), "http home root directory");
3682 #if __WINDOWS__
3683 {
3684 char *wwwroot = r_str_newf ("%s\\share\\www", r_sys_prefix (NULL));
3685 SETPREF ("http.root", wwwroot, "http root directory");
3686 free (wwwroot);
3687 }
3688 #elif __ANDROID__
3689 SETPREF ("http.root", "/data/data/org.radare.radare2installer/www", "http root directory");
3690 #else
3691 SETPREF ("http.root", R2_WWWROOT, "http root directory");
3692 #endif
3693 SETPREF ("http.port", "9090", "HTTP server port");
3694 SETPREF ("http.maxport", "9999", "Last HTTP server port");
3695 SETPREF ("http.ui", "m", "Default webui (m, t, f)");
3696 SETBPREF ("http.sandbox", "true", "Sandbox the HTTP server");
3697 SETI ("http.timeout", 3, "Disconnect clients after N seconds of inactivity");
3698 SETI ("http.dietime", 0, "Kill server after N seconds with no client");
3699 SETBPREF ("http.verbose", "false", "Output server logs to stdout");
3700 SETBPREF ("http.upget", "false", "/up/ answers GET requests, in addition to POST");
3701 SETBPREF ("http.upload", "false", "Enable file uploads to /up/<filename>");
3702 SETPREF ("http.uri", "", "Address of HTTP proxy");
3703 SETBPREF ("http.auth", "false", "Enable/Disable HTTP Authentification");
3704 SETPREF ("http.authtok", "r2admin:r2admin", "HTTP Authentification user:password token");
3705 p = r_sys_getenv ("R2_HTTP_AUTHFILE");
3706 SETPREF ("http.authfile", r_str_get (p), "HTTP Authentification user file");
3707 tmpdir = r_file_tmpdir ();
3708 r_config_set (cfg, "http.uproot", tmpdir);
3709 free (tmpdir);
3710 r_config_desc (cfg, "http.uproot", "Path where files are uploaded");
3711
3712 /* tcp */
3713 SETBPREF ("tcp.islocal", "false", "Bind a loopback for tcp command server");
3714
3715 /* graph */
3716 SETBPREF ("graph.aeab", "false", "Show aeab info on each basic block instead of disasm");
3717 SETBPREF ("graph.trace", "false", "Fold all non-traced basic blocks");
3718 SETBPREF ("graph.dummy", "true", "Create dummy nodes in the graph for better layout (20% slower)");
3719 SETBPREF ("graph.few", "false", "Show few basic blocks in the graph");
3720 SETBPREF ("graph.comments", "true", "Show disasm comments in graph");
3721 SETBPREF ("graph.cmtright", "false", "Show comments at right");
3722 SETCB ("graph.gv.format", "gif", &cb_graphformat, "Graph image extension when using 'w' format (png, jpg, pdf, ps, svg, json)");
3723 SETBPREF ("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)");
3724 SETBPREF ("graph.json.usenames", "true", "Use names instead of addresses in Global Call Graph (agCj)");
3725 SETI ("graph.edges", 2, "0=no edges, 1=simple edges, 2=avoid collisions");
3726 SETI ("graph.layout", 0, "Graph layout (0=vertical, 1=horizontal)");
3727 SETI ("graph.linemode", 1, "Graph edges (0=diagonal, 1=square)");
3728 SETPREF ("graph.font", "Courier", "Font for dot graphs");
3729 SETBPREF ("graph.offset", "false", "Show offsets in graphs");
3730 SETBPREF ("graph.bytes", "false", "Show opcode bytes in graphs");
3731 SETBPREF ("graph.web", "false", "Display graph in web browser (VV)");
3732 SETI ("graph.from", UT64_MAX, "Lower bound address when drawing global graphs");
3733 SETI ("graph.to", UT64_MAX, "Upper bound address when drawing global graphs");
3734 SETI ("graph.scroll", 5, "Scroll speed in ascii-art graph");
3735 SETBPREF ("graph.invscroll", "false", "Invert scroll direction in ascii-art graph");
3736 SETPREF ("graph.title", "", "Title of the graph");
3737 SETBPREF ("graph.body", "true", "Show body of the nodes in the graph");
3738 SETBPREF ("graph.bubble", "false", "Show nodes as bubbles");
3739 SETBPREF ("graph.ntitles", "true", "Display title of node");
3740 SETPREF ("graph.gv.node", "", "Graphviz node style. (color=gray, style=filled shape=box)");
3741 SETPREF ("graph.gv.edge", "", "Graphviz edge style. (arrowhead=\"vee\")");
3742 SETPREF ("graph.gv.spline", "", "Graphviz spline style. (splines=\"ortho\")");
3743 SETPREF ("graph.gv.graph", "", "Graphviz global style attributes. (bgcolor=white)");
3744 SETPREF ("graph.gv.current", "false", "Highlight the current node in graphviz graph.");
3745 SETBPREF ("graph.nodejmps", "true", "Enables shortcuts for every node.");
3746 SETBPREF ("graph.hints", "true", "Show true (t) and false (f) hints for conditional edges in graph");
3747 SETCB ("graph.dotted", "false", &cb_dotted, "Dotted lines for conditional jumps in graph");
3748
3749 /* hud */
3750 SETPREF ("hud.path", "", "Set a custom path for the HUD file");
3751
3752 SETCB ("esil.exectrap", "false", &cb_exectrap, "trap when executing code in non-executable memory");
3753 SETCB ("esil.iotrap", "true", &cb_iotrap, "invalid read or writes produce a trap exception");
3754 SETBPREF ("esil.romem", "false", "Set memory as read-only for ESIL");
3755 SETBPREF ("esil.stats", "false", "Statistics from ESIL emulation stored in sdb");
3756 SETBPREF ("esil.nonull", "false", "Prevent memory read, memory write at null pointer");
3757 SETCB ("esil.mdev.range", "", &cb_mdevrange, "Specify a range of memory to be handled by cmd.esil.mdev");
3758
3759 /* json encodings */
3760 n = NODECB ("cfg.json.str", "none", &cb_jsonencoding);
3761 SETDESC (n, "Encode strings from json outputs using the specified option");
3762 SETOPTIONS (n, "none", "base64", "strip", "hex", "array", NULL);
3763
3764 n = NODECB ("cfg.json.num", "none", &cb_jsonencoding_numbers);
3765 SETDESC (n, "Encode numbers from json outputs using the specified option");
3766 SETOPTIONS (n, "none", "string", "hex", NULL);
3767
3768
3769 /* scr */
3770 #if __EMSCRIPTEN__
3771 r_config_set_cb (cfg, "scr.fgets", "true", cb_scrfgets);
3772 #else
3773 r_config_set_cb (cfg, "scr.fgets", "false", cb_scrfgets);
3774 #endif
3775 r_config_desc (cfg, "scr.fgets", "Use fgets() instead of dietline for prompt input");
3776 SETCB ("scr.echo", "false", &cb_screcho, "Show rcons output in realtime to stderr and buffer");
3777 SETICB ("scr.linesleep", 0, &cb_scrlinesleep, "Flush sleeping some ms in every line");
3778 SETICB ("scr.maxtab", 4096, &cb_completion_maxtab, "Change max number of auto completion suggestions");
3779 SETICB ("scr.pagesize", 1, &cb_scrpagesize, "Flush in pages when scr.linesleep is != 0");
3780 SETCB ("scr.flush", "false", &cb_scrflush, "Force flush to console in realtime (breaks scripting)");
3781 SETBPREF ("scr.slow", "true", "Do slow stuff on visual mode like RFlag.get_at(true)");
3782 SETCB ("scr.prompt.popup", "false", &cb_scr_prompt_popup, "Show widget dropdown for autocomplete");
3783 #if __WINDOWS__
3784 SETICB ("scr.vtmode", r_cons_singleton ()->vtmode,
3785 &scr_vtmode, "Use VT sequences on Windows (0: Disable, 1: Output, 2: Input & Output)");
3786 #endif
3787 #if __ANDROID__
3788 SETBPREF ("scr.responsive", "true", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
3789 SETI ("scr.wheel.speed", 1, "Mouse wheel speed");
3790 #else
3791 SETBPREF ("scr.responsive", "false", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
3792 SETI ("scr.wheel.speed", 4, "Mouse wheel speed");
3793 #endif
3794 SETBPREF ("scr.wheel.nkey", "false", "Use sn/sp and scr.nkey on wheel instead of scroll");
3795 // RENAME TO scr.mouse
3796 SETBPREF ("scr.wheel", "true", "Mouse wheel in Visual; temporaryly disable/reenable by right click/Enter)");
3797 SETBPREF ("scr.cursor", "false", "Keyboard controlled cursor in visual and panels");
3798 SETPREF ("scr.layout", "", "Name of the selected layout");
3799 // DEPRECATED: USES hex.cols now SETI ("scr.colpos", 80, "Column position of cmd.cprompt in visual");
3800 SETCB ("scr.breakword", "", &cb_scrbreakword, "Emulate console break (^C) when a word is printed (useful for pD)");
3801 SETCB ("scr.breaklines", "false", &cb_breaklines, "Break lines in Visual instead of truncating them");
3802 SETCB ("scr.gadgets", "true", &cb_scr_gadgets, "Run pg in prompt, visual and panels");
3803 SETBPREF ("scr.panelborder", "false", "Specify panels border active area (0 by default)");
3804 SETICB ("scr.columns", 0, &cb_scrcolumns, "Force console column count (width)");
3805 SETBPREF ("scr.dumpcols", "false", "Prefer pC commands before p ones");
3806 SETCB ("scr.rows", "0", &cb_scrrows, "Force console row count (height) ");
3807 SETICB ("scr.rows", 0, &cb_rows, "Force console row count (height) (duplicate?)");
3808 SETCB ("scr.fps", "false", &cb_fps, "Show FPS in Visual");
3809 SETICB ("scr.fix.rows", 0, &cb_fixrows, "Workaround for Linux TTY");
3810 SETICB ("scr.fix.columns", 0, &cb_fixcolumns, "Workaround for Prompt iOS SSH client");
3811 SETCB ("scr.highlight", "", &cb_scrhighlight, "Highlight that word at RCons level");
3812 SETCB ("scr.interactive", "true", &cb_scrint, "Start in interactive mode");
3813 SETCB ("scr.bgfill", "false", &cb_scr_bgfill, "Fill background for ascii art when possible");
3814 SETI ("scr.feedback", 1, "Set visual feedback level (1=arrow on jump, 2=every key (useful for videos))");
3815 SETCB ("scr.html", "false", &cb_scrhtml, "Disassembly uses HTML syntax");
3816 n = NODECB ("scr.nkey", "flag", &cb_scrnkey);
3817 SETDESC (n, "Select visual seek mode (affects n/N visual commands)");
3818 SETOPTIONS (n, "fun", "hit", "flag", NULL);
3819 SETCB ("scr.pager", "", &cb_pager, "System program (or '..') to use when output exceeds screen boundaries");
3820 SETI ("scr.scrollbar", 0, "Show flagzone (fz) scrollbar in visual mode (0=no,1=right,2=top,3=bottom)");
3821 SETBPREF ("scr.randpal", "false", "Random color palete or just get the next one from 'eco'");
3822 SETCB ("scr.highlight.grep", "false", &cb_scr_color_grep_highlight, "Highlight (INVERT) the grepped words");
3823 SETBPREF ("scr.prompt.file", "false", "Show user prompt file (used by r2 -q)");
3824 SETBPREF ("scr.prompt.flag", "false", "Show flag name in the prompt");
3825 SETBPREF ("scr.prompt.sect", "false", "Show section name in the prompt");
3826 SETBPREF ("scr.tts", "false", "Use tts if available by a command (see ic)");
3827 SETCB ("scr.hist.block", "true", &cb_scr_histblock, "Use blocks for histogram");
3828 SETCB ("scr.prompt", "true", &cb_scrprompt, "Show user prompt (used by r2 -q)");
3829 SETCB ("scr.tee", "", &cb_teefile, "Pipe output to file of this name");
3830 SETPREF ("scr.seek", "", "Seek to the specified address on startup");
3831 SETICB ("scr.color", (core->print->flags&R_PRINT_FLAGS_COLOR)?COLOR_MODE_16:COLOR_MODE_DISABLED, &cb_color, "Enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)");
3832 r_config_set_getter (cfg, "scr.color", (RConfigCallback)cb_color_getter);
3833 SETCB ("scr.color.grep", "false", &cb_scr_color_grep, "Enable colors when using ~grep");
3834 SETBPREF ("scr.color.pipe", "false", "Enable colors when using pipes");
3835 SETBPREF ("scr.color.ops", "true", "Colorize numbers and registers in opcodes");
3836 SETBPREF ("scr.color.args", "true", "Colorize arguments and variables of functions");
3837 SETBPREF ("scr.color.bytes", "true", "Colorize bytes that represent the opcodes of the instruction");
3838 SETCB ("scr.null", "false", &cb_scrnull, "Show no output");
3839 SETCB ("scr.errmode", "echo", &cb_screrrmode, "Error string handling");
3840 SETCB ("scr.utf8", r_str_bool (r_cons_is_utf8()), &cb_utf8, "Show UTF-8 characters instead of ANSI");
3841 SETCB ("scr.utf8.curvy", "false", &cb_utf8_curvy, "Show curved UTF-8 corners (requires scr.utf8)");
3842 SETBPREF ("scr.demo", "false", "Use demoscene effects if available");
3843 SETBPREF ("scr.histsave", "true", "Always save history on exit");
3844 n = NODECB ("scr.strconv", "asciiesc", &cb_scrstrconv);
3845 SETDESC (n, "Convert string before display");
3846 SETOPTIONS (n, "asciiesc", "asciidot", NULL);
3847 SETBPREF ("scr.confirmquit", "false", "Confirm on quit");
3848 SETBPREF ("scr.progressbar", "false", "Display a progress bar when running scripts.");
3849
3850 /* str */
3851 SETCB ("str.escbslash", "false", &cb_str_escbslash, "Escape the backslash");
3852
3853 /* search */
3854 SETCB ("search.contiguous", "true", &cb_contiguous, "Accept contiguous/adjacent search hits");
3855 SETBPREF ("search.verbose", "true", "Make the output of search commands verbose");
3856 SETICB ("search.align", 0, &cb_searchalign, "Only catch aligned search hits");
3857 SETI ("search.chunk", 0, "Chunk size for /+ (default size is asm.bits/8");
3858 SETI ("search.esilcombo", 8, "Stop search after N consecutive hits");
3859 SETI ("search.distance", 0, "Search string distance");
3860 SETBPREF ("search.flags", "true", "All search results are flagged, otherwise only printed");
3861 SETBPREF ("search.overlap", "false", "Look for overlapped search hits");
3862 SETI ("search.maxhits", 0, "Maximum number of hits (0: no limit)");
3863 SETI ("search.from", -1, "Search start address");
3864 n = NODECB ("search.in", "io.maps", &cb_searchin);
3865 SETDESC (n, "Specify search boundaries");
3866 SETOPTIONS (n, "raw", "block",
3867 "bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
3868 "io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3869 "dbg.stack", "dbg.heap",
3870 "dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3871 "anal.fcn", "anal.bb",
3872 NULL);
3873 SETICB ("search.kwidx", 0, &cb_search_kwidx, "Store last search index count");
3874 SETPREF ("search.prefix", "hit", "Prefix name in search hits label");
3875 SETBPREF ("search.show", "true", "Show search results");
3876 SETI ("search.to", -1, "Search end address");
3877
3878 /* rop */
3879 SETI ("rop.len", 5, "Maximum ROP gadget length");
3880 SETBPREF ("rop.sdb", "false", "Cache results in sdb (experimental)");
3881 SETBPREF ("rop.db", "true", "Categorize rop gadgets in sdb");
3882 SETBPREF ("rop.subchains", "false", "Display every length gadget from rop.len=X to 2 in /Rl");
3883 SETBPREF ("rop.conditional", "false", "Include conditional jump, calls and returns in ropsearch");
3884 SETBPREF ("rop.comments", "false", "Display comments in rop search output");
3885
3886 /* io */
3887 SETCB ("io.cache", "false", &cb_io_cache, "Change both of io.cache.{read,write}");
3888 SETCB ("io.cache.auto", "false", &cb_io_cache_mode, "Automatic cache all reads in the IO backend");
3889 SETCB ("io.cache.read", "false", &cb_io_cache_read, "Enable read cache for vaddr (or paddr when io.va=0)");
3890 SETCB ("io.cache.write", "false", &cb_io_cache_write, "Enable write cache for vaddr (or paddr when io.va=0)");
3891 SETCB ("io.pcache", "false", &cb_iopcache, "io.cache for p-level");
3892 SETCB ("io.pcache.write", "false", &cb_iopcachewrite, "Enable write-cache");
3893 SETCB ("io.pcache.read", "false", &cb_iopcacheread, "Enable read-cache");
3894 SETCB ("io.ff", "true", &cb_ioff, "Fill invalid buffers with 0xff instead of returning error");
3895 SETBPREF ("io.exec", "true", "See !!r2 -h~-x");
3896 SETICB ("io.0xff", 0xff, &cb_io_oxff, "Use this value instead of 0xff to fill unallocated areas");
3897 SETCB ("io.aslr", "false", &cb_ioaslr, "Disable ASLR for spawn and such");
3898 SETCB ("io.va", "true", &cb_iova, "Use virtual address layout");
3899 SETCB ("io.pava", "false", &cb_io_pava, "Use EXPERIMENTAL paddr -> vaddr address mode");
3900 SETCB ("io.autofd", "true", &cb_ioautofd, "Change fd when opening a new file");
3901 SETCB ("io.unalloc", "false", &cb_io_unalloc, "Check each byte if it's allocated");
3902 SETCB ("io.unalloc.ch", ".", &cb_io_unalloc_ch, "Char to display if byte is unallocated");
3903
3904 /* file */
3905 SETBPREF ("file.info", "true", "RBin info loaded");
3906 SETPREF ("file.offset", "", "Offset where the file will be mapped at");
3907 SETPREF ("file.type", "", "Type of current file");
3908 SETI ("file.loadalign", 1024, "Alignment of load addresses");
3909 SETI ("file.openmany", 1, "Maximum number of files opened at once");
3910 /* magic */
3911 SETI ("magic.depth", 100, "Recursivity depth in magic description strings");
3912
3913 /* rap */
3914 SETBPREF ("rap.loop", "true", "Run rap as a forever-listening daemon (=:9090)");
3915
3916 /* nkeys */
3917 SETPREF ("key.s", "", "override step into action");
3918 SETPREF ("key.S", "", "override step over action");
3919 for (i = 1; i < 13; i++) {
3920 snprintf (buf, sizeof (buf), "key.f%d", i);
3921 snprintf (buf + 10, sizeof (buf) - 10,
3922 "Run this when F%d key is pressed in visual mode", i);
3923 switch (i) {
3924 default: p = ""; break;
3925 }
3926 r_config_set (cfg, buf, p);
3927 r_config_desc (cfg, buf, buf+10);
3928 }
3929
3930 /* zoom */
3931 SETCB ("zoom.byte", "h", &cb_zoombyte, "Zoom callback to calculate each byte (See pz? for help)");
3932 SETI ("zoom.from", 0, "Zoom start address");
3933 SETI ("zoom.maxsz", 512, "Zoom max size of block");
3934 SETI ("zoom.to", 0, "Zoom end address");
3935 n = NODECB ("zoom.in", "io.map", &cb_searchin);
3936 SETDESC (n, "Specify boundaries for zoom");
3937 SETOPTIONS (n, "raw", "block",
3938 "bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
3939 "io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3940 "dbg.stack", "dbg.heap",
3941 "dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3942 "anal.fcn", "anal.bb",
3943 NULL);
3944 /* lines */
3945 SETI ("lines.from", 0, "Start address for line seek");
3946 SETCB ("lines.to", "$s", &cb_linesto, "End address for line seek");
3947 SETCB ("lines.abs", "false", &cb_linesabs, "Enable absolute line numbers");
3948
3949 r_config_lock (cfg, true);
3950 return true;
3951 }
3952
r_core_parse_radare2rc(RCore * r)3953 R_API void r_core_parse_radare2rc(RCore *r) {
3954 bool has_debug = r_sys_getenv_asbool ("R2_DEBUG");
3955 char *rcfile = r_sys_getenv ("R2_RCFILE");
3956 char *homerc = NULL;
3957 if (!R_STR_ISEMPTY (rcfile)) {
3958 homerc = rcfile;
3959 } else {
3960 free (rcfile);
3961 homerc = r_str_home (".radare2rc");
3962 }
3963 if (homerc && r_file_is_regular (homerc)) {
3964 if (has_debug) {
3965 eprintf ("USER CONFIG loaded from %s\n", homerc);
3966 }
3967 r_core_cmd_file (r, homerc);
3968 }
3969 free (homerc);
3970 homerc = r_str_home (R2_HOME_RC);
3971 if (homerc && r_file_is_regular (homerc)) {
3972 if (has_debug) {
3973 eprintf ("USER CONFIG loaded from %s\n", homerc);
3974 }
3975 r_core_cmd_file (r, homerc);
3976 }
3977 free (homerc);
3978 homerc = r_str_home (R2_HOME_RC_DIR);
3979 if (homerc) {
3980 if (r_file_is_directory (homerc)) {
3981 char *file;
3982 RListIter *iter;
3983 RList *files = r_sys_dir (homerc);
3984 r_list_foreach (files, iter, file) {
3985 if (*file != '.') {
3986 char *path = r_str_newf ("%s/%s", homerc, file);
3987 if (r_file_is_regular (path)) {
3988 if (has_debug) {
3989 eprintf ("USER CONFIG loaded from %s\n", homerc);
3990 }
3991 r_core_cmd_file (r, path);
3992 }
3993 free (path);
3994 }
3995 }
3996 r_list_free (files);
3997 }
3998 free (homerc);
3999 }
4000 }
4001
r_core_config_update(RCore * core)4002 R_API void r_core_config_update(RCore *core) {
4003 RConfigNode *cmdpdc = r_config_node_get (core->config, "cmd.pdc");
4004 update_cmdpdc_options (core, cmdpdc);
4005 }
4006