]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/kdp.c
xnu-123.5.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1993 NeXT Computer, Inc. All rights reserved.
24 *
25 * kdp.c -- Kernel Debugging Protocol.
26 *
27 */
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
35 int kdp_vm_read( caddr_t, caddr_t, unsigned int);
36 int kdp_vm_write( caddr_t, caddr_t, unsigned int);
37
38 #define DO_ALIGN 1 /* align all packet data accesses */
39
40 #define KDP_TEST_HARNESS 0
41 #if KDP_TEST_HARNESS
42 #define dprintf(x) kprintf x
43 #else
44 #define dprintf(x)
45 #endif
46
47 static kdp_dispatch_t
48 dispatch_table[KDP_TERMINATION - KDP_CONNECT + 1] =
49 {
50 /* 0 */ kdp_connect,
51 /* 1 */ kdp_disconnect,
52 /* 2 */ kdp_hostinfo,
53 /* 3 */ kdp_regions,
54 /* 4 */ kdp_maxbytes,
55 /* 5 */ kdp_readmem,
56 /* 6 */ kdp_writemem,
57 /* 7 */ kdp_readregs,
58 /* 8 */ kdp_writeregs,
59 /* 9 */ kdp_unknown,
60 /* A */ kdp_unknown,
61 /* B */ kdp_suspend,
62 /* C */ kdp_resumecpus,
63 /* D */ kdp_unknown,
64 /* E */ kdp_unknown,
65 };
66
67 kdp_glob_t kdp;
68 int kdp_flag=0;
69
70 boolean_t
71 kdp_packet(
72 unsigned char *pkt,
73 int *len,
74 unsigned short *reply_port
75 )
76 {
77 static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt
78 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt;
79 int plen = *len;
80 unsigned int req;
81 boolean_t ret;
82
83 #if DO_ALIGN
84 bcopy((char *)pkt, (char *)rd, sizeof(aligned_pkt));
85 #else
86 rd = (kdp_pkt_t *)pkt;
87 #endif
88 if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) {
89 printf("kdp_packet bad len pkt %d hdr %d\n", plen, rd->hdr.len);
90
91 return (FALSE);
92 }
93
94 if (rd->hdr.is_reply) {
95 printf("kdp_packet reply recvd req %x seq %x\n",
96 rd->hdr.request, rd->hdr.seq);
97
98 return (FALSE);
99 }
100
101 req = rd->hdr.request;
102 if (req < KDP_CONNECT || req > KDP_TERMINATION) {
103 printf("kdp_packet bad request %x len %d seq %x key %x\n",
104 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
105
106 return (FALSE);
107 }
108
109 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port));
110 #if DO_ALIGN
111 bcopy((char *)rd, (char *) pkt, *len);
112 #endif
113 return ret;
114 }
115
116 static boolean_t
117 kdp_unknown(
118 kdp_pkt_t *pkt,
119 int *len,
120 unsigned short *reply_port
121 )
122 {
123 kdp_pkt_t *rd = (kdp_pkt_t *)pkt;
124
125 printf("kdp_unknown request %x len %d seq %x key %x\n",
126 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
127
128 return (FALSE);
129 }
130
131 static boolean_t
132 kdp_connect(
133 kdp_pkt_t *pkt,
134 int *len,
135 unsigned short *reply_port
136 )
137 {
138 kdp_connect_req_t *rq = &pkt->connect_req;
139 int plen = *len;
140 kdp_connect_reply_t *rp = &pkt->connect_reply;
141
142 if (plen < sizeof (*rq))
143 return (FALSE);
144
145 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting));
146
147 if (kdp.is_conn) {
148 if (rq->hdr.seq == kdp.conn_seq) /* duplicate request */
149 rp->error = KDPERR_NO_ERROR;
150 else
151 rp->error = KDPERR_ALREADY_CONNECTED;
152 }
153 else {
154 kdp.reply_port = rq->req_reply_port;
155 kdp.exception_port = rq->exc_note_port;
156 kdp.is_conn = TRUE;
157 kdp.conn_seq = rq->hdr.seq;
158
159 rp->error = KDPERR_NO_ERROR;
160 }
161
162 rp->hdr.is_reply = 1;
163 rp->hdr.len = sizeof (*rp);
164
165 *reply_port = kdp.reply_port;
166 *len = rp->hdr.len;
167
168 if (current_debugger == KDP_CUR_DB)
169 active_debugger=1;
170
171 return (TRUE);
172 }
173
174 static boolean_t
175 kdp_disconnect(
176 kdp_pkt_t *pkt,
177 int *len,
178 unsigned short *reply_port
179 )
180 {
181 kdp_disconnect_req_t *rq = &pkt->disconnect_req;
182 int plen = *len;
183 kdp_disconnect_reply_t *rp = &pkt->disconnect_reply;
184
185 if (plen < sizeof (*rq))
186 return (FALSE);
187
188 if (!kdp.is_conn)
189 return (FALSE);
190
191 dprintf(("kdp_disconnect\n"));
192
193 *reply_port = kdp.reply_port;
194
195 kdp.reply_port = kdp.exception_port = 0;
196 kdp.is_halted = kdp.is_conn = FALSE;
197 kdp.exception_seq = kdp.conn_seq = 0;
198
199 rp->hdr.is_reply = 1;
200 rp->hdr.len = sizeof (*rp);
201
202 *len = rp->hdr.len;
203
204 if (current_debugger == KDP_CUR_DB)
205 active_debugger=0;
206
207 return (TRUE);
208 }
209
210 static boolean_t
211 kdp_hostinfo(
212 kdp_pkt_t *pkt,
213 int *len,
214 unsigned short *reply_port
215 )
216 {
217 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req;
218 int plen = *len;
219 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
220
221 if (plen < sizeof (*rq))
222 return (FALSE);
223
224 rp->hdr.is_reply = 1;
225 rp->hdr.len = sizeof (*rp);
226
227 kdp_machine_hostinfo(&rp->hostinfo);
228
229 *reply_port = kdp.reply_port;
230 *len = rp->hdr.len;
231
232 return (TRUE);
233 }
234
235 static boolean_t
236 kdp_suspend(
237 kdp_pkt_t *pkt,
238 int *len,
239 unsigned short *reply_port
240 )
241 {
242 kdp_suspend_req_t *rq = &pkt->suspend_req;
243 int plen = *len;
244 kdp_suspend_reply_t *rp = &pkt->suspend_reply;
245
246 if (plen < sizeof (*rq))
247 return (FALSE);
248
249 rp->hdr.is_reply = 1;
250 rp->hdr.len = sizeof (*rp);
251
252 dprintf(("kdp_suspend\n"));
253
254 kdp.is_halted = TRUE;
255
256 *reply_port = kdp.reply_port;
257 *len = rp->hdr.len;
258
259 return (TRUE);
260 }
261
262 static boolean_t
263 kdp_resumecpus(
264 kdp_pkt_t *pkt,
265 int *len,
266 unsigned short *reply_port
267 )
268 {
269 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req;
270 int plen = *len;
271 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply;
272
273 if (plen < sizeof (*rq))
274 return (FALSE);
275
276 rp->hdr.is_reply = 1;
277 rp->hdr.len = sizeof (*rp);
278
279 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask));
280
281 kdp.is_halted = FALSE;
282
283 *reply_port = kdp.reply_port;
284 *len = rp->hdr.len;
285
286 return (TRUE);
287 }
288
289 static boolean_t
290 kdp_writemem(
291 kdp_pkt_t *pkt,
292 int *len,
293 unsigned short *reply_port
294 )
295 {
296 kdp_writemem_req_t *rq = &pkt->writemem_req;
297 int plen = *len;
298 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
299 int cnt;
300
301 if (plen < sizeof (*rq))
302 return (FALSE);
303
304 if (rq->nbytes > MAX_KDP_DATA_SIZE)
305 rp->error = KDPERR_BAD_NBYTES;
306 else {
307 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes));
308
309 cnt = kdp_vm_write((caddr_t)rq->data, (caddr_t)rq->address, rq->nbytes);
310 rp->error = KDPERR_NO_ERROR;
311 }
312
313 rp->hdr.is_reply = 1;
314 rp->hdr.len = sizeof (*rp);
315
316 *reply_port = kdp.reply_port;
317 *len = rp->hdr.len;
318
319 return (TRUE);
320 }
321
322 static boolean_t
323 kdp_readmem(
324 kdp_pkt_t *pkt,
325 int *len,
326 unsigned short *reply_port
327 )
328 {
329 kdp_readmem_req_t *rq = &pkt->readmem_req;
330 int plen = *len;
331 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
332 int cnt;
333
334 if (plen < sizeof (*rq))
335 return (FALSE);
336
337 rp->hdr.is_reply = 1;
338 rp->hdr.len = sizeof (*rp);
339
340 if (rq->nbytes > MAX_KDP_DATA_SIZE)
341 rp->error = KDPERR_BAD_NBYTES;
342 else {
343 unsigned int n = rq->nbytes;
344
345 dprintf(("kdp_readmem addr %x size %d\n", rq->address, rq->nbytes));
346
347 cnt = kdp_vm_read((caddr_t)rq->address, (caddr_t)rp->data, rq->nbytes);
348 rp->error = KDPERR_NO_ERROR;
349
350 rp->hdr.len += cnt;
351 }
352
353 *reply_port = kdp.reply_port;
354 *len = rp->hdr.len;
355
356 return (TRUE);
357 }
358
359 static boolean_t
360 kdp_maxbytes(
361 kdp_pkt_t *pkt,
362 int *len,
363 unsigned short *reply_port
364 )
365 {
366 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req;
367 int plen = *len;
368 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply;
369
370 if (plen < sizeof (*rq))
371 return (FALSE);
372
373 rp->hdr.is_reply = 1;
374 rp->hdr.len = sizeof (*rp);
375
376 dprintf(("kdp_maxbytes\n"));
377
378 rp->max_bytes = MAX_KDP_DATA_SIZE;
379
380 *reply_port = kdp.reply_port;
381 *len = rp->hdr.len;
382
383 return (TRUE);
384 }
385
386 static boolean_t
387 kdp_regions(
388 kdp_pkt_t *pkt,
389 int *len,
390 unsigned short *reply_port
391 )
392 {
393 kdp_regions_req_t *rq = &pkt->regions_req;
394 int plen = *len;
395 kdp_regions_reply_t *rp = &pkt->regions_reply;
396 kdp_region_t *r;
397
398 if (plen < sizeof (*rq))
399 return (FALSE);
400
401 rp->hdr.is_reply = 1;
402 rp->hdr.len = sizeof (*rp);
403
404 dprintf(("kdp_regions\n"));
405
406 r = rp->regions;
407 rp->nregions = 0;
408
409 (vm_offset_t)r->address = 0;
410 r->nbytes = 0xffffffff;
411
412 r->protection = VM_PROT_ALL; r++; rp->nregions++;
413
414 rp->hdr.len += rp->nregions * sizeof (kdp_region_t);
415
416 *reply_port = kdp.reply_port;
417 *len = rp->hdr.len;
418
419 return (TRUE);
420 }
421
422 static boolean_t
423 kdp_writeregs(
424 kdp_pkt_t *pkt,
425 int *len,
426 unsigned short *reply_port
427 )
428 {
429 kdp_writeregs_req_t *rq = &pkt->writeregs_req;
430 int plen = *len;
431 int size;
432 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
433
434 if (plen < sizeof (*rq))
435 return (FALSE);
436
437 size = rq->hdr.len - sizeof(kdp_hdr_t) - sizeof(unsigned int);
438 rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size);
439
440 rp->hdr.is_reply = 1;
441 rp->hdr.len = sizeof (*rp);
442
443 *reply_port = kdp.reply_port;
444 *len = rp->hdr.len;
445
446 return (TRUE);
447 }
448
449 static boolean_t
450 kdp_readregs(
451 kdp_pkt_t *pkt,
452 int *len,
453 unsigned short *reply_port
454 )
455 {
456 kdp_readregs_req_t *rq = &pkt->readregs_req;
457 int plen = *len;
458 kdp_readregs_reply_t *rp = &pkt->readregs_reply;
459 int size;
460
461 if (plen < sizeof (*rq))
462 return (FALSE);
463
464 rp->hdr.is_reply = 1;
465 rp->hdr.len = sizeof (*rp);
466
467 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size);
468 rp->hdr.len += size;
469
470 *reply_port = kdp.reply_port;
471 *len = rp->hdr.len;
472
473 return (TRUE);
474 }