Commit a2d1ebaf890da03de850812cc8dbec2d56efb4e8
1 parent
4046d913
GDB hosted syscalls.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2364 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
262 additions
and
32 deletions
arm-semi.c
@@ -61,7 +61,30 @@ | @@ -61,7 +61,30 @@ | ||
61 | #define O_BINARY 0 | 61 | #define O_BINARY 0 |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | -int open_modeflags[12] = { | 64 | +#define GDB_O_RDONLY 0x000 |
65 | +#define GDB_O_WRONLY 0x001 | ||
66 | +#define GDB_O_RDWR 0x002 | ||
67 | +#define GDB_O_APPEND 0x008 | ||
68 | +#define GDB_O_CREAT 0x200 | ||
69 | +#define GDB_O_TRUNC 0x400 | ||
70 | +#define GDB_O_BINARY 0 | ||
71 | + | ||
72 | +static int gdb_open_modeflags[12] = { | ||
73 | + GDB_O_RDONLY, | ||
74 | + GDB_O_RDONLY | GDB_O_BINARY, | ||
75 | + GDB_O_RDWR, | ||
76 | + GDB_O_RDWR | GDB_O_BINARY, | ||
77 | + GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC, | ||
78 | + GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, | ||
79 | + GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC, | ||
80 | + GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, | ||
81 | + GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND, | ||
82 | + GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY, | ||
83 | + GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND, | ||
84 | + GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY | ||
85 | +}; | ||
86 | + | ||
87 | +static int open_modeflags[12] = { | ||
65 | O_RDONLY, | 88 | O_RDONLY, |
66 | O_RDONLY | O_BINARY, | 89 | O_RDONLY | O_BINARY, |
67 | O_RDWR, | 90 | O_RDWR, |
@@ -142,6 +165,35 @@ static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr, | @@ -142,6 +165,35 @@ static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr, | ||
142 | #define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len) | 165 | #define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len) |
143 | #endif | 166 | #endif |
144 | 167 | ||
168 | +static target_ulong arm_semi_syscall_len; | ||
169 | + | ||
170 | +static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) | ||
171 | +{ | ||
172 | +#ifdef CONFIG_USER_ONLY | ||
173 | + TaskState *ts = env->opaque; | ||
174 | +#endif | ||
175 | + if (ret == (target_ulong)-1) { | ||
176 | +#ifdef CONFIG_USER_ONLY | ||
177 | + ts->swi_errno = err; | ||
178 | +#endif | ||
179 | + env->regs[0] = ret; | ||
180 | + } else { | ||
181 | + /* Fixup syscalls that use nonstardard return conventions. */ | ||
182 | + switch (env->regs[0]) { | ||
183 | + case SYS_WRITE: | ||
184 | + case SYS_READ: | ||
185 | + env->regs[0] = arm_semi_syscall_len - ret; | ||
186 | + break; | ||
187 | + case SYS_SEEK: | ||
188 | + env->regs[0] = 0; | ||
189 | + break; | ||
190 | + default: | ||
191 | + env->regs[0] = ret; | ||
192 | + break; | ||
193 | + } | ||
194 | + } | ||
195 | +} | ||
196 | + | ||
145 | #define ARG(n) tget32(args + (n) * 4) | 197 | #define ARG(n) tget32(args + (n) * 4) |
146 | #define SET_ARG(n, val) tput32(args + (n) * 4,val) | 198 | #define SET_ARG(n, val) tput32(args + (n) * 4,val) |
147 | uint32_t do_arm_semihosting(CPUState *env) | 199 | uint32_t do_arm_semihosting(CPUState *env) |
@@ -170,52 +222,99 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -170,52 +222,99 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
170 | else | 222 | else |
171 | return STDOUT_FILENO; | 223 | return STDOUT_FILENO; |
172 | } | 224 | } |
173 | - ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); | 225 | + if (use_gdb_syscalls()) { |
226 | + gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2), | ||
227 | + gdb_open_modeflags[ARG(1)]); | ||
228 | + return env->regs[0]; | ||
229 | + } else { | ||
230 | + ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); | ||
231 | + } | ||
174 | unlock_user(s, ARG(0), 0); | 232 | unlock_user(s, ARG(0), 0); |
175 | return ret; | 233 | return ret; |
176 | case SYS_CLOSE: | 234 | case SYS_CLOSE: |
177 | - return set_swi_errno(ts, close(ARG(0))); | 235 | + if (use_gdb_syscalls()) { |
236 | + gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0)); | ||
237 | + return env->regs[0]; | ||
238 | + } else { | ||
239 | + return set_swi_errno(ts, close(ARG(0))); | ||
240 | + } | ||
178 | case SYS_WRITEC: | 241 | case SYS_WRITEC: |
179 | { | 242 | { |
180 | char c = tget8(args); | 243 | char c = tget8(args); |
181 | /* Write to debug console. stderr is near enough. */ | 244 | /* Write to debug console. stderr is near enough. */ |
182 | - return write(STDERR_FILENO, &c, 1); | 245 | + if (use_gdb_syscalls()) { |
246 | + gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args); | ||
247 | + return env->regs[0]; | ||
248 | + } else { | ||
249 | + return write(STDERR_FILENO, &c, 1); | ||
250 | + } | ||
183 | } | 251 | } |
184 | case SYS_WRITE0: | 252 | case SYS_WRITE0: |
185 | s = lock_user_string(args); | 253 | s = lock_user_string(args); |
186 | - ret = write(STDERR_FILENO, s, strlen(s)); | 254 | + len = strlen(s); |
255 | + if (use_gdb_syscalls()) { | ||
256 | + gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len); | ||
257 | + ret = env->regs[0]; | ||
258 | + } else { | ||
259 | + ret = write(STDERR_FILENO, s, len); | ||
260 | + } | ||
187 | unlock_user(s, args, 0); | 261 | unlock_user(s, args, 0); |
188 | return ret; | 262 | return ret; |
189 | case SYS_WRITE: | 263 | case SYS_WRITE: |
190 | len = ARG(2); | 264 | len = ARG(2); |
191 | - s = lock_user(ARG(1), len, 1); | ||
192 | - ret = set_swi_errno(ts, write(ARG(0), s, len)); | ||
193 | - unlock_user(s, ARG(1), 0); | ||
194 | - if (ret == (uint32_t)-1) | ||
195 | - return -1; | ||
196 | - return ARG(2) - ret; | 265 | + if (use_gdb_syscalls()) { |
266 | + arm_semi_syscall_len = len; | ||
267 | + gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len); | ||
268 | + return env->regs[0]; | ||
269 | + } else { | ||
270 | + s = lock_user(ARG(1), len, 1); | ||
271 | + ret = set_swi_errno(ts, write(ARG(0), s, len)); | ||
272 | + unlock_user(s, ARG(1), 0); | ||
273 | + if (ret == (uint32_t)-1) | ||
274 | + return -1; | ||
275 | + return len - ret; | ||
276 | + } | ||
197 | case SYS_READ: | 277 | case SYS_READ: |
198 | len = ARG(2); | 278 | len = ARG(2); |
199 | - s = lock_user(ARG(1), len, 0); | ||
200 | - do | ||
201 | - ret = set_swi_errno(ts, read(ARG(0), s, len)); | ||
202 | - while (ret == -1 && errno == EINTR); | ||
203 | - unlock_user(s, ARG(1), len); | ||
204 | - if (ret == (uint32_t)-1) | ||
205 | - return -1; | ||
206 | - return ARG(2) - ret; | 279 | + if (use_gdb_syscalls()) { |
280 | + arm_semi_syscall_len = len; | ||
281 | + gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len); | ||
282 | + return env->regs[0]; | ||
283 | + } else { | ||
284 | + s = lock_user(ARG(1), len, 0); | ||
285 | + do | ||
286 | + ret = set_swi_errno(ts, read(ARG(0), s, len)); | ||
287 | + while (ret == -1 && errno == EINTR); | ||
288 | + unlock_user(s, ARG(1), len); | ||
289 | + if (ret == (uint32_t)-1) | ||
290 | + return -1; | ||
291 | + return len - ret; | ||
292 | + } | ||
207 | case SYS_READC: | 293 | case SYS_READC: |
208 | /* XXX: Read from debug cosole. Not implemented. */ | 294 | /* XXX: Read from debug cosole. Not implemented. */ |
209 | return 0; | 295 | return 0; |
210 | case SYS_ISTTY: | 296 | case SYS_ISTTY: |
211 | - return isatty(ARG(0)); | 297 | + if (use_gdb_syscalls()) { |
298 | + gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0)); | ||
299 | + return env->regs[0]; | ||
300 | + } else { | ||
301 | + return isatty(ARG(0)); | ||
302 | + } | ||
212 | case SYS_SEEK: | 303 | case SYS_SEEK: |
213 | - ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); | ||
214 | - if (ret == (uint32_t)-1) | ||
215 | - return -1; | ||
216 | - return 0; | 304 | + if (use_gdb_syscalls()) { |
305 | + gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1)); | ||
306 | + return env->regs[0]; | ||
307 | + } else { | ||
308 | + ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); | ||
309 | + if (ret == (uint32_t)-1) | ||
310 | + return -1; | ||
311 | + return 0; | ||
312 | + } | ||
217 | case SYS_FLEN: | 313 | case SYS_FLEN: |
218 | - { | 314 | + if (use_gdb_syscalls()) { |
315 | + /* TODO: Use stat syscall. */ | ||
316 | + return -1; | ||
317 | + } else { | ||
219 | struct stat buf; | 318 | struct stat buf; |
220 | ret = set_swi_errno(ts, fstat(ARG(0), &buf)); | 319 | ret = set_swi_errno(ts, fstat(ARG(0), &buf)); |
221 | if (ret == (uint32_t)-1) | 320 | if (ret == (uint32_t)-1) |
@@ -226,12 +325,21 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -226,12 +325,21 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
226 | /* XXX: Not implemented. */ | 325 | /* XXX: Not implemented. */ |
227 | return -1; | 326 | return -1; |
228 | case SYS_REMOVE: | 327 | case SYS_REMOVE: |
229 | - s = lock_user_string(ARG(0)); | ||
230 | - ret = set_swi_errno(ts, remove(s)); | ||
231 | - unlock_user(s, ARG(0), 0); | 328 | + if (use_gdb_syscalls()) { |
329 | + gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)); | ||
330 | + ret = env->regs[0]; | ||
331 | + } else { | ||
332 | + s = lock_user_string(ARG(0)); | ||
333 | + ret = set_swi_errno(ts, remove(s)); | ||
334 | + unlock_user(s, ARG(0), 0); | ||
335 | + } | ||
232 | return ret; | 336 | return ret; |
233 | case SYS_RENAME: | 337 | case SYS_RENAME: |
234 | - { | 338 | + if (use_gdb_syscalls()) { |
339 | + gdb_do_syscall(arm_semi_cb, "rename,%s,%s", | ||
340 | + ARG(0), (int)ARG(1), ARG(2), (int)ARG(3)); | ||
341 | + return env->regs[0]; | ||
342 | + } else { | ||
235 | char *s2; | 343 | char *s2; |
236 | s = lock_user_string(ARG(0)); | 344 | s = lock_user_string(ARG(0)); |
237 | s2 = lock_user_string(ARG(2)); | 345 | s2 = lock_user_string(ARG(2)); |
@@ -245,9 +353,14 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -245,9 +353,14 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
245 | case SYS_TIME: | 353 | case SYS_TIME: |
246 | return set_swi_errno(ts, time(NULL)); | 354 | return set_swi_errno(ts, time(NULL)); |
247 | case SYS_SYSTEM: | 355 | case SYS_SYSTEM: |
248 | - s = lock_user_string(ARG(0)); | ||
249 | - ret = set_swi_errno(ts, system(s)); | ||
250 | - unlock_user(s, ARG(0), 0); | 356 | + if (use_gdb_syscalls()) { |
357 | + gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)); | ||
358 | + return env->regs[0]; | ||
359 | + } else { | ||
360 | + s = lock_user_string(ARG(0)); | ||
361 | + ret = set_swi_errno(ts, system(s)); | ||
362 | + unlock_user(s, ARG(0), 0); | ||
363 | + } | ||
251 | case SYS_ERRNO: | 364 | case SYS_ERRNO: |
252 | #ifdef CONFIG_USER_ONLY | 365 | #ifdef CONFIG_USER_ONLY |
253 | return ts->swi_errno; | 366 | return ts->swi_errno; |
gdbstub.c
@@ -52,6 +52,7 @@ enum RSState { | @@ -52,6 +52,7 @@ enum RSState { | ||
52 | RS_GETLINE, | 52 | RS_GETLINE, |
53 | RS_CHKSUM1, | 53 | RS_CHKSUM1, |
54 | RS_CHKSUM2, | 54 | RS_CHKSUM2, |
55 | + RS_SYSCALL, | ||
55 | }; | 56 | }; |
56 | typedef struct GDBState { | 57 | typedef struct GDBState { |
57 | CPUState *env; /* current CPU */ | 58 | CPUState *env; /* current CPU */ |
@@ -96,6 +97,27 @@ static int get_char(GDBState *s) | @@ -96,6 +97,27 @@ static int get_char(GDBState *s) | ||
96 | } | 97 | } |
97 | #endif | 98 | #endif |
98 | 99 | ||
100 | +/* GDB stub state for use by semihosting syscalls. */ | ||
101 | +static GDBState *gdb_syscall_state; | ||
102 | +static gdb_syscall_complete_cb gdb_current_syscall_cb; | ||
103 | + | ||
104 | +enum { | ||
105 | + GDB_SYS_UNKNOWN, | ||
106 | + GDB_SYS_ENABLED, | ||
107 | + GDB_SYS_DISABLED, | ||
108 | +} gdb_syscall_mode; | ||
109 | + | ||
110 | +/* If gdb is connected when the first semihosting syscall occurs then use | ||
111 | + remote gdb syscalls. Otherwise use native file IO. */ | ||
112 | +int use_gdb_syscalls(void) | ||
113 | +{ | ||
114 | + if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { | ||
115 | + gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED | ||
116 | + : GDB_SYS_DISABLED); | ||
117 | + } | ||
118 | + return gdb_syscall_mode == GDB_SYS_ENABLED; | ||
119 | +} | ||
120 | + | ||
99 | static void put_buffer(GDBState *s, const uint8_t *buf, int len) | 121 | static void put_buffer(GDBState *s, const uint8_t *buf, int len) |
100 | { | 122 | { |
101 | #ifdef CONFIG_USER_ONLY | 123 | #ifdef CONFIG_USER_ONLY |
@@ -755,6 +777,34 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) | @@ -755,6 +777,34 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) | ||
755 | vm_start(); | 777 | vm_start(); |
756 | #endif | 778 | #endif |
757 | return RS_IDLE; | 779 | return RS_IDLE; |
780 | + case 'F': | ||
781 | + { | ||
782 | + target_ulong ret; | ||
783 | + target_ulong err; | ||
784 | + | ||
785 | + ret = strtoull(p, (char **)&p, 16); | ||
786 | + if (*p == ',') { | ||
787 | + p++; | ||
788 | + err = strtoull(p, (char **)&p, 16); | ||
789 | + } else { | ||
790 | + err = 0; | ||
791 | + } | ||
792 | + if (*p == ',') | ||
793 | + p++; | ||
794 | + type = *p; | ||
795 | + if (gdb_current_syscall_cb) | ||
796 | + gdb_current_syscall_cb(s->env, ret, err); | ||
797 | + if (type == 'C') { | ||
798 | + put_packet(s, "T02"); | ||
799 | + } else { | ||
800 | +#ifdef CONFIG_USER_ONLY | ||
801 | + s->running_state = 1; | ||
802 | +#else | ||
803 | + vm_start(); | ||
804 | +#endif | ||
805 | + } | ||
806 | + } | ||
807 | + break; | ||
758 | case 'g': | 808 | case 'g': |
759 | reg_size = cpu_gdb_read_registers(env, mem_buf); | 809 | reg_size = cpu_gdb_read_registers(env, mem_buf); |
760 | memtohex(buf, mem_buf, reg_size); | 810 | memtohex(buf, mem_buf, reg_size); |
@@ -855,6 +905,9 @@ static void gdb_vm_stopped(void *opaque, int reason) | @@ -855,6 +905,9 @@ static void gdb_vm_stopped(void *opaque, int reason) | ||
855 | char buf[256]; | 905 | char buf[256]; |
856 | int ret; | 906 | int ret; |
857 | 907 | ||
908 | + if (s->state == RS_SYSCALL) | ||
909 | + return; | ||
910 | + | ||
858 | /* disable single step if it was enable */ | 911 | /* disable single step if it was enable */ |
859 | cpu_single_step(s->env, 0); | 912 | cpu_single_step(s->env, 0); |
860 | 913 | ||
@@ -871,6 +924,60 @@ static void gdb_vm_stopped(void *opaque, int reason) | @@ -871,6 +924,60 @@ static void gdb_vm_stopped(void *opaque, int reason) | ||
871 | } | 924 | } |
872 | #endif | 925 | #endif |
873 | 926 | ||
927 | +/* Send a gdb syscall request. | ||
928 | + This accepts limited printf-style format specifiers, specifically: | ||
929 | + %x - target_ulong argument printed in hex. | ||
930 | + %s - string pointer (target_ulong) and length (int) pair. */ | ||
931 | +void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...) | ||
932 | +{ | ||
933 | + va_list va; | ||
934 | + char buf[256]; | ||
935 | + char *p; | ||
936 | + target_ulong addr; | ||
937 | + GDBState *s; | ||
938 | + | ||
939 | + s = gdb_syscall_state; | ||
940 | + if (!s) | ||
941 | + return; | ||
942 | + gdb_current_syscall_cb = cb; | ||
943 | + s->state = RS_SYSCALL; | ||
944 | +#ifndef CONFIG_USER_ONLY | ||
945 | + vm_stop(EXCP_DEBUG); | ||
946 | +#endif | ||
947 | + s->state = RS_IDLE; | ||
948 | + va_start(va, fmt); | ||
949 | + p = buf; | ||
950 | + *(p++) = 'F'; | ||
951 | + while (*fmt) { | ||
952 | + if (*fmt == '%') { | ||
953 | + fmt++; | ||
954 | + switch (*fmt++) { | ||
955 | + case 'x': | ||
956 | + addr = va_arg(va, target_ulong); | ||
957 | + p += sprintf(p, TARGET_FMT_lx, addr); | ||
958 | + break; | ||
959 | + case 's': | ||
960 | + addr = va_arg(va, target_ulong); | ||
961 | + p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int)); | ||
962 | + break; | ||
963 | + default: | ||
964 | + fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n", | ||
965 | + fmt - 1); | ||
966 | + break; | ||
967 | + } | ||
968 | + } else { | ||
969 | + *(p++) = *(fmt++); | ||
970 | + } | ||
971 | + } | ||
972 | + va_end(va); | ||
973 | + put_packet(s, buf); | ||
974 | +#ifdef CONFIG_USER_ONLY | ||
975 | + gdb_handlesig(s->env, 0); | ||
976 | +#else | ||
977 | + cpu_interrupt(s->env, CPU_INTERRUPT_EXIT); | ||
978 | +#endif | ||
979 | +} | ||
980 | + | ||
874 | static void gdb_read_byte(GDBState *s, int ch) | 981 | static void gdb_read_byte(GDBState *s, int ch) |
875 | { | 982 | { |
876 | CPUState *env = s->env; | 983 | CPUState *env = s->env; |
@@ -942,6 +1049,8 @@ static void gdb_read_byte(GDBState *s, int ch) | @@ -942,6 +1049,8 @@ static void gdb_read_byte(GDBState *s, int ch) | ||
942 | s->state = gdb_handle_packet(s, env, s->line_buf); | 1049 | s->state = gdb_handle_packet(s, env, s->line_buf); |
943 | } | 1050 | } |
944 | break; | 1051 | break; |
1052 | + default: | ||
1053 | + abort(); | ||
945 | } | 1054 | } |
946 | } | 1055 | } |
947 | } | 1056 | } |
@@ -1034,6 +1143,8 @@ static void gdb_accept(void *opaque) | @@ -1034,6 +1143,8 @@ static void gdb_accept(void *opaque) | ||
1034 | s->env = first_cpu; /* XXX: allow to change CPU */ | 1143 | s->env = first_cpu; /* XXX: allow to change CPU */ |
1035 | s->fd = fd; | 1144 | s->fd = fd; |
1036 | 1145 | ||
1146 | + gdb_syscall_state = s; | ||
1147 | + | ||
1037 | fcntl(fd, F_SETFL, O_NONBLOCK); | 1148 | fcntl(fd, F_SETFL, O_NONBLOCK); |
1038 | } | 1149 | } |
1039 | 1150 | ||
@@ -1098,6 +1209,7 @@ static void gdb_chr_event(void *opaque, int event) | @@ -1098,6 +1209,7 @@ static void gdb_chr_event(void *opaque, int event) | ||
1098 | switch (event) { | 1209 | switch (event) { |
1099 | case CHR_EVENT_RESET: | 1210 | case CHR_EVENT_RESET: |
1100 | vm_stop(EXCP_INTERRUPT); | 1211 | vm_stop(EXCP_INTERRUPT); |
1212 | + gdb_syscall_state = opaque; | ||
1101 | break; | 1213 | break; |
1102 | default: | 1214 | default: |
1103 | break; | 1215 | break; |
gdbstub.h
@@ -3,6 +3,11 @@ | @@ -3,6 +3,11 @@ | ||
3 | 3 | ||
4 | #define DEFAULT_GDBSTUB_PORT 1234 | 4 | #define DEFAULT_GDBSTUB_PORT 1234 |
5 | 5 | ||
6 | +typedef void (*gdb_syscall_complete_cb)(CPUState *env, | ||
7 | + target_ulong ret, target_ulong err); | ||
8 | + | ||
9 | +void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...); | ||
10 | +int use_gdb_syscalls(void); | ||
6 | #ifdef CONFIG_USER_ONLY | 11 | #ifdef CONFIG_USER_ONLY |
7 | int gdb_handlesig (CPUState *, int); | 12 | int gdb_handlesig (CPUState *, int); |
8 | void gdb_exit(CPUState *, int); | 13 | void gdb_exit(CPUState *, int); |