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;
85 int reattach_wait
= 0;
91 unsigned short *reply_port
94 static unsigned aligned_pkt
[1538/sizeof(unsigned)+1]; // max ether pkt
95 kdp_pkt_t
*rd
= (kdp_pkt_t
*)&aligned_pkt
;
101 bcopy((char *)pkt
, (char *)rd
, sizeof(aligned_pkt
));
103 rd
= (kdp_pkt_t
*)pkt
;
105 if (plen
< sizeof (rd
->hdr
) || rd
->hdr
.len
!= plen
) {
106 printf("kdp_packet bad len pkt %d hdr %d\n", plen
, rd
->hdr
.len
);
111 if (rd
->hdr
.is_reply
) {
112 printf("kdp_packet reply recvd req %x seq %x\n",
113 rd
->hdr
.request
, rd
->hdr
.seq
);
118 req
= rd
->hdr
.request
;
119 if ((req
< KDP_CONNECT
) || (req
> KDP_REATTACH
)) {
120 printf("kdp_packet bad request %x len %d seq %x key %x\n",
121 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
126 ret
= ((*dispatch_table
[req
- KDP_CONNECT
])(rd
, len
, reply_port
));
128 bcopy((char *)rd
, (char *) pkt
, *len
);
137 unsigned short *reply_port
140 kdp_pkt_t
*rd
= (kdp_pkt_t
*)pkt
;
142 printf("kdp_unknown request %x len %d seq %x key %x\n",
143 rd
->hdr
.request
, rd
->hdr
.len
, rd
->hdr
.seq
, rd
->hdr
.key
);
152 unsigned short *reply_port
155 kdp_connect_req_t
*rq
= &pkt
->connect_req
;
157 kdp_connect_reply_t
*rp
= &pkt
->connect_reply
;
159 if (plen
< sizeof (*rq
))
162 dprintf(("kdp_connect seq %x greeting %s\n", rq
->hdr
.seq
, rq
->greeting
));
165 if (rq
->hdr
.seq
== kdp
.conn_seq
) /* duplicate request */
166 rp
->error
= KDPERR_NO_ERROR
;
168 rp
->error
= KDPERR_ALREADY_CONNECTED
;
171 kdp
.reply_port
= rq
->req_reply_port
;
172 kdp
.exception_port
= rq
->exc_note_port
;
174 kdp
.conn_seq
= rq
->hdr
.seq
;
176 rp
->error
= KDPERR_NO_ERROR
;
179 rp
->hdr
.is_reply
= 1;
180 rp
->hdr
.len
= sizeof (*rp
);
182 *reply_port
= kdp
.reply_port
;
185 if (current_debugger
== KDP_CUR_DB
)
195 unsigned short *reply_port
198 kdp_disconnect_req_t
*rq
= &pkt
->disconnect_req
;
200 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
202 if (plen
< sizeof (*rq
))
208 dprintf(("kdp_disconnect\n"));
210 *reply_port
= kdp
.reply_port
;
212 kdp
.reply_port
= kdp
.exception_port
= 0;
213 kdp
.is_halted
= kdp
.is_conn
= FALSE
;
214 kdp
.exception_seq
= kdp
.conn_seq
= 0;
216 rp
->hdr
.is_reply
= 1;
217 rp
->hdr
.len
= sizeof (*rp
);
221 if (current_debugger
== KDP_CUR_DB
)
231 unsigned short *reply_port
234 kdp_reattach_req_t
*rq
= &pkt
->reattach_req
;
235 kdp_disconnect_reply_t
*rp
= &pkt
->disconnect_reply
;
238 kdp_disconnect(pkt
, len
, reply_port
);
239 *reply_port
= rq
->req_reply_port
;
248 unsigned short *reply_port
251 kdp_hostinfo_req_t
*rq
= &pkt
->hostinfo_req
;
253 kdp_hostinfo_reply_t
*rp
= &pkt
->hostinfo_reply
;
255 if (plen
< sizeof (*rq
))
258 rp
->hdr
.is_reply
= 1;
259 rp
->hdr
.len
= sizeof (*rp
);
261 kdp_machine_hostinfo(&rp
->hostinfo
);
263 *reply_port
= kdp
.reply_port
;
273 unsigned short *reply_port
276 kdp_suspend_req_t
*rq
= &pkt
->suspend_req
;
278 kdp_suspend_reply_t
*rp
= &pkt
->suspend_reply
;
280 if (plen
< sizeof (*rq
))
283 rp
->hdr
.is_reply
= 1;
284 rp
->hdr
.len
= sizeof (*rp
);
286 dprintf(("kdp_suspend\n"));
288 kdp
.is_halted
= TRUE
;
290 *reply_port
= kdp
.reply_port
;
300 unsigned short *reply_port
303 kdp_resumecpus_req_t
*rq
= &pkt
->resumecpus_req
;
305 kdp_resumecpus_reply_t
*rp
= &pkt
->resumecpus_reply
;
307 if (plen
< sizeof (*rq
))
310 rp
->hdr
.is_reply
= 1;
311 rp
->hdr
.len
= sizeof (*rp
);
313 dprintf(("kdp_resumecpus %x\n", rq
->cpu_mask
));
315 kdp
.is_halted
= FALSE
;
317 *reply_port
= kdp
.reply_port
;
327 unsigned short *reply_port
330 kdp_writemem_req_t
*rq
= &pkt
->writemem_req
;
332 kdp_writemem_reply_t
*rp
= &pkt
->writemem_reply
;
335 if (plen
< sizeof (*rq
))
338 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
339 rp
->error
= KDPERR_BAD_NBYTES
;
341 dprintf(("kdp_writemem addr %x size %d\n", rq
->address
, rq
->nbytes
));
343 cnt
= kdp_vm_write((caddr_t
)rq
->data
, (caddr_t
)rq
->address
, rq
->nbytes
);
344 rp
->error
= KDPERR_NO_ERROR
;
347 rp
->hdr
.is_reply
= 1;
348 rp
->hdr
.len
= sizeof (*rp
);
350 *reply_port
= kdp
.reply_port
;
360 unsigned short *reply_port
363 kdp_readmem_req_t
*rq
= &pkt
->readmem_req
;
365 kdp_readmem_reply_t
*rp
= &pkt
->readmem_reply
;
368 if (plen
< sizeof (*rq
))
371 rp
->hdr
.is_reply
= 1;
372 rp
->hdr
.len
= sizeof (*rp
);
374 if (rq
->nbytes
> MAX_KDP_DATA_SIZE
)
375 rp
->error
= KDPERR_BAD_NBYTES
;
377 unsigned int n
= rq
->nbytes
;
379 dprintf(("kdp_readmem addr %x size %d\n", rq
->address
, rq
->nbytes
));
381 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)rp
->data
, rq
->nbytes
);
382 rp
->error
= KDPERR_NO_ERROR
;
387 *reply_port
= kdp
.reply_port
;
397 unsigned short *reply_port
400 kdp_maxbytes_req_t
*rq
= &pkt
->maxbytes_req
;
402 kdp_maxbytes_reply_t
*rp
= &pkt
->maxbytes_reply
;
404 if (plen
< sizeof (*rq
))
407 rp
->hdr
.is_reply
= 1;
408 rp
->hdr
.len
= sizeof (*rp
);
410 dprintf(("kdp_maxbytes\n"));
412 rp
->max_bytes
= MAX_KDP_DATA_SIZE
;
414 *reply_port
= kdp
.reply_port
;
424 unsigned short *reply_port
427 kdp_version_req_t
*rq
= &pkt
->version_req
;
429 kdp_version_reply_t
*rp
= &pkt
->version_reply
;
432 if (plen
< sizeof (*rq
))
435 rp
->hdr
.is_reply
= 1;
436 rp
->hdr
.len
= sizeof (*rp
);
438 dprintf(("kdp_version\n"));
440 rp
->version
= KDP_VERSION
;
442 if (!(kdp_flag
& KDP_BP_DIS
))
443 rp
->feature
= KDP_FEATURE_BP
;
450 *reply_port
= kdp
.reply_port
;
460 unsigned short *reply_port
463 kdp_regions_req_t
*rq
= &pkt
->regions_req
;
465 kdp_regions_reply_t
*rp
= &pkt
->regions_reply
;
468 if (plen
< sizeof (*rq
))
471 rp
->hdr
.is_reply
= 1;
472 rp
->hdr
.len
= sizeof (*rp
);
474 dprintf(("kdp_regions\n"));
479 (vm_offset_t
)r
->address
= 0;
480 r
->nbytes
= 0xffffffff;
482 r
->protection
= VM_PROT_ALL
; r
++; rp
->nregions
++;
484 rp
->hdr
.len
+= rp
->nregions
* sizeof (kdp_region_t
);
486 *reply_port
= kdp
.reply_port
;
496 unsigned short *reply_port
499 kdp_writeregs_req_t
*rq
= &pkt
->writeregs_req
;
502 kdp_writeregs_reply_t
*rp
= &pkt
->writeregs_reply
;
504 if (plen
< sizeof (*rq
))
507 size
= rq
->hdr
.len
- sizeof(kdp_hdr_t
) - sizeof(unsigned int);
508 rp
->error
= kdp_machine_write_regs(rq
->cpu
, rq
->flavor
, rq
->data
, &size
);
510 rp
->hdr
.is_reply
= 1;
511 rp
->hdr
.len
= sizeof (*rp
);
513 *reply_port
= kdp
.reply_port
;
523 unsigned short *reply_port
526 kdp_readregs_req_t
*rq
= &pkt
->readregs_req
;
528 kdp_readregs_reply_t
*rp
= &pkt
->readregs_reply
;
531 if (plen
< sizeof (*rq
))
534 rp
->hdr
.is_reply
= 1;
535 rp
->hdr
.len
= sizeof (*rp
);
537 rp
->error
= kdp_machine_read_regs(rq
->cpu
, rq
->flavor
, rp
->data
, &size
);
540 *reply_port
= kdp
.reply_port
;
550 unsigned short *reply_port
553 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
554 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
557 unsigned int old_instruction
= 0;
558 unsigned int breakinstr
= kdp_ml_get_breakinsn();
560 if(breakpoints_initialized
== 0)
562 for(i
=0;(i
< MAX_BREAKPOINTS
); breakpoint_list
[i
].address
=0, i
++);
563 breakpoints_initialized
++;
565 if (plen
< sizeof (*rq
))
567 cnt
= kdp_vm_read((caddr_t
)rq
->address
, (caddr_t
)(&old_instruction
), sizeof(int));
569 if (old_instruction
==breakinstr
)
571 printf("A trap was already set at that address, not setting new breakpoint\n");
572 rp
->error
= BREAKPOINT_ALREADY_SET
;
574 rp
->hdr
.is_reply
= 1;
575 rp
->hdr
.len
= sizeof (*rp
);
576 *reply_port
= kdp
.reply_port
;
582 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= 0); i
++);
584 if (i
== MAX_BREAKPOINTS
)
586 rp
->error
= KDP_MAX_BREAKPOINTS
;
588 rp
->hdr
.is_reply
= 1;
589 rp
->hdr
.len
= sizeof (*rp
);
590 *reply_port
= kdp
.reply_port
;
595 breakpoint_list
[i
].address
= rq
->address
;
596 breakpoint_list
[i
].old_instruction
= old_instruction
;
598 cnt
= kdp_vm_write((caddr_t
)&breakinstr
, (caddr_t
)rq
->address
, sizeof(&breakinstr
));
600 rp
->error
= KDPERR_NO_ERROR
;
601 rp
->hdr
.is_reply
= 1;
602 rp
->hdr
.len
= sizeof (*rp
);
603 *reply_port
= kdp
.reply_port
;
610 kdp_breakpoint_remove(
613 unsigned short *reply_port
616 kdp_breakpoint_req_t
*rq
= &pkt
->breakpoint_req
;
617 kdp_breakpoint_reply_t
*rp
= &pkt
->breakpoint_reply
;
621 if (plen
< sizeof (*rq
))
624 for(i
=0;(i
< MAX_BREAKPOINTS
) && (breakpoint_list
[i
].address
!= rq
->address
); i
++);
625 if (i
== MAX_BREAKPOINTS
)
627 rp
->error
= BREAKPOINT_NOT_FOUND
;
628 rp
->hdr
.is_reply
= 1;
629 rp
->hdr
.len
= sizeof (*rp
);
630 *reply_port
= kdp
.reply_port
;
633 return (TRUE
); /* Check if it needs to be FALSE in case of error */
636 breakpoint_list
[i
].address
= 0;
637 cnt
= kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)rq
->address
, sizeof(int));
638 rp
->error
= KDPERR_NO_ERROR
;
639 rp
->hdr
.is_reply
= 1;
640 rp
->hdr
.len
= sizeof (*rp
);
641 *reply_port
= kdp
.reply_port
;
648 kdp_remove_all_breakpoints()
651 boolean_t breakpoint_found
= FALSE
;
653 if (breakpoints_initialized
)
655 for(i
=0;i
< MAX_BREAKPOINTS
; i
++)
657 if (breakpoint_list
[i
].address
)
659 kdp_vm_write((caddr_t
)&(breakpoint_list
[i
].old_instruction
), (caddr_t
)breakpoint_list
[i
].address
, sizeof(int));
660 breakpoint_found
= TRUE
;
661 breakpoint_list
[i
].address
= 0;
664 if (breakpoint_found
)
665 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
667 return breakpoint_found
;