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