ia64/xen-unstable

view tools/debugger/pdb/pdb_caml_process.c @ 6538:84ee014ebd41

Merge xen-vtx-unstable.hg
author adsharma@los-vmm.sc.intel.com
date Wed Aug 17 12:34:38 2005 -0800 (2005-08-17)
parents 23979fb12c49 60d20acf8928
children 99914b54f7bf
line source
1 /*
2 * pdb_caml_process.c
3 *
4 * http://www.cl.cam.ac.uk/netos/pdb
5 *
6 * PDB's OCaml interface library for debugging processes
7 */
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <caml/alloc.h>
14 #include <caml/fail.h>
15 #include <caml/memory.h>
16 #include <caml/mlvalues.h>
18 #include <xc.h>
19 #include <xen/xen.h>
20 #include <xen/io/domain_controller.h>
21 #include <xen/linux/privcmd.h>
22 #include "pdb_module.h"
23 #include "pdb_caml_xen.h"
25 typedef struct
26 {
27 int domain;
28 int process;
29 int evtchn;
30 pdb_front_ring_t *ring;
31 } context_t;
33 #define decode_context(_ctx, _ocaml) \
34 { \
35 (_ctx)->domain = Int_val(Field((_ocaml),0)); \
36 (_ctx)->process = Int_val(Field((_ocaml),1)); \
37 (_ctx)->evtchn = Int_val(Field((_ocaml),2)); \
38 (_ctx)->ring = (pdb_front_ring_t *)Int32_val(Field((_ocaml),3)); \
39 }
41 #define encode_context(_ctx, _ocaml) \
42 { \
43 (_ocaml) = caml_alloc_tuple(2); \
44 Store_field((_ocaml), 0, Val_int((_ctx)->domain)); \
45 Store_field((_ocaml), 1, Val_int((_ctx)->process)); \
46 }
48 /*
49 * send a request to a pdb domain backend.
50 *
51 * puts the request on a ring and kicks the backend using an event channel.
52 */
53 static void
54 send_request (pdb_front_ring_t *pdb_ring, int evtchn, pdb_request_t *request)
55 {
56 pdb_request_t *req;
58 req = RING_GET_REQUEST(pdb_ring, pdb_ring->req_prod_pvt);
60 memcpy(req, request, sizeof(pdb_request_t));
62 pdb_ring->req_prod_pvt++;
64 RING_PUSH_REQUESTS(pdb_ring);
65 xc_evtchn_send(xc_handle, evtchn);
66 }
68 /*
69 * process_handle_response : int32 -> int * int * string
70 *
71 * A backend domain has notified pdb (via an event channel)
72 * that a command has finished.
73 * We read the result from the channel and formulate a response
74 * as a single string. Also return the domain and process.
75 */
77 static inline unsigned int
78 _flip (unsigned int orig)
79 {
80 return (((orig << 24) & 0xff000000) | ((orig << 8) & 0x00ff0000) |
81 ((orig >> 8) & 0x0000ff00) | ((orig >> 24) & 0x000000ff));
82 }
84 value
85 process_handle_response (value ring)
86 {
87 CAMLparam1(ring);
88 CAMLlocal2(result, str);
90 RING_IDX rp;
91 pdb_response_p resp;
92 pdb_front_ring_t *my_ring = (pdb_front_ring_t *)Int32_val(ring);
93 char msg[2048];
94 int msglen;
96 memset(msg, 0, sizeof(msg));
98 rp = my_ring->sring->rsp_prod;
99 rmb(); /* Ensure we see queued responses up to 'rp'. */
101 /* default response is OK unless the command has something
102 more interesting to say */
103 sprintf(msg, "OK");
105 if (my_ring->rsp_cons != rp)
106 {
107 resp = RING_GET_RESPONSE(my_ring, my_ring->rsp_cons);
109 switch (resp->operation)
110 {
111 case PDB_OPCODE_PAUSE :
112 case PDB_OPCODE_ATTACH :
113 case PDB_OPCODE_DETACH :
114 break;
116 case PDB_OPCODE_RD_REG :
117 {
118 sprintf(&msg[0], "%08x", _flip(resp->u.rd_reg.value));
119 break;
120 }
122 case PDB_OPCODE_RD_REGS :
123 {
124 int loop;
125 pdb_op_rd_regs_p regs = &resp->u.rd_regs;
127 for (loop = 0; loop < GDB_REGISTER_FRAME_SIZE * 8; loop += 8)
128 {
129 sprintf(&msg[loop], "%08x", _flip(regs->reg[loop >> 3]));
130 }
132 break;
133 }
134 case PDB_OPCODE_WR_REG :
135 {
136 /* should check the return status */
137 break;
138 }
140 case PDB_OPCODE_RD_MEM :
141 {
142 int loop;
143 pdb_op_rd_mem_resp_p mem = &resp->u.rd_mem;
145 for (loop = 0; loop < mem->length; loop ++)
146 {
147 sprintf(&msg[loop * 2], "%02x", mem->data[loop]);
148 }
149 break;
150 }
151 case PDB_OPCODE_WR_MEM :
152 {
153 /* should check the return status */
154 break;
155 }
157 /* this is equivalent to process_xen_virq */
158 case PDB_OPCODE_CONTINUE :
159 {
160 sprintf(msg, "S05");
161 break;
162 }
163 case PDB_OPCODE_STEP :
164 {
165 sprintf(msg, "S05");
166 break;
167 }
169 case PDB_OPCODE_SET_BKPT :
170 case PDB_OPCODE_CLR_BKPT :
171 case PDB_OPCODE_SET_WATCHPT :
172 case PDB_OPCODE_CLR_WATCHPT :
173 {
174 break;
175 }
177 case PDB_OPCODE_WATCHPOINT :
178 {
179 sprintf(msg, "S05");
180 break;
181 }
183 default :
184 printf("(linux) UNKNOWN MESSAGE TYPE IN RESPONSE %d\n",
185 resp->operation);
186 break;
187 }
189 my_ring->rsp_cons++;
190 }
192 msglen = strlen(msg);
193 result = caml_alloc(3,0);
194 str = alloc_string(msglen);
195 memmove(&Byte(str,0), msg, msglen);
197 Store_field(result, 0, Val_int(resp->domain));
198 Store_field(result, 1, Val_int(resp->process));
199 Store_field(result, 2, str);
201 CAMLreturn(result);
202 }
204 /*
205 * proc_attach_debugger : context_t -> unit
206 */
207 value
208 proc_attach_debugger (value context)
209 {
210 CAMLparam1(context);
211 context_t ctx;
212 pdb_request_t req;
214 decode_context(&ctx, context);
216 req.operation = PDB_OPCODE_ATTACH;
217 req.u.attach.domain = ctx.domain;
218 req.process = ctx.process;
220 send_request (ctx.ring, ctx.evtchn, &req);
222 CAMLreturn(Val_unit);
223 }
226 /*
227 * proc_detach_debugger : context_t -> unit
228 */
229 value
230 proc_detach_debugger (value context)
231 {
232 CAMLparam1(context);
233 context_t ctx;
234 pdb_request_t req;
236 decode_context(&ctx, context);
238 printf("(pdb) detach process [%d.%d] %d %p\n", ctx.domain, ctx.process,
239 ctx.evtchn, ctx.ring);
240 fflush(stdout);
242 req.operation = PDB_OPCODE_DETACH;
243 req.process = ctx.process;
245 send_request (ctx.ring, ctx.evtchn, &req);
247 CAMLreturn(Val_unit);
248 }
251 /*
252 * proc_pause_target : int -> unit
253 */
254 value
255 proc_pause_target (value context)
256 {
257 CAMLparam1(context);
258 context_t ctx;
259 pdb_request_t req;
261 decode_context(&ctx, context);
263 printf("(pdb) pause target %d %d\n", ctx.domain, ctx.process);
264 fflush(stdout);
266 req.operation = PDB_OPCODE_PAUSE;
267 req.process = ctx.process;
269 send_request (ctx.ring, ctx.evtchn, &req);
271 CAMLreturn(Val_unit);
272 }
275 /*
276 * proc_read_register : context_t -> int -> unit
277 */
278 value
279 proc_read_register (value context, value reg)
280 {
281 CAMLparam1(context);
283 pdb_request_t req;
284 context_t ctx;
285 int my_reg = Int_val(reg);
287 decode_context(&ctx, context);
289 req.operation = PDB_OPCODE_RD_REG;
290 req.process = ctx.process;
291 req.u.rd_reg.reg = my_reg;
292 req.u.rd_reg.value = 0;
294 send_request (ctx.ring, ctx.evtchn, &req);
296 CAMLreturn(Val_unit);
297 }
301 /*
302 * proc_read_registers : context_t -> unit
303 */
304 value
305 proc_read_registers (value context)
306 {
307 CAMLparam1(context);
309 pdb_request_t req;
310 context_t ctx;
312 decode_context(&ctx, context);
314 req.operation = PDB_OPCODE_RD_REGS;
315 req.process = ctx.process;
317 send_request (ctx.ring, ctx.evtchn, &req);
319 CAMLreturn(Val_unit);
320 }
323 /*
324 * proc_write_register : context_t -> register -> int32 -> unit
325 */
326 value
327 proc_write_register (value context, value reg, value newval)
328 {
329 CAMLparam3(context, reg, newval);
331 int my_reg = Int_val(reg);
332 unsigned long my_newval = Int32_val(newval);
334 context_t ctx;
335 pdb_request_t req;
337 decode_context(&ctx, context);
339 req.operation = PDB_OPCODE_WR_REG;
340 req.process = ctx.process;
341 req.u.wr_reg.value = my_newval;
343 switch (my_reg)
344 {
345 case GDB_EAX: req.u.wr_reg.reg = LINUX_EAX; break;
346 case GDB_ECX: req.u.wr_reg.reg = LINUX_ECX; break;
347 case GDB_EDX: req.u.wr_reg.reg = LINUX_EDX; break;
348 case GDB_EBX: req.u.wr_reg.reg = LINUX_EBX; break;
350 case GDB_ESP: req.u.wr_reg.reg = LINUX_ESP; break;
351 case GDB_EBP: req.u.wr_reg.reg = LINUX_EBP; break;
352 case GDB_ESI: req.u.wr_reg.reg = LINUX_ESI; break;
353 case GDB_EDI: req.u.wr_reg.reg = LINUX_EDI; break;
355 case GDB_EIP: req.u.wr_reg.reg = LINUX_EIP; break;
356 case GDB_EFL: req.u.wr_reg.reg = LINUX_EFL; break;
358 case GDB_CS: req.u.wr_reg.reg = LINUX_CS; break;
359 case GDB_SS: req.u.wr_reg.reg = LINUX_SS; break;
360 case GDB_DS: req.u.wr_reg.reg = LINUX_DS; break;
361 case GDB_ES: req.u.wr_reg.reg = LINUX_ES; break;
362 case GDB_FS: req.u.wr_reg.reg = LINUX_FS; break;
363 case GDB_GS: req.u.wr_reg.reg = LINUX_GS; break;
364 }
366 send_request(ctx.ring, ctx.evtchn, &req);
368 CAMLreturn(Val_unit);
369 }
372 /*
373 * proc_read_memory : context_t -> int32 -> int -> unit
374 */
375 value
376 proc_read_memory (value context, value address, value length)
377 {
378 CAMLparam3(context, address, length);
380 context_t ctx;
381 pdb_request_t req;
383 decode_context(&ctx, context);
385 req.operation = PDB_OPCODE_RD_MEM;
386 req.process = ctx.process;
387 req.u.rd_mem.address = Int32_val(address);
388 req.u.rd_mem.length = Int_val(length);
390 send_request(ctx.ring, ctx.evtchn, &req);
392 CAMLreturn(Val_unit);
393 }
396 /*
397 * proc_write_memory : context_t -> int32 -> int list -> unit
398 */
399 value
400 proc_write_memory (value context, value address, value val_list)
401 {
402 CAMLparam3(context, address, val_list);
403 CAMLlocal1(node);
405 context_t ctx;
406 pdb_request_t req;
407 u32 length = 0;
409 decode_context(&ctx, context);
411 req.operation = PDB_OPCODE_WR_MEM;
412 req.process = ctx.process;
414 node = val_list;
415 if ( Int_val(node) == 0 ) /* gdb functionalty test uses empty list */
416 {
417 req.u.wr_mem.address = Int32_val(address);
418 req.u.wr_mem.length = 0;
419 }
420 else
421 {
422 while ( Int_val(Field(node,1)) != 0 )
423 {
424 req.u.wr_mem.data[length++] = Int_val(Field(node, 0));
425 node = Field(node,1);
426 }
427 req.u.wr_mem.data[length++] = Int_val(Field(node, 0));
429 req.u.wr_mem.address = Int32_val(address);
430 req.u.wr_mem.length = length;
431 }
433 send_request(ctx.ring, ctx.evtchn, &req);
435 CAMLreturn(Val_unit);
436 }
439 /*
440 * proc_continue_target : context_t -> unit
441 */
442 value
443 proc_continue_target (value context)
444 {
445 CAMLparam1(context);
447 context_t ctx;
448 pdb_request_t req;
450 decode_context(&ctx, context);
452 req.operation = PDB_OPCODE_CONTINUE;
453 req.process = ctx.process;
455 send_request(ctx.ring, ctx.evtchn, &req);
457 CAMLreturn(Val_unit);
458 }
460 /*
461 * proc_step_target : context_t -> unit
462 */
463 value
464 proc_step_target (value context)
465 {
466 CAMLparam1(context);
468 context_t ctx;
469 pdb_request_t req;
471 decode_context(&ctx, context);
473 req.operation = PDB_OPCODE_STEP;
474 req.process = ctx.process;
476 send_request(ctx.ring, ctx.evtchn, &req);
478 CAMLreturn(Val_unit);
479 }
483 /*
484 * proc_insert_memory_breakpoint : context_t -> int32 -> int -> unit
485 */
486 value
487 proc_insert_memory_breakpoint (value context, value address, value length)
488 {
489 CAMLparam3(context, address, length);
491 context_t ctx;
492 pdb_request_t req;
494 decode_context(&ctx, context);
496 req.operation = PDB_OPCODE_SET_BKPT;
497 req.process = ctx.process;
498 req.u.bkpt.address = (memory_t) Int32_val(address);
499 req.u.bkpt.length = Int_val(length);
501 send_request(ctx.ring, ctx.evtchn, &req);
503 CAMLreturn(Val_unit);
504 }
506 /*
507 * proc_remove_memory_breakpoint : context_t -> int32 -> int -> unit
508 */
509 value
510 proc_remove_memory_breakpoint (value context, value address, value length)
511 {
512 CAMLparam3(context, address, length);
514 context_t ctx;
515 pdb_request_t req;
517 decode_context(&ctx, context);
519 req.operation = PDB_OPCODE_CLR_BKPT;
520 req.process = ctx.process;
521 req.u.bkpt.address = (memory_t) Int32_val(address);
522 req.u.bkpt.length = Int_val(length);
524 send_request(ctx.ring, ctx.evtchn, &req);
526 CAMLreturn(Val_unit);
527 }
529 /*
530 * proc_insert_watchpoint : context_t -> bwcpoint_t -> int32 -> int -> unit
531 */
532 value
533 proc_insert_watchpoint (value context, value kind, value address, value length)
534 {
535 CAMLparam3(context, address, length);
537 context_t ctx;
538 pdb_request_t req;
540 decode_context(&ctx, context);
542 req.operation = PDB_OPCODE_SET_WATCHPT;
543 req.process = ctx.process;
544 req.u.watchpt.type = Int_val(kind);
545 req.u.watchpt.address = (memory_t) Int32_val(address);
546 req.u.watchpt.length = Int_val(length);
548 send_request(ctx.ring, ctx.evtchn, &req);
550 CAMLreturn(Val_unit);
551 }
553 /*
554 * proc_remove_watchpoint : context_t -> bwcpoint_t -> int32 -> int -> unit
555 */
556 value
557 proc_remove_watchpoint (value context, value kind, value address, value length)
558 {
559 CAMLparam3(context, address, length);
561 context_t ctx;
562 pdb_request_t req;
564 decode_context(&ctx, context);
566 req.operation = PDB_OPCODE_CLR_WATCHPT;
567 req.process = ctx.process;
568 req.u.watchpt.type = Int_val(kind);
569 req.u.watchpt.address = (memory_t) Int32_val(address);
570 req.u.watchpt.length = Int_val(length);
572 send_request(ctx.ring, ctx.evtchn, &req);
574 CAMLreturn(Val_unit);
575 }
578 /*
579 * Local variables:
580 * mode: C
581 * c-set-style: "BSD"
582 * c-basic-offset: 4
583 * tab-width: 4
584 * indent-tabs-mode: nil
585 * End:
586 */