2 * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/mach_types.h>
30 #include <sys/appleapiopts.h>
31 #include <kern/debug.h>
32 #include <uuid/uuid.h>
34 #include <kdp/kdp_internal.h>
35 #include <kdp/kdp_private.h>
36 #include <kdp/kdp_core.h>
37 #include <kdp/kdp_dyld.h>
39 #include <libsa/types.h>
41 #include <string.h> /* bcopy */
43 #include <kern/processor.h>
44 #include <kern/thread.h>
45 #include <vm/vm_map.h>
46 #include <vm/vm_kern.h>
48 #define DO_ALIGN 1 /* align all packet data accesses */
50 #define KDP_TEST_HARNESS 0
52 #define dprintf(x) kprintf x
58 dispatch_table
[KDP_INVALID_REQUEST
-KDP_CONNECT
] =
61 /* 1 */ kdp_disconnect
,
68 /* 8 */ kdp_writeregs
,
72 /* C */ kdp_resumecpus
,
75 /* F */ kdp_breakpoint_set
,
76 /*10 */ kdp_breakpoint_remove
,
80 /*14 */ kdp_readmem64
,
81 /*15 */ kdp_writemem64
,
82 /*16 */ kdp_breakpoint64_set
,
83 /*17 */ kdp_breakpoint64_remove
,
84 /*18 */ kdp_kernelversion
,
85 /*19 */ kdp_readphysmem64
,
86 /*1A */ kdp_writephysmem64
,
87 /*1B */ kdp_readioport
,
88 /*1C */ kdp_writeioport
,
89 /*1D */ kdp_readmsr64
,
90 /*1E */ kdp_writemsr64
,
96 #define MAX_BREAKPOINTS 100
99 * Version 11 of the KDP Protocol adds support for 64-bit wide memory
100 * addresses (read/write and breakpoints) as well as a dedicated
101 * kernelversion request. Version 12 adds read/writing of physical
102 * memory with 64-bit wide memory addresses.
104 #define KDP_VERSION 12
107 mach_vm_address_t address
;
109 uint8_t oldbytes
[MAX_BREAKINSN_BYTES
];
110 } kdp_breakpoint_record_t
;
112 static kdp_breakpoint_record_t breakpoint_list
[MAX_BREAKPOINTS
];
113 static unsigned int breakpoints_initialized
= 0;
115 int reattach_wait
= 0;
116 int noresume_on_disconnect
= 0;
117 extern unsigned int return_on_panic
;
119 typedef struct thread_snapshot
*thread_snapshot_t
;
120 typedef struct task_snapshot
*task_snapshot_t
;
123 machine_trace_thread(thread_t thread
, char *tracepos
, char *tracebound
, int nframes
, boolean_t user_p
);
125 machine_trace_thread64(thread_t thread
, char *tracepos
, char *tracebound
, int nframes
, boolean_t user_p
);
129 proc_name_kdp(task_t task
, char *buf
, int size
);
132 kdp_snapshot_postflight(void);
135 pid_from_task(task_t task
);
138 kdp_set_breakpoint_internal(
139 mach_vm_address_t address
143 kdp_remove_breakpoint_internal(
144 mach_vm_address_t address
149 kdp_stackshot(int pid
, void *tracebuf
, uint32_t tracebuf_size
, uint32_t trace_flags
, uint32_t dispatch_offset
, uint32_t *pbytesTraced
);
151 boolean_t
kdp_copyin(pmap_t
, uint64_t, void *, size_t);
152 extern void bcopy_phys(addr64_t
, addr64_t
, vm_size_t
);
154 extern char version
[];
160 unsigned short *reply_port
163 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
164 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
170 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
172 rd
= (kdp_pkt_t
*)pkt
;
174 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
175 printf("kdp_packet bad len pkt %lu hdr %d\n", plen
, rd
->hdr
.len
);
180 if (rd
->hdr
.is_reply
) {
181 printf("kdp_packet reply recvd req %x seq %x\n",
182 rd
->hdr
.request
, rd
->hdr
.seq
);
187 req
= rd
->hdr
.request
;
188 if (req
>= KDP_INVALID_REQUEST
) {
189 printf("kdp_packet bad request %x len %d seq %x key %x\n",
190 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
195 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
197 bcopy((char *)rd
, (char *) pkt
, *len
);
206 __unused
unsigned short *reply_port
209 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
211 printf("kdp_unknown request %x len %d seq %x key %x\n",
212 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
221 unsigned short *reply_port
224 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
226 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
227 uint16_t rport
, eport
;
231 if (plen
< sizeof (*rq
))
234 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
236 rport
= rq
->req_reply_port
;
237 eport
= rq
->exc_note_port
;
241 if ((seq
== kdp
.conn_seq
) && /* duplicate request */
242 (rport
== kdp
.reply_port
) &&
243 (eport
== kdp
.exception_port
) &&
244 (key
== kdp
.session_key
))
245 rp
->error
= KDPERR_NO_ERROR
;
247 rp
->error
= KDPERR_ALREADY_CONNECTED
;
250 kdp
.reply_port
= rport
;
251 kdp
.exception_port
= eport
;
254 kdp
.session_key
= key
;
256 rp
->error
= KDPERR_NO_ERROR
;
259 rp
->hdr
.is_reply
= 1;
260 rp
->hdr
.len
= sizeof (*rp
);
265 if (current_debugger
== KDP_CUR_DB
)
275 unsigned short *reply_port
278 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
280 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
282 if (plen
< sizeof (*rq
))
288 dprintf(("kdp_disconnect\n"));
290 *reply_port
= kdp
.reply_port
;
292 kdp
.reply_port
= kdp
.exception_port
= 0;
293 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
294 kdp
.exception_seq
= kdp
.conn_seq
= 0;
297 if ((panicstr
!= NULL
) && (return_on_panic
== 0))
300 if (noresume_on_disconnect
== 1) {
302 noresume_on_disconnect
= 0;
305 rp
->hdr
.is_reply
= 1;
306 rp
->hdr
.len
= sizeof (*rp
);
310 if (current_debugger
== KDP_CUR_DB
)
320 unsigned short *reply_port
323 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
326 kdp_disconnect(pkt
, len
, reply_port
);
327 *reply_port
= rq
->req_reply_port
;
336 unsigned short *reply_port
339 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
341 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
343 if (plen
< sizeof (*rq
))
346 dprintf(("kdp_hostinfo\n"));
348 rp
->hdr
.is_reply
= 1;
349 rp
->hdr
.len
= sizeof (*rp
);
351 kdp_machine_hostinfo(&rp
->hostinfo
);
353 *reply_port
= kdp
.reply_port
;
363 unsigned short *reply_port
366 kdp_kernelversion_req_t
*rq
= &pkt
->kernelversion_req
;
368 kdp_kernelversion_reply_t
*rp
= &pkt
->kernelversion_reply
;
371 if (plen
< sizeof (*rq
))
374 rp
->hdr
.is_reply
= 1;
375 rp
->hdr
.len
= sizeof (*rp
);
377 dprintf(("kdp_kernelversion\n"));
378 slen
= strlcpy(rp
->version
, version
, MAX_KDP_DATA_SIZE
);
380 rp
->hdr
.len
+= slen
+ 1; /* strlcpy returns the amount copied with NUL */
382 *reply_port
= kdp
.reply_port
;
392 unsigned short *reply_port
395 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
397 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
399 if (plen
< sizeof (*rq
))
402 rp
->hdr
.is_reply
= 1;
403 rp
->hdr
.len
= sizeof (*rp
);
405 dprintf(("kdp_suspend\n"));
407 kdp
.is_halted
= TRUE
;
409 *reply_port
= kdp
.reply_port
;
419 unsigned short *reply_port
422 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
424 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
426 if (plen
< sizeof (*rq
))
429 rp
->hdr
.is_reply
= 1;
430 rp
->hdr
.len
= sizeof (*rp
);
432 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
434 kdp
.is_halted
= FALSE
;
436 *reply_port
= kdp
.reply_port
;
446 unsigned short *reply_port
449 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
451 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
454 if (plen
< sizeof (*rq
))
457 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
458 rp
->error
= KDPERR_BAD_NBYTES
;
460 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
462 cnt
= kdp_machine_vm_write((caddr_t
)rq
->data
, (mach_vm_address_t
)rq
->address
, rq
->nbytes
);
463 rp
->error
= KDPERR_NO_ERROR
;
466 rp
->hdr
.is_reply
= 1;
467 rp
->hdr
.len
= sizeof (*rp
);
469 *reply_port
= kdp
.reply_port
;
479 unsigned short *reply_port
482 kdp_writemem64_req_t
*rq
= &pkt
->writemem64_req
;
484 kdp_writemem64_reply_t
*rp
= &pkt
->writemem64_reply
;
487 if (plen
< sizeof (*rq
))
490 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
491 rp
->error
= KDPERR_BAD_NBYTES
;
493 dprintf(("kdp_writemem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
495 cnt
= kdp_machine_vm_write((caddr_t
)rq
->data
, (mach_vm_address_t
)rq
->address
, (mach_vm_size_t
)rq
->nbytes
);
496 rp
->error
= KDPERR_NO_ERROR
;
499 rp
->hdr
.is_reply
= 1;
500 rp
->hdr
.len
= sizeof (*rp
);
502 *reply_port
= kdp
.reply_port
;
512 unsigned short *reply_port
515 kdp_writephysmem64_req_t
*rq
= &pkt
->writephysmem64_req
;
517 kdp_writephysmem64_reply_t
*rp
= &pkt
->writephysmem64_reply
;
519 if (plen
< sizeof (*rq
))
522 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
523 rp
->error
= KDPERR_BAD_NBYTES
;
525 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
526 kdp_machine_phys_write(rq
, rq
->data
, rq
->lcpu
);
527 rp
->error
= KDPERR_NO_ERROR
;
530 rp
->hdr
.is_reply
= 1;
531 rp
->hdr
.len
= sizeof (*rp
);
533 *reply_port
= kdp
.reply_port
;
543 unsigned short *reply_port
546 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
548 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
550 #if __i386__ || __arm__
551 void *pversion
= &version
;
554 if (plen
< sizeof (*rq
))
557 rp
->hdr
.is_reply
= 1;
558 rp
->hdr
.len
= sizeof (*rp
);
560 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
561 rp
->error
= KDPERR_BAD_NBYTES
;
563 unsigned int n
= rq
->nbytes
;
565 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, n
));
566 #if __i386__ || __arm__
567 /* XXX This is a hack to facilitate the "showversion" macro
568 * on i386/ARM, which is used to obtain the kernel version without
569 * symbols - a pointer to the version string should eventually
570 * be pinned at a fixed address when an equivalent of the
571 * VECTORS segment (loaded at a fixed load address, and contains
572 * a table) is implemented on these architectures, as with PPC.
573 * N.B.: x86 now has a low global page, and the version indirection
574 * is pinned at 0x201C. We retain the 0x501C address override
575 * for compatibility. Future architectures should instead use
576 * the KDP_KERNELVERSION request.
578 if (rq
->address
== 0x501C)
579 rq
->address
= (uintptr_t)&pversion
;
581 cnt
= kdp_machine_vm_read((mach_vm_address_t
)rq
->address
, (caddr_t
)rp
->data
, n
);
582 rp
->error
= KDPERR_NO_ERROR
;
587 *reply_port
= kdp
.reply_port
;
597 unsigned short *reply_port
600 kdp_readmem64_req_t
*rq
= &pkt
->readmem64_req
;
602 kdp_readmem64_reply_t
*rp
= &pkt
->readmem64_reply
;
605 if (plen
< sizeof (*rq
))
608 rp
->hdr
.is_reply
= 1;
609 rp
->hdr
.len
= sizeof (*rp
);
611 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
612 rp
->error
= KDPERR_BAD_NBYTES
;
615 dprintf(("kdp_readmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
617 cnt
= kdp_machine_vm_read((mach_vm_address_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
618 rp
->error
= KDPERR_NO_ERROR
;
623 *reply_port
= kdp
.reply_port
;
633 unsigned short *reply_port
636 kdp_readphysmem64_req_t
*rq
= &pkt
->readphysmem64_req
;
638 kdp_readphysmem64_reply_t
*rp
= &pkt
->readphysmem64_reply
;
641 if (plen
< sizeof (*rq
))
644 rp
->hdr
.is_reply
= 1;
645 rp
->hdr
.len
= sizeof (*rp
);
647 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
648 rp
->error
= KDPERR_BAD_NBYTES
;
651 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq
->address
, rq
->nbytes
));
653 cnt
= (int)kdp_machine_phys_read(rq
, rp
->data
, rq
->lcpu
);
654 rp
->error
= KDPERR_NO_ERROR
;
659 *reply_port
= kdp
.reply_port
;
669 unsigned short *reply_port
672 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
674 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
676 if (plen
< sizeof (*rq
))
679 rp
->hdr
.is_reply
= 1;
680 rp
->hdr
.len
= sizeof (*rp
);
682 dprintf(("kdp_maxbytes\n"));
684 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
686 *reply_port
= kdp
.reply_port
;
696 unsigned short *reply_port
699 kdp_version_req_t
*rq
= &pkt
->version_req
;
701 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
703 if (plen
< sizeof (*rq
))
706 rp
->hdr
.is_reply
= 1;
707 rp
->hdr
.len
= sizeof (*rp
);
709 dprintf(("kdp_version\n"));
711 rp
->version
= KDP_VERSION
;
712 if (!(kdp_flag
& KDP_BP_DIS
))
713 rp
->feature
= KDP_FEATURE_BP
;
717 *reply_port
= kdp
.reply_port
;
727 unsigned short *reply_port
730 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
732 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
735 if (plen
< sizeof (*rq
))
738 rp
->hdr
.is_reply
= 1;
739 rp
->hdr
.len
= sizeof (*rp
);
741 dprintf(("kdp_regions\n"));
747 r
->nbytes
= 0xffffffff;
749 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
751 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
753 *reply_port
= kdp
.reply_port
;
763 unsigned short *reply_port
766 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
769 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
771 if (plen
< sizeof (*rq
))
774 size
= rq
->hdr
.len
- (unsigned)sizeof(kdp_hdr_t
) - (unsigned)sizeof(unsigned int);
775 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
777 rp
->hdr
.is_reply
= 1;
778 rp
->hdr
.len
= sizeof (*rp
);
780 *reply_port
= kdp
.reply_port
;
790 unsigned short *reply_port
793 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
795 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
798 if (plen
< sizeof (*rq
))
801 rp
->hdr
.is_reply
= 1;
802 rp
->hdr
.len
= sizeof (*rp
);
804 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
807 *reply_port
= kdp
.reply_port
;
818 unsigned short *reply_port
821 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
822 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
826 if (plen
< sizeof (*rq
))
829 dprintf(("kdp_breakpoint_set %x\n", rq
->address
));
831 kerr
= kdp_set_breakpoint_internal((mach_vm_address_t
)rq
->address
);
835 rp
->hdr
.is_reply
= 1;
836 rp
->hdr
.len
= sizeof (*rp
);
837 *reply_port
= kdp
.reply_port
;
844 kdp_breakpoint64_set(
847 unsigned short *reply_port
850 kdp_breakpoint64_req_t
*rq
= &pkt
->breakpoint64_req
;
851 kdp_breakpoint64_reply_t
*rp
= &pkt
->breakpoint64_reply
;
855 if (plen
< sizeof (*rq
))
858 dprintf(("kdp_breakpoint64_set %llx\n", rq
->address
));
860 kerr
= kdp_set_breakpoint_internal((mach_vm_address_t
)rq
->address
);
864 rp
->hdr
.is_reply
= 1;
865 rp
->hdr
.len
= sizeof (*rp
);
866 *reply_port
= kdp
.reply_port
;
873 kdp_breakpoint_remove(
876 unsigned short *reply_port
879 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
880 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
883 if (plen
< sizeof (*rq
))
886 dprintf(("kdp_breakpoint_remove %x\n", rq
->address
));
888 kerr
= kdp_remove_breakpoint_internal((mach_vm_address_t
)rq
->address
);
892 rp
->hdr
.is_reply
= 1;
893 rp
->hdr
.len
= sizeof (*rp
);
894 *reply_port
= kdp
.reply_port
;
901 kdp_breakpoint64_remove(
904 unsigned short *reply_port
907 kdp_breakpoint64_req_t
*rq
= &pkt
->breakpoint64_req
;
908 kdp_breakpoint64_reply_t
*rp
= &pkt
->breakpoint64_reply
;
912 if (plen
< sizeof (*rq
))
915 dprintf(("kdp_breakpoint64_remove %llx\n", rq
->address
));
917 kerr
= kdp_remove_breakpoint_internal((mach_vm_address_t
)rq
->address
);
921 rp
->hdr
.is_reply
= 1;
922 rp
->hdr
.len
= sizeof (*rp
);
923 *reply_port
= kdp
.reply_port
;
931 kdp_set_breakpoint_internal(
932 mach_vm_address_t address
936 uint8_t breakinstr
[MAX_BREAKINSN_BYTES
], oldinstr
[MAX_BREAKINSN_BYTES
];
937 uint32_t breakinstrsize
= sizeof(breakinstr
);
941 kdp_machine_get_breakinsn(breakinstr
, &breakinstrsize
);
943 if(breakpoints_initialized
== 0)
945 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
946 breakpoints_initialized
++;
949 cnt
= kdp_machine_vm_read(address
, (caddr_t
)&oldinstr
, (mach_vm_size_t
)breakinstrsize
);
951 if (0 == memcmp(oldinstr
, breakinstr
, breakinstrsize
)) {
952 printf("A trap was already set at that address, not setting new breakpoint\n");
954 return KDPERR_BREAKPOINT_ALREADY_SET
;
957 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
959 if (i
== MAX_BREAKPOINTS
) {
960 return KDPERR_MAX_BREAKPOINTS
;
963 breakpoint_list
[i
].address
= address
;
964 memcpy(breakpoint_list
[i
].oldbytes
, oldinstr
, breakinstrsize
);
965 breakpoint_list
[i
].bytesused
= breakinstrsize
;
967 cnt
= kdp_machine_vm_write((caddr_t
)&breakinstr
, address
, breakinstrsize
);
969 return KDPERR_NO_ERROR
;
973 kdp_remove_breakpoint_internal(
974 mach_vm_address_t address
980 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= address
); i
++);
982 if (i
== MAX_BREAKPOINTS
)
984 return KDPERR_BREAKPOINT_NOT_FOUND
;
987 breakpoint_list
[i
].address
= 0;
988 cnt
= kdp_machine_vm_write((caddr_t
)&breakpoint_list
[i
].oldbytes
, address
, breakpoint_list
[i
].bytesused
);
990 return KDPERR_NO_ERROR
;
994 kdp_remove_all_breakpoints(void)
997 boolean_t breakpoint_found
= FALSE
;
999 if (breakpoints_initialized
)
1001 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
1003 if (breakpoint_list
[i
].address
)
1005 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
);
1006 breakpoint_found
= TRUE
;
1007 breakpoint_list
[i
].address
= 0;
1011 if (breakpoint_found
)
1012 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
1014 return breakpoint_found
;
1019 __unused kdp_pkt_t
*pkt
,
1021 __unused
unsigned short *reply_port
1024 dprintf(("kdp_reboot\n"));
1026 kdp_machine_reboot();
1028 return (TRUE
); // no, not really, we won't return
1031 #define MAX_FRAMES 1000
1033 static int pid_from_task(task_t task
)
1038 pid
= proc_pid(task
->bsd_info
);
1044 kdp_copyin(pmap_t p
, uint64_t uaddr
, void *dest
, size_t size
) {
1046 char *kvaddr
= dest
;
1049 ppnum_t upn
= pmap_find_phys(p
, uaddr
);
1050 uint64_t phys_src
= (upn
<< PAGE_SHIFT
) | (uaddr
& PAGE_MASK
);
1051 uint64_t phys_dest
= kvtophys((vm_offset_t
)kvaddr
);
1052 uint64_t src_rem
= PAGE_SIZE
- (phys_src
& PAGE_MASK
);
1053 uint64_t dst_rem
= PAGE_SIZE
- (phys_dest
& PAGE_MASK
);
1054 size_t cur_size
= (uint32_t) MIN(src_rem
, dst_rem
);
1055 cur_size
= MIN(cur_size
, rem
);
1057 if (upn
&& pmap_valid_page(upn
) && phys_dest
) {
1058 bcopy_phys(phys_src
, phys_dest
, cur_size
);
1070 kdp_stackshot(int pid
, void *tracebuf
, uint32_t tracebuf_size
, uint32_t trace_flags
, uint32_t dispatch_offset
, uint32_t *pbytesTraced
)
1072 char *tracepos
= (char *) tracebuf
;
1073 char *tracebound
= tracepos
+ tracebuf_size
;
1074 uint32_t tracebytes
= 0;
1077 task_t task
= TASK_NULL
;
1078 thread_t thread
= THREAD_NULL
;
1079 thread_snapshot_t tsnap
= NULL
;
1080 unsigned framesize
= 2 * sizeof(vm_offset_t
);
1082 struct thread cthread
;
1084 boolean_t dispatch_p
= ((trace_flags
& STACKSHOT_GET_DQ
) != 0);
1085 boolean_t save_loadinfo_p
= ((trace_flags
& STACKSHOT_SAVE_LOADINFO
) != 0);
1087 queue_iterate(&tasks
, task
, task_t
, tasks
) {
1088 int task_pid
= pid_from_task(task
);
1089 boolean_t task64
= task_has_64BitAddr(task
);
1091 if ((task
== NULL
) || (ml_nofault_copy((vm_offset_t
) task
, (vm_offset_t
) &ctask
, sizeof(struct task
)) != sizeof(struct task
)))
1094 /* Trace everything, unless a process was specified */
1095 if ((pid
== -1) || (pid
== task_pid
)) {
1096 task_snapshot_t task_snap
;
1097 uint32_t uuid_info_count
;
1098 mach_vm_address_t uuid_info_addr
;
1100 if (save_loadinfo_p
&& task_pid
> 0) {
1101 // Read the dyld_all_image_infos struct from the task memory to get UUID array count and location
1103 struct dyld_all_image_infos64 task_image_infos
;
1104 if (!kdp_copyin(task
->map
->pmap
, task
->all_image_info_addr
, &task_image_infos
, sizeof(struct dyld_all_image_infos64
)))
1106 uuid_info_count
= (uint32_t)task_image_infos
.uuidArrayCount
;
1107 uuid_info_addr
= task_image_infos
.uuidArray
;
1109 struct dyld_all_image_infos task_image_infos
;
1110 if (!kdp_copyin(task
->map
->pmap
, task
->all_image_info_addr
, &task_image_infos
, sizeof(struct dyld_all_image_infos
)))
1112 uuid_info_count
= task_image_infos
.uuidArrayCount
;
1113 uuid_info_addr
= task_image_infos
.uuidArray
;
1116 uuid_info_count
= 0;
1120 if (tracepos
+ sizeof(struct task_snapshot
) > tracebound
) {
1125 task_snap
= (task_snapshot_t
) tracepos
;
1126 task_snap
->snapshot_magic
= STACKSHOT_TASK_SNAPSHOT_MAGIC
;
1127 task_snap
->pid
= task_pid
;
1128 task_snap
->nloadinfos
= uuid_info_count
;
1129 /* Add the BSD process identifiers */
1131 proc_name_kdp(task
, task_snap
->p_comm
, sizeof(task_snap
->p_comm
));
1133 task_snap
->p_comm
[0] = '\0';
1134 task_snap
->ss_flags
= 0;
1136 task_snap
->ss_flags
|= kUser64_p
;
1138 tracepos
+= sizeof(struct task_snapshot
);
1140 if (task_pid
> 0 && uuid_info_count
> 0) {
1141 uint32_t uuid_info_size
= (uint32_t)(task64
? sizeof(struct dyld_uuid_info64
) : sizeof(struct dyld_uuid_info
));
1142 uint32_t uuid_info_array_size
= uuid_info_count
* uuid_info_size
;
1144 if (tracepos
+ uuid_info_array_size
> tracebound
) {
1149 // Copy in the UUID info array
1150 if (!kdp_copyin(task
->map
->pmap
, uuid_info_addr
, tracepos
, uuid_info_array_size
))
1153 tracepos
+= uuid_info_array_size
;
1156 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
){
1157 if ((thread
== NULL
) || (ml_nofault_copy((vm_offset_t
) thread
, (vm_offset_t
) &cthread
, sizeof(struct thread
)) != sizeof(struct thread
)))
1160 if (((tracepos
+ 4 * sizeof(struct thread_snapshot
)) > tracebound
)) {
1164 /* Populate the thread snapshot header */
1165 tsnap
= (thread_snapshot_t
) tracepos
;
1166 tsnap
->thread_id
= (uint64_t) (uintptr_t)thread
;
1167 tsnap
->state
= thread
->state
;
1168 tsnap
->wait_event
= thread
->wait_event
;
1169 tsnap
->continuation
= (uint64_t) (uintptr_t) thread
->continuation
;
1171 tsnap
->snapshot_magic
= STACKSHOT_THREAD_SNAPSHOT_MAGIC
;
1172 tracepos
+= sizeof(struct thread_snapshot
);
1173 tsnap
->ss_flags
= 0;
1175 if (dispatch_p
&& (task
!= kernel_task
) && (task
->active
) && (task
->map
)) {
1176 uint64_t dqkeyaddr
= thread_dispatchqaddr(thread
);
1177 if (dqkeyaddr
!= 0) {
1178 uint64_t dqaddr
= 0;
1179 if (kdp_copyin(task
->map
->pmap
, dqkeyaddr
, &dqaddr
, (task64
? 8 : 4)) && (dqaddr
!= 0)) {
1180 uint64_t dqserialnumaddr
= dqaddr
+ dispatch_offset
;
1181 uint64_t dqserialnum
= 0;
1182 if (kdp_copyin(task
->map
->pmap
, dqserialnumaddr
, &dqserialnum
, (task64
? 8 : 4))) {
1183 tsnap
->ss_flags
|= kHasDispatchSerial
;
1184 *(uint64_t *)tracepos
= dqserialnum
;
1190 /* Call through to the machine specific trace routines
1191 * Frames are added past the snapshot header.
1193 if (thread
->kernel_stack
!= 0) {
1194 #if defined(__LP64__)
1195 tracebytes
= machine_trace_thread64(thread
, tracepos
, tracebound
, MAX_FRAMES
, FALSE
);
1196 tsnap
->ss_flags
|= kKernel64_p
;
1199 tracebytes
= machine_trace_thread(thread
, tracepos
, tracebound
, MAX_FRAMES
, FALSE
);
1203 tsnap
->nkern_frames
= tracebytes
/framesize
;
1204 tracepos
+= tracebytes
;
1206 /* Trace user stack, if any */
1207 if (thread
->task
->map
!= kernel_map
) {
1209 if (task_has_64BitAddr(thread
->task
)) {
1210 tracebytes
= machine_trace_thread64(thread
, tracepos
, tracebound
, MAX_FRAMES
, TRUE
);
1211 tsnap
->ss_flags
|= kUser64_p
;
1215 tracebytes
= machine_trace_thread(thread
, tracepos
, tracebound
, MAX_FRAMES
, TRUE
);
1219 tsnap
->nuser_frames
= tracebytes
/framesize
;
1220 tracepos
+= tracebytes
;
1227 /* Release stack snapshot wait indicator */
1228 kdp_snapshot_postflight();
1230 *pbytesTraced
= (uint32_t)(tracepos
- (char *) tracebuf
);
1236 kdp_readioport(kdp_pkt_t
*pkt
,
1238 unsigned short *reply_port
1241 kdp_readioport_req_t
*rq
= &pkt
->readioport_req
;
1242 kdp_readioport_reply_t
*rp
= &pkt
->readioport_reply
;
1245 if (plen
< sizeof (*rq
))
1248 rp
->hdr
.is_reply
= 1;
1249 rp
->hdr
.len
= sizeof (*rp
);
1251 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
1252 rp
->error
= KDPERR_BAD_NBYTES
;
1254 #if KDP_TEST_HARNESS
1255 uint16_t addr
= rq
->address
;
1257 uint16_t size
= rq
->nbytes
;
1258 dprintf(("kdp_readioport addr %x size %d\n", addr
, size
));
1260 rp
->error
= kdp_machine_ioport_read(rq
, rp
->data
, rq
->lcpu
);
1261 if (rp
->error
== KDPERR_NO_ERROR
)
1262 rp
->hdr
.len
+= size
;
1265 *reply_port
= kdp
.reply_port
;
1275 unsigned short *reply_port
1278 kdp_writeioport_req_t
*rq
= &pkt
->writeioport_req
;
1279 kdp_writeioport_reply_t
*rp
= &pkt
->writeioport_reply
;
1282 if (plen
< sizeof (*rq
))
1285 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
1286 rp
->error
= KDPERR_BAD_NBYTES
;
1288 dprintf(("kdp_writeioport addr %x size %d\n", rq
->address
,
1291 rp
->error
= kdp_machine_ioport_write(rq
, rq
->data
, rq
->lcpu
);
1294 rp
->hdr
.is_reply
= 1;
1295 rp
->hdr
.len
= sizeof (*rp
);
1297 *reply_port
= kdp
.reply_port
;
1304 kdp_readmsr64(kdp_pkt_t
*pkt
,
1306 unsigned short *reply_port
1309 kdp_readmsr64_req_t
*rq
= &pkt
->readmsr64_req
;
1310 kdp_readmsr64_reply_t
*rp
= &pkt
->readmsr64_reply
;
1313 if (plen
< sizeof (*rq
))
1316 rp
->hdr
.is_reply
= 1;
1317 rp
->hdr
.len
= sizeof (*rp
);
1319 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq
->lcpu
, rq
->address
));
1320 rp
->error
= kdp_machine_msr64_read(rq
, rp
->data
, rq
->lcpu
);
1321 if (rp
->error
== KDPERR_NO_ERROR
)
1322 rp
->hdr
.len
+= sizeof(uint64_t);
1324 *reply_port
= kdp
.reply_port
;
1334 unsigned short *reply_port
1337 kdp_writemsr64_req_t
*rq
= &pkt
->writemsr64_req
;
1338 kdp_writemsr64_reply_t
*rp
= &pkt
->writemsr64_reply
;
1341 if (plen
< sizeof (*rq
))
1344 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq
->lcpu
, rq
->address
));
1345 rp
->error
= kdp_machine_msr64_write(rq
, rq
->data
, rq
->lcpu
);
1347 rp
->hdr
.is_reply
= 1;
1348 rp
->hdr
.len
= sizeof (*rp
);
1350 *reply_port
= kdp
.reply_port
;
1360 unsigned short *reply_port
1363 kdp_dumpinfo_req_t
*rq
= &pkt
->dumpinfo_req
;
1364 kdp_dumpinfo_reply_t
*rp
= &pkt
->dumpinfo_reply
;
1367 if (plen
< sizeof (*rq
))
1370 dprintf(("kdp_dumpinfo file=%s destip=%s routerip=%s\n", rq
->name
, rq
->destip
, rq
->routerip
));
1371 rp
->hdr
.is_reply
= 1;
1372 rp
->hdr
.len
= sizeof (*rp
);
1374 if ((rq
->type
& KDP_DUMPINFO_MASK
) != KDP_DUMPINFO_GETINFO
) {
1375 kdp_set_dump_info(rq
->type
, rq
->name
, rq
->destip
, rq
->routerip
,
1379 /* gather some stats for reply */
1380 kdp_get_dump_info(&rp
->type
, rp
->name
, rp
->destip
, rp
->routerip
,
1383 *reply_port
= kdp
.reply_port
;