1 /* GDB stub for Itanium OpenVMS
2 Copyright (C) 2012-2015 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