[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 25/43] semihosting: Split out semihost_sys_lseek
From: |
Richard Henderson |
Subject: |
[PATCH 25/43] semihosting: Split out semihost_sys_lseek |
Date: |
Sat, 30 Apr 2022 06:29:14 -0700 |
Split out the non-ARM specific portions of SYS_SEEK to a
reusable function. This handles all GuestFD. Isolate the
curious ARM-specific return value processing to a new
callback, common_semi_seek_cb.
Expand the internal type of the offset to int64_t, and
provide the whence argument, which will be required by m68k
and nios2 semihosting.
Note that gdb_do_syscall %x reads target_ulong, not int.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/gdbstub.h | 5 +++
include/semihosting/guestfd.h | 3 ++
semihosting/arm-compat-semi.c | 51 ++++++----------------
semihosting/guestfd.c | 81 +++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 38 deletions(-)
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 33a262a5a3..a7d3bfd5d4 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -20,6 +20,11 @@
#define GDB_O_TRUNC 0x400
#define GDB_O_EXCL 0x800
+/* For gdb file i/o remote protocol lseek whence. */
+#define GDB_SEEK_SET 0
+#define GDB_SEEK_CUR 1
+#define GDB_SEEK_END 2
+
/* For gdb file i/o stat/fstat. */
typedef uint32_t gdb_mode_t;
typedef uint32_t gdb_time_t;
diff --git a/include/semihosting/guestfd.h b/include/semihosting/guestfd.h
index 5780ea2f13..9c6967ac53 100644
--- a/include/semihosting/guestfd.h
+++ b/include/semihosting/guestfd.h
@@ -62,4 +62,7 @@ void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb
complete,
void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete,
int fd, target_ulong buf, target_ulong len);
+void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
+ int fd, int64_t off, int gdb_whence);
+
#endif /* SEMIHOSTING_GUESTFD_H */
diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 6568d205eb..0cab721a50 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -225,16 +225,6 @@ static void common_semi_cb(CPUState *cs, target_ulong ret,
target_ulong err)
#else
syscall_err = err;
#endif
- } else {
- /* Fixup syscalls that use nonstardard return conventions. */
- target_ulong reg0 = common_semi_arg(cs, 0);
- switch (reg0) {
- case TARGET_SYS_SEEK:
- ret = 0;
- break;
- default:
- break;
- }
}
common_semi_set_ret(cs, ret);
}
@@ -257,6 +247,18 @@ static void common_semi_rw_cb(CPUState *cs, target_ulong
ret, target_ulong err)
common_semi_set_ret(cs, arg2 - ret);
}
+/*
+ * SYS_SEEK returns 0 on success, not the resulting offset.
+ */
+static void common_semi_seek_cb(CPUState *cs, target_ulong ret,
+ target_ulong err)
+{
+ if (!err) {
+ ret = 0;
+ }
+ common_semi_cb(cs, ret, err);
+}
+
/*
* Return an address in target memory of 64 bytes where the remote
* gdb should write its stat struct. (The format of this structure
@@ -289,7 +291,6 @@ common_semi_flen_cb(CPUState *cs, target_ulong ret,
target_ulong err)
* via common_semi_cb.
*/
typedef void sys_isattyfn(CPUState *cs, GuestFD *gf);
-typedef void sys_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset);
typedef void sys_flenfn(CPUState *cs, GuestFD *gf);
static void host_isattyfn(CPUState *cs, GuestFD *gf)
@@ -297,12 +298,6 @@ static void host_isattyfn(CPUState *cs, GuestFD *gf)
common_semi_cb(cs, isatty(gf->hostfd), 0);
}
-static void host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
-{
- off_t ret = lseek(gf->hostfd, offset, SEEK_SET);
- common_semi_cb(cs, ret, ret == -1 ? errno : 0);
-}
-
static void host_flenfn(CPUState *cs, GuestFD *gf)
{
struct stat buf;
@@ -319,11 +314,6 @@ static void gdb_isattyfn(CPUState *cs, GuestFD *gf)
gdb_do_syscall(common_semi_cb, "isatty,%x", gf->hostfd);
}
-static void gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
-{
- gdb_do_syscall(common_semi_cb, "lseek,%x,%x,0", gf->hostfd, offset);
-}
-
static void gdb_flenfn(CPUState *cs, GuestFD *gf)
{
gdb_do_syscall(common_semi_flen_cb, "fstat,%x,%x",
@@ -352,12 +342,6 @@ static void staticfile_isattyfn(CPUState *cs, GuestFD *gf)
common_semi_cb(cs, 0, 0);
}
-static void staticfile_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
-{
- gf->staticfile.off = offset;
- common_semi_cb(cs, 0, 0);
-}
-
static void staticfile_flenfn(CPUState *cs, GuestFD *gf)
{
common_semi_cb(cs, gf->staticfile.len, 0);
@@ -365,24 +349,20 @@ static void staticfile_flenfn(CPUState *cs, GuestFD *gf)
typedef struct GuestFDFunctions {
sys_isattyfn *isattyfn;
- sys_seekfn *seekfn;
sys_flenfn *flenfn;
} GuestFDFunctions;
static const GuestFDFunctions guestfd_fns[] = {
[GuestFDHost] = {
.isattyfn = host_isattyfn,
- .seekfn = host_seekfn,
.flenfn = host_flenfn,
},
[GuestFDGDB] = {
.isattyfn = gdb_isattyfn,
- .seekfn = gdb_seekfn,
.flenfn = gdb_flenfn,
},
[GuestFDStatic] = {
.isattyfn = staticfile_isattyfn,
- .seekfn = staticfile_seekfn,
.flenfn = staticfile_flenfn,
},
};
@@ -518,12 +498,7 @@ void do_common_semihosting(CPUState *cs)
case TARGET_SYS_SEEK:
GET_ARG(0);
GET_ARG(1);
-
- gf = get_guestfd(arg0);
- if (!gf) {
- goto do_badf;
- }
- guestfd_fns[gf->type].seekfn(cs, gf, arg1);
+ semihost_sys_lseek(cs, common_semi_seek_cb, arg0, arg1, GDB_SEEK_SET);
break;
case TARGET_SYS_FLEN:
diff --git a/semihosting/guestfd.c b/semihosting/guestfd.c
index 356b87453c..e33d226534 100644
--- a/semihosting/guestfd.c
+++ b/semihosting/guestfd.c
@@ -442,3 +442,84 @@ void semihost_sys_write(CPUState *cs,
gdb_syscall_complete_cb complete,
g_assert_not_reached();
}
}
+
+static void gdb_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
+ GuestFD *gf, int64_t off, int gdb_whence)
+{
+ gdb_do_syscall(complete, "lseek,%x,%lx,%x",
+ (target_ulong)gf->hostfd, off, (target_ulong)gdb_whence);
+}
+
+static void host_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
+ GuestFD *gf, int64_t off, int whence)
+{
+ /* So far, all hosts use the same values. */
+ QEMU_BUILD_BUG_ON(GDB_SEEK_SET != SEEK_SET);
+ QEMU_BUILD_BUG_ON(GDB_SEEK_CUR != SEEK_CUR);
+ QEMU_BUILD_BUG_ON(GDB_SEEK_END != SEEK_END);
+
+ off_t ret = off;
+ int err = 0;
+
+ if (ret == off) {
+ ret = lseek(gf->hostfd, ret, whence);
+ if (ret == -1) {
+ err = errno;
+ }
+ } else {
+ ret = -1;
+ err = EOVERFLOW;
+ }
+ complete(cs, ret, err);
+}
+
+static void staticfile_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
+ GuestFD *gf, int64_t off, int gdb_whence)
+{
+ int64_t ret;
+
+ switch (gdb_whence) {
+ case GDB_SEEK_SET:
+ ret = off;
+ break;
+ case GDB_SEEK_CUR:
+ ret = gf->staticfile.off + off;
+ break;
+ case GDB_SEEK_END:
+ ret = gf->staticfile.len - off;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ if (ret >= 0 && ret <= gf->staticfile.len) {
+ gf->staticfile.off = ret;
+ complete(cs, ret, 0);
+ } else {
+ complete(cs, -1, EINVAL);
+ }
+}
+
+void semihost_sys_lseek(CPUState *cs, gdb_syscall_complete_cb complete,
+ int fd, int64_t off, int gdb_whence)
+{
+ GuestFD *gf = get_guestfd(fd);
+
+ if (!gf) {
+ complete(cs, -1, EBADF);
+ return;
+ }
+ switch (gf->type) {
+ case GuestFDGDB:
+ gdb_lseek(cs, complete, gf, off, gdb_whence);
+ return;
+ case GuestFDHost:
+ host_lseek(cs, complete, gf, off, gdb_whence);
+ break;
+ case GuestFDStatic:
+ staticfile_lseek(cs, complete, gf, off, gdb_whence);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
--
2.34.1
- [PATCH 00/43] semihosting cleanup, Richard Henderson, 2022/04/30
- [PATCH 01/43] semihosting: Move exec/softmmu-semi.h to semihosting/softmmu-uaccess.h, Richard Henderson, 2022/04/30
- [PATCH 03/43] semihosting: Improve condition for config.c and console.c, Richard Henderson, 2022/04/30
- [PATCH 04/43] semihosting: Move softmmu-uaccess functions out of line, Richard Henderson, 2022/04/30
- [PATCH 07/43] semihosting: Split out guestfd.c, Richard Henderson, 2022/04/30
- [PATCH 10/43] semihosting: Adjust error checking in common_semi_cb, Richard Henderson, 2022/04/30
- [PATCH 02/43] semihosting: Return failure from softmmu-uaccess.h functions, Richard Henderson, 2022/04/30
- [PATCH 11/43] semihosting: Move common-semi.h to include/semihosting/, Richard Henderson, 2022/04/30
- [PATCH 17/43] semihosting: Split out common_semi_has_synccache, Richard Henderson, 2022/04/30
- [PATCH 13/43] include/exec: Move gdb_stat and gdb_timeval to gdbstub.h, Richard Henderson, 2022/04/30
- [PATCH 25/43] semihosting: Split out semihost_sys_lseek,
Richard Henderson <=
- [PATCH 12/43] include/exec: Move gdb open flags to gdbstub.h, Richard Henderson, 2022/04/30
- [PATCH 05/43] semihosting: Add target_strlen for softmmu-uaccess.h, Richard Henderson, 2022/04/30
- [PATCH 20/43] semihosting: Split out semihost_sys_open, Richard Henderson, 2022/04/30
- [PATCH 19/43] semihosting: Move GET_ARG/SET_ARG earlier in the file, Richard Henderson, 2022/04/30
- [PATCH 24/43] semihosting: Bound length for semihost_sys_{read, write}, Richard Henderson, 2022/04/30
- [PATCH 33/43] gdbstub: Widen gdb_syscall_complete_cb return value, Richard Henderson, 2022/04/30
- [PATCH 35/43] target/m68k: Make semihosting system only, Richard Henderson, 2022/04/30
- [PATCH 39/43] target/m68k: Remove EXCP_HALT_INSN, Richard Henderson, 2022/04/30
- [PATCH 09/43] semihosting: Return void from do_common_semihosting, Richard Henderson, 2022/04/30
- [PATCH 15/43] semihosting: Split is_64bit_semihosting per target, Richard Henderson, 2022/04/30