1 /* GDB stub for Itanium OpenVMS
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
4 Contributed by Tristan Gingold, AdaCore.
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.
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.
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/>. */
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.
24 This is currently a partial implementation. In particular, modifying
25 registers is currently not implemented, as well as inferior procedure
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.
32 #if __INITIAL_POINTER_SIZE != 64
33 #error "Must be compiled with 64 bit pointers"
36 #define __NEW_STARLET 1
46 #include <tcpip$inetdef.h>
48 #include <lib$routines.h>
49 #include <ots$routines.h>
50 #include <str$routines.h>
62 #include <lib_c/imcbdef.h>
63 #include <lib_c/ldrimgdef.h>
64 #include <lib_c/intstkdef.h>
65 #include <lib_c/psrdef.h>
66 #include <lib_c/ifddef.h>
67 #include <lib_c/eihddef.h>
70 #include <pthread_debug.h>
72 #define VMS_PAGE_SIZE 0x2000
73 #define VMS_PAGE_MASK (VMS_PAGE_SIZE - 1)
75 /* Declared in lib$ots. */
76 extern void ots$fill (void *addr, size_t len, unsigned char b);
77 extern void ots$move (void *dst, size_t len, const void *src);
78 extern int ots$strcmp_eql (const void *str1, size_t str1len,
79 const void *str2, size_t str2len);
81 /* Stub port number. */
82 static unsigned int serv_port = 1234;
84 /* DBGEXT structure. Not declared in any header. */
85 struct dbgext_control_block
87 unsigned short dbgext$w_function_code;
88 #define DBGEXT$K_NEXT_TASK 3
89 #define DBGEXT$K_STOP_ALL_OTHER_TASKS 31
90 #define DBGEXT$K_GET_REGS 33
91 unsigned short dbgext$w_facility_id;
92 #define CMA$_FACILITY 64
93 unsigned int dbgext$l_status;
94 unsigned int dbgext$l_flags;
95 unsigned int dbgext$l_print_routine;
96 unsigned int dbgext$l_evnt_code;
97 unsigned int dbgext$l_evnt_name;
98 unsigned int dbgext$l_evnt_entry;
99 unsigned int dbgext$l_task_value;
100 unsigned int dbgext$l_task_number;
101 unsigned int dbgext$l_ada_flags;
102 unsigned int dbgext$l_stop_value;
103 #define dbgext$l_priority dbgext$l_stop_value;
104 #define dbgext$l_symb_addr dbgext$l_stop_value;
105 #define dbgext$l_time_slice dbgext$l_stop_value;
106 unsigned int dbgext$l_active_registers;
109 #pragma pointer_size save
110 #pragma pointer_size 32
112 /* Pthread handler. */
113 static int (*dbgext_func) (struct dbgext_control_block *blk);
115 #pragma pointer_size restore
117 /* Set to 1 if thread-aware. */
118 static int has_threads;
120 /* Current thread. */
121 static pthread_t selected_thread;
122 static pthreadDebugId_t selected_id;
124 /* Internal debugging flags. */
127 /* Name of the flag (as a string descriptor). */
128 const struct dsc$descriptor_s name;
133 /* Macro to define a debugging flag. */
134 #define DEBUG_FLAG_ENTRY(str) \
135 { { sizeof (str) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, str }, 0}
137 static struct debug_flag debug_flags[] =
139 /* Disp packets exchanged with gdb. */
140 DEBUG_FLAG_ENTRY("packets"),
141 #define trace_pkt (debug_flags[0].val)
142 /* Display entry point informations. */
143 DEBUG_FLAG_ENTRY("entry"),
144 #define trace_entry (debug_flags[1].val)
145 /* Be verbose about exceptions. */
146 DEBUG_FLAG_ENTRY("excp"),
147 #define trace_excp (debug_flags[2].val)
148 /* Be verbose about unwinding. */
149 DEBUG_FLAG_ENTRY("unwind"),
150 #define trace_unwind (debug_flags[3].val)
151 /* Display image at startup. */
152 DEBUG_FLAG_ENTRY("images"),
153 #define trace_images (debug_flags[4].val)
154 /* Display pthread_debug info. */
155 DEBUG_FLAG_ENTRY("pthreaddbg")
156 #define trace_pthreaddbg (debug_flags[5].val)
159 #define NBR_DEBUG_FLAGS (sizeof (debug_flags) / sizeof (debug_flags[0]))
161 /* Connect inet device I/O channel. */
162 static unsigned short conn_channel;
164 /* Widely used hex digit to ascii. */
165 static const char hex[] = "0123456789abcdef";
167 /* Socket characteristics. Apparently, there are no declaration for it in
176 /* Chain of images loaded. */
177 extern IMCB* ctl$gl_imglstptr;
179 /* IA64 integer register representation. */
186 /* IA64 register numbers, as defined by ia64-tdep.h. */
187 #define IA64_GR0_REGNUM 0
188 #define IA64_GR32_REGNUM (IA64_GR0_REGNUM + 32)
190 /* Floating point registers; 128 82-bit wide registers. */
191 #define IA64_FR0_REGNUM 128
193 /* Predicate registers; There are 64 of these one bit registers. It'd
194 be more convenient (implementation-wise) to use a single 64 bit
195 word with all of these register in them. Note that there's also a
196 IA64_PR_REGNUM below which contains all the bits and is used for
197 communicating the actual values to the target. */
198 #define IA64_PR0_REGNUM 256
200 /* Branch registers: 8 64-bit registers for holding branch targets. */
201 #define IA64_BR0_REGNUM 320
203 /* Virtual frame pointer; this matches IA64_FRAME_POINTER_REGNUM in
204 gcc/config/ia64/ia64.h. */
205 #define IA64_VFP_REGNUM 328
207 /* Virtual return address pointer; this matches
208 IA64_RETURN_ADDRESS_POINTER_REGNUM in gcc/config/ia64/ia64.h. */
209 #define IA64_VRAP_REGNUM 329
211 /* Predicate registers: There are 64 of these 1-bit registers. We
212 define a single register which is used to communicate these values
213 to/from the target. We will somehow contrive to make it appear
214 that IA64_PR0_REGNUM thru IA64_PR63_REGNUM hold the actual values. */
215 #define IA64_PR_REGNUM 330
217 /* Instruction pointer: 64 bits wide. */
218 #define IA64_IP_REGNUM 331
220 /* Process Status Register. */
221 #define IA64_PSR_REGNUM 332
223 /* Current Frame Marker (raw form may be the cr.ifs). */
224 #define IA64_CFM_REGNUM 333
226 /* Application registers; 128 64-bit wide registers possible, but some
227 of them are reserved. */
228 #define IA64_AR0_REGNUM 334
229 #define IA64_KR0_REGNUM (IA64_AR0_REGNUM + 0)
230 #define IA64_KR7_REGNUM (IA64_KR0_REGNUM + 7)
232 #define IA64_RSC_REGNUM (IA64_AR0_REGNUM + 16)
233 #define IA64_BSP_REGNUM (IA64_AR0_REGNUM + 17)
234 #define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM + 18)
235 #define IA64_RNAT_REGNUM (IA64_AR0_REGNUM + 19)
236 #define IA64_FCR_REGNUM (IA64_AR0_REGNUM + 21)
237 #define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM + 24)
238 #define IA64_CSD_REGNUM (IA64_AR0_REGNUM + 25)
239 #define IA64_SSD_REGNUM (IA64_AR0_REGNUM + 26)
240 #define IA64_CFLG_REGNUM (IA64_AR0_REGNUM + 27)
241 #define IA64_FSR_REGNUM (IA64_AR0_REGNUM + 28)
242 #define IA64_FIR_REGNUM (IA64_AR0_REGNUM + 29)
243 #define IA64_FDR_REGNUM (IA64_AR0_REGNUM + 30)
244 #define IA64_CCV_REGNUM (IA64_AR0_REGNUM + 32)
245 #define IA64_UNAT_REGNUM (IA64_AR0_REGNUM + 36)
246 #define IA64_FPSR_REGNUM (IA64_AR0_REGNUM + 40)
247 #define IA64_ITC_REGNUM (IA64_AR0_REGNUM + 44)
248 #define IA64_PFS_REGNUM (IA64_AR0_REGNUM + 64)
249 #define IA64_LC_REGNUM (IA64_AR0_REGNUM + 65)
250 #define IA64_EC_REGNUM (IA64_AR0_REGNUM + 66)
252 /* NAT (Not A Thing) Bits for the general registers; there are 128 of
254 #define IA64_NAT0_REGNUM 462
256 /* Process registers when a condition is caught. */
259 union ia64_ireg gr[32];
260 union ia64_ireg br[8];
269 static struct ia64_all_regs excp_regs;
270 static struct ia64_all_regs sel_regs;
271 static pthread_t sel_regs_pthread;
273 /* IO channel for the terminal. */
274 static unsigned short term_chan;
276 /* Output buffer and length. */
277 static char term_buf[128];
278 static int term_buf_len;
280 /* Buffer for communication with gdb. */
281 static unsigned char gdb_buf[sizeof (struct ia64_all_regs) * 2 + 64];
282 static unsigned int gdb_blen;
284 /* Previous primary handler. */
285 static void *prevhnd;
287 /* Entry point address and bundle. */
288 static unsigned __int64 entry_pc;
289 static unsigned char entry_saved[16];
291 /* Write on the terminal. */
294 term_raw_write (const char *str, unsigned int len)
296 unsigned short status;
299 status = sys$qiow (EFN$C_ENF, /* Event flag. */
300 term_chan, /* I/O channel. */
301 IO$_WRITEVBLK, /* I/O function code. */
302 &iosb, /* I/O status block. */
303 0, /* Ast service routine. */
304 0, /* Ast parameter. */
305 (char *)str, /* P1 - buffer address. */
306 len, /* P2 - buffer length. */
309 if (status & STS$M_SUCCESS)
310 status = iosb.iosb$w_status;
311 if (!(status & STS$M_SUCCESS))
315 /* Flush ther term buffer. */
320 if (term_buf_len != 0)
322 term_raw_write (term_buf, term_buf_len);
327 /* Write a single character, without translation. */
330 term_raw_putchar (char c)
332 if (term_buf_len == sizeof (term_buf))
334 term_buf[term_buf_len++] = c;
337 /* Write character C. Translate '\n' to '\n\r'. */
352 term_raw_putchar (c);
355 term_raw_putchar ('\r');
360 /* Write a C string. */
363 term_puts (const char *str)
369 /* Write LEN bytes from STR. */
372 term_write (const char *str, unsigned int len)
374 for (; len > 0; len--)
378 /* Write using FAO formatting. */
381 term_fao (const char *str, unsigned int str_len, ...)
388 struct dsc$descriptor_s dstr =
389 { str_len, DSC$K_DTYPE_T, DSC$K_CLASS_S, (__char_ptr32)str };
391 $DESCRIPTOR (buf_desc, buf);
393 va_start (vargs, str_len);
395 args = (__int64 *) __ALLOCA (cnt * sizeof (__int64));
397 for (i = 0; i < cnt; i++)
398 args[i] = va_arg (vargs, __int64);
400 status = sys$faol_64 (&dstr, &buf_desc.dsc$w_length, &buf_desc, args);
403 /* FAO !/ already insert a line feed. */
404 for (i = 0; i < buf_desc.dsc$w_length; i++)
406 term_raw_putchar (buf[i]);
415 #define TERM_FAO(STR, ...) term_fao (STR, sizeof (STR) - 1, __VA_ARGS__)
425 /* Initialize terminal. */
430 unsigned int status,i;
432 char resstring[LNM$C_NAMLENGTH];
433 static const $DESCRIPTOR (tabdesc, "LNM$FILE_DEV");
434 static const $DESCRIPTOR (logdesc, "SYS$OUTPUT");
435 $DESCRIPTOR (term_desc, resstring);
438 item_lst[0].ile3$w_length = LNM$C_NAMLENGTH;
439 item_lst[0].ile3$w_code = LNM$_STRING;
440 item_lst[0].ile3$ps_bufaddr = resstring;
441 item_lst[0].ile3$ps_retlen_addr = &len;
442 item_lst[1].ile3$w_length = 0;
443 item_lst[1].ile3$w_code = 0;
445 /* Translate the logical name. */
446 status = SYS$TRNLNM (0, /* Attr of the logical name. */
447 (void *) &tabdesc, /* Logical name table. */
448 (void *) &logdesc, /* Logical name. */
449 0, /* Access mode. */
450 item_lst); /* Item list. */
451 if (!(status & STS$M_SUCCESS))
454 term_desc.dsc$w_length = len;
456 /* Examine 4-byte header. Skip escape sequence. */
457 if (resstring[0] == 0x1B)
459 term_desc.dsc$w_length -= 4;
460 term_desc.dsc$a_pointer += 4;
463 /* Assign a channel. */
464 status = sys$assign (&term_desc, /* Device name. */
465 &term_chan, /* I/O channel. */
466 0, /* Access mode. */
468 if (!(status & STS$M_SUCCESS))
472 /* Convert from native endianness to network endianness (and vice-versa). */
475 wordswap (unsigned int v)
477 return ((v & 0xff) << 8) | ((v >> 8) & 0xff);
480 /* Initialize the socket connection, and wait for a client. */
488 /* Listen channel and characteristics. */
489 unsigned short listen_channel;
490 struct sockchar listen_sockchar;
492 /* Client address. */
493 unsigned short cli_addrlen;
494 struct sockaddr_in cli_addr;
498 struct sockaddr_in serv_addr;
501 /* Reuseaddr option value (on). */
503 ILE2 sockopt_itemlst;
504 ILE2 reuseaddr_itemlst;
506 /* TCP/IP network pseudodevice. */
507 static const $DESCRIPTOR (inet_device, "TCPIP$DEVICE:");
509 /* Initialize socket characteristics. */
510 listen_sockchar.prot = TCPIP$C_TCP;
511 listen_sockchar.type = TCPIP$C_STREAM;
512 listen_sockchar.af = TCPIP$C_AF_INET;
514 /* Assign I/O channels to network device. */
515 status = sys$assign ((void *) &inet_device, &listen_channel, 0, 0);
516 if (status & STS$M_SUCCESS)
517 status = sys$assign ((void *) &inet_device, &conn_channel, 0, 0);
518 if (!(status & STS$M_SUCCESS))
520 term_puts ("Failed to assign I/O channel(s)\n");
524 /* Create a listen socket. */
525 status = sys$qiow (EFN$C_ENF, /* Event flag. */
526 listen_channel, /* I/O channel. */
527 IO$_SETMODE, /* I/O function code. */
528 &iosb, /* I/O status block. */
529 0, /* Ast service routine. */
530 0, /* Ast parameter. */
531 &listen_sockchar, /* P1 - socket characteristics. */
533 if (status & STS$M_SUCCESS)
534 status = iosb.iosb$w_status;
535 if (!(status & STS$M_SUCCESS))
537 term_puts ("Failed to create socket\n");
541 /* Set reuse address option. */
542 /* Initialize reuseaddr's item-list element. */
543 reuseaddr_itemlst.ile2$w_length = sizeof (optval);
544 reuseaddr_itemlst.ile2$w_code = TCPIP$C_REUSEADDR;
545 reuseaddr_itemlst.ile2$ps_bufaddr = &optval;
547 /* Initialize setsockopt's item-list descriptor. */
548 sockopt_itemlst.ile2$w_length = sizeof (reuseaddr_itemlst);
549 sockopt_itemlst.ile2$w_code = TCPIP$C_SOCKOPT;
550 sockopt_itemlst.ile2$ps_bufaddr = &reuseaddr_itemlst;
552 status = sys$qiow (EFN$C_ENF, /* Event flag. */
553 listen_channel, /* I/O channel. */
554 IO$_SETMODE, /* I/O function code. */
555 &iosb, /* I/O status block. */
556 0, /* Ast service routine. */
557 0, /* Ast parameter. */
562 (__int64) &sockopt_itemlst, /* P5 - socket options. */
564 if (status & STS$M_SUCCESS)
565 status = iosb.iosb$w_status;
566 if (!(status & STS$M_SUCCESS))
568 term_puts ("Failed to set socket option\n");
572 /* Bind server's ip address and port number to listen socket. */
573 /* Initialize server's socket address structure. */
574 ots$fill (&serv_addr, sizeof (serv_addr), 0);
575 serv_addr.sin_family = TCPIP$C_AF_INET;
576 serv_addr.sin_port = wordswap (serv_port);
577 serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;
579 /* Initialize server's item-list descriptor. */
580 serv_itemlst.ile2$w_length = sizeof (serv_addr);
581 serv_itemlst.ile2$w_code = TCPIP$C_SOCK_NAME;
582 serv_itemlst.ile2$ps_bufaddr = &serv_addr;
584 status = sys$qiow (EFN$C_ENF, /* Event flag. */
585 listen_channel, /* I/O channel. */
586 IO$_SETMODE, /* I/O function code. */
587 &iosb, /* I/O status block. */
588 0, /* Ast service routine. */
589 0, /* Ast parameter. */
592 (__int64) &serv_itemlst, /* P3 - local socket name. */
594 if (status & STS$M_SUCCESS)
595 status = iosb.iosb$w_status;
596 if (!(status & STS$M_SUCCESS))
598 term_puts ("Failed to bind socket\n");
602 /* Set socket as a listen socket. */
603 status = sys$qiow (EFN$C_ENF, /* Event flag. */
604 listen_channel, /* I/O channel. */
605 IO$_SETMODE, /* I/O function code. */
606 &iosb, /* I/O status block. */
607 0, /* Ast service routine. */
608 0, /* Ast parameter. */
612 1, /* P4 - connection backlog. */
614 if (status & STS$M_SUCCESS)
615 status = iosb.iosb$w_status;
616 if (!(status & STS$M_SUCCESS))
618 term_puts ("Failed to set socket passive\n");
622 /* Accept connection from a client. */
623 TERM_FAO ("Waiting for a client connection on port: !ZW!/",
624 wordswap (serv_addr.sin_port));
626 status = sys$qiow (EFN$C_ENF, /* Event flag. */
627 listen_channel, /* I/O channel. */
628 IO$_ACCESS|IO$M_ACCEPT, /* I/O function code. */
629 &iosb, /* I/O status block. */
630 0, /* Ast service routine. */
631 0, /* Ast parameter. */
635 (__int64) &conn_channel, /* P4 - I/O channel for conn. */
638 if (status & STS$M_SUCCESS)
639 status = iosb.iosb$w_status;
640 if (!(status & STS$M_SUCCESS))
642 term_puts ("Failed to accept client connection\n");
646 /* Log client connection request. */
647 cli_itemlst.ile3$w_length = sizeof (cli_addr);
648 cli_itemlst.ile3$w_code = TCPIP$C_SOCK_NAME;
649 cli_itemlst.ile3$ps_bufaddr = &cli_addr;
650 cli_itemlst.ile3$ps_retlen_addr = &cli_addrlen;
651 ots$fill (&cli_addr, sizeof(cli_addr), 0);
652 status = sys$qiow (EFN$C_ENF, /* Event flag. */
653 conn_channel, /* I/O channel. */
654 IO$_SENSEMODE, /* I/O function code. */
655 &iosb, /* I/O status block. */
656 0, /* Ast service routine. */
657 0, /* Ast parameter. */
661 (__int64) &cli_itemlst, /* P4 - peer socket name. */
663 if (status & STS$M_SUCCESS)
664 status = iosb.iosb$w_status;
665 if (!(status & STS$M_SUCCESS))
667 term_puts ("Failed to get client name\n");
671 TERM_FAO ("Accepted connection from host: !UB.!UB,!UB.!UB, port: !UW!/",
672 (cli_addr.sin_addr.s_addr >> 0) & 0xff,
673 (cli_addr.sin_addr.s_addr >> 8) & 0xff,
674 (cli_addr.sin_addr.s_addr >> 16) & 0xff,
675 (cli_addr.sin_addr.s_addr >> 24) & 0xff,
676 wordswap (cli_addr.sin_port));
679 /* Close the socket. */
688 status = sys$qiow (EFN$C_ENF, /* Event flag. */
689 conn_channel, /* I/O channel. */
690 IO$_DEACCESS, /* I/O function code. */
691 &iosb, /* I/O status block. */
692 0, /* Ast service routine. */
693 0, /* Ast parameter. */
696 if (status & STS$M_SUCCESS)
697 status = iosb.iosb$w_status;
698 if (!(status & STS$M_SUCCESS))
700 term_puts ("Failed to close socket\n");
704 /* Deassign I/O channel to network device. */
705 status = sys$dassgn (conn_channel);
707 if (!(status & STS$M_SUCCESS))
709 term_puts ("Failed to deassign I/O channel\n");
714 /* Mark a page as R/W. Return old rights. */
717 page_set_rw (unsigned __int64 startva, unsigned __int64 len,
718 unsigned int *oldprot)
721 unsigned __int64 retva;
722 unsigned __int64 retlen;
724 status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, PRT$C_UW,
725 (void *)&retva, &retlen, oldprot);
729 /* Restore page rights. */
732 page_restore_rw (unsigned __int64 startva, unsigned __int64 len,
736 unsigned __int64 retva;
737 unsigned __int64 retlen;
738 unsigned int oldprot;
740 status = SYS$SETPRT_64 ((void *)startva, len, PSL$C_USER, prot,
741 (void *)&retva, &retlen, &oldprot);
742 if (!(status & STS$M_SUCCESS))
746 /* Get the TEB (thread environment block). */
751 return (pthread_t)__getReg (_IA64_REG_TP);
754 /* Enable thread scheduling if VAL is true. */
757 set_thread_scheduling (int val)
759 struct dbgext_control_block blk;
765 blk.dbgext$w_function_code = DBGEXT$K_STOP_ALL_OTHER_TASKS;
766 blk.dbgext$w_facility_id = CMA$_FACILITY;
767 blk.dbgext$l_stop_value = val;
769 status = dbgext_func (&blk);
770 if (!(status & STS$M_SUCCESS))
772 TERM_FAO ("set_thread_scheduling error, val=!SL, status=!XL!/",
773 val, blk.dbgext$l_status);
777 return blk.dbgext$l_stop_value;
780 /* Get next thead (after THR). Start with 0. */
783 thread_next (unsigned int thr)
785 struct dbgext_control_block blk;
791 blk.dbgext$w_function_code = DBGEXT$K_NEXT_TASK;
792 blk.dbgext$w_facility_id = CMA$_FACILITY;
793 blk.dbgext$l_ada_flags = 0;
794 blk.dbgext$l_task_value = thr;
796 status = dbgext_func (&blk);
797 if (!(status & STS$M_SUCCESS))
800 return blk.dbgext$l_task_value;
803 /* Pthread Debug callbacks. */
806 read_callback (pthreadDebugClient_t context,
807 pthreadDebugTargetAddr_t addr,
808 pthreadDebugAddr_t buf,
811 if (trace_pthreaddbg)
812 TERM_FAO ("read_callback (!XH, !XH, !SL)!/", addr, buf, size);
813 ots$move (buf, size, addr);
818 write_callback (pthreadDebugClient_t context,
819 pthreadDebugTargetAddr_t addr,
820 pthreadDebugLongConstAddr_t buf,
823 if (trace_pthreaddbg)
824 TERM_FAO ("write_callback (!XH, !XH, !SL)!/", addr, buf, size);
825 ots$move (addr, size, buf);
830 suspend_callback (pthreadDebugClient_t context)
832 /* Always suspended. */
837 resume_callback (pthreadDebugClient_t context)
839 /* So no need to resume. */
844 kthdinfo_callback (pthreadDebugClient_t context,
845 pthreadDebugKId_t kid,
846 pthreadDebugKThreadInfo_p thread_info)
848 if (trace_pthreaddbg)
849 term_puts ("kthinfo_callback");
854 hold_callback (pthreadDebugClient_t context,
855 pthreadDebugKId_t kid)
857 if (trace_pthreaddbg)
858 term_puts ("hold_callback");
863 unhold_callback (pthreadDebugClient_t context,
864 pthreadDebugKId_t kid)
866 if (trace_pthreaddbg)
867 term_puts ("unhold_callback");
872 getfreg_callback (pthreadDebugClient_t context,
873 pthreadDebugFregs_t *reg,
874 pthreadDebugKId_t kid)
876 if (trace_pthreaddbg)
877 term_puts ("getfreg_callback");
882 setfreg_callback (pthreadDebugClient_t context,
883 const pthreadDebugFregs_t *reg,
884 pthreadDebugKId_t kid)
886 if (trace_pthreaddbg)
887 term_puts ("setfreg_callback");
892 getreg_callback (pthreadDebugClient_t context,
893 pthreadDebugRegs_t *reg,
894 pthreadDebugKId_t kid)
896 if (trace_pthreaddbg)
897 term_puts ("getreg_callback");
902 setreg_callback (pthreadDebugClient_t context,
903 const pthreadDebugRegs_t *reg,
904 pthreadDebugKId_t kid)
906 if (trace_pthreaddbg)
907 term_puts ("setreg_callback");
912 output_callback (pthreadDebugClient_t context,
913 pthreadDebugConstString_t line)
921 error_callback (pthreadDebugClient_t context,
922 pthreadDebugConstString_t line)
929 static pthreadDebugAddr_t
930 malloc_callback (pthreadDebugClient_t caller_context, size_t size)
937 status = lib$get_vm (&len, &res, 0);
938 if (!(status & STS$M_SUCCESS))
940 if (trace_pthreaddbg)
941 TERM_FAO ("malloc_callback (!UL) -> !XA!/", size, res);
942 *(unsigned int *)res = len;
943 return (char *)res + 16;
947 free_callback (pthreadDebugClient_t caller_context, pthreadDebugAddr_t address)
953 res = (unsigned int)address - 16;
954 len = *(unsigned int *)res;
955 if (trace_pthreaddbg)
956 TERM_FAO ("free_callback (!XA)!/", address);
957 status = lib$free_vm (&len, &res, 0);
958 if (!(status & STS$M_SUCCESS))
963 speckthd_callback (pthreadDebugClient_t caller_context,
964 pthreadDebugSpecialType_t type,
965 pthreadDebugKId_t *kernel_tid)
970 static pthreadDebugCallbacks_t pthread_debug_callbacks = {
971 PTHREAD_DEBUG_VERSION,
990 /* Name of the pthread shared library. */
991 static const $DESCRIPTOR (pthread_rtl_desc, "PTHREAD$RTL");
993 /* List of symbols to extract from pthread debug library. */
994 struct pthread_debug_entry
996 const unsigned int namelen;
997 const __char_ptr32 name;
1001 #define DEBUG_ENTRY(str) { sizeof(str) - 1, str, 0 }
1003 static struct pthread_debug_entry pthread_debug_entries[] = {
1004 DEBUG_ENTRY("pthreadDebugContextInit"),
1005 DEBUG_ENTRY("pthreadDebugThdSeqInit"),
1006 DEBUG_ENTRY("pthreadDebugThdSeqNext"),
1007 DEBUG_ENTRY("pthreadDebugThdSeqDestroy"),
1008 DEBUG_ENTRY("pthreadDebugThdGetInfo"),
1009 DEBUG_ENTRY("pthreadDebugThdGetInfoAddr"),
1010 DEBUG_ENTRY("pthreadDebugThdGetReg"),
1011 DEBUG_ENTRY("pthreadDebugCmd")
1014 /* Pthread debug context. */
1015 static pthreadDebugContext_t debug_context;
1017 /* Wrapper around pthread debug entry points. */
1020 pthread_debug_thd_seq_init (pthreadDebugId_t *id)
1022 return ((int (*)())pthread_debug_entries[1].func)
1023 (debug_context, id);
1027 pthread_debug_thd_seq_next (pthreadDebugId_t *id)
1029 return ((int (*)())pthread_debug_entries[2].func)
1030 (debug_context, id);
1034 pthread_debug_thd_seq_destroy (void)
1036 return ((int (*)())pthread_debug_entries[3].func)
1041 pthread_debug_thd_get_info (pthreadDebugId_t id,
1042 pthreadDebugThreadInfo_t *info)
1044 return ((int (*)())pthread_debug_entries[4].func)
1045 (debug_context, id, info);
1049 pthread_debug_thd_get_info_addr (pthread_t thr,
1050 pthreadDebugThreadInfo_t *info)
1052 return ((int (*)())pthread_debug_entries[5].func)
1053 (debug_context, thr, info);
1057 pthread_debug_thd_get_reg (pthreadDebugId_t thr,
1058 pthreadDebugRegs_t *regs)
1060 return ((int (*)())pthread_debug_entries[6].func)
1061 (debug_context, thr, regs);
1065 stub_pthread_debug_cmd (const char *cmd)
1067 return ((int (*)())pthread_debug_entries[7].func)
1068 (debug_context, cmd);
1071 /* Show all the threads. */
1076 pthreadDebugId_t id;
1077 pthreadDebugThreadInfo_t info;
1080 res = pthread_debug_thd_seq_init (&id);
1083 TERM_FAO ("seq init failed, res=!SL!/", res);
1088 if (pthread_debug_thd_get_info (id, &info) != 0)
1090 TERM_FAO ("thd_get_info !SL failed!/", id);
1093 if (pthread_debug_thd_seq_next (&id) != 0)
1096 pthread_debug_thd_seq_destroy ();
1099 /* Initialize pthread support. */
1104 static const $DESCRIPTOR (dbgext_desc, "PTHREAD$DBGEXT");
1105 static const $DESCRIPTOR (pthread_debug_desc, "PTHREAD$DBGSHR");
1106 static const $DESCRIPTOR (dbgsymtable_desc, "PTHREAD_DBG_SYMTABLE");
1111 void *caller_context = 0;
1113 status = lib$find_image_symbol
1114 ((void *) &pthread_rtl_desc, (void *) &dbgext_desc,
1115 (int *) &dbgext_func);
1116 if (!(status & STS$M_SUCCESS))
1117 LIB$SIGNAL (status);
1119 status = lib$find_image_symbol
1120 ((void *) &pthread_rtl_desc, (void *) &dbgsymtable_desc,
1121 (int *) &dbg_symtable);
1122 if (!(status & STS$M_SUCCESS))
1123 LIB$SIGNAL (status);
1125 /* Find entry points in pthread_debug. */
1127 i < sizeof (pthread_debug_entries) / sizeof (pthread_debug_entries[0]);
1130 struct dsc$descriptor_s sym =
1131 { pthread_debug_entries[i].namelen,
1132 DSC$K_DTYPE_T, DSC$K_CLASS_S,
1133 pthread_debug_entries[i].name };
1134 status = lib$find_image_symbol
1135 ((void *) &pthread_debug_desc, (void *) &sym,
1136 (int *) &pthread_debug_entries[i].func);
1137 if (!(status & STS$M_SUCCESS))
1138 lib$signal (status);
1141 if (trace_pthreaddbg)
1142 TERM_FAO ("debug symtable: !XH!/", dbg_symtable);
1143 status = ((int (*)()) pthread_debug_entries[0].func)
1144 (&caller_context, &pthread_debug_callbacks, dbg_symtable, &debug_context);
1146 TERM_FAO ("cannot initialize pthread_debug: !UL!/", status);
1147 TERM_FAO ("pthread debug done!/", 0);
1150 /* Convert an hexadecimal character to a nibble. Return -1 in case of
1154 hex2nibble (unsigned char h)
1156 if (h >= '0' && h <= '9')
1158 if (h >= 'A' && h <= 'F')
1159 return h - 'A' + 10;
1160 if (h >= 'a' && h <= 'f')
1161 return h - 'a' + 10;
1165 /* Convert an hexadecimal 2 character string to a byte. Return -1 in case
1169 hex2byte (const unsigned char *p)
1173 h = hex2nibble (p[0]);
1174 l = hex2nibble (p[1]);
1175 if (h == -1 || l == -1)
1177 return (h << 4) | l;
1180 /* Convert a byte V to a 2 character strings P. */
1183 byte2hex (unsigned char *p, unsigned char v)
1186 p[1] = hex[v & 0xf];
1189 /* Convert a quadword V to a 16 character strings P. */
1192 quad2hex (unsigned char *p, unsigned __int64 v)
1195 for (i = 0; i < 16; i++)
1197 p[i] = hex[v >> 60];
1203 long2pkt (unsigned int v)
1207 for (i = 0; i < 8; i++)
1209 gdb_buf[gdb_blen + i] = hex[(v >> 28) & 0x0f];
1215 /* Generate an error packet. */
1218 packet_error (unsigned int err)
1221 byte2hex (gdb_buf + 2, err);
1225 /* Generate an OK packet. */
1235 /* Append a register to the packet. */
1238 ireg2pkt (const unsigned char *p)
1242 for (i = 0; i < 8; i++)
1244 byte2hex (gdb_buf + gdb_blen, p[i]);
1249 /* Append a C string (ASCIZ) to the packet. */
1252 str2pkt (const char *str)
1255 gdb_buf[gdb_blen++] = *str++;
1258 /* Extract a number fro the packet. */
1260 static unsigned __int64
1261 pkt2val (const unsigned char *pkt, unsigned int *pos)
1263 unsigned __int64 res = 0;
1268 int r = hex2nibble (pkt[*pos]);
1272 res = (res << 4) | r;
1277 /* Append LEN bytes from B to the current gdb packet (encode in binary). */
1280 mem2bin (const unsigned char *b, unsigned int len)
1283 for (i = 0; i < len; i++)
1291 gdb_buf[gdb_blen++] = '}';
1292 gdb_buf[gdb_blen++] = b[i] ^ 0x20;
1295 gdb_buf[gdb_blen++] = b[i];
1300 /* Append LEN bytes from B to the current gdb packet (encode in hex). */
1303 mem2hex (const unsigned char *b, unsigned int len)
1306 for (i = 0; i < len; i++)
1308 byte2hex (gdb_buf + gdb_blen, b[i]);
1313 /* Handle the 'q' packet. */
1316 handle_q_packet (const unsigned char *pkt, unsigned int pktlen)
1318 /* For qfThreadInfo and qsThreadInfo. */
1319 static unsigned int first_thread;
1320 static unsigned int last_thread;
1322 static const char xfer_uib[] = "qXfer:uib:read:";
1323 #define XFER_UIB_LEN (sizeof (xfer_uib) - 1)
1324 static const char qfthreadinfo[] = "qfThreadInfo";
1325 #define QFTHREADINFO_LEN (sizeof (qfthreadinfo) - 1)
1326 static const char qsthreadinfo[] = "qsThreadInfo";
1327 #define QSTHREADINFO_LEN (sizeof (qsthreadinfo) - 1)
1328 static const char qthreadextrainfo[] = "qThreadExtraInfo,";
1329 #define QTHREADEXTRAINFO_LEN (sizeof (qthreadextrainfo) - 1)
1330 static const char qsupported[] = "qSupported:";
1331 #define QSUPPORTED_LEN (sizeof (qsupported) - 1)
1333 if (pktlen == 2 && pkt[1] == 'C')
1335 /* Current thread. */
1341 long2pkt ((unsigned long) get_teb ());
1344 else if (pktlen > XFER_UIB_LEN
1345 && ots$strcmp_eql (pkt, XFER_UIB_LEN, xfer_uib, XFER_UIB_LEN))
1347 /* Get unwind information block. */
1348 unsigned __int64 pc;
1349 unsigned int pos = XFER_UIB_LEN;
1354 unsigned char bytes[32];
1357 unsigned __int64 code_start_va;
1358 unsigned __int64 code_end_va;
1359 unsigned __int64 uib_start_va;
1360 unsigned __int64 gp_value;
1368 pc = pkt2val (pkt, &pos);
1369 if (pkt[pos] != ':')
1372 off = pkt2val (pkt, &pos);
1373 if (pkt[pos] != ',' || off != 0)
1376 len = pkt2val (pkt, &pos);
1377 if (pkt[pos] != '#' || len != 0x20)
1380 res = SYS$GET_UNWIND_ENTRY_INFO (pc, &uei.data, 0);
1381 if (res == SS$_NODATA || res != SS$_NORMAL)
1382 ots$fill (uei.bytes, sizeof (uei.bytes), 0);
1386 TERM_FAO ("Unwind request for !XH, status=!XL, uib=!XQ, GP=!XQ!/",
1387 pc, res, uei.data.uib_start_va, uei.data.gp_value);
1393 mem2bin (uei.bytes, sizeof (uei.bytes));
1395 else if (pktlen == QFTHREADINFO_LEN
1396 && ots$strcmp_eql (pkt, QFTHREADINFO_LEN,
1397 qfthreadinfo, QFTHREADINFO_LEN))
1399 /* Get first thread(s). */
1409 first_thread = thread_next (0);
1410 last_thread = first_thread;
1411 long2pkt (first_thread);
1413 else if (pktlen == QSTHREADINFO_LEN
1414 && ots$strcmp_eql (pkt, QSTHREADINFO_LEN,
1415 qsthreadinfo, QSTHREADINFO_LEN))
1417 /* Get subsequent threads. */
1424 res = thread_next (last_thread);
1425 if (res == first_thread)
1428 gdb_buf[gdb_blen++] = ',';
1431 if (gdb_blen > sizeof (gdb_buf) - 16)
1438 else if (pktlen > QTHREADEXTRAINFO_LEN
1439 && ots$strcmp_eql (pkt, QTHREADEXTRAINFO_LEN,
1440 qthreadextrainfo, QTHREADEXTRAINFO_LEN))
1442 /* Get extra info about a thread. */
1444 unsigned int pos = QTHREADEXTRAINFO_LEN;
1445 pthreadDebugThreadInfo_t info;
1452 thr = (pthread_t) pkt2val (pkt, &pos);
1453 if (pkt[pos] != '#')
1455 res = pthread_debug_thd_get_info_addr (thr, &info);
1458 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", thr, res);
1463 mem2hex ((const unsigned char *)"VMS-thread", 11);
1465 else if (pktlen > QSUPPORTED_LEN
1466 && ots$strcmp_eql (pkt, QSUPPORTED_LEN,
1467 qsupported, QSUPPORTED_LEN))
1469 /* Get supported features. */
1471 unsigned int pos = QSUPPORTED_LEN;
1472 pthreadDebugThreadInfo_t info;
1475 /* Ignore gdb features. */
1479 str2pkt ("qXfer:uib:read+");
1486 term_puts ("unknown <: ");
1487 term_write ((char *)pkt, pktlen);
1494 /* Handle the 'v' packet. */
1497 handle_v_packet (const unsigned char *pkt, unsigned int pktlen)
1499 static const char vcontq[] = "vCont?";
1500 #define VCONTQ_LEN (sizeof (vcontq) - 1)
1502 if (pktlen == VCONTQ_LEN
1503 && ots$strcmp_eql (pkt, VCONTQ_LEN, vcontq, VCONTQ_LEN))
1508 str2pkt ("vCont;c;s");
1515 term_puts ("unknown <: ");
1516 term_write ((char *)pkt, pktlen);
1523 /* Get regs for the selected thread. */
1525 static struct ia64_all_regs *
1526 get_selected_regs (void)
1528 pthreadDebugRegs_t regs;
1531 if (selected_thread == 0 || selected_thread == get_teb ())
1534 if (selected_thread == sel_regs_pthread)
1537 /* Read registers. */
1538 res = pthread_debug_thd_get_reg (selected_id, ®s);
1541 /* FIXME: return NULL ? */
1544 sel_regs_pthread = selected_thread;
1545 sel_regs.gr[1].v = regs.gp;
1546 sel_regs.gr[4].v = regs.r4;
1547 sel_regs.gr[5].v = regs.r5;
1548 sel_regs.gr[6].v = regs.r6;
1549 sel_regs.gr[7].v = regs.r7;
1550 sel_regs.gr[12].v = regs.sp;
1551 sel_regs.br[0].v = regs.rp;
1552 sel_regs.br[1].v = regs.b1;
1553 sel_regs.br[2].v = regs.b2;
1554 sel_regs.br[3].v = regs.b3;
1555 sel_regs.br[4].v = regs.b4;
1556 sel_regs.br[5].v = regs.b5;
1557 sel_regs.ip.v = regs.ip;
1558 sel_regs.bsp.v = regs.bspstore; /* FIXME: it is correct ? */
1559 sel_regs.pfs.v = regs.pfs;
1560 sel_regs.pr.v = regs.pr;
1564 /* Create a status packet. */
1567 packet_status (void)
1572 str2pkt ("$T05thread:");
1573 long2pkt ((unsigned long) get_teb ());
1574 gdb_buf[gdb_blen++] = ';';
1580 /* Return 1 to continue. */
1583 handle_packet (unsigned char *pkt, unsigned int len)
1587 /* By default, reply unsupported. */
1605 excp_regs.psr.v &= ~(unsigned __int64)PSR$M_SS;
1615 struct ia64_all_regs *regs = get_selected_regs ();
1616 unsigned char *p = regs->gr[0].b;
1618 for (i = 0; i < 8 * 32; i++)
1619 byte2hex (gdb_buf + 1 + 2 * i, p[i]);
1620 gdb_blen += 2 * 8 * 32;
1628 unsigned __int64 val;
1629 pthreadDebugThreadInfo_t info;
1632 val = pkt2val (pkt, &pos);
1641 selected_thread = get_teb ();
1644 else if (!has_threads)
1651 res = pthread_debug_thd_get_info_addr ((pthread_t) val, &info);
1654 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", val, res);
1658 selected_thread = info.teb;
1659 selected_id = info.sequence;
1664 else if (pkt[1] == 'c'
1665 && ((pkt[2] == '-' && pkt[3] == '1' && len == 4)
1666 || (pkt[2] == '0' && len == 3)))
1668 /* Silently accept 'Hc0' and 'Hc-1'. */
1678 SYS$EXIT (SS$_NORMAL);
1682 unsigned __int64 addr;
1683 unsigned __int64 paddr;
1687 addr = pkt2val (pkt, &pos);
1688 if (pkt[pos] != ',')
1694 l = pkt2val (pkt, &pos);
1695 if (pkt[pos] != '#')
1702 i = l + (addr & VMS_PAGE_MASK);
1703 paddr = addr & ~VMS_PAGE_MASK;
1706 if (__prober (paddr, 0) != 1)
1711 if (i < VMS_PAGE_SIZE)
1714 paddr += VMS_PAGE_SIZE;
1718 for (i = 0; i < l; i++)
1719 byte2hex (gdb_buf + 1 + 2 * i, ((unsigned char *)addr)[i]);
1725 unsigned __int64 addr;
1726 unsigned __int64 paddr;
1729 unsigned int oldprot;
1731 addr = pkt2val (pkt, &pos);
1732 if (pkt[pos] != ',')
1738 l = pkt2val (pkt, &pos);
1739 if (pkt[pos] != ':')
1745 page_set_rw (addr, l, &oldprot);
1748 i = l + (addr & VMS_PAGE_MASK);
1749 paddr = addr & ~VMS_PAGE_MASK;
1752 if (__probew (paddr, 0) != 1)
1754 page_restore_rw (addr, l, oldprot);
1757 if (i < VMS_PAGE_SIZE)
1760 paddr += VMS_PAGE_SIZE;
1764 for (i = 0; i < l; i++)
1766 int v = hex2byte (pkt + pos);
1768 ((unsigned char *)addr)[i] = v;
1772 for (i = 0; i < l; i += 15)
1776 page_restore_rw (addr, l, oldprot);
1782 unsigned int num = 0;
1784 struct ia64_all_regs *regs = get_selected_regs ();
1786 num = pkt2val (pkt, &pos);
1795 case IA64_IP_REGNUM:
1796 ireg2pkt (regs->ip.b);
1798 case IA64_BR0_REGNUM:
1799 ireg2pkt (regs->br[0].b);
1801 case IA64_PSR_REGNUM:
1802 ireg2pkt (regs->psr.b);
1804 case IA64_BSP_REGNUM:
1805 ireg2pkt (regs->bsp.b);
1807 case IA64_CFM_REGNUM:
1808 ireg2pkt (regs->cfm.b);
1810 case IA64_PFS_REGNUM:
1811 ireg2pkt (regs->pfs.b);
1813 case IA64_PR_REGNUM:
1814 ireg2pkt (regs->pr.b);
1817 TERM_FAO ("gdbserv: unhandled reg !UW!/", num);
1824 handle_q_packet (pkt, len);
1830 excp_regs.psr.v |= (unsigned __int64)PSR$M_SS;
1837 /* Thread status. */
1846 unsigned __int64 val;
1847 unsigned int fthr, thr;
1849 val = pkt2val (pkt, &pos);
1850 /* Default is error (but only after parsing is complete). */
1855 /* Follow the list. This makes a O(n2) algorithm, but we don't really
1856 have the choice. Note that pthread_debug_thd_get_info_addr
1857 doesn't look reliable. */
1858 fthr = thread_next (0);
1867 thr = thread_next (thr);
1869 while (thr != fthr);
1873 return handle_v_packet (pkt, len);
1876 if (len > 3 && pkt[1] == 'M' && pkt[2] == 'S' && pkt[3] == ' ')
1878 /* Temporary extension. */
1882 stub_pthread_debug_cmd ((char *)pkt + 4);
1892 term_puts ("unknown <: ");
1893 term_write ((char *)pkt, len);
1901 /* Raw write to gdb. */
1904 sock_write (const unsigned char *buf, int len)
1907 unsigned int status;
1909 /* Write data to connection. */
1910 status = sys$qiow (EFN$C_ENF, /* Event flag. */
1911 conn_channel, /* I/O channel. */
1912 IO$_WRITEVBLK, /* I/O function code. */
1913 &iosb, /* I/O status block. */
1914 0, /* Ast service routine. */
1915 0, /* Ast parameter. */
1916 (char *)buf, /* P1 - buffer address. */
1917 len, /* P2 - buffer length. */
1919 if (status & STS$M_SUCCESS)
1920 status = iosb.iosb$w_status;
1921 if (!(status & STS$M_SUCCESS))
1923 term_puts ("Failed to write data to gdb\n");
1924 LIB$SIGNAL (status);
1928 /* Compute the cheksum and send the packet. */
1933 unsigned char chksum = 0;
1936 for (i = 1; i < gdb_blen; i++)
1937 chksum += gdb_buf[i];
1939 gdb_buf[gdb_blen] = '#';
1940 byte2hex (gdb_buf + gdb_blen + 1, chksum);
1942 sock_write (gdb_buf, gdb_blen + 3);
1947 term_write ((char *)gdb_buf, gdb_blen + 3);
1952 /* Read and handle one command. Return 1 is execution must resume. */
1958 unsigned int status;
1960 unsigned int dollar_off = 0;
1961 unsigned int sharp_off = 0;
1962 unsigned int cmd_off;
1963 unsigned int cmd_len;
1965 /* Wait for a packet. */
1971 /* Read data from connection. */
1972 status = sys$qiow (EFN$C_ENF, /* Event flag. */
1973 conn_channel, /* I/O channel. */
1974 IO$_READVBLK, /* I/O function code. */
1975 &iosb, /* I/O status block. */
1976 0, /* Ast service routine. */
1977 0, /* Ast parameter. */
1978 gdb_buf + off, /* P1 - buffer address. */
1979 sizeof (gdb_buf) - off, /* P2 - buffer leng. */
1981 if (status & STS$M_SUCCESS)
1982 status = iosb.iosb$w_status;
1983 if (!(status & STS$M_SUCCESS))
1985 term_puts ("Failed to read data from connection\n" );
1986 LIB$SIGNAL (status);
1991 term_write ((char *)gdb_buf + off, iosb.iosb$w_bcnt);
1995 gdb_blen = off + iosb.iosb$w_bcnt;
1999 /* Search for '$'. */
2000 for (dollar_off = 0; dollar_off < gdb_blen; dollar_off++)
2001 if (gdb_buf[dollar_off] == '$')
2003 if (dollar_off >= gdb_blen)
2005 /* Not found, discard the data. */
2009 /* Search for '#'. */
2010 for (sharp_off = dollar_off + 1;
2011 sharp_off < gdb_blen;
2013 if (gdb_buf[sharp_off] == '#')
2016 else if (sharp_off >= off)
2018 /* Search for '#'. */
2019 for (; sharp_off < gdb_blen; sharp_off++)
2020 if (gdb_buf[sharp_off] == '#')
2024 /* Got packet with checksum. */
2025 if (sharp_off + 2 <= gdb_blen)
2029 if (gdb_blen == sizeof (gdb_buf))
2031 /* Packet too large, discard. */
2036 /* Validate and acknowledge a packet. */
2038 unsigned char chksum = 0;
2042 for (i = dollar_off + 1; i < sharp_off; i++)
2043 chksum += gdb_buf[i];
2044 v = hex2byte (gdb_buf + sharp_off + 1);
2047 term_puts ("Discard bad checksum packet\n");
2052 sock_write ((const unsigned char *)"+", 1);
2061 term_write ((char *)gdb_buf + dollar_off, sharp_off - dollar_off + 1);
2065 cmd_off = dollar_off + 1;
2066 cmd_len = sharp_off - dollar_off - 1;
2068 if (handle_packet (gdb_buf + dollar_off + 1, sharp_off - dollar_off - 1) == 1)
2075 /* Display the condition given by SIG64. */
2078 display_excp (struct chf64$signal_array *sig64, struct chf$mech_array *mech)
2080 unsigned int status;
2082 unsigned short msglen;
2083 $DESCRIPTOR (msg_desc, msg);
2084 unsigned char outadr[4];
2086 status = SYS$GETMSG (sig64->chf64$q_sig_name, &msglen, &msg_desc, 0, outadr);
2087 if (status & STS$M_SUCCESS)
2090 unsigned short msg2len;
2091 struct dsc$descriptor_s msg2_desc =
2092 { sizeof (msg2), DSC$K_DTYPE_T, DSC$K_CLASS_S, msg2};
2093 msg_desc.dsc$w_length = msglen;
2094 status = SYS$FAOL_64 (&msg_desc, &msg2len, &msg2_desc,
2095 &sig64->chf64$q_sig_arg1);
2096 if (status & STS$M_SUCCESS)
2097 term_write (msg2, msg2len);
2100 term_puts ("no message");
2105 TERM_FAO (" Frame: !XH, Depth: !4SL, Esf: !XH!/",
2106 mech->chf$q_mch_frame, mech->chf$q_mch_depth,
2107 mech->chf$q_mch_esf_addr);
2111 /* Get all registers from current thread. */
2114 read_all_registers (struct chf$mech_array *mech)
2116 struct _intstk *intstk =
2117 (struct _intstk *)mech->chf$q_mch_esf_addr;
2118 struct chf64$signal_array *sig64 =
2119 (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr;
2120 unsigned int cnt = sig64->chf64$w_sig_arg_count;
2121 unsigned __int64 pc = (&sig64->chf64$q_sig_name)[cnt - 2];
2123 excp_regs.ip.v = pc;
2124 excp_regs.psr.v = intstk->intstk$q_ipsr;
2125 /* GDB and linux expects bsp to point after the current register frame.
2128 unsigned __int64 bsp = intstk->intstk$q_bsp;
2129 unsigned int sof = intstk->intstk$q_ifs & 0x7f;
2130 unsigned int delta = ((bsp >> 3) & 0x3f) + sof;
2131 excp_regs.bsp.v = bsp + ((sof + delta / 0x3f) << 3);
2133 excp_regs.cfm.v = intstk->intstk$q_ifs & 0x3fffffffff;
2134 excp_regs.pfs.v = intstk->intstk$q_pfs;
2135 excp_regs.pr.v = intstk->intstk$q_preds;
2136 excp_regs.gr[0].v = 0;
2137 excp_regs.gr[1].v = intstk->intstk$q_gp;
2138 excp_regs.gr[2].v = intstk->intstk$q_r2;
2139 excp_regs.gr[3].v = intstk->intstk$q_r3;
2140 excp_regs.gr[4].v = intstk->intstk$q_r4;
2141 excp_regs.gr[5].v = intstk->intstk$q_r5;
2142 excp_regs.gr[6].v = intstk->intstk$q_r6;
2143 excp_regs.gr[7].v = intstk->intstk$q_r7;
2144 excp_regs.gr[8].v = intstk->intstk$q_r8;
2145 excp_regs.gr[9].v = intstk->intstk$q_r9;
2146 excp_regs.gr[10].v = intstk->intstk$q_r10;
2147 excp_regs.gr[11].v = intstk->intstk$q_r11;
2148 excp_regs.gr[12].v = (unsigned __int64)intstk + intstk->intstk$l_stkalign;
2149 excp_regs.gr[13].v = intstk->intstk$q_r13;
2150 excp_regs.gr[14].v = intstk->intstk$q_r14;
2151 excp_regs.gr[15].v = intstk->intstk$q_r15;
2152 excp_regs.gr[16].v = intstk->intstk$q_r16;
2153 excp_regs.gr[17].v = intstk->intstk$q_r17;
2154 excp_regs.gr[18].v = intstk->intstk$q_r18;
2155 excp_regs.gr[19].v = intstk->intstk$q_r19;
2156 excp_regs.gr[20].v = intstk->intstk$q_r20;
2157 excp_regs.gr[21].v = intstk->intstk$q_r21;
2158 excp_regs.gr[22].v = intstk->intstk$q_r22;
2159 excp_regs.gr[23].v = intstk->intstk$q_r23;
2160 excp_regs.gr[24].v = intstk->intstk$q_r24;
2161 excp_regs.gr[25].v = intstk->intstk$q_r25;
2162 excp_regs.gr[26].v = intstk->intstk$q_r26;
2163 excp_regs.gr[27].v = intstk->intstk$q_r27;
2164 excp_regs.gr[28].v = intstk->intstk$q_r28;
2165 excp_regs.gr[29].v = intstk->intstk$q_r29;
2166 excp_regs.gr[30].v = intstk->intstk$q_r30;
2167 excp_regs.gr[31].v = intstk->intstk$q_r31;
2168 excp_regs.br[0].v = intstk->intstk$q_b0;
2169 excp_regs.br[1].v = intstk->intstk$q_b1;
2170 excp_regs.br[2].v = intstk->intstk$q_b2;
2171 excp_regs.br[3].v = intstk->intstk$q_b3;
2172 excp_regs.br[4].v = intstk->intstk$q_b4;
2173 excp_regs.br[5].v = intstk->intstk$q_b5;
2174 excp_regs.br[6].v = intstk->intstk$q_b6;
2175 excp_regs.br[7].v = intstk->intstk$q_b7;
2178 /* Write all registers to current thread. FIXME: not yet complete. */
2181 write_all_registers (struct chf$mech_array *mech)
2183 struct _intstk *intstk =
2184 (struct _intstk *)mech->chf$q_mch_esf_addr;
2186 intstk->intstk$q_ipsr = excp_regs.psr.v;
2189 /* Do debugging. Report status to gdb and execute commands. */
2192 do_debug (struct chf$mech_array *mech)
2194 struct _intstk *intstk =
2195 (struct _intstk *)mech->chf$q_mch_esf_addr;
2196 unsigned int old_ast;
2197 unsigned int old_sch;
2198 unsigned int status;
2201 status = sys$setast (0);
2211 /* Should never happen! */
2212 lib$signal (status);
2215 /* Disable thread scheduling. */
2217 old_sch = set_thread_scheduling (0);
2219 read_all_registers (mech);
2221 /* Send stop reply packet. */
2225 while (one_command () == 0)
2228 write_all_registers (mech);
2230 /* Re-enable scheduling. */
2232 set_thread_scheduling (old_sch);
2234 /* Re-enable AST. */
2235 status = sys$setast (old_ast);
2236 if (!(status & STS$M_SUCCESS))
2237 LIB$SIGNAL (status);
2240 /* The condition handler. That's the core of the stub. */
2243 excp_handler (struct chf$signal_array *sig,
2244 struct chf$mech_array *mech)
2246 struct chf64$signal_array *sig64 =
2247 (struct chf64$signal_array *)mech->chf$ph_mch_sig64_addr;
2248 unsigned int code = sig->chf$l_sig_name & STS$M_COND_ID;
2249 unsigned int cnt = sig64->chf64$w_sig_arg_count;
2250 unsigned __int64 pc;
2252 /* Self protection. FIXME: Should be per thread ? */
2253 static int in_handler = 0;
2255 /* Completly ignore some conditions (signaled indirectly by this stub). */
2258 case LIB$_KEYNOTFOU & STS$M_COND_ID:
2259 return SS$_RESIGNAL_64;
2264 /* Protect against recursion. */
2268 if (in_handler == 2)
2269 TERM_FAO ("gdbstub: exception in handler (pc=!XH)!!!/",
2270 (&sig64->chf64$q_sig_name)[cnt - 2]);
2271 sys$exit (sig->chf$l_sig_name);
2274 pc = (&sig64->chf64$q_sig_name)[cnt - 2];
2276 TERM_FAO ("excp_handler: code: !XL, pc=!XH!/", code, pc);
2278 /* If break on the entry point, restore the bundle. */
2279 if (code == (SS$_BREAK & STS$M_COND_ID)
2283 static unsigned int entry_prot;
2286 term_puts ("initial entry breakpoint\n");
2287 page_set_rw (entry_pc, 16, &entry_prot);
2289 ots$move ((void *)entry_pc, 16, entry_saved);
2291 page_restore_rw (entry_pc, 16, entry_prot);
2296 case SS$_ACCVIO & STS$M_COND_ID:
2297 if (trace_excp <= 1)
2298 display_excp (sig64, mech);
2300 case SS$_BREAK & STS$M_COND_ID:
2301 case SS$_OPCDEC & STS$M_COND_ID:
2302 case SS$_TBIT & STS$M_COND_ID:
2303 case SS$_DEBUG & STS$M_COND_ID:
2307 struct _intstk *intstk =
2308 (struct _intstk *)mech->chf$q_mch_esf_addr;
2310 display_excp (sig64, mech);
2312 TERM_FAO (" intstk: !XH!/", intstk);
2313 for (i = 0; i < cnt + 1; i++)
2314 TERM_FAO (" !XH!/", ((unsigned __int64 *)sig64)[i]);
2317 ret = SS$_CONTINUE_64;
2321 display_excp (sig64, mech);
2322 ret = SS$_RESIGNAL_64;
2327 /* Discard selected thread registers. */
2328 sel_regs_pthread = 0;
2332 /* Setup internal trace flags according to GDBSTUB$TRACE logical. */
2337 unsigned int status, i, start;
2339 char resstring[LNM$C_NAMLENGTH];
2340 static const $DESCRIPTOR (tabdesc, "LNM$DCL_LOGICAL");
2341 static const $DESCRIPTOR (logdesc, "GDBSTUB$TRACE");
2342 $DESCRIPTOR (sub_desc, resstring);
2345 item_lst[0].ile3$w_length = LNM$C_NAMLENGTH;
2346 item_lst[0].ile3$w_code = LNM$_STRING;
2347 item_lst[0].ile3$ps_bufaddr = resstring;
2348 item_lst[0].ile3$ps_retlen_addr = &len;
2349 item_lst[1].ile3$w_length = 0;
2350 item_lst[1].ile3$w_code = 0;
2352 /* Translate the logical name. */
2353 status = SYS$TRNLNM (0, /* Attributes of the logical name. */
2354 (void *)&tabdesc, /* Logical name table. */
2355 (void *)&logdesc, /* Logical name. */
2356 0, /* Access mode. */
2357 &item_lst); /* Item list. */
2358 if (status == SS$_NOLOGNAM)
2360 if (!(status & STS$M_SUCCESS))
2361 LIB$SIGNAL (status);
2364 for (i = 0; i <= len; i++)
2366 if ((i == len || resstring[i] == ',' || resstring[i] == ';')
2371 sub_desc.dsc$a_pointer = resstring + start;
2372 sub_desc.dsc$w_length = i - start;
2374 for (j = 0; j < NBR_DEBUG_FLAGS; j++)
2375 if (str$case_blind_compare (&sub_desc,
2376 (void *)&debug_flags[j].name) == 0)
2378 debug_flags[j].val++;
2381 if (j == NBR_DEBUG_FLAGS)
2382 TERM_FAO ("GDBSTUB$TRACE: unknown directive !AS!/", &sub_desc);
2388 TERM_FAO ("GDBSTUB$TRACE=!AD ->", len, resstring);
2389 for (i = 0; i < NBR_DEBUG_FLAGS; i++)
2390 if (debug_flags[i].val > 0)
2391 TERM_FAO (" !AS=!ZL", &debug_flags[i].name, debug_flags[i].val);
2399 stub_start (unsigned __int64 *progxfer, void *cli_util,
2400 EIHD *imghdr, IFD *imgfile,
2401 unsigned int linkflag, unsigned int cliflag)
2403 static int initialized;
2409 term_puts ("gdbstub: re-entry\n");
2413 /* When attached (through SS$_DEBUG condition), the number of arguments
2414 is 4 and PROGXFER is the PC at interruption. */
2416 is_attached = cnt == 4;
2421 term_puts ("Hello from gdb stub\n");
2425 if (trace_entry && !is_attached)
2427 TERM_FAO ("xfer: !XH, imghdr: !XH, ifd: !XH!/",
2428 progxfer, imghdr, imgfile);
2429 for (i = -2; i < 8; i++)
2430 TERM_FAO (" at !2SW: !XH!/", i, progxfer[i]);
2433 /* Search for entry point. */
2437 for (i = 0; progxfer[i]; i++)
2438 entry_pc = progxfer[i];
2444 term_puts ("No entry point\n");
2448 TERM_FAO ("Entry: !XH!/",entry_pc);
2452 entry_pc = progxfer[0];
2455 for (imcb = ctl$gl_imglstptr->imcb$l_flink;
2456 imcb != ctl$gl_imglstptr;
2457 imcb = imcb->imcb$l_flink)
2459 if (ots$strcmp_eql (pthread_rtl_desc.dsc$a_pointer,
2460 pthread_rtl_desc.dsc$w_length,
2461 imcb->imcb$t_log_image_name + 1,
2462 imcb->imcb$t_log_image_name[0]))
2468 LDRIMG *ldrimg = imcb->imcb$l_ldrimg;
2471 TERM_FAO ("!XA-!XA ",
2472 imcb->imcb$l_starting_address,
2473 imcb->imcb$l_end_address);
2475 switch (imcb->imcb$b_act_code)
2477 case IMCB$K_MAIN_PROGRAM:
2480 case IMCB$K_MERGED_IMAGE:
2483 case IMCB$K_GLOBAL_IMAGE_SECTION:
2489 TERM_FAO (" !AD !40AC!/",
2490 1, "KESU" + (imcb->imcb$b_access_mode & 3),
2491 imcb->imcb$t_log_image_name);
2493 if ((long) ldrimg < 0 || trace_images < 2)
2495 ldrisd = ldrimg->ldrimg$l_segments;
2496 for (j = 0; j < ldrimg->ldrimg$l_segcount; j++)
2498 unsigned int flags = ldrisd[j].ldrisd$i_flags;
2500 term_putc (flags & 0x04 ? 'R' : '-');
2501 term_putc (flags & 0x02 ? 'W' : '-');
2502 term_putc (flags & 0x01 ? 'X' : '-');
2503 term_puts (flags & 0x01000000 ? " Prot" : " ");
2504 term_puts (flags & 0x04000000 ? " Shrt" : " ");
2505 term_puts (flags & 0x08000000 ? " Shrd" : " ");
2506 TERM_FAO (" !XA-!XA!/",
2507 ldrisd[j].ldrisd$p_base,
2508 (unsigned __int64) ldrisd[j].ldrisd$p_base
2509 + ldrisd[j].ldrisd$i_len - 1);
2511 ldrisd = ldrimg->ldrimg$l_dyn_seg;
2513 TERM_FAO (" dynamic !XA-!XA!/",
2514 ldrisd->ldrisd$p_base,
2515 (unsigned __int64) ldrisd->ldrisd$p_base
2516 + ldrisd->ldrisd$i_len - 1);
2523 /* Wait for connection. */
2526 /* Set primary exception vector. */
2528 unsigned int status;
2529 status = sys$setexv (0, excp_handler, PSL$C_USER, (__void_ptr32) &prevhnd);
2530 if (!(status & STS$M_SUCCESS))
2531 LIB$SIGNAL (status);
2536 return excp_handler ((struct chf$signal_array *) progxfer[2],
2537 (struct chf$mech_array *) progxfer[3]);
2540 /* Change first instruction to set a breakpoint. */
2543 01 08 00 40 00 00 [MII] break.m 0x80001
2544 00 00 00 02 00 00 nop.i 0x0
2545 00 00 04 00 nop.i 0x0;;
2547 static const unsigned char initbp[16] =
2548 { 0x01, 0x08, 0x00, 0x40, 0x00, 0x00,
2549 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
2550 0x00, 0x00, 0x04, 0x00 };
2551 unsigned int entry_prot;
2552 unsigned int status;
2554 status = page_set_rw (entry_pc, 16, &entry_prot);
2556 if (!(status & STS$M_SUCCESS))
2558 if ((status & STS$M_COND_ID) == (SS$_NOT_PROCESS_VA & STS$M_COND_ID))
2560 /* Cannot write here. This can happen when pthreads are
2563 term_puts ("gdbstub: cannot set breakpoint on entry\n");
2566 LIB$SIGNAL (status);
2571 ots$move (entry_saved, 16, (void *)entry_pc);
2572 ots$move ((void *)entry_pc, 16, (void *)initbp);
2574 page_restore_rw (entry_pc, 16, entry_prot);
2578 /* If it wasn't possible to set a breakpoint on the entry point,
2579 accept gdb commands now. Note that registers are not updated. */
2582 while (one_command () == 0)
2587 return SS$_CONTINUE;
2590 /* Declare the entry point of this relocatable module. */
2594 __int64 impure_start;
2599 #pragma __extern_model save
2600 #pragma __extern_model strict_refdef "XFER_PSECT"
2601 struct xfer_vector xfer_vector = {0, 0, stub_start};
2602 #pragma __extern_model restore