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