RZ_API int rz_core_analysis_fcn(RzCore *core, ut64 at, ut64 from, int reftype, int depth) {
	if (from == UT64_MAX && is_skippable_addr(core, at)) {
		if (core->analysis->verbose) {
			RZ_LOG_WARN("invalid address for function 0x%08" PFMT64x "\n", at);
		}
		return 0;
	}

	const bool use_esil = rz_config_get_i(core->config, "analysis.esil");
	RzAnalysisFunction *fcn;

	//update bits based on the core->offset otherwise we could have the
	//last value set and blow everything up
	rz_core_seek_arch_bits(core, at);

	if (core->io->va) {
		if (!rz_io_is_valid_offset(core->io, at, !core->analysis->opt.noncode)) {
			if (core->analysis->verbose) {
				RZ_LOG_WARN("address not mapped or not executable at 0x%08" PFMT64x "\n", at);
			}
			return false;
		}
	}
	if (use_esil) {
		return rz_core_analysis_esil_fcn(core, at, from, reftype, depth);
	}

	if ((from != UT64_MAX && !at) || at == UT64_MAX) {
		RZ_LOG_WARN("invalid address from 0x%08" PFMT64x "\n", from);
		return false;
	}
	if (depth < 0) {
		if (core->analysis->verbose) {
			RZ_LOG_WARN("analysis depth reached\n");
		}
		return false;
	}
	if (rz_cons_is_breaked()) {
		return false;
	}
	fcn = rz_analysis_get_fcn_in(core->analysis, at, 0);
	if (fcn) {
		if (fcn->addr == at) {
			// if the function was already analyzed as a "loc.",
			// convert it to function and rename it to "fcn.",
			// because we found a call to this address
			if (reftype == RZ_ANALYSIS_REF_TYPE_CALL && fcn->type == RZ_ANALYSIS_FCN_TYPE_LOC) {
				function_rename(core->flags, fcn);
			}

			return 0; // already analyzed function
		}
		if (rz_analysis_function_contains(fcn, from)) { // inner function
			RzList *l = rz_analysis_xrefs_get_to(core->analysis, from);
			if (l && !rz_list_empty(l)) {
				rz_list_free(l);
				return true;
			}
			rz_list_free(l);

			// we should analyze and add code ref otherwise aaa != aac
			if (from != UT64_MAX) {
				rz_analysis_xrefs_set(core->analysis, from, at, reftype);
			}
			return true;
		}
	}
	if (__core_analysis_fcn(core, at, from, reftype, depth - 1)) {
		// split function if overlaps
		if (fcn) {
			rz_analysis_function_resize(fcn, at - fcn->addr);
		}
		return true;
	}
	return false;
}
RZ_API int rz_core_analysis_fcn(RzCore *core, ut64 at, ut64 from, int reftype, int depth) {
	if (from == UT64_MAX && is_skippable_addr(core, at)) {
		if (core->analysis->verbose) {
			RZ_LOG_WARN("invalid address for function 0x%08" PFMT64x "\n", at);
		}
		return 0;
	}

	const bool use_esil = rz_config_get_i(core->config, "analysis.esil");
	RzAnalysisFunction *fcn;

	 
	 
	rz_core_seek_arch_bits(core, at);

	if (core->io->va) {
		if (!rz_io_is_valid_offset(core->io, at, !core->analysis->opt.noncode)) {
			if (core->analysis->verbose) {
				RZ_LOG_WARN("address not mapped or not executable at 0x%08" PFMT64x "\n", at);
			}
			return false;
		}
	}
	if (use_esil) {
		return rz_core_analysis_esil_fcn(core, at, from, reftype, depth);
	}

	if ((from != UT64_MAX && !at) || at == UT64_MAX) {
		RZ_LOG_WARN("invalid address from 0x%08" PFMT64x "\n", from);
		return false;
	}
	if (depth < 0) {
		if (core->analysis->verbose) {
			RZ_LOG_WARN("analysis depth reached\n");
		}
		return false;
	}
	if (rz_cons_is_breaked()) {
		return false;
	}
	fcn = rz_analysis_get_fcn_in(core->analysis, at, 0);
	if (fcn) {
		if (fcn->addr == at) {
			 
			 
			 
			if (reftype == RZ_ANALYSIS_REF_TYPE_CALL && fcn->type == RZ_ANALYSIS_FCN_TYPE_LOC) {
				function_rename(core->flags, fcn);
			}

			return 0;  
		}
		if (rz_analysis_function_contains(fcn, from)) {  
			RzList *l = rz_analysis_xrefs_get_to(core->analysis, from);
			if (l && !rz_list_empty(l)) {
				rz_list_free(l);
				return true;
			}
			rz_list_free(l);

			 
			if (from != UT64_MAX) {
				rz_analysis_xrefs_set(core->analysis, from, at, reftype);
			}
			return true;
		}
	}
	if (__core_analysis_fcn(core, at, from, reftype, depth - 1)) {
		 
		if (fcn) {
			rz_analysis_function_resize(fcn, at - fcn->addr);
		}
		return true;
	}
	return false;
}