2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <mach/mach_types.h>
27 #include <kern/debug.h>
29 #include <kdp/kdp_internal.h>
30 #include <kdp/kdp_private.h>
32 #include <libsa/types.h>
34 int kdp_vm_read( caddr_t
, caddr_t
, unsigned int);
35 int kdp_vm_write( caddr_t
, caddr_t
, unsigned int);
37 #define DO_ALIGN 1 /* align all packet data accesses */
39 #define KDP_TEST_HARNESS 0
41 #define dprintf(x) kprintf x
47 dispatch_table
[KDP_REATTACH
- KDP_CONNECT
+1] =
50 /* 1 */ kdp_disconnect
,
57 /* 8 */ kdp_writeregs
,
61 /* C */ kdp_resumecpus
,
64 /* F */ kdp_breakpoint_set
,
65 /*10 */ kdp_breakpoint_remove
,
73 #define MAX_BREAKPOINTS 100
74 #define KDP_MAX_BREAKPOINTS 100
76 #define BREAKPOINT_NOT_FOUND 101
77 #define BREAKPOINT_ALREADY_SET 102
79 #define KDP_VERSION 10
83 unsigned int old_instruction
;
84 } kdp_breakpoint_record_t
;
86 static kdp_breakpoint_record_t breakpoint_list
[MAX_BREAKPOINTS
];
87 static unsigned int breakpoints_initialized
= 0;
89 int reattach_wait
= 0;
90 int noresume_on_disconnect
= 0;
96 unsigned short *reply_port
99 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
100 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
106 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
108 rd
= (kdp_pkt_t
*)pkt
;
110 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
111 printf("kdp_packet bad len pkt %d hdr %d\n", plen
, rd
->hdr
.len
);
116 if (rd
->hdr
.is_reply
) {
117 printf("kdp_packet reply recvd req %x seq %x\n",
118 rd
->hdr
.request
, rd
->hdr
.seq
);
123 req
= rd
->hdr
.request
;
124 if ((req
< KDP_CONNECT
) || (req
> KDP_REATTACH
)) {
125 printf("kdp_packet bad request %x len %d seq %x key %x\n",
126 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
131 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
133 bcopy((char *)rd
, (char *) pkt
, *len
);
142 unsigned short *reply_port
145 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
147 printf("kdp_unknown request %x len %d seq %x key %x\n",
148 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
157 unsigned short *reply_port
160 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
162 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
164 if (plen
< sizeof (*rq
))
167 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
170 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
171 rp
->error
= KDPERR_NO_ERROR
;
173 rp
->error
= KDPERR_ALREADY_CONNECTED
;
176 kdp
.reply_port
= rq
->req_reply_port
;
177 kdp
.exception_port
= rq
->exc_note_port
;
179 kdp
.conn_seq
= rq
->hdr
.seq
;
181 rp
->error
= KDPERR_NO_ERROR
;
184 rp
->hdr
.is_reply
= 1;
185 rp
->hdr
.len
= sizeof (*rp
);
187 *reply_port
= kdp
.reply_port
;
190 if (current_debugger
== KDP_CUR_DB
)
200 unsigned short *reply_port
203 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
205 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
207 if (plen
< sizeof (*rq
))
213 dprintf(("kdp_disconnect\n"));
215 *reply_port
= kdp
.reply_port
;
217 kdp
.reply_port
= kdp
.exception_port
= 0;
218 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
219 kdp
.exception_seq
= kdp
.conn_seq
= 0;
221 if (noresume_on_disconnect
== 1) {
223 noresume_on_disconnect
= 0;
226 rp
->hdr
.is_reply
= 1;
227 rp
->hdr
.len
= sizeof (*rp
);
231 if (current_debugger
== KDP_CUR_DB
)
241 unsigned short *reply_port
244 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
245 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
248 kdp_disconnect(pkt
, len
, reply_port
);
249 *reply_port
= rq
->req_reply_port
;
258 unsigned short *reply_port
261 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
263 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
265 if (plen
< sizeof (*rq
))
268 rp
->hdr
.is_reply
= 1;
269 rp
->hdr
.len
= sizeof (*rp
);
271 kdp_machine_hostinfo(&rp
->hostinfo
);
273 *reply_port
= kdp
.reply_port
;
283 unsigned short *reply_port
286 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
288 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
290 if (plen
< sizeof (*rq
))
293 rp
->hdr
.is_reply
= 1;
294 rp
->hdr
.len
= sizeof (*rp
);
296 dprintf(("kdp_suspend\n"));
298 kdp
.is_halted
= TRUE
;
300 *reply_port
= kdp
.reply_port
;
310 unsigned short *reply_port
313 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
315 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
317 if (plen
< sizeof (*rq
))
320 rp
->hdr
.is_reply
= 1;
321 rp
->hdr
.len
= sizeof (*rp
);
323 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
325 kdp
.is_halted
= FALSE
;
327 *reply_port
= kdp
.reply_port
;
337 unsigned short *reply_port
340 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
342 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
345 if (plen
< sizeof (*rq
))
348 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
349 rp
->error
= KDPERR_BAD_NBYTES
;
351 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
353 cnt
= kdp_vm_write((caddr_t
)rq
->data
, (caddr_t
)rq
->address
, rq
->nbytes
);
354 rp
->error
= KDPERR_NO_ERROR
;
357 rp
->hdr
.is_reply
= 1;
358 rp
->hdr
.len
= sizeof (*rp
);
360 *reply_port
= kdp
.reply_port
;
370 unsigned short *reply_port
373 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
375 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
378 if (plen
< sizeof (*rq
))
381 rp
->hdr
.is_reply
= 1;
382 rp
->hdr
.len
= sizeof (*rp
);
384 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
385 rp
->error
= KDPERR_BAD_NBYTES
;
387 unsigned int n
= rq
->nbytes
;
389 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, rq
->nbytes
));
391 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
392 rp
->error
= KDPERR_NO_ERROR
;
397 *reply_port
= kdp
.reply_port
;
407 unsigned short *reply_port
410 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
412 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
414 if (plen
< sizeof (*rq
))
417 rp
->hdr
.is_reply
= 1;
418 rp
->hdr
.len
= sizeof (*rp
);
420 dprintf(("kdp_maxbytes\n"));
422 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
424 *reply_port
= kdp
.reply_port
;
434 unsigned short *reply_port
437 kdp_version_req_t
*rq
= &pkt
->version_req
;
439 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
442 if (plen
< sizeof (*rq
))
445 rp
->hdr
.is_reply
= 1;
446 rp
->hdr
.len
= sizeof (*rp
);
448 dprintf(("kdp_version\n"));
450 rp
->version
= KDP_VERSION
;
452 if (!(kdp_flag
& KDP_BP_DIS
))
453 rp
->feature
= KDP_FEATURE_BP
;
460 *reply_port
= kdp
.reply_port
;
470 unsigned short *reply_port
473 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
475 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
478 if (plen
< sizeof (*rq
))
481 rp
->hdr
.is_reply
= 1;
482 rp
->hdr
.len
= sizeof (*rp
);
484 dprintf(("kdp_regions\n"));
489 (vm_offset_t
)r
->address
= 0;
490 r
->nbytes
= 0xffffffff;
492 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
494 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
496 *reply_port
= kdp
.reply_port
;
506 unsigned short *reply_port
509 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
512 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
514 if (plen
< sizeof (*rq
))
517 size
= rq
->hdr
.len
- sizeof(kdp_hdr_t
) - sizeof(unsigned int);
518 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
520 rp
->hdr
.is_reply
= 1;
521 rp
->hdr
.len
= sizeof (*rp
);
523 *reply_port
= kdp
.reply_port
;
533 unsigned short *reply_port
536 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
538 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
541 if (plen
< sizeof (*rq
))
544 rp
->hdr
.is_reply
= 1;
545 rp
->hdr
.len
= sizeof (*rp
);
547 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
550 *reply_port
= kdp
.reply_port
;
560 unsigned short *reply_port
563 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
564 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
567 unsigned int old_instruction
= 0;
568 unsigned int breakinstr
= kdp_ml_get_breakinsn();
570 if(breakpoints_initialized
== 0)
572 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
573 breakpoints_initialized
++;
575 if (plen
< sizeof (*rq
))
577 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)(&old_instruction
), sizeof(int));
579 if (old_instruction
==breakinstr
)
581 printf("A trap was already set at that address, not setting new breakpoint\n");
582 rp
->error
= BREAKPOINT_ALREADY_SET
;
584 rp
->hdr
.is_reply
= 1;
585 rp
->hdr
.len
= sizeof (*rp
);
586 *reply_port
= kdp
.reply_port
;
592 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
594 if (i
== MAX_BREAKPOINTS
)
596 rp
->error
= KDP_MAX_BREAKPOINTS
;
598 rp
->hdr
.is_reply
= 1;
599 rp
->hdr
.len
= sizeof (*rp
);
600 *reply_port
= kdp
.reply_port
;
605 breakpoint_list
[i
].address
= rq
->address
;
606 breakpoint_list
[i
].old_instruction
= old_instruction
;
608 cnt
= kdp_vm_write((caddr_t
)&breakinstr
, (caddr_t
)rq
->address
, sizeof(&breakinstr
));
610 rp
->error
= KDPERR_NO_ERROR
;
611 rp
->hdr
.is_reply
= 1;
612 rp
->hdr
.len
= sizeof (*rp
);
613 *reply_port
= kdp
.reply_port
;
620 kdp_breakpoint_remove(
623 unsigned short *reply_port
626 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
627 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
631 if (plen
< sizeof (*rq
))
634 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= rq
->address
); i
++);
635 if (i
== MAX_BREAKPOINTS
)
637 rp
->error
= BREAKPOINT_NOT_FOUND
;
638 rp
->hdr
.is_reply
= 1;
639 rp
->hdr
.len
= sizeof (*rp
);
640 *reply_port
= kdp
.reply_port
;
643 return (TRUE
); /* Check if it needs to be FALSE in case of error */
646 breakpoint_list
[i
].address
= 0;
647 cnt
= kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)rq
->address
, sizeof(int));
648 rp
->error
= KDPERR_NO_ERROR
;
649 rp
->hdr
.is_reply
= 1;
650 rp
->hdr
.len
= sizeof (*rp
);
651 *reply_port
= kdp
.reply_port
;
658 kdp_remove_all_breakpoints()
661 boolean_t breakpoint_found
= FALSE
;
663 if (breakpoints_initialized
)
665 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
667 if (breakpoint_list
[i
].address
)
669 kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)breakpoint_list
[i
].address
, sizeof(int));
670 breakpoint_found
= TRUE
;
671 breakpoint_list
[i
].address
= 0;
674 if (breakpoint_found
)
675 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
677 return breakpoint_found
;