]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/kdp.c
xnu-1456.1.26.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
33 #include <kdp/kdp_internal.h>
34 #include <kdp/kdp_private.h>
35
36 #include <libsa/types.h>
37
38 #include <string.h> /* bcopy */
39
40 #include <kern/processor.h>
41 #include <kern/thread.h>
42 #include <vm/vm_map.h>
43 #include <vm/vm_kern.h>
44
45 #define DO_ALIGN 1 /* align all packet data accesses */
46
47 #define KDP_TEST_HARNESS 0
48 #if KDP_TEST_HARNESS
49 #define dprintf(x) kprintf x
50 #else
51 #define dprintf(x)
52 #endif
53
54 static kdp_dispatch_t
55 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] =
56 {
57 /* 0 */ kdp_connect,
58 /* 1 */ kdp_disconnect,
59 /* 2 */ kdp_hostinfo,
60 /* 3 */ kdp_version,
61 /* 4 */ kdp_maxbytes,
62 /* 5 */ kdp_readmem,
63 /* 6 */ kdp_writemem,
64 /* 7 */ kdp_readregs,
65 /* 8 */ kdp_writeregs,
66 /* 9 */ kdp_unknown,
67 /* A */ kdp_unknown,
68 /* B */ kdp_suspend,
69 /* C */ kdp_resumecpus,
70 /* D */ kdp_unknown,
71 /* E */ kdp_unknown,
72 /* F */ kdp_breakpoint_set,
73 /*10 */ kdp_breakpoint_remove,
74 /*11 */ kdp_regions,
75 /*12 */ kdp_reattach,
76 /*13 */ kdp_reboot,
77 /*14 */ kdp_readmem64,
78 /*15 */ kdp_writemem64,
79 /*16 */ kdp_breakpoint64_set,
80 /*17 */ kdp_breakpoint64_remove,
81 /*18 */ kdp_kernelversion,
82 /*19 */ kdp_readphysmem64,
83 /*20 */ kdp_writephysmem64,
84 /*21 */ kdp_readioport,
85 /*22 */ kdp_writeioport,
86 /*23 */ kdp_readmsr64,
87 /*24 */ kdp_writemsr64,
88 };
89
90 kdp_glob_t kdp;
91
92 #define MAX_BREAKPOINTS 100
93
94 /*
95 * Version 11 of the KDP Protocol adds support for 64-bit wide memory
96 * addresses (read/write and breakpoints) as well as a dedicated
97 * kernelversion request. Version 12 adds read/writing of physical
98 * memory with 64-bit wide memory addresses.
99 */
100 #define KDP_VERSION 12
101
102 typedef struct{
103 mach_vm_address_t address;
104 uint32_t bytesused;
105 uint8_t oldbytes[MAX_BREAKINSN_BYTES];
106 } kdp_breakpoint_record_t;
107
108 static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS];
109 static unsigned int breakpoints_initialized = 0;
110
111 int reattach_wait = 0;
112 int noresume_on_disconnect = 0;
113 extern unsigned int return_on_panic;
114
115 typedef struct thread_snapshot *thread_snapshot_t;
116
117 extern int
118 machine_trace_thread(thread_t thread, char *tracepos, char *tracebound, int nframes, boolean_t user_p);
119 extern int
120 machine_trace_thread64(thread_t thread, char *tracepos, char *tracebound, int nframes, boolean_t user_p);
121 extern int
122 proc_pid(void *p);
123 extern void
124 proc_name_kdp(task_t task, char *buf, int size);
125
126 extern void
127 kdp_snapshot_postflight(void);
128
129 static int
130 pid_from_task(task_t task);
131
132 kdp_error_t
133 kdp_set_breakpoint_internal(
134 mach_vm_address_t address
135 );
136
137 kdp_error_t
138 kdp_remove_breakpoint_internal(
139 mach_vm_address_t address
140 );
141
142
143 int
144 kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size, unsigned trace_options, uint32_t *pbytesTraced);
145
146 boolean_t kdp_copyin(pmap_t, uint64_t, void *, size_t);
147 extern void bcopy_phys(addr64_t, addr64_t, vm_size_t);
148
149 extern char version[];
150
151 boolean_t
152 kdp_packet(
153 unsigned char *pkt,
154 int *len,
155 unsigned short *reply_port
156 )
157 {
158 static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt
159 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt;
160 size_t plen = *len;
161 kdp_req_t req;
162 boolean_t ret;
163
164 #if DO_ALIGN
165 bcopy((char *)pkt, (char *)rd, sizeof(aligned_pkt));
166 #else
167 rd = (kdp_pkt_t *)pkt;
168 #endif
169 if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) {
170 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len);
171
172 return (FALSE);
173 }
174
175 if (rd->hdr.is_reply) {
176 printf("kdp_packet reply recvd req %x seq %x\n",
177 rd->hdr.request, rd->hdr.seq);
178
179 return (FALSE);
180 }
181
182 req = rd->hdr.request;
183 if (req >= KDP_INVALID_REQUEST) {
184 printf("kdp_packet bad request %x len %d seq %x key %x\n",
185 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
186
187 return (FALSE);
188 }
189
190 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port));
191 #if DO_ALIGN
192 bcopy((char *)rd, (char *) pkt, *len);
193 #endif
194 return ret;
195 }
196
197 static boolean_t
198 kdp_unknown(
199 kdp_pkt_t *pkt,
200 __unused int *len,
201 __unused unsigned short *reply_port
202 )
203 {
204 kdp_pkt_t *rd = (kdp_pkt_t *)pkt;
205
206 printf("kdp_unknown request %x len %d seq %x key %x\n",
207 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
208
209 return (FALSE);
210 }
211
212 static boolean_t
213 kdp_connect(
214 kdp_pkt_t *pkt,
215 int *len,
216 unsigned short *reply_port
217 )
218 {
219 kdp_connect_req_t *rq = &pkt->connect_req;
220 size_t plen = *len;
221 kdp_connect_reply_t *rp = &pkt->connect_reply;
222
223 if (plen < sizeof (*rq))
224 return (FALSE);
225
226 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting));
227
228 if (kdp.is_conn) {
229 if (rq->hdr.seq == kdp.conn_seq) /* duplicate request */
230 rp->error = KDPERR_NO_ERROR;
231 else
232 rp->error = KDPERR_ALREADY_CONNECTED;
233 }
234 else {
235 kdp.reply_port = rq->req_reply_port;
236 kdp.exception_port = rq->exc_note_port;
237 kdp.is_conn = TRUE;
238 kdp.conn_seq = rq->hdr.seq;
239
240 rp->error = KDPERR_NO_ERROR;
241 }
242
243 rp->hdr.is_reply = 1;
244 rp->hdr.len = sizeof (*rp);
245
246 *reply_port = kdp.reply_port;
247 *len = rp->hdr.len;
248
249 if (current_debugger == KDP_CUR_DB)
250 active_debugger=1;
251
252 return (TRUE);
253 }
254
255 static boolean_t
256 kdp_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 if (!kdp.is_conn)
270 return (FALSE);
271
272 dprintf(("kdp_disconnect\n"));
273
274 *reply_port = kdp.reply_port;
275
276 kdp.reply_port = kdp.exception_port = 0;
277 kdp.is_halted = kdp.is_conn = FALSE;
278 kdp.exception_seq = kdp.conn_seq = 0;
279
280 if ((panicstr != NULL) && (return_on_panic == 0))
281 reattach_wait = 1;
282
283 if (noresume_on_disconnect == 1) {
284 reattach_wait = 1;
285 noresume_on_disconnect = 0;
286 }
287
288 rp->hdr.is_reply = 1;
289 rp->hdr.len = sizeof (*rp);
290
291 *len = rp->hdr.len;
292
293 if (current_debugger == KDP_CUR_DB)
294 active_debugger=0;
295
296 return (TRUE);
297 }
298
299 static boolean_t
300 kdp_reattach(
301 kdp_pkt_t *pkt,
302 int *len,
303 unsigned short *reply_port
304 )
305 {
306 kdp_reattach_req_t *rq = &pkt->reattach_req;
307
308 kdp.is_conn = TRUE;
309 kdp_disconnect(pkt, len, reply_port);
310 *reply_port = rq->req_reply_port;
311 reattach_wait = 1;
312 return (TRUE);
313 }
314
315 static boolean_t
316 kdp_hostinfo(
317 kdp_pkt_t *pkt,
318 int *len,
319 unsigned short *reply_port
320 )
321 {
322 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req;
323 size_t plen = *len;
324 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
325
326 if (plen < sizeof (*rq))
327 return (FALSE);
328
329 dprintf(("kdp_hostinfo\n"));
330
331 rp->hdr.is_reply = 1;
332 rp->hdr.len = sizeof (*rp);
333
334 kdp_machine_hostinfo(&rp->hostinfo);
335
336 *reply_port = kdp.reply_port;
337 *len = rp->hdr.len;
338
339 return (TRUE);
340 }
341
342 static boolean_t
343 kdp_kernelversion(
344 kdp_pkt_t *pkt,
345 int *len,
346 unsigned short *reply_port
347 )
348 {
349 kdp_kernelversion_req_t *rq = &pkt->kernelversion_req;
350 size_t plen = *len;
351 kdp_kernelversion_reply_t *rp = &pkt->kernelversion_reply;
352 size_t slen;
353
354 if (plen < sizeof (*rq))
355 return (FALSE);
356
357 rp->hdr.is_reply = 1;
358 rp->hdr.len = sizeof (*rp);
359
360 dprintf(("kdp_kernelversion\n"));
361 slen = strlcpy(rp->version, version, MAX_KDP_DATA_SIZE);
362
363 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */
364
365 *reply_port = kdp.reply_port;
366 *len = rp->hdr.len;
367
368 return (TRUE);
369 }
370
371 static boolean_t
372 kdp_suspend(
373 kdp_pkt_t *pkt,
374 int *len,
375 unsigned short *reply_port
376 )
377 {
378 kdp_suspend_req_t *rq = &pkt->suspend_req;
379 size_t plen = *len;
380 kdp_suspend_reply_t *rp = &pkt->suspend_reply;
381
382 if (plen < sizeof (*rq))
383 return (FALSE);
384
385 rp->hdr.is_reply = 1;
386 rp->hdr.len = sizeof (*rp);
387
388 dprintf(("kdp_suspend\n"));
389
390 kdp.is_halted = TRUE;
391
392 *reply_port = kdp.reply_port;
393 *len = rp->hdr.len;
394
395 return (TRUE);
396 }
397
398 static boolean_t
399 kdp_resumecpus(
400 kdp_pkt_t *pkt,
401 int *len,
402 unsigned short *reply_port
403 )
404 {
405 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req;
406 size_t plen = *len;
407 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply;
408
409 if (plen < sizeof (*rq))
410 return (FALSE);
411
412 rp->hdr.is_reply = 1;
413 rp->hdr.len = sizeof (*rp);
414
415 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask));
416
417 kdp.is_halted = FALSE;
418
419 *reply_port = kdp.reply_port;
420 *len = rp->hdr.len;
421
422 return (TRUE);
423 }
424
425 static boolean_t
426 kdp_writemem(
427 kdp_pkt_t *pkt,
428 int *len,
429 unsigned short *reply_port
430 )
431 {
432 kdp_writemem_req_t *rq = &pkt->writemem_req;
433 size_t plen = *len;
434 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
435 mach_vm_size_t cnt;
436
437 if (plen < sizeof (*rq))
438 return (FALSE);
439
440 if (rq->nbytes > MAX_KDP_DATA_SIZE)
441 rp->error = KDPERR_BAD_NBYTES;
442 else {
443 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes));
444
445 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes);
446 rp->error = KDPERR_NO_ERROR;
447 }
448
449 rp->hdr.is_reply = 1;
450 rp->hdr.len = sizeof (*rp);
451
452 *reply_port = kdp.reply_port;
453 *len = rp->hdr.len;
454
455 return (TRUE);
456 }
457
458 static boolean_t
459 kdp_writemem64(
460 kdp_pkt_t *pkt,
461 int *len,
462 unsigned short *reply_port
463 )
464 {
465 kdp_writemem64_req_t *rq = &pkt->writemem64_req;
466 size_t plen = *len;
467 kdp_writemem64_reply_t *rp = &pkt->writemem64_reply;
468 mach_vm_size_t cnt;
469
470 if (plen < sizeof (*rq))
471 return (FALSE);
472
473 if (rq->nbytes > MAX_KDP_DATA_SIZE)
474 rp->error = KDPERR_BAD_NBYTES;
475 else {
476 dprintf(("kdp_writemem64 addr %llx size %d\n", rq->address, rq->nbytes));
477
478 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, (mach_vm_size_t)rq->nbytes);
479 rp->error = KDPERR_NO_ERROR;
480 }
481
482 rp->hdr.is_reply = 1;
483 rp->hdr.len = sizeof (*rp);
484
485 *reply_port = kdp.reply_port;
486 *len = rp->hdr.len;
487
488 return (TRUE);
489 }
490
491 static boolean_t
492 kdp_writephysmem64(
493 kdp_pkt_t *pkt,
494 int *len,
495 unsigned short *reply_port
496 )
497 {
498 kdp_writephysmem64_req_t *rq = &pkt->writephysmem64_req;
499 size_t plen = *len;
500 kdp_writephysmem64_reply_t *rp = &pkt->writephysmem64_reply;
501
502 if (plen < sizeof (*rq))
503 return (FALSE);
504
505 if (rq->nbytes > MAX_KDP_DATA_SIZE)
506 rp->error = KDPERR_BAD_NBYTES;
507 else {
508 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq->address, rq->nbytes));
509 kdp_machine_phys_write(rq, rq->data, rq->lcpu);
510 rp->error = KDPERR_NO_ERROR;
511 }
512
513 rp->hdr.is_reply = 1;
514 rp->hdr.len = sizeof (*rp);
515
516 *reply_port = kdp.reply_port;
517 *len = rp->hdr.len;
518
519 return (TRUE);
520 }
521
522 static boolean_t
523 kdp_readmem(
524 kdp_pkt_t *pkt,
525 int *len,
526 unsigned short *reply_port
527 )
528 {
529 kdp_readmem_req_t *rq = &pkt->readmem_req;
530 size_t plen = *len;
531 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
532 mach_vm_size_t cnt;
533 #if __i386__ || __arm__
534 void *pversion = &version;
535 #endif
536
537 if (plen < sizeof (*rq))
538 return (FALSE);
539
540 rp->hdr.is_reply = 1;
541 rp->hdr.len = sizeof (*rp);
542
543 if (rq->nbytes > MAX_KDP_DATA_SIZE)
544 rp->error = KDPERR_BAD_NBYTES;
545 else {
546 unsigned int n = rq->nbytes;
547
548 dprintf(("kdp_readmem addr %x size %d\n", rq->address, n));
549 #if __i386__ || __arm__
550 /* XXX This is a hack to facilitate the "showversion" macro
551 * on i386/ARM, which is used to obtain the kernel version without
552 * symbols - a pointer to the version string should eventually
553 * be pinned at a fixed address when an equivalent of the
554 * VECTORS segment (loaded at a fixed load address, and contains
555 * a table) is implemented on these architectures, as with PPC.
556 * N.B.: x86 now has a low global page, and the version indirection
557 * is pinned at 0x201C. We retain the 0x501C address override
558 * for compatibility. Future architectures should instead use
559 * the KDP_KERNELVERSION request.
560 */
561 if (rq->address == 0x501C)
562 rq->address = (uintptr_t)&pversion;
563 #endif
564 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, n);
565 rp->error = KDPERR_NO_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
576 static boolean_t
577 kdp_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
588 if (plen < sizeof (*rq))
589 return (FALSE);
590
591 rp->hdr.is_reply = 1;
592 rp->hdr.len = sizeof (*rp);
593
594 if (rq->nbytes > MAX_KDP_DATA_SIZE)
595 rp->error = KDPERR_BAD_NBYTES;
596 else {
597
598 dprintf(("kdp_readmem64 addr %llx size %d\n", rq->address, rq->nbytes));
599
600 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
601 rp->error = KDPERR_NO_ERROR;
602
603 rp->hdr.len += cnt;
604 }
605
606 *reply_port = kdp.reply_port;
607 *len = rp->hdr.len;
608
609 return (TRUE);
610 }
611
612 static boolean_t
613 kdp_readphysmem64(
614 kdp_pkt_t *pkt,
615 int *len,
616 unsigned short *reply_port
617 )
618 {
619 kdp_readphysmem64_req_t *rq = &pkt->readphysmem64_req;
620 size_t plen = *len;
621 kdp_readphysmem64_reply_t *rp = &pkt->readphysmem64_reply;
622 int cnt;
623
624 if (plen < sizeof (*rq))
625 return (FALSE);
626
627 rp->hdr.is_reply = 1;
628 rp->hdr.len = sizeof (*rp);
629
630 if (rq->nbytes > MAX_KDP_DATA_SIZE)
631 rp->error = KDPERR_BAD_NBYTES;
632 else {
633
634 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq->address, rq->nbytes));
635
636 cnt = (int)kdp_machine_phys_read(rq, rp->data, rq->lcpu);
637 rp->error = KDPERR_NO_ERROR;
638
639 rp->hdr.len += cnt;
640 }
641
642 *reply_port = kdp.reply_port;
643 *len = rp->hdr.len;
644
645 return (TRUE);
646 }
647
648 static boolean_t
649 kdp_maxbytes(
650 kdp_pkt_t *pkt,
651 int *len,
652 unsigned short *reply_port
653 )
654 {
655 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req;
656 size_t plen = *len;
657 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply;
658
659 if (plen < sizeof (*rq))
660 return (FALSE);
661
662 rp->hdr.is_reply = 1;
663 rp->hdr.len = sizeof (*rp);
664
665 dprintf(("kdp_maxbytes\n"));
666
667 rp->max_bytes = MAX_KDP_DATA_SIZE;
668
669 *reply_port = kdp.reply_port;
670 *len = rp->hdr.len;
671
672 return (TRUE);
673 }
674
675 static boolean_t
676 kdp_version(
677 kdp_pkt_t *pkt,
678 int *len,
679 unsigned short *reply_port
680 )
681 {
682 kdp_version_req_t *rq = &pkt->version_req;
683 size_t plen = *len;
684 kdp_version_reply_t *rp = &pkt->version_reply;
685
686 if (plen < sizeof (*rq))
687 return (FALSE);
688
689 rp->hdr.is_reply = 1;
690 rp->hdr.len = sizeof (*rp);
691
692 dprintf(("kdp_version\n"));
693
694 rp->version = KDP_VERSION;
695 if (!(kdp_flag & KDP_BP_DIS))
696 rp->feature = KDP_FEATURE_BP;
697 else
698 rp->feature = 0;
699
700 *reply_port = kdp.reply_port;
701 *len = rp->hdr.len;
702
703 return (TRUE);
704 }
705
706 static boolean_t
707 kdp_regions(
708 kdp_pkt_t *pkt,
709 int *len,
710 unsigned short *reply_port
711 )
712 {
713 kdp_regions_req_t *rq = &pkt->regions_req;
714 size_t plen = *len;
715 kdp_regions_reply_t *rp = &pkt->regions_reply;
716 kdp_region_t *r;
717
718 if (plen < sizeof (*rq))
719 return (FALSE);
720
721 rp->hdr.is_reply = 1;
722 rp->hdr.len = sizeof (*rp);
723
724 dprintf(("kdp_regions\n"));
725
726 r = rp->regions;
727 rp->nregions = 0;
728
729 r->address = 0;
730 r->nbytes = 0xffffffff;
731
732 r->protection = VM_PROT_ALL; r++; rp->nregions++;
733
734 rp->hdr.len += rp->nregions * sizeof (kdp_region_t);
735
736 *reply_port = kdp.reply_port;
737 *len = rp->hdr.len;
738
739 return (TRUE);
740 }
741
742 static boolean_t
743 kdp_writeregs(
744 kdp_pkt_t *pkt,
745 int *len,
746 unsigned short *reply_port
747 )
748 {
749 kdp_writeregs_req_t *rq = &pkt->writeregs_req;
750 size_t plen = *len;
751 int size;
752 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
753
754 if (plen < sizeof (*rq))
755 return (FALSE);
756
757 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int);
758 rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size);
759
760 rp->hdr.is_reply = 1;
761 rp->hdr.len = sizeof (*rp);
762
763 *reply_port = kdp.reply_port;
764 *len = rp->hdr.len;
765
766 return (TRUE);
767 }
768
769 static boolean_t
770 kdp_readregs(
771 kdp_pkt_t *pkt,
772 int *len,
773 unsigned short *reply_port
774 )
775 {
776 kdp_readregs_req_t *rq = &pkt->readregs_req;
777 size_t plen = *len;
778 kdp_readregs_reply_t *rp = &pkt->readregs_reply;
779 int size;
780
781 if (plen < sizeof (*rq))
782 return (FALSE);
783
784 rp->hdr.is_reply = 1;
785 rp->hdr.len = sizeof (*rp);
786
787 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size);
788 rp->hdr.len += size;
789
790 *reply_port = kdp.reply_port;
791 *len = rp->hdr.len;
792
793 return (TRUE);
794 }
795
796
797 boolean_t
798 kdp_breakpoint_set(
799 kdp_pkt_t *pkt,
800 int *len,
801 unsigned short *reply_port
802 )
803 {
804 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
805 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
806 size_t plen = *len;
807 kdp_error_t kerr;
808
809 if (plen < sizeof (*rq))
810 return (FALSE);
811
812 dprintf(("kdp_breakpoint_set %x\n", rq->address));
813
814 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
815
816 rp->error = kerr;
817
818 rp->hdr.is_reply = 1;
819 rp->hdr.len = sizeof (*rp);
820 *reply_port = kdp.reply_port;
821 *len = rp->hdr.len;
822
823 return (TRUE);
824 }
825
826 boolean_t
827 kdp_breakpoint64_set(
828 kdp_pkt_t *pkt,
829 int *len,
830 unsigned short *reply_port
831 )
832 {
833 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
834 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
835 size_t plen = *len;
836 kdp_error_t kerr;
837
838 if (plen < sizeof (*rq))
839 return (FALSE);
840
841 dprintf(("kdp_breakpoint64_set %llx\n", rq->address));
842
843 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
844
845 rp->error = kerr;
846
847 rp->hdr.is_reply = 1;
848 rp->hdr.len = sizeof (*rp);
849 *reply_port = kdp.reply_port;
850 *len = rp->hdr.len;
851
852 return (TRUE);
853 }
854
855 boolean_t
856 kdp_breakpoint_remove(
857 kdp_pkt_t *pkt,
858 int *len,
859 unsigned short *reply_port
860 )
861 {
862 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
863 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
864 size_t plen = *len;
865 kdp_error_t kerr;
866 if (plen < sizeof (*rq))
867 return (FALSE);
868
869 dprintf(("kdp_breakpoint_remove %x\n", rq->address));
870
871 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
872
873 rp->error = kerr;
874
875 rp->hdr.is_reply = 1;
876 rp->hdr.len = sizeof (*rp);
877 *reply_port = kdp.reply_port;
878 *len = rp->hdr.len;
879
880 return (TRUE);
881 }
882
883 boolean_t
884 kdp_breakpoint64_remove(
885 kdp_pkt_t *pkt,
886 int *len,
887 unsigned short *reply_port
888 )
889 {
890 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
891 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
892 size_t plen = *len;
893 kdp_error_t kerr;
894
895 if (plen < sizeof (*rq))
896 return (FALSE);
897
898 dprintf(("kdp_breakpoint64_remove %llx\n", rq->address));
899
900 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
901
902 rp->error = kerr;
903
904 rp->hdr.is_reply = 1;
905 rp->hdr.len = sizeof (*rp);
906 *reply_port = kdp.reply_port;
907 *len = rp->hdr.len;
908
909 return (TRUE);
910 }
911
912
913 kdp_error_t
914 kdp_set_breakpoint_internal(
915 mach_vm_address_t address
916 )
917 {
918
919 uint8_t breakinstr[MAX_BREAKINSN_BYTES], oldinstr[MAX_BREAKINSN_BYTES];
920 uint32_t breakinstrsize = sizeof(breakinstr);
921 mach_vm_size_t cnt;
922 int i;
923
924 kdp_machine_get_breakinsn(breakinstr, &breakinstrsize);
925
926 if(breakpoints_initialized == 0)
927 {
928 for(i=0;(i < MAX_BREAKPOINTS); breakpoint_list[i].address=0, i++);
929 breakpoints_initialized++;
930 }
931
932 cnt = kdp_machine_vm_read(address, (caddr_t)&oldinstr, (mach_vm_size_t)breakinstrsize);
933
934 if (0 == memcmp(oldinstr, breakinstr, breakinstrsize)) {
935 printf("A trap was already set at that address, not setting new breakpoint\n");
936
937 return KDPERR_BREAKPOINT_ALREADY_SET;
938 }
939
940 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++);
941
942 if (i == MAX_BREAKPOINTS) {
943 return KDPERR_MAX_BREAKPOINTS;
944 }
945
946 breakpoint_list[i].address = address;
947 memcpy(breakpoint_list[i].oldbytes, oldinstr, breakinstrsize);
948 breakpoint_list[i].bytesused = breakinstrsize;
949
950 cnt = kdp_machine_vm_write((caddr_t)&breakinstr, address, breakinstrsize);
951
952 return KDPERR_NO_ERROR;
953 }
954
955 kdp_error_t
956 kdp_remove_breakpoint_internal(
957 mach_vm_address_t address
958 )
959 {
960 mach_vm_size_t cnt;
961 int i;
962
963 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != address); i++);
964
965 if (i == MAX_BREAKPOINTS)
966 {
967 return KDPERR_BREAKPOINT_NOT_FOUND;
968 }
969
970 breakpoint_list[i].address = 0;
971 cnt = kdp_machine_vm_write((caddr_t)&breakpoint_list[i].oldbytes, address, breakpoint_list[i].bytesused);
972
973 return KDPERR_NO_ERROR;
974 }
975
976 boolean_t
977 kdp_remove_all_breakpoints(void)
978 {
979 int i;
980 boolean_t breakpoint_found = FALSE;
981
982 if (breakpoints_initialized)
983 {
984 for(i=0;i < MAX_BREAKPOINTS; i++)
985 {
986 if (breakpoint_list[i].address)
987 {
988 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);
989 breakpoint_found = TRUE;
990 breakpoint_list[i].address = 0;
991 }
992 }
993
994 if (breakpoint_found)
995 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
996 }
997 return breakpoint_found;
998 }
999
1000 boolean_t
1001 kdp_reboot(
1002 __unused kdp_pkt_t *pkt,
1003 __unused int *len,
1004 __unused unsigned short *reply_port
1005 )
1006 {
1007 dprintf(("kdp_reboot\n"));
1008
1009 kdp_machine_reboot();
1010
1011 return (TRUE); // no, not really, we won't return
1012 }
1013
1014 #define MAX_FRAMES 1000
1015
1016 static int pid_from_task(task_t task)
1017 {
1018 int pid = -1;
1019
1020 if (task->bsd_info)
1021 pid = proc_pid(task->bsd_info);
1022
1023 return pid;
1024 }
1025
1026 boolean_t
1027 kdp_copyin(pmap_t p, uint64_t uaddr, void *dest, size_t size) {
1028 size_t rem = size;
1029 char *kvaddr = dest;
1030
1031 while (rem) {
1032 ppnum_t upn = pmap_find_phys(p, uaddr);
1033 uint64_t phys_src = (upn << PAGE_SHIFT) | (uaddr & PAGE_MASK);
1034 uint64_t phys_dest = kvtophys((vm_offset_t)kvaddr);
1035 uint64_t src_rem = PAGE_SIZE - (phys_src & PAGE_MASK);
1036 uint64_t dst_rem = PAGE_SIZE - (phys_dest & PAGE_MASK);
1037 size_t cur_size = (uint32_t) MIN(src_rem, dst_rem);
1038 cur_size = MIN(cur_size, rem);
1039
1040 if (upn && pmap_valid_page(upn) && phys_dest) {
1041 bcopy_phys(phys_src, phys_dest, cur_size);
1042 }
1043 else
1044 break;
1045 uaddr += cur_size;
1046 kvaddr += cur_size;
1047 rem -= cur_size;
1048 }
1049 return (rem == 0);
1050 }
1051
1052 int
1053 kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size, unsigned trace_options, uint32_t *pbytesTraced)
1054 {
1055 char *tracepos = (char *) tracebuf;
1056 char *tracebound = tracepos + tracebuf_size;
1057 uint32_t tracebytes = 0;
1058 int error = 0;
1059
1060 task_t task = TASK_NULL;
1061 thread_t thread = THREAD_NULL;
1062 int nframes = trace_options;
1063 thread_snapshot_t tsnap = NULL;
1064 unsigned framesize = 2 * sizeof(vm_offset_t);
1065 boolean_t dispatch_p = ((trace_options & STACKSHOT_GET_DQ) != 0);
1066 uint16_t dispatch_offset = (trace_options & STACKSHOT_DISPATCH_OFFSET_MASK) >> STACKSHOT_DISPATCH_OFFSET_SHIFT;
1067 struct task ctask;
1068 struct thread cthread;
1069
1070 if ((nframes <= 0) || nframes > MAX_FRAMES)
1071 nframes = MAX_FRAMES;
1072
1073 queue_iterate(&tasks, task, task_t, tasks) {
1074 if ((task == NULL) || (ml_nofault_copy((vm_offset_t) task, (vm_offset_t) &ctask, sizeof(struct task)) != sizeof(struct task)))
1075 goto error_exit;
1076 /* Trace everything, unless a process was specified */
1077 if ((pid == -1) || (pid == pid_from_task(task)))
1078 queue_iterate(&task->threads, thread, thread_t, task_threads){
1079 if ((thread == NULL) || (ml_nofault_copy((vm_offset_t) thread, (vm_offset_t) &cthread, sizeof(struct thread)) != sizeof(struct thread)))
1080 goto error_exit;
1081 if (((tracepos + 4 * sizeof(struct thread_snapshot)) > tracebound)) {
1082 error = -1;
1083 goto error_exit;
1084 }
1085 /* Populate the thread snapshot header */
1086 tsnap = (thread_snapshot_t) tracepos;
1087 tsnap->thread_id = (uint64_t) (uintptr_t)thread;
1088 tsnap->state = thread->state;
1089 tsnap->wait_event = thread->wait_event;
1090 tsnap->continuation = (uint64_t) (uintptr_t) thread->continuation;
1091 /* Add the BSD process identifiers */
1092 if ((tsnap->pid = pid_from_task(task)) != -1)
1093 proc_name_kdp(task, tsnap->p_comm, sizeof(tsnap->p_comm));
1094 else
1095 tsnap->p_comm[0] = '\0';
1096
1097 tsnap->snapshot_magic = 0xfeedface;
1098 tracepos += sizeof(struct thread_snapshot);
1099 tsnap->ss_flags = 0;
1100
1101 if (dispatch_p && (task != kernel_task) && (task->active) && (task->map)) {
1102 uint64_t dqkeyaddr = thread_dispatchqaddr(thread);
1103 if (dqkeyaddr != 0) {
1104 boolean_t task64 = task_has_64BitAddr(task);
1105 uint64_t dqaddr = 0;
1106 if (kdp_copyin(task->map->pmap, dqkeyaddr, &dqaddr, (task64 ? 8 : 4)) && (dqaddr != 0)) {
1107 uint64_t dqserialnumaddr = dqaddr + dispatch_offset;
1108 uint64_t dqserialnum = 0;
1109 if (kdp_copyin(task->map->pmap, dqserialnumaddr, &dqserialnum, (task64 ? 8 : 4))) {
1110 tsnap->ss_flags |= kHasDispatchSerial;
1111 *(uint64_t *)tracepos = dqserialnum;
1112 tracepos += 8;
1113 }
1114 }
1115 }
1116 }
1117 /* Call through to the machine specific trace routines
1118 * Frames are added past the snapshot header.
1119 */
1120 if (thread->kernel_stack != 0) {
1121 #if defined(__LP64__)
1122 tracebytes = machine_trace_thread64(thread, tracepos, tracebound, nframes, FALSE);
1123 tsnap->ss_flags |= kKernel64_p;
1124 framesize = 16;
1125 #else
1126 tracebytes = machine_trace_thread(thread, tracepos, tracebound, nframes, FALSE);
1127 framesize = 8;
1128 #endif
1129 }
1130 tsnap->nkern_frames = tracebytes/framesize;
1131 tracepos += tracebytes;
1132 tracebytes = 0;
1133 /* Trace user stack, if any */
1134 if (thread->task->map != kernel_map) {
1135 /* 64-bit task? */
1136 if (task_has_64BitAddr(thread->task)) {
1137 tracebytes = machine_trace_thread64(thread, tracepos, tracebound, nframes, TRUE);
1138 tsnap->ss_flags |= kUser64_p;
1139 framesize = 16;
1140 }
1141 else {
1142 tracebytes = machine_trace_thread(thread, tracepos, tracebound, nframes, TRUE);
1143 framesize = 8;
1144 }
1145 }
1146 tsnap->nuser_frames = tracebytes/framesize;
1147 tracepos += tracebytes;
1148 tracebytes = 0;
1149 }
1150 }
1151
1152 error_exit:
1153 /* Release stack snapshot wait indicator */
1154 kdp_snapshot_postflight();
1155
1156 *pbytesTraced = (uint32_t)(tracepos - (char *) tracebuf);
1157
1158 return error;
1159 }
1160
1161 static boolean_t
1162 kdp_readioport(kdp_pkt_t *pkt,
1163 int *len,
1164 unsigned short *reply_port
1165 )
1166 {
1167 kdp_readioport_req_t *rq = &pkt->readioport_req;
1168 kdp_readioport_reply_t *rp = &pkt->readioport_reply;
1169 size_t plen = *len;
1170
1171 if (plen < sizeof (*rq))
1172 return (FALSE);
1173
1174 rp->hdr.is_reply = 1;
1175 rp->hdr.len = sizeof (*rp);
1176
1177 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1178 rp->error = KDPERR_BAD_NBYTES;
1179 else {
1180 #if KDP_TEST_HARNESS
1181 uint16_t addr = rq->address;
1182 #endif
1183 uint16_t size = rq->nbytes;
1184 dprintf(("kdp_readioport addr %x size %d\n", addr, size));
1185
1186 rp->error = kdp_machine_ioport_read(rq, rp->data, rq->lcpu);
1187 if (rp->error == KDPERR_NO_ERROR)
1188 rp->hdr.len += size;
1189 }
1190
1191 *reply_port = kdp.reply_port;
1192 *len = rp->hdr.len;
1193
1194 return (TRUE);
1195 }
1196
1197 static boolean_t
1198 kdp_writeioport(
1199 kdp_pkt_t *pkt,
1200 int *len,
1201 unsigned short *reply_port
1202 )
1203 {
1204 kdp_writeioport_req_t *rq = &pkt->writeioport_req;
1205 kdp_writeioport_reply_t *rp = &pkt->writeioport_reply;
1206 size_t plen = *len;
1207
1208 if (plen < sizeof (*rq))
1209 return (FALSE);
1210
1211 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1212 rp->error = KDPERR_BAD_NBYTES;
1213 else {
1214 dprintf(("kdp_writeioport addr %x size %d\n", rq->address,
1215 rq->nbytes));
1216
1217 rp->error = kdp_machine_ioport_write(rq, rq->data, rq->lcpu);
1218 }
1219
1220 rp->hdr.is_reply = 1;
1221 rp->hdr.len = sizeof (*rp);
1222
1223 *reply_port = kdp.reply_port;
1224 *len = rp->hdr.len;
1225
1226 return (TRUE);
1227 }
1228
1229 static boolean_t
1230 kdp_readmsr64(kdp_pkt_t *pkt,
1231 int *len,
1232 unsigned short *reply_port
1233 )
1234 {
1235 kdp_readmsr64_req_t *rq = &pkt->readmsr64_req;
1236 kdp_readmsr64_reply_t *rp = &pkt->readmsr64_reply;
1237 size_t plen = *len;
1238
1239 if (plen < sizeof (*rq))
1240 return (FALSE);
1241
1242 rp->hdr.is_reply = 1;
1243 rp->hdr.len = sizeof (*rp);
1244
1245 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1246 rp->error = kdp_machine_msr64_read(rq, rp->data, rq->lcpu);
1247 if (rp->error == KDPERR_NO_ERROR)
1248 rp->hdr.len += sizeof(uint64_t);
1249
1250 *reply_port = kdp.reply_port;
1251 *len = rp->hdr.len;
1252
1253 return (TRUE);
1254 }
1255
1256 static boolean_t
1257 kdp_writemsr64(
1258 kdp_pkt_t *pkt,
1259 int *len,
1260 unsigned short *reply_port
1261 )
1262 {
1263 kdp_writemsr64_req_t *rq = &pkt->writemsr64_req;
1264 kdp_writemsr64_reply_t *rp = &pkt->writemsr64_reply;
1265 size_t plen = *len;
1266
1267 if (plen < sizeof (*rq))
1268 return (FALSE);
1269
1270 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1271 rp->error = kdp_machine_msr64_write(rq, rq->data, rq->lcpu);
1272
1273 rp->hdr.is_reply = 1;
1274 rp->hdr.len = sizeof (*rp);
1275
1276 *reply_port = kdp.reply_port;
1277 *len = rp->hdr.len;
1278
1279 return (TRUE);
1280 }