Exemple #1
0
R_API ut64 r_io_seek(RIO *io, ut64 offset, int whence) {
	int posix_whence = SEEK_SET;
	ut64 ret = UT64_MAX;
	if (io->buffer_enabled) {
		io->off = offset;
		return offset;
	}
	switch (whence) {
	case R_IO_SEEK_SET:
		posix_whence = SEEK_SET;
		ret = offset;
		break;
	case R_IO_SEEK_CUR:
//		offset += io->off;
		posix_whence = SEEK_CUR;
		ret = offset+io->off;
		break;
	case R_IO_SEEK_END:
		//offset = UT64_MAX; // XXX: depending on io bits?
		ret = UT64_MAX;
		posix_whence = SEEK_END;
		break;
	}
	if (io == NULL)
		return ret;
	// XXX: list_empty trick must be done in r_io_set_va();
	//eprintf ("-(seek)-> 0x%08llx\n", offset);
	if (!io->debug && io->va && !r_list_empty (io->sections)) {
		ut64 o = r_io_section_vaddr_to_offset (io, offset);
		if (o != UT64_MAX)
			offset = o;
	//	eprintf ("-(vadd)-> 0x%08llx\n", offset);
	}
	// if resolution fails... just return as invalid address
	if (offset==UT64_MAX)
		return UT64_MAX;
	if (io->fd != NULL) {
		if (io->plugin && io->plugin->lseek)
			ret = io->plugin->lseek (io, io->fd, offset, whence);
		// XXX can be problematic on w32..so no 64 bit offset?
		else ret = (ut64)lseek (io->fd->fd, offset, posix_whence);
		if (ret != UT64_MAX) {
			io->off = ret;
			// XXX this can be tricky.. better not to use this .. must be deprecated
			// r_io_sundo_push (io);
			ret = (!io->debug && io->va && !r_list_empty (io->sections))?
				r_io_section_offset_to_vaddr (io, io->off) : io->off;
		} //else eprintf ("r_io_seek: cannot seek to %"PFMT64x"\n", offset);
	} //else { eprintf ("r_io_seek: null fd\n"); }
	return ret;
}
Exemple #2
0
static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
	RCore *core = (RCore *)userptr; // XXX ?
	RAnalFunction *fcn;
	char *ptr, *bptr, *out;
	RFlagItem *flag;
	RIOSection *s;
	RAnalOp op;
	ut64 ret = 0;

	if (ok) *ok = R_FALSE;
	switch (*str) {
	case '[':
{
		ut64 n = 0LL;
		int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4;
		const char *p = NULL;
		if (strlen (str)>5)
			p = strchr (str+5, ':');
		// TODO: honor LE
		if (p) {
			refsz = atoi (str+1);
			str = p;
		}
		// push state
		{
			if (str[0] && str[1]) {
				const char *q;
				char *o = strdup (str+1);
				if (o) {
					q = r_num_calc_index (core->num, NULL);
					if (q) {
						if (r_str_replace_char (o, ']', 0)>0) {
							n = r_num_math (core->num, o);
							r_num_calc_index (core->num, q);
						}
					}
					free (o);
				}
			}
		}
		// pop state
		if (ok) *ok = 1;
		ut32 num = 0;
		switch (refsz) {
		case 8:
		case 4:
		case 2:
		case 1:
			(void)r_io_read_at (core->io, n, (ut8*)&num, refsz);
			r_mem_copyendian ((ut8*)&num, (ut8*)&num, refsz, !core->assembler->big_endian);
			return num;
		default:
			eprintf ("Invalid reference size: %d (%s)\n", refsz, str);
			return 0LL;
		}
}
		break;
	case '$':
		if (ok) *ok = 1;
		// TODO: group analop-dependant vars after a char, so i can filter
		r_anal_op (core->anal, &op, core->offset,
			core->block, core->blocksize);
		switch (str[1]) {
		case '.': // can use pc, sp, a0, a1, ...
			return r_debug_reg_get (core->dbg, str+2);
		case 'k':
			if (str[2]!='{') {
				eprintf ("Expected '{' after 'k'.\n");
				break;
			}
			bptr = strdup (str+3);
			ptr = strchr (bptr, '}');
			if (ptr == NULL) {
				// invalid json
				free (bptr);
				break;
			}
			*ptr = '\0';
			ret = 0LL;
			out = sdb_querys (core->sdb, NULL, 0, bptr);
			if (out && *out) {
				if (strstr (out, "$k{")) {
					eprintf ("Recursivity is not permitted here\n");
				} else {
					ret = r_num_math (core->num, out);
				}
			}
			free (bptr);
			free (out);
			return ret;
			break;
		case '{':
			bptr = strdup (str+2);
			ptr = strchr (bptr, '}');
			if (ptr != NULL) {
				ut64 ret;
				ptr[0] = '\0';
				ret = r_config_get_i (core->config, bptr);
				free (bptr);
				return ret;
			}
			free (bptr);
			break;
		case 'c': return r_cons_get_size (NULL);
		case 'r': { int rows; r_cons_get_size (&rows); return rows; }
		case 'e': return r_anal_op_is_eob (&op);
		case 'j': return op.jump;
		case 'p': return r_sys_getpid ();
		case 'P': return (core->dbg->pid>0)? core->dbg->pid: 0;
		case 'f': return op.fail;
		case 'm': return op.ptr; // memref
		case 'v': return op.val; // immediate value
		case 'l': return op.size;
		case 'b': return core->blocksize;
		case 's':
			if (core->file) {
				return r_io_desc_size (core->io, core->file->desc);
			}
			return 0LL;
		case 'w': return r_config_get_i (core->config, "asm.bits") / 8;
		case 'S':
			s = r_io_section_vget (core->io, core->offset);
			return s? (str[2]=='S'? s->size: s->vaddr): 3;
		case '?': return core->num->value;
		case '$': return core->offset;
		case 'o': return r_io_section_vaddr_to_offset (core->io,
				core->offset);
		case 'C': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_CALL);
		case 'J': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_CODE);
		case 'D': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_DATA);
		case 'X': return getref (core, atoi (str+2), 'x',
				R_ANAL_REF_TYPE_CALL);
		case 'I':
			fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
			return fcn? fcn->ninstr: 0;
		case 'F':
			fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
			return fcn? fcn->size: 0;
		}
		break;
	default:
		if (*str>'A') {
			// NOTE: functions override flags
			RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, str);
			if (fcn) {
				if (ok) *ok = R_TRUE;
				return fcn->addr;
			}
#if 0
			ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str);
			if (addr != 0) {
				ret = addr;
			} else {
				...
			}
#endif
			if ((flag = r_flag_get (core->flags, str))) {
				ret = flag->offset;
				if (ok) *ok = R_TRUE;
			}
		}
		break;
	}
Exemple #3
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 eprintf ("cfg.debug is false\n");
        } 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':
        {
            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_get (core->io,
                                              r_io_section_vaddr_to_offset (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_get (core->io,
                                              r_io_section_vaddr_to_offset (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 '?':
            r_cons_printf (
                "|Usage: s[+-] [addr]\n"
                "| s                 print current address\n"
                "| s 0x320           seek to this address\n"
                "| s-                undo seek\n"
                "| s+                redo seek\n"
                "| s*                list undo seek history\n"
                "| s++               seek blocksize bytes forward\n"
                "| s--               seek blocksize bytes backward\n"
                "| s+ 512            seek 512 bytes forward\n"
                "| s- 512            seek 512 bytes backward\n"
                "| sg/sG             seek begin (sg) or end (sG) of section or file\n"
                "| s.hexoff          Seek honoring a base from core->offset\n"
                "| sa [[+-]a] [asz]  seek asz (or bsize) aligned to addr\n"
                "| sn/sp             seek next/prev scr.nkey\n"
                "| s/ DATA           search for next occurrence of 'DATA'\n"
                "| s/x 9091          search for next occurrence of \\x90\\x91\n"
                "| sb                seek aligned to bb start\n"
                //"| sp [page]  seek page N (page = block)\n"
                "| so [num]          seek to N next opcode(s)\n"
                "| sf                seek to next function (f->addr+f->size)\n"
                "| sC str            seek to comment matching given string\n"
                "| sr pc             seek to register\n");
            break;
        }
    } else r_cons_printf ("0x%"PFMT64x"\n", core->offset);
    return 0;
}
Exemple #4
0
static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
	RCore *core = (RCore *)userptr; // XXX ?
	RAnalFunction *fcn;
	char *ptr, *bptr;
	RFlagItem *flag;
	RIOSection *s;
	RAnalOp op;
	ut64 ret = 0;

	if (ok) *ok = R_FALSE;
	if (*str=='[') {
		int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4;
		const char *p = strchr (str+5, ':');
		ut64 n;
		// TODO: honor endian
		if (p) {
			refsz = atoi (str+1);
			str = p;
		}
		// push state
		{
			char *o = strdup (str+1);
			const char *q = r_num_calc_index (core->num, NULL);
			r_str_replace_char (o, ']', 0);
			n = r_num_math (core->num, o);
			r_num_calc_index (core->num, q);
			free (o);
		}
		// pop state
		switch (refsz) {
		case 8: {
			ut64 num = 0;
			r_io_read_at (core->io, n, (ut8*)&num, sizeof (num));
			return num; }
		case 4: {
			ut32 num = 0;
			r_io_read_at (core->io, n, (ut8*)&num, sizeof (num));
			return num; }
		case 2: {
			ut16 num = 0;
			r_io_read_at (core->io, n, (ut8*)&num, sizeof (num));
			return num; }
		case 1: {
			ut8 num = 0;
			r_io_read_at (core->io, n, (ut8*)&num, sizeof (num));
			return num; }
		default:
			eprintf ("Invalid reference size: %d (%s)\n", refsz, str);
			break;
		}
	} else
	if (str[0]=='$') {
		if (ok) *ok = 1;
		// TODO: group analop-dependant vars after a char, so i can filter
		r_anal_op (core->anal, &op, core->offset,
			core->block, core->blocksize);
		switch (str[1]) {
		case '.': // can use pc, sp, a0, a1, ...
			return r_debug_reg_get (core->dbg, str+2);
		case '{':
			bptr = strdup (str+2);
			ptr = strchr (bptr, '}');
			if (ptr != NULL) {
				ut64 ret;
				ptr[0] = '\0';
				ret = r_config_get_i (core->config, bptr);
				free (bptr);
				return ret;
			}
			break;
		case 'h': {
			int rows;
			r_cons_get_size (&rows);
			return rows;
			}
		case 'e': return op.eob;
		case 'j': return op.jump;
		case 'f': return op.fail;
		case 'r': return op.ref;
		case 'l': return op.length;
		case 'b': return core->blocksize;
		case 's': return core->file->size;
		case 'w': return r_config_get_i (core->config, "asm.bits") / 8;
		case 'S':
			s = r_io_section_get (core->io, 
				r_io_section_vaddr_to_offset (core->io,
				core->offset));
			return s? (str[2]=='S'? s->size: s->offset): 0;
		case '?': return core->num->value;
		case '$': return core->offset;
		case 'o': return core->io->off;
		case 'C': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_CALL);
		case 'J': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_CODE);
		case 'D': return getref (core, atoi (str+2), 'r',
				R_ANAL_REF_TYPE_DATA);
		case 'X': return getref (core, atoi (str+2), 'x',
				R_ANAL_REF_TYPE_CALL);
		case 'I':
			fcn = r_anal_fcn_find (core->anal, core->offset, 0);
			return fcn? fcn->ninstr: 0;
		case 'F':
			fcn = r_anal_fcn_find (core->anal, core->offset, 0);
			return fcn? fcn->size: 0;
		}
	} else
	if (*str>'A') {
		if ((flag = r_flag_get (core->flags, str))) {
			ret = flag->offset;
			if (ok) *ok = R_TRUE;
		}
	}
	return ret;
}
Exemple #5
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;
}
Exemple #6
0
R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
	int ret, l, olen = len;
	int w = 0;

#if 0
	// HACK?: if io->va == 0 -> call seek+read without checking sections ?
	if (!io->va) {
	//	r_io_seek (io, addr, R_IO_SEEK_SET);
		r_io_map_select (io, addr);
		ret = r_io_read_internal (io, buf, len);
		if (io->cached) {
			r_io_cache_read (io, addr, buf, len);
		}
		return ret;
	}
#endif
// XXX: this is buggy!
	while (len>0) {
		int ms;
		ut64 last = r_io_section_next (io, addr);
		l = (len > (last-addr))? (last-addr): len;
		if (l<1) l = len;
		// ignore seek errors
//		eprintf ("0x%llx %llx\n", addr+w, 
		//r_io_seek (io, addr+w, R_IO_SEEK_SET);
		if (r_io_seek (io, addr+w, R_IO_SEEK_SET)==UT64_MAX) {
			memset (buf+w, 0xff, l);
			return -1;
		}
		ms = r_io_map_select (io, addr+w);
		ret = r_io_read_internal (io, buf+w, l);
		if (ret<1) {
			memset (buf+w, 0xff, l); // reading out of file
			ret = 1;
		} else if (ret<l) {
		//	eprintf ("FOUND EOF AT %llx\n", addr+ret);
			l = ret;
		}
		if (io->cached) {
			r_io_cache_read (io, addr+w, buf+w, l);
			/*
			 * XXX: The 'else' below is fixing the io.cache
			 * with resized files. That may be wrong
			 */
		} else
		// hide non-mapped files here
		// do not allow reading on real addresses if mapped != 0
		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);
			if (o == UT64_MAX) {
				ut64 o = r_io_section_vaddr_to_offset (io, addr);
				if (o == UT64_MAX)
					memset (buf+w, 0xff, l);
			}
			break;
		}
		w += l;
		len -= l;
	}
	return olen;
}