From 9043add656177eeac1491a73d2f3ab92bec0013c Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Sat, 29 Dec 2018 14:31:27 -0500 Subject: Imported Upstream version 8.8.2 --- clib/backtrace.ml | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 clib/backtrace.ml (limited to 'clib/backtrace.ml') diff --git a/clib/backtrace.ml b/clib/backtrace.ml new file mode 100644 index 00000000..27ed6fbf --- /dev/null +++ b/clib/backtrace.ml @@ -0,0 +1,119 @@ +(************************************************************************) +(* * The Coq Proof Assistant / The Coq Development Team *) +(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) +(* raw_frame array option + = "caml_get_exception_backtrace" + +type t = raw_frame array list +(** List of partial raw stack frames, in reverse order *) + +let empty = [] + +let of_raw = function +| Unknown_location r -> + { frame_location = None; frame_raised = r; } +| Known_location (r, file, line, st, en) -> + let loc = { + loc_filename = file; + loc_line = line; + loc_start = st; + loc_end = en; + } in + { frame_location = Some loc; frame_raised = r; } + +let rec repr_aux accu = function +| [] -> accu +| fragment :: stack -> + let len = Array.length fragment in + let rec append accu i = + if i = len then accu + else append (of_raw fragment.(i) :: accu) (succ i) + in + repr_aux (append accu 0) stack + +let repr bt = repr_aux [] (List.rev bt) + +let push stack = match get_exception_backtrace () with +| None -> [] +| Some frames -> frames :: stack + +(** Utilities *) + +let print_frame frame = + let raise = if frame.frame_raised then "raise" else "frame" in + match frame.frame_location with + | None -> Printf.sprintf "%s @ unknown" raise + | Some loc -> + Printf.sprintf "%s @ file \"%s\", line %d, characters %d-%d" + raise loc.loc_filename loc.loc_line loc.loc_start loc.loc_end + +(** Exception manipulation *) + +let backtrace : t Exninfo.t = Exninfo.make () + +let is_recording = ref false + +let record_backtrace b = + let () = Printexc.record_backtrace b in + is_recording := b + +let get_backtrace e = + Exninfo.get e backtrace + +let add_backtrace e = + if !is_recording then + (** This must be the first function call, otherwise the stack may be + destroyed *) + let current = get_exception_backtrace () in + let info = Exninfo.info e in + begin match current with + | None -> (e, info) + | Some fragment -> + let bt = match get_backtrace info with + | None -> [] + | Some bt -> bt + in + let bt = fragment :: bt in + (e, Exninfo.add info backtrace bt) + end + else + let info = Exninfo.info e in + (e, info) + +let app_backtrace ~src ~dst = + if !is_recording then + match get_backtrace src with + | None -> dst + | Some bt -> + match get_backtrace dst with + | None -> + Exninfo.add dst backtrace bt + | Some nbt -> + let bt = bt @ nbt in + Exninfo.add dst backtrace bt + else dst -- cgit v1.2.3