|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1993 NeXT Computer, Inc. All rights reserved.
24: *
25: * kdp_udp.c -- Kernel Debugging Protocol UDP implementation.
26: *
27: */
28:
29: #include <mach_kdb.h>
30: #include <mach/boolean.h>
31: #include <mach/exception_types.h>
32: #include <mach/mach_types.h>
33: #include <kern/debug.h>
34:
35: #include <kdp/kdp_internal.h>
36: #include <kdp/kdp_en_debugger.h>
37: #include <kdp/kdp_udp.h>
38:
39: #define DO_ALIGN 1 /* align all packet data accesses */
40:
41: extern int kdp_getc(void);
42:
43: static
44: u_short ip_id; /* ip packet ctr, for ids */
45:
46: /* @(#)udp_usrreq.c 2.2 88/05/23 4.0NFSSRC SMI; from UCB 7.1 6/5/86 */
47:
48: /*
49: * UDP protocol implementation.
50: * Per RFC 768, August, 1980.
51: */
52: #define UDP_TTL 60 /* deflt time to live for UDP packets */
53: int udp_ttl=UDP_TTL;
54: static unsigned char exception_seq;
55:
56: static struct {
57: unsigned char data[KDP_MAXPACKET];
58: unsigned int off, len;
59: boolean_t input;
60: } pkt, saved_reply;
61:
62: struct {
63: struct {
64: struct in_addr in;
65: struct ether_addr ea;
66: } loc;
67: struct {
68: struct in_addr in;
69: struct ether_addr ea;
70: } rmt;
71: } adr;
72:
73: static char
74: *exception_message[] = {
75: "Unknown",
76: "Memory access", /* EXC_BAD_ACCESS */
77: "Failed instruction", /* EXC_BAD_INSTRUCTION */
78: "Arithmetic", /* EXC_ARITHMETIC */
79: "Emulation", /* EXC_EMULATION */
80: "Software", /* EXC_SOFTWARE */
81: "Breakpoint" /* EXC_BREAKPOINT */
82: };
83:
84: static kdp_send_t kdp_en_send_pkt = 0;
85: static kdp_receive_t kdp_en_recv_pkt = 0;
86:
87: static void kdp_handler( void *);
88:
89: void
90: kdp_register_send_receive(kdp_send_t send, kdp_receive_t receive)
91: {
92: #define KDP_READY 0x1
93:
94: kdp_en_send_pkt = send;
95: kdp_en_recv_pkt = receive;
96: kdp_flag |= KDP_READY;
97: if (current_debugger == NO_CUR_DB)
98: current_debugger = KDP_CUR_DB;
99: if (halt_in_debugger) {
100: kdp_call();
101: halt_in_debugger=0;
102: }
103: }
104:
105: static
106: void
107: enaddr_copy(
108: void *src,
109: void *dst
110: )
111: {
112: bcopy((char *)src, (char *)dst, sizeof (struct ether_addr));
113: }
114:
115: static
116: unsigned short
117: ip_sum(
118: unsigned char *c,
119: unsigned int hlen
120: )
121: {
122: unsigned int high, low, sum;
123:
124: high = low = 0;
125: while (hlen-- > 0) {
126: low += c[1] + c[3];
127: high += c[0] + c[2];
128:
129: c += sizeof (int);
130: }
131:
132: sum = (high << 8) + low;
133: sum = (sum >> 16) + (sum & 65535);
134:
135: return (sum > 65535 ? sum - 65535 : sum);
136: }
137:
138: static
139: void
140: kdp_reply(
141: unsigned short reply_port
142: )
143: {
144: struct udpiphdr aligned_ui, *ui = &aligned_ui;
145: struct ip aligned_ip, *ip = &aligned_ip;
146: struct in_addr tmp_ipaddr;
147: struct ether_addr tmp_enaddr;
148: struct ether_header *eh;
149:
150: if (!pkt.input)
151: kdp_panic("kdp_reply");
152:
153: pkt.off -= sizeof (struct udpiphdr);
154:
155: #if DO_ALIGN
156: bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
157: #else
158: ui = (struct udpiphdr *)&pkt.data[pkt.off];
159: #endif
160: ui->ui_next = ui->ui_prev = 0;
161: ui->ui_x1 = 0;
162: ui->ui_pr = IPPROTO_UDP;
163: ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
164: tmp_ipaddr = ui->ui_src;
165: ui->ui_src = ui->ui_dst;
166: ui->ui_dst = tmp_ipaddr;
167: ui->ui_sport = htons(KDP_REMOTE_PORT);
168: ui->ui_dport = reply_port;
169: ui->ui_ulen = ui->ui_len;
170: ui->ui_sum = 0;
171: #if DO_ALIGN
172: bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
173:
174: bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
175: #else
176: ip = (struct ip *)&pkt.data[pkt.off];
177: #endif
178: ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
179: ip->ip_v = IPVERSION;
180: ip->ip_id = htons(ip_id++);
181: ip->ip_hl = sizeof (struct ip) >> 2;
182: ip->ip_ttl = udp_ttl;
183: ip->ip_sum = 0;
184: ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
185: #if DO_ALIGN
186: bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
187: #endif
188:
189: pkt.len += sizeof (struct udpiphdr);
190:
191: pkt.off -= sizeof (struct ether_header);
192:
193: eh = (struct ether_header *)&pkt.data[pkt.off];
194: enaddr_copy(eh->ether_shost, &tmp_enaddr);
195: enaddr_copy(eh->ether_dhost, eh->ether_shost);
196: enaddr_copy(&tmp_enaddr, eh->ether_dhost);
197: eh->ether_type = htons(ETHERTYPE_IP);
198:
199: pkt.len += sizeof (struct ether_header);
200:
201: // save reply for possible retransmission
202: bcopy((char *)&pkt, (char *)&saved_reply, sizeof(pkt));
203:
204: (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
205:
206: // increment expected sequence number
207: exception_seq++;
208: }
209:
210: static
211: void
212: kdp_send(
213: unsigned short remote_port
214: )
215: {
216: struct udpiphdr aligned_ui, *ui = &aligned_ui;
217: struct ip aligned_ip, *ip = &aligned_ip;
218: struct ether_header *eh;
219:
220: if (pkt.input)
221: kdp_panic("kdp_send");
222:
223: pkt.off -= sizeof (struct udpiphdr);
224:
225: #if DO_ALIGN
226: bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
227: #else
228: ui = (struct udpiphdr *)&pkt.data[pkt.off];
229: #endif
230: ui->ui_next = ui->ui_prev = 0;
231: ui->ui_x1 = 0;
232: ui->ui_pr = IPPROTO_UDP;
233: ui->ui_len = htons((u_short)pkt.len + sizeof (struct udphdr));
234: ui->ui_src = adr.loc.in;
235: ui->ui_dst = adr.rmt.in;
236: ui->ui_sport = htons(KDP_REMOTE_PORT);
237: ui->ui_dport = remote_port;
238: ui->ui_ulen = ui->ui_len;
239: ui->ui_sum = 0;
240: #if DO_ALIGN
241: bcopy((char *)ui, (char *)&pkt.data[pkt.off], sizeof(*ui));
242: bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
243: #else
244: ip = (struct ip *)&pkt.data[pkt.off];
245: #endif
246: ip->ip_len = htons(sizeof (struct udpiphdr) + pkt.len);
247: ip->ip_v = IPVERSION;
248: ip->ip_id = htons(ip_id++);
249: ip->ip_hl = sizeof (struct ip) >> 2;
250: ip->ip_ttl = udp_ttl;
251: ip->ip_sum = 0;
252: ip->ip_sum = htons(~ip_sum((unsigned char *)ip, ip->ip_hl));
253: #if DO_ALIGN
254: bcopy((char *)ip, (char *)&pkt.data[pkt.off], sizeof(*ip));
255: #endif
256:
257: pkt.len += sizeof (struct udpiphdr);
258:
259: pkt.off -= sizeof (struct ether_header);
260:
261: eh = (struct ether_header *)&pkt.data[pkt.off];
262: enaddr_copy(&adr.loc.ea, eh->ether_shost);
263: enaddr_copy(&adr.rmt.ea, eh->ether_dhost);
264: eh->ether_type = htons(ETHERTYPE_IP);
265:
266: pkt.len += sizeof (struct ether_header);
267:
268: (*kdp_en_send_pkt)(&pkt.data[pkt.off], pkt.len);
269: }
270:
271: static
272: void
273: kdp_poll(
274: void
275: )
276: {
277: struct ether_header *eh;
278: struct udpiphdr aligned_ui, *ui = &aligned_ui;
279: struct ip aligned_ip, *ip = &aligned_ip;
280: static int msg_printed;
281:
282: if (pkt.input)
283: kdp_panic("kdp_poll");
284:
285: if (!kdp_en_recv_pkt || !kdp_en_send_pkt) {
286: if( msg_printed == 0) {
287: msg_printed = 1;
288: printf("kdp_poll: no debugger device\n");
289: }
290: return;
291: }
292:
293: pkt.off = 0;
294: (*kdp_en_recv_pkt)(pkt.data, &pkt.len, 3/* ms */);
295:
296: if (pkt.len == 0)
297: return;
298:
299: if (pkt.len < (sizeof (struct ether_header) + sizeof (struct udpiphdr)))
300: return;
301:
302: eh = (struct ether_header *)&pkt.data[pkt.off];
303: pkt.off += sizeof (struct ether_header);
304: if (ntohs(eh->ether_type) != ETHERTYPE_IP) {
305: return;
306: }
307:
308: #if DO_ALIGN
309: bcopy((char *)&pkt.data[pkt.off], (char *)ui, sizeof(*ui));
310: bcopy((char *)&pkt.data[pkt.off], (char *)ip, sizeof(*ip));
311: #else
312: ui = (struct udpiphdr *)&pkt.data[pkt.off];
313: ip = (struct ip *)&pkt.data[pkt.off];
314: #endif
315:
316: pkt.off += sizeof (struct udpiphdr);
317: if (ui->ui_pr != IPPROTO_UDP) {
318: return;
319: }
320:
321: if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
322: return;
323: }
324:
325: if (ntohs(ui->ui_dport) != KDP_REMOTE_PORT) {
326: return;
327: }
328:
329: if (!kdp.is_conn) {
330: enaddr_copy(eh->ether_dhost, &adr.loc.ea);
331: adr.loc.in = ui->ui_dst;
332:
333: enaddr_copy(eh->ether_shost, &adr.rmt.ea);
334: adr.rmt.in = ui->ui_src;
335: }
336:
337: /*
338: * Calculate kdp packet length.
339: */
340: pkt.len = ntohs((u_short)ui->ui_ulen) - sizeof (struct udphdr);
341: pkt.input = TRUE;
342:
343: }
344:
345: static
346: void
347: kdp_handler(
348: void *saved_state
349: )
350: {
351: unsigned short reply_port;
352: kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
353:
354:
355: kdp.saved_state = saved_state; // see comment in kdp_raise_exception
356:
357: do {
358: while (!pkt.input)
359: kdp_poll();
360:
361: #if DO_ALIGN
362: bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
363: #else
364: hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
365: #endif
366:
367: // ignore replies -- we're not expecting them anyway.
368: if (hdr->is_reply) {
369: goto again;
370: }
371:
372: // check for retransmitted request
373: if (hdr->seq == (exception_seq - 1)) {
374: /* retransmit last reply */
375: (*kdp_en_send_pkt)(&saved_reply.data[saved_reply.off],
376: saved_reply.len);
377: goto again;
378: } else if (hdr->seq != exception_seq) {
379: printf("kdp: bad sequence %d (want %d)\n",
380: hdr->seq, exception_seq);
381: goto again;
382: }
383:
384: if (kdp_packet((unsigned char*)&pkt.data[pkt.off],
385: (int *)&pkt.len,
386: (unsigned short *)&reply_port)) {
387: kdp_reply(reply_port);
388: }
389:
390: again:
391: pkt.input = FALSE;
392: } while (kdp.is_halted);
393: }
394:
395: static
396: void
397: kdp_connection_wait(
398: void
399: )
400: {
401: unsigned short reply_port;
402: boolean_t kdp_call_kdb();
403:
404: printf("\nWaiting for remote debugger connection.\n");
405: #ifdef MACH_PE
406: if( 0 != kdp_getc())
407: #endif
408: {
409: printf("Options..... Type\n");
410: printf("------------ ----\n");
411: printf("continue.... 'c'\n");
412: printf("reboot...... 'r'\n");
413: #if MACH_KDB
414: printf("enter kdb... 'k'\n");
415: #endif
416: }
417:
418: exception_seq = 0;
419: do {
420: kdp_hdr_t aligned_hdr, *hdr = &aligned_hdr;
421:
422: while (!pkt.input) {
423: int c;
424: c = kdp_getc();
425: switch(c) {
426: case 'c':
427: printf("Continuing...\n");
428: return;
429: case 'r':
430: printf("Rebooting...\n");
431: kdp_reboot();
432: break;
433: #if MACH_KDB
434: case 'k':
435: printf("calling kdb...\n");
436: if (kdp_call_kdb())
437: return;
438: else
439: printf("not implemented...\n");
440: #endif
441: default:
442: break;
443: }
444: kdp_poll();
445: }
446:
447: // check for sequence number of 0
448: #if DO_ALIGN
449: bcopy((char *)&pkt.data[pkt.off], (char *)hdr, sizeof(*hdr));
450: #else
451: hdr = (kdp_hdr_t *)&pkt.data[pkt.off];
452: #endif
453: if (hdr->request == KDP_HOSTREBOOT) {
454: kdp_reboot();
455: /* should not return! */
456: }
457: if ((hdr->request == KDP_CONNECT) &&
458: !hdr->is_reply && (hdr->seq == exception_seq)) {
459: if (kdp_packet((unsigned char *)&pkt.data[pkt.off],
460: (int *)&pkt.len,
461: (unsigned short *)&reply_port))
462: kdp_reply(reply_port);
463: }
464:
465: pkt.input = FALSE;
466: } while (!kdp.is_conn);
467:
468: if (current_debugger == KDP_CUR_DB)
469: active_debugger=1;
470: printf("Connected to remote debugger.\n");
471: }
472:
473: static
474: void
475: kdp_send_exception(
476: unsigned int exception,
477: unsigned int code,
478: unsigned int subcode
479: )
480: {
481: unsigned short remote_port;
482: unsigned int timeout_count;
483:
484: timeout_count = 300; // should be about 30 seconds
485: do {
486: pkt.off = sizeof (struct ether_header) + sizeof (struct udpiphdr);
487: kdp_exception((unsigned char *)&pkt.data[pkt.off],
488: (int *)&pkt.len,
489: (unsigned short *)&remote_port,
490: (unsigned int)exception,
491: (unsigned int)code,
492: (unsigned int)subcode);
493:
494: kdp_send(remote_port);
495:
496: again:
497: kdp_poll();
498:
499: if (pkt.input) {
500: if (!kdp_exception_ack(&pkt.data[pkt.off], pkt.len)) {
501: pkt.input = FALSE;
502: goto again;
503: }
504: } else {
505: pkt.input = FALSE;
506: goto again;
507: }
508: pkt.input = FALSE;
509: if (kdp.exception_ack_needed)
510: kdp_us_spin(100000); // 1/10 sec
511:
512: } while (kdp.exception_ack_needed && timeout_count--);
513:
514: if (kdp.exception_ack_needed) {
515: // give up & disconnect
516: printf("kdp: exception ack timeout\n");
517: kdp_reset();
518: }
519: }
520:
521: void
522: kdp_raise_exception(
523: unsigned int exception,
524: unsigned int code,
525: unsigned int subcode,
526: void *saved_state
527: )
528: {
529: int s;
530: int index;
531:
532: if (saved_state == 0)
533: printf("kdp_raise_exception with NULL state\n");
534:
535: index = exception;
536: if (exception != EXC_BREAKPOINT) {
537: if (exception > EXC_BREAKPOINT || exception < EXC_BAD_ACCESS) {
538: index = 0;
539: }
540: printf("%s exception (%x,%x,%x)\n",
541: exception_message[index],
542: exception, code, subcode);
543: }
544:
545: kdp_sync_cache();
546:
547: /* XXX WMG it seems that sometimes it doesn't work to let kdp_handler
548: * do this. I think the client and the host can get out of sync.
549: */
550: kdp.saved_state = saved_state;
551:
552: if (pkt.input)
553: kdp_panic("kdp_raise_exception");
554:
555: if (!kdp.is_conn)
556: kdp_connection_wait();
557: else
558: kdp_send_exception(exception, code, subcode);
559:
560: if (kdp.is_conn) {
561: kdp.is_halted = TRUE; /* XXX */
562: kdp_handler(saved_state);
563: if (!kdp.is_conn)
564: printf("Remote debugger disconnected.\n");
565: }
566:
567: kdp_sync_cache();
568: }
569:
570: void
571: kdp_reset(void)
572: {
573: kdp.reply_port = kdp.exception_port = 0;
574: kdp.is_halted = kdp.is_conn = FALSE;
575: kdp.exception_seq = kdp.conn_seq = 0;
576: }
577:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.