summaryrefslogtreecommitdiff
path: root/ocaml-binary-annot/debugger/debugcom.ml
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml-binary-annot/debugger/debugcom.ml')
-rw-r--r--ocaml-binary-annot/debugger/debugcom.ml298
1 files changed, 298 insertions, 0 deletions
diff --git a/ocaml-binary-annot/debugger/debugcom.ml b/ocaml-binary-annot/debugger/debugcom.ml
new file mode 100644
index 0000000000..dfe905bac4
--- /dev/null
+++ b/ocaml-binary-annot/debugger/debugcom.ml
@@ -0,0 +1,298 @@
+(***********************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
+(* Objective Caml port by John Malecki and Xavier Leroy *)
+(* *)
+(* Copyright 1996 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(* Low-level communication with the debuggee *)
+
+open Int64ops
+open Primitives
+
+(* The current connection with the debuggee *)
+
+let conn = ref Primitives.std_io
+
+(* Set which process the debugger follows on fork. *)
+
+type follow_fork_mode =
+ Fork_child
+ | Fork_parent
+
+let fork_mode = ref Fork_parent
+
+let update_follow_fork_mode () =
+ let a = match !fork_mode with Fork_child -> 0 | Fork_parent -> 1 in
+ output_char !conn.io_out 'K';
+ output_binary_int !conn.io_out a
+
+(* Set the current connection, and update the fork mode in case it has
+ * changed. *)
+
+let set_current_connection io_chan =
+ conn := io_chan;
+ update_follow_fork_mode ()
+
+(* Modify the program code *)
+
+let set_event pos =
+ output_char !conn.io_out 'e';
+ output_binary_int !conn.io_out pos
+
+let set_breakpoint pos =
+ output_char !conn.io_out 'B';
+ output_binary_int !conn.io_out pos
+
+let reset_instr pos =
+ output_char !conn.io_out 'i';
+ output_binary_int !conn.io_out pos
+
+(* Basic commands for flow control *)
+
+type execution_summary =
+ Event
+ | Breakpoint
+ | Exited
+ | Trap_barrier
+ | Uncaught_exc
+
+type report = {
+ rep_type : execution_summary;
+ rep_event_count : int;
+ rep_stack_pointer : int;
+ rep_program_pointer : int
+}
+
+type checkpoint_report =
+ Checkpoint_done of int
+ | Checkpoint_failed
+
+(* Run the debuggee for N events *)
+
+let do_go_smallint n =
+ output_char !conn.io_out 'g';
+ output_binary_int !conn.io_out n;
+ flush !conn.io_out;
+ Input_handling.execute_with_other_controller
+ Input_handling.exit_main_loop
+ !conn
+ (function () ->
+ Input_handling.main_loop ();
+ let summary =
+ match input_char !conn.io_in with
+ 'e' -> Event
+ | 'b' -> Breakpoint
+ | 'x' -> Exited
+ | 's' -> Trap_barrier
+ | 'u' -> Uncaught_exc
+ | _ -> Misc.fatal_error "Debugcom.do_go" in
+ let event_counter = input_binary_int !conn.io_in in
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ { rep_type = summary;
+ rep_event_count = event_counter;
+ rep_stack_pointer = stack_pos;
+ rep_program_pointer = pc })
+
+let rec do_go n =
+ assert (n >= _0);
+ if n > max_small_int then(
+ ignore (do_go_smallint max_int);
+ do_go (n -- max_small_int)
+ )else(
+ do_go_smallint (Int64.to_int n)
+ )
+;;
+
+(* Perform a checkpoint *)
+
+let do_checkpoint () =
+ match Sys.os_type with
+ "Win32" -> failwith "do_checkpoint"
+ | _ ->
+ output_char !conn.io_out 'c';
+ flush !conn.io_out;
+ let pid = input_binary_int !conn.io_in in
+ if pid = -1 then Checkpoint_failed else Checkpoint_done pid
+
+(* Kill the given process. *)
+let stop chan =
+ try
+ output_char chan.io_out 's';
+ flush chan.io_out
+ with
+ Sys_error _ | End_of_file -> ()
+
+(* Ask a process to wait for its child which has been killed. *)
+(* (so as to eliminate zombies). *)
+let wait_child chan =
+ try
+ output_char chan.io_out 'w'
+ with
+ Sys_error _ | End_of_file -> ()
+
+(* Move to initial frame (that of current function). *)
+(* Return stack position and current pc *)
+
+let initial_frame () =
+ output_char !conn.io_out '0';
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+let set_initial_frame () =
+ ignore(initial_frame ())
+
+(* Move up one frame *)
+(* Return stack position and current pc.
+ If there's no frame above, return (-1, 0). *)
+
+let up_frame stacksize =
+ output_char !conn.io_out 'U';
+ output_binary_int !conn.io_out stacksize;
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = if stack_pos = -1 then 0 else input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+(* Get and set the current frame position *)
+
+let get_frame () =
+ output_char !conn.io_out 'f';
+ flush !conn.io_out;
+ let stack_pos = input_binary_int !conn.io_in in
+ let pc = input_binary_int !conn.io_in in
+ (stack_pos, pc)
+
+let set_frame stack_pos =
+ output_char !conn.io_out 'S';
+ output_binary_int !conn.io_out stack_pos
+
+(* Set the trap barrier to given stack position. *)
+
+let set_trap_barrier pos =
+ output_char !conn.io_out 'b';
+ output_binary_int !conn.io_out pos
+
+(* Handling of remote values *)
+
+let value_size = if 1 lsl 31 = 0 then 4 else 8
+
+let input_remote_value ic =
+ let v = String.create value_size in
+ really_input ic v 0 value_size; v
+
+let output_remote_value ic v =
+ output ic v 0 value_size
+
+exception Marshalling_error
+
+module Remote_value =
+ struct
+ type t = Remote of string | Local of Obj.t
+
+ let obj = function
+ | Local obj -> Obj.obj obj
+ | Remote v ->
+ output_char !conn.io_out 'M';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ try
+ input_value !conn.io_in
+ with End_of_file | Failure _ ->
+ raise Marshalling_error
+
+ let is_block = function
+ | Local obj -> Obj.is_block obj
+ | Remote v -> Obj.is_block (Array.unsafe_get (Obj.magic v : Obj.t array) 0)
+
+ let tag = function
+ | Local obj -> Obj.tag obj
+ | Remote v ->
+ output_char !conn.io_out 'H';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ let header = input_binary_int !conn.io_in in
+ header land 0xFF
+
+ let size = function
+ | Local obj -> Obj.size obj
+ | Remote v ->
+ output_char !conn.io_out 'H';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ let header = input_binary_int !conn.io_in in
+ if header land 0xFF = Obj.double_array_tag && Sys.word_size = 32
+ then header lsr 11
+ else header lsr 10
+
+ let field v n =
+ match v with
+ | Local obj -> Local(Obj.field obj n)
+ | Remote v ->
+ output_char !conn.io_out 'F';
+ output_remote_value !conn.io_out v;
+ output_binary_int !conn.io_out n;
+ flush !conn.io_out;
+ if input_byte !conn.io_in = 0 then
+ Remote(input_remote_value !conn.io_in)
+ else begin
+ let buf = String.create 8 in
+ really_input !conn.io_in buf 0 8;
+ let floatbuf = float n (* force allocation of a new float *) in
+ String.unsafe_blit buf 0 (Obj.magic floatbuf) 0 8;
+ Local(Obj.repr floatbuf)
+ end
+
+ let of_int n =
+ Local(Obj.repr n)
+
+ let local pos =
+ output_char !conn.io_out 'L';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ Remote(input_remote_value !conn.io_in)
+
+ let from_environment pos =
+ output_char !conn.io_out 'E';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ Remote(input_remote_value !conn.io_in)
+
+ let global pos =
+ output_char !conn.io_out 'G';
+ output_binary_int !conn.io_out pos;
+ flush !conn.io_out;
+ Remote(input_remote_value !conn.io_in)
+
+ let accu () =
+ output_char !conn.io_out 'A';
+ flush !conn.io_out;
+ Remote(input_remote_value !conn.io_in)
+
+ let closure_code = function
+ | Local obj -> assert false
+ | Remote v ->
+ output_char !conn.io_out 'C';
+ output_remote_value !conn.io_out v;
+ flush !conn.io_out;
+ input_binary_int !conn.io_in
+
+ let same rv1 rv2 =
+ match (rv1, rv2) with
+ (Local obj1, Local obj2) -> obj1 == obj2
+ | (Remote v1, Remote v2) -> v1 = v2
+ (* string equality -> equality of remote pointers *)
+ | (_, _) -> false
+
+ end