osfmk/kdp/kdp.c

xnu source @ f6217f8 2025-10-16 · 1189 lines · view on GitHub
1/* 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <mach/mach_types.h> 30#include <mach/vm_param.h> 31#include <sys/appleapiopts.h> 32#include <kern/debug.h> 33#include <uuid/uuid.h> 34 35#include <kdp/kdp_internal.h> 36#include <kdp/kdp_private.h> 37#include <kdp/kdp_core.h> 38 39#include <libsa/types.h> 40#include <libkern/section_keywords.h> 41#include <libkern/version.h> 42 43#include <string.h> /* bcopy */ 44 45#include <kern/processor.h> 46#include <kern/thread.h> 47#include <kern/clock.h> 48#include <vm/vm_map.h> 49#include <vm/vm_kern.h> 50#include <vm/vm_pageout.h> 51#include <vm/vm_shared_region.h> 52#include <libkern/OSKextLibPrivate.h> 53 54#define DO_ALIGN 1 /* align all packet data accesses */ 55 56#define KDP_TEST_HARNESS 0 57#if KDP_TEST_HARNESS 58#define dprintf(x) kprintf x 59#else 60#define dprintf(x) 61#endif 62 63SECURITY_READ_ONLY_EARLY(static kdp_dispatch_t) 64dispatch_table[KDP_INVALID_REQUEST - KDP_CONNECT] = 65{ 66/* 0 */ kdp_connect, 67/* 1 */ kdp_disconnect, 68/* 2 */ kdp_hostinfo, 69/* 3 */ kdp_version, 70/* 4 */ kdp_maxbytes, 71/* 5 */ kdp_readmem, 72/* 6 */ kdp_writemem, 73/* 7 */ kdp_readregs, 74/* 8 */ kdp_writeregs, 75/* 9 */ kdp_unknown, 76/* A */ kdp_unknown, 77/* B */ kdp_suspend, 78/* C */ kdp_resumecpus, 79/* D */ kdp_unknown, 80/* E */ kdp_unknown, 81/* F */ kdp_breakpoint_set, 82/*10 */ kdp_breakpoint_remove, 83/*11 */ kdp_regions, 84/*12 */ kdp_reattach, 85/*13 */ kdp_reboot, 86/*14 */ kdp_readmem64, 87/*15 */ kdp_writemem64, 88/*16 */ kdp_breakpoint64_set, 89/*17 */ kdp_breakpoint64_remove, 90/*18 */ kdp_kernelversion, 91/*19 */ kdp_readphysmem64, 92/*1A */ kdp_writephysmem64, 93/*1B */ kdp_readioport, 94/*1C */ kdp_writeioport, 95/*1D */ kdp_readmsr64, 96/*1E */ kdp_writemsr64, 97/*1F */ kdp_dumpinfo, 98}; 99 100kdp_glob_t kdp; 101 102#define MAX_BREAKPOINTS 100 103 104/* 105 * Version 11 of the KDP Protocol adds support for 64-bit wide memory 106 * addresses (read/write and breakpoints) as well as a dedicated 107 * kernelversion request. Version 12 adds read/writing of physical 108 * memory with 64-bit wide memory addresses. 109 */ 110#define KDP_VERSION 12 111 112typedef struct{ 113 mach_vm_address_t address; 114 uint32_t bytesused; 115 uint8_t oldbytes[MAX_BREAKINSN_BYTES]; 116} kdp_breakpoint_record_t; 117 118static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS]; 119static unsigned int breakpoints_initialized = 0; 120 121int reattach_wait = 0; 122int noresume_on_disconnect = 0; 123 124kdp_error_t 125kdp_set_breakpoint_internal( 126 mach_vm_address_t address 127 ); 128 129kdp_error_t 130kdp_remove_breakpoint_internal( 131 mach_vm_address_t address 132 ); 133 134boolean_t 135kdp_packet( 136 unsigned char *pkt, 137 int *len, 138 unsigned short *reply_port 139 ) 140{ 141 static unsigned aligned_pkt[1538 / sizeof(unsigned) + 1];// max ether pkt 142 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt; 143 size_t plen = *len; 144 kdp_req_t req; 145 boolean_t ret; 146 147#if DO_ALIGN 148 if (plen > sizeof(aligned_pkt)) { 149 printf("kdp_packet bad len %lu\n", plen); 150 return FALSE; 151 } 152 bcopy((char *)pkt, (char *)rd, plen); 153#else 154 rd = (kdp_pkt_t *)pkt; 155#endif 156 if (plen < sizeof(rd->hdr) || rd->hdr.len != plen) { 157 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len); 158 159 return FALSE; 160 } 161 162 if (rd->hdr.is_reply) { 163 printf("kdp_packet reply recvd req %x seq %x\n", 164 rd->hdr.request, rd->hdr.seq); 165 166 return FALSE; 167 } 168 169 req = rd->hdr.request; 170 if (req >= KDP_INVALID_REQUEST) { 171 printf("kdp_packet bad request %x len %d seq %x key %x\n", 172 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key); 173 174 return FALSE; 175 } 176 177 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port)); 178#if DO_ALIGN 179 bcopy((char *)rd, (char *) pkt, *len); 180#endif 181 return ret; 182} 183 184static boolean_t 185kdp_unknown( 186 kdp_pkt_t *pkt, 187 __unused int *len, 188 __unused unsigned short *reply_port 189 ) 190{ 191 kdp_pkt_t *rd = (kdp_pkt_t *)pkt; 192 193 printf("kdp_unknown request %x len %d seq %x key %x\n", 194 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key); 195 196 return FALSE; 197} 198 199static boolean_t 200kdp_connect( 201 kdp_pkt_t *pkt, 202 int *len, 203 unsigned short *reply_port 204 ) 205{ 206 kdp_connect_req_t *rq = &pkt->connect_req; 207 size_t plen = *len; 208 kdp_connect_reply_t *rp = &pkt->connect_reply; 209 uint16_t rport, eport; 210 uint32_t key; 211 uint8_t seq; 212 213 if (plen < sizeof(*rq)) { 214 return FALSE; 215 } 216 217 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting)); 218 219 rport = rq->req_reply_port; 220 eport = rq->exc_note_port; 221 key = rq->hdr.key; 222 seq = rq->hdr.seq; 223 if (kdp.is_conn) { 224 if ((seq == kdp.conn_seq) && /* duplicate request */ 225 (rport == kdp.reply_port) && 226 (eport == kdp.exception_port) && 227 (key == kdp.session_key)) { 228 rp->error = KDPERR_NO_ERROR; 229 } else { 230 rp->error = KDPERR_ALREADY_CONNECTED; 231 } 232 } else { 233 kdp.reply_port = rport; 234 kdp.exception_port = eport; 235 kdp.is_conn = TRUE; 236 kdp.conn_seq = seq; 237 kdp.session_key = key; 238 239 rp->error = KDPERR_NO_ERROR; 240 } 241 242 rp->hdr.is_reply = 1; 243 rp->hdr.len = sizeof(*rp); 244 245 *reply_port = rport; 246 *len = rp->hdr.len; 247 248 if (current_debugger == KDP_CUR_DB) { 249 active_debugger = 1; 250 } 251 252 return TRUE; 253} 254 255static boolean_t 256kdp_disconnect( 257 kdp_pkt_t *pkt, 258 int *len, 259 unsigned short *reply_port 260 ) 261{ 262 kdp_disconnect_req_t *rq = &pkt->disconnect_req; 263 size_t plen = *len; 264 kdp_disconnect_reply_t *rp = &pkt->disconnect_reply; 265 266 if (plen < sizeof(*rq)) { 267 return FALSE; 268 } 269 270 if (!kdp.is_conn) { 271 return FALSE; 272 } 273 274 dprintf(("kdp_disconnect\n")); 275 276 *reply_port = kdp.reply_port; 277 278 kdp.reply_port = kdp.exception_port = 0; 279 kdp.is_halted = kdp.is_conn = FALSE; 280 kdp.exception_seq = kdp.conn_seq = 0; 281 kdp.session_key = 0; 282 283 if (debugger_panic_str != NULL) { 284 reattach_wait = 1; 285 } 286 287 if (noresume_on_disconnect == 1) { 288 reattach_wait = 1; 289 noresume_on_disconnect = 0; 290 } 291 292 rp->hdr.is_reply = 1; 293 rp->hdr.len = sizeof(*rp); 294 295 *len = rp->hdr.len; 296 297 if (current_debugger == KDP_CUR_DB) { 298 active_debugger = 0; 299 } 300 301 return TRUE; 302} 303 304static boolean_t 305kdp_reattach( 306 kdp_pkt_t *pkt, 307 int *len, 308 unsigned short *reply_port 309 ) 310{ 311 kdp_reattach_req_t *rq = &pkt->reattach_req; 312 313 kdp.is_conn = TRUE; 314 kdp_disconnect(pkt, len, reply_port); 315 *reply_port = rq->req_reply_port; 316 reattach_wait = 1; 317 return TRUE; 318} 319 320static boolean_t 321kdp_hostinfo( 322 kdp_pkt_t *pkt, 323 int *len, 324 unsigned short *reply_port 325 ) 326{ 327 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req; 328 size_t plen = *len; 329 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply; 330 331 if (plen < sizeof(*rq)) { 332 return FALSE; 333 } 334 335 dprintf(("kdp_hostinfo\n")); 336 337 rp->hdr.is_reply = 1; 338 rp->hdr.len = sizeof(*rp); 339 340 kdp_machine_hostinfo(&rp->hostinfo); 341 342 *reply_port = kdp.reply_port; 343 *len = rp->hdr.len; 344 345 return TRUE; 346} 347 348static boolean_t 349kdp_kernelversion( 350 kdp_pkt_t *pkt, 351 int *len, 352 unsigned short *reply_port 353 ) 354{ 355 kdp_kernelversion_req_t *rq = &pkt->kernelversion_req; 356 size_t plen = *len; 357 kdp_kernelversion_reply_t *rp = &pkt->kernelversion_reply; 358 size_t slen; 359 360 if (plen < sizeof(*rq)) { 361 return FALSE; 362 } 363 364 rp->hdr.is_reply = 1; 365 rp->hdr.len = sizeof(*rp); 366 367 dprintf(("kdp_kernelversion\n")); 368 slen = strlcpy(rp->version, kdp_kernelversion_string, MAX_KDP_DATA_SIZE); 369 370 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */ 371 372 *reply_port = kdp.reply_port; 373 *len = rp->hdr.len; 374 375 return TRUE; 376} 377 378static boolean_t 379kdp_suspend( 380 kdp_pkt_t *pkt, 381 int *len, 382 unsigned short *reply_port 383 ) 384{ 385 kdp_suspend_req_t *rq = &pkt->suspend_req; 386 size_t plen = *len; 387 kdp_suspend_reply_t *rp = &pkt->suspend_reply; 388 389 if (plen < sizeof(*rq)) { 390 return FALSE; 391 } 392 393 rp->hdr.is_reply = 1; 394 rp->hdr.len = sizeof(*rp); 395 396 dprintf(("kdp_suspend\n")); 397 398 kdp.is_halted = TRUE; 399 400 *reply_port = kdp.reply_port; 401 *len = rp->hdr.len; 402 403 return TRUE; 404} 405 406static boolean_t 407kdp_resumecpus( 408 kdp_pkt_t *pkt, 409 int *len, 410 unsigned short *reply_port 411 ) 412{ 413 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req; 414 size_t plen = *len; 415 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply; 416 417 if (plen < sizeof(*rq)) { 418 return FALSE; 419 } 420 421 rp->hdr.is_reply = 1; 422 rp->hdr.len = sizeof(*rp); 423 424 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask)); 425 426 kdp.is_halted = FALSE; 427 428 *reply_port = kdp.reply_port; 429 *len = rp->hdr.len; 430 431 return TRUE; 432} 433 434static boolean_t 435kdp_writemem( 436 kdp_pkt_t *pkt, 437 int *len, 438 unsigned short *reply_port 439 ) 440{ 441 kdp_writemem_req_t *rq = &pkt->writemem_req; 442 size_t plen = *len; 443 kdp_writemem_reply_t *rp = &pkt->writemem_reply; 444 mach_vm_size_t cnt; 445 446 if (plen < sizeof(*rq)) { 447 return FALSE; 448 } 449 450 if (rq->nbytes > MAX_KDP_DATA_SIZE) { 451 rp->error = KDPERR_BAD_NBYTES; 452 } else { 453 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes)); 454 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes); 455 rp->error = KDPERR_ACCESS(rq->nbytes, cnt); 456 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 457 } 458 459 rp->hdr.is_reply = 1; 460 rp->hdr.len = sizeof(*rp); 461 462 *reply_port = kdp.reply_port; 463 *len = rp->hdr.len; 464 465 return TRUE; 466} 467 468static boolean_t 469kdp_writemem64( 470 kdp_pkt_t *pkt, 471 int *len, 472 unsigned short *reply_port 473 ) 474{ 475 kdp_writemem64_req_t *rq = &pkt->writemem64_req; 476 size_t plen = *len; 477 kdp_writemem64_reply_t *rp = &pkt->writemem64_reply; 478 mach_vm_size_t cnt; 479 480 if (plen < sizeof(*rq)) { 481 return FALSE; 482 } 483 484 if (rq->nbytes > MAX_KDP_DATA_SIZE) { 485 rp->error = KDPERR_BAD_NBYTES; 486 } else { 487 dprintf(("kdp_writemem64 addr %llx size %d\n", rq->address, rq->nbytes)); 488 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, (mach_vm_size_t)rq->nbytes); 489 rp->error = KDPERR_ACCESS(rq->nbytes, cnt); 490 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 491 } 492 493 rp->hdr.is_reply = 1; 494 rp->hdr.len = sizeof(*rp); 495 496 *reply_port = kdp.reply_port; 497 *len = rp->hdr.len; 498 499 return TRUE; 500} 501 502static boolean_t 503kdp_writephysmem64( 504 kdp_pkt_t *pkt, 505 int *len, 506 unsigned short *reply_port 507 ) 508{ 509 kdp_writephysmem64_req_t *rq = &pkt->writephysmem64_req; 510 size_t plen = *len; 511 kdp_writephysmem64_reply_t *rp = &pkt->writephysmem64_reply; 512 mach_vm_size_t cnt; 513 unsigned int size; 514 515 if (plen < sizeof(*rq)) { 516 return FALSE; 517 } 518 519 size = rq->nbytes; 520 if (size > MAX_KDP_DATA_SIZE) { 521 rp->error = KDPERR_BAD_NBYTES; 522 } else { 523 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq->address, size)); 524 cnt = kdp_machine_phys_write(rq, rq->data, rq->lcpu); 525 rp->error = KDPERR_ACCESS(size, cnt); 526 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 527 } 528 529 rp->hdr.is_reply = 1; 530 rp->hdr.len = sizeof(*rp); 531 532 *reply_port = kdp.reply_port; 533 *len = rp->hdr.len; 534 535 return TRUE; 536} 537 538static boolean_t 539kdp_readmem( 540 kdp_pkt_t *pkt, 541 int *len, 542 unsigned short *reply_port 543 ) 544{ 545 kdp_readmem_req_t *rq = &pkt->readmem_req; 546 size_t plen = *len; 547 kdp_readmem_reply_t *rp = &pkt->readmem_reply; 548 mach_vm_size_t cnt; 549 unsigned int size; 550 551 if (plen < sizeof(*rq)) { 552 return FALSE; 553 } 554 555 rp->hdr.is_reply = 1; 556 rp->hdr.len = sizeof(*rp); 557 558 size = rq->nbytes; 559 if (size > MAX_KDP_DATA_SIZE) { 560 rp->error = KDPERR_BAD_NBYTES; 561 } else { 562 dprintf(("kdp_readmem addr %x size %d\n", rq->address, size)); 563 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes); 564 rp->error = KDPERR_ACCESS(size, cnt); 565 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 566 567 rp->hdr.len += cnt; 568 } 569 570 *reply_port = kdp.reply_port; 571 *len = rp->hdr.len; 572 573 return TRUE; 574} 575 576static boolean_t 577kdp_readmem64( 578 kdp_pkt_t *pkt, 579 int *len, 580 unsigned short *reply_port 581 ) 582{ 583 kdp_readmem64_req_t *rq = &pkt->readmem64_req; 584 size_t plen = *len; 585 kdp_readmem64_reply_t *rp = &pkt->readmem64_reply; 586 mach_vm_size_t cnt; 587 unsigned int size; 588 589 if (plen < sizeof(*rq)) { 590 return FALSE; 591 } 592 593 rp->hdr.is_reply = 1; 594 rp->hdr.len = sizeof(*rp); 595 596 size = rq->nbytes; 597 if (size > MAX_KDP_DATA_SIZE) { 598 rp->error = KDPERR_BAD_NBYTES; 599 } else { 600 dprintf(("kdp_readmem64 addr %llx size %d\n", rq->address, size)); 601 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes); 602 rp->error = KDPERR_ACCESS(size, cnt); 603 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 604 605 rp->hdr.len += cnt; 606 } 607 608 *reply_port = kdp.reply_port; 609 *len = rp->hdr.len; 610 611 return TRUE; 612} 613 614static boolean_t 615kdp_readphysmem64( 616 kdp_pkt_t *pkt, 617 int *len, 618 unsigned short *reply_port 619 ) 620{ 621 kdp_readphysmem64_req_t *rq = &pkt->readphysmem64_req; 622 size_t plen = *len; 623 kdp_readphysmem64_reply_t *rp = &pkt->readphysmem64_reply; 624 mach_vm_size_t cnt; 625 unsigned int size; 626 627 if (plen < sizeof(*rq)) { 628 return FALSE; 629 } 630 631 rp->hdr.is_reply = 1; 632 rp->hdr.len = sizeof(*rp); 633 634 size = rq->nbytes; 635 if (size > MAX_KDP_DATA_SIZE) { 636 rp->error = KDPERR_BAD_NBYTES; 637 } else { 638 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq->address, size)); 639 cnt = kdp_machine_phys_read(rq, rp->data, rq->lcpu); 640 rp->error = KDPERR_ACCESS(size, cnt); 641 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 642 643 rp->hdr.len += cnt; 644 } 645 646 *reply_port = kdp.reply_port; 647 *len = rp->hdr.len; 648 649 return TRUE; 650} 651 652static boolean_t 653kdp_maxbytes( 654 kdp_pkt_t *pkt, 655 int *len, 656 unsigned short *reply_port 657 ) 658{ 659 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req; 660 size_t plen = *len; 661 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply; 662 663 if (plen < sizeof(*rq)) { 664 return FALSE; 665 } 666 667 rp->hdr.is_reply = 1; 668 rp->hdr.len = sizeof(*rp); 669 670 dprintf(("kdp_maxbytes\n")); 671 672 rp->max_bytes = MAX_KDP_DATA_SIZE; 673 674 *reply_port = kdp.reply_port; 675 *len = rp->hdr.len; 676 677 return TRUE; 678} 679 680static boolean_t 681kdp_version( 682 kdp_pkt_t *pkt, 683 int *len, 684 unsigned short *reply_port 685 ) 686{ 687 kdp_version_req_t *rq = &pkt->version_req; 688 size_t plen = *len; 689 kdp_version_reply_t *rp = &pkt->version_reply; 690 691 if (plen < sizeof(*rq)) { 692 return FALSE; 693 } 694 695 rp->hdr.is_reply = 1; 696 rp->hdr.len = sizeof(*rp); 697 698 dprintf(("kdp_version\n")); 699 700 rp->version = KDP_VERSION; 701 if (!(kdp_flag & KDP_BP_DIS)) { 702 rp->feature = KDP_FEATURE_BP; 703 } else { 704 rp->feature = 0; 705 } 706 707 *reply_port = kdp.reply_port; 708 *len = rp->hdr.len; 709 710 return TRUE; 711} 712 713static boolean_t 714kdp_regions( 715 kdp_pkt_t *pkt, 716 int *len, 717 unsigned short *reply_port 718 ) 719{ 720 kdp_regions_req_t *rq = &pkt->regions_req; 721 size_t plen = *len; 722 kdp_regions_reply_t *rp = &pkt->regions_reply; 723 kdp_region_t *r; 724 725 if (plen < sizeof(*rq)) { 726 return FALSE; 727 } 728 729 rp->hdr.is_reply = 1; 730 rp->hdr.len = sizeof(*rp); 731 732 dprintf(("kdp_regions\n")); 733 734 r = rp->regions; 735 rp->nregions = 0; 736 737 r->address = 0; 738 r->nbytes = 0xffffffff; 739 740 r->protection = VM_PROT_ALL; r++; rp->nregions++; 741 742 rp->hdr.len += rp->nregions * sizeof(kdp_region_t); 743 744 *reply_port = kdp.reply_port; 745 *len = rp->hdr.len; 746 747 return TRUE; 748} 749 750static boolean_t 751kdp_writeregs( 752 kdp_pkt_t *pkt, 753 int *len, 754 unsigned short *reply_port 755 ) 756{ 757 kdp_writeregs_req_t *rq = &pkt->writeregs_req; 758 size_t plen = *len; 759 int size; 760 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply; 761 762 if (plen < sizeof(*rq)) { 763 return FALSE; 764 } 765 766 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int); 767 rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size); 768 769 rp->hdr.is_reply = 1; 770 rp->hdr.len = sizeof(*rp); 771 772 *reply_port = kdp.reply_port; 773 *len = rp->hdr.len; 774 775 return TRUE; 776} 777 778static boolean_t 779kdp_readregs( 780 kdp_pkt_t *pkt, 781 int *len, 782 unsigned short *reply_port 783 ) 784{ 785 kdp_readregs_req_t *rq = &pkt->readregs_req; 786 size_t plen = *len; 787 kdp_readregs_reply_t *rp = &pkt->readregs_reply; 788 int size; 789 790 if (plen < sizeof(*rq)) { 791 return FALSE; 792 } 793 794 rp->hdr.is_reply = 1; 795 rp->hdr.len = sizeof(*rp); 796 797 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size); 798 rp->hdr.len += size; 799 800 *reply_port = kdp.reply_port; 801 *len = rp->hdr.len; 802 803 return TRUE; 804} 805 806 807boolean_t 808kdp_breakpoint_set( 809 kdp_pkt_t *pkt, 810 int *len, 811 unsigned short *reply_port 812 ) 813{ 814 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req; 815 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply; 816 size_t plen = *len; 817 kdp_error_t kerr; 818 819 if (plen < sizeof(*rq)) { 820 return FALSE; 821 } 822 823 dprintf(("kdp_breakpoint_set %x\n", rq->address)); 824 825 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address); 826 827 rp->error = kerr; 828 829 rp->hdr.is_reply = 1; 830 rp->hdr.len = sizeof(*rp); 831 *reply_port = kdp.reply_port; 832 *len = rp->hdr.len; 833 834 return TRUE; 835} 836 837boolean_t 838kdp_breakpoint64_set( 839 kdp_pkt_t *pkt, 840 int *len, 841 unsigned short *reply_port 842 ) 843{ 844 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req; 845 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply; 846 size_t plen = *len; 847 kdp_error_t kerr; 848 849 if (plen < sizeof(*rq)) { 850 return FALSE; 851 } 852 853 dprintf(("kdp_breakpoint64_set %llx\n", rq->address)); 854 855 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address); 856 857 rp->error = kerr; 858 859 rp->hdr.is_reply = 1; 860 rp->hdr.len = sizeof(*rp); 861 *reply_port = kdp.reply_port; 862 *len = rp->hdr.len; 863 864 return TRUE; 865} 866 867boolean_t 868kdp_breakpoint_remove( 869 kdp_pkt_t *pkt, 870 int *len, 871 unsigned short *reply_port 872 ) 873{ 874 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req; 875 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply; 876 size_t plen = *len; 877 kdp_error_t kerr; 878 if (plen < sizeof(*rq)) { 879 return FALSE; 880 } 881 882 dprintf(("kdp_breakpoint_remove %x\n", rq->address)); 883 884 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address); 885 886 rp->error = kerr; 887 888 rp->hdr.is_reply = 1; 889 rp->hdr.len = sizeof(*rp); 890 *reply_port = kdp.reply_port; 891 *len = rp->hdr.len; 892 893 return TRUE; 894} 895 896boolean_t 897kdp_breakpoint64_remove( 898 kdp_pkt_t *pkt, 899 int *len, 900 unsigned short *reply_port 901 ) 902{ 903 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req; 904 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply; 905 size_t plen = *len; 906 kdp_error_t kerr; 907 908 if (plen < sizeof(*rq)) { 909 return FALSE; 910 } 911 912 dprintf(("kdp_breakpoint64_remove %llx\n", rq->address)); 913 914 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address); 915 916 rp->error = kerr; 917 918 rp->hdr.is_reply = 1; 919 rp->hdr.len = sizeof(*rp); 920 *reply_port = kdp.reply_port; 921 *len = rp->hdr.len; 922 923 return TRUE; 924} 925 926 927kdp_error_t 928kdp_set_breakpoint_internal( 929 mach_vm_address_t address 930 ) 931{ 932 uint8_t breakinstr[MAX_BREAKINSN_BYTES], oldinstr[MAX_BREAKINSN_BYTES]; 933 uint32_t breakinstrsize = sizeof(breakinstr); 934 mach_vm_size_t cnt; 935 int i; 936 937 kdp_machine_get_breakinsn(breakinstr, &breakinstrsize); 938 939 if (breakpoints_initialized == 0) { 940 for (i = 0; (i < MAX_BREAKPOINTS); breakpoint_list[i].address = 0, i++) { 941 ; 942 } 943 breakpoints_initialized++; 944 } 945 946 cnt = kdp_machine_vm_read(address, (caddr_t)&oldinstr, (mach_vm_size_t)breakinstrsize); 947 948 if (0 == memcmp(oldinstr, breakinstr, breakinstrsize)) { 949 printf("A trap was already set at that address, not setting new breakpoint\n"); 950 951 return KDPERR_BREAKPOINT_ALREADY_SET; 952 } 953 954 for (i = 0; (i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++) { 955 ; 956 } 957 958 if (i == MAX_BREAKPOINTS) { 959 return KDPERR_MAX_BREAKPOINTS; 960 } 961 962 breakpoint_list[i].address = address; 963 memcpy(breakpoint_list[i].oldbytes, oldinstr, breakinstrsize); 964 breakpoint_list[i].bytesused = breakinstrsize; 965 966 cnt = kdp_machine_vm_write((caddr_t)&breakinstr, address, breakinstrsize); 967 968 return KDPERR_NO_ERROR; 969} 970 971kdp_error_t 972kdp_remove_breakpoint_internal( 973 mach_vm_address_t address 974 ) 975{ 976 mach_vm_size_t cnt; 977 int i; 978 979 for (i = 0; (i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != address); i++) { 980 ; 981 } 982 983 if (i == MAX_BREAKPOINTS) { 984 return KDPERR_BREAKPOINT_NOT_FOUND; 985 } 986 987 breakpoint_list[i].address = 0; 988 cnt = kdp_machine_vm_write((caddr_t)&breakpoint_list[i].oldbytes, address, breakpoint_list[i].bytesused); 989 990 return KDPERR_NO_ERROR; 991} 992 993boolean_t 994kdp_remove_all_breakpoints(void) 995{ 996 int i; 997 boolean_t breakpoint_found = FALSE; 998 999 if (breakpoints_initialized) { 1000 for (i = 0; i < MAX_BREAKPOINTS; i++) { 1001 if (breakpoint_list[i].address) { 1002 kdp_machine_vm_write((caddr_t)&(breakpoint_list[i].oldbytes), (mach_vm_address_t)breakpoint_list[i].address, (mach_vm_size_t)breakpoint_list[i].bytesused); 1003 breakpoint_found = TRUE; 1004 breakpoint_list[i].address = 0; 1005 } 1006 } 1007 1008 if (breakpoint_found) { 1009 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n"); 1010 } 1011 } 1012 return breakpoint_found; 1013} 1014 1015boolean_t 1016kdp_reboot( 1017 __unused kdp_pkt_t *pkt, 1018 __unused int *len, 1019 __unused unsigned short *reply_port 1020 ) 1021{ 1022 dprintf(("kdp_reboot\n")); 1023 1024 kdp_machine_reboot(); 1025 1026 return TRUE; // no, not really, we won't return 1027} 1028 1029static boolean_t 1030kdp_readioport( 1031 kdp_pkt_t *pkt, 1032 int *len, 1033 unsigned short *reply_port 1034 ) 1035{ 1036 kdp_readioport_req_t *rq = &pkt->readioport_req; 1037 kdp_readioport_reply_t *rp = &pkt->readioport_reply; 1038 size_t plen = *len; 1039 1040 if (plen < sizeof(*rq)) { 1041 return FALSE; 1042 } 1043 1044 rp->hdr.is_reply = 1; 1045 rp->hdr.len = sizeof(*rp); 1046 1047 if (rq->nbytes > MAX_KDP_DATA_SIZE) { 1048 rp->error = KDPERR_BAD_NBYTES; 1049 } else { 1050#if KDP_TEST_HARNESS 1051 uint16_t addr = rq->address; 1052#endif 1053 uint16_t size = rq->nbytes; 1054 dprintf(("kdp_readioport addr %x size %d\n", addr, size)); 1055 1056 rp->error = kdp_machine_ioport_read(rq, rp->data, rq->lcpu); 1057 if (rp->error == KDPERR_NO_ERROR) { 1058 rp->hdr.len += size; 1059 } 1060 } 1061 1062 *reply_port = kdp.reply_port; 1063 *len = rp->hdr.len; 1064 1065 return TRUE; 1066} 1067 1068static boolean_t 1069kdp_writeioport( 1070 kdp_pkt_t *pkt, 1071 int *len, 1072 unsigned short *reply_port 1073 ) 1074{ 1075 kdp_writeioport_req_t *rq = &pkt->writeioport_req; 1076 kdp_writeioport_reply_t *rp = &pkt->writeioport_reply; 1077 size_t plen = *len; 1078 1079 if (plen < sizeof(*rq)) { 1080 return FALSE; 1081 } 1082 1083 if (rq->nbytes > MAX_KDP_DATA_SIZE) { 1084 rp->error = KDPERR_BAD_NBYTES; 1085 } else { 1086 dprintf(("kdp_writeioport addr %x size %d\n", rq->address, 1087 rq->nbytes)); 1088 1089 rp->error = kdp_machine_ioport_write(rq, rq->data, rq->lcpu); 1090 } 1091 1092 rp->hdr.is_reply = 1; 1093 rp->hdr.len = sizeof(*rp); 1094 1095 *reply_port = kdp.reply_port; 1096 *len = rp->hdr.len; 1097 1098 return TRUE; 1099} 1100 1101static boolean_t 1102kdp_readmsr64( 1103 kdp_pkt_t *pkt, 1104 int *len, 1105 unsigned short *reply_port 1106 ) 1107{ 1108 kdp_readmsr64_req_t *rq = &pkt->readmsr64_req; 1109 kdp_readmsr64_reply_t *rp = &pkt->readmsr64_reply; 1110 size_t plen = *len; 1111 1112 if (plen < sizeof(*rq)) { 1113 return FALSE; 1114 } 1115 1116 rp->hdr.is_reply = 1; 1117 rp->hdr.len = sizeof(*rp); 1118 1119 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq->lcpu, rq->address)); 1120 rp->error = kdp_machine_msr64_read(rq, rp->data, rq->lcpu); 1121 if (rp->error == KDPERR_NO_ERROR) { 1122 rp->hdr.len += sizeof(uint64_t); 1123 } 1124 1125 *reply_port = kdp.reply_port; 1126 *len = rp->hdr.len; 1127 1128 return TRUE; 1129} 1130 1131static boolean_t 1132kdp_writemsr64( 1133 kdp_pkt_t *pkt, 1134 int *len, 1135 unsigned short *reply_port 1136 ) 1137{ 1138 kdp_writemsr64_req_t *rq = &pkt->writemsr64_req; 1139 kdp_writemsr64_reply_t *rp = &pkt->writemsr64_reply; 1140 size_t plen = *len; 1141 1142 if (plen < sizeof(*rq)) { 1143 return FALSE; 1144 } 1145 1146 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq->lcpu, rq->address)); 1147 rp->error = kdp_machine_msr64_write(rq, rq->data, rq->lcpu); 1148 1149 rp->hdr.is_reply = 1; 1150 rp->hdr.len = sizeof(*rp); 1151 1152 *reply_port = kdp.reply_port; 1153 *len = rp->hdr.len; 1154 1155 return TRUE; 1156} 1157 1158static boolean_t 1159kdp_dumpinfo( 1160 kdp_pkt_t *pkt, 1161 int *len, 1162 unsigned short *reply_port 1163 ) 1164{ 1165 kdp_dumpinfo_req_t *rq = &pkt->dumpinfo_req; 1166 kdp_dumpinfo_reply_t *rp = &pkt->dumpinfo_reply; 1167 size_t plen = *len; 1168 1169 if (plen < sizeof(*rq)) { 1170 return FALSE; 1171 } 1172 1173 dprintf(("kdp_dumpinfo file=%s destip=%s routerip=%s\n", rq->name, rq->destip, rq->routerip)); 1174 rp->hdr.is_reply = 1; 1175 rp->hdr.len = sizeof(*rp); 1176 1177 if ((rq->type & KDP_DUMPINFO_MASK) != KDP_DUMPINFO_GETINFO) { 1178 kdp_set_dump_info(rq->type, rq->name, rq->destip, rq->routerip, 1179 rq->port); 1180 } 1181 1182 /* gather some stats for reply */ 1183 kdp_get_dump_info(rp); 1184 1185 *reply_port = kdp.reply_port; 1186 *len = rp->hdr.len; 1187 1188 return TRUE; 1189}