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;
88 int reattach_wait
= 0;
94 unsigned short *reply_port
97 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
98 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
104 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
106 rd
= (kdp_pkt_t
*)pkt
;
108 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
109 printf("kdp_packet bad len pkt %d hdr %d\n", plen
, rd
->hdr
.len
);
114 if (rd
->hdr
.is_reply
) {
115 printf("kdp_packet reply recvd req %x seq %x\n",
116 rd
->hdr
.request
, rd
->hdr
.seq
);
121 req
= rd
->hdr
.request
;
122 if ((req
< KDP_CONNECT
) || (req
> KDP_REATTACH
)) {
123 printf("kdp_packet bad request %x len %d seq %x key %x\n",
124 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
129 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
131 bcopy((char *)rd
, (char *) pkt
, *len
);
140 unsigned short *reply_port
143 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
145 printf("kdp_unknown request %x len %d seq %x key %x\n",
146 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
155 unsigned short *reply_port
158 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
160 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
162 if (plen
< sizeof (*rq
))
165 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
168 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
169 rp
->error
= KDPERR_NO_ERROR
;
171 rp
->error
= KDPERR_ALREADY_CONNECTED
;
174 kdp
.reply_port
= rq
->req_reply_port
;
175 kdp
.exception_port
= rq
->exc_note_port
;
177 kdp
.conn_seq
= rq
->hdr
.seq
;
179 rp
->error
= KDPERR_NO_ERROR
;
182 rp
->hdr
.is_reply
= 1;
183 rp
->hdr
.len
= sizeof (*rp
);
185 *reply_port
= kdp
.reply_port
;
188 if (current_debugger
== KDP_CUR_DB
)
198 unsigned short *reply_port
201 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
203 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
205 if (plen
< sizeof (*rq
))
211 dprintf(("kdp_disconnect\n"));
213 *reply_port
= kdp
.reply_port
;
215 kdp
.reply_port
= kdp
.exception_port
= 0;
216 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
217 kdp
.exception_seq
= kdp
.conn_seq
= 0;
219 rp
->hdr
.is_reply
= 1;
220 rp
->hdr
.len
= sizeof (*rp
);
224 if (current_debugger
== KDP_CUR_DB
)
234 unsigned short *reply_port
237 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
238 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
241 kdp_disconnect(pkt
, len
, reply_port
);
242 *reply_port
= rq
->req_reply_port
;
251 unsigned short *reply_port
254 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
256 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
258 if (plen
< sizeof (*rq
))
261 rp
->hdr
.is_reply
= 1;
262 rp
->hdr
.len
= sizeof (*rp
);
264 kdp_machine_hostinfo(&rp
->hostinfo
);
266 *reply_port
= kdp
.reply_port
;
276 unsigned short *reply_port
279 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
281 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
283 if (plen
< sizeof (*rq
))
286 rp
->hdr
.is_reply
= 1;
287 rp
->hdr
.len
= sizeof (*rp
);
289 dprintf(("kdp_suspend\n"));
291 kdp
.is_halted
= TRUE
;
293 *reply_port
= kdp
.reply_port
;
303 unsigned short *reply_port
306 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
308 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
310 if (plen
< sizeof (*rq
))
313 rp
->hdr
.is_reply
= 1;
314 rp
->hdr
.len
= sizeof (*rp
);
316 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
318 kdp
.is_halted
= FALSE
;
320 *reply_port
= kdp
.reply_port
;
330 unsigned short *reply_port
333 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
335 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
338 if (plen
< sizeof (*rq
))
341 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
342 rp
->error
= KDPERR_BAD_NBYTES
;
344 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
346 cnt
= kdp_vm_write((caddr_t
)rq
->data
, (caddr_t
)rq
->address
, rq
->nbytes
);
347 rp
->error
= KDPERR_NO_ERROR
;
350 rp
->hdr
.is_reply
= 1;
351 rp
->hdr
.len
= sizeof (*rp
);
353 *reply_port
= kdp
.reply_port
;
363 unsigned short *reply_port
366 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
368 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
371 if (plen
< sizeof (*rq
))
374 rp
->hdr
.is_reply
= 1;
375 rp
->hdr
.len
= sizeof (*rp
);
377 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
378 rp
->error
= KDPERR_BAD_NBYTES
;
380 unsigned int n
= rq
->nbytes
;
382 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, rq
->nbytes
));
384 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
385 rp
->error
= KDPERR_NO_ERROR
;
390 *reply_port
= kdp
.reply_port
;
400 unsigned short *reply_port
403 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
405 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
407 if (plen
< sizeof (*rq
))
410 rp
->hdr
.is_reply
= 1;
411 rp
->hdr
.len
= sizeof (*rp
);
413 dprintf(("kdp_maxbytes\n"));
415 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
417 *reply_port
= kdp
.reply_port
;
427 unsigned short *reply_port
430 kdp_version_req_t
*rq
= &pkt
->version_req
;
432 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
435 if (plen
< sizeof (*rq
))
438 rp
->hdr
.is_reply
= 1;
439 rp
->hdr
.len
= sizeof (*rp
);
441 dprintf(("kdp_version\n"));
443 rp
->version
= KDP_VERSION
;
445 if (!(kdp_flag
& KDP_BP_DIS
))
446 rp
->feature
= KDP_FEATURE_BP
;
453 *reply_port
= kdp
.reply_port
;
463 unsigned short *reply_port
466 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
468 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
471 if (plen
< sizeof (*rq
))
474 rp
->hdr
.is_reply
= 1;
475 rp
->hdr
.len
= sizeof (*rp
);
477 dprintf(("kdp_regions\n"));
482 (vm_offset_t
)r
->address
= 0;
483 r
->nbytes
= 0xffffffff;
485 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
487 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
489 *reply_port
= kdp
.reply_port
;
499 unsigned short *reply_port
502 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
505 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
507 if (plen
< sizeof (*rq
))
510 size
= rq
->hdr
.len
- sizeof(kdp_hdr_t
) - sizeof(unsigned int);
511 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
513 rp
->hdr
.is_reply
= 1;
514 rp
->hdr
.len
= sizeof (*rp
);
516 *reply_port
= kdp
.reply_port
;
526 unsigned short *reply_port
529 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
531 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
534 if (plen
< sizeof (*rq
))
537 rp
->hdr
.is_reply
= 1;
538 rp
->hdr
.len
= sizeof (*rp
);
540 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
543 *reply_port
= kdp
.reply_port
;
553 unsigned short *reply_port
556 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
557 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
560 unsigned int old_instruction
= 0;
561 unsigned int breakinstr
= kdp_ml_get_breakinsn();
563 if(breakpoints_initialized
== 0)
565 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
566 breakpoints_initialized
++;
568 if (plen
< sizeof (*rq
))
570 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)(&old_instruction
), sizeof(int));
572 if (old_instruction
==breakinstr
)
574 printf("A trap was already set at that address, not setting new breakpoint\n");
575 rp
->error
= BREAKPOINT_ALREADY_SET
;
577 rp
->hdr
.is_reply
= 1;
578 rp
->hdr
.len
= sizeof (*rp
);
579 *reply_port
= kdp
.reply_port
;
585 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
587 if (i
== MAX_BREAKPOINTS
)
589 rp
->error
= KDP_MAX_BREAKPOINTS
;
591 rp
->hdr
.is_reply
= 1;
592 rp
->hdr
.len
= sizeof (*rp
);
593 *reply_port
= kdp
.reply_port
;
598 breakpoint_list
[i
].address
= rq
->address
;
599 breakpoint_list
[i
].old_instruction
= old_instruction
;
601 cnt
= kdp_vm_write((caddr_t
)&breakinstr
, (caddr_t
)rq
->address
, sizeof(&breakinstr
));
603 rp
->error
= KDPERR_NO_ERROR
;
604 rp
->hdr
.is_reply
= 1;
605 rp
->hdr
.len
= sizeof (*rp
);
606 *reply_port
= kdp
.reply_port
;
613 kdp_breakpoint_remove(
616 unsigned short *reply_port
619 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
620 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
624 if (plen
< sizeof (*rq
))
627 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= rq
->address
); i
++);
628 if (i
== MAX_BREAKPOINTS
)
630 rp
->error
= BREAKPOINT_NOT_FOUND
;
631 rp
->hdr
.is_reply
= 1;
632 rp
->hdr
.len
= sizeof (*rp
);
633 *reply_port
= kdp
.reply_port
;
636 return (TRUE
); /* Check if it needs to be FALSE in case of error */
639 breakpoint_list
[i
].address
= 0;
640 cnt
= kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)rq
->address
, sizeof(int));
641 rp
->error
= KDPERR_NO_ERROR
;
642 rp
->hdr
.is_reply
= 1;
643 rp
->hdr
.len
= sizeof (*rp
);
644 *reply_port
= kdp
.reply_port
;
651 kdp_remove_all_breakpoints()
654 boolean_t breakpoint_found
= FALSE
;
656 if (breakpoints_initialized
)
658 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
660 if (breakpoint_list
[i
].address
)
662 kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)breakpoint_list
[i
].address
, sizeof(int));
663 breakpoint_found
= TRUE
;
664 breakpoint_list
[i
].address
= 0;
667 if (breakpoint_found
)
668 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
670 return breakpoint_found
;