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,14 +117,21 @@ static inline uint32_t set_swi_errno(CPUState *env, uint32_t code) | ||
117 | 117 | ||
118 | static target_ulong arm_semi_syscall_len; | 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 | static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) | 124 | static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) |
121 | { | 125 | { |
122 | #ifdef CONFIG_USER_ONLY | 126 | #ifdef CONFIG_USER_ONLY |
123 | TaskState *ts = env->opaque; | 127 | TaskState *ts = env->opaque; |
124 | #endif | 128 | #endif |
129 | + | ||
125 | if (ret == (target_ulong)-1) { | 130 | if (ret == (target_ulong)-1) { |
126 | #ifdef CONFIG_USER_ONLY | 131 | #ifdef CONFIG_USER_ONLY |
127 | ts->swi_errno = err; | 132 | ts->swi_errno = err; |
133 | +#else | ||
134 | + syscall_err = err; | ||
128 | #endif | 135 | #endif |
129 | env->regs[0] = ret; | 136 | env->regs[0] = ret; |
130 | } else { | 137 | } else { |
@@ -144,6 +151,20 @@ static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) | @@ -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 | #define ARG(n) tget32(args + (n) * 4) | 168 | #define ARG(n) tget32(args + (n) * 4) |
148 | #define SET_ARG(n, val) tput32(args + (n) * 4,val) | 169 | #define SET_ARG(n, val) tput32(args + (n) * 4,val) |
149 | uint32_t do_arm_semihosting(CPUState *env) | 170 | uint32_t do_arm_semihosting(CPUState *env) |
@@ -173,8 +194,8 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -173,8 +194,8 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
173 | return STDOUT_FILENO; | 194 | return STDOUT_FILENO; |
174 | } | 195 | } |
175 | if (use_gdb_syscalls()) { | 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 | return env->regs[0]; | 199 | return env->regs[0]; |
179 | } else { | 200 | } else { |
180 | ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); | 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,7 +273,7 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
252 | } | 273 | } |
253 | case SYS_SEEK: | 274 | case SYS_SEEK: |
254 | if (use_gdb_syscalls()) { | 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 | return env->regs[0]; | 277 | return env->regs[0]; |
257 | } else { | 278 | } else { |
258 | ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); | 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,8 +283,9 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
262 | } | 283 | } |
263 | case SYS_FLEN: | 284 | case SYS_FLEN: |
264 | if (use_gdb_syscalls()) { | 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 | } else { | 289 | } else { |
268 | struct stat buf; | 290 | struct stat buf; |
269 | ret = set_swi_errno(ts, fstat(ARG(0), &buf)); | 291 | ret = set_swi_errno(ts, fstat(ARG(0), &buf)); |
@@ -276,7 +298,7 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -276,7 +298,7 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
276 | return -1; | 298 | return -1; |
277 | case SYS_REMOVE: | 299 | case SYS_REMOVE: |
278 | if (use_gdb_syscalls()) { | 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 | ret = env->regs[0]; | 302 | ret = env->regs[0]; |
281 | } else { | 303 | } else { |
282 | s = lock_user_string(ARG(0)); | 304 | s = lock_user_string(ARG(0)); |
@@ -287,7 +309,7 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -287,7 +309,7 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
287 | case SYS_RENAME: | 309 | case SYS_RENAME: |
288 | if (use_gdb_syscalls()) { | 310 | if (use_gdb_syscalls()) { |
289 | gdb_do_syscall(arm_semi_cb, "rename,%s,%s", | 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 | return env->regs[0]; | 313 | return env->regs[0]; |
292 | } else { | 314 | } else { |
293 | char *s2; | 315 | char *s2; |
@@ -304,7 +326,7 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -304,7 +326,7 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
304 | return set_swi_errno(ts, time(NULL)); | 326 | return set_swi_errno(ts, time(NULL)); |
305 | case SYS_SYSTEM: | 327 | case SYS_SYSTEM: |
306 | if (use_gdb_syscalls()) { | 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 | return env->regs[0]; | 330 | return env->regs[0]; |
309 | } else { | 331 | } else { |
310 | s = lock_user_string(ARG(0)); | 332 | s = lock_user_string(ARG(0)); |
@@ -315,7 +337,7 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -315,7 +337,7 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
315 | #ifdef CONFIG_USER_ONLY | 337 | #ifdef CONFIG_USER_ONLY |
316 | return ts->swi_errno; | 338 | return ts->swi_errno; |
317 | #else | 339 | #else |
318 | - return 0; | 340 | + return syscall_err; |
319 | #endif | 341 | #endif |
320 | case SYS_GET_CMDLINE: | 342 | case SYS_GET_CMDLINE: |
321 | #ifdef CONFIG_USER_ONLY | 343 | #ifdef CONFIG_USER_ONLY |