|
|
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.