]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/kdp.c
xnu-1504.3.12.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
1 /*
2 * Copyright (c) 2000-2007 Apple Computer, 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 <sys/appleapiopts.h>
31 #include <kern/debug.h>
32 #include <uuid/uuid.h>
33
34 #include <kdp/kdp_internal.h>
35 #include <kdp/kdp_private.h>
36 #include <kdp/kdp_core.h>
37 #include <kdp/kdp_dyld.h>
38
39 #include <libsa/types.h>
40
41 #include <string.h> /* bcopy */
42
43 #include <kern/processor.h>
44 #include <kern/thread.h>
45 #include <vm/vm_map.h>
46 #include <vm/vm_kern.h>
47
48 #define DO_ALIGN 1 /* align all packet data accesses */
49
50 #define KDP_TEST_HARNESS 0
51 #if KDP_TEST_HARNESS
52 #define dprintf(x) kprintf x
53 #else
54 #define dprintf(x)
55 #endif
56
57 static kdp_dispatch_t
58 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] =
59 {
60 /* 0 */ kdp_connect,
61 /* 1 */ kdp_disconnect,
62 /* 2 */ kdp_hostinfo,
63 /* 3 */ kdp_version,
64 /* 4 */ kdp_maxbytes,
65 /* 5 */ kdp_readmem,
66 /* 6 */ kdp_writemem,
67 /* 7 */ kdp_readregs,
68 /* 8 */ kdp_writeregs,
69 /* 9 */ kdp_unknown,
70 /* A */ kdp_unknown,
71 /* B */ kdp_suspend,
72 /* C */ kdp_resumecpus,
73 /* D */ kdp_unknown,
74 /* E */ kdp_unknown,
75 /* F */ kdp_breakpoint_set,
76 /*10 */ kdp_breakpoint_remove,
77 /*11 */ kdp_regions,
78 /*12 */ kdp_reattach,
79 /*13 */ kdp_reboot,
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,
91 /*1F */ kdp_dumpinfo,
92 };
93
94 kdp_glob_t kdp;
95
96 #define MAX_BREAKPOINTS 100
97
98 /*
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.
103 */
104 #define KDP_VERSION 12
105
106 typedef struct{
107 mach_vm_address_t address;
108 uint32_t bytesused;
109 uint8_t oldbytes[MAX_BREAKINSN_BYTES];
110 } kdp_breakpoint_record_t;
111
112 static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS];
113 static unsigned int breakpoints_initialized = 0;
114
115 int reattach_wait = 0;
116 int noresume_on_disconnect = 0;
117 extern unsigned int return_on_panic;
118
119 typedef struct thread_snapshot *thread_snapshot_t;
120 typedef struct task_snapshot *task_snapshot_t;
121
122 extern int
123 machine_trace_thread(thread_t thread, char *tracepos, char *tracebound, int nframes, boolean_t user_p);
124 extern int
125 machine_trace_thread64(thread_t thread, char *tracepos, char *tracebound, int nframes, boolean_t user_p);
126 extern int
127 proc_pid(void *p);
128 extern void
129 proc_name_kdp(task_t task, char *buf, int size);
130
131 extern void
132 kdp_snapshot_postflight(void);
133
134 static int
135 pid_from_task(task_t task);
136
137 kdp_error_t
138 kdp_set_breakpoint_internal(
139 mach_vm_address_t address
140 );
141
142 kdp_error_t
143 kdp_remove_breakpoint_internal(
144 mach_vm_address_t address
145 );
146
147
148 int
149 kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size, uint32_t trace_flags, uint32_t dispatch_offset, uint32_t *pbytesTraced);
150
151 boolean_t kdp_copyin(pmap_t, uint64_t, void *, size_t);
152 extern void bcopy_phys(addr64_t, addr64_t, vm_size_t);
153
154 extern char version[];
155
156 boolean_t
157 kdp_packet(
158 unsigned char *pkt,
159 int *len,
160 unsigned short *reply_port
161 )
162 {
163 static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt
164 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt;
165 size_t plen = *len;
166 kdp_req_t req;
167 boolean_t ret;
168
169 #if DO_ALIGN
170 bcopy((char *)pkt, (char *)rd, sizeof(aligned_pkt));
171 #else
172 rd = (kdp_pkt_t *)pkt;
173 #endif
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);
176
177 return (FALSE);
178 }
179
180 if (rd->hdr.is_reply) {
181 printf("kdp_packet reply recvd req %x seq %x\n",
182 rd->hdr.request, rd->hdr.seq);
183
184 return (FALSE);
185 }
186
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);
191
192 return (FALSE);
193 }
194
195 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port));
196 #if DO_ALIGN
197 bcopy((char *)rd, (char *) pkt, *len);
198 #endif
199 return ret;
200 }
201
202 static boolean_t
203 kdp_unknown(
204 kdp_pkt_t *pkt,
205 __unused int *len,
206 __unused unsigned short *reply_port
207 )
208 {
209 kdp_pkt_t *rd = (kdp_pkt_t *)pkt;
210
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);
213
214 return (FALSE);
215 }
216
217 static boolean_t
218 kdp_connect(
219 kdp_pkt_t *pkt,
220 int *len,
221 unsigned short *reply_port
222 )
223 {
224 kdp_connect_req_t *rq = &pkt->connect_req;
225 size_t plen = *len;
226 kdp_connect_reply_t *rp = &pkt->connect_reply;
227 uint16_t rport, eport;
228 uint32_t key;
229 uint8_t seq;
230
231 if (plen < sizeof (*rq))
232 return (FALSE);
233
234 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting));
235
236 rport = rq->req_reply_port;
237 eport = rq->exc_note_port;
238 key = rq->hdr.key;
239 seq = rq->hdr.seq;
240 if (kdp.is_conn) {
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;
246 else
247 rp->error = KDPERR_ALREADY_CONNECTED;
248 }
249 else {
250 kdp.reply_port = rport;
251 kdp.exception_port = eport;
252 kdp.is_conn = TRUE;
253 kdp.conn_seq = seq;
254 kdp.session_key = key;
255
256 rp->error = KDPERR_NO_ERROR;
257 }
258
259 rp->hdr.is_reply = 1;
260 rp->hdr.len = sizeof (*rp);
261
262 *reply_port = rport;
263 *len = rp->hdr.len;
264
265 if (current_debugger == KDP_CUR_DB)
266 active_debugger=1;
267
268 return (TRUE);
269 }
270
271 static boolean_t
272 kdp_disconnect(
273 kdp_pkt_t *pkt,
274 int *len,
275 unsigned short *reply_port
276 )
277 {
278 kdp_disconnect_req_t *rq = &pkt->disconnect_req;
279 size_t plen = *len;
280 kdp_disconnect_reply_t *rp = &pkt->disconnect_reply;
281
282 if (plen < sizeof (*rq))
283 return (FALSE);
284
285 if (!kdp.is_conn)
286 return (FALSE);
287
288 dprintf(("kdp_disconnect\n"));
289
290 *reply_port = kdp.reply_port;
291
292 kdp.reply_port = kdp.exception_port = 0;
293 kdp.is_halted = kdp.is_conn = FALSE;
294 kdp.exception_seq = kdp.conn_seq = 0;
295 kdp.session_key = 0;
296
297 if ((panicstr != NULL) && (return_on_panic == 0))
298 reattach_wait = 1;
299
300 if (noresume_on_disconnect == 1) {
301 reattach_wait = 1;
302 noresume_on_disconnect = 0;
303 }
304
305 rp->hdr.is_reply = 1;
306 rp->hdr.len = sizeof (*rp);
307
308 *len = rp->hdr.len;
309
310 if (current_debugger == KDP_CUR_DB)
311 active_debugger=0;
312
313 return (TRUE);
314 }
315
316 static boolean_t
317 kdp_reattach(
318 kdp_pkt_t *pkt,
319 int *len,
320 unsigned short *reply_port
321 )
322 {
323 kdp_reattach_req_t *rq = &pkt->reattach_req;
324
325 kdp.is_conn = TRUE;
326 kdp_disconnect(pkt, len, reply_port);
327 *reply_port = rq->req_reply_port;
328 reattach_wait = 1;
329 return (TRUE);
330 }
331
332 static boolean_t
333 kdp_hostinfo(
334 kdp_pkt_t *pkt,
335 int *len,
336 unsigned short *reply_port
337 )
338 {
339 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req;
340 size_t plen = *len;
341 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
342
343 if (plen < sizeof (*rq))
344 return (FALSE);
345
346 dprintf(("kdp_hostinfo\n"));
347
348 rp->hdr.is_reply = 1;
349 rp->hdr.len = sizeof (*rp);
350
351 kdp_machine_hostinfo(&rp->hostinfo);
352
353 *reply_port = kdp.reply_port;
354 *len = rp->hdr.len;
355
356 return (TRUE);
357 }
358
359 static boolean_t
360 kdp_kernelversion(
361 kdp_pkt_t *pkt,
362 int *len,
363 unsigned short *reply_port
364 )
365 {
366 kdp_kernelversion_req_t *rq = &pkt->kernelversion_req;
367 size_t plen = *len;
368 kdp_kernelversion_reply_t *rp = &pkt->kernelversion_reply;
369 size_t slen;
370
371 if (plen < sizeof (*rq))
372 return (FALSE);
373
374 rp->hdr.is_reply = 1;
375 rp->hdr.len = sizeof (*rp);
376
377 dprintf(("kdp_kernelversion\n"));
378 slen = strlcpy(rp->version, version, MAX_KDP_DATA_SIZE);
379
380 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */
381
382 *reply_port = kdp.reply_port;
383 *len = rp->hdr.len;
384
385 return (TRUE);
386 }
387
388 static boolean_t
389 kdp_suspend(
390 kdp_pkt_t *pkt,
391 int *len,
392 unsigned short *reply_port
393 )
394 {
395 kdp_suspend_req_t *rq = &pkt->suspend_req;
396 size_t plen = *len;
397 kdp_suspend_reply_t *rp = &pkt->suspend_reply;
398
399 if (plen < sizeof (*rq))
400 return (FALSE);
401
402 rp->hdr.is_reply = 1;
403 rp->hdr.len = sizeof (*rp);
404
405 dprintf(("kdp_suspend\n"));
406
407 kdp.is_halted = TRUE;
408
409 *reply_port = kdp.reply_port;
410 *len = rp->hdr.len;
411
412 return (TRUE);
413 }
414
415 static boolean_t
416 kdp_resumecpus(
417 kdp_pkt_t *pkt,
418 int *len,
419 unsigned short *reply_port
420 )
421 {
422 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req;
423 size_t plen = *len;
424 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply;
425
426 if (plen < sizeof (*rq))
427 return (FALSE);
428
429 rp->hdr.is_reply = 1;
430 rp->hdr.len = sizeof (*rp);
431
432 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask));
433
434 kdp.is_halted = FALSE;
435
436 *reply_port = kdp.reply_port;
437 *len = rp->hdr.len;
438
439 return (TRUE);
440 }
441
442 static boolean_t
443 kdp_writemem(
444 kdp_pkt_t *pkt,
445 int *len,
446 unsigned short *reply_port
447 )
448 {
449 kdp_writemem_req_t *rq = &pkt->writemem_req;
450 size_t plen = *len;
451 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
452 mach_vm_size_t cnt;
453
454 if (plen < sizeof (*rq))
455 return (FALSE);
456
457 if (rq->nbytes > MAX_KDP_DATA_SIZE)
458 rp->error = KDPERR_BAD_NBYTES;
459 else {
460 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes));
461
462 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes);
463 rp->error = KDPERR_NO_ERROR;
464 }
465
466 rp->hdr.is_reply = 1;
467 rp->hdr.len = sizeof (*rp);
468
469 *reply_port = kdp.reply_port;
470 *len = rp->hdr.len;
471
472 return (TRUE);
473 }
474
475 static boolean_t
476 kdp_writemem64(
477 kdp_pkt_t *pkt,
478 int *len,
479 unsigned short *reply_port
480 )
481 {
482 kdp_writemem64_req_t *rq = &pkt->writemem64_req;
483 size_t plen = *len;
484 kdp_writemem64_reply_t *rp = &pkt->writemem64_reply;
485 mach_vm_size_t cnt;
486
487 if (plen < sizeof (*rq))
488 return (FALSE);
489
490 if (rq->nbytes > MAX_KDP_DATA_SIZE)
491 rp->error = KDPERR_BAD_NBYTES;
492 else {
493 dprintf(("kdp_writemem64 addr %llx size %d\n", rq->address, rq->nbytes));
494
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;
497 }
498
499 rp->hdr.is_reply = 1;
500 rp->hdr.len = sizeof (*rp);
501
502 *reply_port = kdp.reply_port;
503 *len = rp->hdr.len;
504
505 return (TRUE);
506 }
507
508 static boolean_t
509 kdp_writephysmem64(
510 kdp_pkt_t *pkt,
511 int *len,
512 unsigned short *reply_port
513 )
514 {
515 kdp_writephysmem64_req_t *rq = &pkt->writephysmem64_req;
516 size_t plen = *len;
517 kdp_writephysmem64_reply_t *rp = &pkt->writephysmem64_reply;
518
519 if (plen < sizeof (*rq))
520 return (FALSE);
521
522 if (rq->nbytes > MAX_KDP_DATA_SIZE)
523 rp->error = KDPERR_BAD_NBYTES;
524 else {
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;
528 }
529
530 rp->hdr.is_reply = 1;
531 rp->hdr.len = sizeof (*rp);
532
533 *reply_port = kdp.reply_port;
534 *len = rp->hdr.len;
535
536 return (TRUE);
537 }
538
539 static boolean_t
540 kdp_readmem(
541 kdp_pkt_t *pkt,
542 int *len,
543 unsigned short *reply_port
544 )
545 {
546 kdp_readmem_req_t *rq = &pkt->readmem_req;
547 size_t plen = *len;
548 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
549 mach_vm_size_t cnt;
550 #if __i386__ || __arm__
551 void *pversion = &version;
552 #endif
553
554 if (plen < sizeof (*rq))
555 return (FALSE);
556
557 rp->hdr.is_reply = 1;
558 rp->hdr.len = sizeof (*rp);
559
560 if (rq->nbytes > MAX_KDP_DATA_SIZE)
561 rp->error = KDPERR_BAD_NBYTES;
562 else {
563 unsigned int n = rq->nbytes;
564
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.
577 */
578 if (rq->address == 0x501C)
579 rq->address = (uintptr_t)&pversion;
580 #endif
581 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, n);
582 rp->error = KDPERR_NO_ERROR;
583
584 rp->hdr.len += cnt;
585 }
586
587 *reply_port = kdp.reply_port;
588 *len = rp->hdr.len;
589
590 return (TRUE);
591 }
592
593 static boolean_t
594 kdp_readmem64(
595 kdp_pkt_t *pkt,
596 int *len,
597 unsigned short *reply_port
598 )
599 {
600 kdp_readmem64_req_t *rq = &pkt->readmem64_req;
601 size_t plen = *len;
602 kdp_readmem64_reply_t *rp = &pkt->readmem64_reply;
603 mach_vm_size_t cnt;
604
605 if (plen < sizeof (*rq))
606 return (FALSE);
607
608 rp->hdr.is_reply = 1;
609 rp->hdr.len = sizeof (*rp);
610
611 if (rq->nbytes > MAX_KDP_DATA_SIZE)
612 rp->error = KDPERR_BAD_NBYTES;
613 else {
614
615 dprintf(("kdp_readmem64 addr %llx size %d\n", rq->address, rq->nbytes));
616
617 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
618 rp->error = KDPERR_NO_ERROR;
619
620 rp->hdr.len += cnt;
621 }
622
623 *reply_port = kdp.reply_port;
624 *len = rp->hdr.len;
625
626 return (TRUE);
627 }
628
629 static boolean_t
630 kdp_readphysmem64(
631 kdp_pkt_t *pkt,
632 int *len,
633 unsigned short *reply_port
634 )
635 {
636 kdp_readphysmem64_req_t *rq = &pkt->readphysmem64_req;
637 size_t plen = *len;
638 kdp_readphysmem64_reply_t *rp = &pkt->readphysmem64_reply;
639 int cnt;
640
641 if (plen < sizeof (*rq))
642 return (FALSE);
643
644 rp->hdr.is_reply = 1;
645 rp->hdr.len = sizeof (*rp);
646
647 if (rq->nbytes > MAX_KDP_DATA_SIZE)
648 rp->error = KDPERR_BAD_NBYTES;
649 else {
650
651 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq->address, rq->nbytes));
652
653 cnt = (int)kdp_machine_phys_read(rq, rp->data, rq->lcpu);
654 rp->error = KDPERR_NO_ERROR;
655
656 rp->hdr.len += cnt;
657 }
658
659 *reply_port = kdp.reply_port;
660 *len = rp->hdr.len;
661
662 return (TRUE);
663 }
664
665 static boolean_t
666 kdp_maxbytes(
667 kdp_pkt_t *pkt,
668 int *len,
669 unsigned short *reply_port
670 )
671 {
672 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req;
673 size_t plen = *len;
674 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply;
675
676 if (plen < sizeof (*rq))
677 return (FALSE);
678
679 rp->hdr.is_reply = 1;
680 rp->hdr.len = sizeof (*rp);
681
682 dprintf(("kdp_maxbytes\n"));
683
684 rp->max_bytes = MAX_KDP_DATA_SIZE;
685
686 *reply_port = kdp.reply_port;
687 *len = rp->hdr.len;
688
689 return (TRUE);
690 }
691
692 static boolean_t
693 kdp_version(
694 kdp_pkt_t *pkt,
695 int *len,
696 unsigned short *reply_port
697 )
698 {
699 kdp_version_req_t *rq = &pkt->version_req;
700 size_t plen = *len;
701 kdp_version_reply_t *rp = &pkt->version_reply;
702
703 if (plen < sizeof (*rq))
704 return (FALSE);
705
706 rp->hdr.is_reply = 1;
707 rp->hdr.len = sizeof (*rp);
708
709 dprintf(("kdp_version\n"));
710
711 rp->version = KDP_VERSION;
712 if (!(kdp_flag & KDP_BP_DIS))
713 rp->feature = KDP_FEATURE_BP;
714 else
715 rp->feature = 0;
716
717 *reply_port = kdp.reply_port;
718 *len = rp->hdr.len;
719
720 return (TRUE);
721 }
722
723 static boolean_t
724 kdp_regions(
725 kdp_pkt_t *pkt,
726 int *len,
727 unsigned short *reply_port
728 )
729 {
730 kdp_regions_req_t *rq = &pkt->regions_req;
731 size_t plen = *len;
732 kdp_regions_reply_t *rp = &pkt->regions_reply;
733 kdp_region_t *r;
734
735 if (plen < sizeof (*rq))
736 return (FALSE);
737
738 rp->hdr.is_reply = 1;
739 rp->hdr.len = sizeof (*rp);
740
741 dprintf(("kdp_regions\n"));
742
743 r = rp->regions;
744 rp->nregions = 0;
745
746 r->address = 0;
747 r->nbytes = 0xffffffff;
748
749 r->protection = VM_PROT_ALL; r++; rp->nregions++;
750
751 rp->hdr.len += rp->nregions * sizeof (kdp_region_t);
752
753 *reply_port = kdp.reply_port;
754 *len = rp->hdr.len;
755
756 return (TRUE);
757 }
758
759 static boolean_t
760 kdp_writeregs(
761 kdp_pkt_t *pkt,
762 int *len,
763 unsigned short *reply_port
764 )
765 {
766 kdp_writeregs_req_t *rq = &pkt->writeregs_req;
767 size_t plen = *len;
768 int size;
769 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
770
771 if (plen < sizeof (*rq))
772 return (FALSE);
773
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);
776
777 rp->hdr.is_reply = 1;
778 rp->hdr.len = sizeof (*rp);
779
780 *reply_port = kdp.reply_port;
781 *len = rp->hdr.len;
782
783 return (TRUE);
784 }
785
786 static boolean_t
787 kdp_readregs(
788 kdp_pkt_t *pkt,
789 int *len,
790 unsigned short *reply_port
791 )
792 {
793 kdp_readregs_req_t *rq = &pkt->readregs_req;
794 size_t plen = *len;
795 kdp_readregs_reply_t *rp = &pkt->readregs_reply;
796 int size;
797
798 if (plen < sizeof (*rq))
799 return (FALSE);
800
801 rp->hdr.is_reply = 1;
802 rp->hdr.len = sizeof (*rp);
803
804 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size);
805 rp->hdr.len += size;
806
807 *reply_port = kdp.reply_port;
808 *len = rp->hdr.len;
809
810 return (TRUE);
811 }
812
813
814 boolean_t
815 kdp_breakpoint_set(
816 kdp_pkt_t *pkt,
817 int *len,
818 unsigned short *reply_port
819 )
820 {
821 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
822 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
823 size_t plen = *len;
824 kdp_error_t kerr;
825
826 if (plen < sizeof (*rq))
827 return (FALSE);
828
829 dprintf(("kdp_breakpoint_set %x\n", rq->address));
830
831 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
832
833 rp->error = kerr;
834
835 rp->hdr.is_reply = 1;
836 rp->hdr.len = sizeof (*rp);
837 *reply_port = kdp.reply_port;
838 *len = rp->hdr.len;
839
840 return (TRUE);
841 }
842
843 boolean_t
844 kdp_breakpoint64_set(
845 kdp_pkt_t *pkt,
846 int *len,
847 unsigned short *reply_port
848 )
849 {
850 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
851 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
852 size_t plen = *len;
853 kdp_error_t kerr;
854
855 if (plen < sizeof (*rq))
856 return (FALSE);
857
858 dprintf(("kdp_breakpoint64_set %llx\n", rq->address));
859
860 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
861
862 rp->error = kerr;
863
864 rp->hdr.is_reply = 1;
865 rp->hdr.len = sizeof (*rp);
866 *reply_port = kdp.reply_port;
867 *len = rp->hdr.len;
868
869 return (TRUE);
870 }
871
872 boolean_t
873 kdp_breakpoint_remove(
874 kdp_pkt_t *pkt,
875 int *len,
876 unsigned short *reply_port
877 )
878 {
879 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
880 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
881 size_t plen = *len;
882 kdp_error_t kerr;
883 if (plen < sizeof (*rq))
884 return (FALSE);
885
886 dprintf(("kdp_breakpoint_remove %x\n", rq->address));
887
888 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
889
890 rp->error = kerr;
891
892 rp->hdr.is_reply = 1;
893 rp->hdr.len = sizeof (*rp);
894 *reply_port = kdp.reply_port;
895 *len = rp->hdr.len;
896
897 return (TRUE);
898 }
899
900 boolean_t
901 kdp_breakpoint64_remove(
902 kdp_pkt_t *pkt,
903 int *len,
904 unsigned short *reply_port
905 )
906 {
907 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
908 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
909 size_t plen = *len;
910 kdp_error_t kerr;
911
912 if (plen < sizeof (*rq))
913 return (FALSE);
914
915 dprintf(("kdp_breakpoint64_remove %llx\n", rq->address));
916
917 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
918
919 rp->error = kerr;
920
921 rp->hdr.is_reply = 1;
922 rp->hdr.len = sizeof (*rp);
923 *reply_port = kdp.reply_port;
924 *len = rp->hdr.len;
925
926 return (TRUE);
927 }
928
929
930 kdp_error_t
931 kdp_set_breakpoint_internal(
932 mach_vm_address_t address
933 )
934 {
935
936 uint8_t breakinstr[MAX_BREAKINSN_BYTES], oldinstr[MAX_BREAKINSN_BYTES];
937 uint32_t breakinstrsize = sizeof(breakinstr);
938 mach_vm_size_t cnt;
939 int i;
940
941 kdp_machine_get_breakinsn(breakinstr, &breakinstrsize);
942
943 if(breakpoints_initialized == 0)
944 {
945 for(i=0;(i < MAX_BREAKPOINTS); breakpoint_list[i].address=0, i++);
946 breakpoints_initialized++;
947 }
948
949 cnt = kdp_machine_vm_read(address, (caddr_t)&oldinstr, (mach_vm_size_t)breakinstrsize);
950
951 if (0 == memcmp(oldinstr, breakinstr, breakinstrsize)) {
952 printf("A trap was already set at that address, not setting new breakpoint\n");
953
954 return KDPERR_BREAKPOINT_ALREADY_SET;
955 }
956
957 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++);
958
959 if (i == MAX_BREAKPOINTS) {
960 return KDPERR_MAX_BREAKPOINTS;
961 }
962
963 breakpoint_list[i].address = address;
964 memcpy(breakpoint_list[i].oldbytes, oldinstr, breakinstrsize);
965 breakpoint_list[i].bytesused = breakinstrsize;
966
967 cnt = kdp_machine_vm_write((caddr_t)&breakinstr, address, breakinstrsize);
968
969 return KDPERR_NO_ERROR;
970 }
971
972 kdp_error_t
973 kdp_remove_breakpoint_internal(
974 mach_vm_address_t address
975 )
976 {
977 mach_vm_size_t cnt;
978 int i;
979
980 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != address); i++);
981
982 if (i == MAX_BREAKPOINTS)
983 {
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
993 boolean_t
994 kdp_remove_all_breakpoints(void)
995 {
996 int i;
997 boolean_t breakpoint_found = FALSE;
998
999 if (breakpoints_initialized)
1000 {
1001 for(i=0;i < MAX_BREAKPOINTS; i++)
1002 {
1003 if (breakpoint_list[i].address)
1004 {
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;
1008 }
1009 }
1010
1011 if (breakpoint_found)
1012 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
1013 }
1014 return breakpoint_found;
1015 }
1016
1017 boolean_t
1018 kdp_reboot(
1019 __unused kdp_pkt_t *pkt,
1020 __unused int *len,
1021 __unused unsigned short *reply_port
1022 )
1023 {
1024 dprintf(("kdp_reboot\n"));
1025
1026 kdp_machine_reboot();
1027
1028 return (TRUE); // no, not really, we won't return
1029 }
1030
1031 #define MAX_FRAMES 1000
1032
1033 static int pid_from_task(task_t task)
1034 {
1035 int pid = -1;
1036
1037 if (task->bsd_info)
1038 pid = proc_pid(task->bsd_info);
1039
1040 return pid;
1041 }
1042
1043 boolean_t
1044 kdp_copyin(pmap_t p, uint64_t uaddr, void *dest, size_t size) {
1045 size_t rem = size;
1046 char *kvaddr = dest;
1047
1048 while (rem) {
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);
1056
1057 if (upn && pmap_valid_page(upn) && phys_dest) {
1058 bcopy_phys(phys_src, phys_dest, cur_size);
1059 }
1060 else
1061 break;
1062 uaddr += cur_size;
1063 kvaddr += cur_size;
1064 rem -= cur_size;
1065 }
1066 return (rem == 0);
1067 }
1068
1069 int
1070 kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size, uint32_t trace_flags, uint32_t dispatch_offset, uint32_t *pbytesTraced)
1071 {
1072 char *tracepos = (char *) tracebuf;
1073 char *tracebound = tracepos + tracebuf_size;
1074 uint32_t tracebytes = 0;
1075 int error = 0;
1076
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);
1081 struct task ctask;
1082 struct thread cthread;
1083
1084 boolean_t dispatch_p = ((trace_flags & STACKSHOT_GET_DQ) != 0);
1085 boolean_t save_loadinfo_p = ((trace_flags & STACKSHOT_SAVE_LOADINFO) != 0);
1086
1087 queue_iterate(&tasks, task, task_t, tasks) {
1088 int task_pid = pid_from_task(task);
1089 boolean_t task64 = task_has_64BitAddr(task);
1090
1091 if ((task == NULL) || (ml_nofault_copy((vm_offset_t) task, (vm_offset_t) &ctask, sizeof(struct task)) != sizeof(struct task)))
1092 goto error_exit;
1093
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;
1099
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
1102 if (task64) {
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)))
1105 goto error_exit;
1106 uuid_info_count = (uint32_t)task_image_infos.uuidArrayCount;
1107 uuid_info_addr = task_image_infos.uuidArray;
1108 } else {
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)))
1111 goto error_exit;
1112 uuid_info_count = task_image_infos.uuidArrayCount;
1113 uuid_info_addr = task_image_infos.uuidArray;
1114 }
1115 } else {
1116 uuid_info_count = 0;
1117 uuid_info_addr = 0;
1118 }
1119
1120 if (tracepos + sizeof(struct task_snapshot) > tracebound) {
1121 error = -1;
1122 goto error_exit;
1123 }
1124
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 */
1130 if (task_pid != -1)
1131 proc_name_kdp(task, task_snap->p_comm, sizeof(task_snap->p_comm));
1132 else
1133 task_snap->p_comm[0] = '\0';
1134 task_snap->ss_flags = 0;
1135 if (task64)
1136 task_snap->ss_flags |= kUser64_p;
1137
1138 tracepos += sizeof(struct task_snapshot);
1139
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;
1143
1144 if (tracepos + uuid_info_array_size > tracebound) {
1145 error = -1;
1146 goto error_exit;
1147 }
1148
1149 // Copy in the UUID info array
1150 if (!kdp_copyin(task->map->pmap, uuid_info_addr, tracepos, uuid_info_array_size))
1151 goto error_exit;
1152
1153 tracepos += uuid_info_array_size;
1154 }
1155
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)))
1158 goto error_exit;
1159
1160 if (((tracepos + 4 * sizeof(struct thread_snapshot)) > tracebound)) {
1161 error = -1;
1162 goto error_exit;
1163 }
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;
1170
1171 tsnap->snapshot_magic = STACKSHOT_THREAD_SNAPSHOT_MAGIC;
1172 tracepos += sizeof(struct thread_snapshot);
1173 tsnap->ss_flags = 0;
1174
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;
1185 tracepos += 8;
1186 }
1187 }
1188 }
1189 }
1190 /* Call through to the machine specific trace routines
1191 * Frames are added past the snapshot header.
1192 */
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;
1197 framesize = 16;
1198 #else
1199 tracebytes = machine_trace_thread(thread, tracepos, tracebound, MAX_FRAMES, FALSE);
1200 framesize = 8;
1201 #endif
1202 }
1203 tsnap->nkern_frames = tracebytes/framesize;
1204 tracepos += tracebytes;
1205 tracebytes = 0;
1206 /* Trace user stack, if any */
1207 if (thread->task->map != kernel_map) {
1208 /* 64-bit task? */
1209 if (task_has_64BitAddr(thread->task)) {
1210 tracebytes = machine_trace_thread64(thread, tracepos, tracebound, MAX_FRAMES, TRUE);
1211 tsnap->ss_flags |= kUser64_p;
1212 framesize = 16;
1213 }
1214 else {
1215 tracebytes = machine_trace_thread(thread, tracepos, tracebound, MAX_FRAMES, TRUE);
1216 framesize = 8;
1217 }
1218 }
1219 tsnap->nuser_frames = tracebytes/framesize;
1220 tracepos += tracebytes;
1221 tracebytes = 0;
1222 }
1223 }
1224 }
1225
1226 error_exit:
1227 /* Release stack snapshot wait indicator */
1228 kdp_snapshot_postflight();
1229
1230 *pbytesTraced = (uint32_t)(tracepos - (char *) tracebuf);
1231
1232 return error;
1233 }
1234
1235 static boolean_t
1236 kdp_readioport(kdp_pkt_t *pkt,
1237 int *len,
1238 unsigned short *reply_port
1239 )
1240 {
1241 kdp_readioport_req_t *rq = &pkt->readioport_req;
1242 kdp_readioport_reply_t *rp = &pkt->readioport_reply;
1243 size_t plen = *len;
1244
1245 if (plen < sizeof (*rq))
1246 return (FALSE);
1247
1248 rp->hdr.is_reply = 1;
1249 rp->hdr.len = sizeof (*rp);
1250
1251 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1252 rp->error = KDPERR_BAD_NBYTES;
1253 else {
1254 #if KDP_TEST_HARNESS
1255 uint16_t addr = rq->address;
1256 #endif
1257 uint16_t size = rq->nbytes;
1258 dprintf(("kdp_readioport addr %x size %d\n", addr, size));
1259
1260 rp->error = kdp_machine_ioport_read(rq, rp->data, rq->lcpu);
1261 if (rp->error == KDPERR_NO_ERROR)
1262 rp->hdr.len += size;
1263 }
1264
1265 *reply_port = kdp.reply_port;
1266 *len = rp->hdr.len;
1267
1268 return (TRUE);
1269 }
1270
1271 static boolean_t
1272 kdp_writeioport(
1273 kdp_pkt_t *pkt,
1274 int *len,
1275 unsigned short *reply_port
1276 )
1277 {
1278 kdp_writeioport_req_t *rq = &pkt->writeioport_req;
1279 kdp_writeioport_reply_t *rp = &pkt->writeioport_reply;
1280 size_t plen = *len;
1281
1282 if (plen < sizeof (*rq))
1283 return (FALSE);
1284
1285 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1286 rp->error = KDPERR_BAD_NBYTES;
1287 else {
1288 dprintf(("kdp_writeioport addr %x size %d\n", rq->address,
1289 rq->nbytes));
1290
1291 rp->error = kdp_machine_ioport_write(rq, rq->data, rq->lcpu);
1292 }
1293
1294 rp->hdr.is_reply = 1;
1295 rp->hdr.len = sizeof (*rp);
1296
1297 *reply_port = kdp.reply_port;
1298 *len = rp->hdr.len;
1299
1300 return (TRUE);
1301 }
1302
1303 static boolean_t
1304 kdp_readmsr64(kdp_pkt_t *pkt,
1305 int *len,
1306 unsigned short *reply_port
1307 )
1308 {
1309 kdp_readmsr64_req_t *rq = &pkt->readmsr64_req;
1310 kdp_readmsr64_reply_t *rp = &pkt->readmsr64_reply;
1311 size_t plen = *len;
1312
1313 if (plen < sizeof (*rq))
1314 return (FALSE);
1315
1316 rp->hdr.is_reply = 1;
1317 rp->hdr.len = sizeof (*rp);
1318
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);
1323
1324 *reply_port = kdp.reply_port;
1325 *len = rp->hdr.len;
1326
1327 return (TRUE);
1328 }
1329
1330 static boolean_t
1331 kdp_writemsr64(
1332 kdp_pkt_t *pkt,
1333 int *len,
1334 unsigned short *reply_port
1335 )
1336 {
1337 kdp_writemsr64_req_t *rq = &pkt->writemsr64_req;
1338 kdp_writemsr64_reply_t *rp = &pkt->writemsr64_reply;
1339 size_t plen = *len;
1340
1341 if (plen < sizeof (*rq))
1342 return (FALSE);
1343
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);
1346
1347 rp->hdr.is_reply = 1;
1348 rp->hdr.len = sizeof (*rp);
1349
1350 *reply_port = kdp.reply_port;
1351 *len = rp->hdr.len;
1352
1353 return (TRUE);
1354 }
1355
1356 static boolean_t
1357 kdp_dumpinfo(
1358 kdp_pkt_t *pkt,
1359 int *len,
1360 unsigned short *reply_port
1361 )
1362 {
1363 kdp_dumpinfo_req_t *rq = &pkt->dumpinfo_req;
1364 kdp_dumpinfo_reply_t *rp = &pkt->dumpinfo_reply;
1365 size_t plen = *len;
1366
1367 if (plen < sizeof (*rq))
1368 return (FALSE);
1369
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);
1373
1374 if ((rq->type & KDP_DUMPINFO_MASK) != KDP_DUMPINFO_GETINFO) {
1375 kdp_set_dump_info(rq->type, rq->name, rq->destip, rq->routerip,
1376 rq->port);
1377 }
1378
1379 /* gather some stats for reply */
1380 kdp_get_dump_info(&rp->type, rp->name, rp->destip, rp->routerip,
1381 &rp->port);
1382
1383 *reply_port = kdp.reply_port;
1384 *len = rp->hdr.len;
1385
1386 return (TRUE);
1387 }