[gdb/tdep] Fix reverse execution of LDR(immediate) T4
[binutils-gdb.git] / gdb / stubs / ia64vms-stub.c
blobe7578d80938974404b6ad4cc099ad7d49fd43520
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
26 calls.
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"
34 #endif
36 #define __NEW_STARLET 1
37 #include <descrip.h>
38 #include <iledef.h>
39 #include <efndef.h>
40 #include <in.h>
41 #include <inet.h>
42 #include <iodef.h>
43 #include <ssdef.h>
44 #include <starlet.h>
45 #include <stsdef.h>
46 #include <tcpip$inetdef.h>
48 #include <lib$routines.h>
49 #include <ots$routines.h>
50 #include <str$routines.h>
51 #include <libdef.h>
52 #include <clidef.h>
53 #include <iosbdef.h>
54 #include <dvidef.h>
55 #include <lnmdef.h>
56 #include <builtins.h>
57 #include <prtdef.h>
58 #include <psldef.h>
59 #include <chfdef.h>
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>
68 #include <stdarg.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. */
124 struct debug_flag
126 /* Name of the flag (as a string descriptor). */
127 const struct dsc$descriptor_s name;
128 /* Value. */
129 int val;
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
167 standard headers. */
168 struct sockchar
170 unsigned short prot;
171 unsigned char type;
172 unsigned char af;
175 /* Chain of images loaded. */
176 extern IMCB* ctl$gl_imglstptr;
178 /* IA64 integer register representation. */
179 union ia64_ireg
181 unsigned __int64 v;
182 unsigned char b[8];
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
252 these. */
253 #define IA64_NAT0_REGNUM 462
255 /* Process registers when a condition is caught. */
256 struct ia64_all_regs
258 union ia64_ireg gr[32];
259 union ia64_ireg br[8];
260 union ia64_ireg ip;
261 union ia64_ireg psr;
262 union ia64_ireg bsp;
263 union ia64_ireg cfm;
264 union ia64_ireg pfs;
265 union ia64_ireg pr;
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. */
292 static void
293 term_raw_write (const char *str, unsigned int len)
295 unsigned short status;
296 struct _iosb iosb;
298 status = sys$qiow (EFN$C_ENF, /* Event flag. */
299 term_chan, /* I/O channel. */
300 IO$_WRITEVBLK, /* I/O function code. */
301 &iosb, /* I/O status block. */
302 0, /* Ast service routine. */
303 0, /* Ast parameter. */
304 (char *)str, /* P1 - buffer address. */
305 len, /* P2 - buffer length. */
306 0, 0, 0, 0);
308 if (status & STS$M_SUCCESS)
309 status = iosb.iosb$w_status;
310 if (!(status & STS$M_SUCCESS))
311 LIB$SIGNAL (status);
314 /* Flush ther term buffer. */
316 static void
317 term_flush (void)
319 if (term_buf_len != 0)
321 term_raw_write (term_buf, term_buf_len);
322 term_buf_len = 0;
326 /* Write a single character, without translation. */
328 static void
329 term_raw_putchar (char c)
331 if (term_buf_len == sizeof (term_buf))
332 term_flush ();
333 term_buf[term_buf_len++] = c;
336 /* Write character C. Translate '\n' to '\n\r'. */
338 static void
339 term_putc (char c)
341 if (c < 32)
342 switch (c)
344 case '\r':
345 case '\n':
346 break;
347 default:
348 c = '.';
349 break;
351 term_raw_putchar (c);
352 if (c == '\n')
354 term_raw_putchar ('\r');
355 term_flush ();
359 /* Write a C string. */
361 static void
362 term_puts (const char *str)
364 while (*str)
365 term_putc (*str++);
368 /* Write LEN bytes from STR. */
370 static void
371 term_write (const char *str, unsigned int len)
373 for (; len > 0; len--)
374 term_putc (*str++);
377 /* Write using FAO formatting. */
379 static void
380 term_fao (const char *str, unsigned int str_len, ...)
382 int cnt;
383 va_list vargs;
384 int i;
385 __int64 *args;
386 int status;
387 struct dsc$descriptor_s dstr =
388 { str_len, DSC$K_DTYPE_T, DSC$K_CLASS_S, (__char_ptr32)str };
389 char buf[128];
390 $DESCRIPTOR (buf_desc, buf);
392 va_start (vargs, str_len);
393 va_count (cnt);
394 args = (__int64 *) __ALLOCA (cnt * sizeof (__int64));
395 cnt -= 2;
396 for (i = 0; i < cnt; i++)
397 args[i] = va_arg (vargs, __int64);
399 status = sys$faol_64 (&dstr, &buf_desc.dsc$w_length, &buf_desc, args);
400 if (status & 1)
402 /* FAO !/ already insert a line feed. */
403 for (i = 0; i < buf_desc.dsc$w_length; i++)
405 term_raw_putchar (buf[i]);
406 if (buf[i] == '\n')
407 term_flush ();
411 va_end (vargs);
414 #define TERM_FAO(STR, ...) term_fao (STR, sizeof (STR) - 1, __VA_ARGS__)
416 /* New line. */
418 static void
419 term_putnl (void)
421 term_putc ('\n');
424 /* Initialize terminal. */
426 static void
427 term_init (void)
429 unsigned int status,i;
430 unsigned short len;
431 char resstring[LNM$C_NAMLENGTH];
432 static const $DESCRIPTOR (tabdesc, "LNM$FILE_DEV");
433 static const $DESCRIPTOR (logdesc, "SYS$OUTPUT");
434 $DESCRIPTOR (term_desc, resstring);
435 ILE3 item_lst[2];
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))
451 LIB$SIGNAL (status);
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))
468 LIB$SIGNAL (status);
471 /* Convert from native endianness to network endianness (and vice-versa). */
473 static unsigned int
474 wordswap (unsigned int v)
476 return ((v & 0xff) << 8) | ((v >> 8) & 0xff);
479 /* Initialize the socket connection, and wait for a client. */
481 static void
482 sock_init (void)
484 struct _iosb iosb;
485 unsigned int status;
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;
494 ILE3 cli_itemlst;
496 /* Our address. */
497 struct sockaddr_in serv_addr;
498 ILE2 serv_itemlst;
500 /* Reuseaddr option value (on). */
501 int optval = 1;
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");
520 LIB$SIGNAL (status);
523 /* Create a listen socket. */
524 status = sys$qiow (EFN$C_ENF, /* Event flag. */
525 listen_channel, /* I/O channel. */
526 IO$_SETMODE, /* I/O function code. */
527 &iosb, /* I/O status block. */
528 0, /* Ast service routine. */
529 0, /* Ast parameter. */
530 &listen_sockchar, /* P1 - socket characteristics. */
531 0, 0, 0, 0, 0);
532 if (status & STS$M_SUCCESS)
533 status = iosb.iosb$w_status;
534 if (!(status & STS$M_SUCCESS))
536 term_puts ("Failed to create socket\n");
537 LIB$SIGNAL (status);
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. */
557 0, /* P1. */
558 0, /* P2. */
559 0, /* P3. */
560 0, /* P4. */
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");
568 LIB$SIGNAL (status);
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. */
589 0, /* P1. */
590 0, /* P2. */
591 (__int64) &serv_itemlst, /* P3 - local socket name. */
592 0, 0, 0);
593 if (status & STS$M_SUCCESS)
594 status = iosb.iosb$w_status;
595 if (!(status & STS$M_SUCCESS))
597 term_puts ("Failed to bind socket\n");
598 LIB$SIGNAL (status);
601 /* Set socket as a listen socket. */
602 status = sys$qiow (EFN$C_ENF, /* Event flag. */
603 listen_channel, /* I/O channel. */
604 IO$_SETMODE, /* I/O function code. */
605 &iosb, /* I/O status block. */
606 0, /* Ast service routine. */
607 0, /* Ast parameter. */
608 0, /* P1. */
609 0, /* P2. */
610 0, /* P3. */
611 1, /* P4 - connection backlog. */
612 0, 0);
613 if (status & STS$M_SUCCESS)
614 status = iosb.iosb$w_status;
615 if (!(status & STS$M_SUCCESS))
617 term_puts ("Failed to set socket passive\n");
618 LIB$SIGNAL (status);
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. */
631 0, /* P1. */
632 0, /* P2. */
633 0, /* P3. */
634 (__int64) &conn_channel, /* P4 - I/O channel for conn. */
635 0, 0);
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");
642 LIB$SIGNAL (status);
645 /* Log client connection request. */
646 cli_itemlst.ile3$w_length = sizeof (cli_addr);
647 cli_itemlst.ile3$w_code = TCPIP$C_SOCK_NAME;
648 cli_itemlst.ile3$ps_bufaddr = &cli_addr;
649 cli_itemlst.ile3$ps_retlen_addr = &cli_addrlen;
650 ots$fill (&cli_addr, sizeof(cli_addr), 0);
651 status = sys$qiow (EFN$C_ENF, /* Event flag. */
652 conn_channel, /* I/O channel. */
653 IO$_SENSEMODE, /* I/O function code. */
654 &iosb, /* I/O status block. */
655 0, /* Ast service routine. */
656 0, /* Ast parameter. */
657 0, /* P1. */
658 0, /* P2. */
659 0, /* P3. */
660 (__int64) &cli_itemlst, /* P4 - peer socket name. */
661 0, 0);
662 if (status & STS$M_SUCCESS)
663 status = iosb.iosb$w_status;
664 if (!(status & STS$M_SUCCESS))
666 term_puts ("Failed to get client name\n");
667 LIB$SIGNAL (status);
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. */
680 static void
681 sock_close (void)
683 struct _iosb iosb;
684 unsigned int status;
686 /* Close socket. */
687 status = sys$qiow (EFN$C_ENF, /* Event flag. */
688 conn_channel, /* I/O channel. */
689 IO$_DEACCESS, /* I/O function code. */
690 &iosb, /* I/O status block. */
691 0, /* Ast service routine. */
692 0, /* Ast parameter. */
693 0, 0, 0, 0, 0, 0);
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");
700 LIB$SIGNAL (status);
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");
709 LIB$SIGNAL (status);
713 /* Mark a page as R/W. Return old rights. */
715 static unsigned int
716 page_set_rw (unsigned __int64 startva, unsigned __int64 len,
717 unsigned int *oldprot)
719 unsigned int status;
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);
725 return status;
728 /* Restore page rights. */
730 static void
731 page_restore_rw (unsigned __int64 startva, unsigned __int64 len,
732 unsigned int prot)
734 unsigned int status;
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))
742 LIB$SIGNAL (status);
745 /* Get the TEB (thread environment block). */
747 static pthread_t
748 get_teb (void)
750 return (pthread_t)__getReg (_IA64_REG_TP);
753 /* Enable thread scheduling if VAL is true. */
755 static unsigned int
756 set_thread_scheduling (int val)
758 struct dbgext_control_block blk;
759 unsigned int status;
761 if (!dbgext_func)
762 return 0;
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);
773 lib$signal (status);
776 return blk.dbgext$l_stop_value;
779 /* Get next thread (after THR). Start with 0. */
781 static unsigned int
782 thread_next (unsigned int thr)
784 struct dbgext_control_block blk;
785 unsigned int status;
787 if (!dbgext_func)
788 return 0;
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))
797 lib$signal (status);
799 return blk.dbgext$l_task_value;
802 /* Pthread Debug callbacks. */
804 static int
805 read_callback (pthreadDebugClient_t context,
806 pthreadDebugTargetAddr_t addr,
807 pthreadDebugAddr_t buf,
808 size_t size)
810 if (trace_pthreaddbg)
811 TERM_FAO ("read_callback (!XH, !XH, !SL)!/", addr, buf, size);
812 ots$move (buf, size, addr);
813 return 0;
816 static int
817 write_callback (pthreadDebugClient_t context,
818 pthreadDebugTargetAddr_t addr,
819 pthreadDebugLongConstAddr_t buf,
820 size_t size)
822 if (trace_pthreaddbg)
823 TERM_FAO ("write_callback (!XH, !XH, !SL)!/", addr, buf, size);
824 ots$move (addr, size, buf);
825 return 0;
828 static int
829 suspend_callback (pthreadDebugClient_t context)
831 /* Always suspended. */
832 return 0;
835 static int
836 resume_callback (pthreadDebugClient_t context)
838 /* So no need to resume. */
839 return 0;
842 static int
843 kthdinfo_callback (pthreadDebugClient_t context,
844 pthreadDebugKId_t kid,
845 pthreadDebugKThreadInfo_p thread_info)
847 if (trace_pthreaddbg)
848 term_puts ("kthinfo_callback");
849 return ENOSYS;
852 static int
853 hold_callback (pthreadDebugClient_t context,
854 pthreadDebugKId_t kid)
856 if (trace_pthreaddbg)
857 term_puts ("hold_callback");
858 return ENOSYS;
861 static int
862 unhold_callback (pthreadDebugClient_t context,
863 pthreadDebugKId_t kid)
865 if (trace_pthreaddbg)
866 term_puts ("unhold_callback");
867 return ENOSYS;
870 static int
871 getfreg_callback (pthreadDebugClient_t context,
872 pthreadDebugFregs_t *reg,
873 pthreadDebugKId_t kid)
875 if (trace_pthreaddbg)
876 term_puts ("getfreg_callback");
877 return ENOSYS;
880 static int
881 setfreg_callback (pthreadDebugClient_t context,
882 const pthreadDebugFregs_t *reg,
883 pthreadDebugKId_t kid)
885 if (trace_pthreaddbg)
886 term_puts ("setfreg_callback");
887 return ENOSYS;
890 static int
891 getreg_callback (pthreadDebugClient_t context,
892 pthreadDebugRegs_t *reg,
893 pthreadDebugKId_t kid)
895 if (trace_pthreaddbg)
896 term_puts ("getreg_callback");
897 return ENOSYS;
900 static int
901 setreg_callback (pthreadDebugClient_t context,
902 const pthreadDebugRegs_t *reg,
903 pthreadDebugKId_t kid)
905 if (trace_pthreaddbg)
906 term_puts ("setreg_callback");
907 return ENOSYS;
910 static int
911 output_callback (pthreadDebugClient_t context,
912 pthreadDebugConstString_t line)
914 term_puts (line);
915 term_putnl ();
916 return 0;
919 static int
920 error_callback (pthreadDebugClient_t context,
921 pthreadDebugConstString_t line)
923 term_puts (line);
924 term_putnl ();
925 return 0;
928 static pthreadDebugAddr_t
929 malloc_callback (pthreadDebugClient_t caller_context, size_t size)
931 unsigned int status;
932 unsigned int res;
933 int len;
935 len = size + 16;
936 status = lib$get_vm (&len, &res, 0);
937 if (!(status & STS$M_SUCCESS))
938 LIB$SIGNAL (status);
939 if (trace_pthreaddbg)
940 TERM_FAO ("malloc_callback (!UL) -> !XA!/", size, res);
941 *(unsigned int *)res = len;
942 return (char *)res + 16;
945 static void
946 free_callback (pthreadDebugClient_t caller_context, pthreadDebugAddr_t address)
948 unsigned int status;
949 unsigned int res;
950 int len;
952 res = (unsigned int)address - 16;
953 len = *(unsigned int *)res;
954 if (trace_pthreaddbg)
955 TERM_FAO ("free_callback (!XA)!/", address);
956 status = lib$free_vm (&len, &res, 0);
957 if (!(status & STS$M_SUCCESS))
958 LIB$SIGNAL (status);
961 static int
962 speckthd_callback (pthreadDebugClient_t caller_context,
963 pthreadDebugSpecialType_t type,
964 pthreadDebugKId_t *kernel_tid)
966 return ENOTSUP;
969 static pthreadDebugCallbacks_t pthread_debug_callbacks = {
970 PTHREAD_DEBUG_VERSION,
971 read_callback,
972 write_callback,
973 suspend_callback,
974 resume_callback,
975 kthdinfo_callback,
976 hold_callback,
977 unhold_callback,
978 getfreg_callback,
979 setfreg_callback,
980 getreg_callback,
981 setreg_callback,
982 output_callback,
983 error_callback,
984 malloc_callback,
985 free_callback,
986 speckthd_callback
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;
997 __void_ptr32 func;
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. */
1018 static int
1019 pthread_debug_thd_seq_init (pthreadDebugId_t *id)
1021 return ((int (*)())pthread_debug_entries[1].func)
1022 (debug_context, id);
1025 static int
1026 pthread_debug_thd_seq_next (pthreadDebugId_t *id)
1028 return ((int (*)())pthread_debug_entries[2].func)
1029 (debug_context, id);
1032 static int
1033 pthread_debug_thd_seq_destroy (void)
1035 return ((int (*)())pthread_debug_entries[3].func)
1036 (debug_context);
1039 static int
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);
1047 static int
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);
1055 static int
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);
1063 static int
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. */
1072 static void
1073 threads_show (void)
1075 pthreadDebugId_t id;
1076 pthreadDebugThreadInfo_t info;
1077 int res;
1079 res = pthread_debug_thd_seq_init (&id);
1080 if (res != 0)
1082 TERM_FAO ("seq init failed, res=!SL!/", res);
1083 return;
1085 while (1)
1087 if (pthread_debug_thd_get_info (id, &info) != 0)
1089 TERM_FAO ("thd_get_info !SL failed!/", id);
1090 break;
1092 if (pthread_debug_thd_seq_next (&id) != 0)
1093 break;
1095 pthread_debug_thd_seq_destroy ();
1098 /* Initialize pthread support. */
1100 static void
1101 threads_init (void)
1103 static const $DESCRIPTOR (dbgext_desc, "PTHREAD$DBGEXT");
1104 static const $DESCRIPTOR (pthread_debug_desc, "PTHREAD$DBGSHR");
1105 static const $DESCRIPTOR (dbgsymtable_desc, "PTHREAD_DBG_SYMTABLE");
1106 int pthread_dbgext;
1107 int status;
1108 void *dbg_symtable;
1109 int i;
1110 void *caller_context = 0;
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. */
1125 for (i = 0;
1126 i < sizeof (pthread_debug_entries) / sizeof (pthread_debug_entries[0]);
1127 i++)
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);
1144 if (status != 0)
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
1150 error. */
1152 static int
1153 hex2nibble (unsigned char h)
1155 if (h >= '0' && h <= '9')
1156 return h - '0';
1157 if (h >= 'A' && h <= 'F')
1158 return h - 'A' + 10;
1159 if (h >= 'a' && h <= 'f')
1160 return h - 'a' + 10;
1161 return -1;
1164 /* Convert an hexadecimal 2 character string to a byte. Return -1 in case
1165 of error. */
1167 static int
1168 hex2byte (const unsigned char *p)
1170 int h, l;
1172 h = hex2nibble (p[0]);
1173 l = hex2nibble (p[1]);
1174 if (h == -1 || l == -1)
1175 return -1;
1176 return (h << 4) | l;
1179 /* Convert a byte V to a 2 character strings P. */
1181 static void
1182 byte2hex (unsigned char *p, unsigned char v)
1184 p[0] = hex[v >> 4];
1185 p[1] = hex[v & 0xf];
1188 /* Convert a quadword V to a 16 character strings P. */
1190 static void
1191 quad2hex (unsigned char *p, unsigned __int64 v)
1193 int i;
1194 for (i = 0; i < 16; i++)
1196 p[i] = hex[v >> 60];
1197 v <<= 4;
1201 static void
1202 long2pkt (unsigned int v)
1204 int i;
1206 for (i = 0; i < 8; i++)
1208 gdb_buf[gdb_blen + i] = hex[(v >> 28) & 0x0f];
1209 v <<= 4;
1211 gdb_blen += 8;
1214 /* Generate an error packet. */
1216 static void
1217 packet_error (unsigned int err)
1219 gdb_buf[1] = 'E';
1220 byte2hex (gdb_buf + 2, err);
1221 gdb_blen = 4;
1224 /* Generate an OK packet. */
1226 static void
1227 packet_ok (void)
1229 gdb_buf[1] = 'O';
1230 gdb_buf[2] = 'K';
1231 gdb_blen = 3;
1234 /* Append a register to the packet. */
1236 static void
1237 ireg2pkt (const unsigned char *p)
1239 int i;
1241 for (i = 0; i < 8; i++)
1243 byte2hex (gdb_buf + gdb_blen, p[i]);
1244 gdb_blen += 2;
1248 /* Append a C string (ASCIZ) to the packet. */
1250 static void
1251 str2pkt (const char *str)
1253 while (*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;
1263 unsigned int i;
1265 while (1)
1267 int r = hex2nibble (pkt[*pos]);
1269 if (r < 0)
1270 return res;
1271 res = (res << 4) | r;
1272 (*pos)++;
1276 /* Append LEN bytes from B to the current gdb packet (encode in binary). */
1278 static void
1279 mem2bin (const unsigned char *b, unsigned int len)
1281 unsigned int i;
1282 for (i = 0; i < len; i++)
1283 switch (b[i])
1285 case '#':
1286 case '$':
1287 case '}':
1288 case '*':
1289 case 0:
1290 gdb_buf[gdb_blen++] = '}';
1291 gdb_buf[gdb_blen++] = b[i] ^ 0x20;
1292 break;
1293 default:
1294 gdb_buf[gdb_blen++] = b[i];
1295 break;
1299 /* Append LEN bytes from B to the current gdb packet (encode in hex). */
1301 static void
1302 mem2hex (const unsigned char *b, unsigned int len)
1304 unsigned int i;
1305 for (i = 0; i < len; i++)
1307 byte2hex (gdb_buf + gdb_blen, b[i]);
1308 gdb_blen += 2;
1312 /* Handle the 'q' packet. */
1314 static void
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. */
1335 gdb_buf[0] = '$';
1336 gdb_buf[1] = 'Q';
1337 gdb_buf[2] = 'C';
1338 gdb_blen = 3;
1339 if (has_threads)
1340 long2pkt ((unsigned long) get_teb ());
1341 return;
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;
1349 unsigned int off;
1350 unsigned int len;
1351 union
1353 unsigned char bytes[32];
1354 struct
1356 unsigned __int64 code_start_va;
1357 unsigned __int64 code_end_va;
1358 unsigned __int64 uib_start_va;
1359 unsigned __int64 gp_value;
1360 } data;
1361 } uei;
1362 int res;
1363 int i;
1365 packet_error (0);
1367 pc = pkt2val (pkt, &pos);
1368 if (pkt[pos] != ':')
1369 return;
1370 pos++;
1371 off = pkt2val (pkt, &pos);
1372 if (pkt[pos] != ',' || off != 0)
1373 return;
1374 pos++;
1375 len = pkt2val (pkt, &pos);
1376 if (pkt[pos] != '#' || len != 0x20)
1377 return;
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);
1383 if (trace_unwind)
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);
1389 gdb_buf[0] = '$';
1390 gdb_buf[1] = 'l';
1391 gdb_blen = 2;
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). */
1399 gdb_buf[0] = '$';
1400 gdb_buf[1] = 'm';
1401 gdb_blen = 2;
1403 if (!has_threads)
1405 gdb_buf[1] = 'l';
1406 return;
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. */
1417 gdb_buf[0] = '$';
1418 gdb_buf[1] = 'm';
1419 gdb_blen = 2;
1420 while (dbgext_func)
1422 unsigned int res;
1423 res = thread_next (last_thread);
1424 if (res == first_thread)
1425 break;
1426 if (gdb_blen > 2)
1427 gdb_buf[gdb_blen++] = ',';
1428 long2pkt (res);
1429 last_thread = res;
1430 if (gdb_blen > sizeof (gdb_buf) - 16)
1431 break;
1434 if (gdb_blen == 2)
1435 gdb_buf[1] = 'l';
1437 else if (pktlen > QTHREADEXTRAINFO_LEN
1438 && ots$strcmp_eql (pkt, QTHREADEXTRAINFO_LEN,
1439 qthreadextrainfo, QTHREADEXTRAINFO_LEN))
1441 /* Get extra info about a thread. */
1442 pthread_t thr;
1443 unsigned int pos = QTHREADEXTRAINFO_LEN;
1444 pthreadDebugThreadInfo_t info;
1445 int res;
1447 packet_error (0);
1448 if (!has_threads)
1449 return;
1451 thr = (pthread_t) pkt2val (pkt, &pos);
1452 if (pkt[pos] != '#')
1453 return;
1454 res = pthread_debug_thd_get_info_addr (thr, &info);
1455 if (res != 0)
1457 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", thr, res);
1458 return;
1460 gdb_buf[0] = '$';
1461 gdb_blen = 1;
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. */
1469 pthread_t thr;
1470 unsigned int pos = QSUPPORTED_LEN;
1471 pthreadDebugThreadInfo_t info;
1472 int res;
1474 /* Ignore gdb features. */
1475 gdb_buf[0] = '$';
1476 gdb_blen = 1;
1478 str2pkt ("qXfer:uib:read+");
1479 return;
1481 else
1483 if (trace_pkt)
1485 term_puts ("unknown <: ");
1486 term_write ((char *)pkt, pktlen);
1487 term_putnl ();
1489 return;
1493 /* Handle the 'v' packet. */
1495 static int
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))
1504 gdb_buf[0] = '$';
1505 gdb_blen = 1;
1507 str2pkt ("vCont;c;s");
1508 return 0;
1510 else
1512 if (trace_pkt)
1514 term_puts ("unknown <: ");
1515 term_write ((char *)pkt, pktlen);
1516 term_putnl ();
1518 return 0;
1522 /* Get regs for the selected thread. */
1524 static struct ia64_all_regs *
1525 get_selected_regs (void)
1527 pthreadDebugRegs_t regs;
1528 int res;
1530 if (selected_thread == 0 || selected_thread == get_teb ())
1531 return &excp_regs;
1533 if (selected_thread == sel_regs_pthread)
1534 return &sel_regs;
1536 /* Read registers. */
1537 res = pthread_debug_thd_get_reg (selected_id, &regs);
1538 if (res != 0)
1540 /* FIXME: return NULL ? */
1541 return &excp_regs;
1543 sel_regs_pthread = selected_thread;
1544 sel_regs.gr[1].v = regs.gp;
1545 sel_regs.gr[4].v = regs.r4;
1546 sel_regs.gr[5].v = regs.r5;
1547 sel_regs.gr[6].v = regs.r6;
1548 sel_regs.gr[7].v = regs.r7;
1549 sel_regs.gr[12].v = regs.sp;
1550 sel_regs.br[0].v = regs.rp;
1551 sel_regs.br[1].v = regs.b1;
1552 sel_regs.br[2].v = regs.b2;
1553 sel_regs.br[3].v = regs.b3;
1554 sel_regs.br[4].v = regs.b4;
1555 sel_regs.br[5].v = regs.b5;
1556 sel_regs.ip.v = regs.ip;
1557 sel_regs.bsp.v = regs.bspstore; /* FIXME: it is correct ? */
1558 sel_regs.pfs.v = regs.pfs;
1559 sel_regs.pr.v = regs.pr;
1560 return &sel_regs;
1563 /* Create a status packet. */
1565 static void
1566 packet_status (void)
1568 gdb_blen = 0;
1569 if (has_threads)
1571 str2pkt ("$T05thread:");
1572 long2pkt ((unsigned long) get_teb ());
1573 gdb_buf[gdb_blen++] = ';';
1575 else
1576 str2pkt ("$S05");
1579 /* Return 1 to continue. */
1581 static int
1582 handle_packet (unsigned char *pkt, unsigned int len)
1584 unsigned int pos;
1586 /* By default, reply unsupported. */
1587 gdb_buf[0] = '$';
1588 gdb_blen = 1;
1590 pos = 1;
1591 switch (pkt[0])
1593 case '?':
1594 if (len == 1)
1596 packet_status ();
1597 return 0;
1599 break;
1600 case 'c':
1601 if (len == 1)
1603 /* Clear psr.ss. */
1604 excp_regs.psr.v &= ~(unsigned __int64)PSR$M_SS;
1605 return 1;
1607 else
1608 packet_error (0);
1609 break;
1610 case 'g':
1611 if (len == 1)
1613 unsigned int i;
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;
1620 return 0;
1622 break;
1623 case 'H':
1624 if (pkt[1] == 'g')
1626 int res;
1627 unsigned __int64 val;
1628 pthreadDebugThreadInfo_t info;
1630 pos++;
1631 val = pkt2val (pkt, &pos);
1632 if (pos != len)
1634 packet_error (0);
1635 return 0;
1637 if (val == 0)
1639 /* Default one. */
1640 selected_thread = get_teb ();
1641 selected_id = 0;
1643 else if (!has_threads)
1645 packet_error (0);
1646 return 0;
1648 else
1650 res = pthread_debug_thd_get_info_addr ((pthread_t) val, &info);
1651 if (res != 0)
1653 TERM_FAO ("qThreadExtraInfo (!XH) failed: !SL!/", val, res);
1654 packet_error (0);
1655 return 0;
1657 selected_thread = info.teb;
1658 selected_id = info.sequence;
1660 packet_ok ();
1661 break;
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'. */
1668 packet_ok ();
1669 break;
1671 else
1673 packet_error (0);
1674 return 0;
1676 case 'k':
1677 SYS$EXIT (SS$_NORMAL);
1678 break;
1679 case 'm':
1681 unsigned __int64 addr;
1682 unsigned __int64 paddr;
1683 unsigned int l;
1684 unsigned int i;
1686 addr = pkt2val (pkt, &pos);
1687 if (pkt[pos] != ',')
1689 packet_error (0);
1690 return 0;
1692 pos++;
1693 l = pkt2val (pkt, &pos);
1694 if (pkt[pos] != '#')
1696 packet_error (0);
1697 return 0;
1700 /* Check access. */
1701 i = l + (addr & VMS_PAGE_MASK);
1702 paddr = addr & ~VMS_PAGE_MASK;
1703 while (1)
1705 if (__prober (paddr, 0) != 1)
1707 packet_error (2);
1708 return 0;
1710 if (i < VMS_PAGE_SIZE)
1711 break;
1712 i -= VMS_PAGE_SIZE;
1713 paddr += VMS_PAGE_SIZE;
1716 /* Transfer. */
1717 for (i = 0; i < l; i++)
1718 byte2hex (gdb_buf + 1 + 2 * i, ((unsigned char *)addr)[i]);
1719 gdb_blen += 2 * l;
1721 break;
1722 case 'M':
1724 unsigned __int64 addr;
1725 unsigned __int64 paddr;
1726 unsigned int l;
1727 unsigned int i;
1728 unsigned int oldprot;
1730 addr = pkt2val (pkt, &pos);
1731 if (pkt[pos] != ',')
1733 packet_error (0);
1734 return 0;
1736 pos++;
1737 l = pkt2val (pkt, &pos);
1738 if (pkt[pos] != ':')
1740 packet_error (0);
1741 return 0;
1743 pos++;
1744 page_set_rw (addr, l, &oldprot);
1746 /* Check access. */
1747 i = l + (addr & VMS_PAGE_MASK);
1748 paddr = addr & ~VMS_PAGE_MASK;
1749 while (1)
1751 if (__probew (paddr, 0) != 1)
1753 page_restore_rw (addr, l, oldprot);
1754 return 0;
1756 if (i < VMS_PAGE_SIZE)
1757 break;
1758 i -= VMS_PAGE_SIZE;
1759 paddr += VMS_PAGE_SIZE;
1762 /* Write. */
1763 for (i = 0; i < l; i++)
1765 int v = hex2byte (pkt + pos);
1766 pos += 2;
1767 ((unsigned char *)addr)[i] = v;
1770 /* Sync caches. */
1771 for (i = 0; i < l; i += 15)
1772 __fc (addr + i);
1773 __fc (addr + l);
1775 page_restore_rw (addr, l, oldprot);
1776 packet_ok ();
1778 break;
1779 case 'p':
1781 unsigned int num = 0;
1782 unsigned int i;
1783 struct ia64_all_regs *regs = get_selected_regs ();
1785 num = pkt2val (pkt, &pos);
1786 if (pos != len)
1788 packet_error (0);
1789 return 0;
1792 switch (num)
1794 case IA64_IP_REGNUM:
1795 ireg2pkt (regs->ip.b);
1796 break;
1797 case IA64_BR0_REGNUM:
1798 ireg2pkt (regs->br[0].b);
1799 break;
1800 case IA64_PSR_REGNUM:
1801 ireg2pkt (regs->psr.b);
1802 break;
1803 case IA64_BSP_REGNUM:
1804 ireg2pkt (regs->bsp.b);
1805 break;
1806 case IA64_CFM_REGNUM:
1807 ireg2pkt (regs->cfm.b);
1808 break;
1809 case IA64_PFS_REGNUM:
1810 ireg2pkt (regs->pfs.b);
1811 break;
1812 case IA64_PR_REGNUM:
1813 ireg2pkt (regs->pr.b);
1814 break;
1815 default:
1816 TERM_FAO ("gdbserv: unhandled reg !UW!/", num);
1817 packet_error (0);
1818 return 0;
1821 break;
1822 case 'q':
1823 handle_q_packet (pkt, len);
1824 break;
1825 case 's':
1826 if (len == 1)
1828 /* Set psr.ss. */
1829 excp_regs.psr.v |= (unsigned __int64)PSR$M_SS;
1830 return 1;
1832 else
1833 packet_error (0);
1834 break;
1835 case 'T':
1836 /* Thread status. */
1837 if (!has_threads)
1839 packet_ok ();
1840 break;
1842 else
1844 int res;
1845 unsigned __int64 val;
1846 unsigned int fthr, thr;
1848 val = pkt2val (pkt, &pos);
1849 /* Default is error (but only after parsing is complete). */
1850 packet_error (0);
1851 if (pos != len)
1852 break;
1854 /* Follow the list. This makes a O(n2) algorithm, but we don't really
1855 have the choice. Note that pthread_debug_thd_get_info_addr
1856 doesn't look reliable. */
1857 fthr = thread_next (0);
1858 thr = fthr;
1861 if (val == thr)
1863 packet_ok ();
1864 break;
1866 thr = thread_next (thr);
1868 while (thr != fthr);
1870 break;
1871 case 'v':
1872 return handle_v_packet (pkt, len);
1873 break;
1874 case 'V':
1875 if (len > 3 && pkt[1] == 'M' && pkt[2] == 'S' && pkt[3] == ' ')
1877 /* Temporary extension. */
1878 if (has_threads)
1880 pkt[len] = 0;
1881 stub_pthread_debug_cmd ((char *)pkt + 4);
1882 packet_ok ();
1884 else
1885 packet_error (0);
1887 break;
1888 default:
1889 if (trace_pkt)
1891 term_puts ("unknown <: ");
1892 term_write ((char *)pkt, len);
1893 term_putnl ();
1895 break;
1897 return 0;
1900 /* Raw write to gdb. */
1902 static void
1903 sock_write (const unsigned char *buf, int len)
1905 struct _iosb iosb;
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. */
1917 0, 0, 0, 0);
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. */
1929 static void
1930 send_pkt (void)
1932 unsigned char chksum = 0;
1933 unsigned int i;
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);
1943 if (trace_pkt > 1)
1945 term_puts (">: ");
1946 term_write ((char *)gdb_buf, gdb_blen + 3);
1947 term_putnl ();
1951 /* Read and handle one command. Return 1 is execution must resume. */
1953 static int
1954 one_command (void)
1956 struct _iosb iosb;
1957 unsigned int status;
1958 unsigned int off;
1959 unsigned int dollar_off = 0;
1960 unsigned int sharp_off = 0;
1961 unsigned int cmd_off;
1962 unsigned int cmd_len;
1964 /* Wait for a packet. */
1965 while (1)
1967 off = 0;
1968 while (1)
1970 /* Read data from connection. */
1971 status = sys$qiow (EFN$C_ENF, /* Event flag. */
1972 conn_channel, /* I/O channel. */
1973 IO$_READVBLK, /* I/O function code. */
1974 &iosb, /* I/O status block. */
1975 0, /* Ast service routine. */
1976 0, /* Ast parameter. */
1977 gdb_buf + off, /* P1 - buffer address. */
1978 sizeof (gdb_buf) - off, /* P2 - buffer leng. */
1979 0, 0, 0, 0);
1980 if (status & STS$M_SUCCESS)
1981 status = iosb.iosb$w_status;
1982 if (!(status & STS$M_SUCCESS))
1984 term_puts ("Failed to read data from connection\n" );
1985 LIB$SIGNAL (status);
1988 #ifdef RAW_DUMP
1989 term_puts ("{: ");
1990 term_write ((char *)gdb_buf + off, iosb.iosb$w_bcnt);
1991 term_putnl ();
1992 #endif
1994 gdb_blen = off + iosb.iosb$w_bcnt;
1996 if (off == 0)
1998 /* Search for '$'. */
1999 for (dollar_off = 0; dollar_off < gdb_blen; dollar_off++)
2000 if (gdb_buf[dollar_off] == '$')
2001 break;
2002 if (dollar_off >= gdb_blen)
2004 /* Not found, discard the data. */
2005 off = 0;
2006 continue;
2008 /* Search for '#'. */
2009 for (sharp_off = dollar_off + 1;
2010 sharp_off < gdb_blen;
2011 sharp_off++)
2012 if (gdb_buf[sharp_off] == '#')
2013 break;
2015 else if (sharp_off >= off)
2017 /* Search for '#'. */
2018 for (; sharp_off < gdb_blen; sharp_off++)
2019 if (gdb_buf[sharp_off] == '#')
2020 break;
2023 /* Got packet with checksum. */
2024 if (sharp_off + 2 <= gdb_blen)
2025 break;
2027 off = gdb_blen;
2028 if (gdb_blen == sizeof (gdb_buf))
2030 /* Packet too large, discard. */
2031 off = 0;
2035 /* Validate and acknowledge a packet. */
2037 unsigned char chksum = 0;
2038 unsigned int i;
2039 int v;
2041 for (i = dollar_off + 1; i < sharp_off; i++)
2042 chksum += gdb_buf[i];
2043 v = hex2byte (gdb_buf + sharp_off + 1);
2044 if (v != chksum)
2046 term_puts ("Discard bad checksum packet\n");
2047 continue;
2049 else
2051 sock_write ((const unsigned char *)"+", 1);
2052 break;
2057 if (trace_pkt > 1)
2059 term_puts ("<: ");
2060 term_write ((char *)gdb_buf + dollar_off, sharp_off - dollar_off + 1);
2061 term_putnl ();
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)
2068 return 1;
2070 send_pkt ();
2071 return 0;
2074 /* Display the condition given by SIG64. */
2076 static void
2077 display_excp (struct chf64$signal_array *sig64, struct chf$mech_array *mech)
2079 unsigned int status;
2080 char msg[160];
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)
2088 char msg2[160];
2089 unsigned short msg2len;
2090 struct dsc$descriptor_s msg2_desc =
2091 { sizeof (msg2), DSC$K_DTYPE_T, DSC$K_CLASS_S, msg2};
2092 msg_desc.dsc$w_length = msglen;
2093 status = SYS$FAOL_64 (&msg_desc, &msg2len, &msg2_desc,
2094 &sig64->chf64$q_sig_arg1);
2095 if (status & STS$M_SUCCESS)
2096 term_write (msg2, msg2len);
2098 else
2099 term_puts ("no message");
2100 term_putnl ();
2102 if (trace_excp > 1)
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. */
2112 static void
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.
2125 Adjust. */
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. */
2179 static void
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. */
2190 static void
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;
2199 /* Disable ast. */
2200 status = sys$setast (0);
2201 switch (status)
2203 case SS$_WASCLR:
2204 old_ast = 0;
2205 break;
2206 case SS$_WASSET:
2207 old_ast = 1;
2208 break;
2209 default:
2210 /* Should never happen! */
2211 lib$signal (status);
2214 /* Disable thread scheduling. */
2215 if (has_threads)
2216 old_sch = set_thread_scheduling (0);
2218 read_all_registers (mech);
2220 /* Send stop reply packet. */
2221 packet_status ();
2222 send_pkt ();
2224 while (one_command () == 0)
2227 write_all_registers (mech);
2229 /* Re-enable scheduling. */
2230 if (has_threads)
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. */
2241 static int
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;
2250 unsigned int ret;
2251 /* Self protection. FIXME: Should be per thread ? */
2252 static int in_handler = 0;
2254 /* Completely ignore some conditions (signaled indirectly by this stub). */
2255 switch (code)
2257 case LIB$_KEYNOTFOU & STS$M_COND_ID:
2258 return SS$_RESIGNAL_64;
2259 default:
2260 break;
2263 /* Protect against recursion. */
2264 in_handler++;
2265 if (in_handler > 1)
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];
2274 if (trace_excp)
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)
2279 && pc == entry_pc
2280 && entry_pc != 0)
2282 static unsigned int entry_prot;
2284 if (trace_entry)
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);
2289 __fc (entry_pc);
2290 page_restore_rw (entry_pc, 16, entry_prot);
2293 switch (code)
2295 case SS$_ACCVIO & STS$M_COND_ID:
2296 if (trace_excp <= 1)
2297 display_excp (sig64, mech);
2298 /* Fall through. */
2299 case SS$_BREAK & STS$M_COND_ID:
2300 case SS$_OPCDEC & STS$M_COND_ID:
2301 case SS$_TBIT & STS$M_COND_ID:
2302 case SS$_DEBUG & STS$M_COND_ID:
2303 if (trace_excp > 1)
2305 int i;
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]);
2315 do_debug (mech);
2316 ret = SS$_CONTINUE_64;
2317 break;
2319 default:
2320 display_excp (sig64, mech);
2321 ret = SS$_RESIGNAL_64;
2322 break;
2325 in_handler--;
2326 /* Discard selected thread registers. */
2327 sel_regs_pthread = 0;
2328 return ret;
2331 /* Setup internal trace flags according to GDBSTUB$TRACE logical. */
2333 static void
2334 trace_init (void)
2336 unsigned int status, i, start;
2337 unsigned short len;
2338 char resstring[LNM$C_NAMLENGTH];
2339 static const $DESCRIPTOR (tabdesc, "LNM$DCL_LOGICAL");
2340 static const $DESCRIPTOR (logdesc, "GDBSTUB$TRACE");
2341 $DESCRIPTOR (sub_desc, resstring);
2342 ILE3 item_lst[2];
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)
2358 return;
2359 if (!(status & STS$M_SUCCESS))
2360 LIB$SIGNAL (status);
2362 start = 0;
2363 for (i = 0; i <= len; i++)
2365 if ((i == len || resstring[i] == ',' || resstring[i] == ';')
2366 && i != start)
2368 int j;
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++;
2378 break;
2380 if (j == NBR_DEBUG_FLAGS)
2381 TERM_FAO ("GDBSTUB$TRACE: unknown directive !AS!/", &sub_desc);
2383 start = i + 1;
2387 TERM_FAO ("GDBSTUB$TRACE=!AD ->", len, resstring);
2388 for (i = 0; i < NBR_DEBUG_FLAGS; i++)
2389 if (debug_flags[i].val > 0)
2390 TERM_FAO (" !AS=!ZL", &debug_flags[i].name, debug_flags[i].val);
2391 term_putnl ();
2395 /* Entry point. */
2397 static int
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;
2403 int i;
2404 int cnt;
2405 int is_attached;
2406 IMCB *imcb;
2407 if (initialized)
2408 term_puts ("gdbstub: re-entry\n");
2409 else
2410 initialized = 1;
2412 /* When attached (through SS$_DEBUG condition), the number of arguments
2413 is 4 and PROGXFER is the PC at interruption. */
2414 va_count (cnt);
2415 is_attached = cnt == 4;
2417 term_init ();
2419 /* Hello banner. */
2420 term_puts ("Hello from gdb stub\n");
2422 trace_init ();
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. */
2433 if (!is_attached)
2435 entry_pc = 0;
2436 for (i = 0; progxfer[i]; i++)
2437 entry_pc = progxfer[i];
2439 if (trace_entry)
2441 if (entry_pc == 0)
2443 term_puts ("No entry point\n");
2444 return 0;
2446 else
2447 TERM_FAO ("Entry: !XH!/",entry_pc);
2450 else
2451 entry_pc = progxfer[0];
2453 has_threads = 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]))
2462 has_threads = 1;
2464 if (trace_images)
2466 unsigned int j;
2467 LDRIMG *ldrimg = imcb->imcb$l_ldrimg;
2468 LDRISD *ldrisd;
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:
2477 term_puts ("prog");
2478 break;
2479 case IMCB$K_MERGED_IMAGE:
2480 term_puts ("mrge");
2481 break;
2482 case IMCB$K_GLOBAL_IMAGE_SECTION:
2483 term_puts ("glob");
2484 break;
2485 default:
2486 term_puts ("????");
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)
2493 continue;
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;
2498 term_puts (" ");
2499 term_putc (flags & 0x04 ? 'R' : '-');
2500 term_putc (flags & 0x02 ? 'W' : '-');
2501 term_putc (flags & 0x01 ? 'X' : '-');
2502 term_puts (flags & 0x01000000 ? " Prot" : " ");
2503 term_puts (flags & 0x04000000 ? " Shrt" : " ");
2504 term_puts (flags & 0x08000000 ? " Shrd" : " ");
2505 TERM_FAO (" !XA-!XA!/",
2506 ldrisd[j].ldrisd$p_base,
2507 (unsigned __int64) ldrisd[j].ldrisd$p_base
2508 + ldrisd[j].ldrisd$i_len - 1);
2510 ldrisd = ldrimg->ldrimg$l_dyn_seg;
2511 if (ldrisd)
2512 TERM_FAO (" dynamic !XA-!XA!/",
2513 ldrisd->ldrisd$p_base,
2514 (unsigned __int64) ldrisd->ldrisd$p_base
2515 + ldrisd->ldrisd$i_len - 1);
2519 if (has_threads)
2520 threads_init ();
2522 /* Wait for connection. */
2523 sock_init ();
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);
2533 if (is_attached)
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
2560 used. */
2561 entry_pc = 0;
2562 term_puts ("gdbstub: cannot set breakpoint on entry\n");
2564 else
2565 LIB$SIGNAL (status);
2568 if (entry_pc != 0)
2570 ots$move (entry_saved, 16, (void *)entry_pc);
2571 ots$move ((void *)entry_pc, 16, (void *)initbp);
2572 __fc (entry_pc);
2573 page_restore_rw (entry_pc, 16, entry_prot);
2577 /* If it wasn't possible to set a breakpoint on the entry point,
2578 accept gdb commands now. Note that registers are not updated. */
2579 if (entry_pc == 0)
2581 while (one_command () == 0)
2585 /* We will see! */
2586 return SS$_CONTINUE;
2589 /* Declare the entry point of this relocatable module. */
2591 struct xfer_vector
2593 __int64 impure_start;
2594 __int64 impure_end;
2595 int (*entry) ();
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