]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp.c
xnu-124.13.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
CommitLineData
1c79356b
A
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
35int kdp_vm_read( caddr_t, caddr_t, unsigned int);
36int 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
47static 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
67kdp_glob_t kdp;
68int kdp_flag=0;
69
70boolean_t
71kdp_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
116static boolean_t
117kdp_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
131static boolean_t
132kdp_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
174static boolean_t
175kdp_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
210static boolean_t
211kdp_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
235static boolean_t
236kdp_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
262static boolean_t
263kdp_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
289static boolean_t
290kdp_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
322static boolean_t
323kdp_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
359static boolean_t
360kdp_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
386static boolean_t
387kdp_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
422static boolean_t
423kdp_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
449static boolean_t
450kdp_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}