env->boot_info is only set in some ARM startup paths, so we cannot rely on it to support the SYS_HEAPINFO semihosting function. When not available, fallback to finding a RAM memory region containing the current stack and use the base of that. Signed-off-by: Keith Packard --- v2 Explicitly convert 64-bits to 128-bits in find_region_base for hosts that don't have native 128-bit int type. --- hw/semihosting/common-semi.c | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c index 33c82f73b1..f09deff4d3 100644 --- a/hw/semihosting/common-semi.c +++ b/hw/semihosting/common-semi.c @@ -137,6 +137,36 @@ typedef struct GuestFD { static GArray *guestfd_array; +#ifndef CONFIG_USER_ONLY +#include "exec/address-spaces.h" +/* + * Find the base of a RAM region containing the specified address + */ +static inline hwaddr +common_semi_find_region_base(hwaddr addr) +{ + MemoryRegion *subregion; + + /* + * Find the chunk of R/W memory containing the address. This is + * used for the SYS_HEAPINFO semihosting call, which should + * probably be using information from the loaded application. + */ + QTAILQ_FOREACH(subregion, &get_system_memory()->subregions, + subregions_link) { + if (subregion->ram && !subregion->readonly) { + Int128 top128 = int128_add(int128_make64(subregion->addr), + subregion->size); + Int128 addr128 = int128_make64(addr); + if (subregion->addr <= addr && int128_lt(addr128, top128)) { + return subregion->addr; + } + } + } + return 0; +} +#endif + #ifdef TARGET_ARM static inline target_ulong common_semi_arg(CPUState *cs, int argno) @@ -175,7 +205,18 @@ common_semi_rambase(CPUState *cs) { CPUArchState *env = cs->env_ptr; const struct arm_boot_info *info = env->boot_info; - return info->loader_start; + target_ulong sp; + + if (info) { + return info->loader_start; + } + + if (is_a64(env)) { + sp = env->xregs[31]; + } else { + sp = env->regs[13]; + } + return common_semi_find_region_base(sp); } #endif -- 2.29.2