diff options
author | Alex Bennée <alex.bennee@linaro.org> | 2019-05-30 15:35:14 +0100 |
---|---|---|
committer | Alex Bennée <alex.bennee@linaro.org> | 2019-06-12 17:53:22 +0100 |
commit | 78e24848f6a2923f356d15d8751c644f94a39fd8 (patch) | |
tree | f9a6d5636870a08f820e9186ade7738dd656487f /hw/semihosting | |
parent | 3ace9be6d267b2f876ebb34096fe5d9b64a82d9a (diff) |
semihosting: split console_out into string and char versions
This is ostensibly to avoid the weirdness of len looking like it might
come from a guest and sometimes being used. While we are at it fix up
the error checking for the arm-linux-user implementation of the API
which got flagged up by Coverity (CID 1401700).
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Diffstat (limited to 'hw/semihosting')
-rw-r--r-- | hw/semihosting/console.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c index 4ab7533bb8..b4b17c8afb 100644 --- a/hw/semihosting/console.c +++ b/hw/semihosting/console.c @@ -36,26 +36,24 @@ int qemu_semihosting_log_out(const char *s, int len) /* * A re-implementation of lock_user_string that we can use locally * instead of relying on softmmu-semi. Hopefully we can deprecate that - * in time. We either copy len bytes if specified or until we find a NULL. + * in time. Copy string until we find a 0 or address error. */ -static GString *copy_user_string(CPUArchState *env, target_ulong addr, int len) +static GString *copy_user_string(CPUArchState *env, target_ulong addr) { CPUState *cpu = env_cpu(env); - GString *s = g_string_sized_new(len ? len : 128); + GString *s = g_string_sized_new(128); uint8_t c; - bool done; do { if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) { s = g_string_append_c(s, c); - done = len ? s->len == len : c == 0; } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: passed inaccessible address " TARGET_FMT_lx, __func__, addr); - done = true; + break; } - } while (!done); + } while (c!=0); return s; } @@ -68,9 +66,9 @@ static void semihosting_cb(CPUState *cs, target_ulong ret, target_ulong err) } } -int qemu_semihosting_console_out(CPUArchState *env, target_ulong addr, int len) +int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr) { - GString *s = copy_user_string(env, addr, len); + GString *s = copy_user_string(env, addr); int out = s->len; if (use_gdb_syscalls()) { @@ -82,3 +80,21 @@ int qemu_semihosting_console_out(CPUArchState *env, target_ulong addr, int len) g_string_free(s, true); return out; } + +void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr) +{ + CPUState *cpu = env_cpu(env); + uint8_t c; + + if (cpu_memory_rw_debug(cpu, addr, &c, 1, 0) == 0) { + if (use_gdb_syscalls()) { + gdb_do_syscall(semihosting_cb, "write,2,%x,%x", addr, 1); + } else { + qemu_semihosting_log_out((const char *) &c, 1); + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: passed inaccessible address " TARGET_FMT_lx, + __func__, addr); + } +} |