diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-04-28 09:22:18 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-06-28 04:35:52 +0530 |
commit | 5eadbbfca6232710036ccb9f5cf1481be537c0e7 (patch) | |
tree | 3ba27eedd3c34826c8e778ab1955fcc0fc601f33 /semihosting/syscalls.c | |
parent | 5b3f39cb04fda32226e84502f858bab06d83e5c1 (diff) |
semihosting: Split out semihost_sys_close
Split out the non-ARM specific portions of SYS_CLOSE to a
reusable function. This handles all GuestFD.
Note that gdb_do_syscall %x reads target_ulong, not int.
Reviewed-by: Luc Michel <lmichel@kalray.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'semihosting/syscalls.c')
-rw-r--r-- | semihosting/syscalls.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index 9f9d19a59a..3648b9dd49 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -94,6 +94,12 @@ static void gdb_open(CPUState *cs, gdb_syscall_complete_cb complete, fname, len, (target_ulong)gdb_flags, (target_ulong)mode); } +static void gdb_close(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf) +{ + gdb_do_syscall(complete, "close,%x", (target_ulong)gf->hostfd); +} + /* * Host semihosting syscall implementations. */ @@ -140,6 +146,23 @@ static void host_open(CPUState *cs, gdb_syscall_complete_cb complete, unlock_user(p, fname, 0); } +static void host_close(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf) +{ + /* + * Only close the underlying host fd if it's one we opened on behalf + * of the guest in SYS_OPEN. + */ + if (gf->hostfd != STDIN_FILENO && + gf->hostfd != STDOUT_FILENO && + gf->hostfd != STDERR_FILENO && + close(gf->hostfd) < 0) { + complete(cs, -1, errno); + } else { + complete(cs, 0, 0); + } +} + /* * Syscall entry points. */ @@ -154,3 +177,27 @@ void semihost_sys_open(CPUState *cs, gdb_syscall_complete_cb complete, host_open(cs, complete, fname, fname_len, gdb_flags, mode); } } + +void semihost_sys_close(CPUState *cs, gdb_syscall_complete_cb complete, int fd) +{ + GuestFD *gf = get_guestfd(fd); + + if (!gf) { + complete(cs, -1, EBADF); + return; + } + switch (gf->type) { + case GuestFDGDB: + gdb_close(cs, complete, gf); + break; + case GuestFDHost: + host_close(cs, complete, gf); + break; + case GuestFDStatic: + complete(cs, 0, 0); + break; + default: + g_assert_not_reached(); + } + dealloc_guestfd(fd); +} |