Esempio n. 1
0
void r_comment_var_help(RCore *core, char type) {
	const char *help_bp[] = {
		"Usage:", "Cvb", "[name] [comment]",
		"Cvb?", "", "show this help",
		"Cvb", "", "list all base pointer args/vars comments in human friendly format",
		"Cvb*", "", "list all base pointer args/vars comments in r2 format",
		"Cvb-", "[name]", "delete comments for var/arg at current offset for base pointer",
		"Cvb", " [name]", "Show comments for var/arg at current offset for base pointer",
		"Cvb", " [name] [comment]", "add/append comment for the variable with the current name",
		"Cvb!", "[name]", "edit comment using cfg editor",
		NULL
	};
	const char *help_sp[] = {
		"Usage:", "Cvs", "[name] [comment]",
		"Cvs?", "", "show this help",
		"Cvs", "", "list all stack based args/vars comments in human friendly format",
		"Cvs*", "", "list all stack based args/vars comments in r2 format",
		"Cvs-", "[name]", "delete comments for stack pointer var/arg with that name",
		"Cvs", "[name]", "Show comments for stack pointer var/arg with that name",
		"Cvs", "[name] [comment]", "add/append comment for the variable",
		"Cvs!", "[name]", "edit comment using cfg editor",
		NULL
	};
	const char *help_reg[] = {
		"Usage:", "Cvr", "[name] [comment]",
		"Cvr?", "", "show this help",
		"Cvr", "", "list all register based args comments in human friendly format",
		"Cvr*", "", "list all register based args comments in r2 format",
		"Cvr-", "[name]", "delete comments for register based arg for that name",
		"Cvr", "[name]", "Show comments for register based arg for that name",
		"Cvr", "[name] [comment]", "add/append comment for the variable",
		"Cvr!", "[name]", "edit comment using cfg editor",
		NULL
	};

	switch (type) {
	case 'b':
		r_core_cmd_help (core, help_bp);
		break;
	case 's':
		r_core_cmd_help (core, help_sp);
		break;
	case 'r':
		r_core_cmd_help (core, help_reg);
		break;
	default:
		r_cons_printf("See Cvb, Cvs and Cvr\n");
	}
}
Esempio n. 2
0
static void cmd_type_noreturn(RCore *core, const char *input) {
	const char *help_msg[] = {
		"Usage:", "tn [-][0xaddr|symname]", " manage no-return marks",
		"tn[a]", " 0x3000", "stop function analysis if call/jmp to this address",
		"tn[n]", " sym.imp.exit", "same as above but for flag/fcn names",
		"tn", "-*", "remove all no-return references",
		"tn", "", "list them all",
		NULL };
	switch (input[0]) {
	case '-': // "tn-"
		r_anal_noreturn_drop (core->anal, input + 1);
		break;
	case ' ': // "tn"
		if (input[1] == '0' && input[2] == 'x') {
			r_anal_noreturn_add (core->anal, NULL,
					r_num_math (core->num, input + 1));
		} else {
			r_anal_noreturn_add (core->anal, input + 1,
					r_num_math (core->num, input + 1));
		}
		break;
	case 'a': // "ta"
		if (input[1] == ' ') {
			r_anal_noreturn_add (core->anal, NULL,
					r_num_math (core->num, input + 1));
		} else {
			r_core_cmd_help (core, help_msg);
		}
		break;
	case 'n': // "tnn"
		if (input[1] == ' ') {
			/* do nothing? */
		} else {
			r_core_cmd_help (core, help_msg);
		}
		break;
	case '*':
	case 'r': // "tn*"
		r_anal_noreturn_list (core->anal, 1);
		break;
	case 0: // "tn"
		r_anal_noreturn_list (core->anal, 0);
		break;
	default:
	case '?':
		r_core_cmd_help (core, help_msg);
		break;
	}
}
Esempio n. 3
0
static void show_help(RCore *core) {
	const char *help_message[] = {
		"Usage: t", "", "# cparse types commands",
		"t", "", "List all loaded types",
		"t", " <type>", "Show type in 'pf' syntax",
		"t*", "", "List types info in r2 commands",
		"t-", " <name>", "Delete types by its name",
		"t-*", "", "Remove all types",
		//"t-!", "",          "Use to open $EDITOR",
		"tb", " <enum> <value>", "Show matching enum bitfield for given number",
		"te", "", "List all loaded enums",
		"te", " <enum> <value>", "Show name for given enum number",
		"td", " <string>", "Load types from string",
		"tf", "", "List all loaded functions signatures",
		"tk", " <sdb-query>", "Perform sdb query",
		"tl", "[?]", "Show/Link type to an address",
		//"to",  "",         "List opened files",
		"to", " -", "Open cfg.editor to load types",
		"to", " <path>", "Load types from C header file",
		"tos", " <path>", "Load types from parsed Sdb database",
		"tp", " <type>  = <address>", "cast data at <adress> to <type> and print it",
		"ts", "", "print loaded struct types",
		"tu", "", "print loaded union types",
		//"| ts k=v k=v @ link.addr set fields at given linked type\n"
		NULL };
	r_core_cmd_help (core, help_message);
}
Esempio n. 4
0
static void cmd_fz(RCore *core, const char *input) {
	switch (*input) {
	case '?':
		r_core_cmd_help (core, help_msg_fz);
		break;
	case '.':
		{
			const char *a = NULL, *b = NULL;
			r_flag_zone_around (core->flags, core->offset, &a, &b);
			r_cons_printf ("%s %s\n", a?a:"~", b?b:"~");
		}
		break;
	case ':':
		{
			const char *a, *b;
			int a_len = 0;
			int w = r_cons_get_size (NULL);
			r_flag_zone_around (core->flags, core->offset, &a, &b);
			if (a) {
				r_cons_printf ("[<< %s]", a);
				a_len = strlen (a) + 4;
			}
			int padsize = (w / 2)  - a_len;
			int title_size = 12;
			if (a || b) {
				char *title = r_str_newf ("[ 0x%08"PFMT64x" ]", core->offset);
				title_size = strlen (title);
				padsize -= strlen (title) / 2;
				const char *halfpad = r_str_pad (' ', padsize);
				r_cons_printf ("%s%s", halfpad, title);
				free (title);
			}
			if (b) {
				padsize = (w / 2) - title_size - strlen (b) - 4;
				const char *halfpad = padsize > 1? r_str_pad (' ', padsize): "";
				r_cons_printf ("%s[%s >>]", halfpad, b);
			}
			if (a || b) {
				r_cons_newline();
			}
		}
		break;
	case ' ':
		r_flag_zone_add (core->flags, r_str_trim_ro (input + 1), core->offset);
		break;
	case '-':
		if (input[1] == '*') {
			r_flag_zone_reset (core->flags);
		} else {
			r_flag_zone_del (core->flags, input + 1);
		}
		break;
	case '*':
		r_flag_zone_list (core->flags, '*');
		break;
	case 0:
		r_flag_zone_list (core->flags, 0);
		break;
	}
}
Esempio n. 5
0
static void show_help(RCore *core) {
	const char * help_message[] = {
		"Usage: t", "",    "# cparse types commands",
		"t",   "",         "List all loaded types",
		"t",   " <type>",  "Show type in 'pf' syntax",
		"t*",  "",         "List types info in r2 commands",
		"t-",  " <name>",  "Delete types by its name",
		"t-*", "",         "Remove all types",
		//"t-!", "",          "Use to open $EDITOR",
		"tb",  " <enum> <value>","Show matching enum bitfield for given number",
		"te",  " <enum> <value>","Show name for given enum number",
		"td",  " <string>","Load types from string",
		"td-", "<name>",   "Undefine type by name",
		"tf",  " <addr>",  "View linked type at given address",
		"tl",  "[?]",      "Show/Link type to a address",
		//"to",  "",         "List opened files",
		"to",  " -",       "Open cfg.editor to load types",
		"to",  " <path>",  "Load types from C header file",
		"tk",  " <sdb-query>", "Perform sdb query",
		"ts",  " <k>=<v>", "Set fields at curseek linked type",
		//"| ts k=v k=v @ link.addr set fields at given linked type\n"
		NULL
	};
	r_core_cmd_help (core, help_message);
}
Esempio n. 6
0
static int cmd_quit(void *data, const char *input) {
	RCore *core = (RCore *)data;
	const char* help_msg[] = {
		"Usage:",  "q[!] [retval]", "",
		"q","","quit program",
		"q!","","force quit (no questions)",
		"q"," 1","quit with return value 1",
		"q"," a-b","quit with return value a-b",
		NULL};
	if (input)
	switch (*input) {
	case '?':
		r_core_cmd_help (core, help_msg);
		break;
	case ' ':
	case '!':
		input++;
	case '\0':
		// TODO
	default:
		r_line_hist_save (R2_HOMEDIR"/history");
		if (*input)
			r_num_math (core->num, input);
		else core->num->value = 0LL;
		//exit (*input?r_num_math (core->num, input+1):0);
		//if (core->http_up) return R_FALSE; // cancel quit when http is running
		return -2;
	}
	return R_FALSE;
}
static int cmd_quit(void *data, const char *input) {
	RCore *core = (RCore *)data;
	const char* help_msg[] = {
		"Usage:",  "q[!][!] [retval]", "",
		"q","","quit program",
		"q!","","force quit (no questions)",
		"q!!","","force quit without saving history",
		"q"," 1","quit with return value 1",
		"q"," a-b","quit with return value a-b",
		NULL};
	if (input)
	switch (*input) {
	case '?':
		r_core_cmd_help (core, help_msg);
		break;
	case '!':
		if (input[1] == '!')
			r_config_set (core->config, "scr.histsave", "false");
		core->num->value = -1;
		return -2;
	case '\0':
		core->num->value = 0LL;
		return -2;
	default:
		if (*input == ' ')
			input++;
		if (*input)
			r_num_math (core->num, input);
		else core->num->value = 0LL;
		//exit (*input?r_num_math (core->num, input+1):0);
		//if (core->http_up) return R_FALSE; // cancel quit when http is running
		return -2;
	}
	return R_FALSE;
}
Esempio n. 8
0
static bool cmd_wf(RCore *core, const char *input) {
	if (!core || !*input) {
		return false;
	}
	if (input[1] == '?') {
		eprintf ("Usage: wf [file] ([size] ([offset]))\n");
		r_core_cmd_help (core, help_msg_wf);
		return false;
	}
	if (input[1] == 's') { // "wfs"
		return cmd_wfs (core, input + 1);
	}
	if (input[1] == 'f') { // "wff"
		return cmd_wff (core, input + 1);
	}
	char *args = r_str_trim (strdup (input + 1));
	char *arg = strchr (args, ' ');
	int len = core->blocksize;
	if (arg) {
		*arg++ = 0;
		len = r_num_math (core->num, arg);
	}
	ut64 addr = r_num_math (core->num, args);
	ioMemcpy (core, core->offset, addr, len);
	free (args);
	r_core_block_read (core);
	return true;
}
Esempio n. 9
0
static int cmd_meta(void *data, const char *input) {
	RCore *core = (RCore*)data;
	int i;
	RAnalFunction *f;

	switch (*input) {
	case 'j':
	case '*':
		r_meta_list (core->anal, R_META_TYPE_ANY, *input);
		break;
	case 'L':
		cmd_meta_lineinfo (core, input + 1);
		break;
	case 'C':
		cmd_meta_comment (core, input);
		break;
	case 'h': /* comment */
	case 's': /* string */
	case 'd': /* data */
	case 'm': /* magic */
	case 'f': /* formatted */
		cmd_meta_hsdmf (core, input);
		break;
	case '-':
		if (input[1]!='*') {
			i = r_num_math (core->num, input+((input[1]==' ')?2:1));
			r_meta_del (core->anal, R_META_TYPE_ANY, core->offset, i, "");
		} else r_meta_cleanup (core->anal, 0LL, UT64_MAX);
		break;
	case '\0':
	case '?':{
			const char* help_msg[] = {
				"Usage:", "C[-LCvsdfm?] [...]", " # Metadata management",
				"C*", "", "list meta info in r2 commands",
				"C-", " [len] [[@]addr]", "delete metadata at given address range",
				"CL", "[-][*] [file:line] [addr]", "show or add 'code line' information (bininfo)",
				"CC", "[-] [comment-text] [@addr]", "add/remove comment",
				"CC!", " [@addr]", "edit comment with $EDITOR",
				"CCa", "[-at]|[at] [text] [@addr]", "add/remove comment at given address",
				"CCu", " [comment-text] [@addr]", "add unique comment",
				"Cs", "[-] [size] [@addr]", "add string",
				"Ch", "[-] [size] [@addr]", "hide data",
				"Cd", "[-] [size] [@addr]", "hexdump data",
				"Cf", "[-] [sz] [fmt..] [@addr]", "format memory (see pf?)",
				"Cm", "[-] [sz] [fmt..] [@addr]", "magic parse (see pm?)",
				NULL};
			r_core_cmd_help (core, help_msg);
			}
		break;
	case 'F':
		f = r_anal_get_fcn_in (core->anal, core->offset,
			R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
		if (f) r_anal_str_to_fcn (core->anal, f, input+2);
		else eprintf ("Cannot find function here\n");
		break;
	}
	return R_TRUE;
}
Esempio n. 10
0
void r_core_hack_help(const RCore *core) {
	const char* help_msg[] = {
		"wao", " [op]", "performs a modification on current opcode",
		"wao", " nop", "nop current opcode",
		"wao", " jz", "make current opcode conditional (zero)",
		"wao", " jnz", "make current opcode conditional (not zero)",
		"wao", " ret1", "make the current opcode return 1",
		"wao", " ret0", "make the current opcode return 0",
		"wao", " retn", "make the current opcode return -1",
		"wao", " nocj", "remove conditional operation from branch (make it unconditional)",
		"wao", " trap", "make the current opcode a trap",
		"wao", " recj", "reverse (swap) conditional branch instruction",
		"NOTE:", "", "those operations are only implemented for x86 and arm atm.", //TODO
		NULL
	};
	r_core_cmd_help (core, help_msg);
}
Esempio n. 11
0
int main (int argc, char **argv) {
	r_anal_esil_set_pc (core->anal->esil, fcn ? fcn->addr : core->offset);
	switch (*input) {
	case '\0': // "aft"
	{
		seek = core->offset;
		r_anal_esil_set_pc (core->anal->esil, fcn ? fcn->addr : core->offset);
		r_core_anal_type_match (core, fcn);
		r_core_seek (core, seek, true);
		break;
	}
	case '?':
	default:
		r_core_cmd_help (core, help_msg_aft);
		break;
	}
	return 0;
}
Esempio n. 12
0
R_API void r_core_rtr_help(RCore *core) {
	const char* help_msg[] = {
	"Usage:", " =[:!+-=hH] [...]", " # radare remote command execution protocol",
	"=", ":port", "listen on given port using rap protocol (o rap://9999)",
	"=", ":host:port cmd", "run 'cmd' command on remote server",
	"\nrap commands:", "", "",
	"=", "", "list all open connections",
	"=<", "[fd] cmd", "send output of local command to remote fd",
	"=", "[fd] cmd", "exec cmd at remote 'fd' (last open is default one)",
	"=!", " cmd", "run command via r_io_system",
	"=+", " [proto://]host", "add host (default=rap://, tcp://, udp://)",
	"=-", "[fd]", "remove all hosts or host 'fd'",
	"==", "[fd]", "open remote session with host 'fd', 'q' to quit",
	"\nhttp server:", "", "",
	"=h", "", "listen for http connections (r2 -qc=H /bin/ls)",
	"=H", "", "launch browser and listen for http",
	NULL};
	r_core_cmd_help (core, help_msg);
}
Esempio n. 13
0
static int cmd_hash(void *data, const char *input) {
	RCore *core = (RCore *)data;

	if (*input == '!') {
		return cmd_hash_bang (core, input);
	}
	if (*input == '?') {
		const char *helpmsg3[] = {
		"Usage #!interpreter [<args>] [<file] [<<eof]","","",
		" #", "", "comment - do nothing",
		" #!","","list all available interpreters",
		" #!python","","run python commandline",
		" #!python"," foo.py","run foo.py python script (same as '. foo.py')",
		//" #!python <<EOF        get python code until 'EOF' mark\n"
		" #!python"," arg0 a1 <<q","set arg0 and arg1 and read until 'q'",
		NULL};
		r_core_cmd_help (core, helpmsg3);
		return false;
	}
	/* this is a comment - captain obvious
	   should not be reached, see r_core_cmd_subst() */
	return 0;
}
Esempio n. 14
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;
}
Esempio n. 15
0
static int cmd_meta(void *data, const char *input) {
	RCore *core = (RCore*)data;
	int i;
	RAnalFunction *f;

	switch (*input) {
	case 'j':
	case '*':
		r_meta_list (core->anal, R_META_TYPE_ANY, *input);
		break;
	case 'L':
		cmd_meta_lineinfo (core, input + 1);
		break;
	case 'C':
		cmd_meta_comment (core, input);
		break;
	case 'h': /* comment */
	case 's': /* string */
	case 'd': /* data */
	case 'm': /* magic */
	case 'f': /* formatted */
		cmd_meta_hsdmf (core, input);
		break;
	case '-':
		if (input[1]!='*') {
			i = r_num_math (core->num, input+((input[1]==' ')?2:1));
			r_meta_del (core->anal, R_META_TYPE_ANY, core->offset, i, "");
		} else r_meta_cleanup (core->anal, 0LL, UT64_MAX);
		break;
	case '\0':
	case '?':{
			const char* help_msg[] = {
				"Usage:", "C[-LCvsdfm?] [...]", " # Metadata management",
				"C*", "", "list meta info in r2 commands",
				"C-", " [len] [[@]addr]", "delete metadata at given address range",
				"CL", "[-][*] [file:line] [addr]", "show or add 'code line' information (bininfo)",
				"CS", "[-][space]", "manage meta-spaces to filter comments, etc..",
				"CC", "[-] [comment-text] [@addr]", "add/remove comment",
				"CC!", " [@addr]", "edit comment with $EDITOR",
				"CCa", "[-at]|[at] [text] [@addr]", "add/remove comment at given address",
				"CCu", " [comment-text] [@addr]", "add unique comment",
				"Cs", "[-] [size] [@addr]", "add string",
				"Ch", "[-] [size] [@addr]", "hide data",
				"Cd", "[-] [size] [@addr]", "hexdump data",
				"Cf", "[-] [sz] [fmt..] [@addr]", "format memory (see pf?)",
				"Cm", "[-] [sz] [fmt..] [@addr]", "magic parse (see pm?)",
				NULL};
			r_core_cmd_help (core, help_msg);
			}
		break;
	case 'F':
		f = r_anal_get_fcn_in (core->anal, core->offset,
			R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
		if (f) r_anal_str_to_fcn (core->anal, f, input+2);
		else eprintf ("Cannot find function here\n");
		break;
	case 'S':
		 {
		RSpaces *ms = &core->anal->meta_spaces;
		/** copypasta from `fs`.. this must be refactorized to be shared */
		switch (input[1]) {
		case '?':
			{
			const char *help_msg[] = {
			"Usage: CS","[*] [+-][metaspace|addr]", " # Manage metaspaces",
			"CS","","display metaspaces",
			"CS"," *","select all metaspaces",
			"CS"," metaspace","select metaspace or create if it doesn't exist",
			"CS","-metaspace","remove metaspace",
			"CS","-*","remove all metaspaces",
			"CS","+foo","push previous metaspace and set",
			"CS","-","pop to the previous metaspace",
		//	"CSm"," [addr]","move metas at given address to the current metaspace",
			"CSr"," newname","rename selected metaspace",
			NULL};
			r_core_cmd_help (core, help_msg);
			}
			break;
		case '+':
			r_space_push (ms, input+2);
			break;
		case 'r':
			if (input[2]==' ')
				r_space_rename (ms, NULL, input+2);
			else eprintf ("Usage: CSr [newname]\n");
			break;
		case '-':
			if (input[2]) {
				if (input[2]=='*') {
					r_space_unset (ms, NULL);
				} else {
					r_space_unset (ms, input+2);
				}
			} else {
				r_space_pop (ms);
			}
			break;
		case 'j':
		case '\0':
		case '*':
			r_space_list (ms, input[1]);
			break;
		case ' ':
			r_space_set (ms, input+2);
			break;
#if 0
		case 'm':
			{ RFlagItem *f;
			ut64 off = core->offset;
			if (input[2] == ' ')
				off = r_num_math (core->num, input+2);
			f = r_flag_get_i (core->flags, off);
			if (f) {
				f->space = core->flags->space_idx;
			} else eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off);
			}
			break;
#endif
		default: {
			int i, j = 0;
			for (i=0; i<R_FLAG_SPACES_MAX; i++) {
				if (ms->spaces[i])
					r_cons_printf ("%02d %c %s\n", j++,
					(i==ms->space_idx)?'*':' ',
					ms->spaces[i]);
			}
			} break;
		}
		 }
		break;
	}
	return R_TRUE;
}
Esempio n. 16
0
static int cmd_log(void *data, const char *input) {
	RCore *core = (RCore *)data;
	const char *arg, *input2;
	int n, n2;

	if (!input)
		return 1;

	input2 = (input && *input) ? input+1 : "";
	arg = strchr (input2, ' ');
	n = atoi (input2);
	n2 = arg ? atoi (arg+1) : 0;

	switch (*input) {
	case 'e': // shell: less
		{
		char *p = strchr (input, ' ');
		if (p) {
			char *b = r_file_slurp (p+1, NULL);
			if (b) {
				r_cons_less_str (b, NULL);
				free (b);
			} else eprintf ("File not found\n");
		} else eprintf ("Usage: less [filename]\n");
		}
		break;
	case 'l':
		r_cons_printf ("%d\n", core->log->last-1);
		break;
	case '-':
		r_core_log_del (core, n);
		break;
	case '?':{
			const char* help_msg[] = {
			"Usage:", "T","[-][ num|msg]",
			"T", "", "List all Text log messages",
			"T", " new comment", "0x80480",
			"T", " 123", "List log from 123",
			"T", " 10 3", "List 3 log messages starting from 10",
			"T*", "", "List in radare commands",
			"T-", "", "Delete all logs",
			"T-", " 123", "Delete logs before 123",
			"Tl", "", "Get last log message id",
			"Tj", "", "List in json format",
			"Tm", " [idx]", "Display log messages without index",
			"Ts", "", "List files in current directory (see pwd, cd)",
			"Tp", "[-plug]", "Tist, load, unload plugins",
			"TT", "", "Enter into the text log chat console",
			NULL};
		r_core_cmd_help (core, help_msg);
		}
		break;
	case 'T':
		if (r_config_get_i (core->config, "scr.interactive")) {
			textlog_chat (core);
		} else eprintf ("Only available when the screen is interactive\n");
		break;
	case 'p':
		switch (input[1]) {
		case 0:
			r_lib_list (core->lib);
			break;
		case '-':
			r_lib_close (core->lib, input+2);
			break;
		case ' ':
			r_lib_open (core->lib, input+2);
			break;
		case '?': {
			const char* help_msg[] = {
			"Usage:", "Tp", "[-name][ file]",
			"Tp", "", "List all plugins loaded by RCore.lib",
			"Tp-", "duk", "Unload plugin matching in filename",
			"Tp", " blah."R_LIB_EXT, "Load plugin file",
			NULL};
			r_core_cmd_help(core, help_msg);
			}
			break;
		}
		break;
	case ' ':
		if (n>0) {
			r_core_log_list (core, n, n2, *input);
		} else {
			r_core_log_add (core, input+1);
		}
		break;
	case 'm':
		if (n>0) {
			r_core_log_list (core, n, 1, 't');
		} else {
			r_core_log_list (core, n, 0, 't');
		}
		break;
	case 'j':
	case '*':
	case '\0':
		r_core_log_list (core, n, n2, *input);
		break;
	}
	return 0;
}
Esempio n. 17
0
static int cmd_type(void *data, const char *input) {
	RCore *core = (RCore*)data;

	switch (input[0]) {
	// t [typename] - show given type in C syntax
	case 'k':
		if (input[1]==' ') {
			sdb_query (core->anal->sdb_types, input+2);
		} else sdb_query (core->anal->sdb_types, "*");
		break;
	case 's':
	{
		char *q, *p, *o, *e;
		p = o = strdup (input+1);
		for (;;) {
			if (*p == '\0'){
				eprintf ("Usage: ts <k>=<v> Set fields at curseek linked type\n");	
				break;
			}
			q = strchr (p, ' ');
			if (q) *q = 0;
			if (!*p) {
				p++;
				continue;
			}
			e = strchr (p, '=');
			if (e) {
				*e = 0;
				r_anal_type_set (core->anal, core->offset,
					p, r_num_math (core->num, e+1));
			} else eprintf ("TODO: implement get\n");
			if (!q) break;
			p = q+1;
		}
		free (o);
	}
		break;
	case 'b':
		{
		int i;
		char *p, *s = (strlen (input) > 1) ? strdup (input+2): NULL;
		const char *isenum;
		p = s ? strchr (s, ' ') : NULL;
		if (p) {
			*p++ = 0;
// dupp in core.c (see getbitfield())
#if 1
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strcmp (isenum, "enum")) {
				int empty = 1;
				ut32 num = (ut32)r_num_math (core->num, p);
				r_cons_printf ("0x%08"PFMT64x" : ", num);
				for (i=0; i< 32; i++) {
					if (num & (1<<i)) {
						const char *q = sdb_fmt (0, "%s.0x%x", s, (1<<i));
						const char *res = sdb_const_get (core->anal->sdb_types, q, 0);
						if (!empty)
							r_cons_printf (" | ");
						if (res) r_cons_printf ("%s", res);
						else r_cons_printf ("0x%x", (1<<i));
						empty = 0;
					}
				}
			} else {
				eprintf ("This is not an enum\n");
			}
#endif
		} else {
			eprintf ("Missing value\n");
		}
		free (s);
		}
		break;
	case 'e':
		{
		if (!input[1]) {
			eprintf ("Missing value\n");
			break;
		}
		char *p, *s = strdup (input+2);
		const char *isenum;
		p = strchr (s, ' ');
		if (p) {
			*p++ = 0;
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strcmp (isenum, "enum")) {
				const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p));
				const char *res = sdb_const_get (core->anal->sdb_types, q, 0);
				if (res)
					r_cons_printf ("%s\n", res);
			} else {
				eprintf ("This is not an enum\n");
			}
		} else {
			eprintf ("Missing value\n");
		}
		free (s);
		}
		break;
	case ' ':
	{
		const char *isenum = sdb_const_get (core->anal->sdb_types, input+2, 0);
		if (isenum && !strcmp (isenum, "enum")) {
			eprintf ("IS ENUM! \n");
		} else {
			char *fmt = r_anal_type_format (core->anal, input +1);
			if (fmt) {
				r_cons_printf ("pf %s\n", fmt);
				free (fmt);
			} else eprintf ("Cannot find '%s' type\n", input+1);
		}
	}
		break;
#if 0
	// t* - list all types in 'pf' syntax
	case '*':
		r_anal_type_list (core->anal, R_ANAL_TYPE_ANY, 1);
		break;
#endif
	case 0:
		sdb_foreach (core->anal->sdb_types, sdbforcb, core);
		break;
	case 'o':
		if (input[1] == ' ') {
			const char *filename = input + 2;
			if (!strcmp (filename, "-")) {
				char *out, *tmp;
				tmp = r_core_editor (core, NULL, "");
				if (tmp) {
					out = r_parse_c_string (tmp);
					if (out) {
				//		r_cons_strcat (out);
						sdb_query_lines (core->anal->sdb_types, out);
						free (out);
					}
					free (tmp);
				}
			} else {
				char *out = r_parse_c_file (filename);
				if (out) {
				//	r_cons_strcat (out);
					sdb_query_lines (core->anal->sdb_types, out);
					free (out);
				}
				//r_anal_type_loadfile (core->anal, filename);
			}
		}
		break;
	// td - parse string with cparse engine and load types from it
	case 'd':
		if (input[1] == '?') {
			const char * help_message[] = {
				"Usage:", "td[...]", "",
				"td", "[string]", "Load types from string",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else
		if (input[1] == '-') {
			const char *arg = strchr (input+1, ' ');
			if (arg) arg++; else arg = input+2;
			r_anal_type_del (core->anal, arg);
		} else
		if (input[1] == ' ') {
			char tmp[8192];
			snprintf (tmp, sizeof (tmp)-1, "%s;", input+2);
			//const char *string = input + 2;
			//r_anal_str_to_type (core->anal, string);
			char *out = r_parse_c_string (tmp);
			if (out) {
				//r_cons_strcat (out);
				sdb_query_lines (core->anal->sdb_types, out);
				free (out);
			}
		} else {
			eprintf ("Invalid use of td. See td? for help\n");
		}
		break;
	// tl - link a type to an address
	case 'l':
		if (input[1]=='?') {
			const char * help_message[] = {
				"Usage: tl", " [typename|addr] ([addr])@[addr|function]", "",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else if (input[1]) {
			ut64 addr = r_num_math (core->num, input+2);
			char *ptr = strchr (input + 2, ' ');
			if (ptr) {
				addr = r_num_math (core->num, ptr + 1);
				*ptr = '\0';
			} else addr = core->offset;
			r_anal_type_link (core->anal, input+2, addr);
		} else {
			r_core_cmd0 (core, "t~^link");
		}
		break;
	case '-':
		if (input[1] == '?') {
			const char * help_message[] = {
				"Usage: t-", " <type>", "Delete type by its name",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else
		if (input[1]=='*') {
			eprintf ("TODO\n");
		} else {
			const char *name = input + 1;
			if (*name==' ') name++;
			if (*name) {
				r_anal_type_del (core->anal, name);
			} else eprintf ("Invalid use of t- . See t-? for help.\n");
		}
		break;
	// tv - get/set type value linked to a given address
	case 'f':
		 {
			ut64 addr;
			char *fmt, key[128];
			const char *type;
			if (input[1]) {
				addr = r_num_math (core->num, input+1);
			} else addr = core->offset;
			snprintf (key, sizeof (key), "link.%08"PFMT64x, addr);
			type = sdb_const_get (core->anal->sdb_types, key, 0);
			if (type) {
				fmt = r_anal_type_format (core->anal, type);
				r_cons_printf ("struct %s {\n", type);
				if (fmt) {
					r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, addr);
					free (fmt);
				}// else eprintf ("Cannot find '%s' type\n", input+1);
				r_cons_printf ("}\n");
			} //else eprintf ("Cant find type at 0x%llx\n", addr);
		 }
		break;
	case '?':
		show_help (core);
		break;
	}
	return true;
}
Esempio n. 18
0
static void cmd_write_op (RCore *core, const char *input) {
	ut8 *buf;
	int len;
	int value;
	if (!input[0])
		return;
	switch (input[1]) {
	case 'e':
		if (input[2]!=' ') {
			r_cons_printf ("Usage: 'woe from-to step'\n");
			return;
		}
		/* fallthru */
	case 'a':
	case 's':
	case 'A':
	case 'x':
	case 'r':
	case 'l':
	case 'm':
	case 'd':
	case 'o':
	case 'w':
	case '2':
	case '4':
		if (input[2]) {  // parse val from arg
			r_core_write_op (core, input+3, input[1]);
			r_core_block_read (core);
		} else {  // use clipboard instead of val
			r_core_write_op (core, NULL, input[1]);
			r_core_block_read (core);
		}
		break;
	case 'R':
		r_core_cmd0 (core, "wr $b");
		break;
	case 'n':
		r_core_write_op (core, "ff", 'x');
		r_core_block_read (core);
		break;
	case 'E': // "woE" encrypt
	case 'D': // "woD" decrypt
		{
			int direction = (input[1] == 'E') ? 0 : 1;
			const char *algo = NULL;
			const char *key = NULL;
			const char *iv = NULL;
			char *space, *args = strdup (r_str_trim_ro (input+2));
			space = strchr (args, ' ');
			if (space) {
				*space++ = 0;
				key = space;
				space = strchr (key, ' ');
				if (space) {
					*space++ = 0;
					iv = space;
				}
			}
			algo = args;
			if (algo && *algo && key) {
				encrypt_or_decrypt_block (core, algo, key, direction, iv);
			} else {
				eprintf ("Usage: wo%c [algo] [key] [IV]\n", ((!direction)?'E':'D'));
				eprintf ("Currently supported hashes:\n");
				ut64 bits;
				int i;
				for (i = 0; ; i++) {
					bits = ((ut64)1) << i;
					const char *name = r_hash_name (bits);
					if (!name || !*name) break;
					printf ("  %s\n", name);
				}
				eprintf ("Available Encoders/Decoders: \n");
				// TODO: do not hardcode
				eprintf ("  base64\n");
				eprintf ("  base91\n");
				eprintf ("  punycode\n");
				eprintf ("Currently supported crypto algos:\n");
				for (i = 0; ; i++) {
					bits = ((ut64)1) << i;
					const char *name = r_crypto_name (bits);
					if (!name || !*name) break;
					printf ("  %s\n", name);
				}
			}
			free (args);
		}
		break;
	case 'p': // debrujin patterns
		switch (input[2]) {
		case 'D': // "wopD"
			len = (int)(input[3]==' ')
				? r_num_math (core->num, input + 3)
				: core->blocksize;
			if (len > 0) {
				/* XXX This seems to fail at generating long patterns (wopD 512K) */
				buf = (ut8*)r_debruijn_pattern (len, 0, NULL); //debruijn_charset);
				if (buf) {
					const ut8 *ptr = buf;
					ut64 addr = core->offset;
					if (input[3] == '*') {
						int i;
						r_cons_printf ("wx ");
						for (i = 0; i < len; i++) {
							r_cons_printf ("%02x", buf[i]);
						}
						r_cons_newline ();
					} else {
						while (true) {
							int res = r_core_write_at (core, addr, ptr, len);
							if (res < 1 || len == res) {
								break;
							}
							if (res < len) {
								ptr += res;
								len -= res;
								addr += res;
							}
						} 
					}
					free (buf);
				} else {
					eprintf ("Couldn't generate pattern of length %d\n", len);
				}
			}
			break;
		case 'O': // "wopO"
			if (strlen (input) > 4 && strncmp (input + 4, "0x", 2)) {
				eprintf ("Need hex value with `0x' prefix e.g. 0x41414142\n");
			} else if (input[3] == ' ') {
				value = r_num_get (core->num, input + 4);
				core->num->value = r_debruijn_offset (value, r_config_get_i (core->config, "cfg.bigendian"));
				r_cons_printf ("%"PFMT64d"\n", core->num->value);
			}
			break;
		case '\0':
		case '?':
		default:
			r_core_cmd_help (core, help_msg_wop);
			break;
		}
		break;
	case '\0':
	case '?':
	default:
		r_core_cmd_help (core, help_msg_wo);
		break;
	}
}
Esempio n. 19
0
static void cmd_write_value (RCore *core, const char *input) {
	int type = 0;
	ut64 off = 0LL;
	ut8 buf[sizeof(ut64)];
	int wseek = r_config_get_i (core->config, "cfg.wseek");
	bool be = r_config_get_i (core->config, "cfg.bigendian");

	if (!input)
		return;

	if (input[0])
	switch (input[1]) {
	case '?':
		r_core_cmd_help (core, help_msg_wv);
		return;
	case '1': type = 1; break;
	case '2': type = 2; break;
	case '4': type = 4; break;
	case '8': type = 8; break;
	}
	if (input && input[0] && input[1] && input[2]) {
		off = r_num_math (core->num, input+2);
	}
	if (core->file) {
		r_io_use_fd (core->io, core->file->fd);
	}
	ut64 res = r_io_seek (core->io, core->offset, R_IO_SEEK_SET);
	if (res == UT64_MAX) return;
	if (type == 0)
		type = (off&UT64_32U)? 8: 4;
	switch (type) {
	case 1:
		r_write_ble8 (buf, (ut8)(off & UT8_MAX));
		if (!r_io_write (core->io, buf, 1)) {
			cmd_write_fail ();
		} else {
			WSEEK (core, 1);
		}
		break;
	case 2:
		r_write_ble16 (buf, (ut16)(off & UT16_MAX), be);
		if (!r_io_write (core->io, buf, 2)) {
			cmd_write_fail ();
		} else {
			WSEEK (core, 2);
		}
		break;
	case 4:
		r_write_ble32 (buf, (ut32)(off & UT32_MAX), be);
		if (!r_io_write (core->io, buf, 4)) {
			cmd_write_fail ();
		} else {
			WSEEK (core, 4);
		}
		break;
	case 8:
		r_write_ble64 (buf, off, be);
		if (!r_io_write (core->io, buf, 8)) {
			cmd_write_fail ();
		} else {
			WSEEK (core, 8);
		}
		break;
	}
	r_core_block_read (core);
}
Esempio n. 20
0
static int cmd_project(void *data, const char *input) {
	RCore *core = (RCore *) data;
	const char *file, *arg = (input && *input)? input + 1: NULL;
	const char *fileproject = r_config_get (core->config, "prj.name");
	char *str = NULL;

	if (!input) {
		return false;
	}
	str = strdup (fileproject);
	arg = strchr (input, ' ');
	if (arg) {
		arg++;
	} else {
		if (*input) {
			arg = input + 1;
			if (*arg == '&') {
				arg++;
			}
		}
	}
	file = arg;
	switch (input[0]) {
	case 'c':
		if (input[1] == ' ') {
			r_core_project_cat (core, input + 2);
		} else {
			eprintf ("Usage: Pc [prjname]\n");
		}
		break;
	case 'o':
		//	if (r_file_is_regular (file))
		if (input[1] == '&') {
			r_core_project_open (core, file, true);
		} else if (input[1]) {
			r_core_project_open (core, file, false);
		} else {
			if (file && *file) {
				r_cons_println (file);
			}
		}
		break;
	case 'l':
		r_core_project_list (core, input[1]);
		break;
	case 'd':
	case '-':
		r_core_project_delete (core, file);
		break;
	case 's':
		if (!file || !file[0]) { /* if no argument specified use current project */
			file = str;
		}
		if (r_core_project_save (core, file)) {
			r_config_set (core->config, "prj.name", file);
			r_cons_println (file);
		}
		break;
	case 'S':
		if (input[1] == ' ') {
			r_core_project_save_rdb (core, input + 2, R_CORE_PRJ_ALL);
		} else {
			eprintf ("Usage: PS [file]\n");
		}
		break;
	case 'n':
		if (!fileproject || !*fileproject) {
			eprintf ("No project\n");
		} else {
			switch (input[1]) {
			case '-':
				/* remove lines containing specific words */
			{
				FILE *fd = r_sandbox_fopen (str, "w");
				if (!fd) {
					eprintf ("Cannot open %s\n", str);
				} else {
					char *str = r_core_project_notes_file (core, fileproject);
					char *data = r_file_slurp (str, NULL);
					int del = 0;
					if (data) {
						char *ptr, *nl;
						for (ptr = data; ptr; ptr = nl)  {
							nl = strchr (ptr, '\n');
							if (nl) {
								*nl++ = 0;
								if (strstr (ptr, input + 2)) {
									del++;
								} else {
									fprintf (fd, "%s\n", ptr);
								}
							}
						}
						free (data);
					}
					if (del > 0) {
						eprintf ("Deleted %d lines\n", del);
					}
					free (str);
					fclose (fd);
				}
			}
			break;
			case ' ':
				if (input[2] == '-') {
					char *str = r_core_project_notes_file (core, fileproject);
					// edit with cfg.editor
					const char *editor = r_config_get (core->config, "cfg.editor");
					if (str && *str && editor && *editor) {
						r_sys_cmdf ("%s %s", editor, str);
					} else {
						eprintf ("No cfg.editor configured\n");
					}
					free (str);
				} else {
					//char *str = r_core_project_notes_file (core, fileproject);
					// append line to project notes
					char *str = r_core_project_notes_file (core, fileproject);
					char *data = r_file_slurp (str, NULL);
					FILE *fd = r_sandbox_fopen (str, "a");
					if (fd) {
						fprintf (fd, "%s\n", input + 2);
						fclose (fd);
					}
					free (str);
					free (data);
				}
				break;
			case 'j':
				if (!input[2]) {
					int len = 0;
					/* get base64 string */
					char *str = r_core_project_notes_file (core, fileproject);
					if (str) {
						char *data = r_file_slurp (str, &len);
						char *res = r_base64_encode_dyn (data, len);
						if (res) {
							r_cons_println (res);
							free (res);
						}
						free (data);
						free (str);
					}
				} else if (input[2] == ' ') {
					/* set base64 string */
					ut8 *data = r_base64_decode_dyn (input + 3, -1);
					if (data) {
						char *str = r_core_project_notes_file (core, fileproject);
						if (str) {
							r_file_dump (str, data, strlen ((const char *) data), 0);
							free (str);
						}
						free (data);
					}
				} else {
					eprintf ("Usage: `Pnj` or `Pnj ...`\n");
				}
				break;
			case 'x':
				r_core_project_execute_cmds (core, fileproject);
				break;
			case 0:
			{
				char *str = r_core_project_notes_file (core, fileproject);
				char *data = r_file_slurp (str, NULL);
				if (data) {
					r_cons_println (data);
					free (data);
				}
				free (str);
			}
			break;
			case '?':
			{
				const char *help_msg[] = {
					"Usage:", "Pn[j-?] [...]", "Project Notes",
					"Pn", "", "show project notes",
					"Pn", " -", "edit notes with cfg.editor",
					"Pn-", "", "delete notes",
					"Pn-", "str", "delete lines matching /str/ in notes",
					"Pnx", "", "run project note commands",
					"Pnj", "", "show notes in base64",
					"Pnj", " [base64]", "set notes in base64",
					NULL
				};
				r_core_cmd_help (core, help_msg);
			}
			break;
			}
		}
		break;
	case 'i':
		if (file && *file) {
			char *prjName = r_core_project_info (core, file);
			r_cons_println (prjName);
			free (prjName);
		}
		break;
	default: {
		const char *help_msg[] = {
			"Usage:", "P[?osi] [file]", "Project management",
			"Pc", " [file]", "show project script to console",
			"Pd", " [file]", "delete project",
			"Pi", " [file]", "show project information",
			"Pl", "", "list all projects",
			"Pn", "[j]", "show project notes (Pnj for json)",
			"Pn", " [base64]", "set notes text",
			"Pn", " -", "edit notes with cfg.editor",
			"Po", " [file]", "open project",
			"Ps", " [file]", "save project",
			"PS", " [file]", "save script file",
			"P-", " [file]", "delete project (alias for Pd)",
			"NOTE:", "", "See 'e??prj.'",
			"NOTE:", "", "project are stored in ~/.config/radare2/projects",
			NULL
		};
		r_core_cmd_help (core, help_msg);
	}
		break;
	}
	free (str);
	return true;
}
Esempio n. 21
0
static int cmd_type(void *data, const char *input) {
	RCore *core = (RCore *)data;

	switch (input[0]) {
	// t [typename] - show given type in C syntax
	case 'u': // "tu"
		switch (input[1]) {
		case '?': {
			const char *help_message[] = {
				"USAGE tu[...]", "", "",
				"tu", "", "List all loaded unions",
				"tu?", "", "show this help",
				NULL };
			r_core_cmd_help (core, help_message);
		} break;
		case 0:
			sdb_foreach (core->anal->sdb_types, stdprintifunion, core);
			break;
		}
		break;
	case 'k': // "tk"
		if (input[1] == ' ') {
			sdb_query (core->anal->sdb_types, input + 2);
		} else sdb_query (core->anal->sdb_types, "*");
		fflush (stdout);
		break;
	case 's': // "ts"
		switch (input[1]) {
		case '?': {
			const char *help_message[] = {
				"USAGE ts[...]", "", "",
				"ts", "", "List all loaded structs",
				"ts?", "", "show this help",
				NULL };
			r_core_cmd_help (core, help_message);
		} break;
		case 0:
			sdb_foreach (core->anal->sdb_types, stdprintifstruct, core);
			break;
		}
		break;
	case 'b': {
		char *p, *s = (strlen (input) > 1)? strdup (input + 2): NULL;
		const char *isenum;
		p = s? strchr (s, ' '): NULL;
		if (p) {
			*p++ = 0;
			// dupp in core.c (see getbitfield())
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strcmp (isenum, "enum")) {
				*--p = '.';
				const char *res = sdb_const_get (core->anal->sdb_types, s, 0);
				if (res)
					r_cons_println (res);
				else eprintf ("Invalid enum member\n");
			} else {
				eprintf ("This is not an enum\n");
			}
		} else {
			eprintf ("Missing value\n");
		}
		free (s);
	} break;
	case 'e': {
		if (!input[1]) {
			char *name = NULL;
			SdbKv *kv;
			SdbListIter *iter;
			SdbList *l = sdb_foreach_list (core->anal->sdb_types);
			ls_foreach (l, iter, kv) {
				if (!strcmp (kv->value, "enum")) {
					if (!name || strcmp (kv->value, name)) {
						free (name);
						name = strdup (kv->key);
						r_cons_println (name);
					}
				}
			}
			free (name);
			ls_free (l);
			break;
		}
		if (input[1] == '?') {
			const char *help_message[] = {
				"USAGE te[...]", "", "",
				"te", "", "List all loaded enums",
				"te", " <enum> <value>", "Show name for given enum number",
				"te?", "", "show this help",
				NULL };
			r_core_cmd_help (core, help_message);
			break;
		}
		char *p, *s = strdup (input + 2);
		const char *isenum;
		p = strchr (s, ' ');
		if (p) {
			*p++ = 0;
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strncmp (isenum, "enum", 4)) {
				const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p));
				const char *res = sdb_const_get (core->anal->sdb_types, q, 0);
				if (res)
					r_cons_println (res);
			} else {
				eprintf ("This is not an enum\n");
			}
		} else {
			//eprintf ("Missing value\n");
			r_core_cmdf (core, "t~&%s,=0x", s);
		}
		free (s);
	} break;
	case ' ': {
		const char *isenum = sdb_const_get (core->anal->sdb_types, input + 1, 0);
		if (isenum && !strcmp (isenum, "enum")) {
			eprintf ("IS ENUM! \n");
		} else {
			char *fmt = r_anal_type_format (core->anal, input + 1);
			if (fmt) {
				r_str_chop (fmt);
				r_cons_printf ("pf %s\n", fmt);
				free (fmt);
			} else eprintf ("Cannot find '%s' type\n", input + 1);
		}
	} break;
	// t* - list all types in 'pf' syntax
	case '*':
		sdb_foreach (core->anal->sdb_types, typelist, core);
		break;
	case 0:
		sdb_foreach (core->anal->sdb_types, sdbforcb, core);
		break;
	case 'o':
		if (!r_sandbox_enable (0)) {
			if (input[1] == ' ') {
				const char *filename = input + 2;
				char *homefile = NULL;
				if (*filename == '~') {
					if (filename[1] && filename[2]) {
						homefile = r_str_home (filename + 2);
						filename = homefile;
					}
				}
				if (!strcmp (filename, "-")) {
					char *out, *tmp;
					tmp = r_core_editor (core, NULL, "");
					if (tmp) {
						out = r_parse_c_string (tmp);
						if (out) {
							//		r_cons_strcat (out);
							save_parsed_type (core, out);
							free (out);
						}
						free (tmp);
					}
				} else {
					char *out = r_parse_c_file (filename);
					if (out) {
						//r_cons_strcat (out);
						save_parsed_type (core, out);
						free (out);
					}
					//r_anal_type_loadfile (core->anal, filename);
				}
				free (homefile);
			} else if (input[1] == 's') {
				const char *dbpath = input + 3;
				if (r_file_exists (dbpath)) {
					Sdb *db_tmp = sdb_new (0, dbpath, 0);
					sdb_merge (core->anal->sdb_types, db_tmp);
					sdb_close (db_tmp);
					sdb_free (db_tmp);
				}
			}
		} else {
			eprintf ("Sandbox: system call disabled\n");
		}
		break;
	// td - parse string with cparse engine and load types from it
	case 'd':
		if (input[1] == '?') {
			const char *help_message[] = {
				"Usage:", "\"td [...]\"", "",
				"td", "[string]", "Load types from string",
				NULL };
			r_core_cmd_help (core, help_message);
			r_cons_printf ("Note: The td command should be put between double quotes\n"
				"Example: \" td struct foo {int bar;int cow};\""
				"\nt");

		} else if (input[1] == ' ') {
			char tmp[8192];
			snprintf (tmp, sizeof (tmp) - 1, "%s;", input + 2);
			//const char *string = input + 2;
			//r_anal_str_to_type (core->anal, string);
			char *out = r_parse_c_string (tmp);
			if (out) {
				//r_cons_strcat (out);
				save_parsed_type (core, out);
				free (out);
			}
		} else {
			eprintf ("Invalid use of td. See td? for help\n");
		}
		break;
	// tl - link a type to an address
	case 'l':
		switch (input[1]) {
		case '?': {
			const char *help_message[] = {
				"Usage:", "", "",
				"tl", "", "list all links in readable format",
				"tl", "[typename]", "link a type to current adress.",
				"tl", "[typename] = [address]", "link type to given address.",
				"tls", "[address]", "show link at given address",
				"tl-*", "", "delete all links.",
				"tl-", "[address]", "delete link at given address.",
				"tl*", "", "list all links in radare2 command format",
				"tl?", "", "print this help.",
				NULL };
			r_core_cmd_help (core, help_message);
			} break;
		case ' ': {
			char *type = strdup (input + 2);
			char *ptr = strchr (type, '=');
			ut64 addr;

			if (ptr) {
				*ptr++ = 0;
				r_str_chop (ptr);
				if (ptr && *ptr) {
					addr = r_num_math (core->num, ptr);
				} else {
					eprintf ("address is unvalid\n");
					free (type);
					break;
				}
			} else {
				addr = core->offset;
			}
			r_str_chop (type);
			char *tmp = sdb_get (core->anal->sdb_types, type, 0);
			if (tmp && *tmp) {
				r_anal_type_link (core->anal, type, addr);
				free (tmp);
			} else {
				eprintf ("unknown type %s\n", type);
			}
			free (type);
			}
			break;
		case 's': {
			int ptr;
			char *addr = strdup (input + 2);
			SdbKv *kv;
			SdbListIter *sdb_iter;
			SdbList *sdb_list = sdb_foreach_list (core->anal->sdb_types);
			r_str_chop (addr);
			ptr = r_num_math (NULL, addr);
			//r_core_cmdf (core, "tl~0x%08"PFMT64x" = ", addr);
			ls_foreach (sdb_list, sdb_iter, kv) {
				char *linkptr;
				if (strncmp (kv->key, "link.", strlen ("link."))) {
					continue;
				}
				linkptr = sdb_fmt (-1,"0x%s", kv->key + strlen ("link."));
				if (ptr == r_num_math (NULL, linkptr)) {
					linklist_readable (core, kv->key, kv->value);
				}
			}
			free (addr);
			ls_free (sdb_list);
			}
			break;
		case '-':
			switch (input[2]) {
			case '*':
				sdb_foreach (core->anal->sdb_types, sdbdeletelink, core);
				break;
			case ' ': {
				const char *ptr = input + 3;
				ut64 addr = r_num_math (core->num, ptr);
				r_anal_type_unlink (core->anal, addr);
				}
				break;
			}
			break;
		case '*':
			sdb_foreach (core->anal->sdb_types, linklist, core);
			break;
		case '\0':
			sdb_foreach (core->anal->sdb_types, linklist_readable, core);
			break;
		}
Esempio n. 22
0
static int cmd_hash(void *data, const char *input) {
	char algo[32];
	RCore *core = (RCore *)data;
	ut32 osize = 0, len = core->blocksize;
	const char *ptr;
	int pos = 0, handled_cmd = R_FALSE;

	switch (*input) {
	case '\t':
	case ' ':
		return 0;
	case '#':
		if (!input[1]) {
		algolist (1);
		return R_TRUE;
		}
	case '!':
		return cmd_hash_bang (core, input);
	}

	ptr = strchr (input, ' ');
	sscanf (input, "%31s", algo);
	if (ptr && *(ptr+1) && r_num_is_valid_input (core->num, ptr+1)) {
		int nlen = r_num_math (core->num, ptr+1);
		if (nlen>0) len = nlen;
		osize = core->blocksize;
		if (nlen>core->blocksize) {
			r_core_block_size (core, nlen);
			if (nlen != core->blocksize) {
				eprintf ("Invalid block size\n");
				r_core_block_size (core, osize);
				return R_TRUE;
			}
		}
	} else if (!ptr || !*(ptr+1)) osize = len;
	/* TODO: Simplify this spaguetti monster */

	while (osize > 0 && HASH_HANDLERS[pos].name != NULL) {
		if (!r_str_ccmp (input, HASH_HANDLERS[pos].name, ' ')) {
			HASH_HANDLERS[pos].handler (core->block, len);
			handled_cmd = R_TRUE;
			break;
		}
		pos++;
	}

	if (!osize) {
		eprintf ("Error: provided size must be size > 0\n");
	}

	if (*input == '?') {
		const char *helpmsg[] = {
		"Usage: #algo <size> @ addr", "", "",
		" #"," comment","note the space after the sharp sign",
		" ##","","List hash/checksum algorithms.",
		" #sha256", " 10K @ 33","calculate sha256 of 10K at 33",
		NULL
		};
		const char *helpmsg2[] = {
		"Hashes:","","", NULL };
		const char *helpmsg3[] = {
		"Usage #!interpreter [<args>] [<file] [<<eof]","","",
		" #!","","list all available interpreters",
		" #!python","","run python commandline",
		" #!python"," foo.py","run foo.py python script (same as '. foo.py')",
		//" #!python <<EOF        get python code until 'EOF' mark\n"
		" #!python"," arg0 a1 <<q","set arg0 and arg1 and read until 'q'",
		NULL};
		r_core_cmd_help (core, helpmsg);
		r_core_cmd_help (core, helpmsg2);
		algolist (0);
		r_core_cmd_help (core, helpmsg3);
	}
	if (osize)
		r_core_block_size (core, osize);
	return handled_cmd;
}
Esempio n. 23
0
static int cmd_seek(void *data, const char *input) {
	RCore *core = (RCore *)data;
	char *cmd, *p;
	ut64 off;

	if (*input=='r') {
		if (input[1] && input[2]) {
			if (core->io->debug) {
				off = r_debug_reg_get (core->dbg, input+2);
				r_io_sundo_push (core->io, core->offset);
				r_core_seek (core, off, 1);
			} else {
				RReg *orig = core->dbg->reg;
				core->dbg->reg = core->anal->reg;
				off = r_debug_reg_get (core->dbg, input+2);
				core->dbg->reg = orig;
				r_core_seek (core, off, 1);
			}
		} else eprintf ("|Usage| 'sr pc' seek to program counter register\n");
	} else
	if (*input) {
		const char *inputnum = strchr (input+1, ' ');
		int sign = 1;
		inputnum = inputnum? inputnum+1: input+1;
		off = r_num_math (core->num, inputnum);
		if (*inputnum== '-') off = -off;
#if 0
		if (input[0]!='/' && inputnum && isalpha (inputnum[0]) && off == 0) {
			if (!r_flag_get (core->flags, inputnum)) {
				eprintf ("Cannot find address for '%s'\n", inputnum);
				return R_FALSE;
			}
		}
#endif
		if (input[0]==' ') {
			switch (input[1]) {
			case '-': sign=-1;
			case '+': input++; break;
			}
		}

		switch (*input) {
		case 'C':
			if (input[1]=='*') {
				r_core_cmd0 (core, "C*~^\"CC");
			} else
			if (input[1]==' ') {
				typedef struct {
					ut64 addr;
					char *str;
				} MetaCallback;
				int count = 0;
				MetaCallback cb = { 0, NULL };
				ut64 addr;
				char key[128];
				const char *val, *comma;
				char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0);
				char *str, *next, *cur = list;
				if (list) {
					for (;;) {
						cur = sdb_anext (cur, &next);
						addr = sdb_atoi (cur);
						snprintf (key, sizeof (key)-1, "meta.C.0x%"PFMT64x, addr);
						val = sdb_const_get (core->anal->sdb_meta, key, 0);
						if (val) {
							comma = strchr (val, ',');
							if (comma) {
								str = (char *)sdb_decode (comma+1, 0);
								if (strstr (str, input+2)) {
									r_cons_printf ("0x%08"PFMT64x"  %s\n", addr, str);
									count++;
									cb.addr = addr;
									free (cb.str);
									cb.str = str;
								} else free (str);
							}
						} else eprintf ("sdb_const_get key not found '%s'\n", key);
						if (!next)
							break;
						cur = next;
					}
				}

				switch (count) {
				case 0:
					eprintf ("No matching comments\n");
					break;
				case 1:
					off = cb.addr;
					r_io_sundo_push (core->io, core->offset);
					r_core_seek (core, off, 1);
					r_core_block_read (core, 0);
					break;
				default:
					eprintf ("Too many results\n");
					break;
				}
				free (cb.str);
			} else eprintf ("Usage: sC[?*] comment-grep\n"
				"sC*        list all comments\n"
				"sC const   seek to comment matching 'const'\n");
			break;
		case ' ':
			r_io_sundo_push (core->io, core->offset);
			r_core_seek (core, off*sign, 1);
			r_core_block_read (core, 0);
			break;
		case '/':
			{
			const char *pfx = r_config_get (core->config, "search.prefix");
//kwidx cfg var is ignored
			int kwidx = core->search->n_kws; //(int)r_config_get_i (core->config, "search.kwidx")-1;
			if (kwidx<0) kwidx = 0;
			switch (input[1]) {
			case ' ':
			case 'x':
				r_config_set_i (core->config, "search.count", 1);
				r_core_cmdf (core, "s+1; p8 ; .%s;s-1;s %s%d_0;f-%s%d_0",
					input, pfx, kwidx, pfx, kwidx, pfx, kwidx);
				r_config_set_i (core->config, "search.count", 0);
				break;
			default:
				eprintf ("unknown search method\n");
				break;
			}
			}
			break;
		case '.':
			for (input++;*input=='.';input++);
			r_core_seek_base (core, input);
			break;
		case '*':
			r_io_sundo_list (core->io);
			break;
		case '+':
			if (input[1]!='\0') {
				int delta = (input[1]=='+')? core->blocksize: off;
				r_io_sundo_push (core->io, core->offset);
				r_core_seek_delta (core, delta);
			} else {
				off = r_io_sundo_redo (core->io);
				if (off != UT64_MAX)
					r_core_seek (core, off, 0);
			}
			break;
		case '-':
			if (input[1]!='\0') {
				int delta = (input[1]=='-') ? -core->blocksize: -off;
				r_io_sundo_push (core->io, core->offset);
				r_core_seek_delta (core, delta);
			} else {
				off = r_io_sundo (core->io, core->offset);
				if (off != UT64_MAX)
					r_core_seek (core, off, 0);
			}
			break;
		case 'n':
			r_io_sundo_push (core->io, core->offset);
			r_core_seek_next (core, r_config_get (core->config, "scr.nkey"));
			break;
		case 'p':
			r_io_sundo_push (core->io, core->offset);
			r_core_seek_previous (core, r_config_get (core->config, "scr.nkey"));
			break;
		case 'a':
			off = core->blocksize;
			if (input[1]&&input[2]) {
				cmd = strdup (input);
				p = strchr (cmd+2, ' ');
				if (p) {
					off = r_num_math (core->num, p+1);;
					*p = '\0';
				}
				cmd[0] = 's';
				// perform real seek if provided
				r_cmd_call (core->rcmd, cmd);
				free (cmd);
			}
			r_io_sundo_push (core->io, core->offset);
			r_core_seek_align (core, off, 0);
			break;
		case 'b':
			if (off == 0)
				off = core->offset;
			r_io_sundo_push (core->io, core->offset);
			r_core_anal_bb_seek (core, off);
			break;
		case 'f':
			if (strlen(input) > 2 && input[1]==' ') {
				RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, input+2);
				if (fcn) {
					r_core_seek (core, fcn->addr, 1);
				}
				break;
			}
			RAnalFunction *fcn = r_anal_fcn_find (core->anal, core->offset, 0);
			if (fcn) {
				r_core_seek (core, fcn->addr+fcn->size, 1);
			}
			break;
		case 'o':
			{
			RAnalOp op;
			int val=0, ret, i, n = r_num_math (core->num, input+1);
			if (n==0) n = 1;
			if (n<0) {
				int ret = prevopsz (core, n);
				ret = r_anal_op (core->anal, &op,
						core->offset, core->block, core->blocksize);
				val += ret;
			} else
			for (val=i=0; i<n; i++) {
				ret = r_anal_op (core->anal, &op,
						core->offset, core->block, core->blocksize);
				if (ret<1)
					break;
				r_core_seek_delta (core, ret);
				val += ret;
			}
			core->num->value = val;
			}
			break;
		case 'g':
			{
			RIOSection *s = r_io_section_vget (core->io, core->offset);
			if (s) r_core_seek (core, s->vaddr, 1);
			else r_core_seek (core, 0, 1);
			}
			break;
		case 'G':
			{
			RIOSection *s = r_io_section_vget (core->io, core->offset);
			// XXX: this +2 is a hack. must fix gap between sections
			if (s) r_core_seek (core, s->vaddr+s->size+2, 1);
			else r_core_seek (core, core->file->size, 1);
			}
			break;
		case '?': {
			const char * help_message[] = {
			"Usage: s", "", " # Seek commands",
			"s", "", "Print current address",
			"s", " addr", "Seek to address",
			"s-", "", "Undo seek",
			"s-", " n", "Seek n bytes backward",
			"s--", "", "Seek blocksize bytes backward",
			"s+", "", "Redo seek",
			"s+", " n", "Seek n bytes forward",
			"s++", "", "Seek blocksize bytes forward",
			"s*", "", "List undo seek history",
			"s/", " DATA", "Search for next occurrence of 'DATA'",
			"s/x", " 9091", "Search for next occurrence of \\x90\\x91",
			"s.", "hexoff", "Seek honoring a base from core->offset",
			"sa", " [[+-]a] [asz]", "Seek asz (or bsize) aligned to addr",
			"sb", "", "Seek aligned to bb start",
			"sC", " string", "Seek to comment matching given string",
			"sf", "", "Seek to next function (f->addr+f->size)",
			"sf", " function", "Seek to address of specified function",
			"sg/sG", "", "Seek begin (sg) or end (sG) of section or file",
			"sn/sp", "", "Seek next/prev scr.nkey",
			"so", " [N]", "Seek to N next opcode(s)",
			"sr", " pc", "Seek to register",
			//"sp [page]  seek page N (page = block)",
			NULL
			};
			r_core_cmd_help(core, help_message);
		}
			break;
		}
	} else r_cons_printf ("0x%"PFMT64x"\n", core->offset);
	return 0;
}
Esempio n. 24
0
static void cmd_write_value (RCore *core, const char *input) {
	int type = 0;
	ut8 addr1;
	ut16 addr2;
	ut32 addr4, addr4_;
	ut64 addr8, off = 0LL;
	int wseek = r_config_get_i (core->config, "cfg.wseek");

	if (!input)
		return;

	if (input[0])
	switch (input[1]) {
	case '?':
	{
		const char* help_msg[] = {
			"Usage:", "wv[size] [value]", "write value of given size",
			"wv1", " 234", "write one byte with this value",
			"wv", " 0x834002", "write dword with this value",
			"Supported sizes are:", "1, 2, 4, 8", "",
			NULL};
		r_core_cmd_help (core, help_msg);
		return;
	}
	case '1': type = 1; break;
	case '2': type = 2; break;
	case '4': type = 4; break;
	case '8': type = 8; break;
	}
	if (input && input[0] && input[1] && input[2]) {
		off = r_num_math (core->num, input+2);
	}
	if (core->file) {
		r_io_use_desc (core->io, core->file->desc);
	}
	r_io_seek (core->io, core->offset, R_IO_SEEK_SET);
	if (type == 0)
		type = (off&UT64_32U)? 8: 4;
	switch (type) {
	case 1:
		addr1 = (ut8)off;
		r_io_write (core->io, (const ut8 *)&addr1, 1);
		WSEEK (core, 1);
		break;
	case 2:
		addr2 = (ut16)off;
		r_io_write (core->io, (const ut8 *)&addr2, 2);
		WSEEK (core, 2);
		break;
	case 4:
		addr4_ = (ut32)off;
		//drop_endian((ut8*)&addr4_, (ut8*)&addr4, 4); /* addr4_ = addr4 */
		//endian_memcpy((ut8*)&addr4, (ut8*)&addr4_, 4); /* addr4 = addr4_ */
		memcpy ((ut8*)&addr4, (ut8*)&addr4_, 4); // XXX needs endian here too
		r_io_write (core->io, (const ut8 *)&addr4, 4);
		WSEEK (core, 4);
		break;
	case 8:
		/* 8 byte addr */
		memcpy ((ut8*)&addr8, (ut8*)&off, 8); // XXX needs endian here
		//	endian_memcpy((ut8*)&addr8, (ut8*)&off, 8);
		r_io_write (core->io, (const ut8 *)&addr8, 8);
		WSEEK (core, 8);
		break;
	}
	r_core_block_read (core, 0);
}
Esempio n. 25
0
/* TODO: simplify using r_write */
static int cmd_write(void *data, const char *input) {
	int wseek, i, size, len = strlen (input);
	RCore *core = (RCore *)data;
	char *tmp, *str, *ostr;
	const char *arg, *filename;
	char _fn[32];
	ut64 off;
	ut8 *buf;
	st64 num = 0;
	const char* help_msg[] = {
		"Usage:","w[x] [str] [<file] [<<EOF] [@addr]","",
		"w","[1248][+-][n]","increment/decrement byte,word..",
		"w"," foobar","write string 'foobar'",
		"w0"," [len]","write 'len' bytes with value 0x00",
		"w6","[de] base64/hex","write base64 [d]ecoded or [e]ncoded string",
		"wa"," push ebp","write opcode, separated by ';' (use '\"' around the command)",
		"waf"," file","assemble file and write bytes",
		"wA"," r 0","alter/modify opcode at current seek (see wA?)",
		"wb"," 010203","fill current block with cyclic hexpairs",
		"wB","[-]0xVALUE","set or unset bits with given value",
		"wc","","list all write changes",
		"wc","[ir*?]","write cache undo/commit/reset/list (io.cache)",
		"wd"," [off] [n]","duplicate N bytes from offset at current seek (memcpy) (see y?)",
		"we","[nNsxX] [arg]","extend write operations (insert instead of replace)",
		"wf"," -|file","write contents of file at current offset",
		"wF"," -|file","write contents of hexpairs file here",
		"wh"," r2","whereis/which shell command",
		"wm"," f0ff","set binary mask hexpair to be used as cyclic write mask",
		"wo?"," hex","write in block with operation. 'wo?' fmi",
		"wp"," -|file","apply radare patch file. See wp? fmi",
		"wr"," 10","write 10 random bytes",
		"ws"," pstring","write 1 byte for length and then the string",
		"wt"," file [sz]","write to file (from current seek, blocksize or sz bytes)",
		"ww"," foobar","write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'",
		"wx"," 9090","write two intel nops",
		"wv"," eip+34","write 32-64 bit value",
		NULL
	};

	if (!input)
		return 0;

	#define WSEEK(x,y) if (wseek)r_core_seek_delta (x,y)
	wseek = r_config_get_i (core->config, "cfg.wseek");
	str = ostr = strdup ((input&&*input)?input+1:"");
	_fn[0] = 0;

	switch (*input) {
	case 'B':
		switch (input[1]) {
		case ' ':
			cmd_write_bits (core, 1, r_num_math (core->num, input+2));
			break;
		case '-':
			cmd_write_bits (core, 0, r_num_math (core->num, input+2));
			break;
		default:
			eprintf ("Usage: wB 0x2000  # or wB-0x2000\n");
			break;
		}
		break;
	case '0':
		{
			ut64 len = r_num_math (core->num, input+1);
			if (len>0) {
				ut8 *buf = calloc (1, len);
				if (buf) {
					r_io_write (core->io, buf, len);
					free (buf);
				} else eprintf ("Cannot allocate %d bytes\n", (int)len);
			}
		}
		break;
	case '1':
	case '2':
	case '4':
	case '8':
		if (input[1] && input[2]) {
			if (input[1]==input[2]) {
				num = 1;
			} else num = r_num_math (core->num, input+2);
		}
		switch (input[2] ? input[1] : 0) {
		case '+':
			cmd_write_inc (core, *input-'0', num);
			break;
		case '-':
			cmd_write_inc (core, *input-'0', -num);
			break;
		default:
			eprintf ("Usage: w[1248][+-][num]   # inc/dec byte/word/..\n");
		}
		break;
	case '6':
		{
		int fail = 0;
		if(input[1] && input[2] != ' ') {
			fail = 1;
		}
		ut8 *buf;
		int len, str_len;
		const char *str;

		if (input[1] && input[2] && input[3])
			str = input + 3;
		else str = "";
		str_len = strlen (str) + 1;
		if (!fail) {
			switch (input[1]) {
			case 'd':
				buf = malloc (str_len);
				len = r_base64_decode (buf, str, 0);
				if(len == 0) {
					free(buf);
					fail = 1;
				}
				break;
			case 'e':
				{
				ut8 *bin_buf = malloc(str_len);
				int bin_len = r_hex_str2bin(str, bin_buf);
				if(bin_len == 0) {
					fail = 1;
				} else {
					buf = malloc(str_len * 4 + 1);
					len = r_base64_encode((char *)buf, bin_buf, bin_len);
					if(len == 0) {
						free(buf);
						fail = 1;
					}
				}
				free (bin_buf);
				break;
				}
			default:
				fail = 1;
				break;
			}
		}
		if(!fail) {
			r_core_write_at (core, core->offset, buf, len);
			WSEEK (core, len);
			r_core_block_read (core, 0);
			free(buf);
		} else {
			eprintf ("Usage: w6[de] base64/hex\n");
		}
		break;
		}
	case 'h':
		{
		char *p = strchr (input, ' ');
		if (p) {
			while (*p==' ') p++;
			p = r_file_path (p);
			if (p) {
				r_cons_printf ("%s\n", p);
				free (p);
			}
		}
		}
		break;
	case 'e':
		{
		ut64 addr = 0, len = 0, b_size = 0;
		st64 dist = 0;
		ut8* bytes = NULL;
		int cmd_suc = R_FALSE;
		char *input_shadow = NULL, *p = NULL;

		switch (input[1]) {
			case 'n':
				if (input[2] == ' ') {
					len = *input ? r_num_math (
						core->num, input+3) : 0;
					if (len > 0){
						ut64 cur_off = core->offset;
						cmd_suc = r_core_extend_at (core, core->offset, len);
						core->offset = cur_off;
						r_core_block_read (core, 0);
					}
				}
				break;
			case 'N':
				if (input[2] == ' ') {
					input += 3;
					while (*input && *input == ' ') input++;
					addr = r_num_math (core->num, input);
					while (*input && *input != ' ') input++;
					input++;
					len = *input ? r_num_math (core->num, input) : 0;
					if (len > 0){
						ut64 cur_off = core->offset;
						cmd_suc = r_core_extend_at (core, addr, len);
						cmd_suc = r_core_seek (core, cur_off, 1);
						core->offset = addr;
						r_core_block_read (core, 0);
					}
				}
				break;
			case 'x':
				if (input[2] == ' ') {
					input+=2;
					len = *input ? strlen (input) : 0;
					bytes = len > 1? malloc (len+1) : NULL;
					len = bytes ? r_hex_str2bin (input, bytes) : 0;
					if (len > 0) {
						ut64 cur_off = core->offset;
						cmd_suc = r_core_extend_at (core, cur_off, len);
						if (cmd_suc) {
							r_core_write_at (core, cur_off, bytes, len);
						}
						core->offset = cur_off;
						r_core_block_read (core, 0);
					}
					free (bytes);
				}
				break;
			case 'X':
				if (input[2] == ' ') {
					addr = r_num_math (core->num, input+3);
					input += 3;
					while (*input && *input != ' ') input++;
					input++;
					len = *input ? strlen (input) : 0;
					bytes = len > 1? malloc (len+1) : NULL;
					len = bytes ? r_hex_str2bin (input, bytes) : 0;
					if (len > 0) {
						//ut64 cur_off = core->offset;
						cmd_suc = r_core_extend_at (core, addr, len);
						if (cmd_suc) {
							r_core_write_at (core, addr, bytes, len);
						}
						core->offset = addr;
						r_core_block_read (core, 0);
					}
					free (bytes);
				}
				break;
			case 's':
				input +=  3;
				while (*input && *input == ' ') input++;
				len = strlen (input);
				input_shadow = len > 0? malloc (len+1): 0;

				// since the distance can be negative,
				// the r_num_math will perform an unwanted operation
				// the solution is to tokenize the string :/
				if (input_shadow) {
					strncpy (input_shadow, input, len+1);
					p = strtok (input_shadow, " ");
					addr = p && *p ? r_num_math (core->num, p) : 0;

					p = strtok (NULL, " ");
					dist = p && *p ? r_num_math (core->num, p) : 0;

					p = strtok (NULL, " ");
					b_size = p && *p ? r_num_math (core->num, p) : 0;
					if (dist != 0){
						r_core_shift_block (core, addr, b_size, dist);
						r_core_seek (core, addr, 1);
						cmd_suc = R_TRUE;
					}
				}
				free (input_shadow);
				break;
			case '?':
			default:
				cmd_suc = R_FALSE;
		}


		if (cmd_suc == R_FALSE) {
			r_cons_printf ("|Usage: write extend\n"
			"wen <num>               insert num null bytes at current offset\n"
			"wex <hex_bytes>         insert bytes at current offset\n"
			"weN <addr> <len>        insert bytes at address\n"
			"weX <addr> <hex_bytes>  insert bytes at address\n"
			"wes <addr>  <dist> <block_size>   shift a blocksize left or write in the editor\n"
			);
		}
		}
		break;
	case 'p':
		if (input[1]=='-' || (input[1]==' ' && input[2]=='-')) {
			char *out = r_core_editor (core, NULL, NULL);
			if (out) {
				r_core_patch (core, out);
				free (out);
			}
		} else {
			if (input[1]==' ' && input[2]) {
				char *data = r_file_slurp (input+2, NULL);
				if (data) {
					r_core_patch (core, data);
					free (data);
				}
			} else {
				eprintf ("Usage: wp [-|r2patch-file]\n"
			         "TODO: rapatch format documentation here\n");
			}
		}
		break;
	case 'u':
		// TODO: implement it in an API RCore.write_unified_hexpatch() is ETOOLONG
		if (input[1]==' ') {
			char *data = r_file_slurp (input+2, NULL);
			if (data) {
				char sign = ' ';
				int line = 0, offs = 0, hexa = 0;
				int newline = 1;
				for (i=0; data[i]; i++) {
					switch (data[i]) {
					case '+':
						if (newline)
							sign = 1;
						break;
					case '-':
						if (newline) {
							sign = 0;
							offs = i + ((data[i+1]==' ')?2:1);
						}
						break;
					case ' ':
						data[i] = 0;
						if (sign) {
							if (!line) line = i+1;
							else
							if (!hexa) hexa = i+1;
						}
						break;
					case '\r':
						break;
					case '\n':
						newline = 1;
						if (sign == -1) {
							offs = 0;
							line = 0;
							hexa = 0;
						} else if (sign) {
							if (offs && hexa) {
								r_cons_printf ("wx %s @ %s\n", data+hexa, data+offs);
							} else eprintf ("food\n");
							offs = 0;
							line = 0;
						} else hexa = 0;
						sign = -1;
						continue;
					}
					newline = 0;
				}
				free (data);
			}
		} else {
			eprintf ("|Usage: wu [unified-diff-patch]    # see 'cu'\n");
		}
		break;
	case 'r':
		off = r_num_math (core->num, input+1);
		len = (int)off;
		if (len>0) {
			buf = malloc (len);
			if (buf != NULL) {
				r_num_irand ();
				for (i=0; i<len; i++)
					buf[i] = r_num_rand (256);
				r_core_write_at (core, core->offset, buf, len);
				WSEEK (core, len);
				free (buf);
			} else eprintf ("Cannot allocate %d bytes\n", len);
		}
		break;
	case 'A':
		switch (input[1]) {
		case ' ':
			if (input[2] && input[3]==' ') {
				r_asm_set_pc (core->assembler, core->offset);
				eprintf ("modify (%c)=%s\n", input[2], input+4);
				len = r_asm_modify (core->assembler, core->block, input[2],
					r_num_math (core->num, input+4));
				eprintf ("len=%d\n", len);
				if (len>0) {
					r_core_write_at (core, core->offset, core->block, len);
					WSEEK (core, len);
				} else eprintf ("r_asm_modify = %d\n", len);
			} else eprintf ("Usage: wA [type] [value]\n");
			break;
		case '?':
		default:
			r_cons_printf ("|Usage: wA [type] [value]\n"
			"|Types:\n"
			"| r   raw write value\n"
			"| v   set value (taking care of current address)\n"
			"| d   destination register\n"
			"| 0   1st src register\n"
			"| 1   2nd src register\n"
			"|Example: wA r 0 # e800000000\n");
			break;
		}
		break;
	case 'c':
		switch (input[1]) {
		case 'i':
			r_io_cache_commit (core->io, 0, UT64_MAX);
			r_core_block_read (core, 0);
			break;
		case 'r':
			r_io_cache_reset (core->io, R_TRUE);
			/* Before loading the core block we have to make sure that if
			 * the cache wrote past the original EOF these changes are no
			 * longer displayed. */
			memset (core->block, 0xff, core->blocksize);
			r_core_block_read (core, 0);
			break;
		case '+':
			if (input[2]=='*') {
				//r_io_cache_reset (core->io, R_TRUE);
				eprintf ("TODO\n");
			} else if (input[2]==' ') {
				char *p = strchr (input+3, ' ');
				ut64 to, from = core->offset;
				if (p) {
					*p = 0;
					from = r_num_math (core->num, input+3);
					to = r_num_math (core->num, input+3);
					if (to<from) {
						eprintf ("Invalid range (from>to)\n");
						return 0;
					}
				} else {
					from = r_num_math (core->num, input+3);
					to = from + core->blocksize;
				}
				r_io_cache_commit (core->io, from, to);
			} else {
				eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset);
				r_io_cache_commit (core->io, core->offset, core->offset+1);
			}
			break;
		case '-':
			if (input[2]=='*') {
				r_io_cache_reset (core->io, R_TRUE);
			} else if (input[2]==' ') {
				char *p = strchr (input+3, ' ');
				ut64 to, from = core->offset;
				if (p) {
					*p = 0;
					from = r_num_math (core->num, input+3);
					to = r_num_math (core->num, input+3);
					if (to<from) {
						eprintf ("Invalid range (from>to)\n");
						return 0;
					}
				} else {
					from = r_num_math (core->num, input+3);
					to = from + core->blocksize;
				}
				r_io_cache_invalidate (core->io, from, to);
			} else {
				eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset);
				r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize);
			}
			/* See 'r' above. */
			memset (core->block, 0xff, core->blocksize);
			r_core_block_read (core, 0);
			break;
		case '?':
	{
                const char* help_msg[] = {
			"Usage:", "wc[ir+-*?]","  # NOTE: Uses io.cache=true",
			"wc","","list all write changes",
			"wc-"," [from] [to]","remove write op at curseek or given addr",
			"wc+"," [addr]","commit change from cache to io",
			"wc*","","\"\" in radare commands",
			"wcr","","reset all write changes in cache",
			"wci","","commit write cache",
                        NULL
                        };
                        r_core_cmd_help(core, help_msg);
        }
			break;
		case '*':
			r_io_cache_list (core->io, R_TRUE);
			break;
		case '\0':
			//if (!r_config_get_i (core->config, "io.cache"))
			//	eprintf ("[warning] e io.cache must be true\n");
			r_io_cache_list (core->io, R_FALSE);
			break;
		}
		break;
	case ' ':
		/* write string */
		len = r_str_unescape (str);
		r_core_write_at (core, core->offset, (const ut8*)str, len);
#if 0
		r_io_use_desc (core->io, core->file->desc);
		r_io_write_at (core->io, core->offset, (const ut8*)str, len);
#endif
		WSEEK (core, len);
		r_core_block_read (core, 0);
		break;
	case 't': // "wt"
		if (*str == '?' || *str == '\0') {
			eprintf ("Usage: wt[a] file [size]   write 'size' bytes in current block to file\n");
			free (ostr);
			return 0;
		} else {
			int append = 0;
			st64 sz = core->blocksize;
			if (*str=='a') { // "wta"
				append = 1;
				str++;
				if (str[0]==' ') {
					filename = str+1;
				} else {
					const char* prefix = r_config_get (core->config, "cfg.prefixdump");
					snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset);
					filename = _fn;
				}
			} else if (*str != ' ') {
				const char* prefix = r_config_get (core->config, "cfg.prefixdump");
				snprintf(_fn, sizeof(_fn), "%s.0x%08"PFMT64x, prefix, core->offset);
				filename = _fn;
			} else filename = str+1;
			tmp = strchr (str+1, ' ');
			if (tmp) {
				sz = (st64) r_num_math (core->num, tmp+1);
				if (!sz) {
					sz = core->blocksize;
				}
				*tmp = 0;
				if (sz<1) eprintf ("Invalid length\n");
				else r_core_dump (core, filename, core->offset, (ut64)sz, append);
			} else {
				if (!r_file_dump (filename, core->block, core->blocksize, append)) {
					sz = 0;
				} else sz = core->blocksize;
			}
			eprintf ("Dumped %"PFMT64d" bytes from 0x%08"PFMT64x" into %s\n",
				sz, core->offset, filename);
		}
		break;
	case 'f':
		arg = (const char *)(input+((input[1]==' ')?2:1));
		if (!strcmp (arg, "-")) {
			char *out = r_core_editor (core, NULL, NULL);
			if (out) {
				r_io_write_at (core->io, core->offset,
					(ut8*)out, strlen (out));
				free (out);
			}
		} else
		if ((buf = (ut8*) r_file_slurp (arg, &size))) {
			r_io_use_desc (core->io, core->file->desc);
			r_io_write_at (core->io, core->offset, buf, size);
			WSEEK (core, size);
			free (buf);
			r_core_block_read (core, 0);
		} else eprintf ("Cannot open file '%s'\n", arg);
		break;
	case 'F':
		arg = (const char *)(input+((input[1]==' ')?2:1));
		if (!strcmp (arg, "-")) {
			int len;
			ut8 *out;
			char *in = r_core_editor (core, NULL, NULL);
			if (in) {
				out = (ut8 *)strdup (in);
				if (out) {
					len = r_hex_str2bin (in, out);
					if (len>0)
						r_io_write_at (core->io, core->offset, out, len);
					free (out);
				}
				free (in);
			}
		} else
		if ((buf = r_file_slurp_hexpairs (arg, &size))) {
			r_io_use_desc (core->io, core->file->desc);
			r_io_write_at (core->io, core->offset, buf, size);
			WSEEK (core, size);
			free (buf);
			r_core_block_read (core, 0);
		} else eprintf ("Cannot open file '%s'\n", arg);
		break;
	case 'w':
		str++;
		len = (len-1)<<1;
		if (len>0) tmp = malloc (len+1);
		else tmp = NULL;
		if (tmp) {
			for (i=0; i<len; i++) {
				if (i%2) tmp[i] = 0;
				else tmp[i] = str[i>>1];
			}
			str = tmp;
			r_io_use_desc (core->io, core->file->desc);
			r_io_write_at (core->io, core->offset, (const ut8*)str, len);
			WSEEK (core, len);
			r_core_block_read (core, 0);
			free (tmp);
		} else eprintf ("Cannot malloc %d\n", len);
		break;
	case 'x':
		{
		int b, len = strlen (input);
		ut8 *buf = malloc (len+1);
		len = r_hex_str2bin (input+1, buf);
		if (len != 0) {
			if (len<0) len = -len+1;
			if (len<core->blocksize) {
				b = core->block[len]&0xf;
				b |= (buf[len]&0xf0);
			} else b = buf[len];
			buf[len] = b;
			r_core_write_at (core, core->offset, buf, len);
			WSEEK (core, len);
			r_core_block_read (core, 0);
		} else eprintf ("Error: invalid hexpair string\n");
		free (buf);
		}
		break;
	case 'a':
		switch (input[1]) {
		case 'o':
			if (input[2] == ' ')
				r_core_hack (core, input+3);
			else r_core_hack_help (core);
			break;
		case ' ':
		case '*':
			{ const char *file = input[1]=='*'? input+2: input+1;
			RAsmCode *acode;
			r_asm_set_pc (core->assembler, core->offset);
			acode = r_asm_massemble (core->assembler, file);
			if (acode) {
				if (input[1]=='*') {
					r_cons_printf ("wx %s\n", acode->buf_hex);
				} else {
					if (r_config_get_i (core->config, "scr.prompt"))
						eprintf ("Written %d bytes (%s) = wx %s\n", acode->len, input+2, acode->buf_hex);
					r_core_write_at (core, core->offset, acode->buf, acode->len);
					WSEEK (core, acode->len);
					r_core_block_read (core, 0);
				}
				r_asm_code_free (acode);
			}
			} break;
		case 'f':
			if ((input[2]==' '||input[2]=='*')) {
				const char *file = input[2]=='*'? input+4: input+3;
				RAsmCode *acode;
				r_asm_set_pc (core->assembler, core->offset);
				acode = r_asm_assemble_file (core->assembler, file);
				if (acode) {
					if (input[2]=='*') {
						r_cons_printf ("wx %s\n", acode->buf_hex);
					} else {
						if (r_config_get_i (core->config, "scr.prompt"))
						eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex);
						r_core_write_at (core, core->offset, acode->buf, acode->len);
						WSEEK (core, acode->len);
						r_core_block_read (core, 0);
					}
					r_asm_code_free (acode);
				} else eprintf ("Cannot assemble file\n");
			} else eprintf ("Wrong argument\n");
			break;
		default:
			r_cons_printf ("|Usage: wa[of*] [arg]\n"
				"| wa nop           : write nopcode using asm.arch and asm.bits\n"
				"| wa* mov eax, 33  : show 'wx' op with hexpair bytes of assembled opcode\n"
				"| \"wa nop;nop\"     : assemble more than one instruction (note the quotes)\n"
				"| waf foo.asm      : assemble file and write bytes\n"
				"| wao nop          : convert current opcode into nops\n"
				"| wao?             : show help for assembler operation on current opcode (hack)\n");
			break;
		}
		break;
	case 'b':
		{
		int len = strlen (input);
		ut8 *buf = malloc (len+1);
		if (buf) {
			len = r_hex_str2bin (input+1, buf);
			if (len > 0) {
				r_mem_copyloop (core->block, buf, core->blocksize, len);
				r_core_write_at (core, core->offset, core->block, core->blocksize);
				WSEEK (core, core->blocksize);
				r_core_block_read (core, 0);
			} else eprintf ("Wrong argument\n");
			free (buf);
		} else eprintf ("Cannot malloc %d\n", len+1);
		}
		break;
	case 'm':
		size = r_hex_str2bin (input+1, (ut8*)str);
		switch (input[1]) {
		case '\0':
			eprintf ("Current write mask: TODO\n");
			// TODO
			break;
		case '?':
			break;
		case '-':
			r_io_set_write_mask (core->io, 0, 0);
			eprintf ("Write mask disabled\n");
			break;
		case ' ':
			if (size>0) {
				r_io_use_desc (core->io, core->file->desc);
				r_io_set_write_mask (core->io, (const ut8*)str, size);
				WSEEK (core, size);
				eprintf ("Write mask set to '");
				for (i=0; i<size; i++)
					eprintf ("%02x", str[i]);
				eprintf ("'\n");
			} else eprintf ("Invalid string\n");
			break;
		}
		break;
	case 'v':
		cmd_write_value (core, input);
		break;
	case 'o':
		cmd_write_op (core, input);
		break;
	case 'd':
		if (input[1] && input[1]==' ') {
			char *arg, *inp = strdup (input+2);
			arg = strchr (inp, ' ');
			if (arg) {
				*arg = 0;
				ut64 addr = r_num_math (core->num, input+2);
				ut64 len = r_num_math (core->num, arg+1);
				ut8 *data = malloc (len);
				r_io_read_at (core->io, addr, data, len);
				r_io_write_at (core->io, core->offset, data, len);
				free (data);
			} else eprintf ("See wd?\n");
			free (inp);
		} else eprintf ("Usage: wd [source-offset] [length] @ [dest-offset]\n");
		break;
	case 's':
		if (str && *str && str[1]) {
			len = r_str_unescape (str+1);
			if (len>255) {
				eprintf ("Too large\n");
			} else {
				ut8 ulen = (ut8)len;
				r_core_write_at (core, core->offset, &ulen, 1);
				r_core_write_at (core, core->offset+1, (const ut8*)str+1, len);
				WSEEK (core, len);
				r_core_block_read (core, 0);
			}
		} else eprintf ("Too short.\n");
		break;
	default:
	case '?':
		if (core->oobi) {
			eprintf ("Writing oobi buffer!\n");
			r_io_use_desc (core->io, core->file->desc);
			r_io_write (core->io, core->oobi, core->oobi_len);
			WSEEK (core, core->oobi_len);
			r_core_block_read (core, 0);
		} else {
			r_core_cmd_help (core, help_msg);
		}
		break;
	}
Esempio n. 26
0
static void cmd_write_op (RCore *core, const char *input) {
	ut8 *buf;
  char *sequence_err = NULL;
	int len;
	const char* help_msg[] = {
		"Usage:","wo[asmdxoArl24]"," [hexpairs] @ addr[!bsize]",
		"wow"," [val]", "==  write looped value (alias for 'wb')",
		"woa"," [val]", "+=  addition (f.ex: woa 0102)",
		"wos"," [val]", "-=  substraction",
		"wom"," [val]", "*=  multiply",
		"wod"," [val]", "/=  divide",
		"woe"," [from-to] [step]","..  create sequence",
		"wox"," [val]","^=  xor  (f.ex: wox 0x90)",
		"woo"," [val]","|=  or",
		"woA"," [val]","&=  and",
		"woR","","random bytes (alias for 'wr $b')",
		"wor"," [val]", ">>= shift right",
		"wol"," [val]","<<= shift left",
		"wo2"," [val]","2=  2 byte endian swap",
		"wo4"," [val]", "4=  4 byte endian swap",
		"woD"," [len]","De Bruijn Pattern (syntax woD length @ addr)",
		"woO"," [len]", "De Bruijn Pattern Offset (syntax: woO value)",
		NULL
	};
	if (!input[0])
		return;
	switch (input[1]) {
	case 'a':
	case 's':
	case 'e':
	case 'A':
	case 'x':
	case 'r':
	case 'l':
	case 'm':
	case 'd':
	case 'o':
	case 'w':
		if (input[2]!=' ') {
			if (input[1]=='e') r_cons_printf ("Usage: 'woe from-to step'\n");
			else r_cons_printf ("Usage: 'wo%c 00 11 22'\n", input[1]);
			return;
		}
	case '2':
	case '4':
		if (input[2]){
			r_core_write_op (core, input+3, input[1]);
			r_core_block_read (core, 0);
		} else eprintf ("Missing argument\n");
		break;
	case 'R':
		r_core_cmd0 (core, "wr $b");
		break;
	case 'n':
		r_core_write_op (core, "ff", 'x');
		r_core_block_read (core, 0);
		break;
	case 'D':
        len = strtoul (input+2, &sequence_err, 0);
        if (*sequence_err) {
          printf ("Invalid length: %s\n", sequence_err);
          break;
        }
        if (len > 0) {
          buf = (ut8*)r_debruijn_pattern (len, 0, NULL); //debruijn_charset);
          if (buf) {
              r_core_write_at (core, core->offset, buf, len);
              free (buf);
          } else {
            eprintf ("Couldn't generate pattern of length %d\n", len);
          }
        }
        break;
	case 'O':
        len = strtoul (input+2, &sequence_err, 16);
        if (*sequence_err) {
          eprintf ("Invalid sequence: %s\n", sequence_err);
          break;
        }
		core->num->value = r_debruijn_offset (len, !core->assembler->big_endian);
		r_cons_printf ("%d\n", core->num->value);
		break;
	case '\0':
	case '?':
	default:
		r_core_cmd_help (core, help_msg);
		break;
	}
}
Esempio n. 27
0
static int cmd_type(void *data, const char *input) {
	RCore *core = (RCore*)data;

	switch (input[0]) {
	// t [typename] - show given type in C syntax
	case 's':
	{
		char *q, *p, *o, *e;
		p = o = strdup (input+1);
		for (;;) {
			q = strchr (p, ' ');
			if (q) *q = 0;
			if (!*p) {
				p++;
				continue;
			}
			e = strchr (p, '=');
			if (e) {
				*e = 0;
				r_anal_type_set (core->anal, core->offset,
					p, r_num_math (core->num, e+1));
			} else eprintf ("TODO: implement get\n");
			if (!q) break;
			p = q+1;
		}
		free (o);
	}
		break;
	case ' ':
	{
		char *fmt = r_anal_type_format (core->anal, input +1);
		if (fmt) {
			r_cons_printf ("pf %s\n", fmt);
			free (fmt);
		} else eprintf ("Cannot find '%s' type\n", input+1);
	}
		break;
#if 0
	// t* - list all types in 'pf' syntax
	case '*':
		r_anal_type_list (core->anal, R_ANAL_TYPE_ANY, 1);
		break;
#endif
	case 0:
		// TODO: use r_cons here
		//sdb_list (core->anal->sdb_types);
		sdb_foreach (core->anal->sdb_types, sdbforcb, core);
		break;
	case 'o':
		if (input[1] == ' ') {
			const char *filename = input + 2;
			if (!strcmp (filename, "-")) {
				char *out, *tmp;
				tmp = r_core_editor (core, "");
				if (tmp) {
					out = r_parse_c_string (tmp);
					if (out) {
						r_cons_strcat (out);
						sdb_query_lines (core->anal->sdb_types, out);
						free (out);
					}
					free (tmp);
				}
			} else {
				char *out = r_parse_c_file (filename);
				if (out) {
					r_cons_strcat (out);
					sdb_query_lines (core->anal->sdb_types, out);
					free (out);
				}
				//r_anal_type_loadfile (core->anal, filename);
			}
		}
		break;
	// td - parse string with cparse engine and load types from it
	case 'd':
		if (input[1] == '?') {
			const char * help_message[] = {
				"Usage:", "td[...]", "",
				"td", "[string]", "Load types from string",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else
		if (input[1] == '-') {
			const char *arg = strchr (input+1, ' ');
			if (arg) arg++; else arg = input+2;
			r_anal_type_del (core->anal, arg);
		} else
		if (input[1] == ' ') {
			char tmp[256];
			snprintf (tmp, sizeof (tmp), "%s;", input+2);
			//const char *string = input + 2;
			//r_anal_str_to_type (core->anal, string);
			char *out = r_parse_c_string (tmp);
			if (out) {
				r_cons_strcat (out);
				sdb_query_lines (core->anal->sdb_types, out);
				free (out);
			}
		} else {
			eprintf ("Invalid use of td. See td? for help\n");
		}
		break;
	// tl - link a type to an address
	case 'l':
		if (input[1]=='?') {
			const char * help_message[] = {
				"Usage: tl", " [typename|addr] ([addr])@[addr|function]", "",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else if (input[1]) {
			ut64 addr = r_num_math (core->num, input+2);
			char *ptr = strchr (input + 2, ' ');
			if (ptr) {
				addr = r_num_math (core->num, ptr + 1);
				*ptr = '\0';
			} else addr = core->offset;
			r_anal_type_link (core->anal, input+2, addr);
		} else {
			r_core_cmd0 (core, "t~^link");
		}
		break;
	case '-':
		if (input[1] == '?') {
			const char * help_message[] = {
				"Usage: t-", " <type>", "Delete type by its name",
				NULL
			 };

			r_core_cmd_help(core, help_message);
		} else
		if (input[1]=='*') {
			eprintf ("TODO\n");
		} else {
			const char *name = input + 1;
			if (*name==' ') name++;
			if (*name) {
				r_anal_type_del (core->anal, name);
			} else eprintf ("Invalid use of t- . See t-? for help.\n");
		}
		break;
	// tv - get/set type value linked to a given address
	case 'f':
		 {
			ut64 addr;
			char *fmt, key[128];
			const char *type;
			if (input[1]) {
				addr = r_num_math (core->num, input+1);
			} else addr = core->offset;
			snprintf (key, sizeof (key), "link.%"PFMT64x, addr);
			type = sdb_const_get (core->anal->sdb_types, key, 0);
			if (type) {
				fmt = r_anal_type_format (core->anal, type);
				r_cons_printf ("struct %s {\n", type);
				if (fmt) {
					r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, addr);
					free (fmt);
				}// else eprintf ("Cannot find '%s' type\n", input+1);
				r_cons_printf ("}\n");
			}
		 }
		break;
	case '?':
		if (input[1]) {
			sdb_query (core->anal->sdb_types, input+1);
		} else show_help(core);

		break;
	}
	return R_TRUE;
}
Esempio n. 28
0
static int cmd_seek(void *data, const char *input) {
	RCore *core = (RCore *) data;
	char *cmd, *p;
	ut64 off;

	if (!*input) {
		r_cons_printf ("0x%"PFMT64x "\n", core->offset);
		return 0;
	}
	char *ptr;
	if ((ptr = strstr (input, "+.")) != NULL) {
		char *dup = strdup (input);
		dup[ptr - input] = '\x00';
		off = r_num_math (core->num, dup + 1);
		core->offset = off;
		free (dup);
	}
	const char *inputnum = strchr (input, ' ');
	{
		const char *u_num = inputnum? inputnum + 1: input + 1;
		off = r_num_math (core->num, u_num);
		if (*u_num == '-') {
			off = -off;
		}
	}
	int sign = 1;
	if (input[0] == ' ') {
		switch (input[1]) {
		case '-':
			sign = -1;
			/* pass thru */
		case '+':
			input++;
			break;
		}
	}
	bool silent = false;
	if (*input == 's') {
		silent = true;
		input++;
		if (*input == '?') {
			const char *help_message[] = {
				"Usage: ss", "", " # Seek silently (not recorded in the seek history)",
				"s?", "", "Works with all s subcommands",
				NULL
			};
			r_core_cmd_help (core, help_message);
			return 0;
		}
	}

	switch (*input) {
	case 'r':
		if (input[1] && input[2]) {
			seek_to_register (core, input + 2, silent);
		} else {
			eprintf ("|Usage| 'sr PC' seek to program counter register\n");
		}
		break;
	case 'C':
		if (input[1] == '*') {
			r_core_cmd0 (core, "C*~^\"CC");
		} else if (input[1] == ' ') {
			typedef struct {
				ut64 addr;
				char *str;
			} MetaCallback;
			int count = 0;
			MetaCallback cb = {
				0, NULL
			};
			ut64 addr;
			char key[128];
			const char *val, *comma;
			char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0);
			char *str, *next, *cur = list;
			if (list) {
				for (;;) {
					cur = sdb_anext (cur, &next);
					addr = sdb_atoi (cur);
					snprintf (key, sizeof (key) - 1, "meta.C.0x%"PFMT64x, addr);
					val = sdb_const_get (core->anal->sdb_meta, key, 0);
					if (val) {
						comma = strchr (val, ',');
						if (comma) {
							str = (char *) sdb_decode (comma + 1, 0);
							if (strstr (str, input + 2)) {
								r_cons_printf ("0x%08"PFMT64x "  %s\n", addr, str);
								count++;
								cb.addr = addr;
								free (cb.str);
								cb.str = str;
							} else {
								free (str);
							}
						}
					} else {
						eprintf ("sdb_const_get key not found '%s'\n", key);
					}
					if (!next) {
						break;
					}
					cur = next;
				}
			}

			switch (count) {
			case 0:
				eprintf ("No matching comments\n");
				break;
			case 1:
				off = cb.addr;
				if (!silent) {
					r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print));
				}
				r_core_seek (core, off, 1);
				r_core_block_read (core);
				break;
			default:
				eprintf ("Too many results\n");
				break;
			}
			free (cb.str);
		} else {
			const char *help_msg[] = {
				"Usage:", "sC", "Comment grep",
				"sC", "*", "List all comments",
				"sC", " str", "Seek to the first comment matching 'str'",
				NULL
			};
			r_core_cmd_help (core, help_msg);
		}
		break;
	case ' ':
		if (!silent) {
			r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print));
		}
		r_core_seek (core, off * sign, 1);
		r_core_block_read (core);
		break;
	case '/':
	{
		const char *pfx = r_config_get (core->config, "search.prefix");
		ut64 from = r_config_get_i (core->config, "search.from");
// kwidx cfg var is ignored
		int kwidx = core->search->n_kws; // (int)r_config_get_i (core->config, "search.kwidx")-1;
		if (kwidx < 0) {
			kwidx = 0;
		}
		switch (input[1]) {
		case ' ':
		case 'v':
		case 'V':
		case 'w':
		case 'W':
		case 'z':
		case 'm':
		case 'c':
		case 'A':
		case 'e':
		case 'E':
		case 'i':
		case 'R':
		case 'r':
		case '/':
		case 'x':
			r_config_set_i (core->config, "search.from", core->offset + 1);
			r_config_set_i (core->config, "search.count", 1);
			r_core_cmdf (core, "s+1; %s; s-1; s %s%d_0; f-%s%d_0",
				input, pfx, kwidx, pfx, kwidx, pfx, kwidx);
			r_config_set_i (core->config, "search.from", from);
			r_config_set_i (core->config, "search.count", 0);
			break;
		case '?':
			eprintf ("Usage: s/.. arg.\n");
			r_cons_printf ("/?\n");
			break;
		default:
			eprintf ("unknown search method\n");
			break;
		}
	}
	break;
	case '.':
		for (input++; *input == '.'; input++) {
			;
		}
		r_core_seek_base (core, input);
		break;
	case 'j':  // sj
		{
			RList /*<ut64 *>*/ *addrs = r_list_newf (free);
			RList /*<char *>*/ *names = r_list_newf (free);
			RList *list = r_io_sundo_list (core->io, '!');
			ut64 lsz = 0;
			ut64 i;
			RListIter *iter;
			RIOUndos *undo;
			if (list) {
				r_list_foreach (list, iter, undo) {
					char *name = NULL;

					core->flags->space_strict = true;
					RFlagItem *f = r_flag_get_at (core->flags, undo->off, true);
					core->flags->space_strict = false;
					if (f) {
						if (f->offset != undo->off) {
							name = r_str_newf ("%s + %d\n", f->name,
									(int)(undo->off- f->offset));
						} else {
							name = strdup (f->name);
						}
					}
					if (!name) {
						name = strdup ("");
					}
					ut64 *val = malloc (sizeof (ut64));
					if (!val) {
						free (name);
						break;
					}
					*val = undo->off;
					r_list_append (addrs, val);
					r_list_append (names, strdup (name));
					lsz++;
					free (name);
				}
				r_list_free (list);
			}
			r_cons_printf ("[");
			for (i = 0; i < lsz; ++i) {
				ut64 *addr = r_list_get_n (addrs, i);
				const char *name = r_list_get_n (names, i);
				// XXX(should the "name" field be optional? That might make
				// a bit more sense.
				r_cons_printf ("{\"offset\":%"PFMT64d",\"symbol\":\"%s\"}", *addr, name);
				if (i != lsz - 1) {
					r_cons_printf (",");
				}
			}
			r_cons_printf ("]\n");
			r_list_free (addrs);
			r_list_free (names);
		}
		break;
	case '*':
	case '=':
	case '!':
		{
			RList *list = r_io_sundo_list (core->io, input[0]);
			RListIter *iter;
			RIOUndos *undo;
			if (list) {
				r_list_foreach (list, iter, undo) {
					char *name = NULL;

					core->flags->space_strict = true;
					RFlagItem *f = r_flag_get_at (core->flags, undo->off, true);
					core->flags->space_strict = false;
					if (f) {
						if (f->offset != undo->off) {
							name = r_str_newf ("%s + %d\n", f->name,
									(int)(undo->off- f->offset));
						} else {
							name = strdup (f->name);
						}
					}
					if (!name) {
						name = strdup ("");
					}
					r_cons_printf ("0x%"PFMT64x" %s\n", undo->off, name);
					free (name);
				}
				r_list_free (list);
			}
		}
Esempio n. 29
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]==' ' && 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_printf ("%s\n", 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_printf ("%s\n", p);
				free (p);
			} else {
				char **e = r_sys_get_environ ();
				while (e && *e) {
					r_cons_printf ("%s\n", *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
		return cmd_quit (data, "");
	case 'j':
		r_config_list (core->config, NULL, 'j');
		break;
	case '\0':
		r_config_list (core->config, NULL, 0);
		break;
	case 'c':
		switch (input[1]) {
		case 'h': // echo
			if (( p = strchr (input, ' ') )) {
				r_cons_strcat (p+1);
				r_cons_newline ();
			}
			break;
		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",
			"ecs","","show a colorful palette",
			"ecj","","show palette in JSON",
			"ecc","","show palette in CSS",
			"eco"," dark|white","load white color scheme template",
			"ecn","","load next color theme",
			"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] == ' ') {
				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 (!r_core_cmd_file (core, home)) {
					if (r_core_cmd_file (core, path)) {
						//curtheme = r_str_dup (curtheme, path);
						curtheme = r_str_dup (curtheme, input + 3);
					} else {
						if (r_core_cmd_file (core, input+3)) {
							curtheme = r_str_dup (curtheme, input + 3);
						} else {
							eprintf ("eco: cannot open colorscheme profile (%s)\n", path);
							failed = true;
						}
					}
				}
				free (home);
			} else {
				nextpal (core, 'l');
			}
			break;
		case 's': r_cons_pal_show (); break;
		case '*': r_cons_pal_list (1); break;
		case 'j': r_cons_pal_list ('j'); break;
		case 'c': r_cons_pal_list ('c'); break;
		case '\0': r_cons_pal_list (0); break;
		case 'r': // "ecr"
			r_cons_pal_random ();
			break;
		case 'n': // "ecn"
			nextpal (core, 'n');
			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 '-':
		r_core_config_init (core);
		//eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
		break;
	case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); 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:{
			const char* help_msg[] = {
			"Usage:", "e[?] [var[=value]]", "Evaluable vars",
			"e","?asm.bytes", "show description",
			"e", "??", "list config vars with description",
			"e", "", "list config vars",
			"e-", "", "reset config vars",
			"e*", "", "dump config vars in r commands",
			"e!", "a", "invert the boolean value of 'a' var",
			"ee", "var", "open editor to change the value of var",
			"er", " [key]", "set config key as readonly. no way back",
			"ec", " [k] [color]", "set color for given key (prompt, offset, ...)",
			"et", " [key]", "show type of given config variable",
			"e", " a", "get value of var 'a'",
			"e", " a=b", "set var 'a' the 'b' value",
			"env", " [k[=v]]", "get/set environment variable",
			NULL};
			r_core_cmd_help (core, help_msg);
			}
		}
		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;
}
Esempio n. 30
0
static int cmd_type(void *data, const char *input) {
	RCore *core = (RCore *)data;

	switch (input[0]) {
	// t [typename] - show given type in C syntax
	case 'k':
		if (input[1] == ' ') {
			sdb_query (core->anal->sdb_types, input + 2);
		} else sdb_query (core->anal->sdb_types, "*");
		break;
	case 's': {
		char *q, *p, *o, *e;
		p = o = strdup (input + 1);
		for (;;) {
			if (*p == '\0') {
				eprintf ("Usage: ts <k>=<v> Set fields at curseek linked type\n");
				break;
			}
			q = strchr (p, ' ');
			if (q) *q = 0;
			if (!*p) {
				p++;
				continue;
			}
			e = strchr (p, '=');
			if (e) {
				*e = 0;
				r_anal_type_set (core->anal, core->offset,
						p, r_num_math (core->num, e + 1));
			} else eprintf ("TODO: implement get\n");
			if (!q) break;
			p = q + 1;
		}
		free (o);
	} break;
	case 'b': {
		char *p, *s = (strlen (input) > 1)? strdup (input + 2): NULL;
		const char *isenum;
		p = s? strchr (s, ' '): NULL;
		if (p) {
			*p++ = 0;
			// dupp in core.c (see getbitfield())
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strcmp (isenum, "enum")) {
				*--p = '.';
				const char *res = sdb_const_get (core->anal->sdb_types, s, 0);
				if (res)
					r_cons_printf ("%s\n", res);
				else eprintf ("Invalid enum member\n");
			} else {
				eprintf ("This is not an enum\n");
			}
		} else {
			eprintf ("Missing value\n");
		}
		free (s);
	} break;
	case 'e': {
		if (!input[1]) {
			char *name = NULL;
			SdbKv *kv;
			SdbListIter *iter;
			SdbList *l = sdb_foreach_list (core->anal->sdb_types);
			ls_foreach (l, iter, kv) {
				if (!strcmp (kv->value, "enum")) {
					if (!name || strcmp (kv->value, name)) {
						free (name);
						name = strdup (kv->key);
						r_cons_printf ("%s\n", name);
					}
				}
			}
			free (name);
			ls_free (l);
			break;
		}
		char *p, *s = strdup (input + 2);
		const char *isenum;
		p = strchr (s, ' ');
		if (p) {
			*p++ = 0;
			isenum = sdb_const_get (core->anal->sdb_types, s, 0);
			if (isenum && !strcmp (isenum, "enum")) {
				const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p));
				const char *res = sdb_const_get (core->anal->sdb_types, q, 0);
				if (res)
					r_cons_printf ("%s\n", res);
			} else {
				eprintf ("This is not an enum\n");
			}
		} else {
			//eprintf ("Missing value\n");
			r_core_cmdf (core, "t~&%s,=0x", s);
		}
		free (s);
	} break;
	case ' ': {
		const char *isenum = sdb_const_get (core->anal->sdb_types, input + 1, 0);
		if (isenum && !strcmp (isenum, "enum")) {
			eprintf ("IS ENUM! \n");
		} else {
			char *fmt = r_anal_type_format (core->anal, input + 1);
			if (fmt) {
				r_cons_printf ("pf %s\n", fmt);
				free (fmt);
			} else eprintf ("Cannot find '%s' type\n", input + 1);
		}
	} break;
	// t* - list all types in 'pf' syntax
	case '*':
		sdb_foreach (core->anal->sdb_types, typelist, core);
		break;
	case 0:
		sdb_foreach (core->anal->sdb_types, sdbforcb, core);
		break;
	case 'o':
		if (!r_sandbox_enable (0)) {
			if (input[1] == ' ') {
				const char *filename = input + 2;
				char *homefile = NULL;
				if (*filename == '~') {
					if (filename[1] && filename[2]) {
						homefile = r_str_home (filename + 2);
						filename = homefile;
					}
				}
				if (!strcmp (filename, "-")) {
					char *out, *tmp;
					tmp = r_core_editor (core, NULL, "");
					if (tmp) {
						out = r_parse_c_string (tmp);
						if (out) {
							//		r_cons_strcat (out);
							sdb_query_lines (core->anal->sdb_types, out);
							free (out);
						}
						free (tmp);
					}
				} else {
					char *out = r_parse_c_file (filename);
					if (out) {
						//r_cons_strcat (out);
						sdb_query_lines (core->anal->sdb_types, out);
						free (out);
					}
					//r_anal_type_loadfile (core->anal, filename);
				}
				free (homefile);
			}
		} else {
			eprintf ("Sandbox: system call disabled\n");
		}
		break;
	// td - parse string with cparse engine and load types from it
	case 'd':
		if (input[1] == '?') {
			const char *help_message[] = {
				"Usage:", "\"td [...]\"", "",
				"td", "[string]", "Load types from string",
				NULL };
			r_core_cmd_help (core, help_message);
			r_cons_printf ("Note: The td command should be put between double quotes\n"
				"Example: \" td struct foo {int bar;int cow};\""
				"\nt");

		} else if (input[1] == ' ') {
			char tmp[8192];
			snprintf (tmp, sizeof (tmp) - 1, "%s;", input + 2);
			//const char *string = input + 2;
			//r_anal_str_to_type (core->anal, string);
			char *out = r_parse_c_string (tmp);
			if (out) {
				//r_cons_strcat (out);
				sdb_query_lines (core->anal->sdb_types, out);
				free (out);
			}
		} else {
			eprintf ("Invalid use of td. See td? for help\n");
		}
		break;
	// tl - link a type to an address
	case 'l':
		if (input[1] == '?') {
			const char *help_message[] = {
				"Usage: tl", " [typename|addr] ([addr])@[addr|function]", "",
				NULL };

			r_core_cmd_help (core, help_message);
		} else if (input[1]) {
			ut64 addr = r_num_math (core->num, input + 2);
			char *ptr = strchr (input + 2, ' ');
			if (ptr) {
				addr = r_num_math (core->num, ptr + 1);
				*ptr = '\0';
			} else addr = core->offset;
			r_anal_type_link (core->anal, input + 2, addr);
		} else {
			r_core_cmd0 (core, "t~^link");
		}
		break;
	case '-':
		if (input[1] == '?') {
			const char *help_message[] = {
				"Usage: t-", " <type>", "Delete type by its name",
				NULL };

			r_core_cmd_help (core, help_message);
		} else if (input[1] == '*') {
			sdb_foreach (core->anal->sdb_types, sdbdelete, core);
		} else {
			const char *name = input + 1;
			while (IS_WHITESPACE (*name)) name++;
			if (*name) {
				SdbKv *kv;
				SdbListIter *iter;
				int tmp_len = strlen (name);
				char *tmp = malloc (tmp_len + 2);
				r_anal_type_del (core->anal, name);
				if (tmp) {
					snprintf (tmp, tmp_len + 1, "%s.", name);
					SdbList *l = sdb_foreach_list (core->anal->sdb_types);
					ls_foreach (l, iter, kv) {
						if (!strncmp (kv->key, tmp, tmp_len - 1))
							r_anal_type_del (core->anal, kv->key);
					}
					free (tmp);
				}
			} else eprintf ("Invalid use of t- . See t-? for help.\n");
		}