Commit 33d9cc8a9691157fd99b681a5122f734522fc63a
1 parent
6361cdb6
ARM GDB semihosting fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2965 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
9 deletions
arm-semi.c
| ... | ... | @@ -117,14 +117,21 @@ static inline uint32_t set_swi_errno(CPUState *env, uint32_t code) |
| 117 | 117 | |
| 118 | 118 | static target_ulong arm_semi_syscall_len; |
| 119 | 119 | |
| 120 | +#if !defined(CONFIG_USER_ONLY) | |
| 121 | +static target_ulong syscall_err; | |
| 122 | +#endif | |
| 123 | + | |
| 120 | 124 | static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) |
| 121 | 125 | { |
| 122 | 126 | #ifdef CONFIG_USER_ONLY |
| 123 | 127 | TaskState *ts = env->opaque; |
| 124 | 128 | #endif |
| 129 | + | |
| 125 | 130 | if (ret == (target_ulong)-1) { |
| 126 | 131 | #ifdef CONFIG_USER_ONLY |
| 127 | 132 | ts->swi_errno = err; |
| 133 | +#else | |
| 134 | + syscall_err = err; | |
| 128 | 135 | #endif |
| 129 | 136 | env->regs[0] = ret; |
| 130 | 137 | } else { |
| ... | ... | @@ -144,6 +151,20 @@ static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) |
| 144 | 151 | } |
| 145 | 152 | } |
| 146 | 153 | |
| 154 | +static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err) | |
| 155 | +{ | |
| 156 | + /* The size is always stored in big-endian order, extract | |
| 157 | + the value. We assume the size always fit in 32 bits. */ | |
| 158 | + uint32_t size; | |
| 159 | + cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0); | |
| 160 | + env->regs[0] = be32_to_cpu(size); | |
| 161 | +#ifdef CONFIG_USER_ONLY | |
| 162 | + ((TaskState *)env->opaque)->swi_errno = err; | |
| 163 | +#else | |
| 164 | + syscall_err = err; | |
| 165 | +#endif | |
| 166 | +} | |
| 167 | + | |
| 147 | 168 | #define ARG(n) tget32(args + (n) * 4) |
| 148 | 169 | #define SET_ARG(n, val) tput32(args + (n) * 4,val) |
| 149 | 170 | uint32_t do_arm_semihosting(CPUState *env) |
| ... | ... | @@ -173,8 +194,8 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 173 | 194 | return STDOUT_FILENO; |
| 174 | 195 | } |
| 175 | 196 | if (use_gdb_syscalls()) { |
| 176 | - gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2), | |
| 177 | - gdb_open_modeflags[ARG(1)]); | |
| 197 | + gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), | |
| 198 | + (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]); | |
| 178 | 199 | return env->regs[0]; |
| 179 | 200 | } else { |
| 180 | 201 | ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); |
| ... | ... | @@ -252,7 +273,7 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 252 | 273 | } |
| 253 | 274 | case SYS_SEEK: |
| 254 | 275 | if (use_gdb_syscalls()) { |
| 255 | - gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1)); | |
| 276 | + gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1)); | |
| 256 | 277 | return env->regs[0]; |
| 257 | 278 | } else { |
| 258 | 279 | ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); |
| ... | ... | @@ -262,8 +283,9 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 262 | 283 | } |
| 263 | 284 | case SYS_FLEN: |
| 264 | 285 | if (use_gdb_syscalls()) { |
| 265 | - /* TODO: Use stat syscall. */ | |
| 266 | - return -1; | |
| 286 | + gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x", | |
| 287 | + ARG(0), env->regs[13]-64); | |
| 288 | + return env->regs[0]; | |
| 267 | 289 | } else { |
| 268 | 290 | struct stat buf; |
| 269 | 291 | ret = set_swi_errno(ts, fstat(ARG(0), &buf)); |
| ... | ... | @@ -276,7 +298,7 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 276 | 298 | return -1; |
| 277 | 299 | case SYS_REMOVE: |
| 278 | 300 | if (use_gdb_syscalls()) { |
| 279 | - gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)); | |
| 301 | + gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1); | |
| 280 | 302 | ret = env->regs[0]; |
| 281 | 303 | } else { |
| 282 | 304 | s = lock_user_string(ARG(0)); |
| ... | ... | @@ -287,7 +309,7 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 287 | 309 | case SYS_RENAME: |
| 288 | 310 | if (use_gdb_syscalls()) { |
| 289 | 311 | gdb_do_syscall(arm_semi_cb, "rename,%s,%s", |
| 290 | - ARG(0), (int)ARG(1), ARG(2), (int)ARG(3)); | |
| 312 | + ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1); | |
| 291 | 313 | return env->regs[0]; |
| 292 | 314 | } else { |
| 293 | 315 | char *s2; |
| ... | ... | @@ -304,7 +326,7 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 304 | 326 | return set_swi_errno(ts, time(NULL)); |
| 305 | 327 | case SYS_SYSTEM: |
| 306 | 328 | if (use_gdb_syscalls()) { |
| 307 | - gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)); | |
| 329 | + gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1); | |
| 308 | 330 | return env->regs[0]; |
| 309 | 331 | } else { |
| 310 | 332 | s = lock_user_string(ARG(0)); |
| ... | ... | @@ -315,7 +337,7 @@ uint32_t do_arm_semihosting(CPUState *env) |
| 315 | 337 | #ifdef CONFIG_USER_ONLY |
| 316 | 338 | return ts->swi_errno; |
| 317 | 339 | #else |
| 318 | - return 0; | |
| 340 | + return syscall_err; | |
| 319 | 341 | #endif |
| 320 | 342 | case SYS_GET_CMDLINE: |
| 321 | 343 | #ifdef CONFIG_USER_ONLY | ... | ... |