OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [wince.c] - Blame information for rev 105

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.