On 13:45 Tue 07 Jun , Richard Henderson wrote: > These syscalls will be used by m68k and nios2 semihosting. > > Signed-off-by: Richard Henderson <richard.hender...@linaro.org>
Reviewed-by: Luc Michel <lmic...@kalray.eu> > --- > include/semihosting/syscalls.h | 7 ++ > semihosting/syscalls.c | 137 +++++++++++++++++++++++++++++++++ > 2 files changed, 144 insertions(+) > > diff --git a/include/semihosting/syscalls.h b/include/semihosting/syscalls.h > index c9f9e66be1..ecc97751a9 100644 > --- a/include/semihosting/syscalls.h > +++ b/include/semihosting/syscalls.h > @@ -49,6 +49,13 @@ void semihost_sys_flen(CPUState *cs, > gdb_syscall_complete_cb fstat_cb, > gdb_syscall_complete_cb flen_cb, > int fd, target_ulong fstat_addr); > > +void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete, > + int fd, target_ulong addr); > + > +void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete, > + target_ulong fname, target_ulong fname_len, > + target_ulong addr); > + > void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete, > target_ulong fname, target_ulong fname_len); > > diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c > index de846ced32..d21064716d 100644 > --- a/semihosting/syscalls.c > +++ b/semihosting/syscalls.c > @@ -63,6 +63,52 @@ static int validate_lock_user_string(char **pstr, CPUState > *cs, > return ret; > } > > +/* > + * TODO: Note that gdb always stores the stat structure big-endian. > + * So far, that's ok, as the only two targets using this are also > + * big-endian. Until we do something with gdb, also produce the > + * same big-endian result from the host. > + */ > +static int copy_stat_to_user(CPUState *cs, target_ulong addr, > + const struct stat *s) > +{ > + CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; > + struct gdb_stat *p; > + > + if (s->st_dev != (uint32_t)s->st_dev || > + s->st_ino != (uint32_t)s->st_ino) { > + return -EOVERFLOW; > + } > + > + p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0); > + if (!p) { > + return -EFAULT; > + } > + > + p->gdb_st_dev = cpu_to_be32(s->st_dev); > + p->gdb_st_ino = cpu_to_be32(s->st_ino); > + p->gdb_st_mode = cpu_to_be32(s->st_mode); > + p->gdb_st_nlink = cpu_to_be32(s->st_nlink); > + p->gdb_st_uid = cpu_to_be32(s->st_uid); > + p->gdb_st_gid = cpu_to_be32(s->st_gid); > + p->gdb_st_rdev = cpu_to_be32(s->st_rdev); > + p->gdb_st_size = cpu_to_be64(s->st_size); > +#ifdef _WIN32 > + /* Windows stat is missing some fields. */ > + p->gdb_st_blksize = 0; > + p->gdb_st_blocks = 0; > +#else > + p->gdb_st_blksize = cpu_to_be64(s->st_blksize); > + p->gdb_st_blocks = cpu_to_be64(s->st_blocks); > +#endif > + p->gdb_st_atime = cpu_to_be32(s->st_atime); > + p->gdb_st_mtime = cpu_to_be32(s->st_mtime); > + p->gdb_st_ctime = cpu_to_be32(s->st_ctime); > + > + unlock_user(p, addr, sizeof(struct gdb_stat)); > + return 0; > +} > + > /* > * GDB semihosting syscall implementations. > */ > @@ -133,6 +179,19 @@ static void gdb_fstat(CPUState *cs, > gdb_syscall_complete_cb complete, > gdb_do_syscall(complete, "fstat,%x,%x", (target_ulong)gf->hostfd, addr); > } > > +static void gdb_stat(CPUState *cs, gdb_syscall_complete_cb complete, > + target_ulong fname, target_ulong fname_len, > + target_ulong addr) > +{ > + int len = validate_strlen(cs, fname, fname_len); > + if (len < 0) { > + complete(cs, -1, -len); > + return; > + } > + > + gdb_do_syscall(complete, "stat,%s,%x", fname, len, addr); > +} > + > static void gdb_remove(CPUState *cs, gdb_syscall_complete_cb complete, > target_ulong fname, target_ulong fname_len) > { > @@ -321,6 +380,51 @@ static void host_flen(CPUState *cs, > gdb_syscall_complete_cb complete, > } > } > > +static void host_fstat(CPUState *cs, gdb_syscall_complete_cb complete, > + GuestFD *gf, target_ulong addr) > +{ > + struct stat buf; > + int ret; > + > + ret = fstat(gf->hostfd, &buf); > + if (ret) { > + complete(cs, -1, errno); > + return; > + } > + ret = copy_stat_to_user(cs, addr, &buf); > + complete(cs, ret ? -1 : 0, ret ? -ret : 0); > +} > + > +static void host_stat(CPUState *cs, gdb_syscall_complete_cb complete, > + target_ulong fname, target_ulong fname_len, > + target_ulong addr) > +{ > + CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; > + struct stat buf; > + char *name; > + int ret, err; > + > + ret = validate_lock_user_string(&name, cs, fname, fname_len); > + if (ret < 0) { > + complete(cs, -1, -ret); > + return; > + } > + > + ret = stat(name, &buf); > + if (ret) { > + err = errno; > + } else { > + ret = copy_stat_to_user(cs, addr, &buf); > + err = 0; > + if (ret < 0) { > + err = -ret; > + ret = -1; > + } > + } > + complete(cs, ret, err); > + unlock_user(name, fname, 0); > +} > + > static void host_remove(CPUState *cs, gdb_syscall_complete_cb complete, > target_ulong fname, target_ulong fname_len) > { > @@ -629,6 +733,39 @@ void semihost_sys_flen(CPUState *cs, > gdb_syscall_complete_cb fstat_cb, > } > } > > +void semihost_sys_fstat(CPUState *cs, gdb_syscall_complete_cb complete, > + int fd, target_ulong addr) > +{ > + GuestFD *gf = get_guestfd(fd); > + > + if (!gf) { > + complete(cs, -1, EBADF); > + return; > + } > + switch (gf->type) { > + case GuestFDGDB: > + gdb_fstat(cs, complete, gf, addr); > + break; > + case GuestFDHost: > + host_fstat(cs, complete, gf, addr); > + break; > + case GuestFDStatic: > + default: > + g_assert_not_reached(); > + } > +} > + > +void semihost_sys_stat(CPUState *cs, gdb_syscall_complete_cb complete, > + target_ulong fname, target_ulong fname_len, > + target_ulong addr) > +{ > + if (use_gdb_syscalls()) { > + gdb_stat(cs, complete, fname, fname_len, addr); > + } else { > + host_stat(cs, complete, fname, fname_len, addr); > + } > +} > + > void semihost_sys_remove(CPUState *cs, gdb_syscall_complete_cb complete, > target_ulong fname, target_ulong fname_len) > { > -- > 2.34.1 > > > > > To declare a filtering error, please use the following link : > https://www.security-mail.net/reporter.php?mid=c440.629fd46f.95a21.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+38%2F53%5D+semihosting%3A+Create+semihost_sys_%7Bstat%2Cfstat%7D&verdict=C&c=883b33c80ed77b64c3d11130c7aa79d39004fc91 > --