Linux user memory access API change (initial patch by Thayne Harbaugh)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3583 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard
2007-11-11 14:26:47 +00:00
parent 44f8625d23
commit 579a97f7ff
14 changed files with 973 additions and 624 deletions
+1 -1
View File
@@ -260,7 +260,7 @@ endif
ifdef CONFIG_LINUX_USER
OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \
elfload.o linuxload.o
elfload.o linuxload.o uaccess.o
LIBS+= $(AIOLIBS)
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
+39 -13
View File
@@ -184,9 +184,11 @@ uint32_t do_arm_semihosting(CPUState *env)
args = env->regs[1];
switch (nr) {
case SYS_OPEN:
s = lock_user_string(ARG(0));
if (!(s = lock_user_string(ARG(0))))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
if (ARG(1) >= 12)
return (uint32_t)-1;
return (uint32_t)-1;
if (strcmp(s, ":tt") == 0) {
if (ARG(1) < 4)
return STDIN_FILENO;
@@ -221,7 +223,9 @@ uint32_t do_arm_semihosting(CPUState *env)
}
}
case SYS_WRITE0:
s = lock_user_string(args);
if (!(s = lock_user_string(args)))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
len = strlen(s);
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
@@ -238,7 +242,9 @@ uint32_t do_arm_semihosting(CPUState *env)
gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
return env->regs[0];
} else {
s = lock_user(ARG(1), len, 1);
if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
ret = set_swi_errno(ts, write(ARG(0), s, len));
unlock_user(s, ARG(1), 0);
if (ret == (uint32_t)-1)
@@ -252,7 +258,9 @@ uint32_t do_arm_semihosting(CPUState *env)
gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
return env->regs[0];
} else {
s = lock_user(ARG(1), len, 0);
if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
do
ret = set_swi_errno(ts, read(ARG(0), s, len));
while (ret == -1 && errno == EINTR);
@@ -301,7 +309,9 @@ uint32_t do_arm_semihosting(CPUState *env)
gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
ret = env->regs[0];
} else {
s = lock_user_string(ARG(0));
if (!(s = lock_user_string(ARG(0))))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
ret = set_swi_errno(ts, remove(s));
unlock_user(s, ARG(0), 0);
}
@@ -315,9 +325,15 @@ uint32_t do_arm_semihosting(CPUState *env)
char *s2;
s = lock_user_string(ARG(0));
s2 = lock_user_string(ARG(2));
ret = set_swi_errno(ts, rename(s, s2));
unlock_user(s2, ARG(2), 0);
unlock_user(s, ARG(0), 0);
if (!s || !s2)
/* FIXME - should this error code be -TARGET_EFAULT ? */
ret = (uint32_t)-1;
else
ret = set_swi_errno(ts, rename(s, s2));
if (s2)
unlock_user(s2, ARG(2), 0);
if (s)
unlock_user(s, ARG(0), 0);
return ret;
}
case SYS_CLOCK:
@@ -329,7 +345,9 @@ uint32_t do_arm_semihosting(CPUState *env)
gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
return env->regs[0];
} else {
s = lock_user_string(ARG(0));
if (!(s = lock_user_string(ARG(0))))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
ret = set_swi_errno(ts, system(s));
unlock_user(s, ARG(0), 0);
}
@@ -346,7 +364,11 @@ uint32_t do_arm_semihosting(CPUState *env)
char **arg = ts->info->host_argv;
int len = ARG(1);
/* lock the buffer on the ARM side */
char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0);
if (!cmdline_buffer)
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
s = cmdline_buffer;
while (*arg && len > 2) {
@@ -402,7 +424,9 @@ uint32_t do_arm_semihosting(CPUState *env)
ts->heap_limit = limit;
}
ptr = lock_user(ARG(0), 16, 0);
if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
ptr[0] = tswap32(ts->heap_base);
ptr[1] = tswap32(ts->heap_limit);
ptr[2] = tswap32(ts->stack_base);
@@ -410,7 +434,9 @@ uint32_t do_arm_semihosting(CPUState *env)
unlock_user(ptr, ARG(0), 16);
#else
limit = ram_size;
ptr = lock_user(ARG(0), 16, 0);
if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
/* TODO: Make this use the limit of the loaded application. */
ptr[0] = tswap32(limit / 2);
ptr[1] = tswap32(limit);
+8 -2
View File
@@ -2510,13 +2510,19 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
if (is_write) {
if (!(flags & PAGE_WRITE))
return;
p = lock_user(addr, len, 0);
/* XXX: this code should not depend on lock_user */
if (!(p = lock_user(VERIFY_WRITE, addr, len, 0)))
/* FIXME - should this return an error rather than just fail? */
return;
memcpy(p, buf, len);
unlock_user(p, addr, len);
} else {
if (!(flags & PAGE_READ))
return;
p = lock_user(addr, len, 1);
/* XXX: this code should not depend on lock_user */
if (!(p = lock_user(VERIFY_READ, addr, len, 1)))
/* FIXME - should this return an error rather than just fail? */
return;
memcpy(buf, p, len);
unlock_user(p, addr, 0);
}
+2 -1
View File
@@ -677,7 +677,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
if (bprm->page[i]) {
info->rss++;
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
free(bprm->page[i]);
}
@@ -760,6 +760,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
size_t len = strlen(k_platform) + 1;
sp -= (len + n - 1) & ~(n - 1);
u_platform = sp;
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(sp, k_platform, len);
}
/*
+1 -1
View File
@@ -108,7 +108,7 @@ int target_pread(int fd, abi_ulong ptr, abi_ulong len,
void *buf;
int ret;
buf = lock_user(ptr, len, 0);
buf = lock_user(VERIFY_WRITE, ptr, len, 0);
ret = pread(fd, buf, len, offset);
unlock_user(buf, ptr, len);
return ret;
+6 -3
View File
@@ -13,14 +13,17 @@
#define NGROUPS 32
/* ??? This should really be somewhere else. */
void memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len)
abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len)
{
void *host_ptr;
host_ptr = lock_user(dest, len, 0);
host_ptr = lock_user(VERIFY_WRITE, dest, len, 0);
if (!host_ptr)
return -TARGET_EFAULT;
memcpy(host_ptr, src, len);
unlock_user(host_ptr, dest, 1);
return 0;
}
static int in_group_p(gid_t g)
+74 -47
View File
@@ -146,8 +146,8 @@ int load_elf_binary_multi(struct linux_binprm *bprm,
struct image_info *info);
#endif
void memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len);
abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len);
void target_set_brk(abi_ulong new_brk);
abi_long do_brk(abi_ulong new_brk);
void syscall_init(void);
@@ -179,9 +179,7 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
long do_sigreturn(CPUState *env);
long do_rt_sigreturn(CPUState *env);
int do_sigaltstack(const struct target_sigaltstack *uss,
struct target_sigaltstack *uoss,
abi_ulong sp);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
#ifdef TARGET_I386
/* vm86.c */
@@ -207,12 +205,15 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
/* user access */
#define VERIFY_READ 0
#define VERIFY_WRITE 1
#define VERIFY_WRITE 1 /* implies read access */
#define access_ok(type,addr,size) \
(page_check_range((target_ulong)addr,size,(type==VERIFY_READ)?PAGE_READ:PAGE_WRITE)==0)
/* NOTE __get_user and __put_user use host pointers and don't check access. */
/* These are usually used to access struct data members once the
* struct has been locked - usually with lock_user_struct().
*/
#define __put_user(x, hptr)\
({\
int size = sizeof(*hptr);\
@@ -257,26 +258,44 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
0;\
})
#define put_user(x,ptr)\
({\
int __ret;\
if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
__ret = __put_user(x, ptr);\
else\
__ret = -EFAULT;\
__ret;\
/* put_user()/get_user() take a guest address and check access */
/* These are usually used to access an atomic data type, such as an int,
* that has been passed by address. These internally perform locking
* and unlocking on the data type.
*/
#define put_user(x, gaddr, target_type) \
({ \
abi_ulong __gaddr = (gaddr); \
target_type *__hptr; \
abi_long __ret; \
if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \
__ret = __put_user((x), __hptr); \
unlock_user(__hptr, __gaddr, sizeof(target_type)); \
} else \
__ret = -TARGET_EFAULT; \
__ret; \
})
#define get_user(x,ptr)\
({\
int __ret;\
if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
__ret = __get_user(x, ptr);\
else\
__ret = -EFAULT;\
__ret;\
#define get_user(x, gaddr, target_type) \
({ \
abi_ulong __gaddr = (gaddr); \
target_type *__hptr; \
abi_long __ret; \
if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \
__ret = __get_user((x), __hptr); \
unlock_user(__hptr, __gaddr, 0); \
} else \
__ret = -TARGET_EFAULT; \
__ret; \
})
/* copy_from_user() and copy_to_user() are usually used to copy data
* buffers between the target and host. These internally perform
* locking/unlocking of the memory.
*/
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
/* Functions for accessing guest memory. The tget and tput functions
read/write single values, byteswapping as neccessary. The lock_user
gets a pointer to a contiguous area of guest memory, but does not perform
@@ -285,53 +304,61 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
/* Lock an area of guest memory into the host. If copy is true then the
host area will have the same contents as the guest. */
static inline void *lock_user(abi_ulong guest_addr, long len, int copy)
static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy)
{
if (!access_ok(type, guest_addr, len))
return NULL;
#ifdef DEBUG_REMAP
void *addr;
addr = malloc(len);
if (copy)
memcpy(addr, g2h(guest_addr), len);
else
memset(addr, 0, len);
return addr;
{
void *addr;
addr = malloc(len);
if (copy)
memcpy(addr, g2h(guest_addr), len);
else
memset(addr, 0, len);
return addr;
}
#else
return g2h(guest_addr);
#endif
}
/* Unlock an area of guest memory. The first LEN bytes must be flushed back
to guest memory. */
static inline void unlock_user(void *host_addr, abi_ulong guest_addr,
/* Unlock an area of guest memory. The first LEN bytes must be
flushed back to guest memory. host_ptr = NULL is explicitely
allowed and does nothing. */
static inline void unlock_user(void *host_ptr, abi_ulong guest_addr,
long len)
{
#ifdef DEBUG_REMAP
if (host_addr == g2h(guest_addr))
if (!host_ptr)
return;
if (host_ptr == g2h(guest_addr))
return;
if (len > 0)
memcpy(g2h(guest_addr), host_addr, len);
free(host_addr);
memcpy(g2h(guest_ptr), host_ptr, len);
free(host_ptr);
#endif
}
/* Return the length of a string in target memory. */
static inline int target_strlen(abi_ulong ptr)
{
return strlen(g2h(ptr));
}
/* Return the length of a string in target memory or -TARGET_EFAULT if
access error. */
abi_long target_strlen(abi_ulong gaddr);
/* Like lock_user but for null terminated strings. */
static inline void *lock_user_string(abi_ulong guest_addr)
{
long len;
len = target_strlen(guest_addr) + 1;
return lock_user(guest_addr, len, 1);
abi_long len;
len = target_strlen(guest_addr);
if (len < 0)
return NULL;
return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1);
}
/* Helper macros for locking/ulocking a target struct. */
#define lock_user_struct(host_ptr, guest_addr, copy) \
host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy)
#define unlock_user_struct(host_ptr, guest_addr, copy) \
#define lock_user_struct(type, host_ptr, guest_addr, copy) \
(host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy))
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
#define tget8(addr) ldub(addr)
+135 -103
View File
File diff suppressed because it is too large Load Diff
+17 -16
View File
@@ -81,14 +81,18 @@ print_fdset(int n, target_ulong target_fds_addr)
gemu_log("[");
if( target_fds_addr ) {
target_long *target_fds;
abi_long *target_fds;
if (!access_ok(VERIFY_READ, target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1)))
target_fds = lock_user(VERIFY_READ,
target_fds_addr,
sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1),
1);
if (!target_fds)
return;
target_fds = lock_user(target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1), 1);
for (i=n; i>=0; i--) {
if ((tswapl(target_fds[i / TARGET_LONG_BITS]) >> (i & (TARGET_LONG_BITS - 1))) & 1)
if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1)
gemu_log("%d,", i );
}
unlock_user(target_fds, target_fds_addr, 0);
@@ -102,10 +106,9 @@ print_timeval(target_ulong tv_addr)
if( tv_addr ) {
struct target_timeval *tv;
if (!access_ok(VERIFY_READ, tv_addr, sizeof(*tv)))
tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1);
if (!tv)
return;
tv = lock_user(tv_addr, sizeof(*tv), 1);
gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}",
tv->tv_sec, tv->tv_usec);
unlock_user(tv, tv_addr, 0);
@@ -165,27 +168,25 @@ print_execve(struct syscallname *name,
target_ulong arg_ptr_addr;
char *s;
if (!access_ok(VERIFY_READ, arg1, 1))
if (!(s = lock_user_string(arg1)))
return;
s = lock_user_string(arg1);
gemu_log("%s(\"%s\",{", name->name, s);
unlock_user(s, arg1, 0);
for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(target_ulong)) {
target_ulong *arg_ptr, arg_addr, s_addr;
if (!access_ok(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong)))
arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong), 1);
if (!arg_ptr)
return;
arg_ptr = lock_user(arg_ptr_addr, sizeof(target_ulong), 1);
arg_addr = tswapl(*arg_ptr);
unlock_user(arg_ptr, arg_ptr_addr, 0);
if (!arg_addr)
break;
s = lock_user_string(arg_addr);
gemu_log("\"%s\",", s);
unlock_user(s, s_addr, 0);
if ((s = lock_user_string(arg_addr))) {
gemu_log("\"%s\",", s);
unlock_user(s, s_addr, 0);
}
}
gemu_log("NULL})");
+573 -410
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
/* User memory access */
#include <stdio.h>
#include <string.h>
#include "qemu.h"
/* copy_from_user() and copy_to_user() are usually used to copy data
* buffers between the target and host. These internally perform
* locking/unlocking of the memory.
*/
abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
{
abi_long ret = 0;
void *ghptr;
if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
memcpy(hptr, ghptr, len);
unlock_user(ghptr, gaddr, 0);
} else
ret = -TARGET_EFAULT;
return ret;
}
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
{
abi_long ret = 0;
void *ghptr;
if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
memcpy(ghptr, hptr, len);
unlock_user(ghptr, gaddr, len);
} else
ret = -TARGET_EFAULT;
return ret;
}
/* Return the length of a string in target memory. */
/* FIXME - this doesn't check access_ok() - it's rather complicated to
* do it correctly because we need to check the bytes in a page and then
* skip to the next page and check the bytes there until we find the
* terminator. There should be a general function to do this that
* can look for any byte terminator in a buffer - not strlen().
*/
abi_long target_strlen(abi_ulong gaddr)
{
return strlen(g2h(gaddr));
}
+5 -2
View File
@@ -64,7 +64,9 @@ void save_v86_state(CPUX86State *env)
TaskState *ts = env->opaque;
struct target_vm86plus_struct * target_v86;
lock_user_struct(target_v86, ts->target_v86, 0);
if (!lock_user_struct(VERIFY_WRITE, target_v86, ts->target_v86, 0))
/* FIXME - should return an error */
return;
/* put the VM86 registers in the userspace register structure */
target_v86->regs.eax = tswap32(env->regs[R_EAX]);
target_v86->regs.ebx = tswap32(env->regs[R_EBX]);
@@ -424,7 +426,8 @@ int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr)
ts->vm86_saved_regs.gs = env->segs[R_GS].selector;
ts->target_v86 = vm86_addr;
lock_user_struct(target_v86, vm86_addr, 1);
if (!lock_user_struct(VERIFY_READ, target_v86, vm86_addr, 1))
return -EFAULT;
/* build vm86 CPU state */
ts->v86flags = tswap32(target_v86->regs.eflags);
env->eflags = (env->eflags & ~SAFE_MASK) |
+60 -24
View File
@@ -107,7 +107,9 @@ static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
{
struct m68k_gdb_stat *p;
p = lock_user(addr, sizeof(struct m68k_gdb_stat), 0);
if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
/* FIXME - should this return an error code? */
return;
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);
@@ -168,9 +170,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
ARG(2), ARG(3));
return;
} else {
p = lock_user_string(ARG(0));
result = open(p, translate_openflags(ARG(2)), ARG(3));
unlock_user(p, ARG(0), 0);
if (!(p = lock_user_string(ARG(0)))) {
/* FIXME - check error code? */
result = -1;
} else {
result = open(p, translate_openflags(ARG(2)), ARG(3));
unlock_user(p, ARG(0), 0);
}
}
break;
case HOSTED_CLOSE:
@@ -196,9 +202,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
ARG(0), ARG(1), len);
return;
} else {
p = lock_user(ARG(1), len, 0);
result = read(ARG(0), p, len);
unlock_user(p, ARG(1), len);
if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
/* FIXME - check error code? */
result = -1;
} else {
result = read(ARG(0), p, len);
unlock_user(p, ARG(1), len);
}
}
break;
case HOSTED_WRITE:
@@ -208,9 +218,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
ARG(0), ARG(1), len);
return;
} else {
p = lock_user(ARG(1), len, 1);
result = write(ARG(0), p, len);
unlock_user(p, ARG(0), 0);
if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
/* FIXME - check error code? */
result = -1;
} else {
result = write(ARG(0), p, len);
unlock_user(p, ARG(0), 0);
}
}
break;
case HOSTED_LSEEK:
@@ -237,7 +251,12 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
} else {
p = lock_user_string(ARG(0));
q = lock_user_string(ARG(2));
result = rename(p, q);
if (!p || !q) {
/* FIXME - check error code? */
result = -1;
} else {
result = rename(p, q);
}
unlock_user(p, ARG(0), 0);
unlock_user(q, ARG(2), 0);
}
@@ -248,9 +267,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
ARG(0), (int)ARG(1));
return;
} else {
p = lock_user_string(ARG(0));
result = unlink(p);
unlock_user(p, ARG(0), 0);
if (!(p = lock_user_string(ARG(0)))) {
/* FIXME - check error code? */
result = -1;
} else {
result = unlink(p);
unlock_user(p, ARG(0), 0);
}
}
break;
case HOSTED_STAT:
@@ -260,9 +283,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
return;
} else {
struct stat s;
p = lock_user_string(ARG(0));
result = stat(p, &s);
unlock_user(p, ARG(0), 0);
if (!(p = lock_user_string(ARG(0)))) {
/* FIXME - check error code? */
result = -1;
} else {
result = stat(p, &s);
unlock_user(p, ARG(0), 0);
}
if (result == 0) {
translate_stat(env, ARG(2), &s);
}
@@ -291,10 +318,15 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
struct gdb_timeval *p;
result = qemu_gettimeofday(&tv);
if (result != 0) {
p = lock_user(ARG(0), sizeof(struct gdb_timeval), 0);
p->tv_sec = cpu_to_be32(tv.tv_sec);
p->tv_usec = cpu_to_be64(tv.tv_usec);
unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
if (!(p = lock_user(VERIFY_WRITE,
ARG(0), sizeof(struct gdb_timeval), 0))) {
/* FIXME - check error code? */
result = -1;
} else {
p->tv_sec = cpu_to_be32(tv.tv_sec);
p->tv_usec = cpu_to_be64(tv.tv_usec);
unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
}
}
}
break;
@@ -312,9 +344,13 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
ARG(0), (int)ARG(1));
return;
} else {
p = lock_user_string(ARG(0));
result = system(p);
unlock_user(p, ARG(0), 0);
if (!(p = lock_user_string(ARG(0)))) {
/* FIXME - check error code? */
result = -1;
} else {
result = system(p);
unlock_user(p, ARG(0), 0);
}
}
break;
case HOSTED_INIT_SIM:
+1 -1
View File
@@ -41,7 +41,7 @@ static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
cpu_memory_rw_debug(env, addr, p, len, 0);
return p;
}
#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
{
char *p;