2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <mach/mach_types.h>
24 #include <kern/debug.h>
26 #include <kdp/kdp_internal.h>
27 #include <kdp/kdp_private.h>
29 #include <libsa/types.h>
31 int kdp_vm_read( caddr_t
, caddr_t
, unsigned int);
32 int kdp_vm_write( caddr_t
, caddr_t
, unsigned int);
34 #define DO_ALIGN 1 /* align all packet data accesses */
36 #define KDP_TEST_HARNESS 0
38 #define dprintf(x) kprintf x
44 dispatch_table
[KDP_REATTACH
- KDP_CONNECT
+1] =
47 /* 1 */ kdp_disconnect
,
54 /* 8 */ kdp_writeregs
,
58 /* C */ kdp_resumecpus
,
61 /* F */ kdp_breakpoint_set
,
62 /*10 */ kdp_breakpoint_remove
,
70 #define MAX_BREAKPOINTS 100
71 #define KDP_MAX_BREAKPOINTS 100
73 #define BREAKPOINT_NOT_FOUND 101
74 #define BREAKPOINT_ALREADY_SET 102
76 #define KDP_VERSION 10
80 unsigned int old_instruction
;
81 } kdp_breakpoint_record_t
;
83 static kdp_breakpoint_record_t breakpoint_list
[MAX_BREAKPOINTS
];
84 static unsigned int breakpoints_initialized
= 0;
86 int reattach_wait
= 0;
87 int noresume_on_disconnect
= 0;
93 unsigned short *reply_port
96 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
97 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
103 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
105 rd
= (kdp_pkt_t
*)pkt
;
107 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
108 printf("kdp_packet bad len pkt %d hdr %d\n", plen
, rd
->hdr
.len
);
113 if (rd
->hdr
.is_reply
) {
114 printf("kdp_packet reply recvd req %x seq %x\n",
115 rd
->hdr
.request
, rd
->hdr
.seq
);
120 req
= rd
->hdr
.request
;
121 if ((req
< KDP_CONNECT
) || (req
> KDP_REATTACH
)) {
122 printf("kdp_packet bad request %x len %d seq %x key %x\n",
123 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
128 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
130 bcopy((char *)rd
, (char *) pkt
, *len
);
139 unsigned short *reply_port
142 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
144 printf("kdp_unknown request %x len %d seq %x key %x\n",
145 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
154 unsigned short *reply_port
157 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
159 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
161 if (plen
< sizeof (*rq
))
164 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
167 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
168 rp
->error
= KDPERR_NO_ERROR
;
170 rp
->error
= KDPERR_ALREADY_CONNECTED
;
173 kdp
.reply_port
= rq
->req_reply_port
;
174 kdp
.exception_port
= rq
->exc_note_port
;
176 kdp
.conn_seq
= rq
->hdr
.seq
;
178 rp
->error
= KDPERR_NO_ERROR
;
181 rp
->hdr
.is_reply
= 1;
182 rp
->hdr
.len
= sizeof (*rp
);
184 *reply_port
= kdp
.reply_port
;
187 if (current_debugger
== KDP_CUR_DB
)
197 unsigned short *reply_port
200 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
202 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
204 if (plen
< sizeof (*rq
))
210 dprintf(("kdp_disconnect\n"));
212 *reply_port
= kdp
.reply_port
;
214 kdp
.reply_port
= kdp
.exception_port
= 0;
215 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
216 kdp
.exception_seq
= kdp
.conn_seq
= 0;
218 if (noresume_on_disconnect
== 1) {
220 noresume_on_disconnect
= 0;
223 rp
->hdr
.is_reply
= 1;
224 rp
->hdr
.len
= sizeof (*rp
);
228 if (current_debugger
== KDP_CUR_DB
)
238 unsigned short *reply_port
241 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
242 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
245 kdp_disconnect(pkt
, len
, reply_port
);
246 *reply_port
= rq
->req_reply_port
;
255 unsigned short *reply_port
258 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
260 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
262 if (plen
< sizeof (*rq
))
265 rp
->hdr
.is_reply
= 1;
266 rp
->hdr
.len
= sizeof (*rp
);
268 kdp_machine_hostinfo(&rp
->hostinfo
);
270 *reply_port
= kdp
.reply_port
;
280 unsigned short *reply_port
283 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
285 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
287 if (plen
< sizeof (*rq
))
290 rp
->hdr
.is_reply
= 1;
291 rp
->hdr
.len
= sizeof (*rp
);
293 dprintf(("kdp_suspend\n"));
295 kdp
.is_halted
= TRUE
;
297 *reply_port
= kdp
.reply_port
;
307 unsigned short *reply_port
310 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
312 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
314 if (plen
< sizeof (*rq
))
317 rp
->hdr
.is_reply
= 1;
318 rp
->hdr
.len
= sizeof (*rp
);
320 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
322 kdp
.is_halted
= FALSE
;
324 *reply_port
= kdp
.reply_port
;
334 unsigned short *reply_port
337 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
339 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
342 if (plen
< sizeof (*rq
))
345 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
346 rp
->error
= KDPERR_BAD_NBYTES
;
348 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
350 cnt
= kdp_vm_write((caddr_t
)rq
->data
, (caddr_t
)rq
->address
, rq
->nbytes
);
351 rp
->error
= KDPERR_NO_ERROR
;
354 rp
->hdr
.is_reply
= 1;
355 rp
->hdr
.len
= sizeof (*rp
);
357 *reply_port
= kdp
.reply_port
;
367 unsigned short *reply_port
370 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
372 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
375 if (plen
< sizeof (*rq
))
378 rp
->hdr
.is_reply
= 1;
379 rp
->hdr
.len
= sizeof (*rp
);
381 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
382 rp
->error
= KDPERR_BAD_NBYTES
;
384 unsigned int n
= rq
->nbytes
;
386 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, rq
->nbytes
));
388 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
389 rp
->error
= KDPERR_NO_ERROR
;
394 *reply_port
= kdp
.reply_port
;
404 unsigned short *reply_port
407 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
409 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
411 if (plen
< sizeof (*rq
))
414 rp
->hdr
.is_reply
= 1;
415 rp
->hdr
.len
= sizeof (*rp
);
417 dprintf(("kdp_maxbytes\n"));
419 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
421 *reply_port
= kdp
.reply_port
;
431 unsigned short *reply_port
434 kdp_version_req_t
*rq
= &pkt
->version_req
;
436 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
439 if (plen
< sizeof (*rq
))
442 rp
->hdr
.is_reply
= 1;
443 rp
->hdr
.len
= sizeof (*rp
);
445 dprintf(("kdp_version\n"));
447 rp
->version
= KDP_VERSION
;
449 if (!(kdp_flag
& KDP_BP_DIS
))
450 rp
->feature
= KDP_FEATURE_BP
;
457 *reply_port
= kdp
.reply_port
;
467 unsigned short *reply_port
470 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
472 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
475 if (plen
< sizeof (*rq
))
478 rp
->hdr
.is_reply
= 1;
479 rp
->hdr
.len
= sizeof (*rp
);
481 dprintf(("kdp_regions\n"));
486 (vm_offset_t
)r
->address
= 0;
487 r
->nbytes
= 0xffffffff;
489 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
491 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
493 *reply_port
= kdp
.reply_port
;
503 unsigned short *reply_port
506 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
509 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
511 if (plen
< sizeof (*rq
))
514 size
= rq
->hdr
.len
- sizeof(kdp_hdr_t
) - sizeof(unsigned int);
515 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
517 rp
->hdr
.is_reply
= 1;
518 rp
->hdr
.len
= sizeof (*rp
);
520 *reply_port
= kdp
.reply_port
;
530 unsigned short *reply_port
533 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
535 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
538 if (plen
< sizeof (*rq
))
541 rp
->hdr
.is_reply
= 1;
542 rp
->hdr
.len
= sizeof (*rp
);
544 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
547 *reply_port
= kdp
.reply_port
;
557 unsigned short *reply_port
560 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
561 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
564 unsigned int old_instruction
= 0;
565 unsigned int breakinstr
= kdp_ml_get_breakinsn();
567 if(breakpoints_initialized
== 0)
569 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
570 breakpoints_initialized
++;
572 if (plen
< sizeof (*rq
))
574 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)(&old_instruction
), sizeof(int));
576 if (old_instruction
==breakinstr
)
578 printf("A trap was already set at that address, not setting new breakpoint\n");
579 rp
->error
= BREAKPOINT_ALREADY_SET
;
581 rp
->hdr
.is_reply
= 1;
582 rp
->hdr
.len
= sizeof (*rp
);
583 *reply_port
= kdp
.reply_port
;
589 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
591 if (i
== MAX_BREAKPOINTS
)
593 rp
->error
= KDP_MAX_BREAKPOINTS
;
595 rp
->hdr
.is_reply
= 1;
596 rp
->hdr
.len
= sizeof (*rp
);
597 *reply_port
= kdp
.reply_port
;
602 breakpoint_list
[i
].address
= rq
->address
;
603 breakpoint_list
[i
].old_instruction
= old_instruction
;
605 cnt
= kdp_vm_write((caddr_t
)&breakinstr
, (caddr_t
)rq
->address
, sizeof(&breakinstr
));
607 rp
->error
= KDPERR_NO_ERROR
;
608 rp
->hdr
.is_reply
= 1;
609 rp
->hdr
.len
= sizeof (*rp
);
610 *reply_port
= kdp
.reply_port
;
617 kdp_breakpoint_remove(
620 unsigned short *reply_port
623 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
624 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
628 if (plen
< sizeof (*rq
))
631 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= rq
->address
); i
++);
632 if (i
== MAX_BREAKPOINTS
)
634 rp
->error
= BREAKPOINT_NOT_FOUND
;
635 rp
->hdr
.is_reply
= 1;
636 rp
->hdr
.len
= sizeof (*rp
);
637 *reply_port
= kdp
.reply_port
;
640 return (TRUE
); /* Check if it needs to be FALSE in case of error */
643 breakpoint_list
[i
].address
= 0;
644 cnt
= kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)rq
->address
, sizeof(int));
645 rp
->error
= KDPERR_NO_ERROR
;
646 rp
->hdr
.is_reply
= 1;
647 rp
->hdr
.len
= sizeof (*rp
);
648 *reply_port
= kdp
.reply_port
;
655 kdp_remove_all_breakpoints()
658 boolean_t breakpoint_found
= FALSE
;
660 if (breakpoints_initialized
)
662 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
664 if (breakpoint_list
[i
].address
)
666 kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)breakpoint_list
[i
].address
, sizeof(int));
667 breakpoint_found
= TRUE
;
668 breakpoint_list
[i
].address
= 0;
671 if (breakpoint_found
)
672 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
674 return breakpoint_found
;