Example #1
0
static int bin_dwarf(RCore *core, int mode) {
	RBinDwarfRow *row;
	RListIter *iter;
	RList *list = NULL;
	RBinFile *binfile = r_core_bin_cur (core);
	RBinPlugin * plugin = r_bin_file_cur_plugin (binfile);
	if (!binfile) return false;

	if (plugin && plugin->lines) {
		list = plugin->lines (binfile);
	} else if (core->bin) {
		// TODO: complete and speed-up support for dwarf
		if (r_config_get_i (core->config, "bin.dwarf")) {
			RBinDwarfDebugAbbrev *da = NULL;
			da = r_bin_dwarf_parse_abbrev (core->bin, mode);
			r_bin_dwarf_parse_info (da, core->bin, mode);
			r_bin_dwarf_parse_aranges (core->bin, mode);
			list = r_bin_dwarf_parse_line (core->bin, mode);
			r_bin_dwarf_free_debug_abbrev (da);
			free (da);
		}
	}
	if (!list) return false;
	r_cons_break (NULL, NULL);
        r_list_foreach (list, iter, row) {
		if (r_cons_singleton()->breaked) break;
		if (mode) {
			// TODO: use 'Cl' instead of CC
			const char *path = row->file;
			char *line = r_file_slurp_line (path, row->line-1, 0);
			if (line) {
				r_str_filter (line, strlen (line));
				line = r_str_replace (line, "\"", "\\\"", 1);
				line = r_str_replace (line, "\\\\", "\\", 1);
			}
			// TODO: implement internal : if ((mode & R_CORE_BIN_SET))
			if ((mode & R_CORE_BIN_SET)) {
				char *cmt = r_str_newf ("%s:%d  %s", row->file, row->line, line?line:"");
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
						row->address, cmt);
				free (cmt);
			} else {
				r_cons_printf ("\"CC %s:%d  %s\"@0x%"PFMT64x"\n",
					row->file, row->line, line?line:"", row->address);
			}
			free (line);
		} else {
			r_cons_printf ("0x%08"PFMT64x"\t%s\t%d\n", row->address, row->file, row->line);
		}
        }
	r_cons_break_end ();
	r_list_free (list);
	return true;
}
Example #2
0
void gb_bankswitch_detect(RMeta *m, RIOBind iob, ut64 addr, ut16 ldarg) {
	ut8 rt;
	if(addr > 0x3fff)
		return;
	iob.read_at(iob.io, 0x147, &rt, 1);									//xxx: it won't change
	switch(gb_mbc_resolve(rt)) {
		case -1:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "unknown MBC!!!");
		case 0:
			return;
		default:
			meta_gb_bankswitch_cmt(m, addr, ldarg, (ut8)gb_mbc_resolve(rt));
	}
}
Example #3
0
static int cmd_meta_hsdmf (RCore *core, const char *input) {
	int n, type = input[0];
	char *t = 0, *p, name[256];
	ut64 addr_end = 0LL, addr = core->offset;

	switch (input[1]) {
	case '?':
		eprintf ("See C?\n");
		break;
	case '-':
		switch (input[2]) {
			case '*':
				core->num->value = r_meta_del (core->anal,
						input[0], 0, UT64_MAX, NULL);
				break;
			case ' ':
				addr = r_num_math (core->num, input+3);
			default:
				core->num->value = r_meta_del (core->anal,
						input[0], addr, 1, NULL);
				break;
		}
		break;
	case '*':
		r_meta_list (core->anal, input[0], 1);
		break;
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal,
						R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case ' ':
	case '\0':
		if (type!='z' && !input[1]) {
			r_meta_list (core->anal, type, 0);
			break;
		}
		t = strdup (input+2);
		p = NULL;
		n = 0;
		strncpy (name, t, sizeof (name)-1);
		if (*input != 'C') {
			n = r_num_math (core->num, t);
			if (type == 'f') {
				p = strchr (t, ' ');
				if (p)
					n = r_print_format (core->print, addr, core->block,
							core->blocksize, p+1, -1, NULL, NULL);
			}
			if (type == 's') {
				/* This is kept for compatibility with old projects.
				 * Somewhat broken, but project will get corrected on
				 * save and reload.
				 */
				p = strchr (t, ' ');
				if (p)
					addr = r_num_math (core->num, p+1);
			}
			if (!*t || n>0) {
				RFlagItem *fi;
				p = strchr (t, ' ');
				if (p) {
					*p = '\0';
					strncpy (name, p+1, sizeof (name)-1);
				} else
					switch (type) {
					case 'z':
						type='s';
					case 's':
						// TODO: filter \n and so on :)
						strncpy (name, t, sizeof (name)-1);
						name[sizeof (name)-1] = '\0';
						r_core_read_at (core, addr, (ut8*)name, sizeof (name)-1);
						if (n < sizeof(name))
							name[n] = '\0';
						else name[sizeof (name)-1] = '\0';
						break;
					default:
						fi = r_flag_get_i (core->flags, addr);
						if (fi) strncpy (name, fi->name, sizeof (name)-1);
					}
			} else if (n<1) {
				eprintf ("Invalid length %d\n", n);
				return R_FALSE;
			}
		}
		if (!n) n++;
		addr_end = addr + n;
		r_meta_add (core->anal, type, addr, addr_end, name);
		free (t);
		//r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX);
		break;
	default:
		eprintf ("Missing space after CC\n");
		break;
	}

	return R_TRUE;
}
Example #4
0
static int cmd_meta_comment(RCore *core, const char *input) {
	ut64 addr = core->offset;
	switch (input[1]) {
	case '?': {
		const char* help_msg[] = {
			"Usage:", "CC[-+!*au] [base64:..|str] @ addr", "",
			"CC", "", "list all comments in human friednly form",
			"CC*", "", "list all comments in r2 commands",
			"CC.", "", "show comment at current offset",
			"CC", " or maybe not", "append comment at current address",
			"CC+", " same as above", "append comment at current address",
			"CC!", "", "edit comment using cfg.editor (vim, ..)",
			"CC-", " @ cmt_addr", "remove comment at given address",
			"CCu", " good boy @ addr", "add good boy comment at given address",
			"CCu", " base64:AA== @ addr", "add comment in base64",
			NULL};
		r_core_cmd_help (core, help_msg);
		} break;
	case '.':
		  {
			  char *comment = r_meta_get_string (
					  core->anal, R_META_TYPE_COMMENT, addr);
			  if (comment) {
				  r_cons_printf ("%s\n", comment);
				  free (comment);
			  }
		  }
		break;
	case 0:
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 0);
		break;
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal,
						R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case '+':
	case ' ':
		{
		const char* newcomment = input+2;
		char *text, *nc;
		while (*newcomment==' ') newcomment++;
		char *comment = r_meta_get_string (
				core->anal, R_META_TYPE_COMMENT, addr);
		nc = strdup (newcomment);
		r_str_unescape (nc);
		if (comment) {
			text = malloc (strlen (comment)+strlen (newcomment)+2);
			strcpy (text, comment);
			strcat (text, "\n");
			strcat (text, nc);
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, text);
			free (text);
		} else {
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, nc);
		}
		free (nc);
		}
		break;
	case '*':
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 1);
		break;
	case '-':
		r_meta_del (core->anal, R_META_TYPE_COMMENT, core->offset, 1, NULL);
		break;
	case 'u':
		//
		{
		char *newcomment;
		const char *arg = input+2;
		while (*arg && *arg == ' ') arg++;
		if (!strncmp (arg, "base64:", 7)) {
			char *s = (char *)sdb_decode (arg+7, NULL);
			if (s) {
				newcomment = s;
			} else {
				newcomment = NULL;
			}
		} else {
			newcomment = strdup (arg);
		}
		if (newcomment) {
			char *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			if (!comment || (comment && !strstr (comment, newcomment))) {
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
						addr, newcomment);
			}
			free (comment);
			free (newcomment);
		}
		}
		break;
	case 'a':
		{
		char *s, *p;
		s = strchr (input, ' ');
		if (s) {
			s = strdup (s+1);
		} else {
			eprintf ("Usage\n");
			return R_FALSE;
		}
		p = strchr (s, ' ');
		if (p) *p++ = 0;
		ut64 addr;
		if (input[2]=='-') {
			if (input[3]) {
				addr = r_num_math (core->num, input+3);
				r_meta_del (core->anal,
						R_META_TYPE_COMMENT,
						addr, 1, NULL);
			} else eprintf ("Usage: CCa-[address]\n");
			free (s);
			return R_TRUE;
		}
		addr = r_num_math (core->num, s);
		// Comment at
		if (p) {
			if (input[2]=='+') {
				char *text = p;
				char *comment = r_meta_get_string (
						core->anal, R_META_TYPE_COMMENT,
						addr);
				if (comment) {
					text = malloc (strlen (comment) + strlen (p)+2);
					strcpy (text, comment);
					strcat (text, "\n");
					strcat (text, p);
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, text);
					free (text);
				} else {
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, p);
				}
			} else {
				r_meta_add (core->anal,
						R_META_TYPE_COMMENT,
						addr, addr+1, p);
			}
		} else eprintf ("Usage: CCa [address] [comment]\n");
		free (s);
		return R_TRUE;
		}
	}

	return R_TRUE;
}
Example #5
0
static int cmd_meta_comment(RCore *core, const char *input) {
	ut64 addr = core->offset;
	if (input[1] == '+' || input[1] == ' ') {
		const char* newcomment = input+2;
		char *text;
		while (*newcomment==' ') newcomment++;
		char *comment = r_meta_get_string (
				core->anal, R_META_TYPE_COMMENT, addr);
		if (comment) {
			text = malloc (strlen (comment)+strlen (newcomment)+2);
			strcpy (text, comment);
			strcat (text, "\n");
			strcat (text, newcomment);
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, text);
			free (text);
		} else {
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, newcomment);
		}
		return R_TRUE;
	} else if (input[1] == 'a') {
		char *s, *p;
		s = strchr (input, ' ');
		if (s) {
			s = strdup (s+1);
		} else {
			eprintf ("Usage\n");
			return R_FALSE;
		}
		p = strchr (s, ' ');
		if (p) *p++ = 0;
		ut64 addr;
		if (input[2]=='-') {
			if (input[3]) {
				addr = r_num_math (core->num, input+3);
				r_meta_del (core->anal,
						R_META_TYPE_COMMENT,
						addr, 1, NULL);
			} else eprintf ("Usage: CCa-[address]\n");
			free (s);
			return R_TRUE;
		}
		addr = r_num_math (core->num, s);
		// Comment at
		if (p) {
			if (input[2]=='+') {
				char *text = p;
				char *comment = r_meta_get_string (
						core->anal, R_META_TYPE_COMMENT,
						addr);
				if (comment) {
					text = malloc (strlen (comment) + strlen (p)+2);
					strcpy (text, comment);
					strcat (text, "\n");
					strcat (text, p);
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, text);
					free (text);
				} else {
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, p);
				}
			} else {
				r_meta_add (core->anal,
						R_META_TYPE_COMMENT,
						addr, addr+1, p);
			}
		} else eprintf ("Usage: CCa [address] [comment]\n");
		free (s);
		return R_TRUE;
	} else if (input[1] == '*') {
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 1);
	} else if (input[1] == '-') {
		r_meta_del (core->anal, R_META_TYPE_COMMENT, core->offset, 1, NULL);
	}

	return R_TRUE;
}
Example #6
0
void meta_gb_bankswitch_cmt(RMeta *m, ut64 addr, ut16 ldarg, ut8 rmbc) {
	if(rmbc>4)												//todo
		return;
	if(mbc[rmbc-1].from<ldarg && ldarg<mbc[rmbc-1].to)
		r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "Bankswitch");
}
Example #7
0
void meta_gb_hardware_cmt(RMeta *m, const ut8 hw, ut64 addr) {
	switch(hw)
	{
		case 0:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "JOYPAD");				//Moar context for this (which Key is affected)
			break;
		case 1:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "Serial tranfer data");
			break;
		case 2:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "Serial tranfer data - Ctl");
			break;
		case 4:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "DIV");
			break;
		case 5:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "TIMA");
			break;
		case 6:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "TMA");
			break;
		case 7:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "TAC");
			break;
		case 0x0f:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "Interrupt Flag");			//TODO: save in sdb for halt
			break;
		case 0x10:
		case 0x11:
		case 0x12:
		case 0x13:
		case 0x14:
		case 0x16:
		case 0x17:
		case 0x18:
		case 0x19:
		case 0x1a:
		case 0x1b:
		case 0x1c:
		case 0x1d:
		case 0x1e:
		case 0x20:
		case 0x21:
		case 0x22:
		case 0x23:
		case 0x24:
		case 0x25:
		case 0x26:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "SOUND");
			break;
		case 0x30:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "Wave Pattern RAM/SOUND");
			break;
		case 0x40:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC");
			break;
		case 0x41:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC - STAT");
			break;
		case 0x42:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC - Scroll y");
			break;
		case 0x43:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC - Scroll x");
			break;
		case 0x44:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC - y cord");
			break;
		case 0x45:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "LCDC - y cord cmp");
			break;
		case 0x46:
			r_meta_set_string(m, R_META_TYPE_COMMENT, addr, "DMA");
			break;

	}
}
Example #8
0
static int cmd_meta_comment(RCore *core, const char *input) {
	ut64 addr = core->offset;
	switch (input[1]) {
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal,
						R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case '+':
	case ' ':
		{
		const char* newcomment = input+2;
		char *text;
		while (*newcomment==' ') newcomment++;
		char *comment = r_meta_get_string (
				core->anal, R_META_TYPE_COMMENT, addr);
		if (comment) {
			text = malloc (strlen (comment)+strlen (newcomment)+2);
			strcpy (text, comment);
			strcat (text, "\n");
			strcat (text, newcomment);
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, text);
			free (text);
		} else {
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, newcomment);
		}
		}
		break;
	case '*':
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 1);
		break;
	case '-':
		r_meta_del (core->anal, R_META_TYPE_COMMENT, core->offset, 1, NULL);
		break;
	case 'u':
		//
		{
		const char* newcomment = input+2;
		while (*newcomment==' ') newcomment++;
		char *comment = r_meta_get_string (
				core->anal, R_META_TYPE_COMMENT, addr);
		if (!comment || (comment && !strstr (comment, newcomment))) {
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
					addr, newcomment);
		}
		free (comment);
		}
		break;
	case 'a':
		{
		char *s, *p;
		s = strchr (input, ' ');
		if (s) {
			s = strdup (s+1);
		} else {
			eprintf ("Usage\n");
			return R_FALSE;
		}
		p = strchr (s, ' ');
		if (p) *p++ = 0;
		ut64 addr;
		if (input[2]=='-') {
			if (input[3]) {
				addr = r_num_math (core->num, input+3);
				r_meta_del (core->anal,
						R_META_TYPE_COMMENT,
						addr, 1, NULL);
			} else eprintf ("Usage: CCa-[address]\n");
			free (s);
			return R_TRUE;
		}
		addr = r_num_math (core->num, s);
		// Comment at
		if (p) {
			if (input[2]=='+') {
				char *text = p;
				char *comment = r_meta_get_string (
						core->anal, R_META_TYPE_COMMENT,
						addr);
				if (comment) {
					text = malloc (strlen (comment) + strlen (p)+2);
					strcpy (text, comment);
					strcat (text, "\n");
					strcat (text, p);
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, text);
					free (text);
				} else {
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, p);
				}
			} else {
				r_meta_add (core->anal,
						R_META_TYPE_COMMENT,
						addr, addr+1, p);
			}
		} else eprintf ("Usage: CCa [address] [comment]\n");
		free (s);
		return R_TRUE;
		}
	}

	return R_TRUE;
}
Example #9
0
void meta_gb_bankswitch_cmt(RAnal *a, ut64 addr, ut16 ldarg) {
	if(0x1fff <ldarg && ldarg < 0x4000 && addr < 0x4000)
		r_meta_set_string (a, R_META_TYPE_COMMENT, addr, "Bankswitch");
	if(0x6000 > ldarg && ldarg > 0x3fff)
		r_meta_set_string(a, R_META_TYPE_COMMENT, addr, "Ramswitch");
}
Example #10
0
static int ws_anal(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
	RAsmOp *aop;
	memset (op, '\0', sizeof(RAnalOp));
	op->addr = addr;
	op->type = R_ANAL_OP_TYPE_UNK;
	aop = R_NEW0(RAsmOp);
	op->size = wsdis(aop, data, len);
	if(op->size) {
		switch(aop->buf_asm[0]) {
			case 'n':
				op->type = R_ANAL_OP_TYPE_NOP;
				break;
			case 'e':
				op->type = R_ANAL_OP_TYPE_TRAP;
				break;
			case 'd':
				if(aop->buf_asm[1] == 'u')
					op->type = R_ANAL_OP_TYPE_UPUSH;
				else
					op->type = R_ANAL_OP_TYPE_DIV;
				break;
			case 'i':
				op->type = R_ANAL_OP_TYPE_ILL;
				break;
			case 'a':
				op->type = R_ANAL_OP_TYPE_ADD;
				break;
			case 'm':
				if(aop->buf_asm[1] == 'o')
					op->type = R_ANAL_OP_TYPE_MOD;
				else
					op->type = R_ANAL_OP_TYPE_MUL;
				break;
			case 'r':
				op->type = R_ANAL_OP_TYPE_RET;
				break;
			case 'l':
				op->type = R_ANAL_OP_TYPE_LOAD;
				break;
			case 'c':
				if(aop->buf_asm[1] == 'a') {
					op->type = R_ANAL_OP_TYPE_CALL;
					op->fail = addr + aop->size;
					op->jump = ws_find_label(atoi(&aop->buf_asm[5]), anal->iob);
				} else {
					op->type = R_ANAL_OP_TYPE_UPUSH;
				}
				break;
			case 'j':
				if(aop->buf_asm[1] == 'm') {
					op->type = R_ANAL_OP_TYPE_JMP;
					op->jump = ws_find_label(atoi(&aop->buf_asm[4]), anal->iob);
				} else {
					op->type = R_ANAL_OP_TYPE_CJMP;
					op->jump = ws_find_label(atoi(&aop->buf_asm[3]), anal->iob);
				}
				op->fail = addr + aop->size;
				break;
			case 'g':
				op->type = R_ANAL_OP_TYPE_IO;
				break;
			case 'p':
				if(aop->buf_asm[1] == 'o') {
					op->type = R_ANAL_OP_TYPE_POP;
				} else {
					if(aop->buf_asm[2] == 's') {
						op->type = R_ANAL_OP_TYPE_PUSH;
						if(127 > atoi(&aop->buf_asm[5])
						&& atoi(&aop->buf_asm[5]) >= 33) {
							char c[4];
							c[3] = '\0';
							c[0] = c[2] = '\'';
							c[1] = (char) atoi(&aop->buf_asm[5]);
							r_meta_set_string(anal, R_META_TYPE_COMMENT, addr, c);
						}
					} else {
						op->type = R_ANAL_OP_TYPE_IO;
					}
				}
				break;
			case 's':
				switch (aop->buf_asm[1]) {
					case 'u':
						op->type = R_ANAL_OP_TYPE_SUB;
						break;
					case 't':
						op->type = R_ANAL_OP_TYPE_STORE;
						break;
					case 'l':
						op->type = R_ANAL_OP_TYPE_LOAD;			// XXX
						break;
					case 'w':
						op->type = R_ANAL_OP_TYPE_ROR;
				}
				break;
		}
	}
	r_asm_op_free(aop);
	return op->size;
}
Example #11
0
static void type_match(RCore *core, ut64 addr, char *name) {
	Sdb *trace = core->anal->esil->db_trace;
	RAnal *anal = core->anal;
	RAnalVar *v;
	char *fcn_name;
	if (r_anal_type_func_exist (anal, name)) {
		fcn_name = strdup (name);
	} else if (!(fcn_name = r_anal_type_func_guess (anal, name))) {
		eprintf ("can't find function prototype for %s\n", name);
		return;
	}
	const char* cc = r_anal_type_func_cc (anal, fcn_name);
	if (!cc || !r_anal_cc_exist (anal, cc)) {
		eprintf ("can't find %s calling convention %s\n", fcn_name, cc);
		return;
	}
	int i, j, max = r_anal_type_func_args_count (anal, fcn_name);
	int size = 0, idx = sdb_num_get (trace, "idx", 0);
	const char *sp_name = r_reg_get_name (anal->reg, R_REG_NAME_SP);
	const char *bp_name = r_reg_get_name (anal->reg, R_REG_NAME_BP);
	ut64 sp = r_reg_getv (anal->reg, sp_name);
	ut64 bp = r_reg_getv (anal->reg, bp_name);
	for (i = 0; i < max; i++) {
		char *type = r_anal_type_func_args_type (anal, fcn_name, i);
		const char *name =r_anal_type_func_args_name (anal, fcn_name, i);
		const char *place = r_anal_cc_arg (anal, cc, i + 1);
		if (!strcmp (place, "stack")) {
			// type_match_stack ();
			for (j = idx; j >= 0; j--) {
				ut64 write_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.mem.write", j), 0);
				if (write_addr == sp + size) {
					ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0);
					r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr,
						sdb_fmt (-1, "%s %s", type, name));
					char *tmp = sdb_fmt (-1, "%d.mem.read", j);
					int i2, array_size = sdb_array_size (trace, tmp);
					for (i2 = 0; i2 < array_size; i2++) {
						if (bp_name) {
							int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp;
							if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) {
								r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name);
								r_anal_var_free (v);
							}
						}
						int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp;
						if ((v = r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) {
							r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name);
							r_anal_var_free (v);
						}
					}
					break;
				}
			}
			size += r_anal_type_get_size (anal, type) / 8;
		} else if (!strcmp (place , "stack_rev")) {
			// type_match_stack_rev ();
			free (type);
			int k;
			for ( k = max -1; k >=i; k--) {
				type = r_anal_type_func_args_type (anal, fcn_name, k);
				name =r_anal_type_func_args_name (anal, fcn_name, k);
				place = r_anal_cc_arg (anal, cc, k + 1);
				if (strcmp (place ,"stack_rev")) {
					break;
				}
				for (j = idx; j >= 0; j--) {
					ut64 write_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.mem.write", j), 0);
					if (write_addr == sp + size) {
						ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0);
						r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr,
							sdb_fmt (-1, "%s %s", type, name));
						char *tmp = sdb_fmt (-1, "%d.mem.read", j);
						int i2, array_size = sdb_array_size (trace, tmp);
						for (i2 = 0; i2 < array_size; i2++) {
							if (bp_name) {
								int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp;
								if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) {
									r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name);
									r_anal_var_free (v);
								}
							}
							int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp;
							if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) {
								r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name);
								r_anal_var_free (v);
							}
						}
						break;
					}

				}
				size += r_anal_type_get_size (anal, type) / 8;
			}
			break;
		} else {
			// type_match_reg ();
			for (j = idx; j >= 0; j--) {
				if (sdb_array_contains (trace, sdb_fmt (-1, "%d.reg.write", j), place, 0)) {
					ut64 instr_addr = sdb_num_get (trace, sdb_fmt (-1, "%d.addr", j), 0);
					r_meta_set_string (core->anal, R_META_TYPE_COMMENT, instr_addr,
						sdb_fmt (-1, "%s %s", type, name));
					char *tmp = sdb_fmt (-1, "%d.mem.read", j);
					int i2, array_size = sdb_array_size (trace, tmp);
					for (i2 = 0; i2 < array_size; i2++) {
						if (bp_name) {
							int bp_idx = sdb_array_get_num (trace, tmp, i2, 0) - bp;
							if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_BPV, 1, bp_idx))) {
								r_anal_var_retype (anal, addr, 1, bp_idx, R_ANAL_VAR_KIND_BPV, type, -1, v->name);
								r_anal_var_free (v);
							}
						}
						int sp_idx = sdb_array_get_num (trace, tmp, i2, 0) - sp;
						if ((v =r_anal_var_get (anal, addr, R_ANAL_VAR_KIND_SPV, 1, sp_idx))) {
							r_anal_var_retype (anal, addr, 1, sp_idx, R_ANAL_VAR_KIND_SPV, type, -1, v->name);
							r_anal_var_free (v);
						}
					}
					break;
				}
			}
		}
		free (type);
	}
	free (fcn_name);
}
Example #12
0
static int cmd_meta_hsdmf(RCore *core, const char *input) {
	int n, type = input[0];
	char *t = 0, *p, name[256];
	int repeat = 1;
	ut64 addr_end = 0LL, addr = core->offset;

	switch (input[1]) {
	case '?':
		eprintf ("See C?\n");
		break;
	case '-':
		switch (input[2]) {
		case '*':
			core->num->value = r_meta_del (core->anal,
					input[0], 0, UT64_MAX, NULL);
			break;
		case ' ':
			addr = r_num_math (core->num, input+3);
			/* fallthrough */
		default:
			core->num->value = r_meta_del (core->anal,
					input[0], addr, 1, NULL);
			break;
		}
		break;
	case '*':
		r_meta_list (core->anal, input[0], 1);
		break;
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case ' ':
	case '\0':
		if (type!='z' && input[1] == '*') {
			r_meta_list (core->anal, type, 0);
			break;
		}
		if (type == 'z') {
			type = 's';
		}
		if (strlen (input) > 2) {
			char *rep = strchr (input + 2, '[');
			if (!rep) rep = strchr (input + 2, ' ');
			if (rep) {
				repeat = r_num_get (core->num, rep + 1);
			}
		}
		int repcnt = 0;
		if (repeat < 1) repeat = 1;
		while (repcnt < repeat) {
			t = strdup (r_str_chop_ro (input + 1));
			p = NULL;
			n = 0;
			strncpy (name, t, sizeof (name) - 1);
			if (type != 'C') {
				n = r_num_math (core->num, t);
				if (type == 'f') {
					p = strchr (t, ' ');
					if (p) {
						n = r_print_format (core->print, addr, core->block,
							core->blocksize, p + 1, 0, NULL, NULL);
					}
				}
				if (type == 's') {
					strncpy (name, t, sizeof (name) - 1);
					(void)r_core_read_at (core, addr, (ut8*)name, sizeof (name) - 1);
					name[sizeof (name) - 1] = '\0';
					int name_len = strlen (name);
					if (n == 0) {
						n = name_len + 1;
					} else {
						if (n > 0 && n < name_len) {
							name[n] = 0;
						}
					}
				}
				if (!*t || n > 0) {
					RFlagItem *fi;
					p = strchr (t, ' ');
					if (p) {
						*p = '\0';
						strncpy (name, p + 1, sizeof (name)-1);
					} else {
						if (type != 's') {
							fi = r_flag_get_i (core->flags, addr);
							if (fi) strncpy (name, fi->name, sizeof (name)-1);
						}
					}
				} else if (n < 1) {
					eprintf ("Invalid length %d\n", n);
					return false;
				}
			}
			if (!n) n++;
			addr_end = addr + n;
			r_meta_add (core->anal, type, addr, addr_end, name);
			free (t);
			repcnt ++;
			addr = addr_end;
		}
		//r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX);
		break;
	default:
		eprintf ("Missing space after CC\n");
		break;
	}

	return true;
}
Example #13
0
static int cmd_eval(void *data, const char *input) {
	char *p;
	RCore *core = (RCore *)data;
	switch (input[0]) {
	case 't': // env
		if (input[1] == 'a') {
			r_cons_printf ("%s\n", (r_num_rand (10) % 2)? "wen": "son");
		} else if (input[1]==' ' && input[2]) {
			RConfigNode *node = r_config_node_get (core->config, input+2);
			if (node) {
				const char *type = r_config_node_type (node);
				if (type && *type) {
					r_cons_println (type);
				}
			}
		} else {
			eprintf ("Usage: et [varname]  ; show type of eval var\n");
		}
		break;
	case 'n': // env
		if (!strchr (input, '=')) {
			char *var, *p;
			var = strchr (input, ' ');
			if (var) while (*var==' ') var++;
			p = r_sys_getenv (var);
			if (p) {
				r_cons_println (p);
				free (p);
			} else {
				char **e = r_sys_get_environ ();
				while (e && *e) {
					r_cons_println (*e);
					e++;
				}
			}
		} else if (strlen (input)>3) {
			char *v, *k = strdup (input+3);
			if (!k) break;
			v = strchr (k, '=');
			if (v) {
				*v++ = 0;
				r_sys_setenv (k, v);
			}
			free (k);
		}
		return true;
	case 'x': // exit
		// XXX we need headers for the cmd_xxx files.
		return cmd_quit (data, "");
	case 'j': // json
		r_config_list (core->config, NULL, 'j');
		break;
	case 'v': // verbose
		r_config_list (core->config, input + 1, 'v');
		break;
	case 'q': // quiet list of eval keys
		r_config_list (core->config, NULL, 'q');
		break;
	case '\0': // "e"
		r_config_list (core->config, NULL, 0);
		break;
	case 'c': // "ec"
		switch (input[1]) {
		case 'd':
			r_cons_pal_init (NULL);
			break;
		case '?': {
			const char *helpmsg[] = {
			"Usage ec[s?] [key][[=| ]fg] [bg]","","",
			"ec","","list all color keys",
			"ec*","","same as above, but using r2 commands",
			"ecd","","set default palette",
			"ecr","","set random palette (see also scr.randpal)",
			"ecs","","show a colorful palette",
			"ecj","","show palette in JSON",
			"ecc"," [prefix]","show palette in CSS",
			"eco"," dark|white","load white color scheme template",
			"ecp","","load previous color theme",
			"ecn","","load next color theme",
			"ecH","[?]","highlight word or instruction",
			"ec"," prompt red","change color of prompt",
			"ec"," prompt red blue","change color and background of prompt",
			""," ","",
			"colors:","","rgb:000, red, green, blue, ...",
			"e scr.rgbcolor","=1|0","for 256 color cube (boolean)",
			"e scr.truecolor","=1|0","for 256*256*256 colors (boolean)",
			"$DATADIR/radare2/cons","","~/.config/radare2/cons ./",
			NULL};
			r_core_cmd_help (core, helpmsg);
			}
			break;
		case 'o': // "eco"
			if (input[2] == 'j') {
				nextpal (core, 'j');
			} else if (input[2] == ' ') {
				bool failed = false;
				char *home, path[512];
				snprintf (path, sizeof (path), ".config/radare2/cons/%s", input + 3);
				home = r_str_home (path);
				snprintf (path, sizeof (path), R2_DATDIR"/radare2/"
					R2_VERSION"/cons/%s", input + 3);
				if (!load_theme (core, home)) {
					if (load_theme (core, path)) {
						//curtheme = r_str_dup (curtheme, path);
						curtheme = r_str_dup (curtheme, input + 3);
					} else {
						if (load_theme (core, input + 3)) {
							curtheme = r_str_dup (curtheme, input + 3);
						} else {
							char *absfile = r_file_abspath (input + 3);
							eprintf ("eco: cannot open colorscheme profile (%s)\n", absfile);
							free (absfile);
							failed = true;
						}
					}
				}
				free (home);
				if (failed) {
					eprintf ("Something went wrong\n");
				}
			} else if (input[2] == '?') {
				eprintf ("Usage: eco [themename]  ;load theme from "R2_DATDIR"/radare2/"R2_VERSION"/cons/\n");

			} else {
				nextpal (core, 'l');
			}
			break;
		case 's': r_cons_pal_show (); break; // "ecs"
		case '*': r_cons_pal_list (1, NULL); break; // "ec*"
		case 'h': // echo
			if (( p = strchr (input, ' ') )) {
				r_cons_strcat (p+1);
				r_cons_newline ();
			} else {
				// "ech"
				r_cons_pal_list ('h', NULL);
			}
			break;
		case 'j': // "ecj"
			r_cons_pal_list ('j', NULL);
			break;
		case 'c': // "ecc"
			r_cons_pal_list ('c', input + 2);
			break;
		case '\0': // "ec"
			r_cons_pal_list (0, NULL);
			break;
		case 'r': // "ecr"
			r_cons_pal_random ();
			break;
		case 'n': // "ecn"
			nextpal (core, 'n');
			break;
		case 'p': // "ecp"
			nextpal (core, 'p');
			break;
		case 'H': { // "ecH"
			char *color_code = NULL;
			char *word = NULL;
			int argc = 0;
			char** argv = r_str_argv (input + 4, &argc);
			switch (input[2]) {
			case '?': {
				const char *helpmsg[] = {
					"Usage ecH[iw-?]","","",
					"ecHi","[color]","highlight current instruction with 'color' background",
					"ecHw","[word] [color]","highlight 'word ' in current instruction with 'color' background",
					"ecH-","","remove all highlights on current instruction",
					NULL
				};
				r_core_cmd_help (core, helpmsg);
				}
				break;
			case '-':
				r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, "");
				return false;
			case '\0':
			case 'i': // "ecHi
				if (argc) {
					char *dup = r_str_newf ("bgonly %s", argv[0]);
					color_code = r_cons_pal_parse (dup);
					R_FREE (dup);
				}
				break;
			case 'w': // "ecHw"
				if (!argc) {
					eprintf ("Usage: echw word [color]\n");
					r_str_argv_free (argv);
					return true;
				}
				word = strdup (argv[0]);
				if (argc > 1) {
					char *dup = r_str_newf ("bgonly %s", argv[1]);
					color_code = r_cons_pal_parse (dup);
					if (!color_code) {
						eprintf ("Unknown color %s\n", argv[1]);
						r_str_argv_free (argv);
						free (dup);
						free (word);
						return true;
					}
					R_FREE (dup);
				}
				break;
			default:
				eprintf ("See ecH?\n");
				r_str_argv_free (argv);
				return true;
			}
			char *str = r_meta_get_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset);
			char *dup = r_str_newf ("%s \"%s%s\"", str?str:"", word?word:"", color_code?color_code:r_cons_pal_get ("highlight"));
			r_meta_set_string (core->anal, R_META_TYPE_HIGHLIGHT, core->offset, dup);
			r_str_argv_free (argv);
			R_FREE (word);
			R_FREE (dup);
			break;
		}
		default: {
			char *p = strdup (input + 2);
			char *q = strchr (p, '=');
			if (!q) {
				q = strchr (p, ' ');
			}
			if (q) {
				// set
				*q++ = 0;
				r_cons_pal_set (p, q);
			} else {
				const char *k = r_cons_pal_get (p);
				if (k) {
					eprintf ("(%s)(%sCOLOR"Color_RESET")\n", p, k);
				}
			}
			free (p);
		}
		}
		break;
	case 'e':
		if (input[1] == ' ') {
			char *p;
			const char *val, *input2 = strchr (input+2, ' ');
			if (input2) input2++; else input2 = input+2;
			val = r_config_get (core->config, input2);
			p = r_core_editor (core, NULL, val);
			if (p) {
				r_str_replace_char (p, '\n', ';');
				r_config_set (core->config, input2, p);
			}
		} else {
			eprintf ("Usage: ee varname\n");
		}
		break;
	case '!':
		input = r_str_chop_ro (input+1);
		if (!r_config_toggle (core->config, input))
			eprintf ("r_config: '%s' is not a boolean variable.\n", input);
		break;
	case 's':
		r_config_list (core->config, (input[1])? input + 1: NULL, 's');
		break;
	case '-':
		r_core_config_init (core);
		//eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
		break;
	case '*': r_config_list (core->config, NULL, 1); break;
	case '?':
		switch (input[1]) {
		case '?': r_config_list (core->config, input+2, 2); break;
		default: r_config_list (core->config, input+1, 2); break;
		case 0:
			r_core_cmd_help (core, help_msg_e);
		}
		break;
	case 'r':
		if (input[1]) {
			const char *key = input+((input[1]==' ')?2:1);
			if (!r_config_readonly (core->config, key)) {
				eprintf ("cannot find key '%s'\n", key);
			}
		} else {
			eprintf ("Usage: er [key]\n");
		}
		break;
	case ' ': r_config_eval (core->config, input+1); break;
	default: r_config_eval (core->config, input); break;
	}
	return 0;
}
Example #14
0
static int cmd_meta_hsdmf(RCore *core, const char *input) {
	int n, type = input[0];
	char *t = 0, *p, name[256];
	int repeat = 1;
	ut64 addr_end = 0LL, addr = core->offset;

	switch (input[1]) {
	case '?':
		eprintf ("See C?\n");
		break;
	case '-':
		switch (input[2]) {
		case '*':
			core->num->value = r_meta_del (core->anal,
					input[0], 0, UT64_MAX, NULL);
			break;
		case ' ':
			addr = r_num_math (core->num, input+3);
			/* fallthrough */
		default:
			core->num->value = r_meta_del (core->anal,
					input[0], addr, 1, NULL);
			break;
		}
		break;
	case '*':
		r_meta_list (core->anal, input[0], 1);
		break;
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case ' ':
	case '\0':
		if (type != 'z' && input[1] == '*') {
			r_meta_list (core->anal, type, 0);
			break;
		}
		if (type == 'z') {
			type = 's';
		}
		if (strlen (input) > 2) {
			char *rep = strchr (input + 2, '[');
			if (!rep) rep = strchr (input + 2, ' ');
			if (rep) {
				repeat = r_num_get (core->num, rep + 1);
			}
		}
		int repcnt = 0;
		if (repeat < 1) {
			repeat = 1;
		}
		while (repcnt < repeat) {
			t = strdup (r_str_chop_ro (input + 1));
			p = NULL;
			n = 0;
			strncpy (name, t, sizeof (name) - 1);
			if (type != 'C') {
				n = r_num_math (core->num, t);
				if (type == 'f') { // "Cf"
					p = strchr (t, ' ');
					if (p) {
						if (n < 1) {
							n = r_print_format_struct_size (p + 1, core->print, 0);
							if (n < 1) {
								eprintf ("Cannot resolve struct size\n");
								n = 32; //
							}
						}
						int r = r_print_format (core->print, addr, core->block,
							n, p + 1, 0, NULL, NULL);
						if (r < 0) {
							n  = -1;
						}
					} else {
						eprintf ("Usage: Cf [size] [pf-format-string]\n");
						break;
					}
				} else if (type == 's') { //Cs
					char tmp[256] = {0};
					int i, j, name_len = 0;
					(void)r_core_read_at (core, addr, (ut8*)tmp, sizeof (tmp) - 1);
					name_len = r_str_nlen_w (tmp, sizeof (tmp));
					//handle wide strings
					for (i = 0, j = 0; i < sizeof (name); i++, j++) {
						name[i] = tmp[j];
						if (!tmp[j]) {
							break;
						}
						if (!tmp[j + 1]) {
							if (j + 3 < sizeof (tmp)) {
								if (tmp[j + 3]) {
									break;	
								}
							}
							j++;
						}
					}
					name[sizeof (name) - 1] = '\0';
					if (n == 0) {
						n = name_len + 1;
					} else {
						if (n > 0 && n < name_len) {
							name[n] = 0;
						}
					}
				}
				if (n < 1) {
					/* invalid length, do not insert into db */
					return false;
				}
				if (!*t || n > 0) {
					RFlagItem *fi;
					p = strchr (t, ' ');
					if (p) {
						*p = '\0';
						strncpy (name, p + 1, sizeof (name)-1);
					} else {
						if (type != 's') {
							fi = r_flag_get_i (core->flags, addr);
							if (fi) strncpy (name, fi->name, sizeof (name)-1);
						}
					}
				}
			}
			if (!n) {
				n++;
			}
			addr_end = addr + n;
			r_meta_add (core->anal, type, addr, addr_end, name);
			free (t);
			repcnt ++;
			addr = addr_end;
		}
		//r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX);
		break;
	default:
		eprintf ("Missing space after CC\n");
		break;
	}

	return true;
}
Example #15
0
static int cmd_meta_comment(RCore *core, const char *input) {
	ut64 addr = core->offset;
	switch (input[1]) {
	case '?': {
		const char* help_msg[] = {
			"Usage:", "CC[-+!*au] [base64:..|str] @ addr", "",
			"CC", "", "list all comments in human friendly form",
			"CC*", "", "list all comments in r2 commands",
			"CC.", "", "show comment at current offset",
			"CC,", " [file]", "show or set comment file",
			"CC", " [text]", "append comment at current address",
			"CCf", "", "list comments in function",
			"CC+", " [text]", "append comment at current address",
			"CC!", "", "edit comment using cfg.editor (vim, ..)",
			"CC-", " @ cmt_addr", "remove comment at given address",
			"CCu", " good boy @ addr", "add good boy comment at given address",
			"CCu", " base64:AA== @ addr", "add comment in base64",
			NULL};
		r_core_cmd_help (core, help_msg);
		} break;
	case ',': // "CC,"
		if (input[2]=='?') {
			eprintf ("Usage: CC, [file]\n");
		} else if (input[2]==' ') {
			const char *fn = input+2;
			char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
			while (*fn== ' ')fn++;
			if (comment && *comment) {
				// append filename in current comment
				char *nc = r_str_newf ("%s ,(%s)", comment, fn);
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, nc);
				free (nc);
			} else {
				char *comment = r_str_newf (",(%s)", fn);
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, comment);
				free (comment);
			}
		} else {
			char *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
			if (comment && *comment) {
				char *cmtfile = r_str_between (comment, ",(", ")");
				if (cmtfile && *cmtfile) {
					char *getcommapath(RCore *core);
					char *cwd = getcommapath (core);
					r_cons_printf ("%s"R_SYS_DIR"%s\n", cwd, cmtfile);
					free (cwd);
				}
				free (cmtfile);
			}
			free (comment);
		}
		break;
	case '.':
		  {
			  char *comment = r_meta_get_string (
					  core->anal, R_META_TYPE_COMMENT, addr);
			  if (comment) {
				  r_cons_println (comment);
				  free (comment);
			  }
		  }
		break;
	case 0: // "CC"
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 0);
		break;
	case 'f': // "CCf"
		r_meta_list_at (core->anal, R_META_TYPE_COMMENT, 'f', core->offset);
		break;
	case 'j': // "CCj"
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 'j');
		break;
	case '!':
		{
			char *out, *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			out = r_core_editor (core, NULL, comment);
			if (out) {
				//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
				r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
				//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
				r_meta_set_string (core->anal,
						R_META_TYPE_COMMENT, addr, out);
				free (out);
			}
			free (comment);
		}
		break;
	case '+':
	case ' ':
		{
		const char* newcomment = r_str_chop_ro (input + 2);
		char *text, *comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
		char *nc = strdup (newcomment);
		r_str_unescape (nc);
		if (comment) {
			text = malloc (strlen (comment)+strlen (newcomment)+2);
			if (text) {
				strcpy (text, comment);
				strcat (text, "\n");
				strcat (text, nc);
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, text);
				free (text);
			} else {
				r_sys_perror ("malloc");
			}
		} else {
			r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, nc);
		}
		free (nc);
		}
		break;
	case '*':
		r_meta_list (core->anal, R_META_TYPE_COMMENT, 1);
		break;
	case '-': // "CC-"
		r_meta_del (core->anal, R_META_TYPE_COMMENT, core->offset, 1, NULL);
		break;
	case 'u':
		//
		{
		char *newcomment;
		const char *arg = input + 2;
		while (*arg && *arg == ' ') arg++;
		if (!strncmp (arg, "base64:", 7)) {
			char *s = (char *)sdb_decode (arg+7, NULL);
			if (s) {
				newcomment = s;
			} else {
				newcomment = NULL;
			}
		} else {
			newcomment = strdup (arg);
		}
		if (newcomment) {
			char *comment = r_meta_get_string (
					core->anal, R_META_TYPE_COMMENT, addr);
			if (!comment || (comment && !strstr (comment, newcomment))) {
				r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
						addr, newcomment);
			}
			free (comment);
			free (newcomment);
		}
		}
		break;
	case 'a':
		{
		char *s, *p;
		s = strchr (input, ' ');
		if (s) {
			s = strdup (s + 1);
		} else {
			eprintf ("Usage\n");
			return false;
		}
		p = strchr (s, ' ');
		if (p) {
			*p++ = 0;
		}
		ut64 addr;
		if (input[2]=='-') {
			if (input[3]) {
				addr = r_num_math (core->num, input+3);
				r_meta_del (core->anal,
						R_META_TYPE_COMMENT,
						addr, 1, NULL);
			} else eprintf ("Usage: CCa-[address]\n");
			free (s);
			return true;
		}
		addr = r_num_math (core->num, s);
		// Comment at
		if (p) {
			if (input[2]=='+') {
				char *comment = r_meta_get_string (
						core->anal, R_META_TYPE_COMMENT,
						addr);
				if (comment) {
					char* text = r_str_newf ("%s\n%s", comment, p);
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, text);
					free (text);
				} else {
					r_meta_add (core->anal,
							R_META_TYPE_COMMENT,
							addr, addr+1, p);
				}
			} else {
				r_meta_add (core->anal,
						R_META_TYPE_COMMENT,
						addr, addr + 1, p);
			}
		} else {
			eprintf ("Usage: CCa [address] [comment]\n");
		}
		free (s);
		return true;
		}
	}

	return true;
}