mirror of
https://github.com/mii443/qemu.git
synced 2025-12-03 11:08:25 +00:00
semihosting: Split out semihost_sys_lseek
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. Reviewed-by: Luc Michel <lmichel@kalray.eu> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -114,6 +114,13 @@ static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete,
|
||||
(target_ulong)gf->hostfd, buf, len);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Host semihosting syscall implementations.
|
||||
*/
|
||||
@@ -216,6 +223,29 @@ static void host_write(CPUState *cs, gdb_syscall_complete_cb complete,
|
||||
unlock_user(ptr, buf, 0);
|
||||
}
|
||||
|
||||
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 = EINVAL;
|
||||
}
|
||||
complete(cs, ret, err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Static file semihosting syscall implementations.
|
||||
*/
|
||||
@@ -241,6 +271,33 @@ static void staticfile_read(CPUState *cs, gdb_syscall_complete_cb complete,
|
||||
unlock_user(ptr, buf, len);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Syscall entry points.
|
||||
*/
|
||||
@@ -356,3 +413,27 @@ void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete,
|
||||
complete(cs, -1, EBADF);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user