2016-02-18 07:11:59 -08:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* OCaml *)
|
|
|
|
(* *)
|
|
|
|
(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* OCaml 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 GNU Lesser General Public License version 2.1, with the *)
|
|
|
|
(* special exception on linking described in the file LICENSE. *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(******************************* Breakpoints ***************************)
|
|
|
|
|
2003-11-21 08:10:57 -08:00
|
|
|
open Checkpoints
|
|
|
|
open Debugcom
|
1996-11-29 08:55:09 -08:00
|
|
|
open Instruct
|
2019-05-02 08:05:15 -07:00
|
|
|
open Events
|
2003-11-21 08:10:57 -08:00
|
|
|
open Printf
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(*** Debugging. ***)
|
1997-03-21 05:31:13 -08:00
|
|
|
let debug_breakpoints = ref false
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(*** Data. ***)
|
|
|
|
|
|
|
|
(* Number of the last added breakpoint. *)
|
|
|
|
let breakpoint_number = ref 0
|
|
|
|
|
|
|
|
(* Breakpoint number -> event. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
type breakpoint_id = int
|
|
|
|
let breakpoints = ref ([] : (breakpoint_id * code_event) list)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Program counter -> breakpoint count. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
let positions = ref ([] : (pc * int ref) list)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Versions of the breakpoint list. *)
|
|
|
|
let current_version = ref 0
|
|
|
|
let max_version = ref 0
|
|
|
|
|
|
|
|
(*** Miscellaneous. ***)
|
|
|
|
|
|
|
|
(* Mark breakpoints as installed in current checkpoint. *)
|
|
|
|
let copy_breakpoints () =
|
|
|
|
!current_checkpoint.c_breakpoints <- !positions;
|
|
|
|
!current_checkpoint.c_breakpoint_version <- !current_version
|
|
|
|
|
|
|
|
(* Announce a new version of the breakpoint list. *)
|
|
|
|
let new_version () =
|
|
|
|
incr max_version;
|
1997-03-27 13:08:13 -08:00
|
|
|
current_version := !max_version
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(*** Information about breakpoints. ***)
|
|
|
|
|
|
|
|
let breakpoints_count () =
|
|
|
|
List.length !breakpoints
|
|
|
|
|
|
|
|
(* List of breakpoints at `pc'. *)
|
1997-03-27 13:08:13 -08:00
|
|
|
let rec breakpoints_at_pc pc =
|
2019-05-02 08:05:15 -07:00
|
|
|
begin match Symbols.event_at_pc pc with
|
|
|
|
| {ev_frag = frag; ev_ev = {ev_repr = Event_child {contents = pos}}} ->
|
|
|
|
breakpoints_at_pc {frag; pos}
|
|
|
|
| _ -> []
|
|
|
|
| exception Not_found -> []
|
1997-03-27 13:08:13 -08:00
|
|
|
end
|
|
|
|
@
|
2019-05-02 08:05:15 -07:00
|
|
|
List.map fst (List.filter
|
|
|
|
(function (_, {ev_frag = frag; ev_ev = {ev_pos = pos}}) ->
|
|
|
|
{frag; pos} = pc)
|
|
|
|
!breakpoints)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
1997-03-27 13:08:13 -08:00
|
|
|
(* Is there a breakpoint at `pc' ? *)
|
|
|
|
let breakpoint_at_pc pc =
|
|
|
|
breakpoints_at_pc pc <> []
|
|
|
|
|
1996-11-29 08:55:09 -08:00
|
|
|
(*** Set and remove breakpoints ***)
|
|
|
|
|
2019-05-02 08:05:15 -07:00
|
|
|
let print_pc out {frag;pos} = fprintf out "%d:%d" frag pos
|
|
|
|
|
1996-11-29 08:55:09 -08:00
|
|
|
(* Remove all breakpoints. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
let remove_breakpoints pcs =
|
1996-11-29 08:55:09 -08:00
|
|
|
if !debug_breakpoints then
|
2019-05-02 08:05:15 -07:00
|
|
|
printf "Removing breakpoints...\n%!";
|
1996-11-29 08:55:09 -08:00
|
|
|
List.iter
|
2019-05-02 08:05:15 -07:00
|
|
|
(function (pc, _) ->
|
|
|
|
if !debug_breakpoints then printf "%a\n%!" print_pc pc;
|
|
|
|
reset_instr pc;
|
|
|
|
Symbols.set_event_at_pc pc)
|
|
|
|
pcs
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Set all breakpoints. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
let set_breakpoints pcs =
|
1996-11-29 08:55:09 -08:00
|
|
|
if !debug_breakpoints then
|
2019-05-02 08:05:15 -07:00
|
|
|
printf "Setting breakpoints...\n%!";
|
1996-11-29 08:55:09 -08:00
|
|
|
List.iter
|
2019-05-02 08:05:15 -07:00
|
|
|
(function (pc, _) ->
|
|
|
|
if !debug_breakpoints then printf "%a\n%!" print_pc pc;
|
|
|
|
set_breakpoint pc)
|
|
|
|
pcs
|
1996-11-29 08:55:09 -08:00
|
|
|
|
2017-08-10 03:59:23 -07:00
|
|
|
(* Ensure the current version is installed in current checkpoint. *)
|
1996-11-29 08:55:09 -08:00
|
|
|
let update_breakpoints () =
|
1997-03-27 13:08:13 -08:00
|
|
|
if !debug_breakpoints then begin
|
|
|
|
prerr_string "Updating breakpoints... ";
|
|
|
|
prerr_int !current_checkpoint.c_breakpoint_version;
|
|
|
|
prerr_string " ";
|
|
|
|
prerr_int !current_version;
|
|
|
|
prerr_endline ""
|
|
|
|
end;
|
1996-11-29 08:55:09 -08:00
|
|
|
if !current_checkpoint.c_breakpoint_version <> !current_version then
|
1997-11-13 01:04:16 -08:00
|
|
|
Exec.protect
|
1996-11-29 08:55:09 -08:00
|
|
|
(function () ->
|
|
|
|
remove_breakpoints !current_checkpoint.c_breakpoints;
|
|
|
|
set_breakpoints !positions;
|
|
|
|
copy_breakpoints ())
|
|
|
|
|
|
|
|
(* Execute given function with no breakpoint in current checkpoint. *)
|
|
|
|
(* --- `goto' runs faster this way (does not stop on each breakpoint). *)
|
|
|
|
let execute_without_breakpoints f =
|
2019-05-02 08:05:15 -07:00
|
|
|
Misc.protect_refs [Misc.R (Debugger_config.break_on_load, false);
|
|
|
|
Misc.R (current_version, 0);
|
2019-07-16 04:42:04 -07:00
|
|
|
Misc.R (positions, []);
|
|
|
|
Misc.R (breakpoints, []);
|
|
|
|
Misc.R (breakpoint_number, 0)]
|
2019-05-02 08:05:15 -07:00
|
|
|
f
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Add a position in the position list. *)
|
|
|
|
(* Change version if necessary. *)
|
|
|
|
let insert_position pos =
|
|
|
|
try
|
|
|
|
incr (List.assoc pos !positions)
|
|
|
|
with
|
|
|
|
Not_found ->
|
|
|
|
positions := (pos, ref 1) :: !positions;
|
|
|
|
new_version ()
|
|
|
|
|
|
|
|
(* Remove a position in the position list. *)
|
|
|
|
(* Change version if necessary. *)
|
|
|
|
let remove_position pos =
|
|
|
|
let count = List.assoc pos !positions in
|
|
|
|
decr count;
|
|
|
|
if !count = 0 then begin
|
2009-05-20 04:52:42 -07:00
|
|
|
positions := List.remove_assoc pos !positions;
|
1997-03-27 13:08:13 -08:00
|
|
|
new_version ()
|
1996-11-29 08:55:09 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
(* Insert a new breakpoint in lists. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
let rec new_breakpoint event =
|
|
|
|
match event with
|
|
|
|
{ev_frag=frag; ev_ev={ev_repr=Event_child pos}} ->
|
|
|
|
new_breakpoint (Symbols.any_event_at_pc {frag; pos=(!pos)})
|
|
|
|
| {ev_frag=frag; ev_ev={ev_pos=pos}} ->
|
|
|
|
let pc = {frag; pos} in
|
|
|
|
Exec.protect
|
|
|
|
(function () ->
|
|
|
|
incr breakpoint_number;
|
|
|
|
insert_position pc;
|
|
|
|
breakpoints := (!breakpoint_number, event) :: !breakpoints);
|
|
|
|
if !Parameters.breakpoint then
|
|
|
|
printf "Breakpoint %d at %a: %s\n%!" !breakpoint_number print_pc pc
|
|
|
|
(Pos.get_desc event)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Remove a breakpoint from lists. *)
|
|
|
|
let remove_breakpoint number =
|
|
|
|
try
|
2005-08-23 13:16:43 -07:00
|
|
|
let ev = List.assoc number !breakpoints in
|
2019-05-02 08:05:15 -07:00
|
|
|
let pc = {frag = ev.ev_frag; pos=ev.ev_ev.ev_pos} in
|
|
|
|
Exec.protect
|
|
|
|
(function () ->
|
|
|
|
breakpoints := List.remove_assoc number !breakpoints;
|
|
|
|
remove_position pc;
|
|
|
|
if !Parameters.breakpoint then
|
|
|
|
printf "Removed breakpoint %d at %a: %s\n%!" number print_pc pc
|
|
|
|
(Pos.get_desc ev))
|
1996-11-29 08:55:09 -08:00
|
|
|
with
|
|
|
|
Not_found ->
|
2018-08-30 10:15:32 -07:00
|
|
|
prerr_endline ("No breakpoint number " ^ (Int.to_string number) ^ ".");
|
1996-11-29 08:55:09 -08:00
|
|
|
raise Not_found
|
|
|
|
|
|
|
|
let remove_all_breakpoints () =
|
|
|
|
List.iter (function (number, _) -> remove_breakpoint number) !breakpoints
|
|
|
|
|
|
|
|
(*** Temporary breakpoints. ***)
|
|
|
|
|
|
|
|
(* Temporary breakpoint position. *)
|
2019-05-02 08:05:15 -07:00
|
|
|
let temporary_breakpoint_position = ref (None : pc option)
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
(* Execute `funct' with a breakpoint added at `pc'. *)
|
|
|
|
(* --- Used by `finish'. *)
|
|
|
|
let exec_with_temporary_breakpoint pc funct =
|
|
|
|
let previous_version = !current_version in
|
|
|
|
let remove () =
|
|
|
|
temporary_breakpoint_position := None;
|
|
|
|
current_version := previous_version;
|
|
|
|
let count = List.assoc pc !positions in
|
|
|
|
decr count;
|
|
|
|
if !count = 0 then begin
|
2009-05-20 04:52:42 -07:00
|
|
|
positions := List.remove_assoc pc !positions;
|
1996-11-29 08:55:09 -08:00
|
|
|
reset_instr pc;
|
1998-11-12 06:51:27 -08:00
|
|
|
Symbols.set_event_at_pc pc
|
1997-05-19 08:42:21 -07:00
|
|
|
end
|
1996-11-29 08:55:09 -08:00
|
|
|
|
|
|
|
in
|
1997-11-13 01:04:16 -08:00
|
|
|
Exec.protect (function () -> insert_position pc);
|
1996-11-29 08:55:09 -08:00
|
|
|
temporary_breakpoint_position := Some pc;
|
2019-10-19 03:49:18 -07:00
|
|
|
Fun.protect ~finally:(fun () -> Exec.protect remove) funct
|