]>
Commit | Line | Data |
---|---|---|
e20520b8 SG |
1 | /* Remote utility routines for the remote server for GDB. |
2 | Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include <stdio.h> | |
22 | #include <signal.h> | |
23 | #include <sys/wait.h> | |
24 | #include <sys/ioctl.h> | |
25 | #include <a.out.h> | |
26 | #include <sys/file.h> | |
27 | #include <sgtty.h> | |
38dc5e12 SG |
28 | #include <netinet/in.h> |
29 | #include <arpa/inet.h> | |
30 | #include <sys/socket.h> | |
31 | #include <sys/types.h> | |
32 | #include <netinet/tcp.h> | |
33 | #include <sys/time.h> | |
e20520b8 SG |
34 | |
35 | extern int remote_desc; | |
36 | extern int remote_debugging; | |
e20520b8 SG |
37 | |
38 | void remote_open (); | |
39 | void remote_send (); | |
40 | void putpkt (); | |
41 | void getpkt (); | |
42 | ||
43 | void write_ok (); | |
44 | void write_enn (); | |
45 | void convert_ascii_to_int (); | |
46 | void convert_int_to_ascii (); | |
47 | void prepare_resume_reply (); | |
48 | ||
49 | /* Open a connection to a remote debugger. | |
50 | NAME is the filename used for communication. */ | |
51 | ||
52 | void | |
53 | remote_open (name, from_tty) | |
54 | char *name; | |
55 | int from_tty; | |
56 | { | |
57 | struct sgttyb sg; | |
58 | ||
59 | remote_debugging = 0; | |
60 | ||
38dc5e12 SG |
61 | if (!strchr (name, ':')) |
62 | { | |
63 | remote_desc = open (name, O_RDWR); | |
64 | if (remote_desc < 0) | |
65 | perror_with_name ("Could not open remote device"); | |
66 | ||
67 | ioctl (remote_desc, TIOCGETP, &sg); | |
68 | sg.sg_flags = RAW; | |
69 | ioctl (remote_desc, TIOCSETP, &sg); | |
70 | } | |
71 | else | |
72 | { | |
73 | char *port_str; | |
74 | int port; | |
75 | struct sockaddr_in sockaddr; | |
76 | int tmp; | |
77 | ||
78 | port_str = strchr (name, ':'); | |
79 | ||
80 | port = atoi (port_str + 1); | |
81 | ||
82 | remote_desc = socket (PF_INET, SOCK_STREAM, 0); | |
83 | if (remote_desc < 0) | |
84 | perror_with_name ("Can't open socket"); | |
85 | ||
86 | /* Allow rapid reuse of this port. */ | |
87 | tmp = 1; | |
88 | setsockopt (remote_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, | |
89 | sizeof(tmp)); | |
90 | ||
91 | /* Enable TCP keep alive process. */ | |
92 | tmp = 1; | |
93 | setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); | |
94 | ||
95 | sockaddr.sin_family = PF_INET; | |
96 | sockaddr.sin_port = htons(port); | |
97 | sockaddr.sin_addr.s_addr = INADDR_ANY; | |
e20520b8 | 98 | |
38dc5e12 SG |
99 | if (bind (remote_desc, &sockaddr, sizeof (sockaddr)) |
100 | || listen (remote_desc, 1)) | |
101 | perror_with_name ("Can't bind address"); | |
102 | ||
103 | tmp = sizeof (sockaddr); | |
104 | remote_desc = accept (remote_desc, &sockaddr, &tmp); | |
105 | if (remote_desc == -1) | |
106 | perror_with_name ("Accept failed"); | |
107 | ||
108 | tmp = 1; | |
109 | setsockopt (remote_desc, 6, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); | |
110 | } | |
e20520b8 SG |
111 | |
112 | fprintf (stderr, "Remote debugging using %s\n", name); | |
113 | remote_debugging = 1; | |
114 | } | |
115 | ||
116 | /* Convert hex digit A to a number. */ | |
117 | ||
118 | static int | |
119 | fromhex (a) | |
120 | int a; | |
121 | { | |
122 | if (a >= '0' && a <= '9') | |
123 | return a - '0'; | |
124 | else if (a >= 'a' && a <= 'f') | |
125 | return a - 'a' + 10; | |
126 | else | |
127 | error ("Reply contains invalid hex digit"); | |
128 | } | |
129 | ||
130 | /* Convert number NIB to a hex digit. */ | |
131 | ||
132 | static int | |
133 | tohex (nib) | |
134 | int nib; | |
135 | { | |
136 | if (nib < 10) | |
137 | return '0' + nib; | |
138 | else | |
139 | return 'a' + nib - 10; | |
140 | } | |
141 | ||
142 | /* Send the command in BUF to the remote machine, | |
143 | and read the reply into BUF. | |
144 | Report an error if we get an error reply. */ | |
145 | ||
146 | void | |
147 | remote_send (buf) | |
148 | char *buf; | |
149 | { | |
150 | putpkt (buf); | |
151 | getpkt (buf); | |
152 | ||
153 | if (buf[0] == 'E') | |
154 | error ("Remote failure reply: E"); | |
155 | } | |
156 | ||
157 | /* Send a packet to the remote machine, with error checking. | |
158 | The data of the packet is in BUF. */ | |
159 | ||
160 | void | |
161 | putpkt (buf) | |
162 | char *buf; | |
163 | { | |
164 | int i; | |
165 | unsigned char csum = 0; | |
166 | char buf2[2000]; | |
167 | char buf3[1]; | |
168 | int cnt = strlen (buf); | |
169 | char *p; | |
170 | ||
171 | /* Copy the packet into buffer BUF2, encapsulating it | |
172 | and giving it a checksum. */ | |
173 | ||
174 | p = buf2; | |
175 | *p++ = '$'; | |
176 | ||
177 | for (i = 0; i < cnt; i++) | |
178 | { | |
179 | csum += buf[i]; | |
180 | *p++ = buf[i]; | |
181 | } | |
182 | *p++ = '#'; | |
183 | *p++ = tohex ((csum >> 4) & 0xf); | |
184 | *p++ = tohex (csum & 0xf); | |
185 | ||
186 | /* Send it over and over until we get a positive ack. */ | |
187 | ||
188 | do | |
189 | { | |
190 | write (remote_desc, buf2, p - buf2); | |
191 | read (remote_desc, buf3, 1); | |
192 | } | |
193 | while (buf3[0] != '+'); | |
194 | } | |
195 | ||
196 | static int | |
197 | readchar () | |
198 | { | |
38dc5e12 SG |
199 | static char buf[BUFSIZ]; |
200 | static int bufcnt = 0; | |
201 | static char *bufp; | |
202 | ||
203 | if (bufcnt-- > 0) | |
204 | return *bufp++ & 0x7f; | |
205 | ||
206 | bufcnt = read (remote_desc, buf, sizeof (buf)); | |
207 | ||
208 | if (bufcnt <= 0) | |
209 | { | |
210 | perror ("readchar"); | |
211 | fatal ("read error, quitting"); | |
212 | } | |
213 | ||
214 | bufp = buf; | |
215 | bufcnt--; | |
216 | return *bufp++ & 0x7f; | |
e20520b8 SG |
217 | } |
218 | ||
219 | /* Read a packet from the remote machine, with error checking, | |
220 | and store it in BUF. */ | |
221 | ||
222 | void | |
223 | getpkt (buf) | |
224 | char *buf; | |
225 | { | |
226 | char *bp; | |
38dc5e12 SG |
227 | unsigned char csum, c1, c2; |
228 | int c; | |
e20520b8 SG |
229 | |
230 | while (1) | |
231 | { | |
232 | csum = 0; | |
38dc5e12 | 233 | |
e20520b8 SG |
234 | while ((c = readchar ()) != '$'); |
235 | ||
236 | bp = buf; | |
237 | while (1) | |
238 | { | |
239 | c = readchar (); | |
240 | if (c == '#') | |
241 | break; | |
242 | *bp++ = c; | |
243 | csum += c; | |
244 | } | |
245 | *bp = 0; | |
246 | ||
247 | c1 = fromhex (readchar ()); | |
248 | c2 = fromhex (readchar ()); | |
249 | if (csum == (c1 << 4) + c2) | |
250 | break; | |
251 | ||
252 | fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", | |
253 | (c1 << 4) + c2, csum, buf); | |
254 | write (remote_desc, "-", 1); | |
255 | } | |
256 | ||
257 | write (remote_desc, "+", 1); | |
258 | } | |
259 | ||
260 | void | |
261 | write_ok (buf) | |
262 | char *buf; | |
263 | { | |
264 | buf[0] = 'O'; | |
265 | buf[1] = 'k'; | |
266 | buf[2] = '\0'; | |
267 | } | |
268 | ||
269 | void | |
270 | write_enn (buf) | |
271 | char *buf; | |
272 | { | |
273 | buf[0] = 'E'; | |
274 | buf[1] = 'N'; | |
275 | buf[2] = 'N'; | |
276 | buf[3] = '\0'; | |
277 | } | |
278 | ||
279 | void | |
280 | convert_int_to_ascii (from, to, n) | |
281 | char *from, *to; | |
282 | int n; | |
283 | { | |
284 | int nib; | |
285 | char ch; | |
286 | while (n--) | |
287 | { | |
288 | ch = *from++; | |
289 | nib = ((ch & 0xf0) >> 4) & 0x0f; | |
290 | *to++ = tohex (nib); | |
291 | nib = ch & 0x0f; | |
292 | *to++ = tohex (nib); | |
293 | } | |
294 | *to++ = 0; | |
295 | } | |
296 | ||
297 | ||
298 | void | |
299 | convert_ascii_to_int (from, to, n) | |
300 | char *from, *to; | |
301 | int n; | |
302 | { | |
303 | int nib1, nib2; | |
304 | while (n--) | |
305 | { | |
306 | nib1 = fromhex (*from++); | |
307 | nib2 = fromhex (*from++); | |
308 | *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f); | |
309 | } | |
310 | } | |
311 | ||
312 | static char * | |
313 | outreg(regno, buf) | |
314 | int regno; | |
315 | char *buf; | |
316 | { | |
317 | extern char registers[]; | |
318 | ||
319 | *buf++ = tohex (regno >> 4); | |
320 | *buf++ = tohex (regno & 0xf); | |
321 | *buf++ = ':'; | |
322 | convert_int_to_ascii (®isters[REGISTER_BYTE (regno)], buf, 4); | |
323 | buf += 8; | |
324 | *buf++ = ';'; | |
325 | ||
326 | return buf; | |
327 | } | |
328 | ||
329 | void | |
330 | prepare_resume_reply (buf, status, signal) | |
331 | char *buf, status; | |
332 | unsigned char signal; | |
333 | { | |
334 | int nib; | |
335 | char ch; | |
336 | ||
337 | *buf++ = 'T'; | |
338 | ||
339 | nib = ((signal & 0xf0) >> 4); | |
340 | *buf++ = tohex (nib); | |
341 | nib = signal & 0x0f; | |
342 | *buf++ = tohex (nib); | |
343 | ||
344 | buf = outreg (PC_REGNUM, buf); | |
345 | buf = outreg (FP_REGNUM, buf); | |
346 | buf = outreg (SP_REGNUM, buf); | |
347 | #ifdef NPC_REGNUM | |
348 | buf = outreg (NPC_REGNUM, buf); | |
349 | #endif | |
350 | #ifdef O7_REGNUM | |
351 | buf = outreg (O7_REGNUM, buf); | |
352 | #endif | |
353 | ||
354 | *buf++ = 0; | |
355 | } | |
356 | ||
357 | void | |
358 | decode_m_packet (from, mem_addr_ptr, len_ptr) | |
359 | char *from; | |
360 | unsigned int *mem_addr_ptr, *len_ptr; | |
361 | { | |
362 | int i = 0, j = 0; | |
363 | char ch; | |
364 | *mem_addr_ptr = *len_ptr = 0; | |
365 | ||
366 | while ((ch = from[i++]) != ',') | |
367 | { | |
368 | *mem_addr_ptr = *mem_addr_ptr << 4; | |
369 | *mem_addr_ptr |= fromhex (ch) & 0x0f; | |
370 | } | |
371 | ||
372 | for (j = 0; j < 4; j++) | |
373 | { | |
374 | if ((ch = from[i++]) == 0) | |
375 | break; | |
376 | *len_ptr = *len_ptr << 4; | |
377 | *len_ptr |= fromhex (ch) & 0x0f; | |
378 | } | |
379 | } | |
380 | ||
381 | void | |
382 | decode_M_packet (from, mem_addr_ptr, len_ptr, to) | |
383 | char *from, *to; | |
384 | unsigned int *mem_addr_ptr, *len_ptr; | |
385 | { | |
386 | int i = 0, j = 0; | |
387 | char ch; | |
388 | *mem_addr_ptr = *len_ptr = 0; | |
389 | ||
390 | while ((ch = from[i++]) != ',') | |
391 | { | |
392 | *mem_addr_ptr = *mem_addr_ptr << 4; | |
393 | *mem_addr_ptr |= fromhex (ch) & 0x0f; | |
394 | } | |
395 | ||
396 | while ((ch = from[i++]) != ':') | |
397 | { | |
398 | *len_ptr = *len_ptr << 4; | |
399 | *len_ptr |= fromhex (ch) & 0x0f; | |
400 | } | |
401 | ||
402 | convert_ascii_to_int (&from[i++], to, *len_ptr); | |
403 | } |