]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp_udp.c
xnu-344.21.74.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp_udp.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
9bccf70c
A
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.
1c79356b
A
32 */
33
34#include <mach_kdb.h>
35#include <mach/boolean.h>
1c79356b 36#include <mach/mach_types.h>
d7e50217 37#include <mach/exception_types.h>
9bccf70c 38#include <kern/cpu_data.h>
1c79356b
A
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
47extern int kdp_getc(void);
9bccf70c 48extern int reattach_wait;
1c79356b 49
9bccf70c 50static u_short ip_id; /* ip packet ctr, for ids */
1c79356b
A
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 */
59int udp_ttl=UDP_TTL;
60static unsigned char exception_seq;
61
62static struct {
63 unsigned char data[KDP_MAXPACKET];
64 unsigned int off, len;
65 boolean_t input;
66} pkt, saved_reply;
67
68struct {
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
79static 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
9bccf70c
A
90int kdp_flag = 0;
91
1c79356b
A
92static kdp_send_t kdp_en_send_pkt = 0;
93static kdp_receive_t kdp_en_recv_pkt = 0;
94
9bccf70c
A
95
96static unsigned int kdp_current_ip_address = 0;
97static struct ether_addr kdp_current_mac_address = {{0, 0, 0, 0, 0, 0}};
98static char kdp_arp_init = 0;
99
1c79356b
A
100static void kdp_handler( void *);
101
102void
9bccf70c
A
103kdp_register_send_receive(
104 kdp_send_t send,
105 kdp_receive_t receive)
1c79356b 106{
9bccf70c 107 unsigned int debug;
1c79356b
A
108
109 kdp_en_send_pkt = send;
110 kdp_en_recv_pkt = receive;
9bccf70c
A
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
1c79356b
A
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
1c79356b 125void
9bccf70c
A
126kdp_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
137static void
1c79356b 138enaddr_copy(
9bccf70c
A
139 void *src,
140 void *dst
1c79356b
A
141)
142{
9bccf70c 143 bcopy((char *)src, (char *)dst, sizeof (struct ether_addr));
1c79356b
A
144}
145
9bccf70c 146static unsigned short
1c79356b 147ip_sum(
9bccf70c
A
148 unsigned char *c,
149 unsigned int hlen
1c79356b
A
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
9bccf70c 168static void
1c79356b 169kdp_reply(
9bccf70c 170 unsigned short reply_port
1c79356b
A
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
9bccf70c 239static void
1c79356b
A
240kdp_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);
1c79356b
A
295 (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
296}
297
9bccf70c
A
298
299void
300kdp_set_ip_and_mac_addresses(
301 struct in_addr *ipaddr,
302 struct ether_addr *macaddr)
1c79356b 303{
9bccf70c
A
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
318struct ether_addr
319kdp_get_mac_addr(void)
320{
321 return kdp_current_mac_address;
322}
323
324unsigned int
325kdp_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
336static void
337kdp_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
381static void
382kdp_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
1c79356b
A
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
9bccf70c 401 pkt.off = pkt.len = 0;
1c79356b 402 (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */);
9bccf70c 403
1c79356b
A
404 if (pkt.len == 0)
405 return;
9bccf70c
A
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
1c79356b
A
421 if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr)))
422 return;
9bccf70c 423
1c79356b
A
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
9bccf70c 466static void
1c79356b 467kdp_handler(
9bccf70c 468 void *saved_state
1c79356b
A
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
9bccf70c
A
492 if (hdr->request == KDP_REATTACH)
493 exception_seq = hdr->seq;
494
1c79356b
A
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
513again:
514 pkt.input = FALSE;
515 } while (kdp.is_halted);
516}
517
9bccf70c
A
518static void
519kdp_connection_wait(void)
1c79356b
A
520{
521 unsigned short reply_port;
522 boolean_t kdp_call_kdb();
9bccf70c
A
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
1c79356b 540 printf("\nWaiting for remote debugger connection.\n");
9bccf70c
A
541
542 if (reattach_wait == 0)
543 {
1c79356b 544#ifdef MACH_PE
9bccf70c 545 if( 0 != kdp_getc())
1c79356b 546#endif
9bccf70c
A
547 {
548 printf("Options..... Type\n");
549 printf("------------ ----\n");
550 printf("continue.... 'c'\n");
551 printf("reboot...... 'r'\n");
1c79356b 552#if MACH_KDB
9bccf70c 553 printf("enter kdb... 'k'\n");
1c79356b 554#endif
9bccf70c
A
555 }
556 }
557 else
558 reattach_wait = 0;
559
1c79356b
A
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 }
9bccf70c 599 if (((hdr->request == KDP_CONNECT) || (hdr->request == KDP_REATTACH)) &&
1c79356b
A
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);
9bccf70c
A
605 if (hdr->request == KDP_REATTACH)
606 {
607 reattach_wait = 0;
608 hdr->request=KDP_DISCONNECT;
609 exception_seq = 0;
610 }
1c79356b
A
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
9bccf70c 621static void
1c79356b
A
622kdp_send_exception(
623 unsigned int exception,
624 unsigned int code,
625 unsigned int subcode
626)
627{
628 unsigned short remote_port;
9bccf70c
A
629 unsigned int timeout_count = 100;
630 unsigned int poll_timeout;
1c79356b 631
1c79356b
A
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);
9bccf70c 640
1c79356b
A
641 kdp_send(remote_port);
642
9bccf70c
A
643 poll_timeout = 50;
644 while(!pkt.input && poll_timeout)
645 {
646 kdp_poll();
647 poll_timeout--;
648 }
649
1c79356b
A
650 if (pkt.input) {
651 if (!kdp_exception_ack(&pkt.data[pkt.off], pkt.len)) {
652 pkt.input = FALSE;
1c79356b 653 }
1c79356b 654 }
9bccf70c 655
1c79356b 656 pkt.input = FALSE;
9bccf70c 657
1c79356b 658 if (kdp.exception_ack_needed)
9bccf70c 659 kdp_us_spin(250000);
1c79356b
A
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");
9bccf70c
A
666 if (current_debugger == KDP_CUR_DB)
667 active_debugger=0;
1c79356b
A
668 kdp_reset();
669 }
670}
671
672void
673kdp_raise_exception(
674 unsigned int exception,
675 unsigned int code,
676 unsigned int subcode,
677 void *saved_state
678)
679{
1c79356b
A
680 int index;
681
9bccf70c
A
682 disable_preemption();
683
1c79356b
A
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");
9bccf70c 706 again:
1c79356b
A
707 if (!kdp.is_conn)
708 kdp_connection_wait();
709 else
9bccf70c 710 {
1c79356b 711 kdp_send_exception(exception, code, subcode);
9bccf70c
A
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 }
1c79356b
A
719
720 if (kdp.is_conn) {
721 kdp.is_halted = TRUE; /* XXX */
722 kdp_handler(saved_state);
723 if (!kdp.is_conn)
9bccf70c
A
724 {
725 kdp_remove_all_breakpoints();
1c79356b 726 printf("Remote debugger disconnected.\n");
9bccf70c 727 }
1c79356b
A
728 }
729
730 kdp_sync_cache();
9bccf70c
A
731
732 if (reattach_wait == 1)
733 goto again;
734
735 enable_preemption();
1c79356b
A
736}
737
738void
739kdp_reset(void)
740{
9bccf70c
A
741 kdp.reply_port = kdp.exception_port = 0;
742 kdp.is_halted = kdp.is_conn = FALSE;
743 kdp.exception_seq = kdp.conn_seq = 0;
1c79356b
A
744}
745