Create new file regcache.h. Update all uses.
[deliverable/binutils-gdb.git] / gdb / wince.c
CommitLineData
0f07afe1 1/* Target-vector operations for controlling Windows CE child processes, for GDB.
29e57380 2 Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
0f07afe1
CF
3 Contributed by Cygnus Solutions, A Red Hat Company.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
dc8d251e 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
0f07afe1
CF
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21 */
22
23/* by Christopher Faylor (cgf@cygnus.com) */
24
25/* We assume we're being built with and will be used for cygwin. */
26
27#ifdef SHx
28#undef SH4
29#define SH4 /* Just to get all of the CONTEXT defines. */
30#endif
31
32#include "defs.h"
33#include "frame.h" /* required by inferior.h */
34#include "inferior.h"
35#include "target.h"
0f07afe1
CF
36#include "gdbcore.h"
37#include "command.h"
38#include <signal.h>
39#include <sys/types.h>
40#include <fcntl.h>
41#include <stdlib.h>
42
43#include <windows.h>
44#include <rapi.h>
45#include <netdb.h>
46#include <cygwin/in.h>
47#include <cygwin/socket.h>
48
49#include "buildsym.h"
50#include "symfile.h"
51#include "objfiles.h"
52#include "gdb_string.h"
53#include "gdbthread.h"
54#include "gdbcmd.h"
55#include <sys/param.h>
56#include "wince-stub.h"
61c37cee 57#include <time.h>
4e052eda 58#include "regcache.h"
0f07afe1
CF
59
60/* The ui's event loop. */
507f3c78 61extern int (*ui_loop_hook) (int signo);
0f07afe1
CF
62
63/* If we're not using the old Cygwin header file set, define the
64 following which never should have been in the generic Win32 API
65 headers in the first place since they were our own invention... */
66#ifndef _GNU_H_WINDOWS_H
67#define FLAG_TRACE_BIT 0x100
68#ifdef CONTEXT_FLOATING_POINT
69#define CONTEXT_DEBUGGER0 (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
70#else
71#define CONTEXT_DEBUGGER0 (CONTEXT_FULL)
72#endif
73#endif
74
75#ifdef SH4
76#define CONTEXT_DEBUGGER ((CONTEXT_DEBUGGER0 & ~(CONTEXT_SH4 | CONTEXT_FLOATING_POINT)) | CONTEXT_SH3)
77#else
78#define CONTEXT_DEBUGGER CONTEXT_DEBUGGER0
79#endif
80/* The string sent by cygwin when it processes a signal.
81 FIXME: This should be in a cygwin include file. */
82#define CYGWIN_SIGNAL_STRING "cygwin: signal"
83
84#define CHECK(x) check (x, __FILE__,__LINE__)
85#define DEBUG_EXEC(x) if (debug_exec) printf x
86#define DEBUG_EVENTS(x) if (debug_events) printf x
87#define DEBUG_MEM(x) if (debug_memory) printf x
88#define DEBUG_EXCEPT(x) if (debug_exceptions) printf x
89
90static int connection_initialized = 0; /* True if we've initialized a RAPI session. */
91
0f07afe1
CF
92/* The directory where the stub and executable files are uploaded. */
93static const char *remote_directory = "\\gdb";
94
95/* The types automatic upload available. */
96static enum
97 {
98 UPLOAD_ALWAYS = 0,
99 UPLOAD_NEWER = 1,
100 UPLOAD_NEVER = 2
101 }
102upload_when = UPLOAD_NEWER;
103
104/* Valid options for 'set remoteupload'. Note that options
105 must track upload_when enum. */
106static struct opts
107 {
108 const char *name;
109 int abbrev;
110 }
111upload_options[3] =
112{
113 {
114 "always", 1
115 }
116 ,
117 {
118 "newer", 3
119 }
120 ,
121 {
122 "never", 3
123 }
124};
125
126static char *remote_upload = NULL; /* Set by set remoteupload */
127static int remote_add_host = 0;
128
129/* Forward declaration */
130extern struct target_ops child_ops;
131
a14ed312
KB
132static int win32_child_thread_alive (int);
133void child_kill_inferior (void);
0f07afe1
CF
134
135static int last_sig = 0; /* Set if a signal was received from the
136 debugged process */
137
138/* Thread information structure used to track information that is
139 not available in gdb's thread structure. */
140typedef struct thread_info_struct
141 {
142 struct thread_info_struct *next;
143 DWORD id;
144 HANDLE h;
145 char *name;
146 int suspend_count;
147 int stepped; /* True if stepped. */
148 CORE_ADDR step_pc;
0f07afe1
CF
149 unsigned long step_prev;
150 CONTEXT context;
151 }
152thread_info;
153
154static thread_info thread_head =
155{NULL};
61c37cee 156static thread_info * thread_rec (DWORD id, int get_context);
0f07afe1
CF
157
158/* The process and thread handles for the above context. */
159
160static DEBUG_EVENT current_event; /* The current debug event from
161 WaitForDebugEvent */
162static HANDLE current_process_handle; /* Currently executing process */
163static thread_info *current_thread; /* Info on currently selected thread */
164static thread_info *this_thread; /* Info on thread returned by wait_for_debug_event */
165static DWORD main_thread_id; /* Thread ID of the main thread */
166
167/* Counts of things. */
168static int exception_count = 0;
169static int event_count = 0;
170
171/* User options. */
172static int debug_exec = 0; /* show execution */
173static int debug_events = 0; /* show events from kernel */
174static int debug_memory = 0; /* show target memory accesses */
175static int debug_exceptions = 0; /* show target exceptions */
176
177/* An array of offset mappings into a Win32 Context structure.
178 This is a one-to-one mapping which is indexed by gdb's register
179 numbers. It retrieves an offset into the context structure where
180 the 4 byte register is located.
181 An offset value of -1 indicates that Win32 does not provide this
182 register in it's CONTEXT structure. regptr will return zero for this
183 register.
184
185 This is used by the regptr function. */
186#define context_offset(x) ((int)&(((PCONTEXT)NULL)->x))
187static const int mappings[NUM_REGS + 1] =
188{
189#ifdef __i386__
190 context_offset (Eax),
191 context_offset (Ecx),
192 context_offset (Edx),
193 context_offset (Ebx),
194 context_offset (Esp),
195 context_offset (Ebp),
196 context_offset (Esi),
197 context_offset (Edi),
198 context_offset (Eip),
199 context_offset (EFlags),
200 context_offset (SegCs),
201 context_offset (SegSs),
202 context_offset (SegDs),
203 context_offset (SegEs),
204 context_offset (SegFs),
205 context_offset (SegGs),
206 context_offset (FloatSave.RegisterArea[0 * 10]),
207 context_offset (FloatSave.RegisterArea[1 * 10]),
208 context_offset (FloatSave.RegisterArea[2 * 10]),
209 context_offset (FloatSave.RegisterArea[3 * 10]),
210 context_offset (FloatSave.RegisterArea[4 * 10]),
211 context_offset (FloatSave.RegisterArea[5 * 10]),
212 context_offset (FloatSave.RegisterArea[6 * 10]),
213 context_offset (FloatSave.RegisterArea[7 * 10]),
214#elif defined(SHx)
215 context_offset (R0),
216 context_offset (R1),
217 context_offset (R2),
218 context_offset (R3),
219 context_offset (R4),
220 context_offset (R5),
221 context_offset (R6),
222 context_offset (R7),
223 context_offset (R8),
224 context_offset (R9),
225 context_offset (R10),
226 context_offset (R11),
227 context_offset (R12),
228 context_offset (R13),
229 context_offset (R14),
230 context_offset (R15),
231 context_offset (Fir),
232 context_offset (PR), /* Procedure Register */
233 context_offset (GBR), /* Global Base Register */
234 context_offset (MACH), /* Accumulate */
235 context_offset (MACL), /* Multiply */
236 context_offset (Psr),
237 context_offset (Fpul),
238 context_offset (Fpscr),
239 context_offset (FRegs[0]),
240 context_offset (FRegs[1]),
241 context_offset (FRegs[2]),
242 context_offset (FRegs[3]),
243 context_offset (FRegs[4]),
244 context_offset (FRegs[5]),
245 context_offset (FRegs[6]),
246 context_offset (FRegs[7]),
247 context_offset (FRegs[8]),
248 context_offset (FRegs[9]),
249 context_offset (FRegs[10]),
250 context_offset (FRegs[11]),
251 context_offset (FRegs[12]),
252 context_offset (FRegs[13]),
253 context_offset (FRegs[14]),
254 context_offset (FRegs[15]),
255 context_offset (xFRegs[0]),
256 context_offset (xFRegs[1]),
257 context_offset (xFRegs[2]),
258 context_offset (xFRegs[3]),
259 context_offset (xFRegs[4]),
260 context_offset (xFRegs[5]),
261 context_offset (xFRegs[6]),
262 context_offset (xFRegs[7]),
263 context_offset (xFRegs[8]),
264 context_offset (xFRegs[9]),
265 context_offset (xFRegs[10]),
266 context_offset (xFRegs[11]),
267 context_offset (xFRegs[12]),
268 context_offset (xFRegs[13]),
269 context_offset (xFRegs[14]),
270 context_offset (xFRegs[15]),
271#elif defined(MIPS)
272 context_offset (IntZero),
273 context_offset (IntAt),
274 context_offset (IntV0),
275 context_offset (IntV1),
276 context_offset (IntA0),
277 context_offset (IntA1),
278 context_offset (IntA2),
279 context_offset (IntA3),
280 context_offset (IntT0),
281 context_offset (IntT1),
282 context_offset (IntT2),
283 context_offset (IntT3),
284 context_offset (IntT4),
285 context_offset (IntT5),
286 context_offset (IntT6),
287 context_offset (IntT7),
288 context_offset (IntS0),
289 context_offset (IntS1),
290 context_offset (IntS2),
291 context_offset (IntS3),
292 context_offset (IntS4),
293 context_offset (IntS5),
294 context_offset (IntS6),
295 context_offset (IntS7),
296 context_offset (IntT8),
297 context_offset (IntT9),
298 context_offset (IntK0),
299 context_offset (IntK1),
300 context_offset (IntGp),
301 context_offset (IntSp),
302 context_offset (IntS8),
303 context_offset (IntRa),
304 context_offset (Psr),
305 context_offset (IntLo),
306 context_offset (IntHi),
307 -1, /* bad */
308 -1, /* cause */
309 context_offset (Fir),
310 context_offset (FltF0),
311 context_offset (FltF1),
312 context_offset (FltF2),
313 context_offset (FltF3),
314 context_offset (FltF4),
315 context_offset (FltF5),
316 context_offset (FltF6),
317 context_offset (FltF7),
318 context_offset (FltF8),
319 context_offset (FltF9),
320 context_offset (FltF10),
321 context_offset (FltF11),
322 context_offset (FltF12),
323 context_offset (FltF13),
324 context_offset (FltF14),
325 context_offset (FltF15),
326 context_offset (FltF16),
327 context_offset (FltF17),
328 context_offset (FltF18),
329 context_offset (FltF19),
330 context_offset (FltF20),
331 context_offset (FltF21),
332 context_offset (FltF22),
333 context_offset (FltF23),
334 context_offset (FltF24),
335 context_offset (FltF25),
336 context_offset (FltF26),
337 context_offset (FltF27),
338 context_offset (FltF28),
339 context_offset (FltF29),
340 context_offset (FltF30),
341 context_offset (FltF31),
342 context_offset (Fsr),
343 context_offset (Fir),
344 -1, /* fp */
345#elif defined(ARM)
346 context_offset (R0),
347 context_offset (R1),
348 context_offset (R2),
349 context_offset (R3),
350 context_offset (R4),
351 context_offset (R5),
352 context_offset (R6),
353 context_offset (R7),
354 context_offset (R8),
355 context_offset (R9),
356 context_offset (R10),
357 context_offset (R11),
358 context_offset (R12),
359 context_offset (Sp),
360 context_offset (Lr),
361 context_offset (Pc),
362 -1,
363 -1,
364 -1,
365 -1,
366 -1,
367 -1,
368 -1,
369 -1,
370 -1,
371 context_offset (Psr),
372#endif
373 -1
374};
375
61c37cee
CF
376/* Return a pointer into a CONTEXT field indexed by gdb register number.
377 Return a pointer to an address pointing to zero if there is no
378 corresponding CONTEXT field for the given register number.
379 */
380static ULONG *
381regptr (LPCONTEXT c, int r)
0f07afe1 382{
61c37cee
CF
383 static ULONG zero = 0;
384 ULONG *p;
385 if (mappings[r] < 0)
386 p = &zero;
387 else
388 p = (ULONG *) (((char *) c) + mappings[r]);
389 return p;
390}
0f07afe1
CF
391
392/******************** Beginning of stub interface ********************/
393
394/* Stub interface description:
395
396 The Windows CE stub implements a crude RPC. The hand-held device
397 connects to gdb using port 7000. gdb and the stub then communicate
398 using packets where:
399
400 byte 0: command id (e.g. Create Process)
401
402 byte 1-4: DWORD
403
404 byte 1-2: WORD
405
406 byte 1-2: length
407 byte 3-n: arbitrary memory.
408
409 The interface is deterministic, i.e., if the stub expects a DWORD then
410 the gdb server should send a DWORD.
411 */
412
413/* Note: In the functions below, the `huh' parameter is a string passed from the
414 function containing a descriptive string concerning the current operation.
415 This is used for error reporting.
416
417 The 'what' parameter is a command id as found in wince-stub.h.
418
419 Hopefully, the rest of the parameters are self-explanatory.
420 */
421
422static int s; /* communication socket */
423
424/* v-style interface for handling varying argyment list error messages.
425 Displays the error message in a dialog box and exits when user clicks
426 on OK. */
427static void
428vstub_error (LPCSTR fmt, va_list * args)
429{
430 char buf[4096];
431 vsprintf (buf, fmt, args);
432 s = -1;
433 error ("%s", buf);
434}
435
436/* The standard way to display an error message and exit. */
437static void
438stub_error (LPCSTR fmt,...)
439{
440 va_list args;
441 va_start (args, fmt);
442 vstub_error (fmt, args);
443}
444
445/* Standard "oh well" can't communicate error. Someday this might attempt
446 synchronization. */
447static void
448attempt_resync (LPCSTR huh, int s)
449{
450 stub_error ("lost synchronization with target attempting %s", huh);
451}
452
453/* Read arbitrary stuff from a socket. */
454static int
455sockread (LPCSTR huh, int s, void *str, size_t n)
456{
457 for (;;)
458 {
459 if (recv (s, str, n, 0) == n)
460 return n;
461 attempt_resync (huh, s);
462 }
463}
464
465/* Write arbitrary stuff to a socket. */
466static int
467sockwrite (LPCSTR huh, const void *str, size_t n)
468{
469 for (;;)
470 {
471 if (send (s, str, n, 0) == n)
472 return n;
473 attempt_resync (huh, s);
474 }
475}
476
477/* Output an id/dword to the host */
478static void
479putdword (LPCSTR huh, gdb_wince_id what, DWORD n)
480{
481 if (sockwrite (huh, &what, sizeof (what)) != sizeof (what))
482 stub_error ("error writing record id to host for %s", huh);
483 if (sockwrite (huh, &n, sizeof (n)) != sizeof (n))
484 stub_error ("error writing %s to host.", huh);
485}
486
487/* Output an id/word to the host */
488static void
489putword (LPCSTR huh, gdb_wince_id what, WORD n)
490{
491 if (sockwrite (huh, &what, sizeof (what)) != sizeof (what))
492 stub_error ("error writing record id to host for %s", huh);
493 if (sockwrite (huh, &n, sizeof (n)) != sizeof (n))
494 stub_error ("error writing %s host.", huh);
495}
496
497/* Convenience define for outputting a "gdb_wince_len" type. */
498#define putlen(huh, what, n) putword((huh), (what), (gdb_wince_len) (n))
499
500/* Put an arbitrary block of memory to the gdb host. This comes in
501 two chunks an id/dword representing the length and the stream of memory
502 itself. */
503static void
504putmemory (LPCSTR huh, gdb_wince_id what, const void *mem, gdb_wince_len len)
505{
506 putlen (huh, what, len);
507 if (((short) len > 0) && sockwrite (huh, mem, len) != len)
508 stub_error ("error writing %s to host.", huh);
509}
510
511/* Output the result of an operation to the host. If res != 0, sends a block of
512 memory starting at mem of len bytes. If res == 0, sends -GetLastError () and
513 avoids sending the mem. */
514static DWORD
515getdword (LPCSTR huh, gdb_wince_id what_this)
516{
517 DWORD n;
518 gdb_wince_id what;
519 do
520 if (sockread (huh, s, &what, sizeof (what)) != sizeof (what))
521 stub_error ("error getting record type from host - %s.", huh);
522 while (what_this != what);
523
524 if (sockread (huh, s, &n, sizeof (n)) != sizeof (n))
525 stub_error ("error getting %s from host.", huh);
526
527 return n;
528}
529
530/* Get a an ID (possibly) and a WORD from the host gdb.
531 Don't bother with the id if the main loop has already
532 read it. */
533static WORD
534getword (LPCSTR huh, gdb_wince_id what_this)
535{
536 WORD n;
537 gdb_wince_id what;
538 do
539 if (sockread (huh, s, &what, sizeof (what)) != sizeof (what))
540 stub_error ("error getting record type from host - %s.", huh);
541 while (what_this != what);
542
543 if (sockread (huh, s, &n, sizeof (n)) != sizeof (n))
544 stub_error ("error getting %s from host.", huh);
545
546 return n;
547}
548
549/* Handy defines for getting/putting various types of values. */
550#define gethandle(huh, what) (HANDLE) getdword ((huh), (what))
551#define getpvoid(huh, what) (LPVOID) getdword ((huh), (what))
552#define getlen(huh, what) (gdb_wince_len) getword ((huh), (what))
553#define puthandle(huh, what, h) putdword ((huh), (what), (DWORD) (h))
554#define putpvoid(huh, what, p) putdword ((huh), (what), (DWORD) (p))
555
556/* Retrieve the result of an operation from the stub. If nbytes < 0) then nbytes
557 is actually an error and nothing else follows. Use SetLastError to remember this.
558 if nbytes > 0, retrieve a block of *nbytes into buf.
559 */
560int
561getresult (LPCSTR huh, gdb_wince_id what, LPVOID buf, gdb_wince_len * nbytes)
562{
563 gdb_wince_len dummy;
564 if (nbytes == NULL)
565 nbytes = &dummy;
566
567 *nbytes = getlen (huh, what);
568
569 if ((short) *nbytes < 0)
570 {
571 SetLastError (-(short) *nbytes);
572 return 0;
573 }
574
575 if ((gdb_wince_len) sockread (huh, s, buf, *nbytes) != *nbytes)
576 stub_error ("couldn't read information from wince stub - %s", huh);
577
578 return 1;
579}
580
581/* Convert "narrow" string to "wide". Manipulates a buffer ring of 8
582 buffers which hold the translated string. This is an arbitrary limit
583 but it is approximately double the current needs of this module.
584 */
585LPWSTR
586towide (const char *s, gdb_wince_len * out_len)
587{
588 static int n = -1;
589 static LPWSTR outs[8] =
590 {NULL /*, NULL, etc. */ };
591 gdb_wince_len dummy;
592
593 if (!out_len)
594 out_len = &dummy;
595
596 /* First determine the length required to hold the converted string. */
597 *out_len = sizeof (WCHAR) * MultiByteToWideChar (CP_ACP, 0, s, -1, NULL, 0);
598 if (!*out_len)
599 return NULL; /* The conversion failed */
600
601 if (++n >= (sizeof (outs) / sizeof (outs[0])))
602 n = 0; /* wrap */
603
604 /* Allocate space for the converted string, reusing any previously allocated
605 space, if applicable. Note that if outs[n] is NULL, realloc will act as
606 a malloc (under cygwin, at least).
607 */
608 outs[n] = (LPWSTR) realloc (outs[n], *out_len);
609 memset (outs[n], 0, *out_len);
610 (void) MultiByteToWideChar (CP_ACP, 0, s, -1, outs[n], *out_len);
611 return outs[n];
612}
613
614/******************** Emulation routines start here. ********************
615
616 The functions below are modelled after their Win32 counterparts. They are named
617 similarly to Win32 and take exactly the same arguments except where otherwise noted.
618 They communicate with the stub on the hand-held device by sending their arguments
619 over the socket and waiting for results from the socket.
620
621 There is one universal change. In cases where a length is expected to be returned
622 in a DWORD, we use a gdb_wince_len type instead. Currently this is an unsigned short
623 which is smaller than the standard Win32 DWORD. This is done to minimize unnecessary
624 traffic since the connection to Windows CE can be slow. To change this, modify the
625 typedef in wince-stub.h and change the putlen/getlen macros in this file and in
626 the stub.
627*/
61c37cee 628
0f07afe1
CF
629static int
630create_process (LPSTR exec_file, LPSTR args, DWORD flags, PROCESS_INFORMATION * pi)
631{
632 gdb_wince_len len;
633 LPWSTR buf;
634
635 buf = towide (exec_file, &len);
636 putmemory ("CreateProcess exec_file", GDB_CREATEPROCESS, buf, len);
637 buf = towide (args, &len);
638 putmemory ("CreateProcess args", GDB_CREATEPROCESS, buf, len);
639 putdword ("CreateProcess flags", GDB_CREATEPROCESS, flags);
640 return getresult ("CreateProcess result", GDB_CREATEPROCESS, pi, NULL);
641}
642
643/* Emulate TerminateProcess. Don't bother with the second argument since CE
644 ignores it.
645 */
646static int
647terminate_process (HANDLE h)
648{
649 gdb_wince_result res;
650 if (s < 0)
651 return 1;
652 puthandle ("TerminateProcess handle", GDB_TERMINATEPROCESS, h);
653 return getresult ("TerminateProcess result", GDB_TERMINATEPROCESS, &res, NULL);
654}
655
656static int
657wait_for_debug_event (DEBUG_EVENT * ev, DWORD ms)
658{
659 if (s < 0)
660 return 1;
661 putdword ("WaitForDebugEvent ms", GDB_WAITFORDEBUGEVENT, ms);
662 return getresult ("WaitForDebugEvent event", GDB_WAITFORDEBUGEVENT, ev, NULL);
663}
664
665static int
666get_thread_context (HANDLE h, CONTEXT * c)
667{
668 if (s < 0)
669 return 1;
670 puthandle ("GetThreadContext handle", GDB_GETTHREADCONTEXT, h);
671 putdword ("GetThreadContext flags", GDB_GETTHREADCONTEXT, c->ContextFlags);
672 return getresult ("GetThreadContext context", GDB_GETTHREADCONTEXT, c, NULL);
673}
674
675static int
676set_thread_context (HANDLE h, CONTEXT * c)
677{
678 gdb_wince_result res;
679 if (s < 0)
680 return 1;
681 puthandle ("SetThreadContext handle", GDB_SETTHREADCONTEXT, h);
682 putmemory ("SetThreadContext context", GDB_SETTHREADCONTEXT, c, sizeof (*c));
683 return getresult ("SetThreadContext context", GDB_SETTHREADCONTEXT, &res, NULL);
684}
685
686static int
687read_process_memory (HANDLE h, LPCVOID where, LPVOID buf, gdb_wince_len len, gdb_wince_len * nbytes)
688{
689 if (s < 0)
690 return 1;
691 puthandle ("ReadProcessMemory handle", GDB_READPROCESSMEMORY, h);
692 putpvoid ("ReadProcessMemory location", GDB_READPROCESSMEMORY, where);
693 putlen ("ReadProcessMemory size", GDB_READPROCESSMEMORY, len);
694
695 return getresult ("ReadProcessMemory buf", GDB_READPROCESSMEMORY, buf, nbytes);
696}
697
698static int
699write_process_memory (HANDLE h, LPCVOID where, LPCVOID buf, gdb_wince_len len, gdb_wince_len * nbytes)
700{
701 if (s < 0)
702 return 1;
703 puthandle ("WriteProcessMemory handle", GDB_WRITEPROCESSMEMORY, h);
704 putpvoid ("WriteProcessMemory location", GDB_WRITEPROCESSMEMORY, where);
705 putmemory ("WriteProcProcessMemory buf", GDB_WRITEPROCESSMEMORY, buf, len);
706
707 return getresult ("WriteProcessMemory result", GDB_WRITEPROCESSMEMORY, nbytes, NULL);
708}
709
710static int
711remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
712{
713 gdb_wince_len nbytes;
714 if (!read_process_memory (current_process_handle, (LPCVOID) memaddr,
715 (LPVOID) myaddr, len, &nbytes))
716 return -1;
717 return nbytes;
718}
719
720static int
721remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
722{
723 gdb_wince_len nbytes;
724 if (!write_process_memory (current_process_handle, (LPCVOID) memaddr,
725 (LPCVOID) myaddr, len, &nbytes))
726 return -1;
727 return nbytes;
728}
729
730/* This is not a standard Win32 function. It instructs the stub to return TRUE
731 if the thread referenced by HANDLE h is alive.
732 */
733static int
734thread_alive (HANDLE h)
735{
736 gdb_wince_result res;
737 if (s < 0)
738 return 1;
739 puthandle ("ThreadAlive handle", GDB_THREADALIVE, h);
740 return getresult ("ThreadAlive result", GDB_THREADALIVE, &res, NULL);
741}
742
743static int
744suspend_thread (HANDLE h)
745{
746 if (s < 0)
747 return 1;
748 puthandle ("SuspendThread handle", GDB_SUSPENDTHREAD, h);
749 return (int) getdword ("SuspendThread result", GDB_SUSPENDTHREAD);
750}
751
752static int
753resume_thread (HANDLE h)
754{
755 if (s < 0)
756 return 1;
757 puthandle ("ResumeThread handle", GDB_RESUMETHREAD, h);
758 return (int) getdword ("SuspendThread result", GDB_RESUMETHREAD);
759}
760
761static int
762continue_debug_event (DWORD pid, DWORD tid, DWORD status)
763{
764 gdb_wince_result res;
765 if (s < 0)
766 return 0;
767 putdword ("ContinueDebugEvent pid", GDB_CONTINUEDEBUGEVENT, pid);
768 putdword ("ContinueDebugEvent tid", GDB_CONTINUEDEBUGEVENT, tid);
769 putdword ("ContinueDebugEvent status", GDB_CONTINUEDEBUGEVENT, status);
770 return getresult ("ContinueDebugEvent result", GDB_CONTINUEDEBUGEVENT, &res, NULL);
771}
772
773static int
774close_handle (HANDLE h)
775{
776 gdb_wince_result res;
777 if (s < 0)
778 return 1;
779 puthandle ("CloseHandle handle", GDB_CLOSEHANDLE, h);
780 return (int) getresult ("CloseHandle result", GDB_CLOSEHANDLE, &res, NULL);
781}
782
783/* This is not a standard Win32 interface. This function tells the stub
784 to terminate.
785 */
786static void
fba45db2 787stop_stub (void)
0f07afe1
CF
788{
789 if (s < 0)
790 return;
791 (void) putdword ("Stopping gdb stub", GDB_STOPSTUB, 0);
792 s = -1;
793}
794
795/******************** End of emulation routines. ********************/
796/******************** End of stub interface ********************/
797
61c37cee
CF
798#define check_for_step(a, x) (x)
799
800#ifdef MIPS
801static void
802undoSStep (thread_info * th)
803{
804 if (th->stepped)
805 {
806 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
807 th->stepped = 0;
808 }
809}
810
811void
812wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
813{
814 unsigned long pc;
815 thread_info *th = current_thread; /* Info on currently selected thread */
816 CORE_ADDR mips_next_pc (CORE_ADDR pc);
817
818 if (!insert_breakpoints_p)
819 {
820 undoSStep (th);
821 return;
822 }
823
824 th->stepped = 1;
825 pc = read_register (PC_REGNUM);
826 th->step_pc = mips_next_pc (pc);
827 th->step_prev = 0;
828 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
829 return;
830}
831#elif SHx
832/* Hitachi SH architecture instruction encoding masks */
833
834#define COND_BR_MASK 0xff00
835#define UCOND_DBR_MASK 0xe000
836#define UCOND_RBR_MASK 0xf0df
837#define TRAPA_MASK 0xff00
838
839#define COND_DISP 0x00ff
840#define UCOND_DISP 0x0fff
841#define UCOND_REG 0x0f00
842
843/* Hitachi SH instruction opcodes */
844
845#define BF_INSTR 0x8b00
846#define BT_INSTR 0x8900
847#define BRA_INSTR 0xa000
848#define BSR_INSTR 0xb000
849#define JMP_INSTR 0x402b
850#define JSR_INSTR 0x400b
851#define RTS_INSTR 0x000b
852#define RTE_INSTR 0x002b
853#define TRAPA_INSTR 0xc300
854#define SSTEP_INSTR 0xc3ff
855
856
857#define T_BIT_MASK 0x0001
858
859static CORE_ADDR
860sh_get_next_pc (CONTEXT *c)
861{
862 short *instrMem;
863 int displacement;
864 int reg;
865 unsigned short opcode;
866
867 instrMem = (short *) c->Fir;
868
869 opcode = read_memory_integer ((CORE_ADDR) c->Fir, sizeof (opcode));
870
871 if ((opcode & COND_BR_MASK) == BT_INSTR)
872 {
873 if (c->Psr & T_BIT_MASK)
874 {
875 displacement = (opcode & COND_DISP) << 1;
876 if (displacement & 0x80)
877 displacement |= 0xffffff00;
878 /*
879 * Remember PC points to second instr.
880 * after PC of branch ... so add 4
881 */
882 instrMem = (short *) (c->Fir + displacement + 4);
883 }
884 else
885 instrMem += 1;
886 }
887 else if ((opcode & COND_BR_MASK) == BF_INSTR)
888 {
889 if (c->Psr & T_BIT_MASK)
890 instrMem += 1;
891 else
892 {
893 displacement = (opcode & COND_DISP) << 1;
894 if (displacement & 0x80)
895 displacement |= 0xffffff00;
896 /*
897 * Remember PC points to second instr.
898 * after PC of branch ... so add 4
899 */
900 instrMem = (short *) (c->Fir + displacement + 4);
901 }
902 }
903 else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR)
904 {
905 displacement = (opcode & UCOND_DISP) << 1;
906 if (displacement & 0x0800)
907 displacement |= 0xfffff000;
908
909 /*
910 * Remember PC points to second instr.
911 * after PC of branch ... so add 4
912 */
913 instrMem = (short *) (c->Fir + displacement + 4);
914 }
915 else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR)
916 {
917 reg = (char) ((opcode & UCOND_REG) >> 8);
918
919 instrMem = (short *) *regptr (c, reg);
920 }
921 else if (opcode == RTS_INSTR)
922 instrMem = (short *) c->PR;
923 else if (opcode == RTE_INSTR)
924 instrMem = (short *) *regptr (c, 15);
925 else if ((opcode & TRAPA_MASK) == TRAPA_INSTR)
926 instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2);
927 else
928 instrMem += 1;
929
930 return (CORE_ADDR) instrMem;
931}
932/* Single step (in a painstaking fashion) by inspecting the current
933 instruction and setting a breakpoint on the "next" instruction
934 which would be executed. This code hails from sh-stub.c.
935 */
936static void
937undoSStep (thread_info * th)
938{
939 if (th->stepped)
940 {
941 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
942 th->stepped = 0;
943 }
944 return;
945}
946
947/* Single step (in a painstaking fashion) by inspecting the current
948 instruction and setting a breakpoint on the "next" instruction
949 which would be executed. This code hails from sh-stub.c.
950 */
951void
952wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
953{
954 thread_info *th = current_thread; /* Info on currently selected thread */
955
956 if (!insert_breakpoints_p)
957 {
958 undoSStep (th);
959 return;
960 }
961
962 th->stepped = 1;
963 th->step_pc = sh_get_next_pc (&th->context);
964 th->step_prev = 0;
965 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
966 return;
967}
968#elif defined (ARM)
969#undef check_for_step
970
971static enum target_signal
972check_for_step (DEBUG_EVENT *ev, enum target_signal x)
973{
974 thread_info *th = thread_rec (ev->dwThreadId, 1);
975
976 if (th->stepped &&
977 th->step_pc == (CORE_ADDR) ev->u.Exception.ExceptionRecord.ExceptionAddress)
978 return TARGET_SIGNAL_TRAP;
979 else
980 return x;
981}
982
983/* Single step (in a painstaking fashion) by inspecting the current
984 instruction and setting a breakpoint on the "next" instruction
985 which would be executed. This code hails from sh-stub.c.
986 */
987static void
988undoSStep (thread_info * th)
989{
990 if (th->stepped)
991 {
992 memory_remove_breakpoint (th->step_pc, (void *) &th->step_prev);
993 th->stepped = 0;
994 }
995}
996
997void
998wince_software_single_step (unsigned int ignore, int insert_breakpoints_p)
999{
1000 unsigned long pc;
1001 thread_info *th = current_thread; /* Info on currently selected thread */
1002 CORE_ADDR mips_next_pc (CORE_ADDR pc);
1003
1004 if (!insert_breakpoints_p)
1005 {
1006 undoSStep (th);
1007 return;
1008 }
1009
1010 th->stepped = 1;
1011 pc = read_register (PC_REGNUM);
1012 th->step_pc = arm_get_next_pc (pc);
1013 th->step_prev = 0;
1014 memory_insert_breakpoint (th->step_pc, (void *) &th->step_prev);
1015 return;
1016}
1017#endif
1018
0f07afe1
CF
1019/* Find a thread record given a thread id.
1020 If get_context then also retrieve the context for this
1021 thread. */
1022static thread_info *
1023thread_rec (DWORD id, int get_context)
1024{
1025 thread_info *th;
1026
1027 for (th = &thread_head; (th = th->next) != NULL;)
1028 if (th->id == id)
1029 {
1030 if (!th->suspend_count && get_context)
1031 {
1032 if (get_context > 0 && th != this_thread)
1033 th->suspend_count = suspend_thread (th->h) + 1;
1034 else if (get_context < 0)
1035 th->suspend_count = -1;
1036
1037 th->context.ContextFlags = CONTEXT_DEBUGGER;
1038 get_thread_context (th->h, &th->context);
1039 }
1040 return th;
1041 }
1042
1043 return NULL;
1044}
1045
1046/* Add a thread to the thread list */
1047static thread_info *
1048child_add_thread (DWORD id, HANDLE h)
1049{
1050 thread_info *th;
1051
1052 if ((th = thread_rec (id, FALSE)))
1053 return th;
1054
1055 th = (thread_info *) xmalloc (sizeof (*th));
1056 memset (th, 0, sizeof (*th));
1057 th->id = id;
1058 th->h = h;
1059 th->next = thread_head.next;
1060 thread_head.next = th;
1061 add_thread (id);
1062 return th;
1063}
1064
1065/* Clear out any old thread list and reintialize it to a
1066 pristine state. */
1067static void
fba45db2 1068child_init_thread_list (void)
0f07afe1
CF
1069{
1070 thread_info *th = &thread_head;
1071
1072 DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
1073 init_thread_list ();
1074 while (th->next != NULL)
1075 {
1076 thread_info *here = th->next;
1077 th->next = here->next;
1078 (void) close_handle (here->h);
b8c9b27d 1079 xfree (here);
0f07afe1
CF
1080 }
1081}
1082
1083/* Delete a thread from the list of threads */
1084static void
1085child_delete_thread (DWORD id)
1086{
1087 thread_info *th;
1088
1089 if (info_verbose)
1090 printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
1091 delete_thread (id);
1092
1093 for (th = &thread_head;
1094 th->next != NULL && th->next->id != id;
1095 th = th->next)
1096 continue;
1097
1098 if (th->next != NULL)
1099 {
1100 thread_info *here = th->next;
1101 th->next = here->next;
1102 close_handle (here->h);
b8c9b27d 1103 xfree (here);
0f07afe1
CF
1104 }
1105}
1106
1107static void
1108check (BOOL ok, const char *file, int line)
1109{
1110 if (!ok)
1111 printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
1112}
1113
0f07afe1
CF
1114static void
1115do_child_fetch_inferior_registers (int r)
1116{
1117 if (r >= 0)
1118 {
1119 supply_register (r, (char *) regptr (&current_thread->context, r));
1120 }
1121 else
1122 {
1123 for (r = 0; r < NUM_REGS; r++)
1124 do_child_fetch_inferior_registers (r);
1125 }
1126}
1127
1128static void
1129child_fetch_inferior_registers (int r)
1130{
1131 current_thread = thread_rec (inferior_pid, TRUE);
1132 do_child_fetch_inferior_registers (r);
1133}
1134
1135static void
1136do_child_store_inferior_registers (int r)
1137{
1138 if (r >= 0)
1139 read_register_gen (r, ((char *) &current_thread->context) + mappings[r]);
1140 else
1141 {
1142 for (r = 0; r < NUM_REGS; r++)
1143 do_child_store_inferior_registers (r);
1144 }
1145}
1146
1147/* Store a new register value into the current thread context */
1148static void
1149child_store_inferior_registers (int r)
1150{
1151 current_thread = thread_rec (inferior_pid, TRUE);
1152 do_child_store_inferior_registers (r);
1153}
1154
1155/* Wait for child to do something. Return pid of child, or -1 in case
1156 of error; store status through argument pointer OURSTATUS. */
1157
1158static int
1159handle_load_dll (PTR dummy)
1160{
1161 LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
1162 char dll_buf[MAX_PATH + 1];
1163 char *p, *bufp, *imgp, *dll_name, *dll_basename;
1164 int len;
1165
1166 dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
1167 if (!event->lpImageName)
1168 return 1;
1169
1170 len = 0;
1171 for (bufp = dll_buf, imgp = event->lpImageName;
1172 bufp < dll_buf + sizeof (dll_buf);
1173 bufp += 16, imgp += 16)
1174 {
1175 gdb_wince_len nbytes = 0;
1176 (void) read_process_memory (current_process_handle,
1177 imgp, bufp, 16, &nbytes);
1178
1179 if (!nbytes && bufp == dll_buf)
1180 return 1; /* couldn't read it */
1181 for (p = bufp; p < bufp + nbytes; p++)
1182 {
1183 len++;
1184 if (*p == '\0')
1185 goto out;
1186 if (event->fUnicode)
1187 p++;
1188 }
1189 if (!nbytes)
1190 break;
1191 }
1192
1193out:
1194 if (!len)
1195 return 1;
61c37cee 1196#if 0
0f07afe1 1197 dll_buf[len] = '\0';
61c37cee 1198#endif
0f07afe1
CF
1199 dll_name = alloca (len);
1200
1201 if (!dll_name)
1202 return 1;
1203
1204 if (!event->fUnicode)
1205 memcpy (dll_name, dll_buf, len);
1206 else
1207 WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) dll_buf, len,
1208 dll_name, len, 0, 0);
1209
1210 while ((p = strchr (dll_name, '\\')))
1211 *p = '/';
1212
1213 /* FIXME!! It would be nice to define one symbol which pointed to the
1214 front of the dll if we can't find any symbols. */
1215
1216 if (!(dll_basename = strrchr (dll_name, '/')))
1217 dll_basename = dll_name;
1218 else
1219 dll_basename++;
1220
1221 /* The symbols in a dll are offset by 0x1000, which is the
1222 the offset from 0 of the first byte in an image - because
1223 of the file header and the section alignment.
1224
1225 FIXME: Is this the real reason that we need the 0x1000 ? */
1226
1227 printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
0f07afe1
CF
1228 printf_unfiltered ("\n");
1229
1230 return 1;
1231}
1232
61c37cee 1233/* Handle DEBUG_STRING output from child process. */
0f07afe1
CF
1234static void
1235handle_output_debug_string (struct target_waitstatus *ourstatus)
1236{
1237 char p[256];
1238 char s[255];
1239 char *q;
1240 gdb_wince_len nbytes_read;
1241 gdb_wince_len nbytes = current_event.u.DebugString.nDebugStringLength;
1242
1243 if (nbytes > 255)
1244 nbytes = 255;
1245
1246 memset (p, 0, sizeof (p));
1247 if (!read_process_memory (current_process_handle,
1248 current_event.u.DebugString.lpDebugStringData,
1249 &p, nbytes, &nbytes_read)
1250 || !*p)
1251 return;
1252
1253 memset (s, 0, sizeof (s));
1254 WideCharToMultiByte (CP_ACP, 0, (LPCWSTR) p, (int) nbytes_read, s,
1255 sizeof (s) - 1, NULL, NULL);
1256 q = strchr (s, '\n');
1257 if (q != NULL)
1258 {
1259 *q = '\0';
1260 if (*--q = '\r')
1261 *q = '\0';
1262 }
1263
1264 warning (s);
61c37cee 1265
0f07afe1
CF
1266 return;
1267}
1268
1269/* Handle target exceptions. */
1270static int
1271handle_exception (struct target_waitstatus *ourstatus)
1272{
61c37cee 1273#if 0
0f07afe1
CF
1274 if (current_event.u.Exception.dwFirstChance)
1275 return 0;
61c37cee 1276#endif
0f07afe1
CF
1277
1278 ourstatus->kind = TARGET_WAITKIND_STOPPED;
1279
0f07afe1
CF
1280 switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
1281 {
1282 case EXCEPTION_ACCESS_VIOLATION:
1283 DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
1284 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1285 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1286 break;
1287 case STATUS_STACK_OVERFLOW:
1288 DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
1289 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1290 ourstatus->value.sig = TARGET_SIGNAL_SEGV;
1291 break;
1292 case EXCEPTION_BREAKPOINT:
1293 DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
1294 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1295 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1296 break;
1297 case DBG_CONTROL_C:
1298 DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
1299 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1300 ourstatus->value.sig = TARGET_SIGNAL_INT;
1301 /* User typed CTRL-C. Continue with this status */
1302 last_sig = SIGINT; /* FIXME - should check pass state */
1303 break;
1304 case EXCEPTION_SINGLE_STEP:
1305 DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
1306 (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1307 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
1308 break;
61c37cee
CF
1309 case EXCEPTION_ILLEGAL_INSTRUCTION:
1310 DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
1311 current_event.u.Exception.ExceptionRecord.ExceptionAddress));
1312 ourstatus->value.sig = check_for_step (&current_event, TARGET_SIGNAL_ILL);
1313 break;
0f07afe1
CF
1314 default:
1315 /* This may be a structured exception handling exception. In
61c37cee
CF
1316 that case, we want to let the program try to handle it, and
1317 only break if we see the exception a second time. */
0f07afe1
CF
1318
1319 printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
1320 current_event.u.Exception.ExceptionRecord.ExceptionCode,
1321 current_event.u.Exception.ExceptionRecord.ExceptionAddress);
1322 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
1323 break;
1324 }
1325 exception_count++;
1326 return 1;
1327}
1328
1329/* Resume all artificially suspended threads if we are continuing
1330 execution */
1331static BOOL
1332child_continue (DWORD continue_status, int id)
1333{
1334 int i;
1335 thread_info *th;
1336 BOOL res;
1337
1338 DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=%d, DBG_CONTINUE);\n",
1339 (unsigned) current_event.dwProcessId, (unsigned) current_event.dwThreadId));
1340 res = continue_debug_event (current_event.dwProcessId,
1341 current_event.dwThreadId,
1342 continue_status);
1343 if (res)
1344 for (th = &thread_head; (th = th->next) != NULL;)
1345 if (((id == -1) || (id == th->id)) && th->suspend_count)
1346 {
1347 for (i = 0; i < th->suspend_count; i++)
1348 (void) resume_thread (th->h);
1349 th->suspend_count = 0;
1350 }
1351
1352 return res;
1353}
1354
1355/* Get the next event from the child. Return 1 if the event requires
1356 handling by WFI (or whatever).
1357 */
1358static int
61c37cee
CF
1359get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
1360 DWORD target_event_code, int *retval)
0f07afe1 1361{
61c37cee 1362 int breakout = 0;
0f07afe1 1363 BOOL debug_event;
61c37cee
CF
1364 DWORD continue_status, event_code;
1365 thread_info *th = NULL;
1366 static thread_info dummy_thread_info;
0f07afe1
CF
1367
1368 if (!(debug_event = wait_for_debug_event (&current_event, 1000)))
1369 {
61c37cee 1370 *retval = 0;
0f07afe1
CF
1371 goto out;
1372 }
1373
0f07afe1
CF
1374 event_count++;
1375 continue_status = DBG_CONTINUE;
1376 *retval = 0;
61c37cee
CF
1377
1378 event_code = current_event.dwDebugEventCode;
1379 breakout = event_code == target_event_code;
1380
1381 switch (event_code)
0f07afe1
CF
1382 {
1383 case CREATE_THREAD_DEBUG_EVENT:
1384 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
1385 (unsigned) current_event.dwProcessId,
1386 (unsigned) current_event.dwThreadId,
1387 "CREATE_THREAD_DEBUG_EVENT"));
1388 /* Record the existence of this thread */
61c37cee
CF
1389 th = child_add_thread (current_event.dwThreadId,
1390 current_event.u.CreateThread.hThread);
0f07afe1
CF
1391 if (info_verbose)
1392 printf_unfiltered ("[New %s]\n",
1393 target_pid_to_str (current_event.dwThreadId));
1394 break;
1395
1396 case EXIT_THREAD_DEBUG_EVENT:
1397 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1398 (unsigned) current_event.dwProcessId,
1399 (unsigned) current_event.dwThreadId,
1400 "EXIT_THREAD_DEBUG_EVENT"));
1401 child_delete_thread (current_event.dwThreadId);
61c37cee 1402 th = &dummy_thread_info;
0f07afe1
CF
1403 break;
1404
1405 case CREATE_PROCESS_DEBUG_EVENT:
1406 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1407 (unsigned) current_event.dwProcessId,
1408 (unsigned) current_event.dwThreadId,
1409 "CREATE_PROCESS_DEBUG_EVENT"));
1410 current_process_handle = current_event.u.CreateProcessInfo.hProcess;
1411
1412 main_thread_id = inferior_pid = current_event.dwThreadId;
1413 /* Add the main thread */
61c37cee
CF
1414 th = child_add_thread (inferior_pid,
1415 current_event.u.CreateProcessInfo.hThread);
0f07afe1
CF
1416 break;
1417
1418 case EXIT_PROCESS_DEBUG_EVENT:
1419 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1420 (unsigned) current_event.dwProcessId,
1421 (unsigned) current_event.dwThreadId,
1422 "EXIT_PROCESS_DEBUG_EVENT"));
1423 ourstatus->kind = TARGET_WAITKIND_EXITED;
1424 ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
1425 close_handle (current_process_handle);
1426 *retval = current_event.dwProcessId;
61c37cee
CF
1427 breakout = 1;
1428 break;
0f07afe1
CF
1429
1430 case LOAD_DLL_DEBUG_EVENT:
1431 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1432 (unsigned) current_event.dwProcessId,
1433 (unsigned) current_event.dwThreadId,
1434 "LOAD_DLL_DEBUG_EVENT"));
1435 catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
1436 registers_changed (); /* mark all regs invalid */
1437 break;
1438
1439 case UNLOAD_DLL_DEBUG_EVENT:
1440 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1441 (unsigned) current_event.dwProcessId,
1442 (unsigned) current_event.dwThreadId,
1443 "UNLOAD_DLL_DEBUG_EVENT"));
1444 break; /* FIXME: don't know what to do here */
1445
1446 case EXCEPTION_DEBUG_EVENT:
1447 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1448 (unsigned) current_event.dwProcessId,
1449 (unsigned) current_event.dwThreadId,
1450 "EXCEPTION_DEBUG_EVENT"));
1451 if (handle_exception (ourstatus))
61c37cee
CF
1452 *retval = current_event.dwThreadId;
1453 else
0f07afe1 1454 {
61c37cee
CF
1455 continue_status = DBG_EXCEPTION_NOT_HANDLED;
1456 breakout = 0;
0f07afe1 1457 }
0f07afe1
CF
1458 break;
1459
1460 case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
1461 DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
1462 (unsigned) current_event.dwProcessId,
1463 (unsigned) current_event.dwThreadId,
1464 "OUTPUT_DEBUG_STRING_EVENT"));
61c37cee 1465 handle_output_debug_string ( ourstatus);
0f07afe1
CF
1466 break;
1467 default:
1468 printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
1469 current_event.dwProcessId,
1470 current_event.dwThreadId);
1471 printf_unfiltered (" unknown event code %d\n",
1472 current_event.dwDebugEventCode);
1473 break;
1474 }
1475
61c37cee
CF
1476 if (breakout)
1477 this_thread = current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
1478 else
1479 CHECK (child_continue (continue_status, -1));
0f07afe1
CF
1480
1481out:
1482 return breakout;
1483}
1484
1485/* Wait for interesting events to occur in the target process. */
1486static int
1487child_wait (int pid, struct target_waitstatus *ourstatus)
1488{
1489 DWORD event_code;
1490 int retval;
1491
1492 /* We loop when we get a non-standard exception rather than return
1493 with a SPURIOUS because resume can try and step or modify things,
1494 which needs a current_thread->h. But some of these exceptions mark
1495 the birth or death of threads, which mean that the current thread
1496 isn't necessarily what you think it is. */
1497
1498 while (1)
61c37cee 1499 if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval))
0f07afe1
CF
1500 return retval;
1501 else
1502 {
1503 int detach = 0;
1504
1505 if (ui_loop_hook != NULL)
1506 detach = ui_loop_hook (0);
1507
1508 if (detach)
1509 child_kill_inferior ();
1510 }
1511}
1512
1513/* Print status information about what we're accessing. */
1514
1515static void
fba45db2 1516child_files_info (struct target_ops *ignore)
0f07afe1
CF
1517{
1518 printf_unfiltered ("\tUsing the running image of child %s.\n",
1519 target_pid_to_str (inferior_pid));
1520}
1521
1522/* ARGSUSED */
1523static void
fba45db2 1524child_open (char *arg, int from_tty)
0f07afe1
CF
1525{
1526 error ("Use the \"run\" command to start a child process.");
1527}
1528
1529#define FACTOR (0x19db1ded53ea710LL)
1530#define NSPERSEC 10000000
1531
1532/* Convert a Win32 time to "UNIX" format. */
1533long
1534to_time_t (FILETIME * ptr)
1535{
1536 /* A file time is the number of 100ns since jan 1 1601
1537 stuffed into two long words.
1538 A time_t is the number of seconds since jan 1 1970. */
1539
1540 long rem;
1541 long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned) ptr->dwLowDateTime);
1542 x -= FACTOR; /* number of 100ns between 1601 and 1970 */
1543 rem = x % ((long long) NSPERSEC);
1544 rem += (NSPERSEC / 2);
1545 x /= (long long) NSPERSEC; /* number of 100ns in a second */
1546 x += (long long) (rem / NSPERSEC);
1547 return x;
1548}
1549
1550/* Upload a file to the remote device depending on the user's
1551 'set remoteupload' specification. */
1552char *
1553upload_to_device (const char *to, const char *from)
1554{
1555 HANDLE h;
61c37cee 1556 const char *dir = remote_directory ?: "\\gdb";
0f07afe1
CF
1557 int len;
1558 static char *remotefile = NULL;
1559 LPWSTR wstr;
1560 char *p;
1561 DWORD err;
1562 const char *in_to = to;
61c37cee
CF
1563 FILETIME crtime, actime, wrtime;
1564 time_t utime;
0f07afe1
CF
1565 struct stat st;
1566 int fd;
1567
1568 /* Look for a path separator and only use trailing part. */
1569 while ((p = strpbrk (to, "/\\")) != NULL)
1570 to = p + 1;
1571
1572 if (!*to)
1573 error ("no filename found to upload - %s.", in_to);
1574
1575 len = strlen (dir) + strlen (to) + 2;
1576 remotefile = (char *) realloc (remotefile, len);
1577 strcpy (remotefile, dir);
1578 strcat (remotefile, "\\");
1579 strcat (remotefile, to);
1580
1581 if (upload_when == UPLOAD_NEVER)
1582 return remotefile; /* Don't bother uploading. */
1583
1584 /* Open the source. */
1585 if ((fd = openp (getenv ("PATH"), TRUE, (char *) from, O_RDONLY, 0, NULL)) < 0)
1586 error ("couldn't open %s", from);
1587
1588 /* Get the time for later comparison. */
1589 if (fstat (fd, &st))
1590 st.st_mtime = (time_t) - 1;
1591
1592 /* Always attempt to create the directory on the remote system. */
1593 wstr = towide (dir, NULL);
1594 (void) CeCreateDirectory (wstr, NULL);
1595
1596 /* Attempt to open the remote file, creating it if it doesn't exist. */
1597 wstr = towide (remotefile, NULL);
1598 h = CeCreateFile (wstr, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1599 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1600
1601 /* Some kind of problem? */
1602 err = CeGetLastError ();
61c37cee
CF
1603 if (h == NULL || h == INVALID_HANDLE_VALUE)
1604 error ("error opening file \"%s\". Windows error %d.",
0f07afe1
CF
1605 remotefile, err);
1606
61c37cee
CF
1607 CeGetFileTime (h, &crtime, &actime, &wrtime);
1608 utime = to_time_t (&wrtime);
1609#if 0
1610 if (utime < st.st_mtime)
1611 {
1612 char buf[80];
1613 strcpy (buf, ctime(&utime));
1614 printf ("%s < %s\n", buf, ctime(&st.st_mtime));
1615 }
1616#endif
0f07afe1
CF
1617 /* See if we need to upload the file. */
1618 if (upload_when == UPLOAD_ALWAYS ||
1619 err != ERROR_ALREADY_EXISTS ||
61c37cee
CF
1620 !CeGetFileTime (h, &crtime, &actime, &wrtime) ||
1621 to_time_t (&wrtime) < st.st_mtime)
0f07afe1
CF
1622 {
1623 DWORD nbytes;
1624 char buf[4096];
1625 int n;
1626
1627 /* Upload the file. */
1628 while ((n = read (fd, buf, sizeof (buf))) > 0)
1629 if (!CeWriteFile (h, buf, (DWORD) n, &nbytes, NULL))
1630 error ("error writing to remote device - %d.",
1631 CeGetLastError ());
1632 }
1633
1634 close (fd);
61c37cee
CF
1635 if (!CeCloseHandle (h))
1636 error ("error closing remote file - %d.", CeGetLastError ());
0f07afe1
CF
1637
1638 return remotefile;
1639}
1640
1641/* Initialize the connection to the remote device. */
1642static void
fba45db2 1643wince_initialize (void)
0f07afe1
CF
1644{
1645 int tmp;
1646 char args[256];
1647 char *hostname;
1648 struct sockaddr_in sin;
1649 char *stub_file_name;
1650 int s0;
1651 PROCESS_INFORMATION pi;
1652
1653 if (!connection_initialized)
1654 switch (CeRapiInit ())
1655 {
1656 case 0:
1657 connection_initialized = 1;
1658 break;
1659 default:
1660 CeRapiUninit ();
1661 error ("Can't initialize connection to remote device.\n");
1662 break;
1663 }
1664
1665 /* Upload the stub to the handheld device. */
1666 stub_file_name = upload_to_device ("wince-stub.exe", WINCE_STUB);
1667 strcpy (args, stub_file_name);
1668
1669 if (remote_add_host)
1670 {
1671 strcat (args, " ");
1672 hostname = strchr (args, '\0');
1673 if (gethostname (hostname, sizeof (args) - strlen (args)))
1674 error ("couldn't get hostname of this system.");
1675 }
1676
1677 /* Get a socket. */
1678 if ((s0 = socket (AF_INET, SOCK_STREAM, 0)) < 0)
1679 stub_error ("Couldn't connect to host system.");
1680
1681 /* Allow rapid reuse of the port. */
1682 tmp = 1;
1683 (void) setsockopt (s0, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp));
1684
1685
1686 /* Set up the information for connecting to the host gdb process. */
1687 memset (&sin, 0, sizeof (sin));
1688 sin.sin_family = AF_INET;
1689 sin.sin_port = htons (7000); /* FIXME: This should be configurable */
1690
1691 if (bind (s0, (struct sockaddr *) &sin, sizeof (sin)))
1692 error ("couldn't bind socket");
1693
1694 if (listen (s0, 1))
1695 error ("Couldn't open socket for listening.\n");
1696
1697 /* Start up the stub on the remote device. */
1698 if (!CeCreateProcess (towide (stub_file_name, NULL), towide (args, NULL),
1699 NULL, NULL, 0, 0, NULL, NULL, NULL, &pi))
1700 error ("Unable to start remote stub '%s'. Windows CE error %d.",
1701 stub_file_name, CeGetLastError ());
1702
1703 /* Wait for a connection */
1704
1705 if ((s = accept (s0, NULL, NULL)) < 0)
1706 error ("couldn't set up server for connection.");
1707
1708 close (s0);
1709}
1710
1711/* Start an inferior win32 child process and sets inferior_pid to its pid.
1712 EXEC_FILE is the file to run.
1713 ALLARGS is a string containing the arguments to the program.
1714 ENV is the environment vector to pass. Errors reported with error(). */
1715static void
1716child_create_inferior (char *exec_file, char *args, char **env)
1717{
1718 PROCESS_INFORMATION pi;
1719 struct target_waitstatus dummy;
1720 int ret;
1721 DWORD flags, event_code;
1722 char *exec_and_args;
1723
1724 if (!exec_file)
1725 error ("No executable specified, use `target exec'.\n");
1726
1727 flags = DEBUG_PROCESS;
1728
1729 wince_initialize (); /* Make sure we've got a connection. */
0f07afe1
CF
1730
1731 exec_file = upload_to_device (exec_file, exec_file);
1732
1733 while (*args == ' ')
1734 args++;
1735
1736 /* Allocate space for "command<sp>args" */
1737 if (*args == '\0')
1738 {
1739 exec_and_args = alloca (strlen (exec_file) + 1);
1740 strcpy (exec_and_args, exec_file);
1741 }
1742 else
1743 {
1744 exec_and_args = alloca (strlen (exec_file + strlen (args) + 2));
1745 sprintf (exec_and_args, "%s %s", exec_file, args);
1746 }
1747
1748 memset (&pi, 0, sizeof (pi));
1749 /* Execute the process */
1750 if (!create_process (exec_file, exec_and_args, flags, &pi))
1751 error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
1752
1753 exception_count = 0;
1754 event_count = 0;
1755
1756 current_process_handle = pi.hProcess;
1757 current_event.dwProcessId = pi.dwProcessId;
1758 memset (&current_event, 0, sizeof (current_event));
1759 inferior_pid = current_event.dwThreadId = pi.dwThreadId;
1760 push_target (&child_ops);
1761 child_init_thread_list ();
1762 child_add_thread (pi.dwThreadId, pi.hThread);
1763 init_wait_for_inferior ();
1764 clear_proceed_status ();
1765 target_terminal_init ();
1766 target_terminal_inferior ();
1767
0f07afe1 1768 /* Run until process and threads are loaded */
61c37cee
CF
1769 while (!get_child_debug_event (inferior_pid, &dummy,
1770 CREATE_PROCESS_DEBUG_EVENT, &ret))
1771 continue;
0f07afe1
CF
1772
1773 proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
1774}
1775
1776/* Chile has gone bye-bye. */
1777static void
fba45db2 1778child_mourn_inferior (void)
0f07afe1
CF
1779{
1780 (void) child_continue (DBG_CONTINUE, -1);
1781 unpush_target (&child_ops);
1782 stop_stub ();
1783 CeRapiUninit ();
1784 connection_initialized = 0;
1785 generic_mourn_inferior ();
1786}
1787
1788/* Move memory from child to/from gdb. */
1789int
1790child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
1791 int write, struct target_ops *target)
1792{
1793 if (len <= 0)
1794 return 0;
4930751a
C
1795
1796 if (write)
1797 res = remote_write_bytes (memaddr, our, len);
1798 else
1799 res = remote_read_bytes (memaddr, our, len);
1800
1801 return res;
0f07afe1
CF
1802}
1803
1804/* Terminate the process and wait for child to tell us it has completed. */
1805void
1806child_kill_inferior (void)
1807{
1808 CHECK (terminate_process (current_process_handle));
1809
1810 for (;;)
1811 {
1812 if (!child_continue (DBG_CONTINUE, -1))
1813 break;
1814 if (!wait_for_debug_event (&current_event, INFINITE))
1815 break;
1816 if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
1817 break;
1818 }
1819
1820 CHECK (close_handle (current_process_handle));
1821 close_handle (current_thread->h);
1822 target_mourn_inferior (); /* or just child_mourn_inferior? */
1823}
1824
0f07afe1
CF
1825/* Resume the child after an exception. */
1826void
1827child_resume (int pid, int step, enum target_signal sig)
1828{
1829 thread_info *th;
1830 DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
1831 DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
1832
1833 DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
1834 pid, step, sig));
1835
1836 /* Get context for currently selected thread */
1837 th = thread_rec (current_event.dwThreadId, FALSE);
1838
1839 if (th->context.ContextFlags)
1840 {
1841 CHECK (set_thread_context (th->h, &th->context));
1842 th->context.ContextFlags = 0;
1843 }
1844
0f07afe1
CF
1845 /* Allow continuing with the same signal that interrupted us.
1846 Otherwise complain. */
1847 if (sig && sig != last_sig)
1848 fprintf_unfiltered (gdb_stderr, "Can't send signals to the child. signal %d\n", sig);
1849
1850 last_sig = 0;
1851 child_continue (continue_status, pid);
1852}
1853
1854static void
fba45db2 1855child_prepare_to_store (void)
0f07afe1
CF
1856{
1857 /* Do nothing, since we can store individual regs */
1858}
1859
1860static int
fba45db2 1861child_can_run (void)
0f07afe1
CF
1862{
1863 return 1;
1864}
1865
1866static void
fba45db2 1867child_close (void)
0f07afe1
CF
1868{
1869 DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
1870}
1871
1872/* Explicitly upload file to remotedir */
1873
1874static void
1875child_load (char *file, int from_tty)
1876{
1877 upload_to_device (file, file);
1878}
1879
1880struct target_ops child_ops;
1881
1882static void
1883init_child_ops (void)
1884{
1885 memset (&child_ops, 0, sizeof (child_ops));
1886 child_ops.to_shortname = (char *) "child";
1887 child_ops.to_longname = (char *) "Windows CE process";
1888 child_ops.to_doc = (char *) "Windows CE process (started by the \"run\" command).";
1889 child_ops.to_open = child_open;
1890 child_ops.to_close = child_close;
1891 child_ops.to_resume = child_resume;
1892 child_ops.to_wait = child_wait;
1893 child_ops.to_fetch_registers = child_fetch_inferior_registers;
1894 child_ops.to_store_registers = child_store_inferior_registers;
1895 child_ops.to_prepare_to_store = child_prepare_to_store;
1896 child_ops.to_xfer_memory = child_xfer_memory;
1897 child_ops.to_files_info = child_files_info;
1898 child_ops.to_insert_breakpoint = memory_insert_breakpoint;
1899 child_ops.to_remove_breakpoint = memory_remove_breakpoint;
1900 child_ops.to_terminal_init = terminal_init_inferior;
1901 child_ops.to_terminal_inferior = terminal_inferior;
1902 child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1903 child_ops.to_terminal_ours = terminal_ours;
1904 child_ops.to_terminal_info = child_terminal_info;
1905 child_ops.to_kill = child_kill_inferior;
1906 child_ops.to_load = child_load;
1907 child_ops.to_create_inferior = child_create_inferior;
1908 child_ops.to_mourn_inferior = child_mourn_inferior;
1909 child_ops.to_can_run = child_can_run;
1910 child_ops.to_thread_alive = win32_child_thread_alive;
1911 child_ops.to_stratum = process_stratum;
1912 child_ops.to_has_all_memory = 1;
1913 child_ops.to_has_memory = 1;
1914 child_ops.to_has_stack = 1;
1915 child_ops.to_has_registers = 1;
1916 child_ops.to_has_execution = 1;
1917 child_ops.to_sections = 0;
1918 child_ops.to_sections_end = 0;
1919 child_ops.to_magic = OPS_MAGIC;
1920}
1921
1922
1923/* Handle 'set remoteupload' parameter. */
1924
1925#define replace_upload(what) \
61c37cee
CF
1926 upload_when = what; \
1927 remote_upload = realloc (remote_upload, strlen (upload_options[upload_when].name) + 1); \
0f07afe1
CF
1928 strcpy (remote_upload, upload_options[upload_when].name);
1929
1930static void
1931set_upload_type (char *ignore, int from_tty)
1932{
1933 int i, len;
1934 char *bad_option;
1935
1936 if (!remote_upload || !remote_upload[0])
1937 {
1938 replace_upload (UPLOAD_NEWER);
1939 if (from_tty)
1940 printf_unfiltered ("Upload upload_options are: always, newer, never.\n");
1941 return;
1942 }
1943
1944 len = strlen (remote_upload);
1945 for (i = 0; i < (sizeof (upload_options) / sizeof (upload_options[0])); i++)
1946 if (len >= upload_options[i].abbrev &&
1947 strncasecmp (remote_upload, upload_options[i].name, len) == 0)
1948 {
61c37cee 1949 replace_upload (i);
0f07afe1
CF
1950 return;
1951 }
1952
1953 bad_option = remote_upload;
1954 replace_upload (UPLOAD_NEWER);
1955 error ("Unknown upload type: %s.", bad_option);
1956}
1957
1958void
fba45db2 1959_initialize_inftarg (void)
0f07afe1
CF
1960{
1961 struct cmd_list_element *set;
1962 init_child_ops ();
1963
1964 add_show_from_set
1965 (add_set_cmd ((char *) "remotedirectory", no_class,
1966 var_string_noescape, (char *) &remote_directory,
1967 (char *) "Set directory for remote upload.\n",
1968 &setlist),
1969 &showlist);
1970 remote_directory = xstrdup (remote_directory);
1971
1972 set = add_set_cmd ((char *) "remoteupload", no_class,
1973 var_string_noescape, (char *) &remote_upload,
1974 (char *) "Set how to upload executables to remote device.\n",
1975 &setlist);
1976 add_show_from_set (set, &showlist);
1977 set->function.cfunc = set_upload_type;
1978 set_upload_type (NULL, 0);
0f07afe1
CF
1979
1980 add_show_from_set
1981 (add_set_cmd ((char *) "debugexec", class_support, var_boolean,
1982 (char *) &debug_exec,
1983 (char *) "Set whether to display execution in child process.",
1984 &setlist),
1985 &showlist);
1986
1987 add_show_from_set
1988 (add_set_cmd ((char *) "remoteaddhost", class_support, var_boolean,
1989 (char *) &remote_add_host,
1990 (char *) "Set whether to add this host to remote stub arguments for\n
1991debugging over a network.", &setlist),
1992 &showlist);
1993
1994 add_show_from_set
1995 (add_set_cmd ((char *) "debugevents", class_support, var_boolean,
1996 (char *) &debug_events,
1997 (char *) "Set whether to display kernel events in child process.",
1998 &setlist),
1999 &showlist);
2000
2001 add_show_from_set
2002 (add_set_cmd ((char *) "debugmemory", class_support, var_boolean,
2003 (char *) &debug_memory,
2004 (char *) "Set whether to display memory accesses in child process.",
2005 &setlist),
2006 &showlist);
2007
2008 add_show_from_set
2009 (add_set_cmd ((char *) "debugexceptions", class_support, var_boolean,
2010 (char *) &debug_exceptions,
2011 (char *) "Set whether to display kernel exceptions in child process.",
2012 &setlist),
2013 &showlist);
2014
2015 add_target (&child_ops);
2016}
2017
2018/* Determine if the thread referenced by "pid" is alive
2019 by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
2020 it means that the pid has died. Otherwise it is assumed to be alive. */
2021static int
2022win32_child_thread_alive (int pid)
2023{
2024 return thread_alive (thread_rec (pid, FALSE)->h);
2025}
2026
2027/* Convert pid to printable format. */
2028char *
2029cygwin_pid_to_str (int pid)
2030{
2031 static char buf[80];
2032 if (pid == current_event.dwProcessId)
2033 sprintf (buf, "process %d", pid);
2034 else
2035 sprintf (buf, "thread %d.0x%x", (unsigned) current_event.dwProcessId, pid);
2036 return buf;
2037}
This page took 0.152773 seconds and 4 git commands to generate.