This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / gnu / usr.bin / kgdb / remote.c
CommitLineData
04497f0b
NW
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $Header: /home/cvs/386BSD/src/usr.bin/gdb/remote.c,v 1.1.1.1 1993/06/12 14:52:22 rgrimes Exp $;
37 */
38
39#ifndef lint
40static char sccsid[] = "@(#)remote.c 6.5 (Berkeley) 5/8/91";
41#endif /* not lint */
42
43#include "param.h"
44
45#include <stdio.h>
46#include <varargs.h>
47
48#include <signal.h>
49#include <sys/types.h>
50#include <sys/ioctl.h>
51#include <sys/file.h>
52
53#include "defs.h"
54#include "frame.h"
55#include "inferior.h"
56#include "wait.h"
57
58#include "kgdb_proto.h"
59
60static FILE *kiodebug;
61static int icache = 1;
62extern int kernel_debugging;
63
64static int remote_cache_valid;
65static int remote_instub;
66
67static void remote_signal();
68static void remote_debug();
69static void print_msg();
70
71static int remote_mtu;
72static int (*send_msg)();
73static int (*recv_msg)();
74static void (*closelink)();
75
76static u_char *inbuffer;
77static u_char *outbuffer;
78
79/*
80 * Statistics.
81 */
82static int remote_ierrs;
83static int remote_oerrs;
84static int remote_seqerrs;
85static int remote_spurious;
86
87#define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)
88
89/*
90 * Send an outbound message to the remote machine and read the reply.
91 * Either or both message buffers may be NULL.
92 */
93static int
94m_xchg(type, out, outlen, in, inlen)
95 int type;
96 u_char *out;
97 int outlen;
98 u_char *in;
99 int *inlen;
100{
101 register int err, (*send)() = send_msg, (*recv)() = recv_msg;
102 int ack;
103 static int seqbit = 0;
104
105 if (!remote_instub) {
106 remote_instub = 1;
107 PUTCMD(KGDB_EXEC);
108 }
109
110 seqbit ^= KGDB_SEQ;
111 while (1) {
112 err = (*send)(type | seqbit, out, outlen);
113 if (err) {
114 ++remote_oerrs;
115 if (kiodebug)
116 remote_debug("send error %d\n", err);
117 }
118 if (kiodebug)
119 print_msg(type | seqbit, out, outlen, 'O');
120
121 recv:
122 err = (*recv)(&ack, in, inlen);
123 if (err) {
124 ++remote_ierrs;
125 if (kiodebug)
126 remote_debug("recv error %d\n", err);
127 remote_cache_valid = 0;
128 } else if (kiodebug)
129 print_msg(ack, in, inlen ? *inlen : 0, 'I');
130
131 if (err)
132 continue;
133
134 if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) {
135 ++remote_spurious;
136 continue;
137 }
138 if ((ack & KGDB_SEQ) ^ seqbit) {
139 ++remote_seqerrs;
140 goto recv;
141 }
142 return ack;
143 }
144}
145
146/*
147 * Wait for the specified message type. Discard anything else.
148 * (this is used by 'remote-signal' to help us resync with other side.)
149 */
150static void
151m_recv(type, in, inlen)
152 int type;
153 u_char *in;
154 int *inlen;
155{
156 int reply, err;
157
158 while (1) {
159 err = (*recv_msg)(&reply, in, inlen);
160 if (err) {
161 ++remote_ierrs;
162 if (kiodebug)
163 remote_debug("recv error %d\n", err);
164 } else if (kiodebug)
165 print_msg(reply, in, inlen ? *inlen : 0, 'I');
166
167 if (KGDB_CMD(reply) == type)
168 return;
169 ++remote_spurious;
170 }
171}
172
173/*
174 * Send a message. Do not wait for *any* response from the other side.
175 * Some other thread of control will pick up the ack that will be generated.
176 */
177static void
178m_send(type, buf, len)
179 int type;
180 u_char *buf;
181 int len;
182{
183 int err;
184
185 if (!remote_instub) {
186 remote_instub = 1;
187 PUTCMD(KGDB_EXEC);
188 }
189
190 err = (*send_msg)(type, buf, len);
191 if (err) {
192 ++remote_ierrs;
193 if (kiodebug)
194 remote_debug("[send error %d] ", err);
195 }
196 if (kiodebug)
197 print_msg(type, buf, len, 'O');
198}
199
200/*
201 * Open a connection to a remote debugger.
202 * NAME is the filename used for communication.
203 */
204void
205remote_open(name, from_tty)
206 char *name;
207 int from_tty;
208{
209 int bufsize;
210
211 remote_debugging = 0;
212 if (sl_open(name, &send_msg, &recv_msg, &closelink, &remote_mtu,
213 &bufsize))
214 return;
215 if (from_tty)
216 printf("Remote debugging using %s\n", name);
217 remote_debugging = 1;
218
219 remote_cache_valid = 0;
220
221 inbuffer = (u_char *)malloc(bufsize);
222 outbuffer = (u_char *)malloc(bufsize);
223
224 remote_signal();
225
226 remote_ierrs = 0;
227 remote_oerrs = 0;
228 remote_spurious = 0;
229}
230
231/*
232 * Close the open connection to the remote debugger. Use this when you want
233 * to detach and do something else with your gdb.
234 */
235void
236remote_close(from_tty)
237 int from_tty;
238{
239 if (!remote_debugging)
240 error("remote debugging not enabled");
241
242 remote_debugging = 0;
243 /*
244 * Take remote machine out of debug mode.
245 */
246 (void)PUTCMD(KGDB_KILL);
247 (*closelink)();
248 if (from_tty)
249 printf("Ending remote debugging\n");
250
251 free((char *)inbuffer);
252 free((char *)outbuffer);
253}
254
255/*
256 * Tell the remote machine to resume.
257 */
258int
259remote_resume(step, signal)
260 int step, signal;
261{
262 if (!step) {
263 (void)PUTCMD(KGDB_CONT);
264 remote_instub = 0;
265 } else {
266#ifdef NO_SINGLE_STEP
267 single_step(0);
268#else
269 (void)PUTCMD(KGDB_STEP);
270#endif
271 }
272}
273
274/*
275 * Wait until the remote machine stops, then return, storing status in STATUS
276 * just as `wait' would.
277 */
278int
279remote_wait(status)
280 WAITTYPE *status;
281{
282 int len;
283
284 WSETEXIT((*status), 0);
285 /*
286 * When the machine stops, it will send us a KGDB_SIGNAL message,
287 * so we wait for one of these.
288 */
289 m_recv(KGDB_SIGNAL, inbuffer, &len);
290 WSETSTOP((*status), inbuffer[0]);
291}
292
293/*
294 * Register context as of last remote_fetch_registers().
295 */
296static char reg_cache[REGISTER_BYTES];
297
298/*
299 * Read the remote registers into the block REGS.
300 */
301void
302remote_fetch_registers(regs)
303 char *regs;
304{
305 int regno, len, rlen, ack;
306 u_char *cp, *ep;
307
308 regno = -1;
309 do {
310 outbuffer[0] = regno + 1;
311 ack = m_xchg(remote_cache_valid ?
312 KGDB_REG_R|KGDB_DELTA : KGDB_REG_R,
313 outbuffer, 1, inbuffer, &len);
314 cp = inbuffer;
315 ep = cp + len;
316 while (cp < ep) {
317 regno = *cp++;
318 rlen = REGISTER_RAW_SIZE(regno);
319 bcopy((char *)cp,
320 &reg_cache[REGISTER_BYTE(regno)], rlen);
321 cp += rlen;
322 }
323 } while (ack & KGDB_MORE);
324
325 remote_cache_valid = 1;
326 bcopy(reg_cache, regs, REGISTER_BYTES);
327}
328
329/*
330 * Store the remote registers from the contents of the block REGS.
331 */
332void
333remote_store_registers(regs)
334 char *regs;
335{
336 u_char *cp, *ep;
337 int regno, off, rlen;
338
339 cp = outbuffer;
340 ep = cp + remote_mtu;
341
342 for (regno = 0; regno < NUM_REGS; ++regno) {
343 off = REGISTER_BYTE(regno);
344 rlen = REGISTER_RAW_SIZE(regno);
345 if (!remote_cache_valid ||
346 bcmp(&regs[off], &reg_cache[off], rlen) != 0) {
347 if (cp + rlen + 1 >= ep) {
348 (void)m_xchg(KGDB_REG_W,
349 outbuffer, cp - outbuffer,
350 (u_char *)0, (int *)0);
351 cp = outbuffer;
352 }
353 *cp++ = regno;
354 bcopy(&regs[off], cp, rlen);
355 cp += rlen;
356 }
357 }
358 if (cp != outbuffer)
359 (void)m_xchg(KGDB_REG_W, outbuffer, cp - outbuffer,
360 (u_char *)0, (int *)0);
361 bcopy(regs, reg_cache, REGISTER_BYTES);
362}
363
364/*
365 * Store a chunk of memory into the remote host.
366 * 'remote_addr' is the address in the remote memory space.
367 * 'cp' is the address of the buffer in our space, and 'len' is
368 * the number of bytes. Returns an errno status.
369 */
370int
371remote_write_inferior_memory(remote_addr, cp, len)
372 CORE_ADDR remote_addr;
373 u_char *cp;
374 int len;
375{
376 int cnt;
377
378 while (len > 0) {
379 cnt = min(len, remote_mtu - 4);
380 bcopy((char *)&remote_addr, outbuffer, 4);
381 bcopy(cp, outbuffer + 4, cnt);
382 (void)m_xchg(KGDB_MEM_W, outbuffer, cnt + 4, inbuffer, &len);
383
384 if (inbuffer[0])
385 return inbuffer[0];
386
387 remote_addr += cnt;
388 cp += cnt;
389 len -= cnt;
390 }
391 return 0;
392}
393
394/*
395 * Read memory data directly from the remote machine.
396 * 'remote_addr' is the address in the remote memory space.
397 * 'cp' is the address of the buffer in our space, and 'len' is
398 * the number of bytes. Returns an errno status.
399 */
400static int
401remote_read_memory(remote_addr, cp, len)
402 CORE_ADDR remote_addr;
403 u_char *cp;
404 int len;
405{
406 int cnt, inlen;
407
408 while (len > 0) {
409 cnt = min(len, remote_mtu - 1);
410 outbuffer[0] = cnt;
411 bcopy((char *)&remote_addr, (char *)&outbuffer[1], 4);
412
413 (void)m_xchg(KGDB_MEM_R, outbuffer, 5, inbuffer, &inlen);
414
415 if (inbuffer[0] != 0)
416 return inbuffer[0];
417
418 if (cnt != inlen - 1)
419 /* XXX */
420 error("remote_read_memory() request botched");
421
422 bcopy((char *)&inbuffer[1], (char *)cp, cnt);
423
424 remote_addr += cnt;
425 cp += cnt;
426 len -= cnt;
427 }
428 return 0;
429}
430
431int
432remote_read_inferior_memory(remote_addr, cp, len)
433 CORE_ADDR remote_addr;
434 char *cp;
435 int len;
436{
437 int stat = 0;
438
439 if (icache) {
440 extern CORE_ADDR text_start, text_end;
441 CORE_ADDR xferend = remote_addr + len;
442
443 if (remote_addr < text_end && text_start < xferend) {
444 /*
445 * at least part of this xfer is in the text
446 * space -- xfer the overlap from the exec file.
447 */
448 if (remote_addr >= text_start && xferend < text_end)
449 return (xfer_core_file(remote_addr, cp, len));
450 if (remote_addr >= text_start) {
451 int i = text_end - remote_addr;
452
453 if (stat = xfer_core_file(remote_addr, cp, i))
454 return (stat);
455 remote_addr += i;
456 cp += i;
457 len -= i;
458 } else if (xferend <= text_end) {
459 int i = xferend - text_start;
460
461 len = text_start - remote_addr;
462 if (stat = xfer_core_file(text_start,
463 cp + len, i))
464 return (stat);
465 }
466 }
467 }
468 return remote_read_memory(remote_addr, cp, len);
469}
470
471/*
472 * Signal the remote machine. The remote end might be idle or it might
473 * already be in debug mode -- we need to handle both case. Thus, we use
474 * the framing character as the wakeup byte, and send a SIGNAL packet.
475 * If the remote host is idle, the framing character will wake it up.
476 * If it is in the kgdb stub, then we will get a SIGNAL reply.
477 */
478static void
479remote_signal()
480{
481 if (!remote_debugging)
482 printf("Remote debugging not enabled.\n");
483 else {
484 remote_instub = 0;
485 m_send(KGDB_SIGNAL, (u_char *)0, 0);
486 }
487}
488
489static void
490remote_signal_command()
491{
492 extern int stop_after_attach;
493
494 if (!remote_debugging)
495 error("Not debugging remote.");
496 remote_cache_valid = 0;
497 remote_signal();
498 restart_remote();
499}
500
501/*
502 * Print a message for debugging.
503 */
504static void
505print_msg(type, buf, len, dir)
506 int type;
507 u_char *buf;
508 int len;
509 int dir;
510{
511 int i;
512 char *s;
513
514 switch (KGDB_CMD(type)) {
515 case KGDB_MEM_R: s = "memr"; break;
516 case KGDB_MEM_W: s = "memw"; break;
517 case KGDB_REG_R: s = "regr"; break;
518 case KGDB_REG_W: s = "regw"; break;
519 case KGDB_CONT: s = "cont"; break;
520 case KGDB_STEP: s = "step"; break;
521 case KGDB_KILL: s = "kill"; break;
522 case KGDB_SIGNAL: s = "sig "; break;
523 case KGDB_EXEC: s = "exec"; break;
524 default: s = "unk "; break;
525 }
526 remote_debug("%c %c%c%c%c %s (%02x): ", dir,
527 (type & KGDB_ACK) ? 'A' : '.',
528 (type & KGDB_DELTA) ? 'D' : '.',
529 (type & KGDB_MORE) ? 'M' : '.',
530 (type & KGDB_SEQ) ? '-' : '+',
531 s, type);
532 if (buf)
533 for (i = 0; i < len; ++i)
534 remote_debug("%02x", buf[i]);
535 remote_debug("\n");
536}
537
538static void
539set_remote_text_refs_command(arg, from_tty)
540 char *arg;
541 int from_tty;
542{
543 icache = !parse_binary_operation("set remote-text-refs", arg);
544}
545
546static void
547remote_debug_command(arg, from_tty)
548 char *arg;
549 int from_tty;
550{
551 char *name;
552
553 if (kiodebug != 0 && kiodebug != stderr)
554 (void)fclose(kiodebug);
555
556 if (arg == 0) {
557 kiodebug = 0;
558 printf("Remote debugging off.\n");
559 return;
560 }
561 if (arg[0] == '-') {
562 kiodebug = stderr;
563 name = "stderr";
564 } else {
565 kiodebug = fopen(arg, "w");
566 if (kiodebug == 0) {
567 printf("Cannot open '%s'.\n", arg);
568 return;
569 }
570 name = arg;
571 }
572 printf("Remote debugging output routed to %s.\n", name);
573}
574
575/* ARGSUSED */
576static void
577remote_info(arg, from_tty)
578 char *arg;
579 int from_tty;
580{
581 printf("Using %s for text references.\n",
582 icache? "local executable" : "remote");
583 printf("Protocol debugging is %s.\n", kiodebug? "on" : "off");
584 printf("%d spurious input messages.\n", remote_spurious);
585 printf("%d input errors; %d output errors; %d sequence errors.\n",
586 remote_ierrs, remote_oerrs, remote_seqerrs);
587}
588
589/* VARARGS */
590static void
591remote_debug(va_alist)
592 va_dcl
593{
594 register char *cp;
595 va_list ap;
596
597 va_start(ap);
598 cp = va_arg(ap, char *);
599 (void)vfprintf(kiodebug, cp, ap);
600 va_end(ap);
601 fflush(kiodebug);
602}
603
604extern struct cmd_list_element *setlist;
605
606void
607_initialize_remote()
608{
609 add_com("remote-signal", class_run, remote_signal_command,
610 "If remote debugging, send interrupt signal to remote.");
611 add_cmd("remote-text-refs", class_support,
612 set_remote_text_refs_command,
613"Enable/disable use of local executable for text segment references.\n\
614If on, all memory read/writes go to remote.\n\
615If off, text segment reads use the local executable.",
616 &setlist);
617
618 add_com("remote-debug", class_run, remote_debug_command,
619"With a file name argument, enables output of remote protocol debugging\n\
620messages to said file. If file is `-', stderr is used.\n\
621With no argument, remote debugging is disabled.");
622
623 add_info("remote", remote_info,
624 "Show current settings of remote debugging options.");
625}
626