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, ®s);
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