1 /* GDB stub for Itanium OpenVMS
2 Copyright (C) 2012-2024 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>
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>
69 #include <pthread_debug.h>
71 #define VMS_PAGE_SIZE 0x2000
72 #define VMS_PAGE_MASK (VMS_PAGE_SIZE - 1)
74 /* Declared in lib$ots. */
75 extern void ots$
fill (void *addr
, size_t len
, unsigned char b
);
76 extern void ots$
move (void *dst
, size_t len
, const void *src
);
77 extern int ots$
strcmp_eql (const void *str1
, size_t str1len
,
78 const void *str2
, size_t str2len
);
80 /* Stub port number. */
81 static unsigned int serv_port
= 1234;
83 /* DBGEXT structure. Not declared in any header. */
84 struct dbgext_control_block
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
;
108 #pragma pointer_size save
109 #pragma pointer_size 32
111 /* Pthread handler. */
112 static int (*dbgext_func
) (struct dbgext_control_block
*blk
);
114 #pragma pointer_size restore
116 /* Set to 1 if thread-aware. */
117 static int has_threads
;
119 /* Current thread. */
120 static pthread_t selected_thread
;
121 static pthreadDebugId_t selected_id
;
123 /* Internal debugging flags. */
126 /* Name of the flag (as a string descriptor). */
127 const struct dsc$descriptor_s name
;
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}
136 static struct debug_flag debug_flags
[] =
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)
158 #define NBR_DEBUG_FLAGS (sizeof (debug_flags) / sizeof (debug_flags[0]))
160 /* Connect inet device I/O channel. */
161 static unsigned short conn_channel
;
163 /* Widely used hex digit to ascii. */
164 static const char hex
[] = "0123456789abcdef";
166 /* Socket characteristics. Apparently, there are no declaration for it in
175 /* Chain of images loaded. */
176 extern IMCB
* ctl$gl_imglstptr
;
178 /* IA64 integer register representation. */
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)
189 /* Floating point registers; 128 82-bit wide registers. */
190 #define IA64_FR0_REGNUM 128
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
199 /* Branch registers: 8 64-bit registers for holding branch targets. */
200 #define IA64_BR0_REGNUM 320
202 /* Virtual frame pointer; this matches IA64_FRAME_POINTER_REGNUM in
203 gcc/config/ia64/ia64.h. */
204 #define IA64_VFP_REGNUM 328
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
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
216 /* Instruction pointer: 64 bits wide. */
217 #define IA64_IP_REGNUM 331
219 /* Process Status Register. */
220 #define IA64_PSR_REGNUM 332
222 /* Current Frame Marker (raw form may be the cr.ifs). */
223 #define IA64_CFM_REGNUM 333
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)
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)
251 /* NAT (Not A Thing) Bits for the general registers; there are 128 of
253 #define IA64_NAT0_REGNUM 462
255 /* Process registers when a condition is caught. */
258 union ia64_ireg gr
[32];
259 union ia64_ireg br
[8];
268 static struct ia64_all_regs excp_regs
;
269 static struct ia64_all_regs sel_regs
;
270 static pthread_t sel_regs_pthread
;
272 /* IO channel for the terminal. */
273 static unsigned short term_chan
;
275 /* Output buffer and length. */
276 static char term_buf
[128];
277 static int term_buf_len
;
279 /* Buffer for communication with gdb. */
280 static unsigned char gdb_buf
[sizeof (struct ia64_all_regs
) * 2 + 64];
281 static unsigned int gdb_blen
;
283 /* Previous primary handler. */
284 static void *prevhnd
;
286 /* Entry point address and bundle. */
287 static unsigned __int64 entry_pc
;
288 static unsigned char entry_saved
[16];
290 /* Write on the terminal. */
293 term_raw_write (const char *str
, unsigned int len
)
295 unsigned short status
;
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. */
308 if (status
& STS$M_SUCCESS
)
309 status
= iosb
.iosb$w_status
;
310 if (!(status
& STS$M_SUCCESS
))
314 /* Flush ther term buffer. */
319 if (term_buf_len
!= 0)
321 term_raw_write (term_buf
, term_buf_len
);
326 /* Write a single character, without translation. */
329 term_raw_putchar (char c
)
331 if (term_buf_len
== sizeof (term_buf
))
333 term_buf
[term_buf_len
++] = c
;
336 /* Write character C. Translate '\n' to '\n\r'. */
351 term_raw_putchar (c
);
354 term_raw_putchar ('\r');
359 /* Write a C string. */
362 term_puts (const char *str
)
368 /* Write LEN bytes from STR. */
371 term_write (const char *str
, unsigned int len
)
373 for (; len
> 0; len
--)
377 /* Write using FAO formatting. */
380 term_fao (const char *str
, unsigned int str_len
, ...)
387 struct dsc$descriptor_s dstr
=
388 { str_len
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (__char_ptr32
)str
};
390 $
DESCRIPTOR (buf_desc
, buf
);
392 va_start (vargs
, str_len
);
394 args
= (__int64
*) __ALLOCA (cnt
* sizeof (__int64
));
396 for (i
= 0; i
< cnt
; i
++)
397 args
[i
] = va_arg (vargs
, __int64
);
399 status
= sys$
faol_64 (&dstr
, &buf_desc
.dsc$w_length
, &buf_desc
, args
);
402 /* FAO !/ already insert a line feed. */
403 for (i
= 0; i
< buf_desc
.dsc$w_length
; i
++)
405 term_raw_putchar (buf
[i
]);
414 #define TERM_FAO(STR, ...) term_fao (STR, sizeof (STR) - 1, __VA_ARGS__)
424 /* Initialize terminal. */
429 unsigned int status
,i
;
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
);
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;
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
))
453 term_desc
.dsc$w_length
= len
;
455 /* Examine 4-byte header. Skip escape sequence. */
456 if (resstring
[0] == 0x1B)
458 term_desc
.dsc$w_length
-= 4;
459 term_desc
.dsc$a_pointer
+= 4;
462 /* Assign a channel. */
463 status
= sys$
assign (&term_desc
, /* Device name. */
464 &term_chan
, /* I/O channel. */
465 0, /* Access mode. */
467 if (!(status
& STS$M_SUCCESS
))
471 /* Convert from native endianness to network endianness (and vice-versa). */
474 wordswap (unsigned int v
)
476 return ((v
& 0xff) << 8) | ((v
>> 8) & 0xff);
479 /* Initialize the socket connection, and wait for a client. */
487 /* Listen channel and characteristics. */
488 unsigned short listen_channel
;
489 struct sockchar listen_sockchar
;
491 /* Client address. */
492 unsigned short cli_addrlen
;
493 struct sockaddr_in cli_addr
;
497 struct sockaddr_in serv_addr
;
500 /* Reuseaddr option value (on). */
502 ILE2 sockopt_itemlst
;
503 ILE2 reuseaddr_itemlst
;
505 /* TCP/IP network pseudodevice. */
506 static const $
DESCRIPTOR (inet_device
, "TCPIP$DEVICE:");
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
;
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
))
519 term_puts ("Failed to assign I/O channel(s)\n");
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. */
532 if (status
& STS$M_SUCCESS
)
533 status
= iosb
.iosb$w_status
;
534 if (!(status
& STS$M_SUCCESS
))
536 term_puts ("Failed to create socket\n");
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
;
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
;
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. */
561 (__int64
) &sockopt_itemlst
, /* P5 - socket options. */
563 if (status
& STS$M_SUCCESS
)
564 status
= iosb
.iosb$w_status
;
565 if (!(status
& STS$M_SUCCESS
))
567 term_puts ("Failed to set socket option\n");
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
;
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
;
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. */
591 (__int64
) &serv_itemlst
, /* P3 - local socket name. */
593 if (status
& STS$M_SUCCESS
)
594 status
= iosb
.iosb$w_status
;
595 if (!(status
& STS$M_SUCCESS
))
597 term_puts ("Failed to bind socket\n");
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. */
611 1, /* P4 - connection backlog. */
613 if (status
& STS$M_SUCCESS
)
614 status
= iosb
.iosb$w_status
;
615 if (!(status
& STS$M_SUCCESS
))
617 term_puts ("Failed to set socket passive\n");
621 /* Accept connection from a client. */
622 TERM_FAO ("Waiting for a client connection on port: !ZW!/",
623 wordswap (serv_addr
.sin_port
));
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. */
634 (__int64
) &conn_channel
, /* P4 - I/O channel for conn. */
637 if (status
& STS$M_SUCCESS
)
638 status
= iosb
.iosb$w_status
;
639 if (!(status
& STS$M_SUCCESS
))
641 term_puts ("Failed to accept client connection\n");
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. */
660 (__int64
) &cli_itemlst
, /* P4 - peer socket name. */
662 if (status
& STS$M_SUCCESS
)
663 status
= iosb
.iosb$w_status
;
664 if (!(status
& STS$M_SUCCESS
))
666 term_puts ("Failed to get client name\n");
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
));
678 /* Close the 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. */
695 if (status
& STS$M_SUCCESS
)
696 status
= iosb
.iosb$w_status
;
697 if (!(status
& STS$M_SUCCESS
))
699 term_puts ("Failed to close socket\n");
703 /* Deassign I/O channel to network device. */
704 status
= sys$
dassgn (conn_channel
);
706 if (!(status
& STS$M_SUCCESS
))
708 term_puts ("Failed to deassign I/O channel\n");
713 /* Mark a page as R/W. Return old rights. */
716 page_set_rw (unsigned __int64 startva
, unsigned __int64 len
,
717 unsigned int *oldprot
)
720 unsigned __int64 retva
;
721 unsigned __int64 retlen
;
723 status
= SYS$
SETPRT_64 ((void *)startva
, len
, PSL$C_USER
, PRT$C_UW
,
724 (void *)&retva
, &retlen
, oldprot
);
728 /* Restore page rights. */
731 page_restore_rw (unsigned __int64 startva
, unsigned __int64 len
,
735 unsigned __int64 retva
;
736 unsigned __int64 retlen
;
737 unsigned int oldprot
;
739 status
= SYS$
SETPRT_64 ((void *)startva
, len
, PSL$C_USER
, prot
,
740 (void *)&retva
, &retlen
, &oldprot
);
741 if (!(status
& STS$M_SUCCESS
))
745 /* Get the TEB (thread environment block). */
750 return (pthread_t
)__getReg (_IA64_REG_TP
);
753 /* Enable thread scheduling if VAL is true. */
756 set_thread_scheduling (int val
)
758 struct dbgext_control_block blk
;
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
;
768 status
= dbgext_func (&blk
);
769 if (!(status
& STS$M_SUCCESS
))
771 TERM_FAO ("set_thread_scheduling error, val=!SL, status=!XL!/",
772 val
, blk
.dbgext$l_status
);
776 return blk
.dbgext$l_stop_value
;
779 /* Get next thread (after THR). Start with 0. */
782 thread_next (unsigned int thr
)
784 struct dbgext_control_block blk
;
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
;
795 status
= dbgext_func (&blk
);
796 if (!(status
& STS$M_SUCCESS
))
799 return blk
.dbgext$l_task_value
;
802 /* Pthread Debug callbacks. */
805 read_callback (pthreadDebugClient_t context
,
806 pthreadDebugTargetAddr_t addr
,
807 pthreadDebugAddr_t buf
,
810 if (trace_pthreaddbg
)
811 TERM_FAO ("read_callback (!XH, !XH, !SL)!/", addr
, buf
, size
);
812 ots$
move (buf
, size
, addr
);
817 write_callback (pthreadDebugClient_t context
,
818 pthreadDebugTargetAddr_t addr
,
819 pthreadDebugLongConstAddr_t buf
,
822 if (trace_pthreaddbg
)
823 TERM_FAO ("write_callback (!XH, !XH, !SL)!/", addr
, buf
, size
);
824 ots$
move (addr
, size
, buf
);
829 suspend_callback (pthreadDebugClient_t context
)
831 /* Always suspended. */
836 resume_callback (pthreadDebugClient_t context
)
838 /* So no need to resume. */
843 kthdinfo_callback (pthreadDebugClient_t context
,
844 pthreadDebugKId_t kid
,
845 pthreadDebugKThreadInfo_p thread_info
)
847 if (trace_pthreaddbg
)
848 term_puts ("kthinfo_callback");
853 hold_callback (pthreadDebugClient_t context
,
854 pthreadDebugKId_t kid
)
856 if (trace_pthreaddbg
)
857 term_puts ("hold_callback");
862 unhold_callback (pthreadDebugClient_t context
,
863 pthreadDebugKId_t kid
)
865 if (trace_pthreaddbg
)
866 term_puts ("unhold_callback");
871 getfreg_callback (pthreadDebugClient_t context
,
872 pthreadDebugFregs_t
*reg
,
873 pthreadDebugKId_t kid
)
875 if (trace_pthreaddbg
)
876 term_puts ("getfreg_callback");
881 setfreg_callback (pthreadDebugClient_t context
,
882 const pthreadDebugFregs_t
*reg
,
883 pthreadDebugKId_t kid
)
885 if (trace_pthreaddbg
)
886 term_puts ("setfreg_callback");
891 getreg_callback (pthreadDebugClient_t context
,
892 pthreadDebugRegs_t
*reg
,
893 pthreadDebugKId_t kid
)
895 if (trace_pthreaddbg
)
896 term_puts ("getreg_callback");
901 setreg_callback (pthreadDebugClient_t context
,
902 const pthreadDebugRegs_t
*reg
,
903 pthreadDebugKId_t kid
)
905 if (trace_pthreaddbg
)
906 term_puts ("setreg_callback");
911 output_callback (pthreadDebugClient_t context
,
912 pthreadDebugConstString_t line
)
920 error_callback (pthreadDebugClient_t context
,
921 pthreadDebugConstString_t line
)
928 static pthreadDebugAddr_t
929 malloc_callback (pthreadDebugClient_t caller_context
, size_t size
)
936 status
= lib$
get_vm (&len
, &res
, 0);
937 if (!(status
& STS$M_SUCCESS
))
939 if (trace_pthreaddbg
)
940 TERM_FAO ("malloc_callback (!UL) -> !XA!/", size
, res
);
941 *(unsigned int *)res
= len
;
942 return (char *)res
+ 16;
946 free_callback (pthreadDebugClient_t caller_context
, pthreadDebugAddr_t address
)
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
))
962 speckthd_callback (pthreadDebugClient_t caller_context
,
963 pthreadDebugSpecialType_t type
,
964 pthreadDebugKId_t
*kernel_tid
)
969 static pthreadDebugCallbacks_t pthread_debug_callbacks
= {
970 PTHREAD_DEBUG_VERSION
,
989 /* Name of the pthread shared library. */
990 static const $
DESCRIPTOR (pthread_rtl_desc
, "PTHREAD$RTL");
992 /* List of symbols to extract from pthread debug library. */
993 struct pthread_debug_entry
995 const unsigned int namelen
;
996 const __char_ptr32 name
;
1000 #define DEBUG_ENTRY(str) { sizeof(str) - 1, str, 0 }
1002 static 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")
1013 /* Pthread debug context. */
1014 static pthreadDebugContext_t debug_context
;
1016 /* Wrapper around pthread debug entry points. */
1019 pthread_debug_thd_seq_init (pthreadDebugId_t
*id
)
1021 return ((int (*)())pthread_debug_entries
[1].func
)
1022 (debug_context
, id
);
1026 pthread_debug_thd_seq_next (pthreadDebugId_t
*id
)
1028 return ((int (*)())pthread_debug_entries
[2].func
)
1029 (debug_context
, id
);
1033 pthread_debug_thd_seq_destroy (void)
1035 return ((int (*)())pthread_debug_entries
[3].func
)
1040 pthread_debug_thd_get_info (pthreadDebugId_t id
,
1041 pthreadDebugThreadInfo_t
*info
)
1043 return ((int (*)())pthread_debug_entries
[4].func
)
1044 (debug_context
, id
, info
);
1048 pthread_debug_thd_get_info_addr (pthread_t thr
,
1049 pthreadDebugThreadInfo_t
*info
)
1051 return ((int (*)())pthread_debug_entries
[5].func
)
1052 (debug_context
, thr
, info
);
1056 pthread_debug_thd_get_reg (pthreadDebugId_t thr
,
1057 pthreadDebugRegs_t
*regs
)
1059 return ((int (*)())pthread_debug_entries
[6].func
)
1060 (debug_context
, thr
, regs
);
1064 stub_pthread_debug_cmd (const char *cmd
)
1066 return ((int (*)())pthread_debug_entries
[7].func
)
1067 (debug_context
, cmd
);
1070 /* Show all the threads. */
1075 pthreadDebugId_t id
;
1076 pthreadDebugThreadInfo_t info
;
1079 res
= pthread_debug_thd_seq_init (&id
);
1082 TERM_FAO ("seq init failed, res=!SL!/", res
);
1087 if (pthread_debug_thd_get_info (id
, &info
) != 0)
1089 TERM_FAO ("thd_get_info !SL failed!/", id
);
1092 if (pthread_debug_thd_seq_next (&id
) != 0)
1095 pthread_debug_thd_seq_destroy ();
1098 /* Initialize pthread support. */
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");
1110 void *caller_context
= 0;
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
);
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
);
1124 /* Find entry points in pthread_debug. */
1126 i
< sizeof (pthread_debug_entries
) / sizeof (pthread_debug_entries
[0]);
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
);
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
);
1145 TERM_FAO ("cannot initialize pthread_debug: !UL!/", status
);
1146 TERM_FAO ("pthread debug done!/", 0);
1149 /* Convert an hexadecimal character to a nibble. Return -1 in case of
1153 hex2nibble (unsigned char h
)
1155 if (h
>= '0' && h
<= '9')
1157 if (h
>= 'A' && h
<= 'F')
1158 return h
- 'A' + 10;
1159 if (h
>= 'a' && h
<= 'f')
1160 return h
- 'a' + 10;
1164 /* Convert an hexadecimal 2 character string to a byte. Return -1 in case
1168 hex2byte (const unsigned char *p
)
1172 h
= hex2nibble (p
[0]);
1173 l
= hex2nibble (p
[1]);
1174 if (h
== -1 || l
== -1)
1176 return (h
<< 4) | l
;
1179 /* Convert a byte V to a 2 character strings P. */
1182 byte2hex (unsigned char *p
, unsigned char v
)
1185 p
[1] = hex
[v
& 0xf];
1188 /* Convert a quadword V to a 16 character strings P. */
1191 quad2hex (unsigned char *p
, unsigned __int64 v
)
1194 for (i
= 0; i
< 16; i
++)
1196 p
[i
] = hex
[v
>> 60];
1202 long2pkt (unsigned int v
)
1206 for (i
= 0; i
< 8; i
++)
1208 gdb_buf
[gdb_blen
+ i
] = hex
[(v
>> 28) & 0x0f];
1214 /* Generate an error packet. */
1217 packet_error (unsigned int err
)
1220 byte2hex (gdb_buf
+ 2, err
);
1224 /* Generate an OK packet. */
1234 /* Append a register to the packet. */
1237 ireg2pkt (const unsigned char *p
)
1241 for (i
= 0; i
< 8; i
++)
1243 byte2hex (gdb_buf
+ gdb_blen
, p
[i
]);
1248 /* Append a C string (ASCIZ) to the packet. */
1251 str2pkt (const char *str
)
1254 gdb_buf
[gdb_blen
++] = *str
++;
1257 /* Extract a number fro the packet. */
1259 static unsigned __int64
1260 pkt2val (const unsigned char *pkt
, unsigned int *pos
)
1262 unsigned __int64 res
= 0;
1267 int r
= hex2nibble (pkt
[*pos
]);
1271 res
= (res
<< 4) | r
;
1276 /* Append LEN bytes from B to the current gdb packet (encode in binary). */
1279 mem2bin (const unsigned char *b
, unsigned int len
)
1282 for (i
= 0; i
< len
; i
++)
1290 gdb_buf
[gdb_blen
++] = '}';
1291 gdb_buf
[gdb_blen
++] = b
[i
] ^ 0x20;
1294 gdb_buf
[gdb_blen
++] = b
[i
];
1299 /* Append LEN bytes from B to the current gdb packet (encode in hex). */
1302 mem2hex (const unsigned char *b
, unsigned int len
)
1305 for (i
= 0; i
< len
; i
++)
1307 byte2hex (gdb_buf
+ gdb_blen
, b
[i
]);
1312 /* Handle the 'q' packet. */
1315 handle_q_packet (const unsigned char *pkt
, unsigned int pktlen
)
1317 /* For qfThreadInfo and qsThreadInfo. */
1318 static unsigned int first_thread
;
1319 static unsigned int last_thread
;
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)
1332 if (pktlen
== 2 && pkt
[1] == 'C')
1334 /* Current thread. */
1340 long2pkt ((unsigned long) get_teb ());
1343 else if (pktlen
> XFER_UIB_LEN
1344 && ots$
strcmp_eql (pkt
, XFER_UIB_LEN
, xfer_uib
, XFER_UIB_LEN
))
1346 /* Get unwind information block. */
1347 unsigned __int64 pc
;
1348 unsigned int pos
= XFER_UIB_LEN
;
1353 unsigned char bytes
[32];
1356 unsigned __int64 code_start_va
;
1357 unsigned __int64 code_end_va
;
1358 unsigned __int64 uib_start_va
;
1359 unsigned __int64 gp_value
;
1367 pc
= pkt2val (pkt
, &pos
);
1368 if (pkt
[pos
] != ':')
1371 off
= pkt2val (pkt
, &pos
);
1372 if (pkt
[pos
] != ',' || off
!= 0)
1375 len
= pkt2val (pkt
, &pos
);
1376 if (pkt
[pos
] != '#' || len
!= 0x20)
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);
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
);
1392 mem2bin (uei
.bytes
, sizeof (uei
.bytes
));
1394 else if (pktlen
== QFTHREADINFO_LEN
1395 && ots$
strcmp_eql (pkt
, QFTHREADINFO_LEN
,
1396 qfthreadinfo
, QFTHREADINFO_LEN
))
1398 /* Get first thread(s). */
1408 first_thread
= thread_next (0);
1409 last_thread
= first_thread
;
1410 long2pkt (first_thread
);
1412 else if (pktlen
== QSTHREADINFO_LEN
1413 && ots$
strcmp_eql (pkt
, QSTHREADINFO_LEN
,
1414 qsthreadinfo
, QSTHREADINFO_LEN
))
1416 /* Get subsequent threads. */
1423 res
= thread_next (last_thread
);
1424 if (res
== first_thread
)
1427 gdb_buf
[gdb_blen
++] = ',';
1430 if (gdb_blen
> sizeof (gdb_buf
) - 16)
1437 else if (pktlen
> QTHREADEXTRAINFO_LEN
1438 && ots$
strcmp_eql (pkt
, QTHREADEXTRAINFO_LEN
,
1439 qthreadextrainfo
, QTHREADEXTRAINFO_LEN
))
1441 /* Get extra info about a thread. */
1443 unsigned int pos
= QTHREADEXTRAINFO_LEN
;
1444 pthreadDebugThreadInfo_t info
;
1451 thr
= (pthread_t
) pkt2val (pkt
, &pos
);
1452 if (pkt
[pos
] != '#')
1454 res
= pthread_debug_thd_get_info_addr (thr
, &info
);
1457 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", thr
, res
);
1462 mem2hex ((const unsigned char *)"VMS-thread", 11);
1464 else if (pktlen
> QSUPPORTED_LEN
1465 && ots$
strcmp_eql (pkt
, QSUPPORTED_LEN
,
1466 qsupported
, QSUPPORTED_LEN
))
1468 /* Get supported features. */
1470 unsigned int pos
= QSUPPORTED_LEN
;
1471 pthreadDebugThreadInfo_t info
;
1474 /* Ignore gdb features. */
1478 str2pkt ("qXfer:uib:read+");
1485 term_puts ("unknown <: ");
1486 term_write ((char *)pkt
, pktlen
);
1493 /* Handle the 'v' packet. */
1496 handle_v_packet (const unsigned char *pkt
, unsigned int pktlen
)
1498 static const char vcontq
[] = "vCont?";
1499 #define VCONTQ_LEN (sizeof (vcontq) - 1)
1501 if (pktlen
== VCONTQ_LEN
1502 && ots$
strcmp_eql (pkt
, VCONTQ_LEN
, vcontq
, VCONTQ_LEN
))
1507 str2pkt ("vCont;c;s");
1514 term_puts ("unknown <: ");
1515 term_write ((char *)pkt
, pktlen
);
1522 /* Get regs for the selected thread. */
1524 static struct ia64_all_regs
*
1525 get_selected_regs (void)
1527 pthreadDebugRegs_t regs
;
1530 if (selected_thread
== 0 || selected_thread
== get_teb ())
1533 if (selected_thread
== sel_regs_pthread
)
1536 /* Read registers. */
1537 res
= pthread_debug_thd_get_reg (selected_id
, ®s
);
1540 /* FIXME: return NULL ? */
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
;
1563 /* Create a status packet. */
1566 packet_status (void)
1571 str2pkt ("$T05thread:");
1572 long2pkt ((unsigned long) get_teb ());
1573 gdb_buf
[gdb_blen
++] = ';';
1579 /* Return 1 to continue. */
1582 handle_packet (unsigned char *pkt
, unsigned int len
)
1586 /* By default, reply unsupported. */
1604 excp_regs
.psr
.v
&= ~(unsigned __int64
)PSR$M_SS
;
1614 struct ia64_all_regs
*regs
= get_selected_regs ();
1615 unsigned char *p
= regs
->gr
[0].b
;
1617 for (i
= 0; i
< 8 * 32; i
++)
1618 byte2hex (gdb_buf
+ 1 + 2 * i
, p
[i
]);
1619 gdb_blen
+= 2 * 8 * 32;
1627 unsigned __int64 val
;
1628 pthreadDebugThreadInfo_t info
;
1631 val
= pkt2val (pkt
, &pos
);
1640 selected_thread
= get_teb ();
1643 else if (!has_threads
)
1650 res
= pthread_debug_thd_get_info_addr ((pthread_t
) val
, &info
);
1653 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", val
, res
);
1657 selected_thread
= info
.teb
;
1658 selected_id
= info
.sequence
;
1663 else if (pkt
[1] == 'c'
1664 && ((pkt
[2] == '-' && pkt
[3] == '1' && len
== 4)
1665 || (pkt
[2] == '0' && len
== 3)))
1667 /* Silently accept 'Hc0' and 'Hc-1'. */
1677 SYS$
EXIT (SS$_NORMAL
);
1681 unsigned __int64 addr
;
1682 unsigned __int64 paddr
;
1686 addr
= pkt2val (pkt
, &pos
);
1687 if (pkt
[pos
] != ',')
1693 l
= pkt2val (pkt
, &pos
);
1694 if (pkt
[pos
] != '#')
1701 i
= l
+ (addr
& VMS_PAGE_MASK
);
1702 paddr
= addr
& ~VMS_PAGE_MASK
;
1705 if (__prober (paddr
, 0) != 1)
1710 if (i
< VMS_PAGE_SIZE
)
1713 paddr
+= VMS_PAGE_SIZE
;
1717 for (i
= 0; i
< l
; i
++)
1718 byte2hex (gdb_buf
+ 1 + 2 * i
, ((unsigned char *)addr
)[i
]);
1724 unsigned __int64 addr
;
1725 unsigned __int64 paddr
;
1728 unsigned int oldprot
;
1730 addr
= pkt2val (pkt
, &pos
);
1731 if (pkt
[pos
] != ',')
1737 l
= pkt2val (pkt
, &pos
);
1738 if (pkt
[pos
] != ':')
1744 page_set_rw (addr
, l
, &oldprot
);
1747 i
= l
+ (addr
& VMS_PAGE_MASK
);
1748 paddr
= addr
& ~VMS_PAGE_MASK
;
1751 if (__probew (paddr
, 0) != 1)
1753 page_restore_rw (addr
, l
, oldprot
);
1756 if (i
< VMS_PAGE_SIZE
)
1759 paddr
+= VMS_PAGE_SIZE
;
1763 for (i
= 0; i
< l
; i
++)
1765 int v
= hex2byte (pkt
+ pos
);
1767 ((unsigned char *)addr
)[i
] = v
;
1771 for (i
= 0; i
< l
; i
+= 15)
1775 page_restore_rw (addr
, l
, oldprot
);
1781 unsigned int num
= 0;
1783 struct ia64_all_regs
*regs
= get_selected_regs ();
1785 num
= pkt2val (pkt
, &pos
);
1794 case IA64_IP_REGNUM
:
1795 ireg2pkt (regs
->ip
.b
);
1797 case IA64_BR0_REGNUM
:
1798 ireg2pkt (regs
->br
[0].b
);
1800 case IA64_PSR_REGNUM
:
1801 ireg2pkt (regs
->psr
.b
);
1803 case IA64_BSP_REGNUM
:
1804 ireg2pkt (regs
->bsp
.b
);
1806 case IA64_CFM_REGNUM
:
1807 ireg2pkt (regs
->cfm
.b
);
1809 case IA64_PFS_REGNUM
:
1810 ireg2pkt (regs
->pfs
.b
);
1812 case IA64_PR_REGNUM
:
1813 ireg2pkt (regs
->pr
.b
);
1816 TERM_FAO ("gdbserv: unhandled reg !UW!/", num
);
1823 handle_q_packet (pkt
, len
);
1829 excp_regs
.psr
.v
|= (unsigned __int64
)PSR$M_SS
;
1836 /* Thread status. */
1845 unsigned __int64 val
;
1846 unsigned int fthr
, thr
;
1848 val
= pkt2val (pkt
, &pos
);
1849 /* Default is error (but only after parsing is complete). */
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);
1866 thr
= thread_next (thr
);
1868 while (thr
!= fthr
);
1872 return handle_v_packet (pkt
, len
);
1875 if (len
> 3 && pkt
[1] == 'M' && pkt
[2] == 'S' && pkt
[3] == ' ')
1877 /* Temporary extension. */
1881 stub_pthread_debug_cmd ((char *)pkt
+ 4);
1891 term_puts ("unknown <: ");
1892 term_write ((char *)pkt
, len
);
1900 /* Raw write to gdb. */
1903 sock_write (const unsigned char *buf
, int len
)
1906 unsigned int status
;
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. */
1918 if (status
& STS$M_SUCCESS
)
1919 status
= iosb
.iosb$w_status
;
1920 if (!(status
& STS$M_SUCCESS
))
1922 term_puts ("Failed to write data to gdb\n");
1923 LIB$
SIGNAL (status
);
1927 /* Compute the checksum and send the packet. */
1932 unsigned char chksum
= 0;
1935 for (i
= 1; i
< gdb_blen
; i
++)
1936 chksum
+= gdb_buf
[i
];
1938 gdb_buf
[gdb_blen
] = '#';
1939 byte2hex (gdb_buf
+ gdb_blen
+ 1, chksum
);
1941 sock_write (gdb_buf
, gdb_blen
+ 3);
1946 term_write ((char *)gdb_buf
, gdb_blen
+ 3);
1951 /* Read and handle one command. Return 1 is execution must resume. */
1957 unsigned int status
;
1959 unsigned int dollar_off
= 0;
1960 unsigned int sharp_off
= 0;
1961 unsigned int cmd_off
;
1962 unsigned int cmd_len
;
1964 /* Wait for a packet. */
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. */
1980 if (status
& STS$M_SUCCESS
)
1981 status
= iosb
.iosb$w_status
;
1982 if (!(status
& STS$M_SUCCESS
))
1984 term_puts ("Failed to read data from connection\n" );
1985 LIB$
SIGNAL (status
);
1990 term_write ((char *)gdb_buf
+ off
, iosb
.iosb$w_bcnt
);
1994 gdb_blen
= off
+ iosb
.iosb$w_bcnt
;
1998 /* Search for '$'. */
1999 for (dollar_off
= 0; dollar_off
< gdb_blen
; dollar_off
++)
2000 if (gdb_buf
[dollar_off
] == '$')
2002 if (dollar_off
>= gdb_blen
)
2004 /* Not found, discard the data. */
2008 /* Search for '#'. */
2009 for (sharp_off
= dollar_off
+ 1;
2010 sharp_off
< gdb_blen
;
2012 if (gdb_buf
[sharp_off
] == '#')
2015 else if (sharp_off
>= off
)
2017 /* Search for '#'. */
2018 for (; sharp_off
< gdb_blen
; sharp_off
++)
2019 if (gdb_buf
[sharp_off
] == '#')
2023 /* Got packet with checksum. */
2024 if (sharp_off
+ 2 <= gdb_blen
)
2028 if (gdb_blen
== sizeof (gdb_buf
))
2030 /* Packet too large, discard. */
2035 /* Validate and acknowledge a packet. */
2037 unsigned char chksum
= 0;
2041 for (i
= dollar_off
+ 1; i
< sharp_off
; i
++)
2042 chksum
+= gdb_buf
[i
];
2043 v
= hex2byte (gdb_buf
+ sharp_off
+ 1);
2046 term_puts ("Discard bad checksum packet\n");
2051 sock_write ((const unsigned char *)"+", 1);
2060 term_write ((char *)gdb_buf
+ dollar_off
, sharp_off
- dollar_off
+ 1);
2064 cmd_off
= dollar_off
+ 1;
2065 cmd_len
= sharp_off
- dollar_off
- 1;
2067 if (handle_packet (gdb_buf
+ dollar_off
+ 1, sharp_off
- dollar_off
- 1) == 1)
2074 /* Display the condition given by SIG64. */
2077 display_excp (struct chf64$signal_array
*sig64
, struct chf$mech_array
*mech
)
2079 unsigned int status
;
2081 unsigned short msglen
;
2082 $
DESCRIPTOR (msg_desc
, msg
);
2083 unsigned char outadr
[4];
2085 status
= SYS$
GETMSG (sig64
->chf64$q_sig_name
, &msglen
, &msg_desc
, 0, outadr
);
2086 if (status
& STS$M_SUCCESS
)
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
);
2099 term_puts ("no message");
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
);
2110 /* Get all registers from current thread. */
2113 read_all_registers (struct chf$mech_array
*mech
)
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];
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.
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);
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
;
2177 /* Write all registers to current thread. FIXME: not yet complete. */
2180 write_all_registers (struct chf$mech_array
*mech
)
2182 struct _intstk
*intstk
=
2183 (struct _intstk
*)mech
->chf$q_mch_esf_addr
;
2185 intstk
->intstk$q_ipsr
= excp_regs
.psr
.v
;
2188 /* Do debugging. Report status to gdb and execute commands. */
2191 do_debug (struct chf$mech_array
*mech
)
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
;
2200 status
= sys$
setast (0);
2210 /* Should never happen! */
2211 lib$
signal (status
);
2214 /* Disable thread scheduling. */
2216 old_sch
= set_thread_scheduling (0);
2218 read_all_registers (mech
);
2220 /* Send stop reply packet. */
2224 while (one_command () == 0)
2227 write_all_registers (mech
);
2229 /* Re-enable scheduling. */
2231 set_thread_scheduling (old_sch
);
2233 /* Re-enable AST. */
2234 status
= sys$
setast (old_ast
);
2235 if (!(status
& STS$M_SUCCESS
))
2236 LIB$
SIGNAL (status
);
2239 /* The condition handler. That's the core of the stub. */
2242 excp_handler (struct chf$signal_array
*sig
,
2243 struct chf$mech_array
*mech
)
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
;
2251 /* Self protection. FIXME: Should be per thread ? */
2252 static int in_handler
= 0;
2254 /* Completely ignore some conditions (signaled indirectly by this stub). */
2257 case LIB$_KEYNOTFOU
& STS$M_COND_ID
:
2258 return SS$_RESIGNAL_64
;
2263 /* Protect against recursion. */
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
);
2273 pc
= (&sig64
->chf64$q_sig_name
)[cnt
- 2];
2275 TERM_FAO ("excp_handler: code: !XL, pc=!XH!/", code
, pc
);
2277 /* If break on the entry point, restore the bundle. */
2278 if (code
== (SS$_BREAK
& STS$M_COND_ID
)
2282 static unsigned int entry_prot
;
2285 term_puts ("initial entry breakpoint\n");
2286 page_set_rw (entry_pc
, 16, &entry_prot
);
2288 ots$
move ((void *)entry_pc
, 16, entry_saved
);
2290 page_restore_rw (entry_pc
, 16, entry_prot
);
2295 case SS$_ACCVIO
& STS$M_COND_ID
:
2296 if (trace_excp
<= 1)
2297 display_excp (sig64
, mech
);
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
:
2306 struct _intstk
*intstk
=
2307 (struct _intstk
*)mech
->chf$q_mch_esf_addr
;
2309 display_excp (sig64
, mech
);
2311 TERM_FAO (" intstk: !XH!/", intstk
);
2312 for (i
= 0; i
< cnt
+ 1; i
++)
2313 TERM_FAO (" !XH!/", ((unsigned __int64
*)sig64
)[i
]);
2316 ret
= SS$_CONTINUE_64
;
2320 display_excp (sig64
, mech
);
2321 ret
= SS$_RESIGNAL_64
;
2326 /* Discard selected thread registers. */
2327 sel_regs_pthread
= 0;
2331 /* Setup internal trace flags according to GDBSTUB$TRACE logical. */
2336 unsigned int status
, i
, start
;
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
);
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;
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
)
2359 if (!(status
& STS$M_SUCCESS
))
2360 LIB$
SIGNAL (status
);
2363 for (i
= 0; i
<= len
; i
++)
2365 if ((i
== len
|| resstring
[i
] == ',' || resstring
[i
] == ';')
2370 sub_desc
.dsc$a_pointer
= resstring
+ start
;
2371 sub_desc
.dsc$w_length
= i
- start
;
2373 for (j
= 0; j
< NBR_DEBUG_FLAGS
; j
++)
2374 if (str$
case_blind_compare (&sub_desc
,
2375 (void *)&debug_flags
[j
].name
) == 0)
2377 debug_flags
[j
].val
++;
2380 if (j
== NBR_DEBUG_FLAGS
)
2381 TERM_FAO ("GDBSTUB$TRACE: unknown directive !AS!/", &sub_desc
);
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
);
2398 stub_start (unsigned __int64
*progxfer
, void *cli_util
,
2399 EIHD
*imghdr
, IFD
*imgfile
,
2400 unsigned int linkflag
, unsigned int cliflag
)
2402 static int initialized
;
2408 term_puts ("gdbstub: re-entry\n");
2412 /* When attached (through SS$_DEBUG condition), the number of arguments
2413 is 4 and PROGXFER is the PC at interruption. */
2415 is_attached
= cnt
== 4;
2420 term_puts ("Hello from gdb stub\n");
2424 if (trace_entry
&& !is_attached
)
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
]);
2432 /* Search for entry point. */
2436 for (i
= 0; progxfer
[i
]; i
++)
2437 entry_pc
= progxfer
[i
];
2443 term_puts ("No entry point\n");
2447 TERM_FAO ("Entry: !XH!/",entry_pc
);
2451 entry_pc
= progxfer
[0];
2454 for (imcb
= ctl$gl_imglstptr
->imcb$l_flink
;
2455 imcb
!= ctl$gl_imglstptr
;
2456 imcb
= imcb
->imcb$l_flink
)
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]))
2467 LDRIMG
*ldrimg
= imcb
->imcb$l_ldrimg
;
2470 TERM_FAO ("!XA-!XA ",
2471 imcb
->imcb$l_starting_address
,
2472 imcb
->imcb$l_end_address
);
2474 switch (imcb
->imcb$b_act_code
)
2476 case IMCB$K_MAIN_PROGRAM
:
2479 case IMCB$K_MERGED_IMAGE
:
2482 case IMCB$K_GLOBAL_IMAGE_SECTION
:
2488 TERM_FAO (" !AD !40AC!/",
2489 1, "KESU" + (imcb
->imcb$b_access_mode
& 3),
2490 imcb
->imcb$t_log_image_name
);
2492 if ((long) ldrimg
< 0 || trace_images
< 2)
2494 ldrisd
= ldrimg
->ldrimg$l_segments
;
2495 for (j
= 0; j
< ldrimg
->ldrimg$l_segcount
; j
++)
2497 unsigned int flags
= ldrisd
[j
].ldrisd$i_flags
;
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);
2510 ldrisd
= ldrimg
->ldrimg$l_dyn_seg
;
2512 TERM_FAO (" dynamic !XA-!XA!/",
2513 ldrisd
->ldrisd$p_base
,
2514 (unsigned __int64
) ldrisd
->ldrisd$p_base
2515 + ldrisd
->ldrisd$i_len
- 1);
2522 /* Wait for connection. */
2525 /* Set primary exception vector. */
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
);
2535 return excp_handler ((struct chf$signal_array
*) progxfer
[2],
2536 (struct chf$mech_array
*) progxfer
[3]);
2539 /* Change first instruction to set a breakpoint. */
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;;
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
;
2553 status
= page_set_rw (entry_pc
, 16, &entry_prot
);
2555 if (!(status
& STS$M_SUCCESS
))
2557 if ((status
& STS$M_COND_ID
) == (SS$_NOT_PROCESS_VA
& STS$M_COND_ID
))
2559 /* Cannot write here. This can happen when pthreads are
2562 term_puts ("gdbstub: cannot set breakpoint on entry\n");
2565 LIB$
SIGNAL (status
);
2570 ots$
move (entry_saved
, 16, (void *)entry_pc
);
2571 ots$
move ((void *)entry_pc
, 16, (void *)initbp
);
2573 page_restore_rw (entry_pc
, 16, entry_prot
);
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. */
2581 while (one_command () == 0)
2586 return SS$_CONTINUE
;
2589 /* Declare the entry point of this relocatable module. */
2593 __int64 impure_start
;
2598 #pragma __extern_model save
2599 #pragma __extern_model strict_refdef "XFER_PSECT"
2600 struct xfer_vector xfer_vector
= {0, 0, stub_start
};
2601 #pragma __extern_model restore