/debugger/debugcom.ml

http://github.com/multani/ocaml-mirror · OCaml · 298 lines · 209 code · 55 blank · 34 comment · 13 complexity · 3fe40122c196cd0ade4ae04d85c28336 MD5 · raw file

  1. (***********************************************************************)
  2. (* *)
  3. (* OCaml *)
  4. (* *)
  5. (* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
  6. (* OCaml port by John Malecki and Xavier Leroy *)
  7. (* *)
  8. (* Copyright 1996 Institut National de Recherche en Informatique et *)
  9. (* en Automatique. All rights reserved. This file is distributed *)
  10. (* under the terms of the Q Public License version 1.0. *)
  11. (* *)
  12. (***********************************************************************)
  13. (* $Id$ *)
  14. (* Low-level communication with the debuggee *)
  15. open Int64ops
  16. open Primitives
  17. (* The current connection with the debuggee *)
  18. let conn = ref Primitives.std_io
  19. (* Set which process the debugger follows on fork. *)
  20. type follow_fork_mode =
  21. Fork_child
  22. | Fork_parent
  23. let fork_mode = ref Fork_parent
  24. let update_follow_fork_mode () =
  25. let a = match !fork_mode with Fork_child -> 0 | Fork_parent -> 1 in
  26. output_char !conn.io_out 'K';
  27. output_binary_int !conn.io_out a
  28. (* Set the current connection, and update the fork mode in case it has
  29. * changed. *)
  30. let set_current_connection io_chan =
  31. conn := io_chan;
  32. update_follow_fork_mode ()
  33. (* Modify the program code *)
  34. let set_event pos =
  35. output_char !conn.io_out 'e';
  36. output_binary_int !conn.io_out pos
  37. let set_breakpoint pos =
  38. output_char !conn.io_out 'B';
  39. output_binary_int !conn.io_out pos
  40. let reset_instr pos =
  41. output_char !conn.io_out 'i';
  42. output_binary_int !conn.io_out pos
  43. (* Basic commands for flow control *)
  44. type execution_summary =
  45. Event
  46. | Breakpoint
  47. | Exited
  48. | Trap_barrier
  49. | Uncaught_exc
  50. type report = {
  51. rep_type : execution_summary;
  52. rep_event_count : int;
  53. rep_stack_pointer : int;
  54. rep_program_pointer : int
  55. }
  56. type checkpoint_report =
  57. Checkpoint_done of int
  58. | Checkpoint_failed
  59. (* Run the debuggee for N events *)
  60. let do_go_smallint n =
  61. output_char !conn.io_out 'g';
  62. output_binary_int !conn.io_out n;
  63. flush !conn.io_out;
  64. Input_handling.execute_with_other_controller
  65. Input_handling.exit_main_loop
  66. !conn
  67. (function () ->
  68. Input_handling.main_loop ();
  69. let summary =
  70. match input_char !conn.io_in with
  71. 'e' -> Event
  72. | 'b' -> Breakpoint
  73. | 'x' -> Exited
  74. | 's' -> Trap_barrier
  75. | 'u' -> Uncaught_exc
  76. | _ -> Misc.fatal_error "Debugcom.do_go" in
  77. let event_counter = input_binary_int !conn.io_in in
  78. let stack_pos = input_binary_int !conn.io_in in
  79. let pc = input_binary_int !conn.io_in in
  80. { rep_type = summary;
  81. rep_event_count = event_counter;
  82. rep_stack_pointer = stack_pos;
  83. rep_program_pointer = pc })
  84. let rec do_go n =
  85. assert (n >= _0);
  86. if n > max_small_int then(
  87. ignore (do_go_smallint max_int);
  88. do_go (n -- max_small_int)
  89. )else(
  90. do_go_smallint (Int64.to_int n)
  91. )
  92. ;;
  93. (* Perform a checkpoint *)
  94. let do_checkpoint () =
  95. match Sys.os_type with
  96. "Win32" -> failwith "do_checkpoint"
  97. | _ ->
  98. output_char !conn.io_out 'c';
  99. flush !conn.io_out;
  100. let pid = input_binary_int !conn.io_in in
  101. if pid = -1 then Checkpoint_failed else Checkpoint_done pid
  102. (* Kill the given process. *)
  103. let stop chan =
  104. try
  105. output_char chan.io_out 's';
  106. flush chan.io_out
  107. with
  108. Sys_error _ | End_of_file -> ()
  109. (* Ask a process to wait for its child which has been killed. *)
  110. (* (so as to eliminate zombies). *)
  111. let wait_child chan =
  112. try
  113. output_char chan.io_out 'w'
  114. with
  115. Sys_error _ | End_of_file -> ()
  116. (* Move to initial frame (that of current function). *)
  117. (* Return stack position and current pc *)
  118. let initial_frame () =
  119. output_char !conn.io_out '0';
  120. flush !conn.io_out;
  121. let stack_pos = input_binary_int !conn.io_in in
  122. let pc = input_binary_int !conn.io_in in
  123. (stack_pos, pc)
  124. let set_initial_frame () =
  125. ignore(initial_frame ())
  126. (* Move up one frame *)
  127. (* Return stack position and current pc.
  128. If there's no frame above, return (-1, 0). *)
  129. let up_frame stacksize =
  130. output_char !conn.io_out 'U';
  131. output_binary_int !conn.io_out stacksize;
  132. flush !conn.io_out;
  133. let stack_pos = input_binary_int !conn.io_in in
  134. let pc = if stack_pos = -1 then 0 else input_binary_int !conn.io_in in
  135. (stack_pos, pc)
  136. (* Get and set the current frame position *)
  137. let get_frame () =
  138. output_char !conn.io_out 'f';
  139. flush !conn.io_out;
  140. let stack_pos = input_binary_int !conn.io_in in
  141. let pc = input_binary_int !conn.io_in in
  142. (stack_pos, pc)
  143. let set_frame stack_pos =
  144. output_char !conn.io_out 'S';
  145. output_binary_int !conn.io_out stack_pos
  146. (* Set the trap barrier to given stack position. *)
  147. let set_trap_barrier pos =
  148. output_char !conn.io_out 'b';
  149. output_binary_int !conn.io_out pos
  150. (* Handling of remote values *)
  151. let value_size = if 1 lsl 31 = 0 then 4 else 8
  152. let input_remote_value ic =
  153. let v = String.create value_size in
  154. really_input ic v 0 value_size; v
  155. let output_remote_value ic v =
  156. output ic v 0 value_size
  157. exception Marshalling_error
  158. module Remote_value =
  159. struct
  160. type t = Remote of string | Local of Obj.t
  161. let obj = function
  162. | Local obj -> Obj.obj obj
  163. | Remote v ->
  164. output_char !conn.io_out 'M';
  165. output_remote_value !conn.io_out v;
  166. flush !conn.io_out;
  167. try
  168. input_value !conn.io_in
  169. with End_of_file | Failure _ ->
  170. raise Marshalling_error
  171. let is_block = function
  172. | Local obj -> Obj.is_block obj
  173. | Remote v -> Obj.is_block (Array.unsafe_get (Obj.magic v : Obj.t array) 0)
  174. let tag = function
  175. | Local obj -> Obj.tag obj
  176. | Remote v ->
  177. output_char !conn.io_out 'H';
  178. output_remote_value !conn.io_out v;
  179. flush !conn.io_out;
  180. let header = input_binary_int !conn.io_in in
  181. header land 0xFF
  182. let size = function
  183. | Local obj -> Obj.size obj
  184. | Remote v ->
  185. output_char !conn.io_out 'H';
  186. output_remote_value !conn.io_out v;
  187. flush !conn.io_out;
  188. let header = input_binary_int !conn.io_in in
  189. if header land 0xFF = Obj.double_array_tag && Sys.word_size = 32
  190. then header lsr 11
  191. else header lsr 10
  192. let field v n =
  193. match v with
  194. | Local obj -> Local(Obj.field obj n)
  195. | Remote v ->
  196. output_char !conn.io_out 'F';
  197. output_remote_value !conn.io_out v;
  198. output_binary_int !conn.io_out n;
  199. flush !conn.io_out;
  200. if input_byte !conn.io_in = 0 then
  201. Remote(input_remote_value !conn.io_in)
  202. else begin
  203. let buf = String.create 8 in
  204. really_input !conn.io_in buf 0 8;
  205. let floatbuf = float n (* force allocation of a new float *) in
  206. String.unsafe_blit buf 0 (Obj.magic floatbuf) 0 8;
  207. Local(Obj.repr floatbuf)
  208. end
  209. let of_int n =
  210. Local(Obj.repr n)
  211. let local pos =
  212. output_char !conn.io_out 'L';
  213. output_binary_int !conn.io_out pos;
  214. flush !conn.io_out;
  215. Remote(input_remote_value !conn.io_in)
  216. let from_environment pos =
  217. output_char !conn.io_out 'E';
  218. output_binary_int !conn.io_out pos;
  219. flush !conn.io_out;
  220. Remote(input_remote_value !conn.io_in)
  221. let global pos =
  222. output_char !conn.io_out 'G';
  223. output_binary_int !conn.io_out pos;
  224. flush !conn.io_out;
  225. Remote(input_remote_value !conn.io_in)
  226. let accu () =
  227. output_char !conn.io_out 'A';
  228. flush !conn.io_out;
  229. Remote(input_remote_value !conn.io_in)
  230. let closure_code = function
  231. | Local obj -> assert false
  232. | Remote v ->
  233. output_char !conn.io_out 'C';
  234. output_remote_value !conn.io_out v;
  235. flush !conn.io_out;
  236. input_binary_int !conn.io_in
  237. let same rv1 rv2 =
  238. match (rv1, rv2) with
  239. (Local obj1, Local obj2) -> obj1 == obj2
  240. | (Remote v1, Remote v2) -> v1 = v2
  241. (* string equality -> equality of remote pointers *)
  242. | (_, _) -> false
  243. end