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