2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include <mach/mach_types.h>
32 #include <kern/debug.h>
34 #include <kdp/kdp_internal.h>
35 #include <kdp/kdp_private.h>
37 #include <libsa/types.h>
39 #include <string.h> /* bcopy */
41 int kdp_vm_read( caddr_t
, caddr_t
, unsigned int);
42 int kdp_vm_write( caddr_t
, caddr_t
, unsigned int);
44 #define DO_ALIGN 1 /* align all packet data accesses */
46 #define KDP_TEST_HARNESS 0
48 #define dprintf(x) kprintf x
54 dispatch_table
[KDP_HOSTREBOOT
- KDP_CONNECT
+1] =
57 /* 1 */ kdp_disconnect
,
64 /* 8 */ kdp_writeregs
,
68 /* C */ kdp_resumecpus
,
71 /* F */ kdp_breakpoint_set
,
72 /*10 */ kdp_breakpoint_remove
,
81 #define MAX_BREAKPOINTS 100
82 #define KDP_MAX_BREAKPOINTS 100
84 #define BREAKPOINT_NOT_FOUND 101
85 #define BREAKPOINT_ALREADY_SET 102
87 #define KDP_VERSION 10
91 unsigned int old_instruction
;
92 } kdp_breakpoint_record_t
;
94 static kdp_breakpoint_record_t breakpoint_list
[MAX_BREAKPOINTS
];
95 static unsigned int breakpoints_initialized
= 0;
97 int reattach_wait
= 0;
98 int noresume_on_disconnect
= 0;
104 unsigned short *reply_port
107 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
108 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
114 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
116 rd
= (kdp_pkt_t
*)pkt
;
118 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
119 printf("kdp_packet bad len pkt %d hdr %d\n", plen
, rd
->hdr
.len
);
124 if (rd
->hdr
.is_reply
) {
125 printf("kdp_packet reply recvd req %x seq %x\n",
126 rd
->hdr
.request
, rd
->hdr
.seq
);
131 req
= rd
->hdr
.request
;
132 if ((req
< KDP_CONNECT
) || (req
> KDP_HOSTREBOOT
)) {
133 printf("kdp_packet bad request %x len %d seq %x key %x\n",
134 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
139 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
141 bcopy((char *)rd
, (char *) pkt
, *len
);
150 unsigned short *reply_port
153 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
155 printf("kdp_unknown request %x len %d seq %x key %x\n",
156 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
165 unsigned short *reply_port
168 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
170 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
172 if (plen
< sizeof (*rq
))
175 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
178 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
179 rp
->error
= KDPERR_NO_ERROR
;
181 rp
->error
= KDPERR_ALREADY_CONNECTED
;
184 kdp
.reply_port
= rq
->req_reply_port
;
185 kdp
.exception_port
= rq
->exc_note_port
;
187 kdp
.conn_seq
= rq
->hdr
.seq
;
189 rp
->error
= KDPERR_NO_ERROR
;
192 rp
->hdr
.is_reply
= 1;
193 rp
->hdr
.len
= sizeof (*rp
);
195 *reply_port
= kdp
.reply_port
;
198 if (current_debugger
== KDP_CUR_DB
)
208 unsigned short *reply_port
211 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
213 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
215 if (plen
< sizeof (*rq
))
221 dprintf(("kdp_disconnect\n"));
223 *reply_port
= kdp
.reply_port
;
225 kdp
.reply_port
= kdp
.exception_port
= 0;
226 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
227 kdp
.exception_seq
= kdp
.conn_seq
= 0;
229 if (noresume_on_disconnect
== 1) {
231 noresume_on_disconnect
= 0;
234 rp
->hdr
.is_reply
= 1;
235 rp
->hdr
.len
= sizeof (*rp
);
239 if (current_debugger
== KDP_CUR_DB
)
249 unsigned short *reply_port
252 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
253 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
256 kdp_disconnect(pkt
, len
, reply_port
);
257 *reply_port
= rq
->req_reply_port
;
266 unsigned short *reply_port
269 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
271 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
273 if (plen
< sizeof (*rq
))
276 rp
->hdr
.is_reply
= 1;
277 rp
->hdr
.len
= sizeof (*rp
);
279 kdp_machine_hostinfo(&rp
->hostinfo
);
281 *reply_port
= kdp
.reply_port
;
291 unsigned short *reply_port
294 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
296 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
298 if (plen
< sizeof (*rq
))
301 rp
->hdr
.is_reply
= 1;
302 rp
->hdr
.len
= sizeof (*rp
);
304 dprintf(("kdp_suspend\n"));
306 kdp
.is_halted
= TRUE
;
308 *reply_port
= kdp
.reply_port
;
318 unsigned short *reply_port
321 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
323 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
325 if (plen
< sizeof (*rq
))
328 rp
->hdr
.is_reply
= 1;
329 rp
->hdr
.len
= sizeof (*rp
);
331 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
333 kdp
.is_halted
= FALSE
;
335 *reply_port
= kdp
.reply_port
;
345 unsigned short *reply_port
348 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
350 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
353 if (plen
< sizeof (*rq
))
356 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
357 rp
->error
= KDPERR_BAD_NBYTES
;
359 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
361 cnt
= kdp_vm_write((caddr_t
)rq
->data
, (caddr_t
)rq
->address
, rq
->nbytes
);
362 rp
->error
= KDPERR_NO_ERROR
;
365 rp
->hdr
.is_reply
= 1;
366 rp
->hdr
.len
= sizeof (*rp
);
368 *reply_port
= kdp
.reply_port
;
378 unsigned short *reply_port
381 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
383 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
386 if (plen
< sizeof (*rq
))
389 rp
->hdr
.is_reply
= 1;
390 rp
->hdr
.len
= sizeof (*rp
);
392 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
393 rp
->error
= KDPERR_BAD_NBYTES
;
395 unsigned int n
= rq
->nbytes
;
397 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, rq
->nbytes
));
399 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
400 rp
->error
= KDPERR_NO_ERROR
;
405 *reply_port
= kdp
.reply_port
;
415 unsigned short *reply_port
418 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
420 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
422 if (plen
< sizeof (*rq
))
425 rp
->hdr
.is_reply
= 1;
426 rp
->hdr
.len
= sizeof (*rp
);
428 dprintf(("kdp_maxbytes\n"));
430 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
432 *reply_port
= kdp
.reply_port
;
442 unsigned short *reply_port
445 kdp_version_req_t
*rq
= &pkt
->version_req
;
447 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
450 if (plen
< sizeof (*rq
))
453 rp
->hdr
.is_reply
= 1;
454 rp
->hdr
.len
= sizeof (*rp
);
456 dprintf(("kdp_version\n"));
458 rp
->version
= KDP_VERSION
;
460 if (!(kdp_flag
& KDP_BP_DIS
))
461 rp
->feature
= KDP_FEATURE_BP
;
468 *reply_port
= kdp
.reply_port
;
478 unsigned short *reply_port
481 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
483 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
486 if (plen
< sizeof (*rq
))
489 rp
->hdr
.is_reply
= 1;
490 rp
->hdr
.len
= sizeof (*rp
);
492 dprintf(("kdp_regions\n"));
497 (vm_offset_t
)r
->address
= 0;
498 r
->nbytes
= 0xffffffff;
500 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
502 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
504 *reply_port
= kdp
.reply_port
;
514 unsigned short *reply_port
517 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
520 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
522 if (plen
< sizeof (*rq
))
525 size
= rq
->hdr
.len
- sizeof(kdp_hdr_t
) - sizeof(unsigned int);
526 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
528 rp
->hdr
.is_reply
= 1;
529 rp
->hdr
.len
= sizeof (*rp
);
531 *reply_port
= kdp
.reply_port
;
541 unsigned short *reply_port
544 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
546 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
549 if (plen
< sizeof (*rq
))
552 rp
->hdr
.is_reply
= 1;
553 rp
->hdr
.len
= sizeof (*rp
);
555 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
558 *reply_port
= kdp
.reply_port
;
568 unsigned short *reply_port
571 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
572 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
575 unsigned int old_instruction
= 0;
576 unsigned int breakinstr
= kdp_ml_get_breakinsn();
578 if(breakpoints_initialized
== 0)
580 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
581 breakpoints_initialized
++;
583 if (plen
< sizeof (*rq
))
585 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)(&old_instruction
), sizeof(int));
587 if (old_instruction
==breakinstr
)
589 printf("A trap was already set at that address, not setting new breakpoint\n");
590 rp
->error
= BREAKPOINT_ALREADY_SET
;
592 rp
->hdr
.is_reply
= 1;
593 rp
->hdr
.len
= sizeof (*rp
);
594 *reply_port
= kdp
.reply_port
;
600 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
602 if (i
== MAX_BREAKPOINTS
)
604 rp
->error
= KDP_MAX_BREAKPOINTS
;
606 rp
->hdr
.is_reply
= 1;
607 rp
->hdr
.len
= sizeof (*rp
);
608 *reply_port
= kdp
.reply_port
;
613 breakpoint_list
[i
].address
= rq
->address
;
614 breakpoint_list
[i
].old_instruction
= old_instruction
;
616 cnt
= kdp_vm_write((caddr_t
)&breakinstr
, (caddr_t
)rq
->address
, sizeof(&breakinstr
));
618 rp
->error
= KDPERR_NO_ERROR
;
619 rp
->hdr
.is_reply
= 1;
620 rp
->hdr
.len
= sizeof (*rp
);
621 *reply_port
= kdp
.reply_port
;
628 kdp_breakpoint_remove(
631 unsigned short *reply_port
634 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
635 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
639 if (plen
< sizeof (*rq
))
642 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= rq
->address
); i
++);
643 if (i
== MAX_BREAKPOINTS
)
645 rp
->error
= BREAKPOINT_NOT_FOUND
;
646 rp
->hdr
.is_reply
= 1;
647 rp
->hdr
.len
= sizeof (*rp
);
648 *reply_port
= kdp
.reply_port
;
651 return (TRUE
); /* Check if it needs to be FALSE in case of error */
654 breakpoint_list
[i
].address
= 0;
655 cnt
= kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)rq
->address
, sizeof(int));
656 rp
->error
= KDPERR_NO_ERROR
;
657 rp
->hdr
.is_reply
= 1;
658 rp
->hdr
.len
= sizeof (*rp
);
659 *reply_port
= kdp
.reply_port
;
666 kdp_remove_all_breakpoints()
669 boolean_t breakpoint_found
= FALSE
;
671 if (breakpoints_initialized
)
673 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
675 if (breakpoint_list
[i
].address
)
677 kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)breakpoint_list
[i
].address
, sizeof(int));
678 breakpoint_found
= TRUE
;
679 breakpoint_list
[i
].address
= 0;
682 if (breakpoint_found
)
683 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
685 return breakpoint_found
;