ARM GDB semihosting fixes

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2965 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
pbrook 2007-06-09 14:44:00 +00:00
parent 6361cdb630
commit 33d9cc8a96

View file

@ -117,14 +117,21 @@ static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
static target_ulong arm_semi_syscall_len; static target_ulong arm_semi_syscall_len;
#if !defined(CONFIG_USER_ONLY)
static target_ulong syscall_err;
#endif
static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
{ {
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
TaskState *ts = env->opaque; TaskState *ts = env->opaque;
#endif #endif
if (ret == (target_ulong)-1) { if (ret == (target_ulong)-1) {
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
ts->swi_errno = err; ts->swi_errno = err;
#else
syscall_err = err;
#endif #endif
env->regs[0] = ret; env->regs[0] = ret;
} else { } else {
@ -144,6 +151,20 @@ static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
} }
} }
static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err)
{
/* The size is always stored in big-endian order, extract
the value. We assume the size always fit in 32 bits. */
uint32_t size;
cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
env->regs[0] = be32_to_cpu(size);
#ifdef CONFIG_USER_ONLY
((TaskState *)env->opaque)->swi_errno = err;
#else
syscall_err = err;
#endif
}
#define ARG(n) tget32(args + (n) * 4) #define ARG(n) tget32(args + (n) * 4)
#define SET_ARG(n, val) tput32(args + (n) * 4,val) #define SET_ARG(n, val) tput32(args + (n) * 4,val)
uint32_t do_arm_semihosting(CPUState *env) uint32_t do_arm_semihosting(CPUState *env)
@ -173,8 +194,8 @@ uint32_t do_arm_semihosting(CPUState *env)
return STDOUT_FILENO; return STDOUT_FILENO;
} }
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2), gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
gdb_open_modeflags[ARG(1)]); (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
return env->regs[0]; return env->regs[0];
} else { } else {
ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
@ -252,7 +273,7 @@ uint32_t do_arm_semihosting(CPUState *env)
} }
case SYS_SEEK: case SYS_SEEK:
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1)); gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
return env->regs[0]; return env->regs[0];
} else { } else {
ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
@ -262,8 +283,9 @@ uint32_t do_arm_semihosting(CPUState *env)
} }
case SYS_FLEN: case SYS_FLEN:
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
/* TODO: Use stat syscall. */ gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
return -1; ARG(0), env->regs[13]-64);
return env->regs[0];
} else { } else {
struct stat buf; struct stat buf;
ret = set_swi_errno(ts, fstat(ARG(0), &buf)); ret = set_swi_errno(ts, fstat(ARG(0), &buf));
@ -276,7 +298,7 @@ uint32_t do_arm_semihosting(CPUState *env)
return -1; return -1;
case SYS_REMOVE: case SYS_REMOVE:
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)); gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
ret = env->regs[0]; ret = env->regs[0];
} else { } else {
s = lock_user_string(ARG(0)); s = lock_user_string(ARG(0));
@ -287,7 +309,7 @@ uint32_t do_arm_semihosting(CPUState *env)
case SYS_RENAME: case SYS_RENAME:
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "rename,%s,%s", gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
ARG(0), (int)ARG(1), ARG(2), (int)ARG(3)); ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
return env->regs[0]; return env->regs[0];
} else { } else {
char *s2; char *s2;
@ -304,7 +326,7 @@ uint32_t do_arm_semihosting(CPUState *env)
return set_swi_errno(ts, time(NULL)); return set_swi_errno(ts, time(NULL));
case SYS_SYSTEM: case SYS_SYSTEM:
if (use_gdb_syscalls()) { if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)); gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
return env->regs[0]; return env->regs[0];
} else { } else {
s = lock_user_string(ARG(0)); s = lock_user_string(ARG(0));
@ -315,7 +337,7 @@ uint32_t do_arm_semihosting(CPUState *env)
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
return ts->swi_errno; return ts->swi_errno;
#else #else
return 0; return syscall_err;
#endif #endif
case SYS_GET_CMDLINE: case SYS_GET_CMDLINE:
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY