1 /* radare2 - LGPL - Copyright 2009-2020 - pancake */
2
3 #include <r_core.h>
4 #include <r_socket.h>
5 #include <config.h>
6 #include <r_util.h>
7 #if __UNIX__
8 #include <signal.h>
9 #endif
10
11 #define DB core->sdb
12
13 R_LIB_VERSION(r_core);
14
15 static ut64 letter_divs[R_CORE_ASMQJMPS_LEN_LETTERS - 1] = {
16 R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
17 R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
18 R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
19 R_CORE_ASMQJMPS_LETTERS
20 };
21
22 extern bool r_core_is_project (RCore *core, const char *name);
23
on_fcn_new(RAnal * _anal,void * _user,RAnalFunction * fcn)24 static int on_fcn_new(RAnal *_anal, void* _user, RAnalFunction *fcn) {
25 RCore *core = (RCore*)_user;
26 const char *cmd = r_config_get (core->config, "cmd.fcn.new");
27 if (cmd && *cmd) {
28 ut64 oaddr = core->offset;
29 ut64 addr = fcn->addr;
30 r_core_seek (core, addr, true);
31 r_core_cmd0 (core, cmd);
32 r_core_seek (core, oaddr, true);
33 }
34 return 0;
35 }
36
on_fcn_delete(RAnal * _anal,void * _user,RAnalFunction * fcn)37 static int on_fcn_delete(RAnal *_anal, void* _user, RAnalFunction *fcn) {
38 RCore *core = (RCore*)_user;
39 const char *cmd = r_config_get (core->config, "cmd.fcn.delete");
40 if (cmd && *cmd) {
41 ut64 oaddr = core->offset;
42 ut64 addr = fcn->addr;
43 r_core_seek (core, addr, true);
44 r_core_cmd0 (core, cmd);
45 r_core_seek (core, oaddr, true);
46 }
47 return 0;
48 }
49
on_fcn_rename(RAnal * _anal,void * _user,RAnalFunction * fcn,const char * oname)50 static int on_fcn_rename(RAnal *_anal, void* _user, RAnalFunction *fcn, const char *oname) {
51 RCore *core = (RCore*)_user;
52 const char *cmd = r_config_get (core->config, "cmd.fcn.rename");
53 if (cmd && *cmd) {
54 // XXX: wat do with old name here?
55 ut64 oaddr = core->offset;
56 ut64 addr = fcn->addr;
57 r_core_seek (core, addr, true);
58 r_core_cmd0 (core, cmd);
59 r_core_seek (core, oaddr, true);
60 }
61 return 0;
62 }
63
r_core_debug_breakpoint_hit(RCore * core,RBreakpointItem * bpi)64 static void r_core_debug_breakpoint_hit(RCore *core, RBreakpointItem *bpi) {
65 const char *cmdbp = r_config_get (core->config, "cmd.bp");
66 const bool cmdbp_exists = (cmdbp && *cmdbp);
67 const bool bpcmd_exists = (bpi->data && bpi->data[0]);
68 const bool may_output = (cmdbp_exists || bpcmd_exists);
69 if (may_output) {
70 r_cons_push ();
71 }
72 if (cmdbp_exists) {
73 r_core_cmd0 (core, cmdbp);
74 }
75 if (bpcmd_exists) {
76 r_core_cmd0 (core, bpi->data);
77 }
78 if (may_output) {
79 r_cons_flush ();
80 r_cons_pop ();
81 }
82 }
83
r_core_debug_syscall_hit(RCore * core)84 static void r_core_debug_syscall_hit(RCore *core) {
85 const char *cmdhit = r_config_get (core->config, "cmd.onsyscall");
86
87 if (cmdhit && cmdhit[0] != 0) {
88 r_core_cmd0 (core, cmdhit);
89 r_cons_flush ();
90 }
91 }
92
93 struct getreloc_t {
94 ut64 vaddr;
95 int size;
96 };
97
getreloc_tree(const void * user,const RBNode * n,void * user2)98 static int getreloc_tree(const void *user, const RBNode *n, void *user2) {
99 struct getreloc_t *gr = (struct getreloc_t *)user;
100 const RBinReloc *r = container_of (n, const RBinReloc, vrb);
101 if ((r->vaddr >= gr->vaddr) && (r->vaddr < (gr->vaddr + gr->size))) {
102 return 0;
103 }
104 if (gr->vaddr > r->vaddr) {
105 return 1;
106 }
107 if (gr->vaddr < r->vaddr) {
108 return -1;
109 }
110 return 0;
111 }
112
r_core_getreloc(RCore * core,ut64 addr,int size)113 R_API RBinReloc *r_core_getreloc(RCore *core, ut64 addr, int size) {
114 if (size < 1 || addr == UT64_MAX) {
115 return NULL;
116 }
117 RBNode *relocs = r_bin_get_relocs (core->bin);
118 if (!relocs) {
119 return NULL;
120 }
121 struct getreloc_t gr = { .vaddr = addr, .size = size };
122 RBNode *res = r_rbtree_find (relocs, &gr, getreloc_tree, NULL);
123 return res? container_of (res, RBinReloc, vrb): NULL;
124 }
125
126 /* returns the address of a jmp/call given a shortcut by the user or UT64_MAX
127 * if there's no valid shortcut. When is_asmqjmps_letter is true, the string
128 * should be of the form XYZWu, where XYZW are uppercase letters and u is a
129 * lowercase one. If is_asmqjmps_letter is false, the string should be a number
130 * between 1 and 9 included. */
r_core_get_asmqjmps(RCore * core,const char * str)131 R_API ut64 r_core_get_asmqjmps(RCore *core, const char *str) {
132 if (!core->asmqjmps) {
133 return UT64_MAX;
134 }
135 if (core->is_asmqjmps_letter) {
136 int i, pos = 0;
137 int len = strlen (str);
138 for (i = 0; i < len - 1; i++) {
139 if (!isupper ((ut8)str[i])) {
140 return UT64_MAX;
141 }
142 pos *= R_CORE_ASMQJMPS_LETTERS;
143 pos += str[i] - 'A' + 1;
144 }
145 if (!islower ((ut8)str[i])) {
146 return UT64_MAX;
147 }
148 pos *= R_CORE_ASMQJMPS_LETTERS;
149 pos += str[i] - 'a';
150 if (pos < core->asmqjmps_count) {
151 return core->asmqjmps[pos + 1];
152 }
153 } else if (str[0] > '0' && str[1] <= '9') {
154 int pos = str[0] - '0';
155 if (pos <= core->asmqjmps_count) {
156 return core->asmqjmps[pos];
157 }
158 }
159 return UT64_MAX;
160 }
161
162 /**
163 * Takes addr and returns already saved shortcut or a new one
164 * The returned buffer needs to be freed
165 */
r_core_add_asmqjmp(RCore * core,ut64 addr)166 R_API char* r_core_add_asmqjmp(RCore *core, ut64 addr) {
167 bool found = false;
168 if (!core->asmqjmps) {
169 return NULL;
170 }
171 if (core->is_asmqjmps_letter) {
172 if (core->asmqjmps_count >= R_CORE_ASMQJMPS_MAX_LETTERS) {
173 return NULL;
174 }
175 if (core->asmqjmps_count >= core->asmqjmps_size - 2) {
176 core->asmqjmps = realloc (core->asmqjmps, core->asmqjmps_size * 2 * sizeof (ut64));
177 if (!core->asmqjmps) {
178 return NULL;
179 }
180 core->asmqjmps_size *= 2;
181 }
182 }
183 if (core->asmqjmps_count < core->asmqjmps_size - 1) {
184 int i = 0;
185 char t[R_CORE_ASMQJMPS_LEN_LETTERS + 1] = {0};
186 for (i = 0; i < core->asmqjmps_count + 1; i++) {
187 if (core->asmqjmps[i] == addr) {
188 found = true;
189 break;
190 }
191 }
192 if (!found) {
193 i = ++core->asmqjmps_count;
194 core->asmqjmps[i] = addr;
195 }
196 // This check makes pos never be <1, thefor not fill 't' with trash
197 if (i < 1) {
198 return NULL;
199 }
200 r_core_set_asmqjmps (core, t, sizeof (t), i);
201 return strdup (t);
202 }
203 return NULL;
204 }
205
206 /* returns in str a string that represents the shortcut to access the asmqjmp
207 * at position pos. When is_asmqjmps_letter is true, pos is converted into a
208 * multiletter shortcut of the form XYWZu and returned (see r_core_get_asmqjmps
209 * for more info). Otherwise, the shortcut is the string representation of pos. */
r_core_set_asmqjmps(RCore * core,char * str,size_t len,int pos)210 R_API void r_core_set_asmqjmps(RCore *core, char *str, size_t len, int pos) {
211 if (core->is_asmqjmps_letter) {
212 int i, j = 0;
213 // if (pos > 0) {
214 pos --;
215 //// }
216 for (i = 0; i < R_CORE_ASMQJMPS_LEN_LETTERS - 1; i++) {
217 int div = pos / letter_divs[i];
218 pos %= letter_divs[i];
219 if (div > 0 && j < len) {
220 str[j++] = 'A' + div - 1;
221 }
222 }
223 if (j < len) {
224 int div = pos % R_CORE_ASMQJMPS_LETTERS;
225 str[j++] = 'a' + div;
226 }
227 str[j] = '\0';
228 } else {
229 snprintf (str, len, "%d", pos);
230 }
231 }
232
setab(RCore * core,const char * arch,int bits)233 static void setab(RCore *core, const char *arch, int bits) {
234 if (arch) {
235 r_config_set (core->config, "asm.arch", arch);
236 }
237 if (bits > 0) {
238 r_config_set_i (core->config, "asm.bits", bits);
239 }
240 }
241
getName(RCore * core,ut64 addr)242 static const char *getName(RCore *core, ut64 addr) {
243 RFlagItem *item = r_flag_get_i (core->flags, addr);
244 if (item) {
245 if (core->flags->realnames) {
246 return item->realname
247 ? item->realname: item->name;
248 }
249 return item->name;
250 }
251 return NULL;
252 }
253
getNameDelta(RCore * core,ut64 addr)254 static char *getNameDelta(RCore *core, ut64 addr) {
255 RFlagItem *item = r_flag_get_at (core->flags, addr, true);
256 if (item) {
257 if (item->offset != addr) {
258 return r_str_newf ("%s + %d", item->name, (int)(addr - item->offset));
259 }
260 return strdup (item->name);
261 }
262 return NULL;
263 }
264
archbits(RCore * core,ut64 addr)265 static void archbits(RCore *core, ut64 addr) {
266 r_core_seek_arch_bits (core, addr);
267 }
268
cfggeti(RCore * core,const char * k)269 static int cfggeti(RCore *core, const char *k) {
270 return r_config_get_i (core->config, k);
271 }
272
cfgget(RCore * core,const char * k)273 static const char *cfgget(RCore *core, const char *k) {
274 return r_config_get (core->config, k);
275 }
276
numget(RCore * core,const char * k)277 static ut64 numget(RCore *core, const char *k) {
278 return r_num_math (core->num, k);
279 }
280
__isMapped(RCore * core,ut64 addr,int perm)281 static bool __isMapped(RCore *core, ut64 addr, int perm) {
282 if (r_config_get_i (core->config, "cfg.debug")) {
283 // RList *maps = core->dbg->maps;
284 RDebugMap *map = NULL;
285 RListIter *iter = NULL;
286
287 r_list_foreach (core->dbg->maps, iter, map) {
288 if (addr >= map->addr && addr < map->addr_end) {
289 if (perm > 0) {
290 if (map->perm & perm) {
291 return true;
292 }
293 } else {
294 return true;
295 }
296 }
297 }
298 return false;
299 }
300
301 return r_io_map_is_mapped (core->io, addr);
302 }
303
__syncDebugMaps(RCore * core)304 static bool __syncDebugMaps(RCore *core) {
305 if (r_config_get_i (core->config, "cfg.debug")) {
306 return r_debug_map_sync (core->dbg);
307 }
308 return false;
309 }
310
r_core_bind(RCore * core,RCoreBind * bnd)311 R_API int r_core_bind(RCore *core, RCoreBind *bnd) {
312 bnd->core = core;
313 bnd->bphit = (RCoreDebugBpHit)r_core_debug_breakpoint_hit;
314 bnd->syshit = (RCoreDebugSyscallHit)r_core_debug_syscall_hit;
315 bnd->cmd = (RCoreCmd)r_core_cmd0;
316 bnd->cmdf = (RCoreCmdF)r_core_cmdf;
317 bnd->cmdstr = (RCoreCmdStr)r_core_cmd_str;
318 bnd->cmdstrf = (RCoreCmdStrF)r_core_cmd_strf;
319 bnd->puts = (RCorePuts)r_cons_strcat;
320 bnd->setab = (RCoreSetArchBits)setab;
321 bnd->getName = (RCoreGetName)getName;
322 bnd->getNameDelta = (RCoreGetNameDelta)getNameDelta;
323 bnd->archbits = (RCoreSeekArchBits)archbits;
324 bnd->cfggeti = (RCoreConfigGetI)cfggeti;
325 bnd->cfgGet = (RCoreConfigGet)cfgget;
326 bnd->numGet = (RCoreNumGet)numget;
327 bnd->isMapped = (RCoreIsMapped)__isMapped;
328 bnd->syncDebugMaps = (RCoreDebugMapsSync)__syncDebugMaps;
329 bnd->pjWithEncoding = (RCorePJWithEncoding)r_core_pj_new;
330 return true;
331 }
332
r_core_ncast(ut64 p)333 R_API RCore *r_core_ncast(ut64 p) {
334 return (RCore*)(size_t)p;
335 }
336
r_core_cast(void * p)337 R_API RCore *r_core_cast(void *p) {
338 return (RCore*)p;
339 }
340
getref(RCore * core,int n,char t,int type)341 static ut64 getref (RCore *core, int n, char t, int type) {
342 RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
343 RListIter *iter;
344 RAnalRef *r;
345 RList *list;
346 int i = 0;
347 if (!fcn) {
348 return UT64_MAX;
349 }
350 if (t == 'r') {
351 list = r_anal_function_get_refs (fcn);
352 } else {
353 list = r_anal_function_get_xrefs (fcn);
354 }
355 r_list_foreach (list, iter, r) {
356 if (r->type == type) {
357 if (i == n) {
358 ut64 addr = r->addr;
359 r_list_free (list);
360 return addr;
361 }
362 i++;
363 }
364 }
365 r_list_free (list);
366
367 return UT64_MAX;
368 }
369
bbInstructions(RAnalFunction * fcn,ut64 addr)370 static ut64 bbInstructions(RAnalFunction *fcn, ut64 addr) {
371 RListIter *iter;
372 RAnalBlock *bb;
373 r_list_foreach (fcn->bbs, iter, bb) {
374 if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
375 return bb->ninstr;
376 }
377 }
378 return UT64_MAX;
379 }
380
bbBegin(RAnalFunction * fcn,ut64 addr)381 static ut64 bbBegin(RAnalFunction *fcn, ut64 addr) {
382 RListIter *iter;
383 RAnalBlock *bb;
384 r_list_foreach (fcn->bbs, iter, bb) {
385 if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
386 return bb->addr;
387 }
388 }
389 return UT64_MAX;
390 }
391
bbJump(RAnalFunction * fcn,ut64 addr)392 static ut64 bbJump(RAnalFunction *fcn, ut64 addr) {
393 RListIter *iter;
394 RAnalBlock *bb;
395 r_list_foreach (fcn->bbs, iter, bb) {
396 if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
397 return bb->jump;
398 }
399 }
400 return UT64_MAX;
401 }
402
bbFail(RAnalFunction * fcn,ut64 addr)403 static ut64 bbFail(RAnalFunction *fcn, ut64 addr) {
404 RListIter *iter;
405 RAnalBlock *bb;
406 r_list_foreach (fcn->bbs, iter, bb) {
407 if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
408 return bb->fail;
409 }
410 }
411 return UT64_MAX;
412 }
413
bbSize(RAnalFunction * fcn,ut64 addr)414 static ut64 bbSize(RAnalFunction *fcn, ut64 addr) {
415 RListIter *iter;
416 RAnalBlock *bb;
417 r_list_foreach (fcn->bbs, iter, bb) {
418 if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
419 return bb->size;
420 }
421 }
422 return 0;
423 }
424
str_callback(RNum * user,ut64 off,int * ok)425 static const char *str_callback(RNum *user, ut64 off, int *ok) {
426 RFlag *f = (RFlag*)user;
427 if (ok) {
428 *ok = 0;
429 }
430 if (f) {
431 RFlagItem *item = r_flag_get_i (f, off);
432 if (item) {
433 if (ok) {
434 *ok = true;
435 }
436 return item->name;
437 }
438 }
439 return NULL;
440 }
441
numvar_instruction_backward(RCore * core,const char * input)442 static ut64 numvar_instruction_backward(RCore *core, const char *input) {
443 // N forward instructions
444 int i, ret;
445 int n = 1;
446 if (isdigit ((unsigned char)input[0])) {
447 n = atoi (input);
448 } else if (input[0] == '{') {
449 n = atoi (input + 1);
450 }
451 if (n < 1) {
452 r_cons_eprintf ("Invalid negative value%c", 10);
453 n = 1;
454 }
455 int numinstr = n;
456 // N previous instructions
457 ut64 addr = core->offset;
458 ut64 val = addr;
459 if (r_core_prevop_addr (core, core->offset, numinstr, &addr)) {
460 val = addr;
461 } else {
462 ut8 data[32];
463 addr = core->offset;
464 const int mininstrsize = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
465 for (i = 0; i < numinstr; i++) {
466 ut64 prev_addr = r_core_prevop_addr_force (core, addr, 1);
467 if (prev_addr == UT64_MAX) {
468 prev_addr = addr - mininstrsize;
469 }
470 if (prev_addr == UT64_MAX || prev_addr >= core->offset) {
471 break;
472 }
473 RAnalOp op = {0};
474 ret = r_anal_op (core->anal, &op, prev_addr, data,
475 sizeof (data), R_ANAL_OP_MASK_BASIC);
476 if (ret < 1) {
477 ret = 1;
478 }
479 if (op.size < mininstrsize) {
480 op.size = mininstrsize;
481 }
482 val -= op.size;
483 r_anal_op_fini (&op);
484 addr = prev_addr;
485 }
486 }
487 return val;
488 }
489
numvar_instruction(RCore * core,const char * input)490 static ut64 numvar_instruction(RCore *core, const char *input) {
491 ut64 addr = core->offset;
492 // N forward instructions
493 ut8 data[32];
494 int i, ret;
495 ut64 val = addr;
496 int n = 1;
497 if (input[0] == '{') {
498 n = atoi (input + 1);
499 }
500 if (n < 1) {
501 r_cons_eprintf ("Invalid negative value%c", 10);
502 n = 1;
503 }
504 for (i = 0; i < n; i++) {
505 r_io_read_at (core->io, val, data, sizeof (data));
506 RAnalOp op;
507 ret = r_anal_op (core->anal, &op, val, data,
508 sizeof (data), R_ANAL_OP_MASK_BASIC);
509 if (ret < 1) {
510 ret = 1;
511 }
512 val += op.size;
513 r_anal_op_fini (&op);
514 //val += ret;
515 }
516 return val;
517
518 }
519
num_callback(RNum * userptr,const char * str,int * ok)520 static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
521 RCore *core = (RCore *)userptr; // XXX ?
522 RAnalFunction *fcn;
523 char *ptr, *bptr, *out = NULL;
524 RFlagItem *flag;
525 RBinSection *s;
526 RAnalOp op;
527 ut64 ret = 0;
528
529 if (ok) {
530 *ok = false;
531 }
532 switch (*str) {
533 case '.':
534 if (str[1] == '.') {
535 if (ok) {
536 *ok = true;
537 }
538 return r_num_tail (core->num, core->offset, str + 2);
539 }
540 if (core->num->nc.curr_tok == '+') {
541 ut64 off = core->num->nc.number_value.n;
542 if (!off) {
543 off = core->offset;
544 }
545 RAnalFunction *fcn = r_anal_get_function_at (core->anal, off);
546 if (fcn) {
547 if (ok) {
548 *ok = true;
549 }
550 ut64 dst = r_anal_function_get_label (fcn, str + 1);
551 if (dst == UT64_MAX) {
552 dst = fcn->addr;
553 }
554 st64 delta = dst - off;
555 if (delta < 0) {
556 core->num->nc.curr_tok = '-';
557 delta = off - dst;
558 }
559 return delta;
560 }
561 }
562 break;
563 case '[':
564 {
565 ut64 n = 0LL;
566 int refsz = core->rasm->bits / 8;
567 const char *p = NULL;
568 if (strlen (str) > 5) {
569 p = strchr (str + 5, ':');
570 }
571 if (p) {
572 refsz = atoi (str + 1);
573 str = p;
574 }
575 // push state
576 if (str[0] && str[1]) {
577 const char *q;
578 char *o = strdup (str + 1);
579 if (o) {
580 q = r_num_calc_index (core->num, NULL);
581 if (q) {
582 if (r_str_replace_char (o, ']', 0)>0) {
583 n = r_num_math (core->num, o);
584 if (core->num->nc.errors) {
585 return 0;
586 }
587 r_num_calc_index (core->num, q);
588 }
589 }
590 free (o);
591 }
592 } else {
593 return 0;
594 }
595 // pop state
596 if (ok) {
597 *ok = 1;
598 }
599 ut8 buf[sizeof (ut64)] = R_EMPTY;
600 (void)r_io_read_at (core->io, n, buf, R_MIN (sizeof (buf), refsz));
601 switch (refsz) {
602 case 8:
603 return r_read_ble64 (buf, core->print->big_endian);
604 case 4:
605 return r_read_ble32 (buf, core->print->big_endian);
606 case 2:
607 return r_read_ble16 (buf, core->print->big_endian);
608 case 1:
609 return r_read_ble8 (buf);
610 default:
611 r_cons_eprintf ("Invalid reference size: %d (%s)\n", refsz, str);
612 return 0LL;
613 }
614 }
615 break;
616 case '$':
617 if (ok) {
618 *ok = 1;
619 }
620 // TODO: group analop-dependant vars after a char, so i can filter
621 r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize, R_ANAL_OP_MASK_BASIC);
622 r_anal_op_fini (&op); // we don't need strings or pointers, just values, which are not nullified in fini
623 // XXX the above line is assuming op after fini keeps jump, fail, ptr, val, size and r_anal_op_is_eob()
624 switch (str[1]) {
625 case 'i': // "$i"
626 if (ok) {
627 *ok = true;
628 }
629 return numvar_instruction (core, str + 2);
630 case 'I': // "$I"
631 if (ok) {
632 *ok = true;
633 }
634 return numvar_instruction_backward (core, str + 2);
635 case '.': // can use pc, sp, a0, a1, ...
636 return r_debug_reg_get (core->dbg, str + 2);
637 case 'k': // $k{kv}
638 if (str[2] != '{') {
639 r_cons_eprintf ("Expected '{' after 'k'.\n");
640 break;
641 }
642 bptr = strdup (str + 3);
643 ptr = strchr (bptr, '}');
644 if (!ptr) {
645 // invalid json
646 free (bptr);
647 break;
648 }
649 *ptr = '\0';
650 ret = 0LL;
651 out = sdb_querys (core->sdb, NULL, 0, bptr);
652 if (out && *out) {
653 if (strstr (out, "$k{")) {
654 r_cons_eprintf ("Recursivity is not permitted here\n");
655 } else {
656 ret = r_num_math (core->num, out);
657 }
658 }
659 free (bptr);
660 free (out);
661 return ret;
662 case '{': // ${ev} eval var
663 bptr = strdup (str + 2);
664 ptr = strchr (bptr, '}');
665 if (ptr) {
666 ptr[0] = '\0';
667 ut64 ret = r_config_get_i (core->config, bptr);
668 free (bptr);
669 return ret;
670 }
671 // take flag here
672 free (bptr);
673 break;
674 case 'c': // $c console width
675 return r_cons_get_size (NULL);
676 case 'd': // $d - same as 'op'
677 if (core->io && core->io->desc) {
678 return core->io->desc->fd;
679 }
680 return 0;
681 case 'r': // $r
682 if (str[2] == '{') {
683 bptr = strdup (str + 3);
684 ptr = strchr (bptr, '}');
685 if (!ptr) {
686 free (bptr);
687 break;
688 }
689 *ptr = 0;
690 if (r_config_get_i (core->config, "cfg.debug")) {
691 if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
692 RRegItem *r = r_reg_get (core->dbg->reg, bptr, -1);
693 if (r) {
694 free (bptr);
695 return r_reg_get_value (core->dbg->reg, r);
696 }
697 }
698 } else {
699 RRegItem *r = r_reg_get (core->anal->reg, bptr, -1);
700 if (r) {
701 free (bptr);
702 return r_reg_get_value (core->anal->reg, r);
703 }
704 }
705 free (bptr);
706 return 0; // UT64_MAX;
707 } else {
708 int rows;
709 (void)r_cons_get_size (&rows);
710 return rows;
711 }
712 break;
713 case 'e': // $e
714 if (str[2] == '{') { // $e{flag} flag off + size
715 char *flagName = strdup (str + 3);
716 int flagLength = strlen (flagName);
717 if (flagLength > 0) {
718 flagName[flagLength - 1] = 0;
719 }
720 RFlagItem *flag = r_flag_get (core->flags, flagName);
721 free (flagName);
722 if (flag) {
723 return flag->offset + flag->size;
724 }
725 return UT64_MAX;
726 }
727 return r_anal_op_is_eob (&op);
728 case 'j': // $j jump address
729 return op.jump;
730 case 'p': // $p
731 return r_sys_getpid ();
732 case 'P': // $P
733 return core->dbg->pid > 0 ? core->dbg->pid : 0;
734 case 'f': // $f jump fail address
735 if (str[2] == 'l') { // $fl flag length
736 RFlagItem *fi = r_flag_get_i (core->flags, core->offset);
737 if (fi) {
738 return fi->size;
739 }
740 return 0;
741 }
742 return op.fail;
743 case 'm': // $m memref
744 return op.ptr;
745 case 'B': // $B base address
746 case 'M': { // $M map address
747 ut64 lower = UT64_MAX;
748 ut64 size = 0LL;
749 RIOMap *map = r_io_map_get (core->io, core->offset);
750 if (map) {
751 lower = r_io_map_begin (map);
752 size = r_io_map_size (map);
753 }
754
755 if (str[1] == 'B') {
756 /* clear lower bits of the lowest map address to define the base address */
757 const int clear_bits = 16;
758 lower >>= clear_bits;
759 lower <<= clear_bits;
760 }
761 if (str[2] == 'M') {
762 return size;
763 }
764 return (lower == UT64_MAX)? 0LL: lower;
765 }
766 break;
767 case 'v': // $v immediate value
768 return op.val;
769 case 'l': // $l opcode length
770 return op.size;
771 case 'b': // $b
772 return core->blocksize;
773 case 's': // $s file size
774 if (str[2] == '{') { // $s{flag} flag size
775 bptr = strdup (str + 3);
776 ptr = strchr (bptr, '}');
777 if (!ptr) {
778 // invalid json
779 free (bptr);
780 break;
781 }
782 *ptr = '\0';
783 RFlagItem *flag = r_flag_get (core->flags, bptr);
784 ret = flag? flag->size: 0LL; // flag
785 free (bptr);
786 free (out);
787 return ret;
788 } else if (core->io->desc) {
789 return r_io_fd_size (core->io, core->io->desc->fd);
790 }
791 return 0LL;
792 case 'w': // $w word size
793 return r_config_get_i (core->config, "asm.bits") / 8;
794 case 'S': // $S section offset
795 {
796 RBinObject *bo = r_bin_cur_object (core->bin);
797 if (bo && (s = r_bin_get_section_at (bo, core->offset, true))) {
798 return (str[2] == 'S'? s->size: s->vaddr);
799 }
800 }
801 return 0LL;
802 case 'D': // $D
803 if (str[2] == 'B') { // $DD
804 return r_debug_get_baddr (core->dbg, NULL);
805 } else if (IS_DIGIT (str[2])) {
806 return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_DATA);
807 } else {
808 RDebugMap *map;
809 RListIter *iter;
810 r_list_foreach (core->dbg->maps, iter, map) {
811 if (core->offset >= map->addr && core->offset < map->addr_end) {
812 return (str[2] == 'D')? map->size: map->addr;
813 }
814 }
815 }
816 return 0LL; // maybe // return UT64_MAX;
817 case '?': // $?
818 return core->num->value; // rc;
819 case '$': // $$ offset
820 return str[2] == '$' ? core->prompt_offset : core->offset;
821 case 'o': { // $o
822 RBinSection *s = r_bin_get_section_at (r_bin_cur_object (core->bin), core->offset, true);
823 return s ? core->offset - s->vaddr + s->paddr : core->offset;
824 break;
825 }
826 case 'O': // $O
827 if (core->print->cur_enabled) {
828 return core->offset + core->print->cur;
829 }
830 return core->offset;
831 case 'C': // $C nth call
832 return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_CALL);
833 case 'J': // $J nth jump
834 return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_CODE);
835 case 'X': // $X nth xref
836 return getref (core, atoi (str + 2), 'x', R_ANAL_REF_TYPE_CALL);
837 case 'F': // $F function size
838 fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
839 if (fcn) {
840 switch (str[2]) {
841 /* function bounds (uppercase) */
842 case 'B': return fcn->addr; // begin
843 case 'E': return r_anal_function_max_addr (fcn); // end
844 case 'S': return (str[3]=='S') ? r_anal_function_realsize (fcn) : r_anal_function_linear_size (fcn);
845 case 'I': return fcn->ninstr;
846 /* basic blocks (lowercase) */
847 case 'b': return bbBegin (fcn, core->offset);
848 case 'e': return bbBegin (fcn, core->offset) + bbSize (fcn, core->offset);
849 case 'i': return bbInstructions (fcn, core->offset);
850 case 's': return bbSize (fcn, core->offset);
851 case 'j': return bbJump (fcn, core->offset); // jump
852 case 'f': return bbFail (fcn, core->offset); // fail
853 }
854 return fcn->addr;
855 }
856 return 0;
857 default:
858 r_cons_eprintf ("Invalid variable '%s'\n", str);
859 return 0;
860 }
861 break;
862 default:
863 if (*str >= 'A' || *str == ':' || *str == '_') {
864 // NOTE: functions override flags
865 RAnalFunction *fcn = r_anal_get_function_byname (core->anal, str);
866 if (fcn) {
867 if (ok) {
868 *ok = true;
869 }
870 return fcn->addr;
871 }
872 #if 0
873 ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str);
874 if (addr != 0) {
875 ret = addr;
876 } else {
877 ...
878 }
879 #endif
880 if ((flag = r_flag_get (core->flags, str))) {
881 ret = flag->offset;
882 if (ok) {
883 *ok = true;
884 }
885 return ret;
886 }
887
888 // check for reg alias
889 struct r_reg_item_t *r = r_reg_get (core->dbg->reg, str, -1);
890 if (!r) {
891 int role = r_reg_get_name_idx (str);
892 if (role != -1) {
893 const char *alias = r_reg_get_name (core->dbg->reg, role);
894 if (alias) {
895 r = r_reg_get (core->dbg->reg, alias, -1);
896 if (r) {
897 if (ok) {
898 *ok = true;
899 }
900 ret = r_reg_get_value (core->dbg->reg, r);
901 return ret;
902 }
903 }
904 }
905 } else {
906 if (ok) {
907 *ok = true;
908 }
909 ret = r_reg_get_value (core->dbg->reg, r);
910 return ret;
911 }
912 }
913 break;
914 }
915
916 return ret;
917 }
918
r_core_new(void)919 R_API RCore *r_core_new(void) {
920 RCore *c = R_NEW0 (RCore);
921 if (c) {
922 r_core_init (c);
923 }
924 return c;
925 }
926
927 /*-----------------------------------*/
928 #define radare_argc (sizeof (radare_argv) / sizeof(const char*) - 1)
929 #define ms_argc (sizeof (ms_argv) / sizeof (const char*) - 1)
930 static const char *ms_argv[] = {
931 "?", "!", "ls", "cd", "cat", "get", "mount", "help", "q", "exit", NULL
932 };
933
934 static const char *radare_argv[] = {
935 "whereis", "which", "ls", "rm", "mkdir", "pwd", "cat", "sort", "uniq", "join", "less", "exit", "quit",
936 "#?", "#!", "#sha1", "#crc32", "#pcprint", "#sha256", "#sha512", "#md4", "#md5",
937 "#!python", "#!vala", "#!pipe",
938 "*?", "*", "$",
939 "(", "(*", "(-", "()", ".?", ".", "..", "...", ".:", ".--", ".-", ".!", ".(", "./", ".*",
940 "_?", "_",
941 "=?", "=", "=<", "=!", "=+", "=-", "==", "=!=", "!=!", "=:", "=&:",
942 "=g?", "=g", "=g!", "=h?", "=h", "=h-", "=h--", "=h*", "=h&", "=H?", "=H", "=H&",
943 "<",
944 "/?", "/", "/j", "/j!", "/j!x", "/+", "//", "/a", "/a1", "/ab", "/ad", "/aa", "/as", "/asl", "/at", "/atl", "/af", "/afl", "/ae", "/aej", "/ai", "/aij",
945 "/c", "/ca", "/car", "/d", "/e", "/E", "/Ej", "/f", "/F", "/g", "/gg", "/h", "/ht", "/i", "/m", "/mb", "/mm",
946 "/o", "/O", "/p", "/P", "/s", "/s*", "/r?", "/r", "/ra", "/rc", "/re", "/rr", "/rw", "/rc",
947 "/R",
948 "/v?", "/v", "/v1", "/v2", "/v4", "/v8",
949 "/V?", "/V", "/V1", "/V2", "/V4", "/V8",
950 "/w", "/wi", "/x", "/z",
951 "!?", "!", "!!", "!!!", "!!!-", "!-", "!-*", "!=!",
952 "a?", "a", "aa", "aa*",
953 "aaa", "aab", "aac", "aac*", "aad", "aae", "aaf", "aaF", "aaFa", "aai", "aaij", "aan", "aang", "aao", "aap",
954 "aar?", "aar", "aar*", "aarj", "aas", "aat", "aaT", "aau", "aav",
955 "a8", "ab", "abb",
956 "acl", "acll", "aclj", "acl*", "ac?", "ac", "ac-", "acn", "acv", "acvf", "acv-", "acb", "acb-", "acm", "acm-", "acmn",
957 "aC?", "aC", "aCe", "ad", "ad4", "ad8", "adf", "adfg", "adt", "adk",
958 "ae?", "ae??", "ae", "aea", "aeA", "aeaf", "aeAf", "aeC", "aec?", "aec", "aecs", "aecc", "aecu", "aecue",
959 "aef", "aefa",
960 "aei", "aeim", "aeip", "aek", "aek-", "aeli", "aelir", "aep?", "aep", "aep-", "aepc",
961 "aer", "aets?", "aets+", "aets-", "aes", "aesp", "aesb", "aeso", "aesou", "aess", "aesu", "aesue", "aetr", "aex",
962 "af?", "af", "afr", "af+", "af-",
963 "afa", "afan",
964 "afb?", "afb", "afb.", "afb+", "afbb", "afbr", "afbi", "afbj", "afbe", "afB", "afbc", "afb=",
965 "afB", "afC", "afCl", "afCc", "afc?", "afc", "afcr", "afcrj", "afca", "afcf", "afcfj",
966 "afck", "afcl", "afco", "afcR",
967 "afd", "aff", "afF", "afi",
968 "afl?", "afl", "afl+", "aflc", "aflj", "afll", "afllj", "aflm", "aflq", "aflqj", "afls",
969 "afm", "afM", "afn?", "afna", "afns", "afnsj", "afl=",
970 "afo", "afs", "afS", "aft?", "aft", "afu",
971 "afv?", "afv", "afvr?", "afvr", "afvr*", "afvrj", "afvr-", "afvrg", "afvrs",
972 "afvb?", "afvb", "afvbj", "afvb-", "afvbg", "afvbs",
973 "afvs?", "afvs", "afvs*", "afvsj", "afvs-", "afvsg", "afvss",
974 "afv*", "afvR", "afvW", "afva", "afvd", "afvn", "afvt", "afv-", "af*", "afx",
975 "aF",
976 "ag?", "ag", "aga", "agA", "agc", "agC", "agd", "agf", "agi", "agr", "agR", "agx", "agg", "ag-",
977 "agn?", "agn", "agn-", "age?", "age", "age-",
978 "agl", "agfl",
979 "ah?", "ah", "ah.", "ah-", "ah*", "aha", "ahb", "ahc", "ahe", "ahf", "ahh", "ahi?", "ahi", "ahj", "aho",
980 "ahp", "ahr", "ahs", "ahS", "aht",
981 "ai", "aL", "an",
982 "ao?", "ao", "aoj", "aoe", "aor", "aos", "aom", "aod", "aoda", "aoc", "ao*",
983 "aO", "ap",
984 "ar?", "ar", "ar0", "ara?", "ara", "ara+", "ara-", "aras", "arA", "arC", "arr", "arrj", "ar=",
985 "arb", "arc", "ard", "arn", "aro", "arp?", "arp", "arpi", "arpg", "arp.", "arpj", "arps",
986 "ars", "art", "arw",
987 "as?", "as", "asc", "asca", "asf", "asj", "asl", "ask",
988 "av?", "av", "avj", "av*", "avr", "avra", "avraj", "avrr", "avrD",
989 "at",
990 "ax?", "ax", "ax*", "ax-", "ax-*", "axc", "axC", "axg", "axg*", "axgj", "axd", "axw", "axj", "axF",
991 "axt", "axf", "ax.", "axff", "axffj", "axs",
992 "b?", "b", "b+", "b-", "bf", "bm",
993 "c?", "c", "c1", "c2", "c4", "c8", "cc", "ccd", "cf", "cg?", "cg", "cgf", "cgff", "cgfc", "cgfn", "cgo",
994 "cu?", "cu", "cu1", "cu2", "cu4", "cu8", "cud",
995 "cv", "cv1", "cv2", "cv4", "cv8",
996 "cV", "cV1", "cV2", "cV4", "cV8",
997 "cw?", "cw", "cw*", "cwr", "cwu",
998 "cx", "cx*", "cX",
999 "cl", "cls", "clear",
1000 "d?", "db ", "db-", "db-*", "db.", "dbj", "dbc", "dbC", "dbd", "dbe", "dbs", "dbf", "dbm", "dbn",
1001 "db?", "dbi", "dbi.", "dbix", "dbic", "dbie", "dbid", "dbis", "dbite", "dbitd", "dbits", "dbh", "dbh-",
1002 "dbt", "dbt*", "dbt=", "dbtv", "dbtj", "dbta", "dbte", "dbtd", "dbts", "dbx", "dbw",
1003 "dc?", "dc", "dca", "dcb", "dcc", "dccu", "dcf", "dck", "dcp", "dcr", "dcs", "dcs*", "dct", "dcu", "dcu.",
1004 "dd?", "dd", "dd-", "dd*", "dds", "ddd", "ddr", "ddw",
1005 "de",
1006 "dg",
1007 "dH",
1008 "di?", "di", "di*", "diq", "dij",
1009 "dk?", "dk", "dko", "dkj",
1010 "dL?", "dL", "dLq", "dLj",
1011 "dm?", "dm", "dm=", "dm.", "dm*", "dm-", "dmd",
1012 "dmh?", "dmh", "dmha", "dmhb", "dmhbg", "dmhc", "dmhf", "dmhg", "dmhi", "dmhm", "dmht",
1013 "dmi?", "dmi", "dmi*", "dmi.", "dmiv",
1014 "dmj",
1015 "dml?", "dml",
1016 "dmm?", "dmm", "dmm*", "dmm.", "dmmj",
1017 "dmp?", "dmp",
1018 "dms?", "dms", "dmsj", "dms*", "dms-", "dmsA", "dmsC", "dmsd", "dmsw", "dmsa", "dmsf", "dmst",
1019 "dmS", "dmS*",
1020 "do?", "do", "dor", "doo",
1021 "dp?", "dp", "dpj", "dpl", "dplj", "dp-", "dp=", "dpa", "dpc", "dpc*", "dpe", "dpf", "dpk", "dpn", "dptn", "dpt",
1022 "dr?", "dr", "drps", "drpj", "drr", "drrj", "drs", "drs+", "drs-", "drt", "drt*", "drtj", "drw", "drx", "drx-",
1023 ".dr*", ".dr-",
1024 "ds?", "ds", "dsb", "dsf", "dsi", "dsl", "dso", "dsp", "dss", "dsu", "dsui", "dsuo", "dsue", "dsuf",
1025 "dt?", "dt", "dt%", "dt*", "dt+", "dt-", "dt=", "dtD", "dta", "dtc", "dtd", "dte", "dte-*", "dtei", "dtek",
1026 "dtg", "dtg*", "dtgi",
1027 "dtr",
1028 "dts?", "dts", "dts+", "dts-", "dtsf", "dtst", "dtsC", "dtt",
1029 "dw",
1030 "dx?", "dx", "dxa", "dxe", "dxr", "dxs",
1031 "e?", "e", "e-", "e*", "e!", "ec", "ee?", "ee", "?ed", "ed", "ej", "env", "er", "es", "et", "ev", "evj",
1032 "ec?", "ec", "ec*", "ecd", "ecr", "ecs", "ecj", "ecc", "eco", "ecp", "ecn",
1033 "ecH?", "ecH", "ecHi", "ecHw", "ecH-",
1034 "f?", "f", "f.", "f*", "f-", "f--", "f+", "f=", "fa", "fb", "fc?", "fc", "fC", "fd", "fe-", "fe",
1035 "ff", "fi", "fg", "fj",
1036 "fl", "fla", "fm", "fn", "fnj", "fo", "fO", "fr", "fR", "fR?",
1037 "fs?", "fs", "fs*", "fsj", "fs-", "fs+", "fs-.", "fsq", "fsm", "fss", "fss*", "fssj", "fsr",
1038 "ft?", "ft", "ftn", "fV", "fx", "fq",
1039 "fz?", "fz", "fz-", "fz.", "fz:", "fz*",
1040 "g?", "g", "gw", "gc", "gl?", "gl", "gs", "gi", "gp", "ge", "gr", "gS",
1041 "i?", "i", "ij", "iA", "ia", "ib", "ic", "icc", "iC",
1042 "id?", "id", "idp", "idpi", "idpi*", "idpd", "iD", "ie", "iee", "iE", "iE.",
1043 "ih", "iHH", "ii", "iI", "ik", "il", "iL", "im", "iM", "io", "iO?", "iO",
1044 "ir", "iR", "is", "is.", "iS", "iS.", "iS=", "iSS",
1045 "it", "iV", "iX", "iz", "izj", "izz", "izzz", "iz-", "iZ",
1046 "k?", "k", "ko", "kd", "ks", "kj",
1047 "l",
1048 "L?", "L", "L-", "Ll", "LL", "La", "Lc", "Ld", "Lh", "Li", "Lo",
1049 "m?", "m", "m*", "ml", "m-", "md", "mf?", "mf", "mg", "mo", "mi", "mp", "ms", "my",
1050 "o?", "o", "o-", "o--", "o+", "oa", "oa-", "oq", "o*", "o.", "o=",
1051 "ob?", "ob", "ob*", "obo", "oba", "obf", "obj", "obr", "ob-", "ob-*",
1052 "oc", "of", "oi", "oj", "oL", "om", "on",
1053 "oo?", "oo", "oo+", "oob", "ood", "oom", "oon", "oon+", "oonn", "oonn+",
1054 "op", "opn", "opp", "opr", "ox",
1055 "p?", "p-", "p=", "p2", "p3", "p6?", "p6", "p6d", "p6e", "p8?", "p8", "p8f", "p8j",
1056 "pa?", "paD", "pad", "pade", "pae", "pA",
1057 "pb?", "pb", "pB", "pxb", "pB?",
1058 "pc?", "pc", "pc*", "pca", "pcA", "pcd", "pch", "pcj", "pcp", "pcs", "pcS", "pcw",
1059 "pC?", "pC", "pCa", "pCA", "pCc", "pCd", "pCD", "pCx", "pCw",
1060 "pd?", "pd", "pd--", "pD", "pda", "pdb", "pdc", "pdC", "pdf", "pdi", "pdj", "pdJ",
1061 "pdk", "pdl", "pdp", "pdr", "pdr.", "pdR", "pds?", "pds", "pdsb", "pdsf", "pdt",
1062 "pD",
1063 "pf?", "pf", "pf??", "pf???", "pf.", "pfj", "pfj.", "pf*", "pf*.", "pfd", "pfd.",
1064 "pfo", "pfq", "pfv", "pfv.", "pfs", "pfs.",
1065 "pF?", "pF", "pFa", "pFaq", "pFo", "pFp", "pFx",
1066 "pg?", "pg", "pg*", "pg-*",
1067 "ph?", "ph", "ph=",
1068 "pi?", "pi", "pia", "pib", "pid", "pie", "pif?", "pif", "pifc", "pifcj", "pifj", "pij", "pir",
1069 "pI?", "pI", "pIa", "pIb", "pId", "pIe", "pIf?", "pIf", "pIfc", "pIfcj", "pIfj", "pIj", "pIr",
1070 "pj?", "pj", "pj.", "pj..",
1071 "pk?", "pk", "pK?", "pK",
1072 "pm?", "pm",
1073 "pq?", "pq", "pqi", "pqz",
1074 "pr?", "pr", "prc", "prl", "prx", "prg?", "prg", "prgi", "prgo", "prz",
1075 "ps?", "ps", "psb", "psi", "psj", "psp", "pss", "psu", "psw", "psW", "psx", "psz", "ps+",
1076 "pt?", "pt", "pt.", "ptd", "pth", "ptn",
1077 "pu?", "pu", "puw", "pU",
1078 "pv?", "pv", "pv1", "pv2", "pv4", "pv8", "pvz", "pvj", "pvh", "pv1j", "pv2j", "pv4j", "pv8j",
1079 "pv1h", "pv2h", "pv4h", "pv8h",
1080 "px?", "px", "px/", "px0", "pxa", "pxA?", "pxA", "pxb", "pxc", "pxd?", "pxd", "pxd2", "pxd4", "pxd8",
1081 "pxe", "pxf", "pxh", "pxH", "pxi", "pxl", "pxo", "pxq", "pxq", "pxQ", "pxQq", "pxr", "pxrj",
1082 "pxs", "pxt", "pxt*", "pxt.", "pxw", "pxW", "pxWq", "pxx", "pxX",
1083 "pz?", "pz", "pzp", "pzf", "pzs", "pz0", "pzF", "pze", "pzh",
1084 "P?", "P", "Pc", "Pd", "Pi", "Pn", "Pnj", "Po", "Ps", "PS", "P-",
1085 "q?", "q", "q!", "q!!", "q!!!", "qy", "qn", "qyy", "qyn", "qny", "qnn",
1086 "r?", "r", "r-", "r+", "rh",
1087 "s?", "s", "s:", "s-", "s-*", "s--", "s+", "s++", "sj", "s*", "s=", "s!", "s/", "s/x", "s.", "sa", "sb",
1088 "sC?", "sC", "sC*",
1089 "sf", "sf.", "sg", "sG", "sl?", "sl", "sl+", "sl-", "slc", "sll", "sn", "sp", "so", "sr", "ss",
1090 "t?", "t", "tj", "t*", "t-", "t-*", "ta", "tb", "tc", "te?", "te", "tej", "teb", "tec",
1091 "td?", "td", "td-", "tf", "tk", "tl", "tn", "to", "tos", "tp", "tpx", "ts?", "ts", "tsj", "ts*", "tsc", "tss",
1092 "tu?", "tu", "tuj", "tu*", "tuc", "tt?", "tt", "ttj", "ttc",
1093 "T?", "T", "T*", "T-", "Tl", "Tj", "Tm", "Ts", "TT", "T=", "T=.", "T=&",
1094 "u?", "u", "uw", "us", "uc",
1095 "v", "V", "v!", "vv", "vV", "vVV", "VV",
1096 "w?", "w", "w1+", "w1-", "w2+", "w2-", "w4+", "w4-", "w8+", "w8-",
1097 "w0", "w", "w6", "w6d", "w6e", "wa", "wa*", "waf", "wao?", "wao",
1098 "wA?", "wA", "wB", "wB-", "wc", "wcj", "wc-", "wc+", "wc*", "wcr", "wci", "wcp", "wcp*", "wcpi",
1099 "wd", "we?", "we", "wen", "weN", "wes", "wex", "weX",
1100 "wf?", "wf", "wff", "wfs", "wF", "wh", "wm",
1101 "wo?", "wo", "wo2", "wo4", "woa", "woA", "wod", "woD", "woe", "woE", "wol", "wom", "woo",
1102 "wop?", "wop", "wopD", "wopD*", "wopO",
1103 "wp?", "wp", "wr", "ws",
1104 "wt?", "wt", "wta", "wtf", "wtf!", "wtff", "wts",
1105 "wu",
1106 "wv?", "wv", "wv1", "wv2", "wv4", "wv8",
1107 "ww",
1108 "wx?", "wx", "wxf", "wxs",
1109 "wz",
1110 "x?", "x", "x/", "x0", "xa", "xA?", "xA", "xb", "xc", "xd?", "xd", "xd2", "xd4", "xd8",
1111 "xe", "xf", "xh", "xH", "xi", "xl", "xo", "xq", "xq", "xQ", "xQq", "xr", "xrj",
1112 "xs", "xt", "xt*", "xt.", "xw", "xW", "xWq", "xx", "xX",
1113 "y?", "y", "yz", "yp", "yx", "ys", "yt", "ytf", "yf", "yfa", "yfx", "yw", "ywx", "yy",
1114 "z?", "z", "z*", "zj", "z-", "z-*",
1115 "za?", "za??", "za", "zaf", "zaF", "zg",
1116 "zo?", "zo", "zoz", "zos",
1117 "zf?", "zfd", "zfs", "zfz",
1118 "z/?", "z/", "z/*",
1119 "zc",
1120 "zs?", "zs", "zs-", "zs-*", "zs+", "zsr",
1121 "zi",
1122 "?", "?v", "?$?", "?@?", "?>?",
1123 NULL
1124 };
1125
autocomplete_mount_point(RLineCompletion * completion,RCore * core,const char * path)1126 static void autocomplete_mount_point (RLineCompletion *completion, RCore *core, const char *path) {
1127 RFSRoot *r;
1128 RListIter *iter;
1129 r_list_foreach (core->fs->roots, iter, r) {
1130 char *base = strdup (r->path);
1131 char *ls = (char *) r_str_lchr (base, '/');
1132 if (ls) {
1133 ls++;
1134 *ls = 0;
1135 }
1136 if (!strcmp (path, base)) {
1137 r_line_completion_push (completion, r->path);
1138 }
1139 free (base);
1140 }
1141 }
1142
autocomplete_ms_path(RLineCompletion * completion,RCore * core,const char * str,const char * path)1143 static void autocomplete_ms_path(RLineCompletion *completion, RCore *core, const char *str, const char *path) {
1144 char *lpath = NULL, *dirname = NULL , *basename = NULL;
1145 char *p = NULL;
1146 char *pwd = (core->rfs && *(core->rfs->cwd)) ? *(core->rfs->cwd): ".";
1147 int n = 0;
1148 RList *list;
1149 RListIter *iter;
1150 RFSFile *file;
1151 r_return_if_fail (path);
1152 lpath = r_str_new (path);
1153 p = (char *)r_str_last (lpath, R_SYS_DIR);
1154 if (p) {
1155 *p = 0;
1156 if (p == lpath) { // /xxx
1157 dirname = r_str_new ("/");
1158 } else if (lpath[0] == '.') { // ./xxx/yyy
1159 dirname = r_str_newf ("%s%s", pwd, R_SYS_DIR);
1160 } else if (lpath[0] == '/') { // /xxx/yyy
1161 dirname = r_str_newf ("%s%s", lpath, R_SYS_DIR);
1162 } else { // xxx/yyy
1163 if (strlen (pwd) == 1) { // if pwd is root
1164 dirname = r_str_newf ("%s%s%s", R_SYS_DIR, lpath, R_SYS_DIR);
1165 } else {
1166 dirname = r_str_newf ("%s%s%s%s", pwd, R_SYS_DIR, lpath, R_SYS_DIR);
1167 }
1168 }
1169 basename = r_str_new (p + 1);
1170 } else { // xxx
1171 if (strlen (pwd) == 1) {
1172 dirname = r_str_newf ("%s", R_SYS_DIR);
1173 } else {
1174 dirname = r_str_newf ("%s%s", pwd, R_SYS_DIR);
1175 }
1176 basename = r_str_new (lpath);
1177 }
1178
1179 if (!dirname || !basename) {
1180 goto out;
1181 }
1182 list= r_fs_dir (core->fs, dirname);
1183 n = strlen (basename);
1184 bool chgdir = !strncmp (str, "cd ", 3);
1185 if (list) {
1186 r_list_foreach (list, iter, file) {
1187 if (!file) {
1188 continue;
1189 }
1190 if (!basename[0] || !strncmp (file->name, basename, n)) {
1191 char *tmpstring = r_str_newf ("%s%s", dirname, file->name);
1192 if (r_file_is_directory (tmpstring)) {
1193 char *s = r_str_newf ("%s/", tmpstring);
1194 r_line_completion_push (completion, s);
1195 free (s);
1196 } else if (!chgdir) {
1197 r_line_completion_push (completion, tmpstring);
1198 }
1199 free (tmpstring);
1200 }
1201 }
1202 r_list_free (list);
1203 }
1204 autocomplete_mount_point (completion, core, path);
1205 out:
1206 free (lpath);
1207 free (dirname);
1208 free (basename);
1209 }
1210
autocomplete_process_path(RLineCompletion * completion,const char * str,const char * path)1211 static void autocomplete_process_path(RLineCompletion *completion, const char *str, const char *path) {
1212 char *lpath = NULL, *dirname = NULL , *basename = NULL;
1213 char *home = NULL, *filename = NULL, *p = NULL;
1214 int n = 0;
1215 RList *list;
1216 RListIter *iter;
1217
1218 if (!path) {
1219 goto out;
1220 }
1221
1222 lpath = r_str_new (path);
1223 #if __WINDOWS__
1224 r_str_replace_ch (lpath, '/', '\\', true);
1225 #endif
1226 p = (char *)r_str_last (lpath, R_SYS_DIR);
1227 if (p) {
1228 *p = 0;
1229 if (p == lpath) { // /xxx
1230 #if __WINDOWS__
1231 dirname = strdup ("\\.\\");
1232 #else
1233 dirname = r_str_new (R_SYS_DIR);
1234 #endif
1235 } else if (lpath[0] == '~' && lpath[1]) { // ~/xxx/yyy
1236 dirname = r_str_home (lpath + 2);
1237 } else if (lpath[0] == '~') { // ~/xxx
1238 if (!(home = r_str_home (NULL))) {
1239 goto out;
1240 }
1241 dirname = r_str_newf ("%s%s", home, R_SYS_DIR);
1242 free (home);
1243 } else if (lpath[0] == '.' || lpath[0] == R_SYS_DIR[0] ) { // ./xxx/yyy || /xxx/yyy
1244 dirname = r_str_newf ("%s%s", lpath, R_SYS_DIR);
1245 } else { // xxx/yyy
1246 char *fmt = ".%s%s%s";
1247 #if __WINDOWS__
1248 if (strchr (path, ':')) {
1249 fmt = "%.0s%s%s";
1250 }
1251 #endif
1252 dirname = r_str_newf (fmt, R_SYS_DIR, lpath, R_SYS_DIR);
1253 }
1254 basename = r_str_new (p + 1);
1255 } else { // xxx
1256 dirname = r_str_newf (".%s", R_SYS_DIR);
1257 basename = r_str_new (lpath);
1258 }
1259
1260 if (!dirname || !basename) {
1261 goto out;
1262 }
1263
1264 list= r_sys_dir (dirname);
1265 n = strlen (basename);
1266 bool chgdir = !strncmp (str, "cd ", 3);
1267 if (list) {
1268 r_list_foreach (list, iter, filename) {
1269 if (*filename == '.') {
1270 continue;
1271 }
1272 if (!basename[0] || !strncmp (filename, basename, n)) {
1273 char *tmpstring = r_str_newf ("%s%s", dirname, filename);
1274 if (r_file_is_directory (tmpstring)) {
1275 char *s = r_str_newf ("%s%s", tmpstring, R_SYS_DIR);
1276 r_line_completion_push (completion, s);
1277 free (s);
1278 } else if (!chgdir) {
1279 r_line_completion_push (completion, tmpstring);
1280 }
1281 free (tmpstring);
1282 }
1283 }
1284 r_list_free (list);
1285 }
1286 out:
1287 free (lpath);
1288 free (dirname);
1289 free (basename);
1290 }
1291
autocompleteFilename(RLineCompletion * completion,RLineBuffer * buf,char ** extra_paths,int narg)1292 static void autocompleteFilename(RLineCompletion *completion, RLineBuffer *buf, char **extra_paths, int narg) {
1293 char *args = NULL, *input = NULL;
1294 int n = 0, i = 0;
1295 char *pipe = strchr (buf->data, '>');
1296 if (pipe) {
1297 args = r_str_new (pipe + 1);
1298 } else {
1299 args = r_str_new (buf->data);
1300 }
1301 if (!args) {
1302 goto out;
1303 }
1304
1305 n = r_str_word_set0 (args);
1306 if (n < narg) {
1307 goto out;
1308 }
1309
1310 input = r_str_new (r_str_word_get0 (args, narg));
1311 if (!input) {
1312 goto out;
1313 }
1314 const char *tinput = r_str_trim_head_ro (input);
1315
1316 autocomplete_process_path (completion, buf->data, tinput);
1317
1318 if (input[0] == '/' || input[0] == '.' || !extra_paths) {
1319 goto out;
1320 }
1321
1322 for (i = 0; extra_paths[i]; i ++) {
1323 char *s = r_str_newf ("%s%s%s", extra_paths[i], R_SYS_DIR, tinput);
1324 if (!s) {
1325 break;
1326 }
1327 autocomplete_process_path (completion, buf->data, s);
1328 free (s);
1329 }
1330 out:
1331 free (args);
1332 free (input);
1333 }
1334
1335 //TODO: make it recursive to handle nested struct
autocomplete_pfele(RCore * core,RLineCompletion * completion,char * key,char * pfx,int idx,char * ptr)1336 static int autocomplete_pfele (RCore *core, RLineCompletion *completion, char *key, char *pfx, int idx, char *ptr) {
1337 int i, ret = 0;
1338 int len = strlen (ptr);
1339 char* fmt = sdb_get (core->print->formats, key, NULL);
1340 if (fmt) {
1341 int nargs = r_str_word_set0_stack (fmt);
1342 if (nargs > 1) {
1343 for (i = 1; i < nargs; i++) {
1344 const char *arg = r_str_word_get0 (fmt, i);
1345 char *p = strchr (arg, '(');
1346 char *p2 = strchr (arg, ')');
1347 // remove '(' and ')' from fmt
1348 if (p && p2) {
1349 arg = p + 1;
1350 *p2 = '\0';
1351 }
1352 if (!len || !strncmp (ptr, arg, len)) {
1353 char *s = r_str_newf ("pf%s.%s.%s", pfx, key, arg);
1354 r_line_completion_push (completion, s);
1355 free (s);
1356 }
1357 }
1358 }
1359 }
1360 free (fmt);
1361 return ret;
1362 }
1363
1364 #define ADDARG(x) if (!strncmp (buf->data+chr, x, strlen (buf->data+chr))) { r_line_completion_push (completion, x); }
1365
autocomplete_default(R_NULLABLE RCore * core,RLineCompletion * completion,RLineBuffer * buf)1366 static void autocomplete_default(R_NULLABLE RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1367 RCoreAutocomplete *a = core ? core->autocomplete : NULL;
1368 int i;
1369 if (a) {
1370 for (i = 0; i < a->n_subcmds; i++) {
1371 if (buf->data[0] == 0 || !strncmp (a->subcmds[i]->cmd, buf->data, a->subcmds[i]->length)) {
1372 r_line_completion_push (completion, a->subcmds[i]->cmd);
1373 }
1374 }
1375 } else {
1376 for (i = 0; i < radare_argc && radare_argv[i]; i++) {
1377 int length = strlen (radare_argv[i]);
1378 if (!strncmp (radare_argv[i], buf->data, length)) {
1379 r_line_completion_push (completion, radare_argv[i]);
1380 }
1381 }
1382 }
1383 }
1384
autocomplete_evals(RCore * core,RLineCompletion * completion,const char * str)1385 static void autocomplete_evals(RCore *core, RLineCompletion *completion, const char *str) {
1386 r_return_if_fail (str);
1387 RConfigNode *bt;
1388 RListIter *iter;
1389 const char *tmp = strrchr (str, ' ');
1390 if (tmp) {
1391 str = tmp + 1;
1392 }
1393 size_t n = strlen (str);
1394 r_list_foreach (core->config->nodes, iter, bt) {
1395 if (!strncmp (bt->name, str, n)) {
1396 r_line_completion_push (completion, bt->name);
1397 }
1398 }
1399 }
1400
autocomplete_project(RCore * core,RLineCompletion * completion,const char * str)1401 static void autocomplete_project(RCore *core, RLineCompletion *completion, const char* str) {
1402 r_return_if_fail (str);
1403 char *foo, *projects_path = r_file_abspath (r_config_get (core->config, "dir.projects"));
1404 RList *list = r_sys_dir (projects_path);
1405 RListIter *iter;
1406 int n = strlen (str);
1407 if (projects_path) {
1408 r_list_foreach (list, iter, foo) {
1409 if (r_core_is_project (core, foo)) {
1410 if (!strncmp (foo, str, n)) {
1411 r_line_completion_push (completion, foo);
1412 }
1413 }
1414 }
1415 free (projects_path);
1416 r_list_free (list);
1417 }
1418 }
1419
autocomplete_minus(RCore * core,RLineCompletion * completion,const char * str)1420 static void autocomplete_minus(RCore *core, RLineCompletion *completion, const char *str) {
1421 r_return_if_fail (str);
1422 int count;
1423 int length = strlen (str);
1424 char **keys = r_cmd_alias_keys(core->rcmd, &count);
1425 if (!keys) {
1426 return;
1427 }
1428 int i;
1429 for (i = 0; i < count; i++) {
1430 if (!strncmp (keys[i], str, length)) {
1431 r_line_completion_push (completion, keys[i]);
1432 }
1433 }
1434 }
1435
autocomplete_breakpoints(RCore * core,RLineCompletion * completion,const char * str)1436 static void autocomplete_breakpoints(RCore *core, RLineCompletion *completion, const char *str) {
1437 r_return_if_fail (str);
1438 RListIter *iter;
1439 RBreakpoint *bp = core->dbg->bp;
1440 RBreakpointItem *b;
1441 int n = strlen (str);
1442 r_list_foreach (bp->bps, iter, b) {
1443 char *addr = r_str_newf ("0x%"PFMT64x"", b->addr);
1444 if (!strncmp (addr, str, n)) {
1445 r_line_completion_push (completion, addr);
1446 }
1447 free (addr);
1448 }
1449 }
1450
add_argv(RFlagItem * fi,void * user)1451 static bool add_argv(RFlagItem *fi, void *user) {
1452 RLineCompletion *completion = user;
1453 r_line_completion_push (completion, fi->name);
1454 return true;
1455 }
1456
autocomplete_flags(RCore * core,RLineCompletion * completion,const char * str)1457 static void autocomplete_flags(RCore *core, RLineCompletion *completion, const char* str) {
1458 r_return_if_fail (str);
1459 int n = strlen (str);
1460 r_flag_foreach_prefix (core->flags, str, n, add_argv, completion);
1461 }
1462
1463 // TODO: Should be refactored
autocomplete_sdb(RCore * core,RLineCompletion * completion,const char * str)1464 static void autocomplete_sdb (RCore *core, RLineCompletion *completion, const char *str) {
1465 r_return_if_fail (core && completion && str);
1466 char *pipe = strchr (str, '>');
1467 Sdb *sdb = core->sdb;
1468 char *lpath = NULL, *p1 = NULL, *out = NULL, *p2 = NULL;
1469 char *cur_pos = NULL, *cur_cmd = NULL, *next_cmd = NULL;
1470 char *temp_cmd = NULL, *temp_pos = NULL, *key = NULL;
1471 if (pipe) {
1472 str = r_str_trim_head_ro (pipe + 1);
1473 }
1474 lpath = r_str_new (str);
1475 p1 = strchr (lpath, '/');
1476 if (p1) {
1477 *p1 = 0;
1478 char *ns = p1 + 1;
1479 p2 = strchr (ns, '/');
1480 if (!p2) { // anal/m
1481 char *tmp = p1 + 1;
1482 int n = strlen (tmp);
1483 out = sdb_querys (sdb, NULL, 0, "anal/**");
1484 if (!out) {
1485 return;
1486 }
1487 while (*out) {
1488 cur_pos = strchr (out, '\n');
1489 if (!cur_pos) {
1490 break;
1491 }
1492 cur_cmd = r_str_ndup (out, cur_pos - out);
1493 if (!strncmp (tmp, cur_cmd, n)) {
1494 char *cmplt = r_str_newf ("anal/%s/", cur_cmd);
1495 r_line_completion_push (completion, cmplt);
1496 free (cmplt);
1497 }
1498 out += cur_pos - out + 1;
1499 }
1500
1501 } else { // anal/meta/*
1502 char *tmp = p2 + 1;
1503 int n = strlen (tmp);
1504 char *spltr = strchr (ns, '/');
1505 *spltr = 0;
1506 next_cmd = r_str_newf ("anal/%s/*", ns);
1507 out = sdb_querys (sdb, NULL, 0, next_cmd);
1508 if (!out) {
1509 free (lpath);
1510 return;
1511 }
1512 while (*out) {
1513 temp_pos = strchr (out, '\n');
1514 if (!temp_pos) {
1515 break;
1516 }
1517 temp_cmd = r_str_ndup (out, temp_pos - out); // contains the key=value pair
1518 key = strchr (temp_cmd, '=');
1519 *key = 0;
1520 if (!strncmp (tmp, temp_cmd, n)) {
1521 char *cmplt = r_str_newf ("anal/%s/%s", ns, temp_cmd);
1522 r_line_completion_push (completion, cmplt);
1523 free (cmplt);
1524 }
1525 out += temp_pos - out + 1;
1526 }
1527 }
1528 } else {
1529 int n = strlen (lpath);
1530 if (!strncmp (lpath, "anal", n)) {
1531 r_line_completion_push (completion, "anal/");
1532 }
1533 }
1534 }
1535
autocomplete_zignatures(RCore * core,RLineCompletion * completion,const char * msg)1536 static void autocomplete_zignatures(RCore *core, RLineCompletion *completion, const char* msg) {
1537 r_return_if_fail (msg);
1538 int length = strlen (msg);
1539 RSpaces *zs = &core->anal->zign_spaces;
1540 RSpace *s;
1541 RSpaceIter it;
1542
1543 r_spaces_foreach (zs, it, s) {
1544 if (!strncmp (msg, s->name, length)) {
1545 r_line_completion_push (completion, s->name);
1546 }
1547 }
1548
1549 if (strlen (msg) == 0) {
1550 r_line_completion_push (completion, "*");
1551 }
1552 }
1553
autocomplete_flagspaces(RCore * core,RLineCompletion * completion,const char * msg)1554 static void autocomplete_flagspaces(RCore *core, RLineCompletion *completion, const char* msg) {
1555 r_return_if_fail (msg);
1556 int length = strlen (msg);
1557 RFlag *flag = core->flags;
1558 RSpaceIter it;
1559 RSpace *s;
1560 r_flag_space_foreach (flag, it, s) {
1561 if (!strncmp (msg, s->name, length)) {
1562 r_line_completion_push (completion, s->name);
1563 }
1564 }
1565
1566 if (strlen (msg) == 0) {
1567 r_line_completion_push (completion, "*");
1568 }
1569 }
1570
autocomplete_functions(RCore * core,RLineCompletion * completion,const char * str)1571 static void autocomplete_functions (RCore *core, RLineCompletion *completion, const char* str) {
1572 r_return_if_fail (str);
1573 RListIter *iter;
1574 RAnalFunction *fcn;
1575 int n = strlen (str);
1576 r_list_foreach (core->anal->fcns, iter, fcn) {
1577 char *name = r_core_anal_fcn_name (core, fcn);
1578 if (!strncmp (name, str, n)) {
1579 r_line_completion_push (completion, name);
1580 }
1581 free (name);
1582 }
1583 }
1584
autocomplete_macro(RCore * core,RLineCompletion * completion,const char * str)1585 static void autocomplete_macro(RCore *core, RLineCompletion *completion, const char *str) {
1586 r_return_if_fail (core && core->rcmd && completion && str);
1587 RCmdMacroItem *item;
1588 RListIter *iter;
1589 size_t n = strlen (str);
1590 r_list_foreach (core->rcmd->macro.macros, iter, item) {
1591 char *p = item->name;
1592 if (!*str || !strncmp (str, p, n)) {
1593 char *buf = r_str_newf ("%s%s)", str, p);
1594 if (buf) {
1595 r_line_completion_push (completion, buf);
1596 free (buf);
1597 }
1598 }
1599 }
1600 }
1601
autocomplete_file(RLineCompletion * completion,const char * str)1602 static void autocomplete_file(RLineCompletion *completion, const char *str) {
1603 r_return_if_fail (str);
1604 char *pipe = strchr (str, '>');
1605
1606 if (pipe) {
1607 str = r_str_trim_head_ro (pipe + 1);
1608 }
1609 if (str && !*str) {
1610 autocomplete_process_path (completion, str, "./");
1611 } else {
1612 autocomplete_process_path (completion, str, str);
1613 }
1614
1615 }
1616
autocomplete_ms_file(RCore * core,RLineCompletion * completion,const char * str)1617 static void autocomplete_ms_file(RCore* core, RLineCompletion *completion, const char *str) {
1618 r_return_if_fail (str);
1619 char *pipe = strchr (str, '>');
1620 char *path = (core->rfs && *(core->rfs->cwd)) ? *(core->rfs->cwd): "/";
1621 if (pipe) {
1622 str = r_str_trim_head_ro (pipe + 1);
1623 }
1624 if (str && !*str) {
1625 autocomplete_ms_path (completion, core, str, path);
1626 } else {
1627 autocomplete_ms_path (completion, core, str, str);
1628 }
1629 }
1630
autocomplete_theme(RCore * core,RLineCompletion * completion,const char * str)1631 static void autocomplete_theme(RCore *core, RLineCompletion *completion, const char *str) {
1632 r_return_if_fail (str);
1633 int len = strlen (str);
1634 char *theme;
1635 RListIter *iter;
1636 RList *themes = r_core_list_themes (core);
1637 r_list_foreach (themes, iter, theme) {
1638 if (!len || !strncmp (str, theme, len)) {
1639 r_line_completion_push (completion, theme);
1640 }
1641 }
1642 r_list_free (themes);
1643 }
1644
find_e_opts(RCore * core,RLineCompletion * completion,RLineBuffer * buf)1645 static bool find_e_opts(RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1646 const char *pattern = "e (.*)=";
1647 RRegex *rx = r_regex_new (pattern, "e");
1648 const size_t nmatch = 2;
1649 RRegexMatch pmatch[2] = {0};
1650 bool ret = false;
1651
1652 // required to get the new list of items to autocomplete for cmd.pdc at least
1653 r_core_config_update (core);
1654
1655 if (r_regex_exec (rx, buf->data, nmatch, pmatch, 1)) {
1656 goto out;
1657 }
1658 int i;
1659 char *str = NULL, *sp;
1660 for (i = pmatch[1].rm_so; i < pmatch[1].rm_eo; i++) {
1661 str = r_str_appendch (str, buf->data[i]);
1662 }
1663 if (!str) {
1664 goto out;
1665 }
1666 if ((sp = strchr (str, ' '))) {
1667 // if the name contains a space, just null
1668 *sp = 0;
1669 }
1670 RConfigNode *node = r_config_node_get (core->config, str);
1671 if (sp) {
1672 // if nulled, then restore.
1673 *sp = ' ';
1674 }
1675 if (!node) {
1676 return false;
1677 }
1678 RListIter *iter;
1679 char *option;
1680 char *p = (char *) strchr (buf->data, '=');
1681 p = r_str_ichr (p + 1, ' ');
1682 int n = strlen (p);
1683 r_list_foreach (node->options, iter, option) {
1684 if (!strncmp (option, p, n)) {
1685 r_line_completion_push (completion, option);
1686 }
1687 }
1688 completion->opt = true;
1689 ret = true;
1690
1691 out:
1692 r_regex_free (rx);
1693 return ret;
1694 }
1695
find_autocomplete(RCore * core,RLineCompletion * completion,RLineBuffer * buf)1696 static bool find_autocomplete(RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1697 RCoreAutocomplete* child = NULL;
1698 RCoreAutocomplete* parent = core->autocomplete;
1699 const char* p = buf->data;
1700 if (!*p) {
1701 return false;
1702 }
1703 char arg[256];
1704 arg[0] = 0;
1705 while (*p) {
1706 const char* e = r_str_trim_head_wp (p);
1707 if (!e || (e - p) >= 256 || e == p) {
1708 return false;
1709 }
1710 memcpy (arg, p, e - p);
1711 arg[e - p] = 0;
1712 child = r_core_autocomplete_find (parent, arg, false);
1713 if (child && child->length < buf->length && p[child->length] == ' ') {
1714 // if is spaced then i can provide the
1715 // next subtree as suggestion..
1716 p = r_str_trim_head_ro (p + child->length);
1717 if (child->type == R_CORE_AUTOCMPLT_OPTN) {
1718 continue;
1719 }
1720 parent = child;
1721 } else {
1722 break;
1723 }
1724 }
1725 int i;
1726 /* if something went wrong this will prevent bad behavior */
1727 r_line_completion_clear (completion);
1728 switch (parent->type) {
1729 case R_CORE_AUTOCMPLT_SEEK:
1730 autocomplete_functions (core, completion, p);
1731 case R_CORE_AUTOCMPLT_FLAG:
1732 autocomplete_flags (core, completion, p);
1733 break;
1734 case R_CORE_AUTOCMPLT_FLSP:
1735 autocomplete_flagspaces (core, completion, p);
1736 break;
1737 case R_CORE_AUTOCMPLT_FCN:
1738 autocomplete_functions (core, completion, p);
1739 break;
1740 case R_CORE_AUTOCMPLT_ZIGN:
1741 autocomplete_zignatures (core, completion, p);
1742 break;
1743 case R_CORE_AUTOCMPLT_EVAL:
1744 autocomplete_evals (core, completion, p);
1745 break;
1746 case R_CORE_AUTOCMPLT_PRJT:
1747 autocomplete_project (core, completion, p);
1748 break;
1749 case R_CORE_AUTOCMPLT_MINS:
1750 autocomplete_minus (core, completion, p);
1751 break;
1752 case R_CORE_AUTOCMPLT_BRKP:
1753 autocomplete_breakpoints (core, completion, p);
1754 break;
1755 case R_CORE_AUTOCMPLT_MACR:
1756 autocomplete_macro (core, completion, p);
1757 break;
1758 case R_CORE_AUTOCMPLT_MS:
1759 autocomplete_ms_file(core, completion, p);
1760 break;
1761 case R_CORE_AUTOCMPLT_FILE:
1762 autocomplete_file (completion, p);
1763 break;
1764 case R_CORE_AUTOCMPLT_THME:
1765 autocomplete_theme (core, completion, p);
1766 break;
1767 case R_CORE_AUTOCMPLT_SDB:
1768 autocomplete_sdb (core, completion, p);
1769 break;
1770 case R_CORE_AUTOCMPLT_OPTN:
1771 // handled before
1772 break;
1773 default:
1774 if (r_config_get_i (core->config, "cfg.newtab")) {
1775 RCmdDescriptor *desc = &core->root_cmd_descriptor;
1776 for (i = 0; arg[i] && desc; i++) {
1777 ut8 c = arg[i];
1778 desc = c < R_ARRAY_SIZE (desc->sub) ? desc->sub[c] : NULL;
1779 }
1780 if (desc && desc->help_msg) {
1781 r_core_cmd_help (core, desc->help_msg);
1782 r_cons_flush ();
1783 return true;
1784 }
1785 // fallback to command listing
1786 }
1787 int length = strlen (arg);
1788 for (i = 0; i < parent->n_subcmds; i++) {
1789 if (!strncmp (arg, parent->subcmds[i]->cmd, length)) {
1790 r_line_completion_push (completion, parent->subcmds[i]->cmd);
1791 }
1792 }
1793 break;
1794 }
1795 return true;
1796 }
1797
r_core_autocomplete(R_NULLABLE RCore * core,RLineCompletion * completion,RLineBuffer * buf,RLinePromptType prompt_type)1798 R_API void r_core_autocomplete(R_NULLABLE RCore *core, RLineCompletion *completion, RLineBuffer *buf, RLinePromptType prompt_type) {
1799 if (!core) {
1800 autocomplete_default (core, completion, buf);
1801 return;
1802 }
1803 r_line_completion_clear (completion);
1804 char *pipe = strchr (buf->data, '>');
1805 char *ptr = strchr (buf->data, '@');
1806 if (pipe && strchr (pipe + 1, ' ') && buf->data + buf->index >= pipe) {
1807 autocompleteFilename (completion, buf, NULL, 1);
1808 } else if (ptr && strchr (ptr + 1, ' ') && buf->data + buf->index >= ptr) {
1809 int sdelta, n;
1810 ptr = (char *)r_str_trim_head_ro (ptr + 1);
1811 n = strlen (ptr);//(buf->data+sdelta);
1812 sdelta = (int)(size_t)(ptr - buf->data);
1813 r_flag_foreach_prefix (core->flags, buf->data + sdelta, n, add_argv, completion);
1814 } else if (!strncmp (buf->data, "#!pipe ", 7)) {
1815 if (strchr (buf->data + 7, ' ')) {
1816 autocompleteFilename (completion, buf, NULL, 2);
1817 } else {
1818 int chr = 7;
1819 ADDARG ("node");
1820 ADDARG ("vala");
1821 ADDARG ("ruby");
1822 ADDARG ("newlisp");
1823 ADDARG ("perl");
1824 ADDARG ("python");
1825 }
1826 } else if (!strncmp (buf->data, "ec ", 3)) {
1827 if (strchr (buf->data + 3, ' ')) {
1828 autocompleteFilename (completion, buf, NULL, 2);
1829 } else {
1830 int chr = 3;
1831 ADDARG("comment")
1832 ADDARG("usrcmt")
1833 ADDARG("args")
1834 ADDARG("fname")
1835 ADDARG("floc")
1836 ADDARG("fline")
1837 ADDARG("flag")
1838 ADDARG("label")
1839 ADDARG("help")
1840 ADDARG("flow")
1841 ADDARG("prompt")
1842 ADDARG("offset")
1843 ADDARG("input")
1844 ADDARG("invalid")
1845 ADDARG("other")
1846 ADDARG("b0x00")
1847 ADDARG("b0x7f")
1848 ADDARG("b0xff")
1849 ADDARG("math")
1850 ADDARG("bin")
1851 ADDARG("btext")
1852 ADDARG("push")
1853 ADDARG("pop")
1854 ADDARG("crypto")
1855 ADDARG("jmp")
1856 ADDARG("cjmp")
1857 ADDARG("call")
1858 ADDARG("nop")
1859 ADDARG("ret")
1860 ADDARG("trap")
1861 ADDARG("swi")
1862 ADDARG("cmp")
1863 ADDARG("reg")
1864 ADDARG("creg")
1865 ADDARG("num")
1866 ADDARG("mov")
1867 ADDARG("func_var")
1868 ADDARG("func_var_type")
1869 ADDARG("func_var_addr")
1870 ADDARG("widget_bg")
1871 ADDARG("widget_sel")
1872 ADDARG("ai.read")
1873 ADDARG("ai.write")
1874 ADDARG("ai.exec")
1875 ADDARG("ai.seq")
1876 ADDARG("ai.ascii")
1877 ADDARG("ai.unmap")
1878 ADDARG("graph.box")
1879 ADDARG("graph.box2")
1880 ADDARG("graph.box3")
1881 ADDARG("graph.box4")
1882 ADDARG("graph.true")
1883 ADDARG("graph.false")
1884 ADDARG("graph.trufae")
1885 ADDARG("graph.current")
1886 ADDARG("graph.traced")
1887 ADDARG("gui.cflow")
1888 ADDARG("gui.dataoffset")
1889 ADDARG("gui.background")
1890 ADDARG("gui.alt_background")
1891 ADDARG("gui.border")
1892 }
1893 } else if (!strncmp (buf->data, "pf.", 3)
1894 || !strncmp (buf->data, "pf*.", 4)
1895 || !strncmp (buf->data, "pfd.", 4)
1896 || !strncmp (buf->data, "pfv.", 4)
1897 || !strncmp (buf->data, "pfj.", 4)) {
1898 char pfx[2];
1899 int chr = (buf->data[2]=='.')? 3: 4;
1900 if (chr == 4) {
1901 pfx[0] = buf->data[2];
1902 pfx[1] = 0;
1903 } else {
1904 *pfx = 0;
1905 }
1906 SdbList *sls = sdb_foreach_list (core->print->formats, false);
1907 SdbListIter *iter;
1908 SdbKv *kv;
1909 ls_foreach (sls, iter, kv) {
1910 int len = strlen (buf->data + chr);
1911 int minlen = R_MIN (len, strlen (sdbkv_key (kv)));
1912 if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), minlen)) {
1913 char *p = strchr (buf->data + chr, '.');
1914 if (p) {
1915 autocomplete_pfele (core, completion, sdbkv_key (kv), pfx, 0, p + 1);
1916 break;
1917 } else {
1918 char *s = r_str_newf ("pf%s.%s", pfx, sdbkv_key (kv));
1919 r_line_completion_push (completion, s);
1920 free (s);
1921 }
1922 }
1923 }
1924 } else if ((!strncmp (buf->data, "afvn ", 5))
1925 || (!strncmp (buf->data, "afan ", 5))) {
1926 RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
1927 RList *vars;
1928 if (!strncmp (buf->data, "afvn ", 5)) {
1929 vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_BPV);
1930 } else {
1931 vars = r_list_new (); // TODO wtf r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_ARG);
1932 }
1933 const char *f_ptr, *l_ptr;
1934 RAnalVar *var;
1935 int len = strlen (buf->data);
1936
1937 f_ptr = r_sub_str_lchr (buf->data, 0, buf->index, ' ');
1938 f_ptr = f_ptr != NULL ? f_ptr + 1 : buf->data;
1939 l_ptr = r_sub_str_rchr (buf->data, buf->index, len, ' ');
1940 if (!l_ptr) {
1941 l_ptr = buf->data + len;
1942 }
1943 RListIter *iter;
1944 r_list_foreach (vars, iter, var) {
1945 if (!strncmp (f_ptr, var->name, l_ptr - f_ptr)) {
1946 r_line_completion_push (completion, var->name);
1947 }
1948 }
1949 r_list_free (vars);
1950 } else if (!strncmp (buf->data, "t ", 2)
1951 || !strncmp (buf->data, "t- ", 3)) {
1952 SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1953 SdbListIter *iter;
1954 SdbKv *kv;
1955 int chr = (buf->data[1] == ' ')? 2: 3;
1956 ls_foreach (l, iter, kv) {
1957 int len = strlen (buf->data + chr);
1958 if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), len)) {
1959 if (!strcmp (sdbkv_value (kv), "type") || !strcmp (sdbkv_value (kv), "enum")
1960 || !strcmp (sdbkv_value (kv), "struct")) {
1961 r_line_completion_push (completion, sdbkv_key (kv));
1962 }
1963 }
1964 }
1965 ls_free (l);
1966 } else if ((!strncmp (buf->data, "te ", 3))) {
1967 SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1968 SdbListIter *iter;
1969 SdbKv *kv;
1970 int chr = 3;
1971 ls_foreach (l, iter, kv) {
1972 int len = strlen (buf->data + chr);
1973 if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), len)) {
1974 if (!strcmp (sdbkv_value (kv), "enum")) {
1975 r_line_completion_push (completion, sdbkv_key (kv));
1976 }
1977 }
1978 }
1979 ls_free (l);
1980 } else if (!strncmp (buf->data, "$", 1)) {
1981 int i;
1982 for (i = 0; i < core->rcmd->aliases.count; i++) {
1983 const char *key = core->rcmd->aliases.keys[i];
1984 int len = strlen (buf->data);
1985 if (!len || !strncmp (buf->data, key, len)) {
1986 r_line_completion_push (completion, key);
1987 }
1988 }
1989 } else if (!strncmp (buf->data, "ts ", 3)
1990 || !strncmp (buf->data, "ta ", 3)
1991 || !strncmp (buf->data, "tp ", 3)
1992 || !strncmp (buf->data, "tl ", 3)
1993 || !strncmp (buf->data, "tpx ", 4)
1994 || !strncmp (buf->data, "tss ", 4)
1995 || !strncmp (buf->data, "ts* ", 4)) {
1996 SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1997 SdbListIter *iter;
1998 SdbKv *kv;
1999 int chr = (buf->data[2] == ' ')? 3: 4;
2000 ls_foreach (l, iter, kv) {
2001 int len = strlen (buf->data + chr);
2002 const char *key = sdbkv_key (kv);
2003 if (!len || !strncmp (buf->data + chr, key, len)) {
2004 if (!strncmp (sdbkv_value (kv), "struct", strlen ("struct") + 1)) {
2005 r_line_completion_push (completion, key);
2006 }
2007 }
2008 }
2009 ls_free (l);
2010 } else if (!strncmp (buf->data, "zo ", 3)
2011 || !strncmp (buf->data, "zoz ", 4)) {
2012 if (core->anal->zign_path && core->anal->zign_path[0]) {
2013 char *zignpath = r_file_abspath (core->anal->zign_path);
2014 char *paths[2] = { zignpath, NULL };
2015 autocompleteFilename (completion, buf, paths, 1);
2016 free (zignpath);
2017 } else {
2018 autocompleteFilename (completion, buf, NULL, 1);
2019 }
2020 } else if (find_e_opts (core, completion, buf)) {
2021 return;
2022 } else if (prompt_type == R_LINE_PROMPT_OFFSET) {
2023 autocomplete_flags (core, completion, buf->data);
2024 } else if (prompt_type == R_LINE_PROMPT_FILE) {
2025 autocomplete_file (completion, buf->data);
2026 } else if (!find_autocomplete (core, completion, buf)) {
2027 autocomplete_default (core, completion, buf);
2028 }
2029 }
2030
autocomplete(RLineCompletion * completion,RLineBuffer * buf,RLinePromptType prompt_type,void * user)2031 static int autocomplete(RLineCompletion *completion, RLineBuffer *buf, RLinePromptType prompt_type, void *user) {
2032 RCore *core = user;
2033 r_core_autocomplete (core, completion, buf, prompt_type);
2034 return true;
2035 }
2036
r_core_fgets(char * buf,int len)2037 R_API int r_core_fgets(char *buf, int len) {
2038 RCons *cons = r_cons_singleton ();
2039 RLine *rli = cons->line;
2040 bool prompt = cons->context->is_interactive;
2041 buf[0] = '\0';
2042 if (prompt) {
2043 r_line_completion_set (&rli->completion, radare_argc, radare_argv);
2044 rli->completion.run = autocomplete;
2045 rli->completion.run_user = rli->user;
2046 } else {
2047 r_line_hist_free ();
2048 r_line_completion_set (&rli->completion, 0, NULL);
2049 rli->completion.run = NULL;
2050 rli->completion.run_user = NULL;
2051 }
2052 const char *ptr = r_line_readline ();
2053 if (!ptr) {
2054 return -1;
2055 }
2056 return r_str_ncpy (buf, ptr, len - 1);
2057 }
2058
r_core_print_offname(void * p,ut64 addr)2059 static const char *r_core_print_offname(void *p, ut64 addr) {
2060 RCore *c = (RCore*)p;
2061 RFlagItem *item = r_flag_get_i (c->flags, addr);
2062 return item ? item->name : NULL;
2063 }
2064
r_core_print_offsize(void * p,ut64 addr)2065 static int r_core_print_offsize(void *p, ut64 addr) {
2066 RCore *c = (RCore*)p;
2067 RFlagItem *item = r_flag_get_i (c->flags, addr);
2068 return item ? item->size: -1;
2069 }
2070
2071 /**
2072 * Disassemble one instruction at specified address.
2073 */
__disasm(void * _core,ut64 addr)2074 static int __disasm(void *_core, ut64 addr) {
2075 RCore *core = _core;
2076 ut64 prevaddr = core->offset;
2077
2078 r_core_seek (core, addr, true);
2079 int len = r_core_print_disasm_instructions (core, 0, 1);
2080 r_core_seek (core, prevaddr, true);
2081
2082 return len;
2083 }
2084
update_sdb(RCore * core)2085 static void update_sdb(RCore *core) {
2086 Sdb *d;
2087 RBinObject *o;
2088 if (!core) {
2089 return;
2090 }
2091 //SDB// anal/
2092 if (core->anal && core->anal->sdb) {
2093 sdb_ns_set (DB, "anal", core->anal->sdb);
2094 }
2095 //SDB// bin/
2096 if (core->bin && core->bin->sdb) {
2097 sdb_ns_set (DB, "bin", core->bin->sdb);
2098 }
2099 //SDB// bin/info
2100 o = r_bin_cur_object (core->bin);
2101 if (o) {
2102 sdb_ns_set (sdb_ns (DB, "bin", 1), "info", o->kv);
2103 }
2104 //sdb_ns_set (core->sdb, "flags", core->flags->sdb);
2105 //sdb_ns_set (core->sdb, "bin", core->bin->sdb);
2106 //SDB// syscall/
2107 if (core->rasm && core->rasm->syscall && core->rasm->syscall->db) {
2108 core->rasm->syscall->db->refs++;
2109 sdb_ns_set (DB, "syscall", core->rasm->syscall->db);
2110 }
2111 d = sdb_ns (DB, "debug", 1);
2112 if (core->dbg->sgnls) {
2113 core->dbg->sgnls->refs++;
2114 sdb_ns_set (d, "signals", core->dbg->sgnls);
2115 }
2116 }
2117
2118 #define MINLEN 1
is_string(const ut8 * buf,int size,int * len)2119 static int is_string(const ut8 *buf, int size, int *len) {
2120 int i;
2121 if (size < 1) {
2122 return 0;
2123 }
2124 if (size > 3 && buf[0] && !buf[1] && buf[2] && !buf[3]) {
2125 *len = 1; // XXX: TODO: Measure wide string length
2126 return 2; // is wide
2127 }
2128 for (i = 0; i < size; i++) {
2129 if (!buf[i] && i > MINLEN) {
2130 *len = i;
2131 return 1;
2132 }
2133 if (buf[i] == 10|| buf[i] == 13|| buf[i] == 9) {
2134 continue;
2135 }
2136 if (buf[i] < 32 || buf[i] > 127) {
2137 // not ascii text
2138 return 0;
2139 }
2140 if (!IS_PRINTABLE (buf[i])) {
2141 *len = i;
2142 return 0;
2143 }
2144 }
2145 *len = i;
2146 return 1;
2147 }
2148
r_core_anal_hasrefs(RCore * core,ut64 value,int mode)2149 R_API char *r_core_anal_hasrefs(RCore *core, ut64 value, int mode) {
2150 if (mode) {
2151 PJ *pj = (mode == 'j')? pj_new (): NULL;
2152 const int hex_depth = 1; // r_config_get_i (core->config, "hex.depth");
2153 char *res = r_core_anal_hasrefs_to_depth (core, value, pj, hex_depth);
2154 if (pj) {
2155 free (res);
2156 return pj_drain (pj);
2157 }
2158 return res;
2159 }
2160 RFlagItem *fi = r_flag_get_i (core->flags, value);
2161 return fi? strdup (fi->name): NULL;
2162 }
2163
getvalue(ut64 value,int bits)2164 static char *getvalue(ut64 value, int bits) {
2165 switch (bits) {
2166 case 16: // umf, not in sync with pxr
2167 {
2168 st16 v = (st16)(value & UT16_MAX);
2169 st16 h = UT16_MAX / 0x100;
2170 if (v > -h && v < h) {
2171 return r_str_newf ("%hd", v);
2172 }
2173 }
2174 break;
2175 case 32:
2176 {
2177 st32 v = (st32)(value & UT32_MAX);
2178 st32 h = UT32_MAX / 0x10000;
2179 if (v > -h && v < h) {
2180 return r_str_newf ("%d", v);
2181 }
2182 }
2183 break;
2184 case 64:
2185 {
2186 st64 v = (st64)(value);
2187 st64 h = UT64_MAX / 0x1000000;
2188 if (v > -h && v < h) {
2189 return r_str_newf ("%"PFMT64d, v);
2190 }
2191 }
2192 break;
2193 }
2194 return NULL;
2195 }
2196
2197 /*
2198 pxr logic is dupplicated in other places
2199 * ai, ad
2200 * no json support
2201 */
r_core_anal_hasrefs_to_depth(RCore * core,ut64 value,PJ * pj,int depth)2202 R_API char *r_core_anal_hasrefs_to_depth(RCore *core, ut64 value, PJ *pj, int depth) {
2203 const int bits = core->rasm->bits;
2204 r_return_val_if_fail (core, NULL);
2205 RStrBuf *s = r_strbuf_new (NULL);
2206 if (pj) {
2207 pj_o (pj);
2208 pj_kn (pj, "addr", value);
2209 }
2210 if (depth < 1 || value == UT64_MAX) {
2211 if (pj) {
2212 pj_end (pj);
2213 }
2214 return NULL;
2215 }
2216
2217 char *val = getvalue (value, bits);
2218 if (val) {
2219 if (pj) {
2220 pj_ks (pj, "value", val);
2221 } else {
2222 r_strbuf_appendf (s, "%s ", val);
2223 }
2224 R_FREE (val);
2225 }
2226
2227 if (value && value != UT64_MAX) {
2228 RDebugMap *map = r_debug_map_get (core->dbg, value);
2229 if (map && map->name && map->name[0]) {
2230 if (pj) {
2231 pj_ks (pj, "map", map->name);
2232 } else {
2233 r_strbuf_appendf (s, "%s ", map->name);
2234 }
2235 }
2236 }
2237 ut64 type = r_core_anal_address (core, value);
2238 RBinSection *sect = value? r_bin_get_section_at (r_bin_cur_object (core->bin), value, true): NULL;
2239 if(! ((type & R_ANAL_ADDR_TYPE_HEAP) || (type & R_ANAL_ADDR_TYPE_STACK)) ) {
2240 // Do not repeat "stack" or "heap" words unnecessarily.
2241 if (sect && sect->name[0]) {
2242 if (pj) {
2243 pj_ks (pj, "section", sect->name);
2244 } else {
2245 r_strbuf_appendf (s, "%s ", sect->name);
2246 }
2247 }
2248 }
2249 if (value != 0 && value != UT64_MAX) {
2250 if (pj) {
2251 RListIter *iter;
2252 RFlagItem *f;
2253 const RList *flags = r_flag_get_list (core->flags, value);
2254 if (flags && !r_list_empty (flags)) {
2255 pj_ka (pj, "flags");
2256 r_list_foreach (flags, iter, f) {
2257 pj_s (pj, f->name);
2258 }
2259 pj_end (pj);
2260 }
2261 } else {
2262 char *flags = r_flag_get_liststr (core->flags, value);
2263 if (flags) {
2264 r_strbuf_appendf (s, "%s ", flags);
2265 free (flags);
2266 }
2267 }
2268 }
2269 RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, value, 0);
2270 if (fcn) {
2271 if (pj) {
2272 pj_ks (pj, "fcn", fcn->name);
2273 } else {
2274 r_strbuf_appendf (s, "%s ", fcn->name);
2275 }
2276 }
2277 if (type) {
2278 const char *c = r_core_anal_optype_colorfor (core, value, true);
2279 const char *cend = (c && *c) ? Color_RESET: "";
2280 if (!c) {
2281 c = "";
2282 }
2283 if (pj) {
2284 pj_ka (pj, "attr");
2285 }
2286 if (type & R_ANAL_ADDR_TYPE_HEAP) {
2287 if (pj) {
2288 pj_s (pj, "heap");
2289 } else {
2290 r_strbuf_appendf (s, "%sheap%s ", c, cend);
2291 }
2292 } else if (type & R_ANAL_ADDR_TYPE_STACK) {
2293 if (pj) {
2294 pj_s (pj, "stack");
2295 } else {
2296 r_strbuf_appendf (s, "%sstack%s ", c, cend);
2297 }
2298 }
2299 if (type & R_ANAL_ADDR_TYPE_PROGRAM) {
2300 if (pj) {
2301 pj_s (pj, "program");
2302 } else {
2303 r_strbuf_appendf (s, "%sprogram%s ", c, cend);
2304 }
2305 }
2306 if (type & R_ANAL_ADDR_TYPE_LIBRARY) {
2307 if (pj) {
2308 pj_s (pj, "library");
2309 } else {
2310 r_strbuf_appendf (s, "%slibrary%s ", c, cend);
2311 }
2312 }
2313 if (type & R_ANAL_ADDR_TYPE_ASCII) {
2314 if (pj) {
2315 pj_s (pj, "ascii");
2316 } else {
2317 r_strbuf_appendf (s, "%sascii%s ('%c') ", c, cend, (char)value);
2318 }
2319 }
2320 if (type & R_ANAL_ADDR_TYPE_SEQUENCE) {
2321 if (pj) {
2322 pj_s (pj, "sequence");
2323 } else {
2324 r_strbuf_appendf (s, "%ssequence%s ", c, cend);
2325 }
2326 }
2327 if (pj) {
2328 if (type & R_ANAL_ADDR_TYPE_READ) {
2329 pj_s (pj, "R");
2330 }
2331 if (type & R_ANAL_ADDR_TYPE_WRITE) {
2332 pj_s (pj, "W");
2333 }
2334 if (type & R_ANAL_ADDR_TYPE_EXEC) {
2335 pj_s (pj, "X");
2336 }
2337 } else {
2338 if (type & R_ANAL_ADDR_TYPE_READ) {
2339 r_strbuf_appendf (s, "%sR%s ", c, cend);
2340 }
2341 if (type & R_ANAL_ADDR_TYPE_WRITE) {
2342 r_strbuf_appendf (s, "%sW%s ", c, cend);
2343 }
2344 if (type & R_ANAL_ADDR_TYPE_EXEC) {
2345 RAsmOp op;
2346 ut8 buf[32];
2347 r_strbuf_appendf (s, "%sX%s ", c, cend);
2348 /* instruction disassembly */
2349 r_io_read_at (core->io, value, buf, sizeof (buf));
2350 r_asm_set_pc (core->rasm, value);
2351 r_asm_disassemble (core->rasm, &op, buf, sizeof (buf));
2352 r_strbuf_appendf (s, "'%s' ", r_asm_op_get_asm (&op));
2353 /* get library name */
2354 { // NOTE: dup for mapname?
2355 RDebugMap *map;
2356 RListIter *iter;
2357 r_list_foreach (core->dbg->maps, iter, map) {
2358 if ((value >= map->addr) &&
2359 (value<map->addr_end)) {
2360 const char *lastslash = r_str_lchr (map->name, '/');
2361 r_strbuf_appendf (s, "'%s' ", lastslash?
2362 lastslash + 1: map->name);
2363 break;
2364 }
2365 }
2366 }
2367 } else if (type & R_ANAL_ADDR_TYPE_READ) {
2368 ut8 buf[32];
2369 ut32 *n32 = (ut32 *)buf;
2370 ut64 *n64 = (ut64*)buf;
2371 if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2372 ut64 n = (bits == 64)? *n64: *n32;
2373 r_strbuf_appendf (s, "0x%"PFMT64x" ", n);
2374 }
2375 }
2376 }
2377 if (pj) {
2378 pj_end (pj);
2379 }
2380 }
2381 {
2382 ut8 buf[128], widebuf[256];
2383 const char *c = r_config_get_i (core->config, "scr.color")? core->cons->context->pal.ai_ascii: "";
2384 const char *cend = (c && *c) ? Color_RESET: "";
2385 int len, r;
2386 if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2387 buf[sizeof (buf) - 1] = 0;
2388 switch (is_string (buf, sizeof (buf), &len)) {
2389 case 1:
2390 if (pj) {
2391 pj_ks (pj, "string", (const char *)buf);
2392 } else {
2393 r_strbuf_appendf (s, "%s%s%s ", c, buf, cend);
2394 }
2395 break;
2396 case 2:
2397 r = r_utf8_encode_str ((const RRune *)buf, widebuf, sizeof (widebuf) - 1);
2398 if (r == -1) {
2399 r_cons_eprintf ("Something was wrong with refs\n");
2400 } else {
2401 if (pj) {
2402 pj_ks (pj, "string", (const char *)widebuf);
2403 } else {
2404 r_strbuf_appendf (s, "%s%s%s ", c, widebuf, cend);
2405 }
2406 }
2407 break;
2408 }
2409 }
2410
2411 }
2412 if ((type & R_ANAL_ADDR_TYPE_READ) && !(type & R_ANAL_ADDR_TYPE_EXEC) && depth) {
2413 // Try to telescope further, but only several levels deep.
2414 ut8 buf[32];
2415 ut32 *n32 = (ut32 *)buf;
2416 ut64 *n64 = (ut64*)buf;
2417 if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2418 ut64 n = (bits == 64)? *n64: *n32;
2419 if (n != value) {
2420 if (pj) {
2421 pj_k (pj, "ref");
2422 }
2423 char* rrstr = r_core_anal_hasrefs_to_depth (core, n, pj, depth - 1);
2424 if (rrstr) {
2425 if (!pj && rrstr[0]) {
2426 r_strbuf_appendf (s, " -> %s", rrstr);
2427 }
2428 free (rrstr);
2429 }
2430 }
2431 }
2432 }
2433 if (pj) {
2434 pj_end (pj);
2435 }
2436 char *res = r_strbuf_drain (s);
2437 r_str_trim_tail (res);
2438 return res;
2439 }
2440
r_core_anal_get_comments(RCore * core,ut64 addr)2441 R_API char *r_core_anal_get_comments(RCore *core, ut64 addr) {
2442 if (core) {
2443 const char *type = r_meta_get_string (core->anal, R_META_TYPE_VARTYPE, addr);
2444 const char *cmt = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
2445 if (type && cmt) {
2446 return r_str_newf ("%s %s", type, cmt);
2447 }
2448 if (type) {
2449 return strdup (type);
2450 }
2451 if (cmt) {
2452 return strdup (cmt);
2453 }
2454 }
2455 return NULL;
2456 }
2457
r_core_anal_optype_colorfor(RCore * core,ut64 addr,bool verbose)2458 R_API const char *r_core_anal_optype_colorfor(RCore *core, ut64 addr, bool verbose) {
2459 ut64 type;
2460 if (!(core->print->flags & R_PRINT_FLAGS_COLOR)) {
2461 return NULL;
2462 }
2463 if (!r_config_get_i (core->config, "scr.color")) {
2464 return NULL;
2465 }
2466 type = r_core_anal_address (core, addr);
2467 if (type & R_ANAL_ADDR_TYPE_EXEC) {
2468 return core->cons->context->pal.ai_exec; //Color_RED;
2469 }
2470 if (type & R_ANAL_ADDR_TYPE_WRITE) {
2471 return core->cons->context->pal.ai_write; //Color_BLUE;
2472 }
2473 if (type & R_ANAL_ADDR_TYPE_READ) {
2474 return core->cons->context->pal.ai_read; //Color_GREEN;
2475 }
2476 if (type & R_ANAL_ADDR_TYPE_SEQUENCE) {
2477 return core->cons->context->pal.ai_seq; //Color_MAGENTA;
2478 }
2479 if (type & R_ANAL_ADDR_TYPE_ASCII) {
2480 return core->cons->context->pal.ai_ascii; //Color_YELLOW;
2481 }
2482 return NULL;
2483 }
2484
r_core_setenv(RCore * core)2485 static void r_core_setenv (RCore *core) {
2486 char *e = r_sys_getenv ("PATH");
2487 char *h = r_str_home (R2_HOME_BIN);
2488 char *n = r_str_newf ("%s%s%s", h, R_SYS_ENVSEP, e);
2489 r_sys_setenv ("PATH", n);
2490 free (n);
2491 free (h);
2492 free (e);
2493 }
2494
mywrite(const ut8 * buf,int len)2495 static int mywrite(const ut8 *buf, int len) {
2496 return r_cons_memcat ((const char *)buf, len);
2497 }
2498
exists_var(RPrint * print,ut64 func_addr,char * str)2499 static bool exists_var(RPrint *print, ut64 func_addr, char *str) {
2500 RAnal *anal = ((RCore*)(print->user))->anal;
2501 RAnalFunction *fcn = r_anal_get_function_at (anal, func_addr);
2502 if (!fcn) {
2503 return false;
2504 }
2505 return !!r_anal_function_get_var_byname (fcn, str);
2506 }
2507
r_core_anal_log(struct r_anal_t * anal,const char * msg)2508 static bool r_core_anal_log(struct r_anal_t *anal, const char *msg) {
2509 RCore *core = anal->user;
2510 if (core->cfglog) {
2511 r_core_log_add (core, msg);
2512 }
2513 return true;
2514 }
2515
r_core_anal_read_at(struct r_anal_t * anal,ut64 addr,ut8 * buf,int len)2516 static bool r_core_anal_read_at(struct r_anal_t *anal, ut64 addr, ut8 *buf, int len) {
2517 return r_io_read_at (anal->iob.io, addr, buf, len);
2518 }
2519
r_core_break(RCore * core)2520 static void r_core_break (RCore *core) {
2521 }
2522
r_core_sleep_begin(RCore * core)2523 static void *r_core_sleep_begin (RCore *core) {
2524 RCoreTask *task = r_core_task_self (&core->tasks);
2525 if (task) {
2526 r_core_task_sleep_begin (task);
2527 }
2528 return task;
2529 }
2530
r_core_sleep_end(RCore * core,void * user)2531 static void r_core_sleep_end (RCore *core, void *user) {
2532 RCoreTask *task = (RCoreTask *)user;
2533 if (task) {
2534 r_core_task_sleep_end (task);
2535 }
2536 }
2537
__foreach(RCore * core,const char ** cmds,int type)2538 static void __foreach(RCore *core, const char **cmds, int type) {
2539 int i;
2540 for (i = 0; cmds[i]; i++) {
2541 r_core_autocomplete_add (core->autocomplete, cmds[i], type, true);
2542 }
2543 }
2544
__init_autocomplete_default(RCore * core)2545 static void __init_autocomplete_default (RCore* core) {
2546 const char *fcns[] = {
2547 "afi", "afcf", "afn", NULL
2548 };
2549 const char *seeks[] = {
2550 "s", NULL
2551 };
2552 const char *flags[] = {
2553 "*", "s", "s+", "b", "f", "fg", "?", "?v", "ad", "bf", "c1", "db", "dbw",
2554 "f-", "fr", "tf", "/a", "/v", "/r", "/re", "aav", "aep", "aef", "afb",
2555 "afc", "axg", "axt", "axf", "dcu", "ag", "agfl", "aecu", "aesu", "aeim", NULL
2556 };
2557 const char *evals[] = {
2558 "e", "ee", "et", "e?", "e!", "ev", "evj", NULL
2559 };
2560 const char *breaks[] = {
2561 "db-", "dbc", "dbC", "dbd", "dbe", "dbs", "dbi", "dbte", "dbtd", "dbts", NULL
2562 };
2563 const char *files[] = {
2564 ".", "..", ".*", "/F", "/m", "!", "!!", "#!c", "#!v", "#!cpipe", "#!vala",
2565 "#!rust", "#!zig", "#!pipe", "#!python", "aeli", "arp", "arpg", "dmd", "drp", "drpg", "o",
2566 "idp", "idpi", "L", "obf", "o+", "oc", "r2", "rabin2", "rasm2", "rahash2", "rax2",
2567 "rafind2", "cd", "ls", "on", "op", "wf", "rm", "wF", "wp", "Sd", "Sl", "to", "pm",
2568 "/m", "zos", "zfd", "zfs", "zfz", "cat", "wta", "wtf", "wxf", "dml", "vi",
2569 "less", "head", "tail", NULL
2570 };
2571 const char *projs[] = {
2572 "Pc", "Pd", "Pi", "Po", "Ps", "P-", NULL
2573 };
2574 const char *mounts[] = {
2575 "md", "mg", "mo", "ms", "mc", "mi", "mw", NULL
2576 };
2577 __foreach (core, flags, R_CORE_AUTOCMPLT_FLAG);
2578 __foreach (core, seeks, R_CORE_AUTOCMPLT_SEEK);
2579 __foreach (core, fcns, R_CORE_AUTOCMPLT_FCN);
2580 __foreach (core, evals, R_CORE_AUTOCMPLT_EVAL);
2581 __foreach (core, breaks, R_CORE_AUTOCMPLT_BRKP);
2582 __foreach (core, files, R_CORE_AUTOCMPLT_FILE);
2583 __foreach (core, projs, R_CORE_AUTOCMPLT_PRJT);
2584 __foreach (core, mounts, R_CORE_AUTOCMPLT_MS);
2585
2586 r_core_autocomplete_add (core->autocomplete, "-", R_CORE_AUTOCMPLT_MINS, true);
2587 r_core_autocomplete_add (core->autocomplete, "zs", R_CORE_AUTOCMPLT_ZIGN, true);
2588 r_core_autocomplete_add (core->autocomplete, "fs", R_CORE_AUTOCMPLT_FLSP, true);
2589 r_core_autocomplete_add (
2590 r_core_autocomplete_add (core->autocomplete, "ls", R_CORE_AUTOCMPLT_DFLT, true),
2591 "-l", R_CORE_AUTOCMPLT_FILE, true);
2592 r_core_autocomplete_add (core->autocomplete, "eco", R_CORE_AUTOCMPLT_THME, true);
2593 r_core_autocomplete_add (core->autocomplete, "k", R_CORE_AUTOCMPLT_SDB, true);
2594 /* macros */
2595 r_core_autocomplete_add (core->autocomplete, ".(", R_CORE_AUTOCMPLT_MACR, true);
2596 r_core_autocomplete_add (core->autocomplete, "(-", R_CORE_AUTOCMPLT_MACR, true);
2597 /* just for hints */
2598 int i;
2599 for (i = 0; i < radare_argc && radare_argv[i]; i++) {
2600 if (!r_core_autocomplete_find (core->autocomplete, radare_argv[i], true)) {
2601 r_core_autocomplete_add (core->autocomplete, radare_argv[i], R_CORE_AUTOCMPLT_DFLT, true);
2602 }
2603 }
2604 }
2605
__init_autocomplete(RCore * core)2606 static void __init_autocomplete(RCore* core) {
2607 int i;
2608 core->autocomplete = R_NEW0 (RCoreAutocomplete);
2609 if (core->autocomplete_type == AUTOCOMPLETE_DEFAULT) {
2610 __init_autocomplete_default (core);
2611 } else if (core->autocomplete_type == AUTOCOMPLETE_MS) {
2612 r_core_autocomplete_add (core->autocomplete, "ls", R_CORE_AUTOCMPLT_MS, true);
2613 r_core_autocomplete_add (core->autocomplete, "cd", R_CORE_AUTOCMPLT_MS, true);
2614 r_core_autocomplete_add (core->autocomplete, "cat", R_CORE_AUTOCMPLT_MS, true);
2615 r_core_autocomplete_add (core->autocomplete, "get", R_CORE_AUTOCMPLT_MS, true);
2616 r_core_autocomplete_add (core->autocomplete, "mount", R_CORE_AUTOCMPLT_MS, true);
2617 for (i = 0; i < ms_argc && ms_argv[i]; i++) {
2618 if (!r_core_autocomplete_find (core->autocomplete, ms_argv[i], true)) {
2619 r_core_autocomplete_add (core->autocomplete, ms_argv[i], R_CORE_AUTOCMPLT_MS, true);
2620 }
2621 }
2622 }
2623 }
2624
colorfor_cb(void * user,ut64 addr,bool verbose)2625 static const char *colorfor_cb(void *user, ut64 addr, bool verbose) {
2626 return r_core_anal_optype_colorfor ((RCore *)user, addr, verbose);
2627 }
2628
hasrefs_cb(void * user,ut64 addr,int mode)2629 static char *hasrefs_cb(void *user, ut64 addr, int mode) {
2630 return r_core_anal_hasrefs ((RCore *)user, addr, mode);
2631 }
2632
get_section_name(void * user,ut64 addr)2633 static const char *get_section_name(void *user, ut64 addr) {
2634 return r_core_get_section_name ((RCore *)user, addr);
2635 }
2636
get_comments_cb(void * user,ut64 addr)2637 static char *get_comments_cb(void *user, ut64 addr) {
2638 return r_core_anal_get_comments ((RCore *)user, addr);
2639 }
2640
cb_event_handler(REvent * ev,int event_type,void * user,void * data)2641 static void cb_event_handler(REvent *ev, int event_type, void *user, void *data) {
2642 RCore *core = (RCore *)ev->user;
2643 if (!core->log_events) {
2644 return;
2645 }
2646 REventMeta *rems = data;
2647 char *str = r_base64_encode_dyn (rems->string, -1);
2648 switch (event_type) {
2649 case R_EVENT_META_SET:
2650 switch (rems->type) {
2651 case 'C':
2652 r_core_log_add (ev->user, sdb_fmt (":add-comment 0x%08"PFMT64x" %s\n", rems->addr, r_str_get (str)));
2653 break;
2654 default:
2655 break;
2656 }
2657 break;
2658 case R_EVENT_META_DEL:
2659 switch (rems->type) {
2660 case 'C':
2661 r_core_log_add (ev->user, sdb_fmt (":del-comment 0x%08"PFMT64x, rems->addr));
2662 break;
2663 default:
2664 r_core_log_add (ev->user, sdb_fmt (":del-comment 0x%08"PFMT64x, rems->addr));
2665 break;
2666 }
2667 break;
2668 case R_EVENT_META_CLEAR:
2669 switch (rems->type) {
2670 case 'C':
2671 r_core_log_add (ev->user, sdb_fmt (":clear-comments 0x%08"PFMT64x, rems->addr));
2672 break;
2673 default:
2674 r_core_log_add (ev->user, sdb_fmt (":clear-comments 0x%08"PFMT64x, rems->addr));
2675 break;
2676 }
2677 break;
2678 default:
2679 // TODO
2680 break;
2681 }
2682 free (str);
2683 }
2684
core_flg_class_set(RFlag * f,const char * name,ut64 addr,ut32 size)2685 static RFlagItem *core_flg_class_set(RFlag *f, const char *name, ut64 addr, ut32 size) {
2686 r_flag_space_push (f, R_FLAGS_FS_CLASSES);
2687 RFlagItem *res = r_flag_set (f, name, addr, size);
2688 r_flag_space_pop (f);
2689 return res;
2690 }
2691
core_flg_class_get(RFlag * f,const char * name)2692 static RFlagItem *core_flg_class_get(RFlag *f, const char *name) {
2693 r_flag_space_push (f, R_FLAGS_FS_CLASSES);
2694 RFlagItem *res = r_flag_get (f, name);
2695 r_flag_space_pop (f);
2696 return res;
2697 }
2698
core_flg_fcn_set(RFlag * f,const char * name,ut64 addr,ut32 size)2699 static RFlagItem *core_flg_fcn_set(RFlag *f, const char *name, ut64 addr, ut32 size) {
2700 r_flag_space_push (f, R_FLAGS_FS_FUNCTIONS);
2701 RFlagItem *res = r_flag_set (f, name, addr, size);
2702 r_flag_space_pop (f);
2703 return res;
2704 }
2705
r_core_autocomplete_reload(RCore * core)2706 R_API void r_core_autocomplete_reload(RCore *core) {
2707 r_return_if_fail (core);
2708 r_core_autocomplete_free (core->autocomplete);
2709 __init_autocomplete (core);
2710 }
2711
r_core_flag_get_by_spaces(RFlag * f,ut64 off)2712 R_API RFlagItem *r_core_flag_get_by_spaces(RFlag *f, ut64 off) {
2713 return r_flag_get_by_spaces (f, off,
2714 R_FLAGS_FS_FUNCTIONS,
2715 R_FLAGS_FS_SIGNS,
2716 R_FLAGS_FS_CLASSES,
2717 R_FLAGS_FS_SYMBOLS,
2718 R_FLAGS_FS_IMPORTS,
2719 R_FLAGS_FS_RELOCS,
2720 R_FLAGS_FS_STRINGS,
2721 R_FLAGS_FS_RESOURCES,
2722 R_FLAGS_FS_SYMBOLS_SECTIONS,
2723 R_FLAGS_FS_SECTIONS,
2724 R_FLAGS_FS_SEGMENTS,
2725 NULL);
2726 }
2727
2728 #if __WINDOWS__
2729 // XXX move to rcons?
win_eprintf(const char * format,...)2730 static int win_eprintf(const char *format, ...) {
2731 va_list ap;
2732 va_start (ap, format);
2733 r_cons_win_vhprintf (STD_ERROR_HANDLE, false, format, ap);
2734 va_end (ap);
2735 return 0;
2736 }
2737 #endif
2738
ev_iowrite_cb(REvent * ev,int type,void * user,void * data)2739 static void ev_iowrite_cb(REvent *ev, int type, void *user, void *data) {
2740 RCore *core = user;
2741 REventIOWrite *iow = data;
2742 if (r_config_get_i (core->config, "anal.detectwrites")) {
2743 r_anal_update_analysis_range (core->anal, iow->addr, iow->len);
2744 if (core->cons->event_resize && core->cons->event_data) {
2745 // Force a reload of the graph
2746 core->cons->event_resize (core->cons->event_data);
2747 }
2748 }
2749 }
2750
r_core_init(RCore * core)2751 R_API bool r_core_init(RCore *core) {
2752 core->blocksize = R_CORE_BLOCKSIZE;
2753 core->block = (ut8 *)calloc (R_CORE_BLOCKSIZE + 1, 1);
2754 if (!core->block) {
2755 r_cons_eprintf ("Cannot allocate %d byte(s)\n", R_CORE_BLOCKSIZE);
2756 /* XXX memory leak */
2757 return false;
2758 }
2759 r_core_setenv (core);
2760 core->ev = r_event_new (core);
2761 r_event_hook (core->ev, R_EVENT_ALL, cb_event_handler, NULL);
2762 core->max_cmd_depth = R_CONS_CMD_DEPTH + 1;
2763 core->sdb = sdb_new (NULL, "r2kv.sdb", 0); // XXX: path must be in home?
2764 core->lastsearch = NULL;
2765 core->cmdfilter = NULL;
2766 core->switch_file_view = 0;
2767 core->cmdremote = 0;
2768 core->incomment = false;
2769 core->config = NULL;
2770 core->prj = r_project_new ();
2771 core->http_up = false;
2772 core->use_tree_sitter_r2cmd = false;
2773 ZERO_FILL (core->root_cmd_descriptor);
2774 core->print = r_print_new ();
2775 core->ropchain = r_list_newf ((RListFree)free);
2776 r_core_bind (core, &(core->print->coreb));
2777 core->print->user = core;
2778 core->print->num = core->num;
2779 core->print->offname = r_core_print_offname;
2780 core->print->offsize = r_core_print_offsize;
2781 core->print->cb_printf = r_cons_printf;
2782 #if __WINDOWS__
2783 core->print->cb_eprintf = win_eprintf;
2784 #endif
2785 core->print->cb_color = r_cons_rainbow_get;
2786 core->print->write = mywrite;
2787 core->print->exists_var = exists_var;
2788 core->print->disasm = __disasm;
2789 core->print->colorfor = colorfor_cb;
2790 core->print->hasrefs = hasrefs_cb;
2791 core->print->get_comments = get_comments_cb;
2792 core->print->get_section_name = get_section_name;
2793 core->print->use_comments = false;
2794 core->rtr_n = 0;
2795 core->blocksize_max = R_CORE_BLOCKSIZE_MAX;
2796 r_core_task_scheduler_init (&core->tasks, core);
2797 core->watchers = r_list_new ();
2798 core->watchers->free = (RListFree)r_core_cmpwatch_free;
2799 core->scriptstack = r_list_new ();
2800 core->scriptstack->free = (RListFree)free;
2801 core->log = r_core_log_new ();
2802 core->times = R_NEW0 (RCoreTimes);
2803 core->vmode = false;
2804 core->printidx = 0;
2805 core->lastcmd = NULL;
2806 core->cmdlog = NULL;
2807 core->print->charset->db = sdb_ns (core->sdb, "charset", 1);
2808 core->print->charset->db->refs++; // increase reference counter to avoid double-free
2809 // ideally sdb_ns_set should be used here, but it doesnt seems to work well. must fix
2810 // sdb_ns_set (DB, "charset", core->print->charset->db);
2811 core->stkcmd = NULL;
2812 core->cmdqueue = NULL;
2813 core->cmdrepeat = true;
2814 core->yank_buf = r_buf_new ();
2815 core->num = r_num_new (&num_callback, &str_callback, core);
2816 core->egg = r_egg_new ();
2817 r_egg_setup (core->egg, R_SYS_ARCH, R_SYS_BITS, 0, R_SYS_OS);
2818
2819 core->undos = r_list_newf ((RListFree)r_core_undo_free);
2820 core->fixedarch = false;
2821 core->fixedbits = false;
2822
2823 core->theme = strdup ("default");
2824 /* initialize libraries */
2825 core->cons = r_cons_new ();
2826 if (core->cons->refcnt == 1) {
2827 core->cons = r_cons_singleton ();
2828 if (core->cons->line) {
2829 core->cons->line->user = core;
2830 core->cons->line->cb_editor = \
2831 (RLineEditorCb)&r_core_editor;
2832 core->cons->line->cb_fkey = core->cons->cb_fkey;
2833 }
2834 #if __EMSCRIPTEN__
2835 core->cons->user_fgets = NULL;
2836 #else
2837 core->cons->user_fgets = (void *)r_core_fgets;
2838 #endif
2839 //r_line_singleton ()->user = (void *)core;
2840 r_line_hist_load (R2_HOME_HISTORY);
2841 }
2842 core->print->cons = core->cons;
2843 r_cons_bind (&core->print->consbind);
2844
2845 // We save the old num ad user, in order to restore it after free
2846 core->lang = r_lang_new ();
2847 core->lang->cmd_str = (char *(*)(void *, const char *))r_core_cmd_str;
2848 core->lang->cmdf = (int (*)(void *, const char *, ...))r_core_cmdf;
2849 r_core_bind_cons (core);
2850 core->table = NULL;
2851 core->lang->cb_printf = r_cons_printf;
2852 r_lang_define (core->lang, "RCore", "core", core);
2853 r_lang_set_user_ptr (core->lang, core);
2854 core->rasm = r_asm_new ();
2855 core->rasm->num = core->num;
2856 r_asm_set_user_ptr (core->rasm, core);
2857 core->anal = r_anal_new ();
2858 core->gadgets = r_list_newf ((RListFree)r_core_gadget_free);
2859 core->anal->ev = core->ev;
2860 core->anal->log = r_core_anal_log;
2861 core->anal->read_at = r_core_anal_read_at;
2862 core->anal->flag_get = r_core_flag_get_by_spaces;
2863 core->anal->cb.on_fcn_new = on_fcn_new;
2864 core->anal->cb.on_fcn_delete = on_fcn_delete;
2865 core->anal->cb.on_fcn_rename = on_fcn_rename;
2866 core->print->sdb_types = core->anal->sdb_types;
2867 core->rasm->syscall = r_syscall_ref (core->anal->syscall); // BIND syscall anal/asm
2868 r_anal_set_user_ptr (core->anal, core);
2869 core->anal->cb_printf = (void *) r_cons_printf;
2870 core->parser = r_parse_new ();
2871 r_anal_bind (core->anal, &(core->parser->analb));
2872 core->parser->varlist = r_anal_function_get_var_fields;
2873 /// XXX shouhld be using coreb
2874 r_parse_set_user_ptr (core->parser, core);
2875 core->bin = r_bin_new ();
2876 r_cons_bind (&core->bin->consb);
2877 // XXX we shuold use RConsBind instead of this hardcoded pointer
2878 core->bin->cb_printf = (PrintfCallback) r_cons_printf;
2879 r_bin_set_user_ptr (core->bin, core);
2880 core->io = r_io_new ();
2881 r_event_hook (core->io->event, R_EVENT_IO_WRITE, ev_iowrite_cb, core);
2882 core->io->ff = 1;
2883 core->search = r_search_new (R_SEARCH_KEYWORD);
2884 r_io_undo_enable (core->io, 1, 0); // TODO: configurable via eval
2885 core->fs = r_fs_new ();
2886 core->flags = r_flag_new ();
2887 core->flags->cb_printf = r_cons_printf;
2888 core->graph = r_agraph_new (r_cons_canvas_new (1, 1));
2889 core->graph->need_reload_nodes = false;
2890 core->asmqjmps_size = R_CORE_ASMQJMPS_NUM;
2891 if (sizeof (ut64) * core->asmqjmps_size < core->asmqjmps_size) {
2892 core->asmqjmps_size = 0;
2893 core->asmqjmps = NULL;
2894 } else {
2895 core->asmqjmps = R_NEWS (ut64, core->asmqjmps_size);
2896 }
2897
2898 r_bin_bind (core->bin, &(core->rasm->binb));
2899 r_bin_bind (core->bin, &(core->anal->binb));
2900 r_bin_bind (core->bin, &(core->anal->binb));
2901
2902 r_io_bind (core->io, &(core->search->iob));
2903 r_io_bind (core->io, &(core->print->iob));
2904 r_io_bind (core->io, &(core->anal->iob));
2905 r_io_bind (core->io, &(core->fs->iob));
2906 r_cons_bind (&(core->fs->csb));
2907 r_core_bind (core, &(core->fs->cob));
2908 r_io_bind (core->io, &(core->bin->iob));
2909 r_flag_bind (core->flags, &(core->anal->flb));
2910 core->anal->flg_class_set = core_flg_class_set;
2911 core->anal->flg_class_get = core_flg_class_get;
2912 core->anal->flg_fcn_set = core_flg_fcn_set;
2913 r_anal_bind (core->anal, &(core->parser->analb));
2914 core->parser->flag_get = r_core_flag_get_by_spaces;
2915 core->parser->label_get = r_anal_function_get_label_at;
2916
2917 r_core_bind (core, &(core->anal->coreb));
2918
2919 core->offset = 0LL;
2920 core->prompt_offset = 0LL;
2921 r_core_cmd_init (core);
2922 core->dbg = r_debug_new (true);
2923
2924 r_io_bind (core->io, &(core->dbg->iob));
2925 r_io_bind (core->io, &(core->dbg->bp->iob));
2926 r_core_bind (core, &core->dbg->corebind);
2927 r_core_bind (core, &core->dbg->bp->corebind);
2928 r_core_bind (core, &core->io->corebind);
2929 core->dbg->anal = core->anal; // XXX: dupped instance.. can cause lost pointerz
2930 //r_debug_use (core->dbg, "native");
2931 // XXX pushing uninitialized regstate results in trashed reg values
2932 // r_reg_arena_push (core->dbg->reg); // create a 2 level register state stack
2933 // core->dbg->anal->reg = core->anal->reg; // XXX: dupped instance.. can cause lost pointerz
2934 core->io->cb_printf = r_cons_printf;
2935 core->dbg->cb_printf = r_cons_printf;
2936 core->dbg->bp->cb_printf = r_cons_printf;
2937 core->dbg->ev = core->ev;
2938 // initialize config before any corebind
2939 r_core_config_init (core);
2940
2941 r_core_loadlibs_init (core);
2942 //r_core_loadlibs (core);
2943
2944 // TODO: get arch from r_bin or from native arch
2945 r_asm_use (core->rasm, R_SYS_ARCH);
2946 r_anal_use (core->anal, R_SYS_ARCH);
2947 if (R_SYS_BITS & R_SYS_BITS_64) {
2948 r_config_set_i (core->config, "asm.bits", 64);
2949 } else {
2950 if (R_SYS_BITS & R_SYS_BITS_32) {
2951 r_config_set_i (core->config, "asm.bits", 32);
2952 }
2953 }
2954 r_config_set (core->config, "asm.arch", R_SYS_ARCH);
2955 r_bp_use (core->dbg->bp, R_SYS_ARCH, core->anal->bits);
2956 update_sdb (core);
2957 {
2958 char *a = r_str_r2_prefix (R2_FLAGS);
2959 if (a) {
2960 char *file = r_str_newf ("%s/tags.r2", a);
2961 bool p = core->print->enable_progressbar;
2962 core->print->enable_progressbar = false;
2963 (void)r_core_run_script (core, file);
2964 core->print->enable_progressbar = p;
2965 free (file);
2966 free (a);
2967 }
2968 }
2969 r_core_anal_type_init (core);
2970 __init_autocomplete (core);
2971 return 0;
2972 }
2973
__cons_cb_fkey(RCore * core,int fkey)2974 R_API void __cons_cb_fkey(RCore *core, int fkey) {
2975 char buf[32];
2976 snprintf (buf, sizeof (buf), "key.f%d", fkey);
2977 const char *v = r_config_get (core->config, buf);
2978 if (v && *v) {
2979 r_cons_printf ("%s\n", v);
2980 r_core_cmd0 (core, v);
2981 r_cons_flush ();
2982 }
2983 }
2984
r_core_bind_cons(RCore * core)2985 R_API void r_core_bind_cons(RCore *core) {
2986 core->cons->num = core->num;
2987 core->cons->cb_fkey = (RConsFunctionKey)__cons_cb_fkey;
2988 core->cons->cb_editor = (RConsEditorCallback)r_core_editor;
2989 core->cons->cb_break = (RConsBreakCallback)r_core_break;
2990 core->cons->cb_sleep_begin = (RConsSleepBeginCallback)r_core_sleep_begin;
2991 core->cons->cb_sleep_end = (RConsSleepEndCallback)r_core_sleep_end;
2992 core->cons->cb_task_oneshot = (RConsQueueTaskOneshot) r_core_task_enqueue_oneshot;
2993 core->cons->user = (void*)core;
2994 }
2995
r_core_fini(RCore * c)2996 R_API void r_core_fini(RCore *c) {
2997 if (!c) {
2998 return;
2999 }
3000 r_core_task_break_all (&c->tasks);
3001 r_core_task_join (&c->tasks, NULL, -1);
3002 r_core_wait (c);
3003 /* TODO: it leaks as shit */
3004 //update_sdb (c);
3005 // avoid double free
3006 r_list_free (c->ropchain);
3007 r_table_free (c->table);
3008 r_event_free (c->ev);
3009 free (c->cmdlog);
3010 free (c->lastsearch);
3011 R_FREE (c->cons->pager);
3012 free (c->cmdqueue);
3013 free (c->lastcmd);
3014 free (c->stkcmd);
3015 r_project_free (c->prj);
3016 r_list_free (c->visual.tabs);
3017 free (c->block);
3018 r_core_autocomplete_free (c->autocomplete);
3019
3020 r_list_free (c->gadgets);
3021 r_list_free (c->undos);
3022 r_num_free (c->num);
3023 // TODO: sync or not? sdb_sync (c->sdb);
3024 // TODO: sync all dbs?
3025 //c->file = NULL;
3026 R_FREE (c->table_query);
3027 r_list_free (c->watchers);
3028 r_list_free (c->scriptstack);
3029 r_core_task_scheduler_fini (&c->tasks);
3030 c->rcmd = r_cmd_free (c->rcmd);
3031 r_list_free (c->cmd_descriptors);
3032 c->anal = r_anal_free (c->anal);
3033 r_asm_free (c->rasm);
3034 c->rasm = NULL;
3035 c->print = r_print_free (c->print);
3036 c->bin = (r_bin_free (c->bin), NULL);
3037 c->dbg = (r_debug_free (c->dbg), NULL);
3038 c->io = (r_io_free (c->io), NULL);
3039 c->lang = (r_lang_free (c->lang), NULL);
3040 r_config_free (c->config);
3041 /* after r_config_free, the value of I.teefile is trashed */
3042 /* rconfig doesnt knows how to deinitialize vars, so we
3043 should probably need to add a r_config_free_payload callback */
3044 r_cons_free ();
3045 r_cons_singleton ()->teefile = NULL; // HACK
3046 free (c->theme);
3047 r_search_free (c->search);
3048 r_flag_free (c->flags);
3049 r_fs_free (c->fs);
3050 r_egg_free (c->egg);
3051 r_lib_free (c->lib);
3052 r_buf_free (c->yank_buf);
3053 r_agraph_free (c->graph);
3054 free (c->asmqjmps);
3055 sdb_free (c->sdb);
3056 r_core_log_free (c->log);
3057 r_parse_free (c->parser);
3058 free (c->times);
3059 }
3060
r_core_free(RCore * c)3061 R_API void r_core_free(RCore *c) {
3062 if (c) {
3063 r_core_fini (c);
3064 free (c);
3065 }
3066 }
3067
r_core_prompt_loop(RCore * r)3068 R_API void r_core_prompt_loop(RCore *r) {
3069 int ret;
3070 do {
3071 int err = r_core_prompt (r, false);
3072 if (err < 1) {
3073 // handle ^D
3074 r->num->value = 0; // r.num->value will be read by r_main_radare2() after calling this fcn
3075 break;
3076 }
3077 /* -1 means invalid command, -2 means quit prompt loop */
3078 if ((ret = r_core_prompt_exec (r)) == -2) {
3079 break;
3080 }
3081 } while (ret != R_CORE_CMD_EXIT);
3082 }
3083
prompt_flag(RCore * r,char * s,size_t maxlen)3084 static int prompt_flag (RCore *r, char *s, size_t maxlen) {
3085 const char DOTS[] = "...";
3086 const RFlagItem *f = r_flag_get_at (r->flags, r->offset, false);
3087 if (!f) {
3088 return false;
3089 }
3090 if (f->offset < r->offset) {
3091 snprintf (s, maxlen, "%s + %" PFMT64u, f->name, r->offset - f->offset);
3092 } else {
3093 snprintf (s, maxlen, "%s", f->name);
3094 }
3095 if (strlen (s) > maxlen - sizeof (DOTS)) {
3096 s[maxlen - sizeof (DOTS) - 1] = '\0';
3097 strcat (s, DOTS);
3098 }
3099 return true;
3100 }
3101
prompt_sec(RCore * r,char * s,size_t maxlen)3102 static void prompt_sec(RCore *r, char *s, size_t maxlen) {
3103 const RBinSection *sec = r_bin_get_section_at (r_bin_cur_object (r->bin), r->offset, true);
3104 if (!sec) {
3105 return;
3106 }
3107 r_str_ncpy (s, sec->name, maxlen - 2);
3108 strcat (s, ":");
3109 }
3110
chop_prompt(const char * filename,char * tmp,size_t max_tmp_size)3111 static void chop_prompt (const char *filename, char *tmp, size_t max_tmp_size) {
3112 size_t tmp_len, file_len;
3113 unsigned int OTHRSCH = 3;
3114 const char DOTS[] = "...";
3115 int w, p_len;
3116
3117 w = r_cons_get_size (NULL);
3118 file_len = strlen (filename);
3119 tmp_len = strlen (tmp);
3120 p_len = R_MAX (0, w - 6);
3121 if (file_len + tmp_len + OTHRSCH >= p_len) {
3122 size_t dots_size = sizeof (DOTS);
3123 size_t chop_point = (size_t)(p_len - OTHRSCH - file_len - dots_size);
3124 if (chop_point < max_tmp_size - dots_size) {
3125 snprintf (tmp + chop_point, dots_size, "%s", DOTS);
3126 }
3127 }
3128 }
3129
set_prompt(RCore * r)3130 static void set_prompt (RCore *r) {
3131 char tmp[128];
3132 char *filename = strdup ("");
3133 const char *cmdprompt = r_config_get (r->config, "cmd.prompt");
3134 const char *BEGIN = "";
3135 const char *END = "";
3136 const char *remote = "";
3137
3138 if (cmdprompt && *cmdprompt) {
3139 r_core_cmd (r, cmdprompt, 0);
3140 }
3141
3142 if (r_config_get_i (r->config, "scr.prompt.file")) {
3143 free (filename);
3144 filename = r_str_newf ("\"%s\"",
3145 r->io->desc ? r_file_basename (r->io->desc->name) : "");
3146 }
3147 if (r->cmdremote) {
3148 char *s = r_core_cmd_str (r, "s");
3149 r->offset = r_num_math (NULL, s);
3150 free (s);
3151 remote = "=!";
3152 }
3153
3154 if (r_config_get_i (r->config, "scr.color")) {
3155 BEGIN = r->cons->context->pal.prompt;
3156 END = r->cons->context->pal.reset;
3157 }
3158
3159 // TODO: also in visual prompt and disasm/hexdump ?
3160 if (r_config_get_i (r->config, "asm.segoff")) {
3161 ut32 a, b;
3162 unsigned int seggrn = r_config_get_i (r->config, "asm.seggrn");
3163
3164 a = ((r->offset >> 16) << (16 - seggrn));
3165 b = (r->offset & 0xffff);
3166 snprintf (tmp, 128, "%04x:%04x", a, b);
3167 } else {
3168 char p[64], sec[32];
3169 int promptset = false;
3170
3171 sec[0] = '\0';
3172 if (r_config_get_i (r->config, "scr.prompt.flag")) {
3173 promptset = prompt_flag (r, p, sizeof (p));
3174 }
3175 if (r_config_get_i (r->config, "scr.prompt.sect")) {
3176 prompt_sec (r, sec, sizeof (sec));
3177 }
3178
3179 if (!promptset) {
3180 if (r->print->wide_offsets && r->dbg->bits & R_SYS_BITS_64) {
3181 snprintf (p, sizeof (p), "0x%016" PFMT64x, r->offset);
3182 } else {
3183 snprintf (p, sizeof (p), "0x%08" PFMT64x, r->offset);
3184 }
3185 }
3186 snprintf (tmp, sizeof (tmp), "%s%s", sec, p);
3187 }
3188
3189 chop_prompt (filename, tmp, 128);
3190 char *prompt = r_str_newf ("%s%s[%s%s]>%s ", filename, BEGIN, remote,
3191 tmp, END);
3192 r_line_set_prompt (r_str_get (prompt));
3193
3194 R_FREE (filename);
3195 R_FREE (prompt);
3196 }
3197
r_core_prompt(RCore * r,int sync)3198 R_API int r_core_prompt(RCore *r, int sync) {
3199 char line[4096];
3200
3201 int rnv = r->num->value;
3202 set_prompt (r);
3203 int ret = r_cons_fgets (line, sizeof (line), 0, NULL);
3204 if (ret == -2) {
3205 return R_CORE_CMD_EXIT; // ^D
3206 }
3207 if (ret == -1) {
3208 return false; // FD READ ERROR
3209 }
3210 r->num->value = rnv;
3211 if (sync) {
3212 return r_core_prompt_exec (r);
3213 }
3214 free (r->cmdqueue);
3215 r->cmdqueue = strdup (line);
3216 if (r->scr_gadgets && *line && *line != 'q') {
3217 r_core_cmd0 (r, "pg");
3218 }
3219 r->num->value = r->rc;
3220 return true;
3221 }
3222
3223 extern void r_core_echo(RCore *core, const char *input);
3224
r_core_prompt_exec(RCore * r)3225 R_API int r_core_prompt_exec(RCore *r) {
3226 int ret = r_core_cmd (r, r->cmdqueue, true);
3227 r->rc = r->num->value;
3228 //int ret = r_core_cmd (r, r->cmdqueue, true);
3229 if (r->cons && r->cons->use_tts) {
3230 const char *buf = r_cons_get_buffer();
3231 r_sys_tts (buf, true);
3232 r->cons->use_tts = false;
3233 }
3234 r_cons_echo (NULL);
3235 r_cons_flush ();
3236 if (r->cons && r->cons->line && r->cons->line->zerosep) {
3237 r_cons_zero ();
3238 }
3239 return ret;
3240 }
3241
r_core_seek_size(RCore * core,ut64 addr,int bsize)3242 R_API int r_core_seek_size(RCore *core, ut64 addr, int bsize) {
3243 ut8 *bump;
3244 int ret = false;
3245 if (bsize < 0) {
3246 return false;
3247 }
3248 if (bsize == core->blocksize) {
3249 return true;
3250 }
3251 if (r_sandbox_enable (0)) {
3252 // TODO : restrict to filesize?
3253 if (bsize > 1024 * 32) {
3254 r_cons_eprintf ("Sandbox mode restricts blocksize bigger than 32k\n");
3255 return false;
3256 }
3257 }
3258 if (bsize > core->blocksize_max) {
3259 r_cons_eprintf ("Block size %d is too big\n", bsize);
3260 return false;
3261 }
3262 core->offset = addr;
3263 if (bsize < 1) {
3264 bsize = 1;
3265 } else if (core->blocksize_max && bsize>core->blocksize_max) {
3266 r_cons_eprintf ("bsize is bigger than `bm`. dimmed to 0x%x > 0x%x\n",
3267 bsize, core->blocksize_max);
3268 bsize = core->blocksize_max;
3269 }
3270 bump = realloc (core->block, bsize + 1);
3271 if (!bump) {
3272 r_cons_eprintf ("Oops. cannot allocate that much (%u)\n", bsize);
3273 ret = false;
3274 } else {
3275 ret = true;
3276 core->block = bump;
3277 core->blocksize = bsize;
3278 memset (core->block, 0xff, core->blocksize);
3279 r_core_block_read (core);
3280 }
3281 return ret;
3282 }
3283
r_core_block_size(RCore * core,int bsize)3284 R_API int r_core_block_size(RCore *core, int bsize) {
3285 return r_core_seek_size (core, core->offset, bsize);
3286 }
3287
r_core_seek_align(RCore * core,ut64 align,int times)3288 R_API int r_core_seek_align(RCore *core, ut64 align, int times) {
3289 int inc = (times >= 0)? 1: -1;
3290 ut64 seek = core->offset;
3291 if (!align) {
3292 return false;
3293 }
3294 int diff = core->offset % align;
3295 if (!times) {
3296 diff = -diff;
3297 } else if (diff) {
3298 if (inc > 0) {
3299 diff += align-diff;
3300 } else {
3301 diff = -diff;
3302 }
3303 if (times) {
3304 times -= inc;
3305 }
3306 }
3307 while ((times*inc) > 0) {
3308 times -= inc;
3309 diff += (align * inc);
3310 }
3311 if (diff < 0 && -diff > seek) {
3312 seek = diff = 0;
3313 }
3314 return r_core_seek (core, seek + diff, true);
3315 }
3316
r_core_op_str(RCore * core,ut64 addr)3317 R_API char *r_core_op_str(RCore *core, ut64 addr) {
3318 RAsmOp op = {0};
3319 ut8 buf[64];
3320 r_asm_set_pc (core->rasm, addr);
3321 r_io_read_at (core->io, addr, buf, sizeof (buf));
3322 int ret = r_asm_disassemble (core->rasm, &op, buf, sizeof (buf));
3323 char *str = (ret > 0)? strdup (r_strbuf_get (&op.buf_asm)): NULL;
3324 r_asm_op_fini (&op);
3325 return str;
3326 }
3327
r_core_op_anal(RCore * core,ut64 addr,RAnalOpMask mask)3328 R_API RAnalOp *r_core_op_anal(RCore *core, ut64 addr, RAnalOpMask mask) {
3329 ut8 buf[64];
3330 RAnalOp *op = R_NEW (RAnalOp);
3331 r_io_read_at (core->io, addr, buf, sizeof (buf));
3332 r_anal_op (core->anal, op, addr, buf, sizeof (buf), mask);
3333 return op;
3334 }
3335
rap_break(void * u)3336 static void rap_break (void *u) {
3337 RIORap *rior = (RIORap*) u;
3338 if (u) {
3339 r_socket_close (rior->fd);
3340 rior->fd = NULL;
3341 }
3342 }
3343
3344 // TODO: PLEASE move into core/io/rap? */
3345 // TODO: use static buffer instead of mallocs all the time. it's network!
r_core_serve(RCore * core,RIODesc * file)3346 R_API bool r_core_serve(RCore *core, RIODesc *file) {
3347 // TODO: use r_socket_rap_server API instead of duplicating the logic
3348 ut8 cmd, flg, *ptr = NULL, buf[1024];
3349 int i, pipefd = -1;
3350 ut64 x;
3351
3352 RIORap *rior = (RIORap *)file->data;
3353 if (!rior || !rior->fd) {
3354 r_cons_eprintf ("rap: cannot listen.\n");
3355 return false;
3356 }
3357 RSocket *fd = rior->fd;
3358 r_cons_eprintf ("RAP Server started (rap.loop=%s)\n",
3359 r_config_get (core->config, "rap.loop"));
3360 r_cons_break_push (rap_break, rior);
3361 reaccept:
3362 while (!r_cons_is_breaked ()) {
3363 RSocket *c = r_socket_accept (fd);
3364 if (!c) {
3365 break;
3366 }
3367 if (r_cons_is_breaked ()) {
3368 goto out_of_function;
3369 }
3370 if (!c) {
3371 r_cons_eprintf ("rap: cannot accept\n");
3372 r_socket_free (c);
3373 goto out_of_function;
3374 }
3375 r_cons_eprintf ("rap: client connected\n");
3376 for (;!r_cons_is_breaked ();) {
3377 if (!r_socket_read_block (c, &cmd, 1)) {
3378 r_cons_eprintf ("rap: connection closed\n");
3379 if (r_config_get_i (core->config, "rap.loop")) {
3380 r_cons_eprintf ("rap: waiting for new connection\n");
3381 r_socket_free (c);
3382 goto reaccept;
3383 }
3384 goto out_of_function;
3385 }
3386 switch (cmd) {
3387 case RAP_PACKET_OPEN:
3388 r_socket_read_block (c, &flg, 1); // flags
3389 r_cons_eprintf ("open (%d): ", cmd);
3390 r_socket_read_block (c, &cmd, 1); // len
3391 pipefd = -1;
3392 if (UT8_ADD_OVFCHK (cmd, 1)) {
3393 goto out_of_function;
3394 }
3395 ptr = malloc ((size_t)cmd + 1);
3396 if (!ptr) {
3397 r_cons_eprintf ("Cannot malloc in rmt-open len = %d\n", cmd);
3398 } else {
3399 ut64 baddr = r_config_get_i (core->config, "bin.laddr");
3400 r_socket_read_block (c, ptr, cmd);
3401 ptr[cmd] = 0;
3402 ut32 perm = R_PERM_R;
3403 if (flg & R_PERM_W) {
3404 perm |= R_PERM_W;
3405 }
3406 if (r_core_file_open (core, (const char *)ptr, perm, 0)) {
3407 int fd = r_io_fd_get_current (core->io);
3408 r_core_bin_load (core, NULL, baddr);
3409 r_io_map_add (core->io, fd, perm, 0, 0, r_io_fd_size (core->io, fd));
3410 if (core->io->desc) {
3411 pipefd = fd;
3412 } else {
3413 pipefd = -1;
3414 }
3415 r_cons_eprintf ("(flags: %d) len: %d filename: '%s'\n",
3416 flg, cmd, ptr); //config.file);
3417 } else {
3418 pipefd = -1;
3419 r_cons_eprintf ("Cannot open file (%s)\n", ptr);
3420 r_socket_close (c);
3421 if (r_config_get_i (core->config, "rap.loop")) {
3422 r_cons_eprintf ("rap: waiting for new connection\n");
3423 r_socket_free (c);
3424 goto reaccept;
3425 }
3426 goto out_of_function; //XXX: Close connection and goto accept
3427 }
3428 }
3429 buf[0] = RAP_PACKET_OPEN | RAP_PACKET_REPLY;
3430 r_write_be32 (buf + 1, pipefd);
3431 r_socket_write (c, buf, 5);
3432 r_socket_flush (c);
3433 R_FREE (ptr);
3434 break;
3435 case RAP_PACKET_READ:
3436 r_socket_read_block (c, (ut8*)&buf, 4);
3437 i = r_read_be32 (buf);
3438 ptr = (ut8 *)malloc (i + core->blocksize + 5);
3439 if (ptr) {
3440 r_core_block_read (core);
3441 ptr[0] = RAP_PACKET_READ | RAP_PACKET_REPLY;
3442 if (i > RAP_PACKET_MAX) {
3443 i = RAP_PACKET_MAX;
3444 }
3445 if (i > core->blocksize) {
3446 r_core_block_size (core, i);
3447 }
3448 if (i + 128 < core->blocksize) {
3449 r_core_block_size (core, i);
3450 }
3451 r_write_be32 (ptr + 1, i);
3452 memcpy (ptr + 5, core->block, i); //core->blocksize);
3453 r_socket_write (c, ptr, i + 5);
3454 r_socket_flush (c);
3455 R_FREE (ptr);
3456 } else {
3457 r_cons_eprintf ("Cannot read %d byte(s)\n", i);
3458 r_socket_free (c);
3459 // TODO: reply error here
3460 goto out_of_function;
3461 }
3462 break;
3463 case RAP_PACKET_CMD:
3464 {
3465 char *cmd = NULL, *cmd_output = NULL;
3466 char bufr[8], *bufw = NULL;
3467 ut32 cmd_len = 0;
3468 int i;
3469
3470 /* read */
3471 r_socket_read_block (c, (ut8*)&bufr, 4);
3472 i = r_read_be32 (bufr);
3473 if (i > 0 && i < RAP_PACKET_MAX) {
3474 if ((cmd = malloc (i + 1))) {
3475 r_socket_read_block (c, (ut8*)cmd, i);
3476 cmd[i] = '\0';
3477 int scr_interactive = r_config_get_i (core->config, "scr.interactive");
3478 r_config_set_i (core->config, "scr.interactive", 0);
3479 cmd_output = r_core_cmd_str (core, cmd);
3480 r_config_set_i (core->config, "scr.interactive", scr_interactive);
3481 free (cmd);
3482 } else {
3483 r_cons_eprintf ("rap: cannot malloc\n");
3484 }
3485 } else {
3486 r_cons_eprintf ("rap: invalid length '%d'\n", i);
3487 }
3488 /* write */
3489 if (cmd_output) {
3490 cmd_len = strlen (cmd_output) + 1;
3491 } else {
3492 cmd_output = strdup ("");
3493 cmd_len = 0;
3494 }
3495 #if DEMO_SERVER_SENDS_CMD_TO_CLIENT
3496 static bool once = true;
3497 /* TODO: server can reply a command request to the client only here */
3498 if (once) {
3499 const char *cmd = "pd 4";
3500 int cmd_len = strlen (cmd) + 1;
3501 ut8 *b = malloc (cmd_len + 5);
3502 b[0] = RAP_PACKET_CMD;
3503 r_write_be32 (b + 1, cmd_len);
3504 strcpy ((char *)b+ 5, cmd);
3505 r_socket_write (c, b, 5 + cmd_len);
3506 r_socket_flush (c);
3507
3508 /* read response */
3509 r_socket_read_block (c, b, 5);
3510 if (b[0] == (RAP_PACKET_CMD | RAP_PACKET_REPLY)) {
3511 ut32 n = r_read_be32 (b + 1);
3512 r_cons_eprintf ("REPLY %d\n", n);
3513 if (n > 0) {
3514 ut8 *res = calloc (1, n);
3515 r_socket_read_block (c, res, n);
3516 r_cons_eprintf ("RESPONSE(%s)\n", (const char *)res);
3517 free (res);
3518 }
3519 }
3520 r_socket_flush (c);
3521 free (b);
3522 once = false;
3523 }
3524 #endif
3525 bufw = malloc (cmd_len + 5);
3526 bufw[0] = (ut8) (RAP_PACKET_CMD | RAP_PACKET_REPLY);
3527 r_write_be32 (bufw + 1, cmd_len);
3528 memcpy (bufw + 5, cmd_output, cmd_len);
3529 r_socket_write (c, bufw, cmd_len+5);
3530 r_socket_flush (c);
3531 free (bufw);
3532 free (cmd_output);
3533 break;
3534 }
3535 case RAP_PACKET_WRITE:
3536 r_socket_read_block (c, buf, 4);
3537 x = r_read_at_be32 (buf, 0);
3538 ptr = malloc (x);
3539 r_socket_read_block (c, ptr, x);
3540 int ret = r_core_write_at (core, core->offset, ptr, x);
3541 buf[0] = RAP_PACKET_WRITE | RAP_PACKET_REPLY;
3542 r_write_be32 (buf + 1, ret);
3543 r_socket_write (c, buf, 5);
3544 r_socket_flush (c);
3545 R_FREE (ptr);
3546 break;
3547 case RAP_PACKET_SEEK:
3548 r_socket_read_block (c, buf, 9);
3549 x = r_read_at_be64 (buf, 1);
3550 if (buf[0] == 2) {
3551 if (core->io->desc) {
3552 x = r_io_fd_size (core->io, core->io->desc->fd);
3553 } else {
3554 x = 0;
3555 }
3556 } else {
3557 if (buf[0] == 0) {
3558 r_core_seek (core, x, true); //buf[0]);
3559 }
3560 x = core->offset;
3561 }
3562 buf[0] = RAP_PACKET_SEEK | RAP_PACKET_REPLY;
3563 r_write_be64 (buf + 1, x);
3564 r_socket_write (c, buf, 9);
3565 r_socket_flush (c);
3566 break;
3567 case RAP_PACKET_CLOSE:
3568 // XXX : proper shutdown
3569 r_socket_read_block (c, buf, 4);
3570 i = r_read_be32 (buf);
3571 {
3572 //FIXME: Use r_socket_close
3573 int ret = close (i);
3574 r_write_be32 (buf + 1, ret);
3575 buf[0] = RAP_PACKET_CLOSE | RAP_PACKET_REPLY;
3576 r_socket_write (c, buf, 5);
3577 r_socket_flush (c);
3578 }
3579 break;
3580 default:
3581 if (cmd == 'G') {
3582 // silly http emulation over rap://
3583 char line[256] = {0};
3584 r_socket_read_block (c, (ut8*)line, sizeof (line));
3585 if (!strncmp (line, "ET /cmd/", 8)) {
3586 char *cmd = line + 8;
3587 char *http = strstr (cmd, "HTTP");
3588 if (http) {
3589 *http = 0;
3590 http--;
3591 if (*http == ' ') {
3592 *http = 0;
3593 }
3594 }
3595 r_str_uri_decode (cmd);
3596 char *res = r_core_cmd_str (core, cmd);
3597 if (res) {
3598 r_socket_printf (c, "HTTP/1.0 %d %s\r\n%s"
3599 "Connection: close\r\nContent-Length: %d\r\n\r\n",
3600 200, "OK", "", -1); // strlen (res));
3601 r_socket_write (c, res, strlen (res));
3602 free (res);
3603 }
3604 r_socket_flush (c);
3605 r_socket_close (c);
3606 }
3607 } else {
3608 r_cons_eprintf ("[rap] unknown command 0x%02x\n", cmd);
3609 r_socket_close (c);
3610 R_FREE (ptr);
3611 }
3612 if (r_config_get_i (core->config, "rap.loop")) {
3613 r_cons_eprintf ("rap: waiting for new connection\n");
3614 r_socket_free (c);
3615 goto reaccept;
3616 }
3617 goto out_of_function;
3618 }
3619 }
3620 r_cons_eprintf ("client: disconnected\n");
3621 r_socket_free (c);
3622 }
3623 out_of_function:
3624 r_cons_break_pop ();
3625 return false;
3626 }
3627
r_core_search_cb(RCore * core,ut64 from,ut64 to,RCoreSearchCallback cb)3628 R_API int r_core_search_cb(RCore *core, ut64 from, ut64 to, RCoreSearchCallback cb) {
3629 int ret, len = core->blocksize;
3630 ut8 *buf = malloc (len);
3631 if (!buf) {
3632 r_cons_eprintf ("Cannot allocate blocksize\n");
3633 return false;
3634 }
3635 while (from < to) {
3636 ut64 delta = to-from;
3637 if (delta < len) {
3638 len = (int)delta;
3639 }
3640 if (!r_io_read_at (core->io, from, buf, len)) {
3641 r_cons_eprintf ("Cannot read at 0x%"PFMT64x"\n", from);
3642 break;
3643 }
3644 for (ret = 0; ret < len;) {
3645 int done = cb (core, from, buf+ret, len-ret);
3646 if (done < 1) { /* interrupted */
3647 free (buf);
3648 return false;
3649 }
3650 ret += done;
3651 }
3652 from += len;
3653 }
3654 free (buf);
3655 return true;
3656 }
3657
r_core_editor(const RCore * core,const char * file,const char * str)3658 R_API char *r_core_editor(const RCore *core, const char *file, const char *str) {
3659 const bool interactive = r_cons_is_interactive ();
3660 const char *editor = r_config_get (core->config, "cfg.editor");
3661 char *name = NULL, *ret = NULL;
3662 int fd;
3663
3664 if (!interactive || !editor || !*editor) {
3665 return NULL;
3666 }
3667 bool readonly = false;
3668 if (file && *file != '*') {
3669 name = strdup (file);
3670 fd = r_sandbox_open (file, O_RDWR, 0644);
3671 if (fd == -1) {
3672 fd = r_sandbox_open (file, O_RDWR | O_CREAT, 0644);
3673 if (fd == -1) {
3674 fd = r_sandbox_open (file, O_RDONLY, 0644);
3675 readonly = true;
3676 }
3677 }
3678 } else {
3679 fd = r_file_mkstemp (file, &name);
3680 }
3681 if (fd == -1) {
3682 free (name);
3683 return NULL;
3684 }
3685 if (readonly) {
3686 r_cons_eprintf ("Opening in read-only\n");
3687 } else {
3688 if (str) {
3689 const size_t str_len = strlen (str);
3690 if (write (fd, str, str_len) != str_len) {
3691 close (fd);
3692 free (name);
3693 return NULL;
3694 }
3695 }
3696 }
3697 close (fd);
3698
3699 if (name && (!editor || !*editor || !strcmp (editor, "-"))) {
3700 RCons *cons = r_cons_singleton ();
3701 void *tmp = cons->cb_editor;
3702 cons->cb_editor = NULL;
3703 r_cons_editor (name, NULL);
3704 cons->cb_editor = tmp;
3705 } else {
3706 if (editor && name) {
3707 char *escaped_name = r_str_escape_sh (name);
3708 r_sys_cmdf ("%s \"%s\"", editor, escaped_name);
3709 free (escaped_name);
3710 }
3711 }
3712 size_t len = 0;
3713 ret = name? r_file_slurp (name, &len): 0;
3714 if (ret) {
3715 if (len && ret[len - 1] == '\n') {
3716 ret[len - 1] = 0; // chop
3717 }
3718 if (!file) {
3719 r_file_rm (name);
3720 }
3721 }
3722 free (name);
3723 return ret;
3724 }
3725
3726 /* weak getters */
r_core_get_cons(RCore * core)3727 R_API RCons *r_core_get_cons (RCore *core) {
3728 return core->cons;
3729 }
3730
r_core_get_config(RCore * core)3731 R_API RConfig *r_core_get_config (RCore *core) {
3732 return core->config;
3733 }
3734
r_core_get_bin(RCore * core)3735 R_API RBin *r_core_get_bin (RCore *core) {
3736 return core->bin;
3737 }
3738
r_core_syscallf(RCore * core,const char * name,const char * fmt,...)3739 R_API RBuffer *r_core_syscallf (RCore *core, const char *name, const char *fmt, ...) {
3740 char str[1024];
3741 RBuffer *buf;
3742 va_list ap;
3743 va_start (ap, fmt);
3744
3745 vsnprintf (str, sizeof (str), fmt, ap);
3746 buf = r_core_syscall (core, name, str);
3747
3748 va_end (ap);
3749 return buf;
3750 }
3751
r_core_syscall(RCore * core,const char * name,const char * args)3752 R_API RBuffer *r_core_syscall (RCore *core, const char *name, const char *args) {
3753 RBuffer *b = NULL;
3754 char code[1024];
3755 int num;
3756
3757 //arch check
3758 if (strcmp (core->anal->cur->arch, "x86")) {
3759 r_cons_eprintf ("architecture not yet supported!\n");
3760 return 0;
3761 }
3762
3763 num = r_syscall_get_num (core->anal->syscall, name);
3764
3765 //bits check
3766 switch (core->rasm->bits) {
3767 case 32:
3768 if (strcmp (name, "setup") && !num ) {
3769 r_cons_eprintf ("syscall not found!\n");
3770 return 0;
3771 }
3772 break;
3773 case 64:
3774 if (strcmp (name, "read") && !num ) {
3775 r_cons_eprintf ("syscall not found!\n");
3776 return 0;
3777 }
3778 break;
3779 default:
3780 r_cons_eprintf ("syscall not found!\n");
3781 return 0;
3782 }
3783
3784 snprintf (code, sizeof (code),
3785 "sc@syscall(%d);\n"
3786 "main@global(0) { sc(%s);\n"
3787 ":int3\n" /// XXX USE trap
3788 "}\n", num, args);
3789 r_egg_reset (core->egg);
3790 // TODO: setup arch/bits/os?
3791 r_egg_load (core->egg, code, 0);
3792
3793 if (!r_egg_compile (core->egg)) {
3794 r_cons_eprintf ("Cannot compile.\n");
3795 }
3796 if (!r_egg_assemble (core->egg)) {
3797 r_cons_eprintf ("r_egg_assemble: invalid assembly\n");
3798 }
3799 if ((b = r_egg_get_bin (core->egg))) {
3800 #if 0
3801 if (b->length > 0) {
3802 for (i = 0; i < b->length; i++) {
3803 r_cons_printf ("%02x", b->buf[i]);
3804 }
3805 r_cons_printf ("\n");
3806 }
3807 #endif
3808 }
3809 return b;
3810 }
3811
r_core_autocomplete_add(RCoreAutocomplete * parent,const char * cmd,int type,bool lock)3812 R_API RCoreAutocomplete *r_core_autocomplete_add(RCoreAutocomplete *parent, const char* cmd, int type, bool lock) {
3813 if (!parent || !cmd || type < 0 || type >= R_CORE_AUTOCMPLT_END) {
3814 return NULL;
3815 }
3816 RCoreAutocomplete *autocmpl = R_NEW0 (RCoreAutocomplete);
3817 if (!autocmpl) {
3818 return NULL;
3819 }
3820 RCoreAutocomplete **updated = realloc (parent->subcmds, (parent->n_subcmds + 1) * sizeof (RCoreAutocomplete*));
3821 if (!updated) {
3822 free (autocmpl);
3823 return NULL;
3824 }
3825 parent->subcmds = updated;
3826 parent->subcmds[parent->n_subcmds] = autocmpl;
3827 parent->n_subcmds++;
3828 autocmpl->cmd = strdup (cmd);
3829 autocmpl->locked = lock;
3830 autocmpl->type = type;
3831 autocmpl->length = strlen (cmd);
3832 return autocmpl;
3833 }
3834
r_core_autocomplete_free(RCoreAutocomplete * obj)3835 R_API void r_core_autocomplete_free(RCoreAutocomplete *obj) {
3836 if (!obj) {
3837 return;
3838 }
3839 int i;
3840 for (i = 0; i < obj->n_subcmds; i++) {
3841 r_core_autocomplete_free (obj->subcmds[i]);
3842 obj->subcmds[i] = NULL;
3843 }
3844 free (obj->subcmds);
3845 free ((char*) obj->cmd);
3846 free (obj);
3847 }
3848
r_core_autocomplete_find(RCoreAutocomplete * parent,const char * cmd,bool exact)3849 R_API RCoreAutocomplete *r_core_autocomplete_find(RCoreAutocomplete *parent, const char* cmd, bool exact) {
3850 if (!parent || !cmd) {
3851 return false;
3852 }
3853 int len = strlen (cmd);
3854 int i;
3855 for (i = 0; i < parent->n_subcmds; i++) {
3856 if (exact && len == parent->subcmds[i]->length && !strncmp (cmd, parent->subcmds[i]->cmd, len)) {
3857 return parent->subcmds[i];
3858 } else if (!exact && !strncmp (cmd, parent->subcmds[i]->cmd, len)) {
3859 return parent->subcmds[i];
3860 }
3861 }
3862 return NULL;
3863 }
3864
r_core_autocomplete_remove(RCoreAutocomplete * parent,const char * cmd)3865 R_API bool r_core_autocomplete_remove(RCoreAutocomplete *parent, const char* cmd) {
3866 if (!parent || !cmd) {
3867 return false;
3868 }
3869 int i, j;
3870 for (i = 0; i < parent->n_subcmds; i++) {
3871 RCoreAutocomplete *ac = parent->subcmds[i];
3872 if (ac->locked) {
3873 continue;
3874 }
3875 // if (!strncmp (parent->subcmds[i]->cmd, cmd, parent->subcmds[i]->length)) {
3876 if (r_str_glob (ac->cmd, cmd)) {
3877 for (j = i + 1; j < parent->n_subcmds; j++) {
3878 parent->subcmds[j - 1] = parent->subcmds[j];
3879 parent->subcmds[j] = NULL;
3880 }
3881 r_core_autocomplete_free (ac);
3882 RCoreAutocomplete **updated = realloc (parent->subcmds, (parent->n_subcmds - 1) * sizeof (RCoreAutocomplete*));
3883 if (!updated && (parent->n_subcmds - 1) > 0) {
3884 r_cons_eprintf ("Something really bad has happen.. this should never ever happen..\n");
3885 return false;
3886 }
3887 parent->subcmds = updated;
3888 parent->n_subcmds--;
3889 i--;
3890 }
3891 }
3892 return false;
3893 }
3894
r_core_table(RCore * core,const char * name)3895 R_API RTable *r_core_table(RCore *core, const char *name) {
3896 RTable *table = r_table_new (R_STR_ISEMPTY (name)? "table": name);
3897 if (table) {
3898 table->cons = core->cons;
3899 }
3900 return table;
3901 }
3902
3903 /* Config helper function for PJ json encodings */
r_core_pj_new(RCore * core)3904 R_API PJ *r_core_pj_new(RCore *core) {
3905 const char *config_string_encoding = r_config_get (core->config, "cfg.json.str");
3906 const char *config_num_encoding = r_config_get (core->config, "cfg.json.num");
3907 PJEncodingNum number_encoding = PJ_ENCODING_NUM_DEFAULT;
3908 PJEncodingStr string_encoding = PJ_ENCODING_STR_DEFAULT;
3909
3910 if (!strcmp ("string", config_num_encoding)) {
3911 number_encoding = PJ_ENCODING_NUM_STR;
3912 } else if (!strcmp ("hex", config_num_encoding)) {
3913 number_encoding = PJ_ENCODING_NUM_HEX;
3914 }
3915
3916 if (!strcmp ("base64", config_string_encoding)) {
3917 string_encoding = PJ_ENCODING_STR_BASE64;
3918 } else if (!strcmp ("hex", config_string_encoding)) {
3919 string_encoding = PJ_ENCODING_STR_HEX;
3920 } else if (!strcmp ("array", config_string_encoding)) {
3921 string_encoding = PJ_ENCODING_STR_ARRAY;
3922 } else if (!strcmp ("strip", config_string_encoding)) {
3923 string_encoding = PJ_ENCODING_STR_STRIP;
3924 }
3925
3926 return pj_new_with_encoding (string_encoding, number_encoding);
3927 }
3928