632ea0cc |
1 | /* Memory-access and commands for inferior process, for GDB. |
2 | Copyright (C) 1988 Free Software Foundation, Inc. |
3 | |
4 | GDB is distributed in the hope that it will be useful, but WITHOUT ANY |
5 | WARRANTY. No author or distributor accepts responsibility to anyone |
6 | for the consequences of using it or for whether it serves any |
7 | particular purpose or works at all, unless he says so in writing. |
8 | Refer to the GDB General Public License for full details. |
9 | |
10 | Everyone is granted permission to copy, modify and redistribute GDB, |
11 | but only under the conditions described in the GDB General Public |
12 | License. A copy of this license is supposed to have been given to you |
13 | along with GDB so you can know your rights and responsibilities. It |
14 | should be in a file named COPYING. Among other things, the copyright |
15 | notice and this notice must be preserved on all copies. |
16 | |
17 | In other words, go ahead and share GDB, but don't try to stop |
18 | anyone else from sharing it farther. Help stamp out software hoarding! |
19 | */ |
20 | |
21 | /* Remote communication protocol. |
22 | All values are encoded in ascii hex digits. |
23 | |
24 | Request Packet |
25 | |
26 | read registers g |
27 | reply XX....X Each byte of register data |
28 | is described by two hex digits. |
29 | Registers are in the internal order |
30 | for GDB, and the bytes in a register |
31 | are in the same order the machine uses. |
32 | or ENN for an error. |
33 | |
34 | write regs GXX..XX Each byte of register data |
35 | is described by two hex digits. |
36 | reply OK for success |
37 | ENN for an error |
38 | |
39 | read mem mAA..AA,LLLL AA..AA is address, LLLL is length. |
40 | reply XX..XX XX..XX is mem contents |
41 | or ENN NN is errno |
42 | |
43 | write mem MAA..AA,LLLL:XX..XX |
44 | AA..AA is address, |
45 | LLLL is number of bytes, |
46 | XX..XX is data |
47 | reply OK for success |
48 | ENN for an error |
49 | |
50 | cont cAA..AA AA..AA is address to resume |
51 | If AA..AA is omitted, |
52 | resume at same address. |
53 | |
54 | step sAA..AA AA..AA is address to resume |
55 | If AA..AA is omitted, |
56 | resume at same address. |
57 | |
58 | There is no immediate reply to step or cont. |
59 | The reply comes when the machine stops. |
60 | It is SAA AA is the "signal number" |
61 | |
62 | kill req k |
63 | */ |
64 | |
65 | #include <stdio.h> |
66 | #include <signal.h> |
67 | |
68 | #include "defs.h" |
69 | #include "initialize.h" |
70 | #include "param.h" |
71 | #include "frame.h" |
72 | #include "inferior.h" |
73 | |
74 | #include <sys/wait.h> |
75 | #include <sys/ioctl.h> |
76 | #include <a.out.h> |
77 | #include <sys/file.h> |
78 | #include <sgtty.h> |
79 | |
80 | int kiodebug; |
81 | |
82 | int icache; |
83 | |
84 | /* Descriptor for I/O to remote machine. */ |
85 | int remote_desc; |
86 | |
87 | #define PBUFSIZ 300 |
88 | |
89 | static void remote_send (); |
90 | static void putpkt (); |
91 | static void getpkt (); |
92 | static void dcache_flush (); |
93 | |
94 | START_FILE |
95 | \f |
96 | /* Open a connection to a remote debugger. |
97 | NAME is the filename used for communication. */ |
98 | |
99 | void |
100 | remote_open (name, from_tty) |
101 | char *name; |
102 | int from_tty; |
103 | { |
104 | struct sgttyb sg; |
105 | |
106 | remote_debugging = 0; |
107 | dcache_init (); |
108 | |
109 | remote_desc = open (name, O_RDWR); |
110 | if (remote_desc < 0) |
111 | perror_with_name (name); |
112 | |
113 | ioctl (remote_desc, TIOCGETP, &sg); |
114 | sg.sg_flags = RAW; |
115 | ioctl (remote_desc, TIOCSETP, &sg); |
116 | |
117 | if (from_tty) |
118 | printf ("Remote debugging using %s\n", name); |
119 | remote_debugging = 1; |
120 | } |
121 | |
122 | /* Convert hex digit A to a number. */ |
123 | |
124 | static int |
125 | fromhex (a) |
126 | int a; |
127 | { |
128 | if (a >= '0' && a <= '9') |
129 | return a - '0'; |
130 | else if (a >= 'a' && a <= 'f') |
131 | return a - 'a' + 10; |
132 | else |
133 | error ("Reply contains invalid hex digit"); |
134 | } |
135 | |
136 | /* Convert number NIB to a hex digit. */ |
137 | |
138 | static int |
139 | tohex (nib) |
140 | int nib; |
141 | { |
142 | if (nib < 10) |
143 | return '0'+nib; |
144 | else |
145 | return 'a'+nib-10; |
146 | } |
147 | \f |
148 | /* Tell the remote machine to resume. */ |
149 | |
150 | int |
151 | remote_resume (step, signal) |
152 | int step, signal; |
153 | { |
154 | char buf[PBUFSIZ]; |
155 | |
156 | dcache_flush (); |
157 | |
158 | strcpy (buf, step ? "s": "c"); |
159 | |
160 | putpkt (buf); |
161 | } |
162 | |
163 | /* Wait until the remote machine stops, then return, |
164 | storing status in STATUS just as `wait' would. */ |
165 | |
166 | int |
167 | remote_wait (status) |
168 | union wait *status; |
169 | { |
170 | char buf[PBUFSIZ]; |
171 | |
172 | status->w_status = 0; |
173 | getpkt (buf); |
174 | if (buf[0] == 'E') |
175 | error ("Remote failure reply: %s", buf); |
176 | if (buf[0] != 'S') |
177 | error ("Invalid remote reply: %s", buf); |
178 | status->w_stopval = WSTOPPED; |
179 | status->w_stopsig = (fromhex (buf[1]) << 4) + fromhex (buf[2]); |
180 | } |
181 | |
182 | /* Read the remote registers into the block REGS. */ |
183 | |
184 | void |
185 | remote_fetch_registers (regs) |
186 | char *regs; |
187 | { |
188 | char buf[PBUFSIZ]; |
189 | int i; |
190 | char *p; |
191 | |
192 | sprintf (buf, "g"); |
193 | remote_send (buf); |
194 | |
195 | /* Reply describes registers byte by byte, |
196 | each byte encoded as two hex characters. */ |
197 | |
198 | p = buf; |
199 | for (i = 0; i < REGISTER_BYTES; i++) |
200 | { |
201 | if (p[0] == 0 || p[1] == 0) |
202 | error ("Remote reply is too short: %s", buf); |
203 | regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); |
204 | p += 2; |
205 | } |
206 | } |
207 | |
208 | /* Store the remote registers from the contents of the block REGS. */ |
209 | |
210 | void |
211 | remote_store_registers (regs) |
212 | char *regs; |
213 | { |
214 | char buf[PBUFSIZ]; |
215 | int i; |
216 | char *p; |
217 | |
218 | buf[0] = 'G'; |
219 | |
220 | /* Command describes registers byte by byte, |
221 | each byte encoded as two hex characters. */ |
222 | |
223 | p = buf + 1; |
224 | for (i = 0; i < REGISTER_BYTES; i++) |
225 | { |
226 | *p++ = (regs[i] > 4) & 0xf; |
227 | *p++ = regs[i] & 0xf; |
228 | } |
229 | |
230 | remote_send (buf); |
231 | } |
232 | |
233 | /* Read a word from remote address ADDR and return it. |
234 | This goes through the data cache. */ |
235 | |
236 | int |
237 | remote_fetch_word (addr) |
238 | CORE_ADDR addr; |
239 | { |
240 | if (icache) |
241 | { |
242 | extern CORE_ADDR text_start, text_end; |
243 | |
244 | if (addr >= text_start && addr < text_end) |
245 | { |
246 | int buffer; |
247 | xfer_core_file (addr, &buffer, sizeof (int)); |
248 | return buffer; |
249 | } |
250 | } |
251 | return dcache_fetch (addr); |
252 | } |
253 | |
254 | /* Write a word WORD into remote address ADDR. |
255 | This goes through the data cache. */ |
256 | |
257 | void |
258 | remote_store_word (addr, word) |
259 | CORE_ADDR addr; |
260 | int word; |
261 | { |
262 | dcache_poke (addr, word); |
263 | } |
264 | \f |
265 | /* Write memory data directly to the remote machine. |
266 | This does not inform the data cache; the data cache uses this. |
267 | MEMADDR is the address in the remote memory space. |
268 | MYADDR is the address of the buffer in our space. |
269 | LEN is the number of bytes. */ |
270 | |
271 | void |
272 | remote_write_bytes (memaddr, myaddr, len) |
273 | CORE_ADDR memaddr; |
274 | char *myaddr; |
275 | int len; |
276 | { |
277 | char buf[PBUFSIZ]; |
278 | int i; |
279 | char *p; |
280 | |
281 | if (len > PBUFSIZ / 2 - 20) |
282 | abort (); |
283 | |
284 | sprintf (buf, "M%x,%x:", memaddr, len); |
285 | |
286 | /* Command describes registers byte by byte, |
287 | each byte encoded as two hex characters. */ |
288 | |
289 | p = buf + strlen (buf); |
290 | for (i = 0; i < len; i++) |
291 | { |
292 | *p++ = (myaddr[i] > 4) & 0xf; |
293 | *p++ = myaddr[i] & 0xf; |
294 | } |
295 | |
296 | remote_send (buf); |
297 | } |
298 | |
299 | /* Read memory data directly from the remote machine. |
300 | This does not use the data cache; the data cache uses this. |
301 | MEMADDR is the address in the remote memory space. |
302 | MYADDR is the address of the buffer in our space. |
303 | LEN is the number of bytes. */ |
304 | |
305 | void |
306 | remote_read_bytes (memaddr, myaddr, len) |
307 | CORE_ADDR memaddr; |
308 | char *myaddr; |
309 | int len; |
310 | { |
311 | char buf[PBUFSIZ]; |
312 | int i; |
313 | char *p; |
314 | |
315 | if (len > PBUFSIZ / 2 - 1) |
316 | abort (); |
317 | |
318 | sprintf (buf, "m%x,%x", memaddr, len); |
319 | remote_send (buf); |
320 | |
321 | /* Reply describes registers byte by byte, |
322 | each byte encoded as two hex characters. */ |
323 | |
324 | p = buf; |
325 | for (i = 0; i < REGISTER_BYTES; i++) |
326 | { |
327 | if (p[0] == 0 || p[1] == 0) |
328 | error ("Remote reply is too short: %s", buf); |
329 | myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]); |
330 | p += 2; |
331 | } |
332 | } |
333 | \f |
334 | /* |
335 | |
336 | A debug packet whose contents are <data> |
337 | is encapsulated for transmission in the form: |
338 | |
339 | $ <data> # CSUM1 CSUM2 |
340 | |
341 | <data> must be ASCII alphanumeric and cannot include characters |
342 | '$' or '#' |
343 | |
344 | CSUM1 and CSUM2 are ascii hex representation of an 8-bit |
345 | checksum of <data>, the most significant nibble is sent first. |
346 | the hex digits 0-9,a-f are used. |
347 | |
348 | Receiver responds with: |
349 | |
350 | + - if CSUM is correct and ready for next packet |
351 | - - if CSUM is incorrect |
352 | |
353 | */ |
354 | |
355 | /* Send the command in BUF to the remote machine, |
356 | and read the reply into BUF. |
357 | Report an error if we get an error reply. */ |
358 | |
359 | static void |
360 | remote_send (buf) |
361 | char *buf; |
362 | { |
363 | int i; |
364 | putpkt (buf); |
365 | getpkt (buf); |
366 | |
367 | if (buf[0] == 'E') |
368 | error ("Remote failure reply: %s", buf); |
369 | } |
370 | |
371 | /* Send a packet to the remote machine, with error checking. |
372 | The data of the packet is in BUF. */ |
373 | |
374 | static void |
375 | putpkt (buf) |
376 | char *buf; |
377 | { |
378 | int i; |
379 | char csum = 0; |
380 | char buf2[500]; |
381 | char buf3[1]; |
382 | int cnt = strlen (buf); |
383 | char *p; |
384 | |
385 | if (kiodebug) |
386 | fprintf (stderr, "Sending packet: %s\n", buf); |
387 | |
388 | /* Copy the packet into buffer BUF2, encapsulating it |
389 | and giving it a checksum. */ |
390 | |
391 | p = buf2; |
392 | *p++ = '$'; |
393 | |
394 | for (i = 0; i < cnt; i++) |
395 | { |
396 | csum += buf[i]; |
397 | *p++ = buf[i]; |
398 | } |
399 | *p++ = '#'; |
400 | *p++ = tohex ((csum >> 4) & 0xf); |
401 | *p++ = tohex (csum & 0xf); |
402 | |
403 | /* Send it over and over until we get a positive ack. */ |
404 | |
405 | do { |
406 | write (remote_desc, buf2, p - buf2); |
407 | read (remote_desc, buf3, 1); |
408 | } while (buf3[0] != '+'); |
409 | } |
410 | |
411 | static int |
412 | readchar () |
413 | { |
414 | char buf[1]; |
415 | while (read (remote_desc, buf, 1) != 1) ; |
416 | return buf[0] & 0x7f; |
417 | } |
418 | |
419 | /* Read a packet from the remote machine, with error checking, |
420 | and store it in BUF. */ |
421 | |
422 | static void |
423 | getpkt (buf) |
424 | char *buf; |
425 | { |
426 | char *bp; |
427 | char csum = 0; |
428 | int c, c1, c2; |
429 | extern kiodebug; |
430 | |
431 | while (1) |
432 | { |
433 | while ((c = readchar()) != '$'); |
434 | |
435 | bp = buf; |
436 | while (1) |
437 | { |
438 | c = readchar (); |
439 | if (c == '#') |
440 | break; |
441 | *bp++ = c; |
442 | csum += c; |
443 | } |
444 | *bp = 0; |
445 | |
446 | c1 = fromhex (readchar ()); |
447 | c2 = fromhex (readchar ()); |
448 | if (csum == (c1 << 4) + c2) |
449 | break; |
450 | printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", |
451 | (c1 << 4) + c2, csum, buf); |
452 | write (remote_desc, "-", 1); |
453 | } |
454 | |
455 | write (remote_desc, "+", 1); |
456 | |
457 | if (kiodebug) |
458 | fprintf (stderr,"Packet received :%s\n", buf); |
459 | } |
460 | \f |
461 | /* The data cache records all the data read from the remote machine |
462 | since the last time it stopped. |
463 | |
464 | Each cache block holds 16 bytes of data |
465 | starting at a multiple-of-16 address. */ |
466 | |
467 | #define DCACHE_SIZE 64 /* Number of cache blocks */ |
468 | |
469 | struct dcache_block { |
470 | struct dcache_block *next, *last; |
471 | unsigned int addr; /* Address for which data is recorded. */ |
472 | int data[4]; |
473 | }; |
474 | |
475 | struct dcache_block dcache_free, dcache_valid; |
476 | |
477 | /* Free all the data cache blocks, thus discarding all cached data. */ |
478 | |
479 | static void |
480 | dcache_flush () |
481 | { |
482 | register struct dcache_block *db; |
483 | |
484 | while ((db = dcache_valid.next) != &dcache_valid) |
485 | { |
486 | remque (db); |
487 | insque (db, &dcache_free); |
488 | } |
489 | } |
490 | |
491 | /* |
492 | * If addr is present in the dcache, return the address of the block |
493 | * containing it. |
494 | */ |
495 | |
496 | struct dcache_block * |
497 | dcache_hit (addr) |
498 | { |
499 | register struct dcache_block *db; |
500 | |
501 | if (addr & 3) |
502 | abort (); |
503 | |
504 | /* Search all cache blocks for one that is at this address. */ |
505 | db = dcache_valid.next; |
506 | while (db != &dcache_valid) |
507 | { |
508 | if ((addr & 0xfffffff0) == db->addr) |
509 | return db; |
510 | db = db->next; |
511 | } |
512 | return NULL; |
513 | } |
514 | |
515 | /* Return the int data at address ADDR in dcache block DC. */ |
516 | |
517 | int |
518 | dcache_value (db, addr) |
519 | struct dcache_block *db; |
520 | unsigned int addr; |
521 | { |
522 | if (addr & 3) |
523 | abort (); |
524 | return (db->data[(addr>>2)&3]); |
525 | } |
526 | |
527 | /* Get a free cache block, put it on the valid list, |
528 | and return its address. The caller should store into the block |
529 | the address and data that it describes. */ |
530 | |
531 | struct dcache_block * |
532 | dcache_alloc () |
533 | { |
534 | register struct dcache_block *db; |
535 | |
536 | if ((db = dcache_free.next) == &dcache_free) |
537 | /* If we can't get one from the free list, take last valid */ |
538 | db = dcache_valid.last; |
539 | |
540 | remque (db); |
541 | insque (db, &dcache_valid); |
542 | return (db); |
543 | } |
544 | |
545 | /* Return the contents of the word at address ADDR in the remote machine, |
546 | using the data cache. */ |
547 | |
548 | int |
549 | dcache_fetch (addr) |
550 | CORE_ADDR addr; |
551 | { |
552 | register struct dcache_block *db; |
553 | |
554 | db = dcache_hit (addr); |
555 | if (db == 0) |
556 | { |
557 | db = dcache_alloc (); |
558 | remote_read_bytes (addr & ~0xf, db->data, 16); |
559 | db->addr = addr & ~0xf; |
560 | } |
561 | return (dcache_value (db, addr)); |
562 | } |
563 | |
564 | /* Write the word at ADDR both in the data cache and in the remote machine. */ |
565 | |
566 | dcache_poke (addr, data) |
567 | CORE_ADDR addr; |
568 | int data; |
569 | { |
570 | register struct dcache_block *db; |
571 | |
572 | /* First make sure the word is IN the cache. DB is its cache block. */ |
573 | db = dcache_hit (addr); |
574 | if (db == 0) |
575 | { |
576 | db = dcache_alloc (); |
577 | remote_read_bytes (addr & ~0xf, db->data, 16); |
578 | db->addr = addr & ~0xf; |
579 | } |
580 | |
581 | /* Modify the word in the cache. */ |
582 | db->data[(addr>>2)&3] = data; |
583 | |
584 | /* Send the changed word. */ |
585 | remote_write_bytes (addr, &data, 4); |
586 | } |
587 | |
588 | /* Initialize the data cache. */ |
589 | |
590 | dcache_init () |
591 | { |
592 | register i; |
593 | register struct dcache_block *db; |
594 | |
595 | db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) * |
596 | DCACHE_SIZE); |
597 | dcache_free.next = dcache_free.last = &dcache_free; |
598 | dcache_valid.next = dcache_valid.last = &dcache_valid; |
599 | for (i=0;i<DCACHE_SIZE;i++,db++) |
600 | insque (db, &dcache_free); |
601 | } |
602 | |
603 | static initialize () |
604 | { |
605 | } |
606 | |
607 | END_FILE |