diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-04-29 09:05:36 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-06-28 04:35:52 +0530 |
commit | a6300ed6b7ecd19eb5ae0fd8a3eb876681cb8e6e (patch) | |
tree | 6be1931b6ed81ecf06d1409f986e9313960019c2 /semihosting/syscalls.c | |
parent | a2212474301bc354bea46e3bdc6c21e33e0b5b2b (diff) |
semihosting: Split out semihost_sys_flen
The ARM-specific SYS_FLEN isn't really something that can be
reused by other semihosting apis, but there are parts that can
reused for the implementation of semihost_sys_fstat.
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 | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index 1f1baf7e2d..fff9550c89 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -127,6 +127,12 @@ static void gdb_isatty(CPUState *cs, gdb_syscall_complete_cb complete, gdb_do_syscall(complete, "isatty,%x", (target_ulong)gf->hostfd); } +static void gdb_fstat(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf, target_ulong addr) +{ + gdb_do_syscall(complete, "fstat,%x,%x", (target_ulong)gf->hostfd, addr); +} + /* * Host semihosting syscall implementations. */ @@ -259,6 +265,18 @@ static void host_isatty(CPUState *cs, gdb_syscall_complete_cb complete, complete(cs, ret, ret ? 0 : errno); } +static void host_flen(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf) +{ + struct stat buf; + + if (fstat(gf->hostfd, &buf) < 0) { + complete(cs, -1, errno); + } else { + complete(cs, buf.st_size, 0); + } +} + /* * Static file semihosting syscall implementations. */ @@ -311,6 +329,12 @@ static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete, } } +static void staticfile_flen(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf) +{ + complete(cs, gf->staticfile.len, 0); +} + /* * Syscall entry points. */ @@ -473,3 +497,28 @@ void semihost_sys_isatty(CPUState *cs, gdb_syscall_complete_cb complete, int fd) g_assert_not_reached(); } } + +void semihost_sys_flen(CPUState *cs, gdb_syscall_complete_cb fstat_cb, + gdb_syscall_complete_cb flen_cb, int fd, + target_ulong fstat_addr) +{ + GuestFD *gf = get_guestfd(fd); + + if (!gf) { + flen_cb(cs, -1, EBADF); + return; + } + switch (gf->type) { + case GuestFDGDB: + gdb_fstat(cs, fstat_cb, gf, fstat_addr); + break; + case GuestFDHost: + host_flen(cs, flen_cb, gf); + break; + case GuestFDStatic: + staticfile_flen(cs, flen_cb, gf); + break; + default: + g_assert_not_reached(); + } +} |