]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
8f6c56a5 A |
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 License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
1c79356b | 27 | */ |
1c79356b A |
28 | |
29 | #include <mach/mach_types.h> | |
30 | #include <kern/debug.h> | |
31 | ||
32 | #include <kdp/kdp_internal.h> | |
33 | #include <kdp/kdp_private.h> | |
34 | ||
9bccf70c A |
35 | #include <libsa/types.h> |
36 | ||
91447636 A |
37 | #include <string.h> /* bcopy */ |
38 | ||
1c79356b A |
39 | int kdp_vm_read( caddr_t, caddr_t, unsigned int); |
40 | int kdp_vm_write( caddr_t, caddr_t, unsigned int); | |
41 | ||
42 | #define DO_ALIGN 1 /* align all packet data accesses */ | |
43 | ||
44 | #define KDP_TEST_HARNESS 0 | |
45 | #if KDP_TEST_HARNESS | |
46 | #define dprintf(x) kprintf x | |
47 | #else | |
48 | #define dprintf(x) | |
49 | #endif | |
50 | ||
51 | static kdp_dispatch_t | |
91447636 | 52 | dispatch_table[KDP_HOSTREBOOT - KDP_CONNECT +1] = |
1c79356b A |
53 | { |
54 | /* 0 */ kdp_connect, | |
55 | /* 1 */ kdp_disconnect, | |
56 | /* 2 */ kdp_hostinfo, | |
9bccf70c | 57 | /* 3 */ kdp_version, |
1c79356b A |
58 | /* 4 */ kdp_maxbytes, |
59 | /* 5 */ kdp_readmem, | |
60 | /* 6 */ kdp_writemem, | |
61 | /* 7 */ kdp_readregs, | |
62 | /* 8 */ kdp_writeregs, | |
9bccf70c A |
63 | /* 9 */ kdp_unknown, |
64 | /* A */ kdp_unknown, | |
1c79356b A |
65 | /* B */ kdp_suspend, |
66 | /* C */ kdp_resumecpus, | |
67 | /* D */ kdp_unknown, | |
9bccf70c A |
68 | /* E */ kdp_unknown, |
69 | /* F */ kdp_breakpoint_set, | |
70 | /*10 */ kdp_breakpoint_remove, | |
71 | /*11 */ kdp_regions, | |
91447636 A |
72 | /*12 */ kdp_reattach, |
73 | /*13 */ kdp_reboot | |
1c79356b A |
74 | }; |
75 | ||
76 | kdp_glob_t kdp; | |
9bccf70c A |
77 | |
78 | ||
79 | #define MAX_BREAKPOINTS 100 | |
80 | #define KDP_MAX_BREAKPOINTS 100 | |
81 | ||
82 | #define BREAKPOINT_NOT_FOUND 101 | |
83 | #define BREAKPOINT_ALREADY_SET 102 | |
84 | ||
85 | #define KDP_VERSION 10 | |
86 | ||
87 | typedef struct{ | |
88 | unsigned int address; | |
89 | unsigned int old_instruction; | |
90 | } kdp_breakpoint_record_t; | |
91 | ||
92 | static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS]; | |
93 | static unsigned int breakpoints_initialized = 0; | |
55e303ae | 94 | |
9bccf70c | 95 | int reattach_wait = 0; |
55e303ae | 96 | int noresume_on_disconnect = 0; |
1c79356b A |
97 | |
98 | boolean_t | |
99 | kdp_packet( | |
100 | unsigned char *pkt, | |
101 | int *len, | |
102 | unsigned short *reply_port | |
103 | ) | |
104 | { | |
105 | static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt | |
106 | kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt; | |
107 | int plen = *len; | |
108 | unsigned int req; | |
109 | boolean_t ret; | |
110 | ||
111 | #if DO_ALIGN | |
112 | bcopy((char *)pkt, (char *)rd, sizeof(aligned_pkt)); | |
113 | #else | |
114 | rd = (kdp_pkt_t *)pkt; | |
115 | #endif | |
116 | if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) { | |
117 | printf("kdp_packet bad len pkt %d hdr %d\n", plen, rd->hdr.len); | |
118 | ||
119 | return (FALSE); | |
120 | } | |
121 | ||
122 | if (rd->hdr.is_reply) { | |
123 | printf("kdp_packet reply recvd req %x seq %x\n", | |
124 | rd->hdr.request, rd->hdr.seq); | |
125 | ||
126 | return (FALSE); | |
127 | } | |
128 | ||
129 | req = rd->hdr.request; | |
91447636 | 130 | if ((req < KDP_CONNECT) || (req > KDP_HOSTREBOOT)) { |
1c79356b A |
131 | printf("kdp_packet bad request %x len %d seq %x key %x\n", |
132 | rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key); | |
133 | ||
134 | return (FALSE); | |
135 | } | |
136 | ||
137 | ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port)); | |
138 | #if DO_ALIGN | |
139 | bcopy((char *)rd, (char *) pkt, *len); | |
140 | #endif | |
141 | return ret; | |
142 | } | |
143 | ||
144 | static boolean_t | |
145 | kdp_unknown( | |
146 | kdp_pkt_t *pkt, | |
147 | int *len, | |
148 | unsigned short *reply_port | |
149 | ) | |
150 | { | |
151 | kdp_pkt_t *rd = (kdp_pkt_t *)pkt; | |
152 | ||
153 | printf("kdp_unknown request %x len %d seq %x key %x\n", | |
154 | rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key); | |
155 | ||
156 | return (FALSE); | |
157 | } | |
158 | ||
159 | static boolean_t | |
160 | kdp_connect( | |
161 | kdp_pkt_t *pkt, | |
162 | int *len, | |
163 | unsigned short *reply_port | |
164 | ) | |
165 | { | |
166 | kdp_connect_req_t *rq = &pkt->connect_req; | |
167 | int plen = *len; | |
168 | kdp_connect_reply_t *rp = &pkt->connect_reply; | |
169 | ||
170 | if (plen < sizeof (*rq)) | |
171 | return (FALSE); | |
172 | ||
173 | dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting)); | |
174 | ||
175 | if (kdp.is_conn) { | |
176 | if (rq->hdr.seq == kdp.conn_seq) /* duplicate request */ | |
177 | rp->error = KDPERR_NO_ERROR; | |
178 | else | |
179 | rp->error = KDPERR_ALREADY_CONNECTED; | |
180 | } | |
181 | else { | |
182 | kdp.reply_port = rq->req_reply_port; | |
183 | kdp.exception_port = rq->exc_note_port; | |
184 | kdp.is_conn = TRUE; | |
185 | kdp.conn_seq = rq->hdr.seq; | |
186 | ||
187 | rp->error = KDPERR_NO_ERROR; | |
188 | } | |
189 | ||
190 | rp->hdr.is_reply = 1; | |
191 | rp->hdr.len = sizeof (*rp); | |
192 | ||
193 | *reply_port = kdp.reply_port; | |
194 | *len = rp->hdr.len; | |
195 | ||
196 | if (current_debugger == KDP_CUR_DB) | |
197 | active_debugger=1; | |
198 | ||
199 | return (TRUE); | |
200 | } | |
201 | ||
202 | static boolean_t | |
203 | kdp_disconnect( | |
204 | kdp_pkt_t *pkt, | |
205 | int *len, | |
206 | unsigned short *reply_port | |
207 | ) | |
208 | { | |
209 | kdp_disconnect_req_t *rq = &pkt->disconnect_req; | |
210 | int plen = *len; | |
211 | kdp_disconnect_reply_t *rp = &pkt->disconnect_reply; | |
212 | ||
213 | if (plen < sizeof (*rq)) | |
214 | return (FALSE); | |
215 | ||
216 | if (!kdp.is_conn) | |
217 | return (FALSE); | |
218 | ||
219 | dprintf(("kdp_disconnect\n")); | |
220 | ||
221 | *reply_port = kdp.reply_port; | |
222 | ||
223 | kdp.reply_port = kdp.exception_port = 0; | |
224 | kdp.is_halted = kdp.is_conn = FALSE; | |
225 | kdp.exception_seq = kdp.conn_seq = 0; | |
226 | ||
55e303ae A |
227 | if (noresume_on_disconnect == 1) { |
228 | reattach_wait = 1; | |
229 | noresume_on_disconnect = 0; | |
230 | } | |
231 | ||
1c79356b A |
232 | rp->hdr.is_reply = 1; |
233 | rp->hdr.len = sizeof (*rp); | |
234 | ||
235 | *len = rp->hdr.len; | |
236 | ||
237 | if (current_debugger == KDP_CUR_DB) | |
238 | active_debugger=0; | |
239 | ||
240 | return (TRUE); | |
241 | } | |
242 | ||
9bccf70c A |
243 | static boolean_t |
244 | kdp_reattach( | |
245 | kdp_pkt_t *pkt, | |
246 | int *len, | |
247 | unsigned short *reply_port | |
248 | ) | |
249 | { | |
250 | kdp_reattach_req_t *rq = &pkt->reattach_req; | |
251 | kdp_disconnect_reply_t *rp = &pkt->disconnect_reply; | |
252 | ||
253 | kdp.is_conn = TRUE; | |
254 | kdp_disconnect(pkt, len, reply_port); | |
255 | *reply_port = rq->req_reply_port; | |
256 | reattach_wait = 1; | |
257 | return (TRUE); | |
258 | } | |
259 | ||
1c79356b A |
260 | static boolean_t |
261 | kdp_hostinfo( | |
262 | kdp_pkt_t *pkt, | |
263 | int *len, | |
264 | unsigned short *reply_port | |
265 | ) | |
266 | { | |
267 | kdp_hostinfo_req_t *rq = &pkt->hostinfo_req; | |
268 | int plen = *len; | |
269 | kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply; | |
270 | ||
271 | if (plen < sizeof (*rq)) | |
272 | return (FALSE); | |
273 | ||
274 | rp->hdr.is_reply = 1; | |
275 | rp->hdr.len = sizeof (*rp); | |
276 | ||
277 | kdp_machine_hostinfo(&rp->hostinfo); | |
9bccf70c | 278 | |
1c79356b A |
279 | *reply_port = kdp.reply_port; |
280 | *len = rp->hdr.len; | |
281 | ||
282 | return (TRUE); | |
283 | } | |
284 | ||
285 | static boolean_t | |
286 | kdp_suspend( | |
287 | kdp_pkt_t *pkt, | |
288 | int *len, | |
289 | unsigned short *reply_port | |
290 | ) | |
291 | { | |
292 | kdp_suspend_req_t *rq = &pkt->suspend_req; | |
293 | int plen = *len; | |
294 | kdp_suspend_reply_t *rp = &pkt->suspend_reply; | |
295 | ||
296 | if (plen < sizeof (*rq)) | |
297 | return (FALSE); | |
298 | ||
299 | rp->hdr.is_reply = 1; | |
300 | rp->hdr.len = sizeof (*rp); | |
301 | ||
302 | dprintf(("kdp_suspend\n")); | |
303 | ||
304 | kdp.is_halted = TRUE; | |
305 | ||
306 | *reply_port = kdp.reply_port; | |
307 | *len = rp->hdr.len; | |
308 | ||
309 | return (TRUE); | |
310 | } | |
311 | ||
312 | static boolean_t | |
313 | kdp_resumecpus( | |
314 | kdp_pkt_t *pkt, | |
315 | int *len, | |
316 | unsigned short *reply_port | |
317 | ) | |
318 | { | |
319 | kdp_resumecpus_req_t *rq = &pkt->resumecpus_req; | |
320 | int plen = *len; | |
321 | kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply; | |
322 | ||
323 | if (plen < sizeof (*rq)) | |
324 | return (FALSE); | |
325 | ||
326 | rp->hdr.is_reply = 1; | |
327 | rp->hdr.len = sizeof (*rp); | |
328 | ||
329 | dprintf(("kdp_resumecpus %x\n", rq->cpu_mask)); | |
9bccf70c | 330 | |
1c79356b A |
331 | kdp.is_halted = FALSE; |
332 | ||
333 | *reply_port = kdp.reply_port; | |
334 | *len = rp->hdr.len; | |
335 | ||
336 | return (TRUE); | |
337 | } | |
338 | ||
339 | static boolean_t | |
340 | kdp_writemem( | |
341 | kdp_pkt_t *pkt, | |
342 | int *len, | |
343 | unsigned short *reply_port | |
344 | ) | |
345 | { | |
346 | kdp_writemem_req_t *rq = &pkt->writemem_req; | |
347 | int plen = *len; | |
348 | kdp_writemem_reply_t *rp = &pkt->writemem_reply; | |
349 | int cnt; | |
350 | ||
351 | if (plen < sizeof (*rq)) | |
352 | return (FALSE); | |
353 | ||
354 | if (rq->nbytes > MAX_KDP_DATA_SIZE) | |
355 | rp->error = KDPERR_BAD_NBYTES; | |
356 | else { | |
357 | dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes)); | |
358 | ||
359 | cnt = kdp_vm_write((caddr_t)rq->data, (caddr_t)rq->address, rq->nbytes); | |
360 | rp->error = KDPERR_NO_ERROR; | |
361 | } | |
362 | ||
363 | rp->hdr.is_reply = 1; | |
364 | rp->hdr.len = sizeof (*rp); | |
365 | ||
366 | *reply_port = kdp.reply_port; | |
367 | *len = rp->hdr.len; | |
368 | ||
369 | return (TRUE); | |
370 | } | |
371 | ||
372 | static boolean_t | |
373 | kdp_readmem( | |
374 | kdp_pkt_t *pkt, | |
375 | int *len, | |
376 | unsigned short *reply_port | |
377 | ) | |
378 | { | |
379 | kdp_readmem_req_t *rq = &pkt->readmem_req; | |
380 | int plen = *len; | |
381 | kdp_readmem_reply_t *rp = &pkt->readmem_reply; | |
382 | int cnt; | |
8f6c56a5 | 383 | |
1c79356b A |
384 | if (plen < sizeof (*rq)) |
385 | return (FALSE); | |
386 | ||
387 | rp->hdr.is_reply = 1; | |
388 | rp->hdr.len = sizeof (*rp); | |
389 | ||
390 | if (rq->nbytes > MAX_KDP_DATA_SIZE) | |
391 | rp->error = KDPERR_BAD_NBYTES; | |
392 | else { | |
393 | unsigned int n = rq->nbytes; | |
394 | ||
395 | dprintf(("kdp_readmem addr %x size %d\n", rq->address, rq->nbytes)); | |
8f6c56a5 | 396 | |
1c79356b A |
397 | cnt = kdp_vm_read((caddr_t)rq->address, (caddr_t)rp->data, rq->nbytes); |
398 | rp->error = KDPERR_NO_ERROR; | |
399 | ||
400 | rp->hdr.len += cnt; | |
401 | } | |
402 | ||
403 | *reply_port = kdp.reply_port; | |
404 | *len = rp->hdr.len; | |
405 | ||
406 | return (TRUE); | |
407 | } | |
408 | ||
409 | static boolean_t | |
410 | kdp_maxbytes( | |
411 | kdp_pkt_t *pkt, | |
412 | int *len, | |
413 | unsigned short *reply_port | |
414 | ) | |
415 | { | |
416 | kdp_maxbytes_req_t *rq = &pkt->maxbytes_req; | |
417 | int plen = *len; | |
418 | kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply; | |
419 | ||
420 | if (plen < sizeof (*rq)) | |
421 | return (FALSE); | |
422 | ||
423 | rp->hdr.is_reply = 1; | |
424 | rp->hdr.len = sizeof (*rp); | |
425 | ||
426 | dprintf(("kdp_maxbytes\n")); | |
427 | ||
428 | rp->max_bytes = MAX_KDP_DATA_SIZE; | |
429 | ||
430 | *reply_port = kdp.reply_port; | |
431 | *len = rp->hdr.len; | |
432 | ||
433 | return (TRUE); | |
434 | } | |
435 | ||
9bccf70c A |
436 | static boolean_t |
437 | kdp_version( | |
438 | kdp_pkt_t *pkt, | |
439 | int *len, | |
440 | unsigned short *reply_port | |
441 | ) | |
442 | { | |
443 | kdp_version_req_t *rq = &pkt->version_req; | |
444 | int plen = *len; | |
445 | kdp_version_reply_t *rp = &pkt->version_reply; | |
446 | kdp_region_t *r; | |
447 | ||
448 | if (plen < sizeof (*rq)) | |
449 | return (FALSE); | |
450 | ||
451 | rp->hdr.is_reply = 1; | |
452 | rp->hdr.len = sizeof (*rp); | |
453 | ||
454 | dprintf(("kdp_version\n")); | |
455 | ||
456 | rp->version = KDP_VERSION; | |
457 | #ifdef __ppc__ | |
458 | if (!(kdp_flag & KDP_BP_DIS)) | |
459 | rp->feature = KDP_FEATURE_BP; | |
460 | else | |
461 | rp->feature = 0; | |
462 | #else | |
463 | rp->feature = 0; | |
464 | #endif | |
465 | ||
466 | *reply_port = kdp.reply_port; | |
467 | *len = rp->hdr.len; | |
468 | ||
469 | return (TRUE); | |
470 | } | |
471 | ||
1c79356b A |
472 | static boolean_t |
473 | kdp_regions( | |
474 | kdp_pkt_t *pkt, | |
475 | int *len, | |
476 | unsigned short *reply_port | |
477 | ) | |
478 | { | |
479 | kdp_regions_req_t *rq = &pkt->regions_req; | |
480 | int plen = *len; | |
481 | kdp_regions_reply_t *rp = &pkt->regions_reply; | |
482 | kdp_region_t *r; | |
483 | ||
484 | if (plen < sizeof (*rq)) | |
485 | return (FALSE); | |
486 | ||
487 | rp->hdr.is_reply = 1; | |
488 | rp->hdr.len = sizeof (*rp); | |
489 | ||
490 | dprintf(("kdp_regions\n")); | |
491 | ||
492 | r = rp->regions; | |
493 | rp->nregions = 0; | |
494 | ||
495 | (vm_offset_t)r->address = 0; | |
496 | r->nbytes = 0xffffffff; | |
497 | ||
498 | r->protection = VM_PROT_ALL; r++; rp->nregions++; | |
499 | ||
500 | rp->hdr.len += rp->nregions * sizeof (kdp_region_t); | |
501 | ||
502 | *reply_port = kdp.reply_port; | |
503 | *len = rp->hdr.len; | |
504 | ||
505 | return (TRUE); | |
506 | } | |
507 | ||
508 | static boolean_t | |
509 | kdp_writeregs( | |
510 | kdp_pkt_t *pkt, | |
511 | int *len, | |
512 | unsigned short *reply_port | |
513 | ) | |
514 | { | |
515 | kdp_writeregs_req_t *rq = &pkt->writeregs_req; | |
516 | int plen = *len; | |
517 | int size; | |
518 | kdp_writeregs_reply_t *rp = &pkt->writeregs_reply; | |
519 | ||
520 | if (plen < sizeof (*rq)) | |
521 | return (FALSE); | |
522 | ||
523 | size = rq->hdr.len - sizeof(kdp_hdr_t) - sizeof(unsigned int); | |
524 | rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size); | |
525 | ||
526 | rp->hdr.is_reply = 1; | |
527 | rp->hdr.len = sizeof (*rp); | |
528 | ||
529 | *reply_port = kdp.reply_port; | |
530 | *len = rp->hdr.len; | |
531 | ||
532 | return (TRUE); | |
533 | } | |
534 | ||
535 | static boolean_t | |
536 | kdp_readregs( | |
537 | kdp_pkt_t *pkt, | |
538 | int *len, | |
539 | unsigned short *reply_port | |
540 | ) | |
541 | { | |
542 | kdp_readregs_req_t *rq = &pkt->readregs_req; | |
543 | int plen = *len; | |
544 | kdp_readregs_reply_t *rp = &pkt->readregs_reply; | |
545 | int size; | |
546 | ||
547 | if (plen < sizeof (*rq)) | |
548 | return (FALSE); | |
549 | ||
550 | rp->hdr.is_reply = 1; | |
551 | rp->hdr.len = sizeof (*rp); | |
552 | ||
553 | rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size); | |
554 | rp->hdr.len += size; | |
555 | ||
556 | *reply_port = kdp.reply_port; | |
557 | *len = rp->hdr.len; | |
558 | ||
559 | return (TRUE); | |
560 | } | |
9bccf70c A |
561 | |
562 | static boolean_t | |
563 | kdp_breakpoint_set( | |
564 | kdp_pkt_t *pkt, | |
565 | int *len, | |
566 | unsigned short *reply_port | |
567 | ) | |
568 | { | |
569 | kdp_breakpoint_req_t *rq = &pkt->breakpoint_req; | |
570 | kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply; | |
571 | int plen = *len; | |
572 | int cnt, i; | |
573 | unsigned int old_instruction = 0; | |
574 | unsigned int breakinstr = kdp_ml_get_breakinsn(); | |
575 | ||
576 | if(breakpoints_initialized == 0) | |
577 | { | |
578 | for(i=0;(i < MAX_BREAKPOINTS); breakpoint_list[i].address=0, i++); | |
579 | breakpoints_initialized++; | |
580 | } | |
581 | if (plen < sizeof (*rq)) | |
582 | return (FALSE); | |
583 | cnt = kdp_vm_read((caddr_t)rq->address, (caddr_t)(&old_instruction), sizeof(int)); | |
584 | ||
585 | if (old_instruction==breakinstr) | |
586 | { | |
587 | printf("A trap was already set at that address, not setting new breakpoint\n"); | |
588 | rp->error = BREAKPOINT_ALREADY_SET; | |
589 | ||
590 | rp->hdr.is_reply = 1; | |
591 | rp->hdr.len = sizeof (*rp); | |
592 | *reply_port = kdp.reply_port; | |
593 | *len = rp->hdr.len; | |
594 | ||
595 | return (TRUE); | |
596 | } | |
597 | ||
598 | for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++); | |
599 | ||
600 | if (i == MAX_BREAKPOINTS) | |
601 | { | |
602 | rp->error = KDP_MAX_BREAKPOINTS; | |
603 | ||
604 | rp->hdr.is_reply = 1; | |
605 | rp->hdr.len = sizeof (*rp); | |
606 | *reply_port = kdp.reply_port; | |
607 | *len = rp->hdr.len; | |
608 | ||
609 | return (TRUE); | |
610 | } | |
611 | breakpoint_list[i].address = rq->address; | |
612 | breakpoint_list[i].old_instruction = old_instruction; | |
613 | ||
614 | cnt = kdp_vm_write((caddr_t)&breakinstr, (caddr_t)rq->address, sizeof(&breakinstr)); | |
615 | ||
616 | rp->error = KDPERR_NO_ERROR; | |
617 | rp->hdr.is_reply = 1; | |
618 | rp->hdr.len = sizeof (*rp); | |
619 | *reply_port = kdp.reply_port; | |
620 | *len = rp->hdr.len; | |
621 | ||
622 | return (TRUE); | |
623 | } | |
624 | ||
625 | static boolean_t | |
626 | kdp_breakpoint_remove( | |
627 | kdp_pkt_t *pkt, | |
628 | int *len, | |
629 | unsigned short *reply_port | |
630 | ) | |
631 | { | |
632 | kdp_breakpoint_req_t *rq = &pkt->breakpoint_req; | |
633 | kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply; | |
634 | int plen = *len; | |
635 | int cnt,i; | |
636 | ||
637 | if (plen < sizeof (*rq)) | |
638 | return (FALSE); | |
639 | ||
640 | for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != rq->address); i++); | |
641 | if (i == MAX_BREAKPOINTS) | |
642 | { | |
643 | rp->error = BREAKPOINT_NOT_FOUND; | |
644 | rp->hdr.is_reply = 1; | |
645 | rp->hdr.len = sizeof (*rp); | |
646 | *reply_port = kdp.reply_port; | |
647 | *len = rp->hdr.len; | |
648 | ||
649 | return (TRUE); /* Check if it needs to be FALSE in case of error */ | |
650 | } | |
651 | ||
652 | breakpoint_list[i].address = 0; | |
653 | cnt = kdp_vm_write((caddr_t)&(breakpoint_list[i].old_instruction), (caddr_t)rq->address, sizeof(int)); | |
654 | rp->error = KDPERR_NO_ERROR; | |
655 | rp->hdr.is_reply = 1; | |
656 | rp->hdr.len = sizeof (*rp); | |
657 | *reply_port = kdp.reply_port; | |
658 | *len = rp->hdr.len; | |
659 | ||
660 | return (TRUE); | |
661 | } | |
662 | ||
663 | boolean_t | |
664 | kdp_remove_all_breakpoints() | |
665 | { | |
666 | int i; | |
667 | boolean_t breakpoint_found = FALSE; | |
668 | ||
669 | if (breakpoints_initialized) | |
670 | { | |
671 | for(i=0;i < MAX_BREAKPOINTS; i++) | |
672 | { | |
673 | if (breakpoint_list[i].address) | |
674 | { | |
675 | kdp_vm_write((caddr_t)&(breakpoint_list[i].old_instruction), (caddr_t)breakpoint_list[i].address, sizeof(int)); | |
676 | breakpoint_found = TRUE; | |
677 | breakpoint_list[i].address = 0; | |
678 | } | |
679 | } | |
680 | if (breakpoint_found) | |
681 | printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n"); | |
682 | } | |
683 | return breakpoint_found; | |
684 | } |