diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c index ae4b8849b1..b54267681e 100644 --- a/target/mips/tcg/sysemu/mips-semi.c +++ b/target/mips/tcg/sysemu/mips-semi.c @@ -198,21 +198,6 @@ static void uhi_fstat_cb(CPUState *cs, uint64_t ret, int err) uhi_cb(cs, ret, err); } -static int copy_argn_to_target(CPUMIPSState *env, int arg_num, - target_ulong vaddr) -{ - int strsize = strlen(semihosting_get_arg(arg_num)) + 1; - char *dst = lock_user(VERIFY_WRITE, vaddr, strsize, 0); - if (!dst) { - report_fault(env); - } - - strcpy(dst, semihosting_get_arg(arg_num)); - - unlock_user(dst, vaddr, strsize); - return 0; -} - #define GET_TARGET_STRING(p, addr) \ do { \ p = lock_user_string(addr); \ @@ -285,18 +270,31 @@ void mips_semihosting(CPUMIPSState *env) gpr[2] = semihosting_get_argc(); break; case UHI_argnlen: - if (gpr[4] >= semihosting_get_argc()) { - gpr[2] = -1; - return; + { + const char *s = semihosting_get_arg(gpr[4]); + gpr[2] = s ? strlen(s) : -1; } - gpr[2] = strlen(semihosting_get_arg(gpr[4])); break; case UHI_argn: - if (gpr[4] >= semihosting_get_argc()) { - gpr[2] = -1; - return; + { + const char *s = semihosting_get_arg(gpr[4]); + target_ulong addr; + size_t len; + + if (!s) { + gpr[2] = -1; + break; + } + len = strlen(s) + 1; + addr = gpr[5]; + p = lock_user(VERIFY_WRITE, addr, len, 0); + if (!p) { + report_fault(env); + } + memcpy(p, s, len); + unlock_user(p, addr, len); + gpr[2] = 0; } - gpr[2] = copy_argn_to_target(env, gpr[4], gpr[5]); break; case UHI_plog: