mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
target-m68k/m68k-semi: Handle get_user failure
Handle failure of get_user accessing the semihosting argument block, rather than simply ignoring the failures. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
aed91c1bff
commit
7ba6c10490
1 changed files with 93 additions and 51 deletions
|
@ -153,17 +153,21 @@ static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
|
||||||
put_user_u32(err, args + 4);
|
put_user_u32(err, args + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARG(n) \
|
/* Read the input value from the argument block; fail the semihosting
|
||||||
({ \
|
* call if the memory read fails.
|
||||||
target_ulong __arg; \
|
*/
|
||||||
/* FIXME - handle get_user() failure */ \
|
#define GET_ARG(n) do { \
|
||||||
get_user_ual(__arg, args + (n) * 4); \
|
if (get_user_ual(arg ## n, args + (n) * 4)) { \
|
||||||
__arg; \
|
result = -1; \
|
||||||
})
|
errno = EFAULT; \
|
||||||
#define PARG(x) ((unsigned long)ARG(x))
|
goto failed; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
void do_m68k_semihosting(CPUM68KState *env, int nr)
|
void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
{
|
{
|
||||||
uint32_t args;
|
uint32_t args;
|
||||||
|
target_ulong arg0, arg1, arg2, arg3;
|
||||||
void *p;
|
void *p;
|
||||||
void *q;
|
void *q;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
@ -175,27 +179,33 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
gdb_exit(env, env->dregs[0]);
|
gdb_exit(env, env->dregs[0]);
|
||||||
exit(env->dregs[0]);
|
exit(env->dregs[0]);
|
||||||
case HOSTED_OPEN:
|
case HOSTED_OPEN:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
|
GET_ARG(3);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
|
gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", arg0, (int)arg1,
|
||||||
ARG(2), ARG(3));
|
arg2, arg3);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = lock_user_string(ARG(0)))) {
|
p = lock_user_string(arg0);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = open(p, translate_openflags(ARG(2)), ARG(3));
|
result = open(p, translate_openflags(arg2), arg3);
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_CLOSE:
|
case HOSTED_CLOSE:
|
||||||
{
|
{
|
||||||
/* Ignore attempts to close stdin/out/err. */
|
/* Ignore attempts to close stdin/out/err. */
|
||||||
int fd = ARG(0);
|
GET_ARG(0);
|
||||||
|
int fd = arg0;
|
||||||
if (fd > 2) {
|
if (fd > 2) {
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
|
gdb_do_syscall(m68k_semi_cb, "close,%x", arg0);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
result = close(fd);
|
result = close(fd);
|
||||||
|
@ -206,47 +216,59 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HOSTED_READ:
|
case HOSTED_READ:
|
||||||
len = ARG(2);
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
|
len = arg2;
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
|
gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
|
||||||
ARG(0), ARG(1), len);
|
arg0, arg1, len);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
|
p = lock_user(VERIFY_WRITE, arg1, len, 0);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = read(ARG(0), p, len);
|
result = read(arg0, p, len);
|
||||||
unlock_user(p, ARG(1), len);
|
unlock_user(p, arg1, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_WRITE:
|
case HOSTED_WRITE:
|
||||||
len = ARG(2);
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
|
len = arg2;
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
|
gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
|
||||||
ARG(0), ARG(1), len);
|
arg0, arg1, len);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
|
p = lock_user(VERIFY_READ, arg1, len, 1);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = write(ARG(0), p, len);
|
result = write(arg0, p, len);
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_LSEEK:
|
case HOSTED_LSEEK:
|
||||||
{
|
{
|
||||||
uint64_t off;
|
uint64_t off;
|
||||||
off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
|
GET_ARG(3);
|
||||||
|
off = (uint32_t)arg2 | ((uint64_t)arg1 << 32);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
m68k_semi_is_fseek = 1;
|
m68k_semi_is_fseek = 1;
|
||||||
gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
|
gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
|
||||||
ARG(0), off, ARG(3));
|
arg0, off, arg3);
|
||||||
} else {
|
} else {
|
||||||
off = lseek(ARG(0), off, ARG(3));
|
off = lseek(arg0, off, arg3);
|
||||||
/* FIXME - handle put_user() failure */
|
/* FIXME - handle put_user() failure */
|
||||||
put_user_u32(off >> 32, args);
|
put_user_u32(off >> 32, args);
|
||||||
put_user_u32(off, args + 4);
|
put_user_u32(off, args + 4);
|
||||||
|
@ -255,74 +277,89 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case HOSTED_RENAME:
|
case HOSTED_RENAME:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
|
GET_ARG(3);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
|
gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
|
||||||
ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
|
arg0, (int)arg1, arg2, (int)arg3);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
p = lock_user_string(ARG(0));
|
p = lock_user_string(arg0);
|
||||||
q = lock_user_string(ARG(2));
|
q = lock_user_string(arg2);
|
||||||
if (!p || !q) {
|
if (!p || !q) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = rename(p, q);
|
result = rename(p, q);
|
||||||
}
|
}
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
unlock_user(q, ARG(2), 0);
|
unlock_user(q, arg2, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_UNLINK:
|
case HOSTED_UNLINK:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "unlink,%s",
|
gdb_do_syscall(m68k_semi_cb, "unlink,%s",
|
||||||
ARG(0), (int)ARG(1));
|
arg0, (int)arg1);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = lock_user_string(ARG(0)))) {
|
p = lock_user_string(arg0);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = unlink(p);
|
result = unlink(p);
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_STAT:
|
case HOSTED_STAT:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
|
GET_ARG(2);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
|
gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
|
||||||
ARG(0), (int)ARG(1), ARG(2));
|
arg0, (int)arg1, arg2);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if (!(p = lock_user_string(ARG(0)))) {
|
p = lock_user_string(arg0);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = stat(p, &s);
|
result = stat(p, &s);
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
translate_stat(env, ARG(2), &s);
|
translate_stat(env, arg2, &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_FSTAT:
|
case HOSTED_FSTAT:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
|
gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
|
||||||
ARG(0), ARG(1));
|
arg0, arg1);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
result = fstat(ARG(0), &s);
|
result = fstat(arg0, &s);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
translate_stat(env, ARG(1), &s);
|
translate_stat(env, arg1, &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_GETTIMEOFDAY:
|
case HOSTED_GETTIMEOFDAY:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
|
gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
|
||||||
ARG(0), ARG(1));
|
arg0, arg1);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
qemu_timeval tv;
|
qemu_timeval tv;
|
||||||
|
@ -330,37 +367,41 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
result = qemu_gettimeofday(&tv);
|
result = qemu_gettimeofday(&tv);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if (!(p = lock_user(VERIFY_WRITE,
|
if (!(p = lock_user(VERIFY_WRITE,
|
||||||
ARG(0), sizeof(struct gdb_timeval), 0))) {
|
arg0, sizeof(struct gdb_timeval), 0))) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
p->tv_sec = cpu_to_be32(tv.tv_sec);
|
p->tv_sec = cpu_to_be32(tv.tv_sec);
|
||||||
p->tv_usec = cpu_to_be64(tv.tv_usec);
|
p->tv_usec = cpu_to_be64(tv.tv_usec);
|
||||||
unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
|
unlock_user(p, arg0, sizeof(struct gdb_timeval));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_ISATTY:
|
case HOSTED_ISATTY:
|
||||||
|
GET_ARG(0);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
|
gdb_do_syscall(m68k_semi_cb, "isatty,%x", arg0);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
result = isatty(ARG(0));
|
result = isatty(arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOSTED_SYSTEM:
|
case HOSTED_SYSTEM:
|
||||||
|
GET_ARG(0);
|
||||||
|
GET_ARG(1);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
gdb_do_syscall(m68k_semi_cb, "system,%s",
|
gdb_do_syscall(m68k_semi_cb, "system,%s",
|
||||||
ARG(0), (int)ARG(1));
|
arg0, (int)arg1);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = lock_user_string(ARG(0)))) {
|
p = lock_user_string(arg0);
|
||||||
|
if (!p) {
|
||||||
/* FIXME - check error code? */
|
/* FIXME - check error code? */
|
||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
result = system(p);
|
result = system(p);
|
||||||
unlock_user(p, ARG(0), 0);
|
unlock_user(p, arg0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -402,6 +443,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
|
||||||
cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
|
cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
failed:
|
||||||
/* FIXME - handle put_user() failure */
|
/* FIXME - handle put_user() failure */
|
||||||
put_user_u32(result, args);
|
put_user_u32(result, args);
|
||||||
put_user_u32(errno, args + 4);
|
put_user_u32(errno, args + 4);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue