RZ_IPI void rz_core_analysis_value_pointers(RzCore *core, RzOutputMode mode) {
	ut64 o_align = rz_config_get_i(core->config, "search.align");
	const char *analysisin = rz_config_get(core->config, "analysis.in");
	char *tmp = strdup(analysisin);
	bool is_debug = rz_config_get_b(core->config, "cfg.debug");
	int archAlign = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_ALIGN);
	rz_config_set_i(core->config, "search.align", archAlign);
	rz_config_set(core->config, "analysis.in", "io.maps.x");
	const char *oldstr = rz_print_rowlog(core->print, "Finding xrefs in noncode section with analysis.in=io.maps");
	rz_print_rowlog_done(core->print, oldstr);

	int vsize = 4; // 32bit dword
	if (core->rasm->bits == 64) {
		vsize = 8;
	}

	// body
	oldstr = rz_print_rowlog(core->print, "Analyze value pointers (aav)");
	rz_print_rowlog_done(core->print, oldstr);
	rz_cons_break_push(NULL, NULL);
	if (is_debug) {
		RzList *list = rz_core_get_boundaries_prot(core, 0, "dbg.map", "analysis");
		RzListIter *iter;
		RzIOMap *map;
		if (!list) {
			goto beach;
		}
		rz_list_foreach (list, iter, map) {
			if (rz_cons_is_breaked()) {
				break;
			}
			oldstr = rz_print_rowlog(core->print, sdb_fmt("from 0x%" PFMT64x " to 0x%" PFMT64x " (aav)", map->itv.addr, rz_itv_end(map->itv)));
			rz_print_rowlog_done(core->print, oldstr);
			(void)rz_core_search_value_in_range(core, map->itv,
				map->itv.addr, rz_itv_end(map->itv), vsize, _CbInRangeAav, (void *)&mode);
		}
		rz_list_free(list);
	} else {
		RzList *list = rz_core_get_boundaries_prot(core, 0, NULL, "analysis");
		if (!list) {
			goto beach;
		}
		RzListIter *iter, *iter2;
		RzIOMap *map, *map2;
		ut64 from = UT64_MAX;
		ut64 to = UT64_MAX;
		// find values pointing to non-executable regions
		rz_list_foreach (list, iter2, map2) {
			if (rz_cons_is_breaked()) {
				break;
			}
			//TODO: Reduce multiple hits for same addr
			from = rz_itv_begin(map2->itv);
			to = rz_itv_end(map2->itv);
			oldstr = rz_print_rowlog(core->print, sdb_fmt("Value from 0x%08" PFMT64x " to 0x%08" PFMT64x " (aav)", from, to));
			if ((to - from) > MAX_SCAN_SIZE) {
				eprintf("Warning: Skipping large region\n");
				continue;
			}
			rz_print_rowlog_done(core->print, oldstr);
			rz_list_foreach (list, iter, map) {
				ut64 begin = map->itv.addr;
				ut64 end = rz_itv_end(map->itv);
				if (rz_cons_is_breaked()) {
					break;
				}
				if (end - begin > UT32_MAX) {
					oldstr = rz_print_rowlog(core->print, "Skipping huge range");
					rz_print_rowlog_done(core->print, oldstr);
					continue;
				}
				oldstr = rz_print_rowlog(core->print, sdb_fmt("0x%08" PFMT64x "-0x%08" PFMT64x " in 0x%" PFMT64x "-0x%" PFMT64x " (aav)", from, to, begin, end));
				rz_print_rowlog_done(core->print, oldstr);
				(void)rz_core_search_value_in_range(core, map->itv, from, to, vsize, _CbInRangeAav, (void *)&mode);
			}
		}
		rz_list_free(list);
	}
beach:
	rz_cons_break_pop();
	// end
	rz_config_set(core->config, "analysis.in", tmp);
	free(tmp);
	rz_config_set_i(core->config, "search.align", o_align);
}
RZ_IPI void rz_core_analysis_value_pointers(RzCore *core, RzOutputMode mode) {
	ut64 o_align = rz_config_get_i(core->config, "search.align");
	const char *analysisin = rz_config_get(core->config, "analysis.in");
	char *tmp = strdup(analysisin);
	bool is_debug = rz_config_get_b(core->config, "cfg.debug");
	int archAlign = rz_analysis_archinfo(core->analysis, RZ_ANALYSIS_ARCHINFO_ALIGN);
	rz_config_set_i(core->config, "search.align", archAlign);
	rz_config_set(core->config, "analysis.in", "io.maps.x");
	const char *oldstr = rz_print_rowlog(core->print, "Finding xrefs in noncode section with analysis.in=io.maps");
	rz_print_rowlog_done(core->print, oldstr);

	int vsize = 4;  
	if (core->rasm->bits == 64) {
		vsize = 8;
	}

	 
	oldstr = rz_print_rowlog(core->print, "Analyze value pointers (aav)");
	rz_print_rowlog_done(core->print, oldstr);
	rz_cons_break_push(NULL, NULL);
	if (is_debug) {
		RzList *list = rz_core_get_boundaries_prot(core, 0, "dbg.map", "analysis");
		RzListIter *iter;
		RzIOMap *map;
		if (!list) {
			goto beach;
		}
		rz_list_foreach (list, iter, map) {
			if (rz_cons_is_breaked()) {
				break;
			}
			oldstr = rz_print_rowlog(core->print, sdb_fmt("from 0x%" PFMT64x " to 0x%" PFMT64x " (aav)", map->itv.addr, rz_itv_end(map->itv)));
			rz_print_rowlog_done(core->print, oldstr);
			(void)rz_core_search_value_in_range(core, map->itv,
				map->itv.addr, rz_itv_end(map->itv), vsize, _CbInRangeAav, (void *)&mode);
		}
		rz_list_free(list);
	} else {
		RzList *list = rz_core_get_boundaries_prot(core, 0, NULL, "analysis");
		if (!list) {
			goto beach;
		}
		RzListIter *iter, *iter2;
		RzIOMap *map, *map2;
		ut64 from = UT64_MAX;
		ut64 to = UT64_MAX;
		 
		rz_list_foreach (list, iter2, map2) {
			if (rz_cons_is_breaked()) {
				break;
			}
			 
			from = rz_itv_begin(map2->itv);
			to = rz_itv_end(map2->itv);
			oldstr = rz_print_rowlog(core->print, sdb_fmt("Value from 0x%08" PFMT64x " to 0x%08" PFMT64x " (aav)", from, to));
			if ((to - from) > MAX_SCAN_SIZE) {
				eprintf("Warning: Skipping large region\n");
				continue;
			}
			rz_print_rowlog_done(core->print, oldstr);
			rz_list_foreach (list, iter, map) {
				ut64 begin = map->itv.addr;
				ut64 end = rz_itv_end(map->itv);
				if (rz_cons_is_breaked()) {
					break;
				}
				if (end - begin > UT32_MAX) {
					oldstr = rz_print_rowlog(core->print, "Skipping huge range");
					rz_print_rowlog_done(core->print, oldstr);
					continue;
				}
				oldstr = rz_print_rowlog(core->print, sdb_fmt("0x%08" PFMT64x "-0x%08" PFMT64x " in 0x%" PFMT64x "-0x%" PFMT64x " (aav)", from, to, begin, end));
				rz_print_rowlog_done(core->print, oldstr);
				(void)rz_core_search_value_in_range(core, map->itv, from, to, vsize, _CbInRangeAav, (void *)&mode);
			}
		}
		rz_list_free(list);
	}
beach:
	rz_cons_break_pop();
	 
	rz_config_set(core->config, "analysis.in", tmp);
	free(tmp);
	rz_config_set_i(core->config, "search.align", o_align);
}