char* test_r_list_del_n(void) {
	RList* list = r_list_new ();
	intptr_t test1 = 0x12345;
	intptr_t test2 = 0x88888;
	r_list_append (list, (void*)test1);
	r_list_append (list, (void*)test2);
	snprintf (buf, 1024, "error, expected size 2, got %d\n", (int)r_list_length (list));
	mu_assert(buf, r_list_length (list) == 2);
	r_list_del_n (list, 0);
	mu_assert("error, first value not 0x88888",
			(intptr_t)0x88888 == (intptr_t)r_list_pop (list));
	return NULL;
}
Beispiel #2
0
R_API void r_vlog(const char *funcname, const char *filename,
	ut32 lineno, RLogLevel level, const char *tag, const char *fmtstr, va_list args) {
	va_list args_copy;
	va_copy (args_copy, args);

	if (level < cfg_loglvl && level < cfg_logtraplvl) {
		// Don't print if output level is lower than current level
		// Don't ignore fatal/trap errors
		va_end (args_copy);
		return;
	}

	// TODO: Colors

	// Build output string with src info, and formatted output
	char output_buf[LOG_OUTPUTBUF_SIZE] = ""; // Big buffer for building the output string
	if (!tag) {
		tag = R_BETWEEN (0, level, R_ARRAY_SIZE (level_tags) - 1)? level_tags[level]: "";
	}
	int offset = snprintf (output_buf, LOG_OUTPUTBUF_SIZE, "%s: ", tag);
	if (cfg_logsrcinfo) {
		offset += snprintf (output_buf + offset, LOG_OUTPUTBUF_SIZE - offset, "%s in %s:%i: ", funcname, filename, lineno);
	}
	vsnprintf (output_buf + offset, LOG_OUTPUTBUF_SIZE - offset, fmtstr, args);

	// Actually print out the string with our callbacks
	if (log_cbs && r_list_length (log_cbs) > 0) {
		RListIter *it;
		RLogCallback cb;

		r_list_foreach (log_cbs, it, cb) {
			cb (output_buf, funcname, filename, lineno, level, NULL, fmtstr, args_copy);
		}
bool test_r_list_size(void) {
	// Test that r_list adding and deleting works correctly.
	int i;
	RList* list = r_list_new ();
	intptr_t test = 0x101010;
	// Add 100 items.
	for (i = 0; i < 100; ++i) {
		r_list_append (list, (void*)test);
		mu_assert_eq (r_list_length (list), i + 1, "r_list_length failed on append");
	}
	// Delete 50 of them.
	for (i = 0; i < 50; ++i) {
		(void)r_list_pop (list);
		mu_assert_eq(99 - i, r_list_length (list), "r_list_length failed on pop");
	}
	// Purge the list.
	r_list_purge (list);
	mu_assert_eq(0, r_list_length (list), "r_list_length failed on purged list");
	r_list_free (list);
	mu_end;
}
char* test_r_list_join(void) {
	RList* list1 = r_list_new ();
	RList* list2 = r_list_new ();
	intptr_t test1 = 0x12345;
	intptr_t test2 = 0x88888;
	r_list_append (list1, (void*)test1);
	r_list_append (list2, (void*)test2);
	mu_assert("r_list_join returned non-success",
			r_list_join (list1, list2) == 1);
	mu_assert("r_list_join two single element lists result length is 1",
			r_list_length (list1) == 2);
	return NULL;
}
Beispiel #5
0
// (in,out)[code,data]
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 addr) {
	RList *list = r_list_new ();
	list->free = NULL; // XXX
	r_anal_xrefs_from (anal, list, "xref", "code", addr);
	r_anal_xrefs_from (anal, list, "xref", "data", addr);
	r_anal_xrefs_from (anal, list, "ref", "code", addr);
	r_anal_xrefs_from (anal, list, "ref", "data", addr);
	if (r_list_length (list)<1) {
		r_list_free (list);
		list = NULL;
	}

	return list;
}
bool test_r_list_join(void) {
	RList* list1 = r_list_new ();
	RList* list2 = r_list_new ();
	intptr_t test1 = 0x12345;
	intptr_t test2 = 0x88888;
	r_list_append (list1, (void*)test1);
	r_list_append (list2, (void*)test2);
	int joined = r_list_join (list1, list2);
	mu_assert_eq(joined, 1, "r_list_join of two lists");
	mu_assert_eq(r_list_length (list1), 2, "r_list_join two single element lists result length is 1");
	r_list_free (list1);
	r_list_free (list2);
	mu_end;
}
Beispiel #7
0
static pyc_object *get_ref_object(RBuffer *buffer) {
	pyc_object *ret;
	pyc_object *obj;
	bool error = false;
	ut32 index = get_ut32 (buffer, &error);
	if (error || index >= r_list_length (refs))
		return NULL;
	obj = r_list_get_n (refs, index);
	if (!obj)
		return NULL;
	ret = copy_object (obj);
	if (!ret)
		free (obj);
	return ret;
}
bool test_r_list_del_n(void) {
	RList* list = r_list_new ();
	intptr_t test1 = 0x12345;
	intptr_t test2 = 0x88888;
	r_list_append (list, (void*)test1);
	r_list_append (list, (void*)test2);
	mu_assert_eq (r_list_length (list), 2,
			"list is of length 2 when adding 2 values");
	r_list_del_n (list, 0);
	int top1 = (intptr_t)r_list_pop (list);
	mu_assert_eq(top1, 0x88888,
			"error, first value not 0x88888");
	r_list_free (list);
	mu_end;
}
char* test_r_list_size(void) {
	// Test that r_list adding and deleting works correctly.
	int i;
	RList* list = r_list_new ();
	intptr_t test = 0x101010;
	// Add 100 items.
	for (i = 0; i < 100; ++i) {
		r_list_append (list, (void*)test);
		snprintf(buf, 1024, "error, append gave wrong length. actual %d, expected %d",
				r_list_length (list), i + 1);
		mu_assert(buf, i + 1 == r_list_length (list));
	}
	// Delete 50 of them.
	for (i = 0; i < 50; ++i) {
		intptr_t val = (intptr_t)r_list_pop (list);
		snprintf(buf, 1024, "error, pop gave wrong length. actual: %d, expected %d",
				r_list_length (list), 99 - i);
		mu_assert(buf, 99 - i == r_list_length (list));
	}
	// Purge the list.
	r_list_purge (list);
	mu_assert("error, purge didn't clear list", 0 == r_list_length (list));
	return NULL;
}
Beispiel #10
0
R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
	RList *list = r_list_new ();
	if (!list) {
		return NULL;
	}
	list->free = NULL; // XXX
	r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, to);
	r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, to);
	r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, to);
	r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, to);
	r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, to);
	if (r_list_length (list)<1) {
		r_list_free (list);
		list = NULL;
	}
	return list;
}
Beispiel #11
0
/* Compute the len and the starting address
 * when disassembling `nb` opcodes backward. */
R_API ut32 r_core_asm_bwdis_len (RCore* core, int* instr_len, ut64* start_addr, ut32 nb) {
	ut32 instr_run = 0;
	RCoreAsmHit *hit;
	RListIter *iter = NULL;
	RList* hits = r_core_asm_bwdisassemble (core, core->offset, nb, core->blocksize);
	if (instr_len)
		*instr_len = 0;
	if (hits && r_list_length (hits) > 0) {
		hit = r_list_get_bottom (hits);
		if (start_addr)
			*start_addr = hit->addr;
		r_list_foreach (hits, iter, hit)
			instr_run += hit->len;
		if (instr_len)
			*instr_len = instr_run;
	}
	r_list_free (hits);
	return instr_run;
}
Beispiel #12
0
int omap_remap(void *stream, int address)
{
	SOmapStream *omap_stream = (SOmapStream *) stream;
	SOmapEntry *omap_entry = 0;
	RListIter *it = 0;
	int i = 0;
	int pos = 0;
	int len = 0;

	if (!omap_stream) {
		return address;
	}

	len = r_list_length(omap_stream->omap_entries);

	if (omap_stream->froms == 0) {
		omap_stream->froms = (unsigned int *) malloc(4 * len);
		it = r_list_iterator(omap_stream->omap_entries);
		while (r_list_iter_next(it)) {
			omap_entry = (SOmapEntry *) r_list_iter_get(it);
			omap_stream->froms[i] = omap_entry->from;
			i++;
		}
	}

	// mb (len -1) ???
	pos = binary_search(omap_stream->froms, address, 0, (len));

	if (omap_stream->froms[pos] != address) {
		pos -= 1;
	}

	omap_entry = (SOmapEntry *) r_list_get_n(omap_stream->omap_entries, pos);
	if (!omap_entry) {
		return -1;
	}
	if (omap_entry->to == 0) {
		return omap_entry->to;
	} else {
		return omap_entry->to + (address - omap_entry->from);
	}
}
Beispiel #13
0
/* Compute the len and the starting address
 * when disassembling `nb` opcodes backward. */
R_API ut32 r_core_asm_bwdis_len(RCore* core, int* instr_len, ut64* start_addr, ut32 nb) {
	ut32 instr_run = 0;
	RCoreAsmHit *hit;
	RListIter *iter = NULL;
	// TODO if length of nb instructions is larger than blocksize
	RList* hits = r_core_asm_bwdisassemble (core, core->offset, nb, core->blocksize);
	if (instr_len) {
		*instr_len = 0;
	}
	if (hits && r_list_length (hits) > 0) {
		hit = r_list_get_bottom (hits);
		if (start_addr) {
			*start_addr = hit->addr;
		}
		r_list_foreach (hits, iter, hit) {
			instr_run += hit->len;
		}
		if (instr_len) {
			*instr_len = instr_run;
		}
	}
Beispiel #14
0
static RList *r_core_asm_back_disassemble (RCore *core, ut64 addr, int len, ut64 max_hit_count, ut8 disassmble_each_addr, ut32 extra_padding) {
	RList *hits;;
	RAsmOp op;
	ut8 *buf = NULL;
	ut8 max_invalid_b4_exit = 4,
		last_num_invalid = 0;
	int current_instr_len = 0;
	ut64 current_instr_addr = addr,
		current_buf_pos = 0,
		next_buf_pos = len;

	RCoreAsmHit dummy_value;
	ut32 hit_count = 0;

	if (disassmble_each_addr){
		return r_core_asm_back_disassemble_all(core, addr, len, max_hit_count, extra_padding+1);
	}

	hits = r_core_asm_hit_list_new ();
	buf = malloc (len + extra_padding);

	if (!hits || !buf ){
		if (hits) {
			r_list_purge (hits);
			free (hits);
		}
		free (buf);
		return NULL;
	}

	if (r_io_read_at (core->io, (addr + extra_padding)-len, buf, len+extra_padding) != len+extra_padding) {
		r_list_purge (hits);
		free (hits);
		free (buf);
		return NULL;
	}

	//
	// XXX - This is a heavy handed approach without a
	// 		an appropriate btree or hash table for storing
	//	 hits, because are using:
	//			1) Sorted RList with many inserts and searches
	//			2) Pruning hits to find the most optimal disassembly

	// greedy approach
	// 1) Consume previous bytes
	// 1a) Instruction is invalid (incr current_instr_addr)
	// 1b) Disasm is perfect
	// 1c) Disasm is underlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) short some bytes)
	// 1d) Disasm is overlap (disasm(current_instr_addr, next_instr_addr - current_instr_addr) over some bytes)

	memset (&dummy_value, 0, sizeof (RCoreAsmHit));
	// disassemble instructions previous to current address, extra_padding can move the location of addr
	// so we need to account for that with current_buf_pos
	current_buf_pos = len - extra_padding - 1;
	next_buf_pos = len + extra_padding - 1;
	current_instr_addr = addr-1;
	do {
		if (r_cons_singleton ()->breaked) break;
		// reset assembler
		r_asm_set_pc (core->assembler, current_instr_addr);
		current_instr_len = next_buf_pos - current_buf_pos;
		current_instr_len = r_asm_disassemble (core->assembler, &op, buf+current_buf_pos, current_instr_len);

		IFDBG {
			ut32 byte_cnt =  current_instr_len ? current_instr_len : 1;
			eprintf("current_instr_addr: 0x%"PFMT64x", current_buf_pos: 0x%"PFMT64x", current_instr_len: %d \n", current_instr_addr, current_buf_pos, current_instr_len);

			ut8 *hex_str = (ut8*)r_hex_bin2strdup(buf+current_buf_pos, byte_cnt);
			eprintf("==== current_instr_bytes: %s ",hex_str);

			if (current_instr_len > 0)
				eprintf("op.buf_asm: %s\n", op.buf_asm);
			else
				eprintf("op.buf_asm: <invalid>\n");

			free(hex_str);
		}

		// disassembly invalid
		if (current_instr_len == 0 || strstr (op.buf_asm, "invalid")) {
			if (current_instr_len == 0) current_instr_len = 1;
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, /* is_valid */ false);
			hit_count ++;
			last_num_invalid ++;
		// disassembly perfect
		} else if (current_buf_pos + current_instr_len == next_buf_pos) {
			// i think this may be the only case where an invalid instruction will be
			// added because handle_forward_disassemble and handle_disassembly_overlap
			// are only called in cases where a valid instruction has been found.
			// and they are lazy, since they purge the hit list
			ut32 purge_results = 0;
			ut8 is_valid = true;
			IFDBG eprintf(" handling underlap case: current_instr_addr: 0x%"PFMT64x".\n", current_instr_addr);
			purge_results =  prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true);
			if (purge_results) {
				handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr);
				hit_count = r_list_length(hits);
			}
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid);
			//handle_forward_disassemble(core, hits, buf, len, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr/*end_addr*/);
			hit_count ++;
			next_buf_pos = current_buf_pos;
			last_num_invalid = 0;
		// disassembly underlap
		} else if (current_buf_pos + current_instr_len < next_buf_pos) {
			ut32 purge_results = 0;
			ut8 is_valid = true;
			purge_results =  prune_hits_in_addr_range(hits, current_instr_addr, current_instr_len, /* is_valid */ true);
			add_hit_to_sorted_hits(hits, current_instr_addr, current_instr_len, is_valid);

			if (hit_count < purge_results ) hit_count = 0; // WTF??
			else hit_count -= purge_results;

			next_buf_pos = current_buf_pos;
			handle_forward_disassemble(core, hits, buf, len - extra_padding, current_buf_pos+current_instr_len, current_instr_addr+current_instr_len, addr);
			hit_count = r_list_length(hits);
			last_num_invalid = 0;
		// disassembly overlap
		} else if (current_buf_pos + current_instr_len > next_buf_pos) {
			//ut64 value = handle_disassembly_overlap(core, hits, buf, len, current_buf_pos, current_instr_addr);
			next_buf_pos = current_buf_pos;
			hit_count = r_list_length (hits);
			last_num_invalid = 0;
		}

		// walk backwards by one instruction
		IFDBG eprintf(" current_instr_addr: 0x%"PFMT64x" current_instr_len: %d next_instr_addr: 0x%04"PFMT64x"\n",
			current_instr_addr, current_instr_len, next_buf_pos);
		IFDBG eprintf(" hit count: %d \n", hit_count );
		current_instr_addr -= 1;
		current_buf_pos -= 1;

		if ( hit_count >= max_hit_count &&
			 (last_num_invalid >= max_invalid_b4_exit || last_num_invalid == 0))
			break;
	} while (((int) current_buf_pos >= 0) && (int)(len - current_buf_pos) >= 0);

	r_asm_set_pc (core->assembler, addr);
	free (buf);
	return hits;
}
Beispiel #15
0
R_API int r_core_pseudo_code(RCore *core, const char *input) {
	Sdb *db;
	ut64 queuegoto = 0LL;
	const char *blocktype = "else";
	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL);
	RConfigHold *hc = r_config_hold_new (core->config);
	if (!hc) {
		return false;
	}
	r_config_save_num (hc, "asm.pseudo", "asm.decode", "asm.lines", "asm.bytes", NULL);
	r_config_save_num (hc, "asm.offset", "asm.flags", "asm.fcnlines", "asm.comments", NULL);
	r_config_save_num (hc, "asm.functions", "asm.section", "asm.cmtcol", "asm.filter", NULL);
	r_config_save_num (hc, "scr.color", "asm.emustr", "asm.emu", "asm.emuwrite", NULL);
	if (!fcn) {
		eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset);
		r_config_hold_free (hc);
		return false;
	}
	r_config_set_i (core->config, "scr.color", 0);
	r_config_set_i (core->config, "asm.pseudo", 1);
	r_config_set_i (core->config, "asm.decode", 0);
	r_config_set_i (core->config, "asm.filter", 1);
	r_config_set_i (core->config, "asm.lines", 0);
	r_config_set_i (core->config, "asm.bytes", 0);
	r_config_set_i (core->config, "asm.offset", 0);
	r_config_set_i (core->config, "asm.flags", 0);
	r_config_set_i (core->config, "asm.emu", 1);
	r_config_set_i (core->config, "asm.emustr", 1);
	r_config_set_i (core->config, "asm.emuwrite", 1);
	r_config_set_i (core->config, "asm.fcnlines", 0);
	r_config_set_i (core->config, "asm.comments", 1);
	r_config_set_i (core->config, "asm.functions", 0);
	r_config_set_i (core->config, "asm.tabs", 0);
	r_config_set_i (core->config, "asm.section", 0);
	r_config_set_i (core->config, "asm.cmtcol", 30);
	r_core_cmd0 (core, "aeim");

	db = sdb_new0 ();

	/* */
	// walk all basic blocks
	// define depth level for each block
	// use it for indentation
	// asm.pseudo=true
	// asm.decode=true
	RAnalBlock *bb = r_list_first (fcn->bbs);
	char indentstr[1024];
	int n_bb = r_list_length (fcn->bbs);
	r_cons_printf ("function %s () {", fcn->name);
	int indent = 1;
	int nindent = 1;

	do {
#define I_TAB 4
#define K_MARK(x) sdb_fmt(0,"mark.%"PFMT64x,x)
#define K_ELSE(x) sdb_fmt(0,"else.%"PFMT64x,x)
#define K_INDENT(x) sdb_fmt(0,"loc.%"PFMT64x,x)
#define SET_INDENT(x) { memset (indentstr, ' ', x*I_TAB); indentstr [(x*I_TAB)-2] = 0; }
		if (!bb) break;
		r_cons_push ();
		char *code = r_core_cmd_str (core, sdb_fmt (0, "pD %d @ 0x%08"PFMT64x"\n", bb->size, bb->addr));
		r_cons_pop ();
		memset (indentstr, ' ', indent * I_TAB);
		indentstr [(indent * I_TAB) - 2] = 0;
		code = r_str_prefix_all (code, indentstr);
		int len = strlen (code);
		code[len - 1] = 0; // chop last newline
		//r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
		//if (nindent != indent) {
		//	r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
		//}
		find_and_change (code, len);
		if (!sdb_const_get (db, K_MARK (bb->addr), 0)) {
			bool mustprint = !queuegoto || queuegoto != bb->addr;
			if (mustprint) {
				if (queuegoto) {
					r_cons_printf ("\n%s  goto loc_0x%llx", indentstr, queuegoto);
					queuegoto = 0LL;
				}
				r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
				indentstr[(indent * I_TAB) - 2] = 0;
				r_cons_printf ("\n%s", code);
				free (code);
				sdb_num_set (db, K_MARK (bb->addr), 1, 0);
			}
		}
		if (sdb_const_get (db, K_INDENT (bb->addr), 0)) {
			// already analyzed, go pop and continue
			// XXX check if cant pop
			//eprintf ("%s// 0x%08llx already analyzed\n", indentstr, bb->addr);
			ut64 addr = sdb_array_pop_num (db, "indent", NULL);
			if (addr == UT64_MAX) {
				int i;
				nindent = 1;
				for (i = indent; i != nindent; i--) {
					SET_INDENT (i);
					r_cons_printf ("\n%s}", indentstr);
				}
				r_cons_printf ("\n%sreturn;\n", indentstr);
				break;
			}
			if (sdb_num_get (db, K_ELSE (bb->addr), 0)) {
				if (!strcmp (blocktype, "else")) {
					r_cons_printf ("\n%s } %s {", indentstr, blocktype);
				} else {
					r_cons_printf ("\n%s } %s (?);", indentstr, blocktype);
				}
			} else {
				r_cons_printf ("\n%s}", indentstr);
			}
			if (addr != bb->addr) {
				queuegoto = addr;
				//r_cons_printf ("\n%s  goto loc_0x%llx", indentstr, addr);
			}
			bb = r_anal_bb_from_offset (core->anal, addr);
			if (!bb) {
				eprintf ("failed block\n");
				break;
			}
			//eprintf ("next is %llx\n", addr);
			nindent = sdb_num_get (db, K_INDENT (addr), NULL);
			if (indent > nindent && !strcmp (blocktype, "else")) {
				int i;
				for (i = indent; i != nindent; i--) {
					SET_INDENT (i);
					r_cons_printf ("\n%s }", indentstr);
				}
			}
			indent = nindent;
		} else {
			sdb_set (db, K_INDENT (bb->addr), "passed", 0);
			if (bb->jump != UT64_MAX) {
				int swap = 1;
				// TODO: determine which branch take first
				ut64 jump = swap ? bb->jump : bb->fail;
				ut64 fail = swap ? bb->fail : bb->jump;
				// if its from another function chop it!
				RAnalFunction *curfcn = r_anal_get_fcn_in (core->anal, jump, R_ANAL_FCN_TYPE_NULL);
				if (curfcn != fcn) {
					// chop that branch
					r_cons_printf ("\n  // chop\n");
					break;
				}
				if (sdb_get (db, K_INDENT (jump), 0)) {
					// already tracekd
					if (!sdb_get (db, K_INDENT (fail), 0)) {
						bb = r_anal_bb_from_offset (core->anal, fail);
					}
				} else {
					bb = r_anal_bb_from_offset (core->anal, jump);
					if (!bb) {
						eprintf ("failed to retrieve blcok at 0x%"PFMT64x"\n", jump);
						break;
					}
					if (fail != UT64_MAX) {
						// do not push if already pushed
						indent++;
						if (sdb_get (db, K_INDENT (bb->fail), 0)) {
							/* do nothing here */
							eprintf ("BlockAlready 0x%"PFMT64x"\n", bb->addr);
						} else {
							//		r_cons_printf (" { RADICAL %llx\n", bb->addr);
							sdb_array_push_num (db, "indent", fail, 0);
							sdb_num_set (db, K_INDENT (fail), indent, 0);
							sdb_num_set (db, K_ELSE (fail), 1, 0);
							SET_INDENT (indent);
							r_cons_printf ("\n%s {", indentstr);
						}
					} else {
						r_cons_printf ("\n%s do", indentstr);
						sdb_array_push_num (db, "indent", jump, 0);
						sdb_num_set (db, K_INDENT (jump), indent, 0);
						sdb_num_set (db, K_ELSE (jump), 1, 0);
						if (jump <= bb->addr) {
							blocktype = "while";
						} else {
							blocktype = "else";
						}
						r_cons_printf ("\n%s {", indentstr);
						indent++;
					}
				}
			} else {
				ut64 addr = sdb_array_pop_num (db, "indent", NULL);
				if (addr == UT64_MAX) {
					//r_cons_printf ("\nbreak\n");
					break;
				}
				bb = r_anal_bb_from_offset (core->anal, addr);
				nindent = sdb_num_get (db, K_INDENT (addr), NULL);
				if (indent > nindent) {
					int i;
					for (i = indent; i != nindent; i--) {
						SET_INDENT (i);
						r_cons_printf ("\n%s}", indentstr);
					}
				}
				if (nindent != indent) {
					r_cons_printf ("\n%s} else {\n", indentstr);
				}
				indent = nindent;
			}
		}
		//n_bb --;
	} while (n_bb > 0);
	r_cons_printf ("\n}\n");
	r_config_restore (hc);
	r_config_hold_free (hc);
	sdb_free (db);
	return true;
}
Beispiel #16
0
static RList* _extract_regs(char *regstr, RList *flags, char *pc_alias) {
	char *regstr_end, *regname, *regtype, *tmp1;
	ut32 flagnum, regname_len, regsize, regnum;
	RList *regs;
	RListIter *iter;
	gdbr_xml_reg_t *tmpreg;
	gdbr_xml_flags_t *tmpflag;
	if (!(regs = r_list_new ())) {
		return NULL;
	}
	while ((regstr = strstr (regstr, "<reg"))) {
		if (!(regstr_end = strchr (regstr, '/'))) {
			goto exit_err;
		}
		*regstr_end = '\0';
		// name
		if (!(regname = strstr (regstr, "name="))) {
			goto exit_err;
		}
		regname += 6;
		if (!(tmp1 = strchr (regname, '"'))) {
			goto exit_err;
		}
		regname_len = tmp1 - regname;
		// size
		if (!(tmp1 = strstr (regstr, "bitsize="))) {
			goto exit_err;
		}
		tmp1 += 9;
		if (!isdigit (*tmp1)) {
			goto exit_err;
		}
		regsize = strtoul (tmp1, NULL, 10);
		// regnum
		regnum = UINT32_MAX;
		if ((tmp1 = strstr (regstr, "regnum="))) {
			tmp1 += 8;
			if (!isdigit (*tmp1)) {
				goto exit_err;
			}
			regnum = strtoul (tmp1, NULL, 10);
		}
		// type
		regtype = "gpr";
		flagnum = r_list_length (flags);
		if ((tmp1 = strstr (regstr, "group="))) {
			tmp1 += 7;
			if (r_str_startswith (tmp1, "float")) {
				regtype = "fpu";
			}
			// We need type information in r2 register profiles
		} else if ((tmp1 = strstr (regstr, "type="))) {
			tmp1 += 6;
			if (r_str_startswith (tmp1, "vec")
			    || r_str_startswith (tmp1, "i387_ext")
			    || r_str_startswith (tmp1, "ieee_single")
			    || r_str_startswith (tmp1, "ieee_double")) {
				regtype = "fpu";
			} else if (r_str_startswith (tmp1, "code_ptr")) {
				strcpy (pc_alias, "=PC	");
				strncpy (pc_alias + 4, regname, regname_len);
				strcpy (pc_alias + 4 + regname_len, "\n");
			} else {
				// Check all flags. If reg is a flag, write flag data
				flagnum = 0;
				r_list_foreach (flags, iter, tmpflag) {
					if (r_str_startswith (tmp1, tmpflag->type)) {
						// Max 64-bit :/
						if (tmpflag->num_bits <= 64) {
							break;
						}
					}
					flagnum++;
				}
			}
			// We need type information in r2 register profiles
		}
		if (!(tmpreg = calloc (1, sizeof (gdbr_xml_reg_t)))) {
			goto exit_err;
		}
		regname[regname_len] = '\0';
		if (regname_len > sizeof (tmpreg->name) - 1) {
			eprintf ("Register name too long: %s\n", regname);
		}
		strncpy (tmpreg->name, regname, sizeof (tmpreg->name) - 1);
		tmpreg->name[sizeof (tmpreg->name) - 1] = '\0';
		regname[regname_len] = '"';
		strncpy (tmpreg->type, regtype, sizeof (tmpreg->type) - 1);
		tmpreg->type[sizeof (tmpreg->type) - 1] = '\0';
		tmpreg->size = regsize / 8;
		tmpreg->flagnum = flagnum;
		if (regnum == UINT32_MAX) {
			r_list_push (regs, tmpreg);
		} else if (regnum >= r_list_length (regs)) {
			int i;
			for (i = regnum - r_list_length (regs); i > 0; i--) {
				// temporary placeholder reg. we trust the xml is correct and this will be replaced.
				r_list_push (regs, tmpreg);
				r_list_tail (regs)->data = NULL;
			}
			r_list_push (regs, tmpreg);
		} else {
			// this is where we replace those placeholder regs
			r_list_set_n (regs, regnum, tmpreg);
		}
		*regstr_end = '/';
		regstr = regstr_end + 2;
	}
Beispiel #17
0
static int gdbr_parse_target_xml(libgdbr_t *g, char *xml_data, ut64 len) {
	char *regstr, *flagstr, *tmp, *profile = NULL, pc_alias[64], flag_bits[65];
	RList *flags, *regs;
	RListIter *iter;
	gdbr_xml_flags_t *tmpflag;
	gdbr_xml_reg_t *tmpreg;
	ut64 profile_len = 0, profile_max_len, regnum = 0, regoff = 0;
	pc_alias[0] = '\0';
	gdb_reg_t *arch_regs = NULL;
	if (_resolve_arch (g, xml_data) < 0) {
		return -1;
	}
	if (!(flagstr = strstr (xml_data, "<feature"))) {
		return -1;
	}
	regstr = flagstr;
	if (!(flags = _extract_flags (flagstr))) {
		return -1;
	}
	if (!(regs = _extract_regs (regstr, flags, pc_alias))) {
		r_list_free (flags);
		return -1;
	}
	if (!(arch_regs = malloc (sizeof (gdb_reg_t) * (r_list_length (regs) + 1)))) {
		goto exit_err;
	}
	// approximate per-reg size estimates
	profile_max_len = r_list_length (regs) * 128 + r_list_length (flags) * 128;
	if (!(profile = malloc (profile_max_len))) {
		goto exit_err;
	}
	r_list_foreach (regs, iter, tmpreg) {
		if (!tmpreg) {
			continue;
		}
		// regsize > 64 not supported by r2 currently
		if (tmpreg->size > 8) {
			regoff += tmpreg->size;
			continue;
		}
		memcpy (arch_regs[regnum].name, tmpreg->name, sizeof (tmpreg->name));
		arch_regs[regnum].size = tmpreg->size;
		arch_regs[regnum].offset = regoff;
		if (profile_len + 128 >= profile_max_len) {
			if (!(tmp = realloc (profile, profile_max_len + 512))) {
				goto exit_err;
			}
			profile = tmp;
			profile_max_len += 512;
		}
		flag_bits[0] = '\0';
		tmpflag = NULL;
		if (tmpreg->flagnum < r_list_length (flags)) {
			tmpflag = r_list_get_n (flags, tmpreg->flagnum);
			_write_flag_bits (flag_bits, tmpflag);
		}
		profile_len += snprintf (profile + profile_len, 128, "%s\t%s\t"
					".%u\t%"PFMT64d"\t0\t%s\n", tmpreg->type,
					tmpreg->name, tmpreg->size * 8, regoff, flag_bits);
		// TODO write flag subregisters
		if (tmpflag) {
			int i;
			for (i = 0; i < tmpflag->num_fields; i++) {
				if (profile_len + 128 >= profile_max_len) {
					if (!(tmp = realloc (profile, profile_max_len + 512))) {
						goto exit_err;
					}
					profile = tmp;
					profile_max_len += 512;
				}
				profile_len += snprintf (profile + profile_len, 128, "gpr\t%s\t"
							".%u\t.%"PFMT64d"\t0\n", tmpflag->fields[i].name,
							tmpflag->fields[i].sz, tmpflag->fields[i].bit_num + (regoff * 8));
			}
		}
		regnum++;
		regoff += tmpreg->size;
	}
	// Difficult to parse these out from xml. So manually added from gdb's xml files
	switch (g->target.arch) {
	case R_SYS_ARCH_ARM:
		switch (g->target.bits) {
		case 32:
			if (!(profile = r_str_prefix (profile,
							"=PC	r15\n"
							"=SP	r14\n" // XXX
							"=A0	r0\n"
							"=A1	r1\n"
							"=A2	r2\n"
							"=A3	r3\n"
						      ))) {
				goto exit_err;
			}
			break;
		case 64:
			if (!(profile = r_str_prefix (profile,
							"=PC	pc\n"
							"=SP	sp\n"
							"=BP	x29\n"
							"=A0	x0\n"
							"=A1	x1\n"
							"=A2	x2\n"
							"=A3	x3\n"
							"=ZF	zf\n"
							"=SF	nf\n"
							"=OF	vf\n"
							"=CF	cf\n"
							"=SN	x8\n"
						      ))) {
				goto exit_err;
			}
		}
		break;
		break;
	case R_SYS_ARCH_X86:
		switch (g->target.bits) {
		case 32:
			if (!(profile = r_str_prefix (profile,
						     "=PC	eip\n"
						     "=SP	esp\n"
						     "=BP	ebp\n"))) {
				goto exit_err;
			}
			break;
		case 64:
			if (!(profile = r_str_prefix (profile,
						     "=PC	rip\n"
						     "=SP	rsp\n"
						     "=BP	rbp\n"))) {
				goto exit_err;
			}
		}
		break;
	case R_SYS_ARCH_MIPS:
		if (!(profile = r_str_prefix (profile,
						"=PC	pc\n"
						"=SP	r29\n"))) {
			goto exit_err;
		}
		break;
	default:
		// TODO others
		if (*pc_alias) {
			if (!(profile = r_str_prefix (profile, pc_alias))) {
				goto exit_err;
			}
		}
	}
	// Special case for MIPS, since profile doesn't separate 32/64 bit MIPS
	if (g->target.arch == R_SYS_ARCH_MIPS) {
		if (arch_regs && arch_regs[0].size == 8) {
			g->target.bits = 64;
		}
	}
	r_list_free (flags);
	r_list_free (regs);
	free (g->target.regprofile);
	if (profile) {
		g->target.regprofile = strdup (profile);
		free (profile);
	}
	g->target.valid = true;
	g->registers = arch_regs;
	return 0;

exit_err:
	r_list_free (flags);
	r_list_free (regs);
	free (profile);
	free (arch_regs);
	return -1;
}
Beispiel #18
0
static int emulate (RAnalEsil *c, char *buf, int *tkns) {
	ut64 num = 0;
	char *op = NULL;
	char *str;
	int i, type;
	c->opstack = r_list_new ();
	c->stack = r_list_new ();
	c->opsize = 0;
	c->rightside = 0;
	for (i=0; tkns[i]; i+=2) {
		TOKEN_GET (type, str);
		eprintf ("(%d) (%s)\n", type, str);

		switch (type) {
		// case 0 handled in for conditional
		case 1: /* special command */
			if (!strcmp (str, "[")) {
				int curstack = r_list_length (c->stack);
eprintf ("STACK POINTER %d\n", curstack);
				c->opsize = (int)num;
				// TODO: test for size
				// read tokens until ']'
				// TOKEN_UNTIL (1, "]");
				for (i+=2; tkns[i]; i+=2) {
					TOKEN_GET (type, str);
					eprintf ("--- %d (%s)\n", tkns[i], buf+tkns[i+1]);
					switch (tkns[i]) {
					case 1:
						if (!strcmp (str, "]")) {
							if (!c->opsize) c->opsize = 
								c->anal->bits==64?8:4;
							//int j, len = r_list_length (c->stack) - curstack;
							char *a;
							OPUSH (op);
							while ((a = OPOP ())) {
								// eprintf ("---> op %s\n", op);
								esil_commit (c, a);
							}
							//op = NULL;
							printf ("   %s (size %d)\n", c->rightside?"GET":"SET", (int)num);
							goto dungeon;
							// set destination for write
							// expect '='
						}
						break;
					case 2:
						op = str;
						OPUSH (op);
						break;
					case 3:
						PUSH (str);
						break;
					}
				}
				if (!tkns[i]) {
					printf ("Unexpected eof\n");
					return 1;
				}
			} else
			if (!strcmp (str, "?")) {
				printf ("   CONDITIONAL\n");
				i += 2;
				TOKEN_GET (type, str);
				if (!type) {
					eprintf ("   UNEXPECTED EOF\n");
					return 1;
				}
				if (type!=3) {
					printf ("   UNEXPECTED TOKEN\n");
					return 1;
				}
				//while () { i += 2; }
			}
			break;
		case 2:
			if (op) {
				//eprintf (" XXX Redefine op %s\n", op);
				if (!strcmp (op, "*")) { // prio
					esil_commit (c, op);
				} else OPUSH (op);
			}
			op = str;
			if (IS ("=")) {
				c->rightside = 1;
			}
			break;
		case 3:
			num = c->num (c, str); // 
	//		eprintf ("; push %s\n" , str);
			PUSH (str);
			break;
		case 4:
			esil_commit (c, op);
			op = NULL;
			break;
		case 5:
// newcontext();
			//esil_push_scope (c);
			eprintf ("OPEN SCOPE\n");
			break;
		case 6:
			{
			//char *res = esil_pop_scope (c);
			// if scope > 0 : 
			//PUSH (res);
			esil_commit (c, op);
			// free (res);
			// commit()
			// closecontext()
			// push result
			eprintf ("CLOSE SCOPE\n");
			}
			break;
		}
		dungeon:
		{/*trick*/int/*label*/x/*parsing*/=/*fix*/0;}
	}
	eprintf (";;; COMMIT (%s) (%s)\n", op, str);
	esil_commit (c, op);
	if (r_list_length (c->opstack)>0) {
		char *a;
		while ((a = OPOP ())) {
			esil_commit (c, a);
		}
	}
	op = NULL;
	return 0;
}
Beispiel #19
0
R_API int r_core_pseudo_code (RCore *core, const char *input) {
	Sdb *db;
	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal,
		core->offset, R_ANAL_FCN_TYPE_NULL);
	int asmpseudo = r_config_get_i (core->config, "asm.pseudo");
	int asmdecode = r_config_get_i (core->config, "asm.decode");
	int asmlines = r_config_get_i (core->config, "asm.lines");
	int asmbytes = r_config_get_i (core->config, "asm.bytes");
	int asmoffset = r_config_get_i (core->config, "asm.offset");
	int asmflags = r_config_get_i (core->config, "asm.flags");
	int asmfcnlines = r_config_get_i (core->config, "asm.fcnlines");
	int asmcomments = r_config_get_i (core->config, "asm.comments");
	int asmfunctions = r_config_get_i (core->config, "asm.functions");
	if (!fcn) {
		eprintf ("Cannot find function in 0x%08"PFMT64x"\n",
			core->offset);
		return R_FALSE;
	}
	r_config_set_i (core->config, "asm.pseudo", 1);
	r_config_set_i (core->config, "asm.decode", 0);
	r_config_set_i (core->config, "asm.lines", 0);
	r_config_set_i (core->config, "asm.bytes", 0);
	r_config_set_i (core->config, "asm.offset", 0);
	r_config_set_i (core->config, "asm.flags", 0);
	r_config_set_i (core->config, "asm.fcnlines", 0);
	r_config_set_i (core->config, "asm.comments", 0);
	r_config_set_i (core->config, "asm.functions", 0);

	db = sdb_new0 ();

	/* */
	// walk all basic blocks
	// define depth level for each block
	// use it for indentation
	// asm.pseudo=true
	// asm.decode=true
	RAnalBlock *bb = r_list_first (fcn->bbs);
	char indentstr[1024];
	int n_bb = r_list_length (fcn->bbs);
	r_cons_printf ("function %s () {", fcn->name);
	int indent = 1;
	int nindent = 1;

	do {
#define I_TAB 4
#define K_ELSE(x) sdb_fmt(0,"else.%"PFMT64x,x)
#define K_INDENT(x) sdb_fmt(0,"loc.%"PFMT64x,x)
#define SET_INDENT(x) { memset (indentstr, ' ', x*I_TAB); indentstr [(x*I_TAB)-2] = 0; }
		if (!bb) break;
		r_cons_push ();
		char *code = r_core_cmd_str (core, sdb_fmt(0,
			"pDI %d @ 0x%08"PFMT64x"\n", bb->size, bb->addr));
		r_cons_pop ();
		memset (indentstr, ' ', indent*I_TAB);
		indentstr [(indent*I_TAB)-2] = 0;
		code = r_str_prefix_all (code, indentstr);
		code[strlen(code)-1] = 0; // chop last newline
		//r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
		//if (nindent != indent) {
		//	r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
		//}
			r_cons_printf ("\n%s  loc_0x%llx:\n", indentstr, bb->addr);
		indentstr[(indent*I_TAB)-2] = 0;
		r_cons_printf ("\n%s", code);
		free (code);
		if (sdb_get (db, K_INDENT(bb->addr), 0)) {
			// already analyzed, go pop and continue
			// XXX check if cant pop
			//eprintf ("%s// 0x%08llx already analyzed\n", indentstr, bb->addr);
			ut64 addr = sdb_array_pop_num (db, "indent", NULL);
			if (addr==UT64_MAX) {
				int i;
				nindent = 1;
				for (i=indent; i!=nindent; i--) {
					SET_INDENT (i);
					r_cons_printf ("\n%s}", indentstr);
				}
				r_cons_printf ("\n%sreturn;\n", indentstr);
				break;
			}
			if (sdb_num_get (db, K_ELSE(bb->addr), 0)) {
				r_cons_printf ("\n%s} else {", indentstr);
			} else {
				r_cons_printf ("\n%s}", indentstr);
			}
			r_cons_printf ("\n%s  goto loc_0x%llx", indentstr, addr);
			bb = r_anal_bb_from_offset (core->anal, addr);
			if (!bb) {
				eprintf ("failed block\n");
				break;
			}
			//eprintf ("next is %llx\n", addr);
			nindent = sdb_num_get (db, K_INDENT(addr), NULL);
			if (indent>nindent) {
				int i;
				for (i=indent; i!=nindent; i--) {
					SET_INDENT (i);
					r_cons_printf ("\n%s}", indentstr);
				}
			}
			indent = nindent;
		} else {
			sdb_set (db, K_INDENT(bb->addr), "passed", 0);
			if (bb->jump != UT64_MAX) {
				int swap = 1;
				// TODO: determine which branch take first
				ut64 jump = swap? bb->jump: bb->fail;
				ut64 fail = swap? bb->fail: bb->jump;
				// if its from another function chop it!
				RAnalFunction *curfcn = r_anal_get_fcn_in (core->anal, jump, R_ANAL_FCN_TYPE_NULL);
				if (curfcn != fcn) {
					// chop that branch
					r_cons_printf ("\n  // chop\n");
					break;
				}
				if (sdb_get (db, K_INDENT(jump), 0)) {
					// already tracekd
					if (!sdb_get (db, K_INDENT(fail), 0)) {
						bb = r_anal_bb_from_offset (core->anal, fail);
					}
				} else {
					bb = r_anal_bb_from_offset (core->anal, jump);
					if (!bb) {
						eprintf ("failed to retrieve blcok at 0x%"PFMT64x"\n", jump);
						break;
					}
					if (fail != UT64_MAX) {
						// do not push if already pushed
						indent++;
						if (sdb_get (db, K_INDENT(bb->fail), 0)) {
							/* do nothing here */
							eprintf ("BlockAlready 0x%"PFMT64x"\n", bb->addr);
						} else {
					//		r_cons_printf (" { RADICAL %llx\n", bb->addr);
							sdb_array_push_num (db, "indent", fail, 0);
							sdb_num_set (db, K_INDENT(fail), indent, 0);
							sdb_num_set (db, K_ELSE(fail), 1, 0);
							r_cons_printf (" {");
						}
					} else {
						r_cons_printf (" do");
						sdb_array_push_num (db, "indent", jump, 0);
						sdb_num_set (db, K_INDENT(jump), indent, 0);
						sdb_num_set (db, K_ELSE(jump), 1, 0);
						r_cons_printf (" {");
						indent++;
					}
				}
			} else {
				ut64 addr = sdb_array_pop_num (db, "indent", NULL);
				if (addr==UT64_MAX) {
					r_cons_printf ("\nbreak\n");
					break;
				}
				bb = r_anal_bb_from_offset (core->anal, addr);
				nindent = sdb_num_get (db, K_INDENT(addr), NULL);
				if (indent>nindent) {
					int i;
					for (i=indent; i!=nindent; i--) {
						SET_INDENT (i);
						r_cons_printf ("\n%s}", indentstr);
					}
				}
				if (nindent != indent) {
					r_cons_printf ("\n%s} else {\n", indentstr);
				}
				indent = nindent;
			}
		}
		//n_bb --;
	} while (n_bb>0);
	r_cons_printf ("}\n");
	r_cons_flush ();
	r_config_set_i (core->config, "asm.pseudo", asmpseudo);
	r_config_set_i (core->config, "asm.decode", asmdecode);
	r_config_set_i (core->config, "asm.lines", asmlines);
	r_config_set_i (core->config, "asm.bytes", asmbytes);
	r_config_set_i (core->config, "asm.offset", asmoffset);
	r_config_set_i (core->config, "asm.flags", asmflags);
	r_config_set_i (core->config, "asm.fcnlines", asmfcnlines);
	r_config_set_i (core->config, "asm.comments", asmcomments);
	r_config_set_i (core->config, "asm.functions", asmfunctions);
	sdb_free (db);
	return R_TRUE;
}
Beispiel #20
0
R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
	ut64 paddr, last, last2;
	int ms, ret, l, olen = len, w = 0;

	io->off = addr;
	memset (buf, 0xff, len); // probably unnecessary

	if (io->buffer_enabled)
		return r_io_buffer_read (io, addr, buf, len);
	while (len>0) {
		last = r_io_section_next (io, addr+w);
		last2 = r_io_map_next (io, addr+w); // XXX: must use physical address
		if (last == (addr+w)) last = last2;
		//else if (last2<last) last = last2;
		l = (len > (last-addr+w))? (last-addr+w): len;
		if (l<1) l = len;
		{
			paddr = w? r_io_section_vaddr_to_offset (io, addr+w): addr;
			if (len>0 && l>len) l = len;
			addr = paddr-w;
			if (r_io_seek (io, paddr, R_IO_SEEK_SET)==UT64_MAX) {
				memset (buf+w, 0xff, l);
			}
		}
#if 0
		if (io->zeromap)
			if (!r_io_map_get (io, addr+w)) {
				if (addr==0||r_io_section_getv (io, addr+w)) {
					memset (buf+w, 0xff, l);
eprintf ("RETRERET\n");
					return -1;
				}
			}
#endif
		// XXX is this necessary?
		ms = r_io_map_select (io, addr+w);
		ret = r_io_read_internal (io, buf+w, l);
//eprintf ("READ %d = %02x %02x %02x\n", ret, buf[w], buf[w+1], buf[w+2]);
		if (ret<1) {
			memset (buf+w, 0xff, l); // reading out of file
			ret = 1;
		} else if (ret<l) {
			l = ret;
		}
#if USE_CACHE
		if (io->cached) {
			r_io_cache_read (io, addr+w, buf+w, len-w);
		} else if (r_list_length (io->maps) >1) {
			if (!io->debug && ms>0) {
				//eprintf ("FAIL MS=%d l=%d d=%d\n", ms, l, d);
				/* check if address is vaddred in sections */
				ut64 o = r_io_section_offset_to_vaddr (io, addr+w);
				if (o == UT64_MAX) {
					ut64 o = r_io_section_vaddr_to_offset (io, addr+w);
					if (o == UT64_MAX)
						memset (buf+w, 0xff, l);
				}
				break;
			}
		}
#endif
		w += l;
		len -= l;
	}
	return olen;
}