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