RZ_API int rz_core_analysis_search_xrefs(RzCore *core, ut64 from, ut64 to, PJ *pj, int rad) {
	bool cfg_debug = rz_config_get_b(core->config, "cfg.debug");
	bool cfg_analysis_strings = rz_config_get_i(core->config, "analysis.strings");
	ut64 at;
	int count = 0;
	const int bsz = 8096;
	RzAnalysisOp op = { 0 };

	if (from == to) {
		return -1;
	}
	if (from > to) {
		eprintf("Invalid range (0x%" PFMT64x
			" >= 0x%" PFMT64x ")\n",
			from, to);
		return -1;
	}

	if (core->blocksize <= OPSZ) {
		eprintf("Error: block size too small\n");
		return -1;
	}
	ut8 *buf = malloc(bsz);
	if (!buf) {
		eprintf("Error: cannot allocate a block\n");
		return -1;
	}
	ut8 *block = malloc(bsz);
	if (!block) {
		eprintf("Error: cannot allocate a temp block\n");
		free(buf);
		return -1;
	}
	rz_cons_break_push(NULL, NULL);
	at = from;
	st64 asm_sub_varmin = rz_config_get_i(core->config, "asm.sub.varmin");
	while (at < to && !rz_cons_is_breaked()) {
		int i = 0, ret = bsz;
		if (!rz_io_is_valid_offset(core->io, at, RZ_PERM_X)) {
			break;
		}
		(void)rz_io_read_at(core->io, at, buf, bsz);
		memset(block, -1, bsz);
		if (!memcmp(buf, block, bsz)) {
			//	eprintf ("Error: skipping uninitialized block \n");
			at += ret;
			continue;
		}
		memset(block, 0, bsz);
		if (!memcmp(buf, block, bsz)) {
			//	eprintf ("Error: skipping uninitialized block \n");
			at += ret;
			continue;
		}
		while (i < bsz && !rz_cons_is_breaked()) {
			ret = rz_analysis_op(core->analysis, &op, at + i, buf + i, bsz - i, RZ_ANALYSIS_OP_MASK_BASIC | RZ_ANALYSIS_OP_MASK_HINT);
			ret = ret > 0 ? ret : 1;
			i += ret;
			if (ret <= 0 || i > bsz) {
				break;
			}
			// find references
			if ((st64)op.val > asm_sub_varmin && op.val != UT64_MAX && op.val != UT32_MAX) {
				if (found_xref(core, op.addr, op.val, RZ_ANALYSIS_REF_TYPE_DATA, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
			}
			// find references
			if (op.ptr && op.ptr != UT64_MAX && op.ptr != UT32_MAX) {
				if (found_xref(core, op.addr, op.ptr, RZ_ANALYSIS_REF_TYPE_DATA, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
			}
			// find references
			if (op.addr > 512 && op.disp > 512 && op.disp && op.disp != UT64_MAX) {
				if (found_xref(core, op.addr, op.disp, RZ_ANALYSIS_REF_TYPE_DATA, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
			}
			switch (op.type) {
			case RZ_ANALYSIS_OP_TYPE_JMP:
			case RZ_ANALYSIS_OP_TYPE_CJMP:
				if (found_xref(core, op.addr, op.jump, RZ_ANALYSIS_REF_TYPE_CODE, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
				break;
			case RZ_ANALYSIS_OP_TYPE_CALL:
			case RZ_ANALYSIS_OP_TYPE_CCALL:
				if (found_xref(core, op.addr, op.jump, RZ_ANALYSIS_REF_TYPE_CALL, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
				break;
			case RZ_ANALYSIS_OP_TYPE_UJMP:
			case RZ_ANALYSIS_OP_TYPE_IJMP:
			case RZ_ANALYSIS_OP_TYPE_RJMP:
			case RZ_ANALYSIS_OP_TYPE_IRJMP:
			case RZ_ANALYSIS_OP_TYPE_MJMP:
			case RZ_ANALYSIS_OP_TYPE_UCJMP:
				count++;
				if (found_xref(core, op.addr, op.ptr, RZ_ANALYSIS_REF_TYPE_CODE, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
				break;
			case RZ_ANALYSIS_OP_TYPE_UCALL:
			case RZ_ANALYSIS_OP_TYPE_ICALL:
			case RZ_ANALYSIS_OP_TYPE_RCALL:
			case RZ_ANALYSIS_OP_TYPE_IRCALL:
			case RZ_ANALYSIS_OP_TYPE_UCCALL:
				if (found_xref(core, op.addr, op.ptr, RZ_ANALYSIS_REF_TYPE_CALL, pj, rad, cfg_debug, cfg_analysis_strings)) {
					count++;
				}
				break;
			default:
				break;
			}
			rz_analysis_op_fini(&op);
		}
		at += bsz;
		rz_analysis_op_fini(&op);
	}
	rz_cons_break_pop();
	free(buf);
	free(block);
	return count;
}