]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/kdp_udp.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp_udp.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1982, 1986, 1993
27 * The Regents of the University of California. All rights reserved.
28 */
29
30 /*
31 * Kernel Debugging Protocol UDP implementation.
32 */
33
34 #include <mach_kdb.h>
35 #include <mach/boolean.h>
36 #include <mach/mach_types.h>
37 #include <mach/exception_types.h>
38 #include <kern/cpu_data.h>
39 #include <kern/debug.h>
40
41 #include <kdp/kdp_internal.h>
42 #include <kdp/kdp_en_debugger.h>
43 #include <kdp/kdp_udp.h>
44
45 #define DO_ALIGN 1 /* align all packet data accesses */
46
47 extern int kdp_getc(void);
48 extern int reattach_wait;
49
50 static u_short ip_id; /* ip packet ctr, for ids */
51
52 /* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */
53
54 /*
55 * UDP protocol implementation.
56 * Per RFC 768, August, 1980.
57 */
58 #define UDP_TTL 60 /* deflt time to live for UDP packets */
59 int udp_ttl=UDP_TTL;
60 static unsigned char exception_seq;
61
62 static struct {
63 unsigned char data[KDP_MAXPACKET];
64 unsigned int off, len;
65 boolean_t input;
66 } pkt, saved_reply;
67
68 struct {
69 struct {
70 struct in_addr in;
71 struct ether_addr ea;
72 } loc;
73 struct {
74 struct in_addr in;
75 struct ether_addr ea;
76 } rmt;
77 } adr;
78
79 static char
80 *exception_message[] = {
81 "Unknown",
82 "Memory access", /* EXC_BAD_ACCESS */
83 "Failed instruction", /* EXC_BAD_INSTRUCTION */
84 "Arithmetic", /* EXC_ARITHMETIC */
85 "Emulation", /* EXC_EMULATION */
86 "Software", /* EXC_SOFTWARE */
87 "Breakpoint" /* EXC_BREAKPOINT */
88 };
89
90 int kdp_flag = 0;
91
92 static kdp_send_t kdp_en_send_pkt = 0;
93 static kdp_receive_t kdp_en_recv_pkt = 0;
94
95
96 static unsigned int kdp_current_ip_address = 0;
97 static struct ether_addr kdp_current_mac_address = {{0, 0, 0, 0, 0, 0}};
98 static char kdp_arp_init = 0;
99
100 static void kdp_handler( void *);
101
102 void
103 kdp_register_send_receive(
104 kdp_send_t send,
105 kdp_receive_t receive)
106 {
107 unsigned int debug;
108
109 kdp_en_send_pkt = send;
110 kdp_en_recv_pkt = receive;
111 debug_log_init();
112 PE_parse_boot_arg("debug", &debug);
113 if (debug & DB_KDP_BP_DIS)
114 kdp_flag |= KDP_BP_DIS;
115
116 kdp_flag |= KDP_READY;
117 if (current_debugger == NO_CUR_DB)
118 current_debugger = KDP_CUR_DB;
119 if (halt_in_debugger) {
120 kdp_call();
121 halt_in_debugger=0;
122 }
123 }
124
125 void
126 kdp_unregister_send_receive(
127 kdp_send_t send,
128 kdp_receive_t receive)
129 {
130 if (current_debugger == KDP_CUR_DB)
131 current_debugger = NO_CUR_DB;
132 kdp_flag &= ~KDP_READY;
133 kdp_en_send_pkt = NULL;
134 kdp_en_recv_pkt = NULL;
135 }
136
137 static void
138 enaddr_copy(
139 void *src,
140 void *dst
141 )
142 {
143 bcopy((char *)src, (char *)dst, sizeof (struct ether_addr));
144 }
145
146 static unsigned short
147 ip_sum(
148 unsigned char *c,
149 unsigned int hlen
150 )
151 {
152 unsigned int high, low, sum;
153
154 high = low = 0;
155 while (hlen-- > 0) {
156 low += c[1] + c[3];
157 high += c[0] + c[2];
158
159 c += sizeof (int);
160 }
161
162 sum = (high << 8) + low;
163 sum = (sum >> 16) + (sum & 65535);
164
165 return (sum > 65535 ? sum - 65535 : sum);
166 }
167
168 static void
169 kdp_reply(
170 unsigned short reply_port
171 )
172 {
173 struct udpiphdr aligned_ui, *ui = &aligned_ui;
174 struct ip aligned_ip, *ip = &aligned_ip;
175 struct in_addr tmp_ipaddr;
176 struct ether_addr tmp_enaddr;
177 struct ether_header *eh;
178
179 if (!pkt.input)
180 kdp_panic("kdp_reply");
181
182 pkt.off -= sizeof (struct udpiphdr);
183
184 #if DO_ALIGN
185 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
186 #else
187 ui = (struct udpiphdr *)&pkt.data[pkt.off];
188 #endif
189 ui->ui_next = ui->ui_prev = 0;
190 ui->ui_x1 = 0;
191 ui->ui_pr = IPPROTO_UDP;
192 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
193 tmp_ipaddr = ui->ui_src;
194 ui->ui_src = ui->ui_dst;
195 ui->ui_dst = tmp_ipaddr;
196 ui->ui_sport = htons(KDP_REMOTE_PORT);
197 ui->ui_dport = reply_port;
198 ui->ui_ulen = ui->ui_len;
199 ui->ui_sum = 0;
200 #if DO_ALIGN
201 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
202
203 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
204 #else
205 ip = (struct ip *)&pkt.data[pkt.off];
206 #endif
207 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
208 ip->ip_v = IPVERSION;
209 ip->ip_id = htons(ip_id++);
210 ip->ip_hl = sizeof (struct ip) >> 2;
211 ip->ip_ttl = udp_ttl;
212 ip->ip_sum = 0;
213 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
214 #if DO_ALIGN
215 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
216 #endif
217
218 pkt.len += sizeof (struct udpiphdr);
219
220 pkt.off -= sizeof (struct ether_header);
221
222 eh = (struct ether_header *)&pkt.data[pkt.off];
223 enaddr_copy(eh->ether_shost, &tmp_enaddr);
224 enaddr_copy(eh->ether_dhost, eh->ether_shost);
225 enaddr_copy(&tmp_enaddr, eh->ether_dhost);
226 eh->ether_type = htons(ETHERTYPE_IP);
227
228 pkt.len += sizeof (struct ether_header);
229
230 // save reply for possible retransmission
231 bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt));
232
233 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
234
235 // increment expected sequence number
236 exception_seq++;
237 }
238
239 static void
240 kdp_send(
241 unsigned short remote_port
242 )
243 {
244 struct udpiphdr aligned_ui, *ui = &aligned_ui;
245 struct ip aligned_ip, *ip = &aligned_ip;
246 struct ether_header *eh;
247
248 if (pkt.input)
249 kdp_panic("kdp_send");
250
251 pkt.off -= sizeof (struct udpiphdr);
252
253 #if DO_ALIGN
254 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
255 #else
256 ui = (struct udpiphdr *)&pkt.data[pkt.off];
257 #endif
258 ui->ui_next = ui->ui_prev = 0;
259 ui->ui_x1 = 0;
260 ui->ui_pr = IPPROTO_UDP;
261 ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
262 ui->ui_src = adr.loc.in;
263 ui->ui_dst = adr.rmt.in;
264 ui->ui_sport = htons(KDP_REMOTE_PORT);
265 ui->ui_dport = remote_port;
266 ui->ui_ulen = ui->ui_len;
267 ui->ui_sum = 0;
268 #if DO_ALIGN
269 bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
270 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
271 #else
272 ip = (struct ip *)&pkt.data[pkt.off];
273 #endif
274 ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
275 ip->ip_v = IPVERSION;
276 ip->ip_id = htons(ip_id++);
277 ip->ip_hl = sizeof (struct ip) >> 2;
278 ip->ip_ttl = udp_ttl;
279 ip->ip_sum = 0;
280 ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
281 #if DO_ALIGN
282 bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
283 #endif
284
285 pkt.len += sizeof (struct udpiphdr);
286
287 pkt.off -= sizeof (struct ether_header);
288
289 eh = (struct ether_header *)&pkt.data[pkt.off];
290 enaddr_copy(&adr.loc.ea, eh->ether_shost);
291 enaddr_copy(&adr.rmt.ea, eh->ether_dhost);
292 eh->ether_type = htons(ETHERTYPE_IP);
293
294 pkt.len += sizeof (struct ether_header);
295 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
296 }
297
298
299 void
300 kdp_set_ip_and_mac_addresses(
301 struct in_addr *ipaddr,
302 struct ether_addr *macaddr)
303 {
304 unsigned int debug = 0;
305
306 kdp_current_ip_address = ipaddr->s_addr;
307 kdp_current_mac_address = *macaddr;
308
309 /* Get the debug boot-arg to decide if ARP replies are allowed */
310 if (kdp_arp_init == 0) {
311 PE_parse_boot_arg("debug", &debug);
312 if (debug & DB_ARP)
313 kdp_flag |= KDP_ARP;
314 kdp_arp_init = 1;
315 }
316 }
317
318 struct ether_addr
319 kdp_get_mac_addr(void)
320 {
321 return kdp_current_mac_address;
322 }
323
324 unsigned int
325 kdp_get_ip_address(void)
326 {
327 return kdp_current_ip_address;
328 }
329
330 /* ARP responses are enabled when the DB_ARP bit of the debug boot arg
331 is set. A workaround if you don't want to reboot is to set
332 kdpDEBUGFlag &= DB_ARP when connected (but that certainly isn't a published
333 interface!)
334 */
335
336 static void
337 kdp_arp_reply(void)
338 {
339 struct ether_header *eh;
340 struct ether_arp aligned_ea, *ea = &aligned_ea;
341
342 struct in_addr isaddr, itaddr, myaddr;
343 struct ether_addr my_enaddr;
344
345 eh = (struct ether_header *)&pkt.data[pkt.off];
346 pkt.off += sizeof(struct ether_header);
347
348 memcpy((void *)ea, (void *)&pkt.data[pkt.off],sizeof(*ea));
349
350 if(ntohs(ea->arp_op) != ARPOP_REQUEST)
351 return;
352
353 myaddr.s_addr = kdp_get_ip_address();
354 my_enaddr = kdp_get_mac_addr();
355
356 if (!(myaddr.s_addr) || !(my_enaddr.ether_addr_octet[1]))
357 return;
358
359 (void)memcpy((void *)&isaddr, (void *)ea->arp_spa, sizeof (isaddr));
360 (void)memcpy((void *)&itaddr, (void *)ea->arp_tpa, sizeof (itaddr));
361
362 if (itaddr.s_addr == myaddr.s_addr) {
363 (void)memcpy((void *)ea->arp_tha, (void *)ea->arp_sha, sizeof(ea->arp_sha));
364 (void)memcpy((void *)ea->arp_sha, (void *)&my_enaddr, sizeof(ea->arp_sha));
365
366 (void)memcpy((void *)ea->arp_tpa, (void *) ea->arp_spa, sizeof(ea->arp_spa));
367 (void)memcpy((void *)ea->arp_spa, (void *) &itaddr, sizeof(ea->arp_spa));
368
369 ea->arp_op = htons(ARPOP_REPLY);
370 ea->arp_pro = htons(ETHERTYPE_IP);
371 (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
372 (void)memcpy(eh->ether_shost, &my_enaddr, sizeof(eh->ether_shost));
373 eh->ether_type = htons(ETHERTYPE_ARP);
374 (void)memcpy(&pkt.data[pkt.off], ea, sizeof(*ea));
375 pkt.off -= sizeof (struct ether_header);
376 /* pkt.len is still the length we want, ether_header+ether_arp */
377 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
378 }
379 }
380
381 static void
382 kdp_poll(void)
383 {
384 struct ether_header *eh;
385 struct udpiphdr aligned_ui, *ui = &aligned_ui;
386 struct ip aligned_ip, *ip = &aligned_ip;
387 static int msg_printed;
388
389
390 if (pkt.input)
391 kdp_panic("kdp_poll");
392
393 if (!kdp_en_recv_pkt || !kdp_en_send_pkt) {
394 if( msg_printed == 0) {
395 msg_printed = 1;
396 printf("kdp_poll: no debugger device\n");
397 }
398 return;
399 }
400
401 pkt.off = pkt.len = 0;
402 (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */);
403
404 if (pkt.len == 0)
405 return;
406
407 if (pkt.len >= sizeof(struct ether_header))
408 {
409 eh = (struct ether_header *)&pkt.data[pkt.off];
410
411 if (kdp_flag & KDP_ARP)
412 {
413 if (ntohs(eh->ether_type) == ETHERTYPE_ARP)
414 {
415 kdp_arp_reply();
416 return;
417 }
418 }
419 }
420
421 if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr)))
422 return;
423
424 pkt.off += sizeof (struct ether_header);
425 if (ntohs(eh->ether_type) != ETHERTYPE_IP) {
426 return;
427 }
428
429 #if DO_ALIGN
430 bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
431 bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
432 #else
433 ui = (struct udpiphdr *)&pkt.data[pkt.off];
434 ip = (struct ip *)&pkt.data[pkt.off];
435 #endif
436
437 pkt.off += sizeof (struct udpiphdr);
438 if (ui->ui_pr != IPPROTO_UDP) {
439 return;
440 }
441
442 if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
443 return;
444 }
445
446 if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) {
447 return;
448 }
449
450 if (!kdp.is_conn) {
451 enaddr_copy(eh->ether_dhost, &adr.loc.ea);
452 adr.loc.in = ui->ui_dst;
453
454 enaddr_copy(eh->ether_shost, &adr.rmt.ea);
455 adr.rmt.in = ui->ui_src;
456 }
457
458 /*
459 * Calculate kdp packet length.
460 */
461 pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr);
462 pkt.input = TRUE;
463
464 }
465
466 static void
467 kdp_handler(
468 void *saved_state
469 )
470 {
471 unsigned short reply_port;
472 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
473
474
475 kdp.saved_state = saved_state; // see comment in kdp_raise_exception
476
477 do {
478 while (!pkt.input)
479 kdp_poll();
480
481 #if DO_ALIGN
482 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
483 #else
484 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
485 #endif
486
487 // ignore replies -- we're not expecting them anyway.
488 if (hdr->is_reply) {
489 goto again;
490 }
491
492 if (hdr->request == KDP_REATTACH)
493 exception_seq = hdr->seq;
494
495 // check for retransmitted request
496 if (hdr->seq == (exception_seq - 1)) {
497 /* retransmit last reply */
498 (*kdp_en_send_pkt)(&saved_reply.data[saved_reply.off],
499 saved_reply.len);
500 goto again;
501 } else if (hdr->seq != exception_seq) {
502 printf("kdp: bad sequence %d (want %d)\n",
503 hdr->seq, exception_seq);
504 goto again;
505 }
506
507 if (kdp_packet((unsigned char*)&pkt.data[pkt.off],
508 (int *)&pkt.len,
509 (unsigned short *)&reply_port)) {
510 kdp_reply(reply_port);
511 }
512
513 again:
514 pkt.input = FALSE;
515 } while (kdp.is_halted);
516 }
517
518 static void
519 kdp_connection_wait(void)
520 {
521 unsigned short reply_port;
522 boolean_t kdp_call_kdb();
523 struct ether_addr kdp_mac_addr = kdp_get_mac_addr();
524 unsigned int ip_addr = kdp_get_ip_address();
525
526 printf( "ethernet MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
527 kdp_mac_addr.ether_addr_octet[0] & 0xff,
528 kdp_mac_addr.ether_addr_octet[1] & 0xff,
529 kdp_mac_addr.ether_addr_octet[2] & 0xff,
530 kdp_mac_addr.ether_addr_octet[3] & 0xff,
531 kdp_mac_addr.ether_addr_octet[4] & 0xff,
532 kdp_mac_addr.ether_addr_octet[5] & 0xff);
533
534 printf( "ip address: %d.%d.%d.%d\n",
535 (ip_addr & 0xff000000) >> 24,
536 (ip_addr & 0xff0000) >> 16,
537 (ip_addr & 0xff00) >> 8,
538 (ip_addr & 0xff));
539
540 printf("\nWaiting for remote debugger connection.\n");
541
542 if (reattach_wait == 0)
543 {
544 #ifdef MACH_PE
545 if( 0 != kdp_getc())
546 #endif
547 {
548 printf("Options..... Type\n");
549 printf("------------ ----\n");
550 printf("continue.... 'c'\n");
551 printf("reboot...... 'r'\n");
552 #if MACH_KDB
553 printf("enter kdb... 'k'\n");
554 #endif
555 }
556 }
557 else
558 reattach_wait = 0;
559
560 exception_seq = 0;
561 do {
562 kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
563
564 while (!pkt.input) {
565 int c;
566 c = kdp_getc();
567 switch(c) {
568 case 'c':
569 printf("Continuing...\n");
570 return;
571 case 'r':
572 printf("Rebooting...\n");
573 kdp_reboot();
574 break;
575 #if MACH_KDB
576 case 'k':
577 printf("calling kdb...\n");
578 if (kdp_call_kdb())
579 return;
580 else
581 printf("not implemented...\n");
582 #endif
583 default:
584 break;
585 }
586 kdp_poll();
587 }
588
589 // check for sequence number of 0
590 #if DO_ALIGN
591 bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
592 #else
593 hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
594 #endif
595 if (hdr->request == KDP_HOSTREBOOT) {
596 kdp_reboot();
597 /* should not return! */
598 }
599 if (((hdr->request == KDP_CONNECT) || (hdr->request == KDP_REATTACH)) &&
600 !hdr->is_reply && (hdr->seq == exception_seq)) {
601 if (kdp_packet((unsigned char *)&pkt.data[pkt.off],
602 (int *)&pkt.len,
603 (unsigned short *)&reply_port))
604 kdp_reply(reply_port);
605 if (hdr->request == KDP_REATTACH)
606 {
607 reattach_wait = 0;
608 hdr->request=KDP_DISCONNECT;
609 exception_seq = 0;
610 }
611 }
612
613 pkt.input = FALSE;
614 } while (!kdp.is_conn);
615
616 if (current_debugger == KDP_CUR_DB)
617 active_debugger=1;
618 printf("Connected to remote debugger.\n");
619 }
620
621 static void
622 kdp_send_exception(
623 unsigned int exception,
624 unsigned int code,
625 unsigned int subcode
626 )
627 {
628 unsigned short remote_port;
629 unsigned int timeout_count = 100;
630 unsigned int poll_timeout;
631
632 do {
633 pkt.off = sizeof (struct ether_header) + sizeof (struct udpiphdr);
634 kdp_exception((unsigned char *)&pkt.data[pkt.off],
635 (int *)&pkt.len,
636 (unsigned short *)&remote_port,
637 (unsigned int)exception,
638 (unsigned int)code,
639 (unsigned int)subcode);
640
641 kdp_send(remote_port);
642
643 poll_timeout = 50;
644 while(!pkt.input && poll_timeout)
645 {
646 kdp_poll();
647 poll_timeout--;
648 }
649
650 if (pkt.input) {
651 if (!kdp_exception_ack(&pkt.data[pkt.off], pkt.len)) {
652 pkt.input = FALSE;
653 }
654 }
655
656 pkt.input = FALSE;
657
658 if (kdp.exception_ack_needed)
659 kdp_us_spin(250000);
660
661 } while (kdp.exception_ack_needed && timeout_count--);
662
663 if (kdp.exception_ack_needed) {
664 // give up & disconnect
665 printf("kdp: exception ack timeout\n");
666 if (current_debugger == KDP_CUR_DB)
667 active_debugger=0;
668 kdp_reset();
669 }
670 }
671
672 void
673 kdp_raise_exception(
674 unsigned int exception,
675 unsigned int code,
676 unsigned int subcode,
677 void *saved_state
678 )
679 {
680 int index;
681
682 disable_preemption();
683
684 if (saved_state == 0)
685 printf("kdp_raise_exception with NULL state\n");
686
687 index = exception;
688 if (exception != EXC_BREAKPOINT) {
689 if (exception > EXC_BREAKPOINT || exception < EXC_BAD_ACCESS) {
690 index = 0;
691 }
692 printf("%s exception (%x,%x,%x)\n",
693 exception_message[index],
694 exception, code, subcode);
695 }
696
697 kdp_sync_cache();
698
699 /* XXX WMG it seems that sometimes it doesn't work to let kdp_handler
700 * do this. I think the client and the host can get out of sync.
701 */
702 kdp.saved_state = saved_state;
703
704 if (pkt.input)
705 kdp_panic("kdp_raise_exception");
706 again:
707 if (!kdp.is_conn)
708 kdp_connection_wait();
709 else
710 {
711 kdp_send_exception(exception, code, subcode);
712 if (kdp.exception_ack_needed)
713 {
714 kdp.exception_ack_needed = FALSE;
715 kdp_remove_all_breakpoints();
716 printf("Remote debugger disconnected.\n");
717 }
718 }
719
720 if (kdp.is_conn) {
721 kdp.is_halted = TRUE; /* XXX */
722 kdp_handler(saved_state);
723 if (!kdp.is_conn)
724 {
725 kdp_remove_all_breakpoints();
726 printf("Remote debugger disconnected.\n");
727 }
728 }
729
730 kdp_sync_cache();
731
732 if (reattach_wait == 1)
733 goto again;
734
735 enable_preemption();
736 }
737
738 void
739 kdp_reset(void)
740 {
741 kdp.reply_port = kdp.exception_port = 0;
742 kdp.is_halted = kdp.is_conn = FALSE;
743 kdp.exception_seq = kdp.conn_seq = 0;
744 }
745