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 | ... | ... |