1/* GDB stub for Itanium OpenVMS 2 Copyright (C) 2012-2020 Free Software Foundation, Inc. 3 4 Contributed by Tristan Gingold, AdaCore. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19/* On VMS, the debugger (in our case the stub) is loaded in the process and 20 executed (via SYS$IMGSTA) before the main entry point of the executable. 21 In UNIX parlance, this is like using LD_PRELOAD and debug via installing 22 SIGTRAP, SIGSEGV... handlers. 23 24 This is currently a partial implementation. In particular, modifying 25 registers is currently not implemented, as well as inferior procedure 26 calls. 27 28 This is written in very low-level C, in order not to use the C runtime, 29 because it may have weird consequences on the program being debugged. 30*/ 31 32#if __INITIAL_POINTER_SIZE != 64 33#error "Must be compiled with 64 bit pointers" 34#endif 35 36#define __NEW_STARLET 1 37#include <descrip.h> 38#include <iledef.h> 39#include <efndef.h> 40#include <in.h> 41#include <inet.h> 42#include <iodef.h> 43#include <ssdef.h> 44#include <starlet.h> 45#include <stsdef.h> 46#include <tcpip$inetdef.h> 47 48#include <lib$routines.h> 49#include <ots$routines.h> 50#include <str$routines.h> 51#include <libdef.h> 52#include <clidef.h> 53#include <iosbdef.h> 54#include <dvidef.h> 55#include <lnmdef.h> 56#include <builtins.h> 57#include <prtdef.h> 58#include <psldef.h> 59#include <chfdef.h> 60 61#include <lib_c/imcbdef.h> 62#include <lib_c/ldrimgdef.h> 63#include <lib_c/intstkdef.h> 64#include <lib_c/psrdef.h> 65#include <lib_c/ifddef.h> 66#include <lib_c/eihddef.h> 67 68#include <stdarg.h> 69#include <pthread_debug.h> 70 71#define VMS_PAGE_SIZE 0x2000 72#define VMS_PAGE_MASK (VMS_PAGE_SIZE - 1) 73 74/* Declared in lib$ots. */ 75extern void ots$fill (void *addr, size_t len, unsigned char b); 76extern void ots$move (void *dst, size_t len, const void *src); 77extern int ots$strcmp_eql (const void *str1, size_t str1len, 78 const void *str2, size_t str2len); 79 80/* Stub port number. */ 81static unsigned int serv_port = 1234; 82 83/* DBGEXT structure. Not declared in any header. */ 84struct dbgext_control_block 85{ 86 unsigned short dbgext$w_function_code; 87#define DBGEXT$K_NEXT_TASK 3 88#define DBGEXT$K_STOP_ALL_OTHER_TASKS 31 89#define DBGEXT$K_GET_REGS 33 90 unsigned short dbgext$w_facility_id; 91#define CMA$_FACILITY 64 92 unsigned int dbgext$l_status; 93 unsigned int dbgext$l_flags; 94 unsigned int dbgext$l_print_routine; 95 unsigned int dbgext$l_evnt_code; 96 unsigned int dbgext$l_evnt_name; 97 unsigned int dbgext$l_evnt_entry; 98 unsigned int dbgext$l_task_value; 99 unsigned int dbgext$l_task_number; 100 unsigned int dbgext$l_ada_flags; 101 unsigned int dbgext$l_stop_value; 102#define dbgext$l_priority dbgext$l_stop_value; 103#define dbgext$l_symb_addr dbgext$l_stop_value; 104#define dbgext$l_time_slice dbgext$l_stop_value; 105 unsigned int dbgext$l_active_registers; 106}; 107 108#pragma pointer_size save 109#pragma pointer_size 32 110 111/* Pthread handler. */ 112static int (*dbgext_func) (struct dbgext_control_block *blk); 113 114#pragma pointer_size restore 115 116/* Set to 1 if thread-aware. */ 117static int has_threads; 118 119/* Current thread. */ 120static pthread_t selected_thread; 121static pthreadDebugId_t selected_id; 122 123/* Internal debugging flags. */ 124struct debug_flag 125{ 126 /* Name of the flag (as a string descriptor). */ 127 const struct dsc$descriptor_s name; 128 /* Value. */ 129 int val; 130}; 131 132/* Macro to define a debugging flag. */ 133#define DEBUG_FLAG_ENTRY(str) \ 134 { { sizeof (str) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, str }, 0} 135 136static struct debug_flag debug_flags[] = 137{ 138 /* Disp packets exchanged with gdb. */ 139 DEBUG_FLAG_ENTRY("packets"), 140#define trace_pkt (debug_flags[0].val) 141 /* Display entry point informations. */ 142 DEBUG_FLAG_ENTRY("entry"), 143#define trace_entry (debug_flags[1].val) 144 /* Be verbose about exceptions. */ 145 DEBUG_FLAG_ENTRY("excp"), 146#define trace_excp (debug_flags[2].val) 147 /* Be verbose about unwinding. */ 148 DEBUG_FLAG_ENTRY("unwind"), 149#define trace_unwind (debug_flags[3].val) 150 /* Display image at startup. */ 151 DEBUG_FLAG_ENTRY("images"), 152#define trace_images (debug_flags[4].val) 153 /* Display pthread_debug info. */ 154 DEBUG_FLAG_ENTRY("pthreaddbg") 155#define trace_pthreaddbg (debug_flags[5].val) 156}; 157 158#define NBR_DEBUG_FLAGS (sizeof (debug_flags) / sizeof (debug_flags[0])) 159 160/* Connect inet device I/O channel. */ 161static unsigned short conn_channel; 162 163/* Widely used hex digit to ascii. */ 164static const char hex[] = "0123456789abcdef"; 165 166/* Socket characteristics. Apparently, there are no declaration for it in 167 standard headers. */ 168struct sockchar 169{ 170 unsigned short prot; 171 unsigned char type; 172 unsigned char af; 173}; 174 175/* Chain of images loaded. */ 176extern IMCB* ctl$gl_imglstptr; 177 178/* IA64 integer register representation. */ 179union ia64_ireg 180{ 181 unsigned __int64 v; 182 unsigned char b[8]; 183}; 184 185/* IA64 register numbers, as defined by ia64-tdep.h. */ 186#define IA64_GR0_REGNUM 0 187#define IA64_GR32_REGNUM (IA64_GR0_REGNUM + 32) 188 189/* Floating point registers; 128 82-bit wide registers. */ 190#define IA64_FR0_REGNUM 128 191 192/* Predicate registers; There are 64 of these one bit registers. It'd 193 be more convenient (implementation-wise) to use a single 64 bit 194 word with all of these register in them. Note that there's also a 195 IA64_PR_REGNUM below which contains all the bits and is used for 196 communicating the actual values to the target. */ 197#define IA64_PR0_REGNUM 256 198 199/* Branch registers: 8 64-bit registers for holding branch targets. */ 200#define IA64_BR0_REGNUM 320 201 202/* Virtual frame pointer; this matches IA64_FRAME_POINTER_REGNUM in 203 gcc/config/ia64/ia64.h. */ 204#define IA64_VFP_REGNUM 328 205 206/* Virtual return address pointer; this matches 207 IA64_RETURN_ADDRESS_POINTER_REGNUM in gcc/config/ia64/ia64.h. */ 208#define IA64_VRAP_REGNUM 329 209 210/* Predicate registers: There are 64 of these 1-bit registers. We 211 define a single register which is used to communicate these values 212 to/from the target. We will somehow contrive to make it appear 213 that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */ 214#define IA64_PR_REGNUM 330 215 216/* Instruction pointer: 64 bits wide. */ 217#define IA64_IP_REGNUM 331 218 219/* Process Status Register. */ 220#define IA64_PSR_REGNUM 332 221 222/* Current Frame Marker (raw form may be the cr.ifs). */ 223#define IA64_CFM_REGNUM 333 224 225/* Application registers; 128 64-bit wide registers possible, but some 226 of them are reserved. */ 227#define IA64_AR0_REGNUM 334 228#define IA64_KR0_REGNUM (IA64_AR0_REGNUM + 0) 229#define IA64_KR7_REGNUM (IA64_KR0_REGNUM + 7) 230 231#define IA64_RSC_REGNUM (IA64_AR0_REGNUM + 16) 232#define IA64_BSP_REGNUM (IA64_AR0_REGNUM + 17) 233#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM + 18) 234#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM + 19) 235#define IA64_FCR_REGNUM (IA64_AR0_REGNUM + 21) 236#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM + 24) 237#define IA64_CSD_REGNUM (IA64_AR0_REGNUM + 25) 238#define IA64_SSD_REGNUM (IA64_AR0_REGNUM + 26) 239#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM + 27) 240#define IA64_FSR_REGNUM (IA64_AR0_REGNUM + 28) 241#define IA64_FIR_REGNUM (IA64_AR0_REGNUM + 29) 242#define IA64_FDR_REGNUM (IA64_AR0_REGNUM + 30) 243#define IA64_CCV_REGNUM (IA64_AR0_REGNUM + 32) 244#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM + 36) 245#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM + 40) 246#define IA64_ITC_REGNUM (IA64_AR0_REGNUM + 44) 247#define IA64_PFS_REGNUM (IA64_AR0_REGNUM + 64) 248#define IA64_LC_REGNUM (IA64_AR0_REGNUM + 65) 249#define IA64_EC_REGNUM (IA64_AR0_REGNUM + 66) 250 251/* NAT (Not A Thing) Bits for the general registers; there are 128 of 252 these. */ 253#define IA64_NAT0_REGNUM 462 254 255/* Process registers when a condition is caught. */ 256struct ia64_all_regs 257{ 258 union ia64_ireg gr[32]; 259 union ia64_ireg br[8]; 260 union ia64_ireg ip; 261 union ia64_ireg psr; 262 union ia64_ireg bsp; 263 union ia64_ireg cfm; 264 union ia64_ireg pfs; 265 union ia64_ireg pr; 266}; 267 268static struct ia64_all_regs excp_regs; 269static struct ia64_all_regs sel_regs; 270static pthread_t sel_regs_pthread; 271 272/* IO channel for the terminal. */ 273static unsigned short term_chan; 274 275/* Output buffer and length. */ 276static char term_buf[128]; 277static int term_buf_len; 278 279/* Buffer for communication with gdb. */ 280static unsigned char gdb_buf[sizeof (struct ia64_all_regs) * 2 + 64]; 281static unsigned int gdb_blen; 282 283/* Previous primary handler. */ 284static void *prevhnd; 285 286/* Entry point address and bundle. */ 287static unsigned __int64 entry_pc; 288static unsigned char entry_saved[16]; 289 290/* Write on the terminal. */ 291 292static void 293term_raw_write (const char *str, unsigned int len) 294{ 295 unsigned short status; 296 struct _iosb iosb; 297 298 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 299 term_chan, /* I/O channel. */ 300 IO$_WRITEVBLK, /* I/O function code. */ 301 &iosb, /* I/O status block. */ 302 0, /* Ast service routine. */ 303 0, /* Ast parameter. */ 304 (char *)str, /* P1 - buffer address. */ 305 len, /* P2 - buffer length. */ 306 0, 0, 0, 0); 307 308 if (status & STS$M_SUCCESS) 309 status = iosb.iosb$w_status; 310 if (!(status & STS$M_SUCCESS)) 311 LIB$SIGNAL (status); 312} 313 314/* Flush ther term buffer. */ 315 316static void 317term_flush (void) 318{ 319 if (term_buf_len != 0) 320 { 321 term_raw_write (term_buf, term_buf_len); 322 term_buf_len = 0; 323 } 324} 325 326/* Write a single character, without translation. */ 327 328static void 329term_raw_putchar (char c) 330{ 331 if (term_buf_len == sizeof (term_buf)) 332 term_flush (); 333 term_buf[term_buf_len++] = c; 334} 335 336/* Write character C. Translate '\n' to '\n\r'. */ 337 338static void 339term_putc (char c) 340{ 341 if (c < 32) 342 switch (c) 343 { 344 case '\r': 345 case '\n': 346 break; 347 default: 348 c = '.'; 349 break; 350 } 351 term_raw_putchar (c); 352 if (c == '\n') 353 { 354 term_raw_putchar ('\r'); 355 term_flush (); 356 } 357} 358 359/* Write a C string. */ 360 361static void 362term_puts (const char *str) 363{ 364 while (*str) 365 term_putc (*str++); 366} 367 368/* Write LEN bytes from STR. */ 369 370static void 371term_write (const char *str, unsigned int len) 372{ 373 for (; len > 0; len--) 374 term_putc (*str++); 375} 376 377/* Write using FAO formatting. */ 378 379static void 380term_fao (const char *str, unsigned int str_len, ...) 381{ 382 int cnt; 383 va_list vargs; 384 int i; 385 __int64 *args; 386 int status; 387 struct dsc$descriptor_s dstr = 388 { str_len, DSC$K_DTYPE_T, DSC$K_CLASS_S, (__char_ptr32)str }; 389 char buf[128]; 390 $DESCRIPTOR (buf_desc, buf); 391 392 va_start (vargs, str_len); 393 va_count (cnt); 394 args = (__int64 *) __ALLOCA (cnt * sizeof (__int64)); 395 cnt -= 2; 396 for (i = 0; i < cnt; i++) 397 args[i] = va_arg (vargs, __int64); 398 399 status = sys$faol_64 (&dstr, &buf_desc.dsc$w_length, &buf_desc, args); 400 if (status & 1) 401 { 402 /* FAO !/ already insert a line feed. */ 403 for (i = 0; i < buf_desc.dsc$w_length; i++) 404 { 405 term_raw_putchar (buf[i]); 406 if (buf[i] == '\n') 407 term_flush (); 408 } 409 } 410 411 va_end (vargs); 412} 413 414#define TERM_FAO(STR, ...) term_fao (STR, sizeof (STR) - 1, __VA_ARGS__) 415 416/* New line. */ 417 418static void 419term_putnl (void) 420{ 421 term_putc ('\n'); 422} 423 424/* Initialize terminal. */ 425 426static void 427term_init (void) 428{ 429 unsigned int status,i; 430 unsigned short len; 431 char resstring[LNM$C_NAMLENGTH]; 432 static const $DESCRIPTOR (tabdesc, "LNM$FILE_DEV"); 433 static const $DESCRIPTOR (logdesc, "SYS$OUTPUT"); 434 $DESCRIPTOR (term_desc, resstring); 435 ILE3 item_lst[2]; 436 437 item_lst[0].ile3$w_length = LNM$C_NAMLENGTH; 438 item_lst[0].ile3$w_code = LNM$_STRING; 439 item_lst[0].ile3$ps_bufaddr = resstring; 440 item_lst[0].ile3$ps_retlen_addr = &len; 441 item_lst[1].ile3$w_length = 0; 442 item_lst[1].ile3$w_code = 0; 443 444 /* Translate the logical name. */ 445 status = SYS$TRNLNM (0, /* Attr of the logical name. */ 446 (void *) &tabdesc, /* Logical name table. */ 447 (void *) &logdesc, /* Logical name. */ 448 0, /* Access mode. */ 449 item_lst); /* Item list. */ 450 if (!(status & STS$M_SUCCESS)) 451 LIB$SIGNAL (status); 452 453 term_desc.dsc$w_length = len; 454 455 /* Examine 4-byte header. Skip escape sequence. */ 456 if (resstring[0] == 0x1B) 457 { 458 term_desc.dsc$w_length -= 4; 459 term_desc.dsc$a_pointer += 4; 460 } 461 462 /* Assign a channel. */ 463 status = sys$assign (&term_desc, /* Device name. */ 464 &term_chan, /* I/O channel. */ 465 0, /* Access mode. */ 466 0); 467 if (!(status & STS$M_SUCCESS)) 468 LIB$SIGNAL (status); 469} 470 471/* Convert from native endianness to network endianness (and vice-versa). */ 472 473static unsigned int 474wordswap (unsigned int v) 475{ 476 return ((v & 0xff) << 8) | ((v >> 8) & 0xff); 477} 478 479/* Initialize the socket connection, and wait for a client. */ 480 481static void 482sock_init (void) 483{ 484 struct _iosb iosb; 485 unsigned int status; 486 487 /* Listen channel and characteristics. */ 488 unsigned short listen_channel; 489 struct sockchar listen_sockchar; 490 491 /* Client address. */ 492 unsigned short cli_addrlen; 493 struct sockaddr_in cli_addr; 494 ILE3 cli_itemlst; 495 496 /* Our address. */ 497 struct sockaddr_in serv_addr; 498 ILE2 serv_itemlst; 499 500 /* Reuseaddr option value (on). */ 501 int optval = 1; 502 ILE2 sockopt_itemlst; 503 ILE2 reuseaddr_itemlst; 504 505 /* TCP/IP network pseudodevice. */ 506 static const $DESCRIPTOR (inet_device, "TCPIP$DEVICE:"); 507 508 /* Initialize socket characteristics. */ 509 listen_sockchar.prot = TCPIP$C_TCP; 510 listen_sockchar.type = TCPIP$C_STREAM; 511 listen_sockchar.af = TCPIP$C_AF_INET; 512 513 /* Assign I/O channels to network device. */ 514 status = sys$assign ((void *) &inet_device, &listen_channel, 0, 0); 515 if (status & STS$M_SUCCESS) 516 status = sys$assign ((void *) &inet_device, &conn_channel, 0, 0); 517 if (!(status & STS$M_SUCCESS)) 518 { 519 term_puts ("Failed to assign I/O channel(s)\n"); 520 LIB$SIGNAL (status); 521 } 522 523 /* Create a listen socket. */ 524 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 525 listen_channel, /* I/O channel. */ 526 IO$_SETMODE, /* I/O function code. */ 527 &iosb, /* I/O status block. */ 528 0, /* Ast service routine. */ 529 0, /* Ast parameter. */ 530 &listen_sockchar, /* P1 - socket characteristics. */ 531 0, 0, 0, 0, 0); 532 if (status & STS$M_SUCCESS) 533 status = iosb.iosb$w_status; 534 if (!(status & STS$M_SUCCESS)) 535 { 536 term_puts ("Failed to create socket\n"); 537 LIB$SIGNAL (status); 538 } 539 540 /* Set reuse address option. */ 541 /* Initialize reuseaddr's item-list element. */ 542 reuseaddr_itemlst.ile2$w_length = sizeof (optval); 543 reuseaddr_itemlst.ile2$w_code = TCPIP$C_REUSEADDR; 544 reuseaddr_itemlst.ile2$ps_bufaddr = &optval; 545 546 /* Initialize setsockopt's item-list descriptor. */ 547 sockopt_itemlst.ile2$w_length = sizeof (reuseaddr_itemlst); 548 sockopt_itemlst.ile2$w_code = TCPIP$C_SOCKOPT; 549 sockopt_itemlst.ile2$ps_bufaddr = &reuseaddr_itemlst; 550 551 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 552 listen_channel, /* I/O channel. */ 553 IO$_SETMODE, /* I/O function code. */ 554 &iosb, /* I/O status block. */ 555 0, /* Ast service routine. */ 556 0, /* Ast parameter. */ 557 0, /* P1. */ 558 0, /* P2. */ 559 0, /* P3. */ 560 0, /* P4. */ 561 (__int64) &sockopt_itemlst, /* P5 - socket options. */ 562 0); 563 if (status & STS$M_SUCCESS) 564 status = iosb.iosb$w_status; 565 if (!(status & STS$M_SUCCESS)) 566 { 567 term_puts ("Failed to set socket option\n"); 568 LIB$SIGNAL (status); 569 } 570 571 /* Bind server's ip address and port number to listen socket. */ 572 /* Initialize server's socket address structure. */ 573 ots$fill (&serv_addr, sizeof (serv_addr), 0); 574 serv_addr.sin_family = TCPIP$C_AF_INET; 575 serv_addr.sin_port = wordswap (serv_port); 576 serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; 577 578 /* Initialize server's item-list descriptor. */ 579 serv_itemlst.ile2$w_length = sizeof (serv_addr); 580 serv_itemlst.ile2$w_code = TCPIP$C_SOCK_NAME; 581 serv_itemlst.ile2$ps_bufaddr = &serv_addr; 582 583 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 584 listen_channel, /* I/O channel. */ 585 IO$_SETMODE, /* I/O function code. */ 586 &iosb, /* I/O status block. */ 587 0, /* Ast service routine. */ 588 0, /* Ast parameter. */ 589 0, /* P1. */ 590 0, /* P2. */ 591 (__int64) &serv_itemlst, /* P3 - local socket name. */ 592 0, 0, 0); 593 if (status & STS$M_SUCCESS) 594 status = iosb.iosb$w_status; 595 if (!(status & STS$M_SUCCESS)) 596 { 597 term_puts ("Failed to bind socket\n"); 598 LIB$SIGNAL (status); 599 } 600 601 /* Set socket as a listen socket. */ 602 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 603 listen_channel, /* I/O channel. */ 604 IO$_SETMODE, /* I/O function code. */ 605 &iosb, /* I/O status block. */ 606 0, /* Ast service routine. */ 607 0, /* Ast parameter. */ 608 0, /* P1. */ 609 0, /* P2. */ 610 0, /* P3. */ 611 1, /* P4 - connection backlog. */ 612 0, 0); 613 if (status & STS$M_SUCCESS) 614 status = iosb.iosb$w_status; 615 if (!(status & STS$M_SUCCESS)) 616 { 617 term_puts ("Failed to set socket passive\n"); 618 LIB$SIGNAL (status); 619 } 620 621 /* Accept connection from a client. */ 622 TERM_FAO ("Waiting for a client connection on port: !ZW!/", 623 wordswap (serv_addr.sin_port)); 624 625 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 626 listen_channel, /* I/O channel. */ 627 IO$_ACCESS|IO$M_ACCEPT, /* I/O function code. */ 628 &iosb, /* I/O status block. */ 629 0, /* Ast service routine. */ 630 0, /* Ast parameter. */ 631 0, /* P1. */ 632 0, /* P2. */ 633 0, /* P3. */ 634 (__int64) &conn_channel, /* P4 - I/O channel for conn. */ 635 0, 0); 636 637 if (status & STS$M_SUCCESS) 638 status = iosb.iosb$w_status; 639 if (!(status & STS$M_SUCCESS)) 640 { 641 term_puts ("Failed to accept client connection\n"); 642 LIB$SIGNAL (status); 643 } 644 645 /* Log client connection request. */ 646 cli_itemlst.ile3$w_length = sizeof (cli_addr); 647 cli_itemlst.ile3$w_code = TCPIP$C_SOCK_NAME; 648 cli_itemlst.ile3$ps_bufaddr = &cli_addr; 649 cli_itemlst.ile3$ps_retlen_addr = &cli_addrlen; 650 ots$fill (&cli_addr, sizeof(cli_addr), 0); 651 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 652 conn_channel, /* I/O channel. */ 653 IO$_SENSEMODE, /* I/O function code. */ 654 &iosb, /* I/O status block. */ 655 0, /* Ast service routine. */ 656 0, /* Ast parameter. */ 657 0, /* P1. */ 658 0, /* P2. */ 659 0, /* P3. */ 660 (__int64) &cli_itemlst, /* P4 - peer socket name. */ 661 0, 0); 662 if (status & STS$M_SUCCESS) 663 status = iosb.iosb$w_status; 664 if (!(status & STS$M_SUCCESS)) 665 { 666 term_puts ("Failed to get client name\n"); 667 LIB$SIGNAL (status); 668 } 669 670 TERM_FAO ("Accepted connection from host: !UB.!UB,!UB.!UB, port: !UW!/", 671 (cli_addr.sin_addr.s_addr >> 0) & 0xff, 672 (cli_addr.sin_addr.s_addr >> 8) & 0xff, 673 (cli_addr.sin_addr.s_addr >> 16) & 0xff, 674 (cli_addr.sin_addr.s_addr >> 24) & 0xff, 675 wordswap (cli_addr.sin_port)); 676} 677 678/* Close the socket. */ 679 680static void 681sock_close (void) 682{ 683 struct _iosb iosb; 684 unsigned int status; 685 686 /* Close socket. */ 687 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 688 conn_channel, /* I/O channel. */ 689 IO$_DEACCESS, /* I/O function code. */ 690 &iosb, /* I/O status block. */ 691 0, /* Ast service routine. */ 692 0, /* Ast parameter. */ 693 0, 0, 0, 0, 0, 0); 694 695 if (status & STS$M_SUCCESS) 696 status = iosb.iosb$w_status; 697 if (!(status & STS$M_SUCCESS)) 698 { 699 term_puts ("Failed to close socket\n"); 700 LIB$SIGNAL (status); 701 } 702 703 /* Deassign I/O channel to network device. */ 704 status = sys$dassgn (conn_channel); 705 706 if (!(status & STS$M_SUCCESS)) 707 { 708 term_puts ("Failed to deassign I/O channel\n"); 709 LIB$SIGNAL (status); 710 } 711} 712 713/* Mark a page as R/W. Return old rights. */ 714 715static unsigned int 716page_set_rw (unsigned __int64 startva, unsigned __int64 len, 717 unsigned int *oldprot) 718{ 719 unsigned int status; 720 unsigned __int64 retva; 721 unsigned __int64 retlen; 722 723 status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, PRT$C_UW, 724 (void *)&retva, &retlen, oldprot); 725 return status; 726} 727 728/* Restore page rights. */ 729 730static void 731page_restore_rw (unsigned __int64 startva, unsigned __int64 len, 732 unsigned int prot) 733{ 734 unsigned int status; 735 unsigned __int64 retva; 736 unsigned __int64 retlen; 737 unsigned int oldprot; 738 739 status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, prot, 740 (void *)&retva, &retlen, &oldprot); 741 if (!(status & STS$M_SUCCESS)) 742 LIB$SIGNAL (status); 743} 744 745/* Get the TEB (thread environment block). */ 746 747static pthread_t 748get_teb (void) 749{ 750 return (pthread_t)__getReg (_IA64_REG_TP); 751} 752 753/* Enable thread scheduling if VAL is true. */ 754 755static unsigned int 756set_thread_scheduling (int val) 757{ 758 struct dbgext_control_block blk; 759 unsigned int status; 760 761 if (!dbgext_func) 762 return 0; 763 764 blk.dbgext$w_function_code = DBGEXT$K_STOP_ALL_OTHER_TASKS; 765 blk.dbgext$w_facility_id = CMA$_FACILITY; 766 blk.dbgext$l_stop_value = val; 767 768 status = dbgext_func (&blk); 769 if (!(status & STS$M_SUCCESS)) 770 { 771 TERM_FAO ("set_thread_scheduling error, val=!SL, status=!XL!/", 772 val, blk.dbgext$l_status); 773 lib$signal (status); 774 } 775 776 return blk.dbgext$l_stop_value; 777} 778 779/* Get next thread (after THR). Start with 0. */ 780 781static unsigned int 782thread_next (unsigned int thr) 783{ 784 struct dbgext_control_block blk; 785 unsigned int status; 786 787 if (!dbgext_func) 788 return 0; 789 790 blk.dbgext$w_function_code = DBGEXT$K_NEXT_TASK; 791 blk.dbgext$w_facility_id = CMA$_FACILITY; 792 blk.dbgext$l_ada_flags = 0; 793 blk.dbgext$l_task_value = thr; 794 795 status = dbgext_func (&blk); 796 if (!(status & STS$M_SUCCESS)) 797 lib$signal (status); 798 799 return blk.dbgext$l_task_value; 800} 801 802/* Pthread Debug callbacks. */ 803 804static int 805read_callback (pthreadDebugClient_t context, 806 pthreadDebugTargetAddr_t addr, 807 pthreadDebugAddr_t buf, 808 size_t size) 809{ 810 if (trace_pthreaddbg) 811 TERM_FAO ("read_callback (!XH, !XH, !SL)!/", addr, buf, size); 812 ots$move (buf, size, addr); 813 return 0; 814} 815 816static int 817write_callback (pthreadDebugClient_t context, 818 pthreadDebugTargetAddr_t addr, 819 pthreadDebugLongConstAddr_t buf, 820 size_t size) 821{ 822 if (trace_pthreaddbg) 823 TERM_FAO ("write_callback (!XH, !XH, !SL)!/", addr, buf, size); 824 ots$move (addr, size, buf); 825 return 0; 826} 827 828static int 829suspend_callback (pthreadDebugClient_t context) 830{ 831 /* Always suspended. */ 832 return 0; 833} 834 835static int 836resume_callback (pthreadDebugClient_t context) 837{ 838 /* So no need to resume. */ 839 return 0; 840} 841 842static int 843kthdinfo_callback (pthreadDebugClient_t context, 844 pthreadDebugKId_t kid, 845 pthreadDebugKThreadInfo_p thread_info) 846{ 847 if (trace_pthreaddbg) 848 term_puts ("kthinfo_callback"); 849 return ENOSYS; 850} 851 852static int 853hold_callback (pthreadDebugClient_t context, 854 pthreadDebugKId_t kid) 855{ 856 if (trace_pthreaddbg) 857 term_puts ("hold_callback"); 858 return ENOSYS; 859} 860 861static int 862unhold_callback (pthreadDebugClient_t context, 863 pthreadDebugKId_t kid) 864{ 865 if (trace_pthreaddbg) 866 term_puts ("unhold_callback"); 867 return ENOSYS; 868} 869 870static int 871getfreg_callback (pthreadDebugClient_t context, 872 pthreadDebugFregs_t *reg, 873 pthreadDebugKId_t kid) 874{ 875 if (trace_pthreaddbg) 876 term_puts ("getfreg_callback"); 877 return ENOSYS; 878} 879 880static int 881setfreg_callback (pthreadDebugClient_t context, 882 const pthreadDebugFregs_t *reg, 883 pthreadDebugKId_t kid) 884{ 885 if (trace_pthreaddbg) 886 term_puts ("setfreg_callback"); 887 return ENOSYS; 888} 889 890static int 891getreg_callback (pthreadDebugClient_t context, 892 pthreadDebugRegs_t *reg, 893 pthreadDebugKId_t kid) 894{ 895 if (trace_pthreaddbg) 896 term_puts ("getreg_callback"); 897 return ENOSYS; 898} 899 900static int 901setreg_callback (pthreadDebugClient_t context, 902 const pthreadDebugRegs_t *reg, 903 pthreadDebugKId_t kid) 904{ 905 if (trace_pthreaddbg) 906 term_puts ("setreg_callback"); 907 return ENOSYS; 908} 909 910static int 911output_callback (pthreadDebugClient_t context, 912 pthreadDebugConstString_t line) 913{ 914 term_puts (line); 915 term_putnl (); 916 return 0; 917} 918 919static int 920error_callback (pthreadDebugClient_t context, 921 pthreadDebugConstString_t line) 922{ 923 term_puts (line); 924 term_putnl (); 925 return 0; 926} 927 928static pthreadDebugAddr_t 929malloc_callback (pthreadDebugClient_t caller_context, size_t size) 930{ 931 unsigned int status; 932 unsigned int res; 933 int len; 934 935 len = size + 16; 936 status = lib$get_vm (&len, &res, 0); 937 if (!(status & STS$M_SUCCESS)) 938 LIB$SIGNAL (status); 939 if (trace_pthreaddbg) 940 TERM_FAO ("malloc_callback (!UL) -> !XA!/", size, res); 941 *(unsigned int *)res = len; 942 return (char *)res + 16; 943} 944 945static void 946free_callback (pthreadDebugClient_t caller_context, pthreadDebugAddr_t address) 947{ 948 unsigned int status; 949 unsigned int res; 950 int len; 951 952 res = (unsigned int)address - 16; 953 len = *(unsigned int *)res; 954 if (trace_pthreaddbg) 955 TERM_FAO ("free_callback (!XA)!/", address); 956 status = lib$free_vm (&len, &res, 0); 957 if (!(status & STS$M_SUCCESS)) 958 LIB$SIGNAL (status); 959} 960 961static int 962speckthd_callback (pthreadDebugClient_t caller_context, 963 pthreadDebugSpecialType_t type, 964 pthreadDebugKId_t *kernel_tid) 965{ 966 return ENOTSUP; 967} 968 969static pthreadDebugCallbacks_t pthread_debug_callbacks = { 970 PTHREAD_DEBUG_VERSION, 971 read_callback, 972 write_callback, 973 suspend_callback, 974 resume_callback, 975 kthdinfo_callback, 976 hold_callback, 977 unhold_callback, 978 getfreg_callback, 979 setfreg_callback, 980 getreg_callback, 981 setreg_callback, 982 output_callback, 983 error_callback, 984 malloc_callback, 985 free_callback, 986 speckthd_callback 987}; 988 989/* Name of the pthread shared library. */ 990static const $DESCRIPTOR (pthread_rtl_desc, "PTHREAD$RTL"); 991 992/* List of symbols to extract from pthread debug library. */ 993struct pthread_debug_entry 994{ 995 const unsigned int namelen; 996 const __char_ptr32 name; 997 __void_ptr32 func; 998}; 999 1000#define DEBUG_ENTRY(str) { sizeof(str) - 1, str, 0 } 1001 1002static struct pthread_debug_entry pthread_debug_entries[] = { 1003 DEBUG_ENTRY("pthreadDebugContextInit"), 1004 DEBUG_ENTRY("pthreadDebugThdSeqInit"), 1005 DEBUG_ENTRY("pthreadDebugThdSeqNext"), 1006 DEBUG_ENTRY("pthreadDebugThdSeqDestroy"), 1007 DEBUG_ENTRY("pthreadDebugThdGetInfo"), 1008 DEBUG_ENTRY("pthreadDebugThdGetInfoAddr"), 1009 DEBUG_ENTRY("pthreadDebugThdGetReg"), 1010 DEBUG_ENTRY("pthreadDebugCmd") 1011}; 1012 1013/* Pthread debug context. */ 1014static pthreadDebugContext_t debug_context; 1015 1016/* Wrapper around pthread debug entry points. */ 1017 1018static int 1019pthread_debug_thd_seq_init (pthreadDebugId_t *id) 1020{ 1021 return ((int (*)())pthread_debug_entries[1].func) 1022 (debug_context, id); 1023} 1024 1025static int 1026pthread_debug_thd_seq_next (pthreadDebugId_t *id) 1027{ 1028 return ((int (*)())pthread_debug_entries[2].func) 1029 (debug_context, id); 1030} 1031 1032static int 1033pthread_debug_thd_seq_destroy (void) 1034{ 1035 return ((int (*)())pthread_debug_entries[3].func) 1036 (debug_context); 1037} 1038 1039static int 1040pthread_debug_thd_get_info (pthreadDebugId_t id, 1041 pthreadDebugThreadInfo_t *info) 1042{ 1043 return ((int (*)())pthread_debug_entries[4].func) 1044 (debug_context, id, info); 1045} 1046 1047static int 1048pthread_debug_thd_get_info_addr (pthread_t thr, 1049 pthreadDebugThreadInfo_t *info) 1050{ 1051 return ((int (*)())pthread_debug_entries[5].func) 1052 (debug_context, thr, info); 1053} 1054 1055static int 1056pthread_debug_thd_get_reg (pthreadDebugId_t thr, 1057 pthreadDebugRegs_t *regs) 1058{ 1059 return ((int (*)())pthread_debug_entries[6].func) 1060 (debug_context, thr, regs); 1061} 1062 1063static int 1064stub_pthread_debug_cmd (const char *cmd) 1065{ 1066 return ((int (*)())pthread_debug_entries[7].func) 1067 (debug_context, cmd); 1068} 1069 1070/* Show all the threads. */ 1071 1072static void 1073threads_show (void) 1074{ 1075 pthreadDebugId_t id; 1076 pthreadDebugThreadInfo_t info; 1077 int res; 1078 1079 res = pthread_debug_thd_seq_init (&id); 1080 if (res != 0) 1081 { 1082 TERM_FAO ("seq init failed, res=!SL!/", res); 1083 return; 1084 } 1085 while (1) 1086 { 1087 if (pthread_debug_thd_get_info (id, &info) != 0) 1088 { 1089 TERM_FAO ("thd_get_info !SL failed!/", id); 1090 break; 1091 } 1092 if (pthread_debug_thd_seq_next (&id) != 0) 1093 break; 1094 } 1095 pthread_debug_thd_seq_destroy (); 1096} 1097 1098/* Initialize pthread support. */ 1099 1100static void 1101threads_init (void) 1102{ 1103 static const $DESCRIPTOR (dbgext_desc, "PTHREAD$DBGEXT"); 1104 static const $DESCRIPTOR (pthread_debug_desc, "PTHREAD$DBGSHR"); 1105 static const $DESCRIPTOR (dbgsymtable_desc, "PTHREAD_DBG_SYMTABLE"); 1106 int pthread_dbgext; 1107 int status; 1108 void *dbg_symtable; 1109 int i; 1110 void *caller_context = 0; 1111 1112 status = lib$find_image_symbol 1113 ((void *) &pthread_rtl_desc, (void *) &dbgext_desc, 1114 (int *) &dbgext_func); 1115 if (!(status & STS$M_SUCCESS)) 1116 LIB$SIGNAL (status); 1117 1118 status = lib$find_image_symbol 1119 ((void *) &pthread_rtl_desc, (void *) &dbgsymtable_desc, 1120 (int *) &dbg_symtable); 1121 if (!(status & STS$M_SUCCESS)) 1122 LIB$SIGNAL (status); 1123 1124 /* Find entry points in pthread_debug. */ 1125 for (i = 0; 1126 i < sizeof (pthread_debug_entries) / sizeof (pthread_debug_entries[0]); 1127 i++) 1128 { 1129 struct dsc$descriptor_s sym = 1130 { pthread_debug_entries[i].namelen, 1131 DSC$K_DTYPE_T, DSC$K_CLASS_S, 1132 pthread_debug_entries[i].name }; 1133 status = lib$find_image_symbol 1134 ((void *) &pthread_debug_desc, (void *) &sym, 1135 (int *) &pthread_debug_entries[i].func); 1136 if (!(status & STS$M_SUCCESS)) 1137 lib$signal (status); 1138 } 1139 1140 if (trace_pthreaddbg) 1141 TERM_FAO ("debug symtable: !XH!/", dbg_symtable); 1142 status = ((int (*)()) pthread_debug_entries[0].func) 1143 (&caller_context, &pthread_debug_callbacks, dbg_symtable, &debug_context); 1144 if (status != 0) 1145 TERM_FAO ("cannot initialize pthread_debug: !UL!/", status); 1146 TERM_FAO ("pthread debug done!/", 0); 1147} 1148 1149/* Convert an hexadecimal character to a nibble. Return -1 in case of 1150 error. */ 1151 1152static int 1153hex2nibble (unsigned char h) 1154{ 1155 if (h >= '0' && h <= '9') 1156 return h - '0'; 1157 if (h >= 'A' && h <= 'F') 1158 return h - 'A' + 10; 1159 if (h >= 'a' && h <= 'f') 1160 return h - 'a' + 10; 1161 return -1; 1162} 1163 1164/* Convert an hexadecimal 2 character string to a byte. Return -1 in case 1165 of error. */ 1166 1167static int 1168hex2byte (const unsigned char *p) 1169{ 1170 int h, l; 1171 1172 h = hex2nibble (p[0]); 1173 l = hex2nibble (p[1]); 1174 if (h == -1 || l == -1) 1175 return -1; 1176 return (h << 4) | l; 1177} 1178 1179/* Convert a byte V to a 2 character strings P. */ 1180 1181static void 1182byte2hex (unsigned char *p, unsigned char v) 1183{ 1184 p[0] = hex[v >> 4]; 1185 p[1] = hex[v & 0xf]; 1186} 1187 1188/* Convert a quadword V to a 16 character strings P. */ 1189 1190static void 1191quad2hex (unsigned char *p, unsigned __int64 v) 1192{ 1193 int i; 1194 for (i = 0; i < 16; i++) 1195 { 1196 p[i] = hex[v >> 60]; 1197 v <<= 4; 1198 } 1199} 1200 1201static void 1202long2pkt (unsigned int v) 1203{ 1204 int i; 1205 1206 for (i = 0; i < 8; i++) 1207 { 1208 gdb_buf[gdb_blen + i] = hex[(v >> 28) & 0x0f]; 1209 v <<= 4; 1210 } 1211 gdb_blen += 8; 1212} 1213 1214/* Generate an error packet. */ 1215 1216static void 1217packet_error (unsigned int err) 1218{ 1219 gdb_buf[1] = 'E'; 1220 byte2hex (gdb_buf + 2, err); 1221 gdb_blen = 4; 1222} 1223 1224/* Generate an OK packet. */ 1225 1226static void 1227packet_ok (void) 1228{ 1229 gdb_buf[1] = 'O'; 1230 gdb_buf[2] = 'K'; 1231 gdb_blen = 3; 1232} 1233 1234/* Append a register to the packet. */ 1235 1236static void 1237ireg2pkt (const unsigned char *p) 1238{ 1239 int i; 1240 1241 for (i = 0; i < 8; i++) 1242 { 1243 byte2hex (gdb_buf + gdb_blen, p[i]); 1244 gdb_blen += 2; 1245 } 1246} 1247 1248/* Append a C string (ASCIZ) to the packet. */ 1249 1250static void 1251str2pkt (const char *str) 1252{ 1253 while (*str) 1254 gdb_buf[gdb_blen++] = *str++; 1255} 1256 1257/* Extract a number fro the packet. */ 1258 1259static unsigned __int64 1260pkt2val (const unsigned char *pkt, unsigned int *pos) 1261{ 1262 unsigned __int64 res = 0; 1263 unsigned int i; 1264 1265 while (1) 1266 { 1267 int r = hex2nibble (pkt[*pos]); 1268 1269 if (r < 0) 1270 return res; 1271 res = (res << 4) | r; 1272 (*pos)++; 1273 } 1274} 1275 1276/* Append LEN bytes from B to the current gdb packet (encode in binary). */ 1277 1278static void 1279mem2bin (const unsigned char *b, unsigned int len) 1280{ 1281 unsigned int i; 1282 for (i = 0; i < len; i++) 1283 switch (b[i]) 1284 { 1285 case '#': 1286 case '$': 1287 case '}': 1288 case '*': 1289 case 0: 1290 gdb_buf[gdb_blen++] = '}'; 1291 gdb_buf[gdb_blen++] = b[i] ^ 0x20; 1292 break; 1293 default: 1294 gdb_buf[gdb_blen++] = b[i]; 1295 break; 1296 } 1297} 1298 1299/* Append LEN bytes from B to the current gdb packet (encode in hex). */ 1300 1301static void 1302mem2hex (const unsigned char *b, unsigned int len) 1303{ 1304 unsigned int i; 1305 for (i = 0; i < len; i++) 1306 { 1307 byte2hex (gdb_buf + gdb_blen, b[i]); 1308 gdb_blen += 2; 1309 } 1310} 1311 1312/* Handle the 'q' packet. */ 1313 1314static void 1315handle_q_packet (const unsigned char *pkt, unsigned int pktlen) 1316{ 1317 /* For qfThreadInfo and qsThreadInfo. */ 1318 static unsigned int first_thread; 1319 static unsigned int last_thread; 1320 1321 static const char xfer_uib[] = "qXfer:uib:read:"; 1322#define XFER_UIB_LEN (sizeof (xfer_uib) - 1) 1323 static const char qfthreadinfo[] = "qfThreadInfo"; 1324#define QFTHREADINFO_LEN (sizeof (qfthreadinfo) - 1) 1325 static const char qsthreadinfo[] = "qsThreadInfo"; 1326#define QSTHREADINFO_LEN (sizeof (qsthreadinfo) - 1) 1327 static const char qthreadextrainfo[] = "qThreadExtraInfo,"; 1328#define QTHREADEXTRAINFO_LEN (sizeof (qthreadextrainfo) - 1) 1329 static const char qsupported[] = "qSupported:"; 1330#define QSUPPORTED_LEN (sizeof (qsupported) - 1) 1331 1332 if (pktlen == 2 && pkt[1] == 'C') 1333 { 1334 /* Current thread. */ 1335 gdb_buf[0] = '$'; 1336 gdb_buf[1] = 'Q'; 1337 gdb_buf[2] = 'C'; 1338 gdb_blen = 3; 1339 if (has_threads) 1340 long2pkt ((unsigned long) get_teb ()); 1341 return; 1342 } 1343 else if (pktlen > XFER_UIB_LEN 1344 && ots$strcmp_eql (pkt, XFER_UIB_LEN, xfer_uib, XFER_UIB_LEN)) 1345 { 1346 /* Get unwind information block. */ 1347 unsigned __int64 pc; 1348 unsigned int pos = XFER_UIB_LEN; 1349 unsigned int off; 1350 unsigned int len; 1351 union 1352 { 1353 unsigned char bytes[32]; 1354 struct 1355 { 1356 unsigned __int64 code_start_va; 1357 unsigned __int64 code_end_va; 1358 unsigned __int64 uib_start_va; 1359 unsigned __int64 gp_value; 1360 } data; 1361 } uei; 1362 int res; 1363 int i; 1364 1365 packet_error (0); 1366 1367 pc = pkt2val (pkt, &pos); 1368 if (pkt[pos] != ':') 1369 return; 1370 pos++; 1371 off = pkt2val (pkt, &pos); 1372 if (pkt[pos] != ',' || off != 0) 1373 return; 1374 pos++; 1375 len = pkt2val (pkt, &pos); 1376 if (pkt[pos] != '#' || len != 0x20) 1377 return; 1378 1379 res = SYS$GET_UNWIND_ENTRY_INFO (pc, &uei.data, 0); 1380 if (res == SS$_NODATA || res != SS$_NORMAL) 1381 ots$fill (uei.bytes, sizeof (uei.bytes), 0); 1382 1383 if (trace_unwind) 1384 { 1385 TERM_FAO ("Unwind request for !XH, status=!XL, uib=!XQ, GP=!XQ!/", 1386 pc, res, uei.data.uib_start_va, uei.data.gp_value); 1387 } 1388 1389 gdb_buf[0] = '$'; 1390 gdb_buf[1] = 'l'; 1391 gdb_blen = 2; 1392 mem2bin (uei.bytes, sizeof (uei.bytes)); 1393 } 1394 else if (pktlen == QFTHREADINFO_LEN 1395 && ots$strcmp_eql (pkt, QFTHREADINFO_LEN, 1396 qfthreadinfo, QFTHREADINFO_LEN)) 1397 { 1398 /* Get first thread(s). */ 1399 gdb_buf[0] = '$'; 1400 gdb_buf[1] = 'm'; 1401 gdb_blen = 2; 1402 1403 if (!has_threads) 1404 { 1405 gdb_buf[1] = 'l'; 1406 return; 1407 } 1408 first_thread = thread_next (0); 1409 last_thread = first_thread; 1410 long2pkt (first_thread); 1411 } 1412 else if (pktlen == QSTHREADINFO_LEN 1413 && ots$strcmp_eql (pkt, QSTHREADINFO_LEN, 1414 qsthreadinfo, QSTHREADINFO_LEN)) 1415 { 1416 /* Get subsequent threads. */ 1417 gdb_buf[0] = '$'; 1418 gdb_buf[1] = 'm'; 1419 gdb_blen = 2; 1420 while (dbgext_func) 1421 { 1422 unsigned int res; 1423 res = thread_next (last_thread); 1424 if (res == first_thread) 1425 break; 1426 if (gdb_blen > 2) 1427 gdb_buf[gdb_blen++] = ','; 1428 long2pkt (res); 1429 last_thread = res; 1430 if (gdb_blen > sizeof (gdb_buf) - 16) 1431 break; 1432 } 1433 1434 if (gdb_blen == 2) 1435 gdb_buf[1] = 'l'; 1436 } 1437 else if (pktlen > QTHREADEXTRAINFO_LEN 1438 && ots$strcmp_eql (pkt, QTHREADEXTRAINFO_LEN, 1439 qthreadextrainfo, QTHREADEXTRAINFO_LEN)) 1440 { 1441 /* Get extra info about a thread. */ 1442 pthread_t thr; 1443 unsigned int pos = QTHREADEXTRAINFO_LEN; 1444 pthreadDebugThreadInfo_t info; 1445 int res; 1446 1447 packet_error (0); 1448 if (!has_threads) 1449 return; 1450 1451 thr = (pthread_t) pkt2val (pkt, &pos); 1452 if (pkt[pos] != '#') 1453 return; 1454 res = pthread_debug_thd_get_info_addr (thr, &info); 1455 if (res != 0) 1456 { 1457 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", thr, res); 1458 return; 1459 } 1460 gdb_buf[0] = '$'; 1461 gdb_blen = 1; 1462 mem2hex ((const unsigned char *)"VMS-thread", 11); 1463 } 1464 else if (pktlen > QSUPPORTED_LEN 1465 && ots$strcmp_eql (pkt, QSUPPORTED_LEN, 1466 qsupported, QSUPPORTED_LEN)) 1467 { 1468 /* Get supported features. */ 1469 pthread_t thr; 1470 unsigned int pos = QSUPPORTED_LEN; 1471 pthreadDebugThreadInfo_t info; 1472 int res; 1473 1474 /* Ignore gdb features. */ 1475 gdb_buf[0] = '$'; 1476 gdb_blen = 1; 1477 1478 str2pkt ("qXfer:uib:read+"); 1479 return; 1480 } 1481 else 1482 { 1483 if (trace_pkt) 1484 { 1485 term_puts ("unknown <: "); 1486 term_write ((char *)pkt, pktlen); 1487 term_putnl (); 1488 } 1489 return; 1490 } 1491} 1492 1493/* Handle the 'v' packet. */ 1494 1495static int 1496handle_v_packet (const unsigned char *pkt, unsigned int pktlen) 1497{ 1498 static const char vcontq[] = "vCont?"; 1499#define VCONTQ_LEN (sizeof (vcontq) - 1) 1500 1501 if (pktlen == VCONTQ_LEN 1502 && ots$strcmp_eql (pkt, VCONTQ_LEN, vcontq, VCONTQ_LEN)) 1503 { 1504 gdb_buf[0] = '$'; 1505 gdb_blen = 1; 1506 1507 str2pkt ("vCont;c;s"); 1508 return 0; 1509 } 1510 else 1511 { 1512 if (trace_pkt) 1513 { 1514 term_puts ("unknown <: "); 1515 term_write ((char *)pkt, pktlen); 1516 term_putnl (); 1517 } 1518 return 0; 1519 } 1520} 1521 1522/* Get regs for the selected thread. */ 1523 1524static struct ia64_all_regs * 1525get_selected_regs (void) 1526{ 1527 pthreadDebugRegs_t regs; 1528 int res; 1529 1530 if (selected_thread == 0 || selected_thread == get_teb ()) 1531 return &excp_regs; 1532 1533 if (selected_thread == sel_regs_pthread) 1534 return &sel_regs; 1535 1536 /* Read registers. */ 1537 res = pthread_debug_thd_get_reg (selected_id, ®s); 1538 if (res != 0) 1539 { 1540 /* FIXME: return NULL ? */ 1541 return &excp_regs; 1542 } 1543 sel_regs_pthread = selected_thread; 1544 sel_regs.gr[1].v = regs.gp; 1545 sel_regs.gr[4].v = regs.r4; 1546 sel_regs.gr[5].v = regs.r5; 1547 sel_regs.gr[6].v = regs.r6; 1548 sel_regs.gr[7].v = regs.r7; 1549 sel_regs.gr[12].v = regs.sp; 1550 sel_regs.br[0].v = regs.rp; 1551 sel_regs.br[1].v = regs.b1; 1552 sel_regs.br[2].v = regs.b2; 1553 sel_regs.br[3].v = regs.b3; 1554 sel_regs.br[4].v = regs.b4; 1555 sel_regs.br[5].v = regs.b5; 1556 sel_regs.ip.v = regs.ip; 1557 sel_regs.bsp.v = regs.bspstore; /* FIXME: it is correct ? */ 1558 sel_regs.pfs.v = regs.pfs; 1559 sel_regs.pr.v = regs.pr; 1560 return &sel_regs; 1561} 1562 1563/* Create a status packet. */ 1564 1565static void 1566packet_status (void) 1567{ 1568 gdb_blen = 0; 1569 if (has_threads) 1570 { 1571 str2pkt ("$T05thread:"); 1572 long2pkt ((unsigned long) get_teb ()); 1573 gdb_buf[gdb_blen++] = ';'; 1574 } 1575 else 1576 str2pkt ("$S05"); 1577} 1578 1579/* Return 1 to continue. */ 1580 1581static int 1582handle_packet (unsigned char *pkt, unsigned int len) 1583{ 1584 unsigned int pos; 1585 1586 /* By default, reply unsupported. */ 1587 gdb_buf[0] = '$'; 1588 gdb_blen = 1; 1589 1590 pos = 1; 1591 switch (pkt[0]) 1592 { 1593 case '?': 1594 if (len == 1) 1595 { 1596 packet_status (); 1597 return 0; 1598 } 1599 break; 1600 case 'c': 1601 if (len == 1) 1602 { 1603 /* Clear psr.ss. */ 1604 excp_regs.psr.v &= ~(unsigned __int64)PSR$M_SS; 1605 return 1; 1606 } 1607 else 1608 packet_error (0); 1609 break; 1610 case 'g': 1611 if (len == 1) 1612 { 1613 unsigned int i; 1614 struct ia64_all_regs *regs = get_selected_regs (); 1615 unsigned char *p = regs->gr[0].b; 1616 1617 for (i = 0; i < 8 * 32; i++) 1618 byte2hex (gdb_buf + 1 + 2 * i, p[i]); 1619 gdb_blen += 2 * 8 * 32; 1620 return 0; 1621 } 1622 break; 1623 case 'H': 1624 if (pkt[1] == 'g') 1625 { 1626 int res; 1627 unsigned __int64 val; 1628 pthreadDebugThreadInfo_t info; 1629 1630 pos++; 1631 val = pkt2val (pkt, &pos); 1632 if (pos != len) 1633 { 1634 packet_error (0); 1635 return 0; 1636 } 1637 if (val == 0) 1638 { 1639 /* Default one. */ 1640 selected_thread = get_teb (); 1641 selected_id = 0; 1642 } 1643 else if (!has_threads) 1644 { 1645 packet_error (0); 1646 return 0; 1647 } 1648 else 1649 { 1650 res = pthread_debug_thd_get_info_addr ((pthread_t) val, &info); 1651 if (res != 0) 1652 { 1653 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", val, res); 1654 packet_error (0); 1655 return 0; 1656 } 1657 selected_thread = info.teb; 1658 selected_id = info.sequence; 1659 } 1660 packet_ok (); 1661 break; 1662 } 1663 else if (pkt[1] == 'c' 1664 && ((pkt[2] == '-' && pkt[3] == '1' && len == 4) 1665 || (pkt[2] == '0' && len == 3))) 1666 { 1667 /* Silently accept 'Hc0' and 'Hc-1'. */ 1668 packet_ok (); 1669 break; 1670 } 1671 else 1672 { 1673 packet_error (0); 1674 return 0; 1675 } 1676 case 'k': 1677 SYS$EXIT (SS$_NORMAL); 1678 break; 1679 case 'm': 1680 { 1681 unsigned __int64 addr; 1682 unsigned __int64 paddr; 1683 unsigned int l; 1684 unsigned int i; 1685 1686 addr = pkt2val (pkt, &pos); 1687 if (pkt[pos] != ',') 1688 { 1689 packet_error (0); 1690 return 0; 1691 } 1692 pos++; 1693 l = pkt2val (pkt, &pos); 1694 if (pkt[pos] != '#') 1695 { 1696 packet_error (0); 1697 return 0; 1698 } 1699 1700 /* Check access. */ 1701 i = l + (addr & VMS_PAGE_MASK); 1702 paddr = addr & ~VMS_PAGE_MASK; 1703 while (1) 1704 { 1705 if (__prober (paddr, 0) != 1) 1706 { 1707 packet_error (2); 1708 return 0; 1709 } 1710 if (i < VMS_PAGE_SIZE) 1711 break; 1712 i -= VMS_PAGE_SIZE; 1713 paddr += VMS_PAGE_SIZE; 1714 } 1715 1716 /* Transfer. */ 1717 for (i = 0; i < l; i++) 1718 byte2hex (gdb_buf + 1 + 2 * i, ((unsigned char *)addr)[i]); 1719 gdb_blen += 2 * l; 1720 } 1721 break; 1722 case 'M': 1723 { 1724 unsigned __int64 addr; 1725 unsigned __int64 paddr; 1726 unsigned int l; 1727 unsigned int i; 1728 unsigned int oldprot; 1729 1730 addr = pkt2val (pkt, &pos); 1731 if (pkt[pos] != ',') 1732 { 1733 packet_error (0); 1734 return 0; 1735 } 1736 pos++; 1737 l = pkt2val (pkt, &pos); 1738 if (pkt[pos] != ':') 1739 { 1740 packet_error (0); 1741 return 0; 1742 } 1743 pos++; 1744 page_set_rw (addr, l, &oldprot); 1745 1746 /* Check access. */ 1747 i = l + (addr & VMS_PAGE_MASK); 1748 paddr = addr & ~VMS_PAGE_MASK; 1749 while (1) 1750 { 1751 if (__probew (paddr, 0) != 1) 1752 { 1753 page_restore_rw (addr, l, oldprot); 1754 return 0; 1755 } 1756 if (i < VMS_PAGE_SIZE) 1757 break; 1758 i -= VMS_PAGE_SIZE; 1759 paddr += VMS_PAGE_SIZE; 1760 } 1761 1762 /* Write. */ 1763 for (i = 0; i < l; i++) 1764 { 1765 int v = hex2byte (pkt + pos); 1766 pos += 2; 1767 ((unsigned char *)addr)[i] = v; 1768 } 1769 1770 /* Sync caches. */ 1771 for (i = 0; i < l; i += 15) 1772 __fc (addr + i); 1773 __fc (addr + l); 1774 1775 page_restore_rw (addr, l, oldprot); 1776 packet_ok (); 1777 } 1778 break; 1779 case 'p': 1780 { 1781 unsigned int num = 0; 1782 unsigned int i; 1783 struct ia64_all_regs *regs = get_selected_regs (); 1784 1785 num = pkt2val (pkt, &pos); 1786 if (pos != len) 1787 { 1788 packet_error (0); 1789 return 0; 1790 } 1791 1792 switch (num) 1793 { 1794 case IA64_IP_REGNUM: 1795 ireg2pkt (regs->ip.b); 1796 break; 1797 case IA64_BR0_REGNUM: 1798 ireg2pkt (regs->br[0].b); 1799 break; 1800 case IA64_PSR_REGNUM: 1801 ireg2pkt (regs->psr.b); 1802 break; 1803 case IA64_BSP_REGNUM: 1804 ireg2pkt (regs->bsp.b); 1805 break; 1806 case IA64_CFM_REGNUM: 1807 ireg2pkt (regs->cfm.b); 1808 break; 1809 case IA64_PFS_REGNUM: 1810 ireg2pkt (regs->pfs.b); 1811 break; 1812 case IA64_PR_REGNUM: 1813 ireg2pkt (regs->pr.b); 1814 break; 1815 default: 1816 TERM_FAO ("gdbserv: unhandled reg !UW!/", num); 1817 packet_error (0); 1818 return 0; 1819 } 1820 } 1821 break; 1822 case 'q': 1823 handle_q_packet (pkt, len); 1824 break; 1825 case 's': 1826 if (len == 1) 1827 { 1828 /* Set psr.ss. */ 1829 excp_regs.psr.v |= (unsigned __int64)PSR$M_SS; 1830 return 1; 1831 } 1832 else 1833 packet_error (0); 1834 break; 1835 case 'T': 1836 /* Thread status. */ 1837 if (!has_threads) 1838 { 1839 packet_ok (); 1840 break; 1841 } 1842 else 1843 { 1844 int res; 1845 unsigned __int64 val; 1846 unsigned int fthr, thr; 1847 1848 val = pkt2val (pkt, &pos); 1849 /* Default is error (but only after parsing is complete). */ 1850 packet_error (0); 1851 if (pos != len) 1852 break; 1853 1854 /* Follow the list. This makes a O(n2) algorithm, but we don't really 1855 have the choice. Note that pthread_debug_thd_get_info_addr 1856 doesn't look reliable. */ 1857 fthr = thread_next (0); 1858 thr = fthr; 1859 do 1860 { 1861 if (val == thr) 1862 { 1863 packet_ok (); 1864 break; 1865 } 1866 thr = thread_next (thr); 1867 } 1868 while (thr != fthr); 1869 } 1870 break; 1871 case 'v': 1872 return handle_v_packet (pkt, len); 1873 break; 1874 case 'V': 1875 if (len > 3 && pkt[1] == 'M' && pkt[2] == 'S' && pkt[3] == ' ') 1876 { 1877 /* Temporary extension. */ 1878 if (has_threads) 1879 { 1880 pkt[len] = 0; 1881 stub_pthread_debug_cmd ((char *)pkt + 4); 1882 packet_ok (); 1883 } 1884 else 1885 packet_error (0); 1886 } 1887 break; 1888 default: 1889 if (trace_pkt) 1890 { 1891 term_puts ("unknown <: "); 1892 term_write ((char *)pkt, len); 1893 term_putnl (); 1894 } 1895 break; 1896 } 1897 return 0; 1898} 1899 1900/* Raw write to gdb. */ 1901 1902static void 1903sock_write (const unsigned char *buf, int len) 1904{ 1905 struct _iosb iosb; 1906 unsigned int status; 1907 1908 /* Write data to connection. */ 1909 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 1910 conn_channel, /* I/O channel. */ 1911 IO$_WRITEVBLK, /* I/O function code. */ 1912 &iosb, /* I/O status block. */ 1913 0, /* Ast service routine. */ 1914 0, /* Ast parameter. */ 1915 (char *)buf, /* P1 - buffer address. */ 1916 len, /* P2 - buffer length. */ 1917 0, 0, 0, 0); 1918 if (status & STS$M_SUCCESS) 1919 status = iosb.iosb$w_status; 1920 if (!(status & STS$M_SUCCESS)) 1921 { 1922 term_puts ("Failed to write data to gdb\n"); 1923 LIB$SIGNAL (status); 1924 } 1925} 1926 1927/* Compute the checksum and send the packet. */ 1928 1929static void 1930send_pkt (void) 1931{ 1932 unsigned char chksum = 0; 1933 unsigned int i; 1934 1935 for (i = 1; i < gdb_blen; i++) 1936 chksum += gdb_buf[i]; 1937 1938 gdb_buf[gdb_blen] = '#'; 1939 byte2hex (gdb_buf + gdb_blen + 1, chksum); 1940 1941 sock_write (gdb_buf, gdb_blen + 3); 1942 1943 if (trace_pkt > 1) 1944 { 1945 term_puts (">: "); 1946 term_write ((char *)gdb_buf, gdb_blen + 3); 1947 term_putnl (); 1948 } 1949} 1950 1951/* Read and handle one command. Return 1 is execution must resume. */ 1952 1953static int 1954one_command (void) 1955{ 1956 struct _iosb iosb; 1957 unsigned int status; 1958 unsigned int off; 1959 unsigned int dollar_off = 0; 1960 unsigned int sharp_off = 0; 1961 unsigned int cmd_off; 1962 unsigned int cmd_len; 1963 1964 /* Wait for a packet. */ 1965 while (1) 1966 { 1967 off = 0; 1968 while (1) 1969 { 1970 /* Read data from connection. */ 1971 status = sys$qiow (EFN$C_ENF, /* Event flag. */ 1972 conn_channel, /* I/O channel. */ 1973 IO$_READVBLK, /* I/O function code. */ 1974 &iosb, /* I/O status block. */ 1975 0, /* Ast service routine. */ 1976 0, /* Ast parameter. */ 1977 gdb_buf + off, /* P1 - buffer address. */ 1978 sizeof (gdb_buf) - off, /* P2 - buffer leng. */ 1979 0, 0, 0, 0); 1980 if (status & STS$M_SUCCESS) 1981 status = iosb.iosb$w_status; 1982 if (!(status & STS$M_SUCCESS)) 1983 { 1984 term_puts ("Failed to read data from connection\n" ); 1985 LIB$SIGNAL (status); 1986 } 1987 1988#ifdef RAW_DUMP 1989 term_puts ("{: "); 1990 term_write ((char *)gdb_buf + off, iosb.iosb$w_bcnt); 1991 term_putnl (); 1992#endif 1993 1994 gdb_blen = off + iosb.iosb$w_bcnt; 1995 1996 if (off == 0) 1997 { 1998 /* Search for '$'. */ 1999 for (dollar_off = 0; dollar_off < gdb_blen; dollar_off++) 2000 if (gdb_buf[dollar_off] == '$') 2001 break; 2002 if (dollar_off >= gdb_blen) 2003 { 2004 /* Not found, discard the data. */ 2005 off = 0; 2006 continue; 2007 } 2008 /* Search for '#'. */ 2009 for (sharp_off = dollar_off + 1; 2010 sharp_off < gdb_blen; 2011 sharp_off++) 2012 if (gdb_buf[sharp_off] == '#') 2013 break; 2014 } 2015 else if (sharp_off >= off) 2016 { 2017 /* Search for '#'. */ 2018 for (; sharp_off < gdb_blen; sharp_off++) 2019 if (gdb_buf[sharp_off] == '#') 2020 break; 2021 } 2022 2023 /* Got packet with checksum. */ 2024 if (sharp_off + 2 <= gdb_blen) 2025 break; 2026 2027 off = gdb_blen; 2028 if (gdb_blen == sizeof (gdb_buf)) 2029 { 2030 /* Packet too large, discard. */ 2031 off = 0; 2032 } 2033 } 2034 2035 /* Validate and acknowledge a packet. */ 2036 { 2037 unsigned char chksum = 0; 2038 unsigned int i; 2039 int v; 2040 2041 for (i = dollar_off + 1; i < sharp_off; i++) 2042 chksum += gdb_buf[i]; 2043 v = hex2byte (gdb_buf + sharp_off + 1); 2044 if (v != chksum) 2045 { 2046 term_puts ("Discard bad checksum packet\n"); 2047 continue; 2048 } 2049 else 2050 { 2051 sock_write ((const unsigned char *)"+", 1); 2052 break; 2053 } 2054 } 2055 } 2056 2057 if (trace_pkt > 1) 2058 { 2059 term_puts ("<: "); 2060 term_write ((char *)gdb_buf + dollar_off, sharp_off - dollar_off + 1); 2061 term_putnl (); 2062 } 2063 2064 cmd_off = dollar_off + 1; 2065 cmd_len = sharp_off - dollar_off - 1; 2066 2067 if (handle_packet (gdb_buf + dollar_off + 1, sharp_off - dollar_off - 1) == 1) 2068 return 1; 2069 2070 send_pkt (); 2071 return 0; 2072} 2073 2074/* Display the condition given by SIG64. */ 2075 2076static void 2077display_excp (struct chf64$signal_array *sig64, struct chf$mech_array *mech) 2078{ 2079 unsigned int status; 2080 char msg[160]; 2081 unsigned short msglen; 2082 $DESCRIPTOR (msg_desc, msg); 2083 unsigned char outadr[4]; 2084 2085 status = SYS$GETMSG (sig64->chf64$q_sig_name, &msglen, &msg_desc, 0, outadr); 2086 if (status & STS$M_SUCCESS) 2087 { 2088 char msg2[160]; 2089 unsigned short msg2len; 2090 struct dsc$descriptor_s msg2_desc = 2091 { sizeof (msg2), DSC$K_DTYPE_T, DSC$K_CLASS_S, msg2}; 2092 msg_desc.dsc$w_length = msglen; 2093 status = SYS$FAOL_64 (&msg_desc, &msg2len, &msg2_desc, 2094 &sig64->chf64$q_sig_arg1); 2095 if (status & STS$M_SUCCESS) 2096 term_write (msg2, msg2len); 2097 } 2098 else 2099 term_puts ("no message"); 2100 term_putnl (); 2101 2102 if (trace_excp > 1) 2103 { 2104 TERM_FAO (" Frame: !XH, Depth: !4SL, Esf: !XH!/", 2105 mech->chf$q_mch_frame, mech->chf$q_mch_depth, 2106 mech->chf$q_mch_esf_addr); 2107 } 2108} 2109 2110/* Get all registers from current thread. */ 2111 2112static void 2113read_all_registers (struct chf$mech_array *mech) 2114{ 2115 struct _intstk *intstk = 2116 (struct _intstk *)mech->chf$q_mch_esf_addr; 2117 struct chf64$signal_array *sig64 = 2118 (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr; 2119 unsigned int cnt = sig64->chf64$w_sig_arg_count; 2120 unsigned __int64 pc = (&sig64->chf64$q_sig_name)[cnt - 2]; 2121 2122 excp_regs.ip.v = pc; 2123 excp_regs.psr.v = intstk->intstk$q_ipsr; 2124 /* GDB and linux expects bsp to point after the current register frame. 2125 Adjust. */ 2126 { 2127 unsigned __int64 bsp = intstk->intstk$q_bsp; 2128 unsigned int sof = intstk->intstk$q_ifs & 0x7f; 2129 unsigned int delta = ((bsp >> 3) & 0x3f) + sof; 2130 excp_regs.bsp.v = bsp + ((sof + delta / 0x3f) << 3); 2131 } 2132 excp_regs.cfm.v = intstk->intstk$q_ifs & 0x3fffffffff; 2133 excp_regs.pfs.v = intstk->intstk$q_pfs; 2134 excp_regs.pr.v = intstk->intstk$q_preds; 2135 excp_regs.gr[0].v = 0; 2136 excp_regs.gr[1].v = intstk->intstk$q_gp; 2137 excp_regs.gr[2].v = intstk->intstk$q_r2; 2138 excp_regs.gr[3].v = intstk->intstk$q_r3; 2139 excp_regs.gr[4].v = intstk->intstk$q_r4; 2140 excp_regs.gr[5].v = intstk->intstk$q_r5; 2141 excp_regs.gr[6].v = intstk->intstk$q_r6; 2142 excp_regs.gr[7].v = intstk->intstk$q_r7; 2143 excp_regs.gr[8].v = intstk->intstk$q_r8; 2144 excp_regs.gr[9].v = intstk->intstk$q_r9; 2145 excp_regs.gr[10].v = intstk->intstk$q_r10; 2146 excp_regs.gr[11].v = intstk->intstk$q_r11; 2147 excp_regs.gr[12].v = (unsigned __int64)intstk + intstk->intstk$l_stkalign; 2148 excp_regs.gr[13].v = intstk->intstk$q_r13; 2149 excp_regs.gr[14].v = intstk->intstk$q_r14; 2150 excp_regs.gr[15].v = intstk->intstk$q_r15; 2151 excp_regs.gr[16].v = intstk->intstk$q_r16; 2152 excp_regs.gr[17].v = intstk->intstk$q_r17; 2153 excp_regs.gr[18].v = intstk->intstk$q_r18; 2154 excp_regs.gr[19].v = intstk->intstk$q_r19; 2155 excp_regs.gr[20].v = intstk->intstk$q_r20; 2156 excp_regs.gr[21].v = intstk->intstk$q_r21; 2157 excp_regs.gr[22].v = intstk->intstk$q_r22; 2158 excp_regs.gr[23].v = intstk->intstk$q_r23; 2159 excp_regs.gr[24].v = intstk->intstk$q_r24; 2160 excp_regs.gr[25].v = intstk->intstk$q_r25; 2161 excp_regs.gr[26].v = intstk->intstk$q_r26; 2162 excp_regs.gr[27].v = intstk->intstk$q_r27; 2163 excp_regs.gr[28].v = intstk->intstk$q_r28; 2164 excp_regs.gr[29].v = intstk->intstk$q_r29; 2165 excp_regs.gr[30].v = intstk->intstk$q_r30; 2166 excp_regs.gr[31].v = intstk->intstk$q_r31; 2167 excp_regs.br[0].v = intstk->intstk$q_b0; 2168 excp_regs.br[1].v = intstk->intstk$q_b1; 2169 excp_regs.br[2].v = intstk->intstk$q_b2; 2170 excp_regs.br[3].v = intstk->intstk$q_b3; 2171 excp_regs.br[4].v = intstk->intstk$q_b4; 2172 excp_regs.br[5].v = intstk->intstk$q_b5; 2173 excp_regs.br[6].v = intstk->intstk$q_b6; 2174 excp_regs.br[7].v = intstk->intstk$q_b7; 2175} 2176 2177/* Write all registers to current thread. FIXME: not yet complete. */ 2178 2179static void 2180write_all_registers (struct chf$mech_array *mech) 2181{ 2182 struct _intstk *intstk = 2183 (struct _intstk *)mech->chf$q_mch_esf_addr; 2184 2185 intstk->intstk$q_ipsr = excp_regs.psr.v; 2186} 2187 2188/* Do debugging. Report status to gdb and execute commands. */ 2189 2190static void 2191do_debug (struct chf$mech_array *mech) 2192{ 2193 struct _intstk *intstk = 2194 (struct _intstk *)mech->chf$q_mch_esf_addr; 2195 unsigned int old_ast; 2196 unsigned int old_sch; 2197 unsigned int status; 2198 2199 /* Disable ast. */ 2200 status = sys$setast (0); 2201 switch (status) 2202 { 2203 case SS$_WASCLR: 2204 old_ast = 0; 2205 break; 2206 case SS$_WASSET: 2207 old_ast = 1; 2208 break; 2209 default: 2210 /* Should never happen! */ 2211 lib$signal (status); 2212 } 2213 2214 /* Disable thread scheduling. */ 2215 if (has_threads) 2216 old_sch = set_thread_scheduling (0); 2217 2218 read_all_registers (mech); 2219 2220 /* Send stop reply packet. */ 2221 packet_status (); 2222 send_pkt (); 2223 2224 while (one_command () == 0) 2225 ; 2226 2227 write_all_registers (mech); 2228 2229 /* Re-enable scheduling. */ 2230 if (has_threads) 2231 set_thread_scheduling (old_sch); 2232 2233 /* Re-enable AST. */ 2234 status = sys$setast (old_ast); 2235 if (!(status & STS$M_SUCCESS)) 2236 LIB$SIGNAL (status); 2237} 2238 2239/* The condition handler. That's the core of the stub. */ 2240 2241static int 2242excp_handler (struct chf$signal_array *sig, 2243 struct chf$mech_array *mech) 2244{ 2245 struct chf64$signal_array *sig64 = 2246 (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr; 2247 unsigned int code = sig->chf$l_sig_name & STS$M_COND_ID; 2248 unsigned int cnt = sig64->chf64$w_sig_arg_count; 2249 unsigned __int64 pc; 2250 unsigned int ret; 2251 /* Self protection. FIXME: Should be per thread ? */ 2252 static int in_handler = 0; 2253 2254 /* Completely ignore some conditions (signaled indirectly by this stub). */ 2255 switch (code) 2256 { 2257 case LIB$_KEYNOTFOU & STS$M_COND_ID: 2258 return SS$_RESIGNAL_64; 2259 default: 2260 break; 2261 } 2262 2263 /* Protect against recursion. */ 2264 in_handler++; 2265 if (in_handler > 1) 2266 { 2267 if (in_handler == 2) 2268 TERM_FAO ("gdbstub: exception in handler (pc=!XH)!!!/", 2269 (&sig64->chf64$q_sig_name)[cnt - 2]); 2270 sys$exit (sig->chf$l_sig_name); 2271 } 2272 2273 pc = (&sig64->chf64$q_sig_name)[cnt - 2]; 2274 if (trace_excp) 2275 TERM_FAO ("excp_handler: code: !XL, pc=!XH!/", code, pc); 2276 2277 /* If break on the entry point, restore the bundle. */ 2278 if (code == (SS$_BREAK & STS$M_COND_ID) 2279 && pc == entry_pc 2280 && entry_pc != 0) 2281 { 2282 static unsigned int entry_prot; 2283 2284 if (trace_entry) 2285 term_puts ("initial entry breakpoint\n"); 2286 page_set_rw (entry_pc, 16, &entry_prot); 2287 2288 ots$move ((void *)entry_pc, 16, entry_saved); 2289 __fc (entry_pc); 2290 page_restore_rw (entry_pc, 16, entry_prot); 2291 } 2292 2293 switch (code) 2294 { 2295 case SS$_ACCVIO & STS$M_COND_ID: 2296 if (trace_excp <= 1) 2297 display_excp (sig64, mech); 2298 /* Fall through. */ 2299 case SS$_BREAK & STS$M_COND_ID: 2300 case SS$_OPCDEC & STS$M_COND_ID: 2301 case SS$_TBIT & STS$M_COND_ID: 2302 case SS$_DEBUG & STS$M_COND_ID: 2303 if (trace_excp > 1) 2304 { 2305 int i; 2306 struct _intstk *intstk = 2307 (struct _intstk *)mech->chf$q_mch_esf_addr; 2308 2309 display_excp (sig64, mech); 2310 2311 TERM_FAO (" intstk: !XH!/", intstk); 2312 for (i = 0; i < cnt + 1; i++) 2313 TERM_FAO (" !XH!/", ((unsigned __int64 *)sig64)[i]); 2314 } 2315 do_debug (mech); 2316 ret = SS$_CONTINUE_64; 2317 break; 2318 2319 default: 2320 display_excp (sig64, mech); 2321 ret = SS$_RESIGNAL_64; 2322 break; 2323 } 2324 2325 in_handler--; 2326 /* Discard selected thread registers. */ 2327 sel_regs_pthread = 0; 2328 return ret; 2329} 2330 2331/* Setup internal trace flags according to GDBSTUB$TRACE logical. */ 2332 2333static void 2334trace_init (void) 2335{ 2336 unsigned int status, i, start; 2337 unsigned short len; 2338 char resstring[LNM$C_NAMLENGTH]; 2339 static const $DESCRIPTOR (tabdesc, "LNM$DCL_LOGICAL"); 2340 static const $DESCRIPTOR (logdesc, "GDBSTUB$TRACE"); 2341 $DESCRIPTOR (sub_desc, resstring); 2342 ILE3 item_lst[2]; 2343 2344 item_lst[0].ile3$w_length = LNM$C_NAMLENGTH; 2345 item_lst[0].ile3$w_code = LNM$_STRING; 2346 item_lst[0].ile3$ps_bufaddr = resstring; 2347 item_lst[0].ile3$ps_retlen_addr = &len; 2348 item_lst[1].ile3$w_length = 0; 2349 item_lst[1].ile3$w_code = 0; 2350 2351 /* Translate the logical name. */ 2352 status = SYS$TRNLNM (0, /* Attributes of the logical name. */ 2353 (void *)&tabdesc, /* Logical name table. */ 2354 (void *)&logdesc, /* Logical name. */ 2355 0, /* Access mode. */ 2356 &item_lst); /* Item list. */ 2357 if (status == SS$_NOLOGNAM) 2358 return; 2359 if (!(status & STS$M_SUCCESS)) 2360 LIB$SIGNAL (status); 2361 2362 start = 0; 2363 for (i = 0; i <= len; i++) 2364 { 2365 if ((i == len || resstring[i] == ',' || resstring[i] == ';') 2366 && i != start) 2367 { 2368 int j; 2369 2370 sub_desc.dsc$a_pointer = resstring + start; 2371 sub_desc.dsc$w_length = i - start; 2372 2373 for (j = 0; j < NBR_DEBUG_FLAGS; j++) 2374 if (str$case_blind_compare (&sub_desc, 2375 (void *)&debug_flags[j].name) == 0) 2376 { 2377 debug_flags[j].val++; 2378 break; 2379 } 2380 if (j == NBR_DEBUG_FLAGS) 2381 TERM_FAO ("GDBSTUB$TRACE: unknown directive !AS!/", &sub_desc); 2382 2383 start = i + 1; 2384 } 2385 } 2386 2387 TERM_FAO ("GDBSTUB$TRACE=!AD ->", len, resstring); 2388 for (i = 0; i < NBR_DEBUG_FLAGS; i++) 2389 if (debug_flags[i].val > 0) 2390 TERM_FAO (" !AS=!ZL", &debug_flags[i].name, debug_flags[i].val); 2391 term_putnl (); 2392} 2393 2394 2395/* Entry point. */ 2396 2397static int 2398stub_start (unsigned __int64 *progxfer, void *cli_util, 2399 EIHD *imghdr, IFD *imgfile, 2400 unsigned int linkflag, unsigned int cliflag) 2401{ 2402 static int initialized; 2403 int i; 2404 int cnt; 2405 int is_attached; 2406 IMCB *imcb; 2407 if (initialized) 2408 term_puts ("gdbstub: re-entry\n"); 2409 else 2410 initialized = 1; 2411 2412 /* When attached (through SS$_DEBUG condition), the number of arguments 2413 is 4 and PROGXFER is the PC at interruption. */ 2414 va_count (cnt); 2415 is_attached = cnt == 4; 2416 2417 term_init (); 2418 2419 /* Hello banner. */ 2420 term_puts ("Hello from gdb stub\n"); 2421 2422 trace_init (); 2423 2424 if (trace_entry && !is_attached) 2425 { 2426 TERM_FAO ("xfer: !XH, imghdr: !XH, ifd: !XH!/", 2427 progxfer, imghdr, imgfile); 2428 for (i = -2; i < 8; i++) 2429 TERM_FAO (" at !2SW: !XH!/", i, progxfer[i]); 2430 } 2431 2432 /* Search for entry point. */ 2433 if (!is_attached) 2434 { 2435 entry_pc = 0; 2436 for (i = 0; progxfer[i]; i++) 2437 entry_pc = progxfer[i]; 2438 2439 if (trace_entry) 2440 { 2441 if (entry_pc == 0) 2442 { 2443 term_puts ("No entry point\n"); 2444 return 0; 2445 } 2446 else 2447 TERM_FAO ("Entry: !XH!/",entry_pc); 2448 } 2449 } 2450 else 2451 entry_pc = progxfer[0]; 2452 2453 has_threads = 0; 2454 for (imcb = ctl$gl_imglstptr->imcb$l_flink; 2455 imcb != ctl$gl_imglstptr; 2456 imcb = imcb->imcb$l_flink) 2457 { 2458 if (ots$strcmp_eql (pthread_rtl_desc.dsc$a_pointer, 2459 pthread_rtl_desc.dsc$w_length, 2460 imcb->imcb$t_log_image_name + 1, 2461 imcb->imcb$t_log_image_name[0])) 2462 has_threads = 1; 2463 2464 if (trace_images) 2465 { 2466 unsigned int j; 2467 LDRIMG *ldrimg = imcb->imcb$l_ldrimg; 2468 LDRISD *ldrisd; 2469 2470 TERM_FAO ("!XA-!XA ", 2471 imcb->imcb$l_starting_address, 2472 imcb->imcb$l_end_address); 2473 2474 switch (imcb->imcb$b_act_code) 2475 { 2476 case IMCB$K_MAIN_PROGRAM: 2477 term_puts ("prog"); 2478 break; 2479 case IMCB$K_MERGED_IMAGE: 2480 term_puts ("mrge"); 2481 break; 2482 case IMCB$K_GLOBAL_IMAGE_SECTION: 2483 term_puts ("glob"); 2484 break; 2485 default: 2486 term_puts ("????"); 2487 } 2488 TERM_FAO (" !AD !40AC!/", 2489 1, "KESU" + (imcb->imcb$b_access_mode & 3), 2490 imcb->imcb$t_log_image_name); 2491 2492 if ((long) ldrimg < 0 || trace_images < 2) 2493 continue; 2494 ldrisd = ldrimg->ldrimg$l_segments; 2495 for (j = 0; j < ldrimg->ldrimg$l_segcount; j++) 2496 { 2497 unsigned int flags = ldrisd[j].ldrisd$i_flags; 2498 term_puts (" "); 2499 term_putc (flags & 0x04 ? 'R' : '-'); 2500 term_putc (flags & 0x02 ? 'W' : '-'); 2501 term_putc (flags & 0x01 ? 'X' : '-'); 2502 term_puts (flags & 0x01000000 ? " Prot" : " "); 2503 term_puts (flags & 0x04000000 ? " Shrt" : " "); 2504 term_puts (flags & 0x08000000 ? " Shrd" : " "); 2505 TERM_FAO (" !XA-!XA!/", 2506 ldrisd[j].ldrisd$p_base, 2507 (unsigned __int64) ldrisd[j].ldrisd$p_base 2508 + ldrisd[j].ldrisd$i_len - 1); 2509 } 2510 ldrisd = ldrimg->ldrimg$l_dyn_seg; 2511 if (ldrisd) 2512 TERM_FAO (" dynamic !XA-!XA!/", 2513 ldrisd->ldrisd$p_base, 2514 (unsigned __int64) ldrisd->ldrisd$p_base 2515 + ldrisd->ldrisd$i_len - 1); 2516 } 2517 } 2518 2519 if (has_threads) 2520 threads_init (); 2521 2522 /* Wait for connection. */ 2523 sock_init (); 2524 2525 /* Set primary exception vector. */ 2526 { 2527 unsigned int status; 2528 status = sys$setexv (0, excp_handler, PSL$C_USER, (__void_ptr32) &prevhnd); 2529 if (!(status & STS$M_SUCCESS)) 2530 LIB$SIGNAL (status); 2531 } 2532 2533 if (is_attached) 2534 { 2535 return excp_handler ((struct chf$signal_array *) progxfer[2], 2536 (struct chf$mech_array *) progxfer[3]); 2537 } 2538 2539 /* Change first instruction to set a breakpoint. */ 2540 { 2541 /* 2542 01 08 00 40 00 00 [MII] break.m 0x80001 2543 00 00 00 02 00 00 nop.i 0x0 2544 00 00 04 00 nop.i 0x0;; 2545 */ 2546 static const unsigned char initbp[16] = 2547 { 0x01, 0x08, 0x00, 0x40, 0x00, 0x00, 2548 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 2549 0x00, 0x00, 0x04, 0x00 }; 2550 unsigned int entry_prot; 2551 unsigned int status; 2552 2553 status = page_set_rw (entry_pc, 16, &entry_prot); 2554 2555 if (!(status & STS$M_SUCCESS)) 2556 { 2557 if ((status & STS$M_COND_ID) == (SS$_NOT_PROCESS_VA & STS$M_COND_ID)) 2558 { 2559 /* Cannot write here. This can happen when pthreads are 2560 used. */ 2561 entry_pc = 0; 2562 term_puts ("gdbstub: cannot set breakpoint on entry\n"); 2563 } 2564 else 2565 LIB$SIGNAL (status); 2566 } 2567 2568 if (entry_pc != 0) 2569 { 2570 ots$move (entry_saved, 16, (void *)entry_pc); 2571 ots$move ((void *)entry_pc, 16, (void *)initbp); 2572 __fc (entry_pc); 2573 page_restore_rw (entry_pc, 16, entry_prot); 2574 } 2575 } 2576 2577 /* If it wasn't possible to set a breakpoint on the entry point, 2578 accept gdb commands now. Note that registers are not updated. */ 2579 if (entry_pc == 0) 2580 { 2581 while (one_command () == 0) 2582 ; 2583 } 2584 2585 /* We will see! */ 2586 return SS$_CONTINUE; 2587} 2588 2589/* Declare the entry point of this relocatable module. */ 2590 2591struct xfer_vector 2592{ 2593 __int64 impure_start; 2594 __int64 impure_end; 2595 int (*entry) (); 2596}; 2597 2598#pragma __extern_model save 2599#pragma __extern_model strict_refdef "XFER_PSECT" 2600struct xfer_vector xfer_vector = {0, 0, stub_start}; 2601#pragma __extern_model restore 2602