Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide primitive to extract debug information from a closure #6689

Closed
vicuna opened this issue Dec 3, 2014 · 5 comments
Closed

Provide primitive to extract debug information from a closure #6689

vicuna opened this issue Dec 3, 2014 · 5 comments

Comments

@vicuna
Copy link

vicuna commented Dec 3, 2014

Original bug ID: 6689
Reporter: @gasche
Status: acknowledged (set by @mshinwell on 2014-12-05T07:27:02Z)
Resolution: open
Priority: normal
Severity: feature
Version: 4.03.0+dev / +beta1
Category: back end (clambda to assembly)
Monitored by: @ygrek

Bug description

During a "Coq developers lunch", Coq developers mentioned that it would be useful for their debugging to be able to access the debug information attached to a function (without calling it).

They mentioned the case of global/closed/static functions and bytecode (they do use bytecode for debugging purposes), but we could extend this to native code and arbitrary closure if possible.

@vicuna
Copy link
Author

vicuna commented Dec 3, 2014

Comment author: @mshinwell

A very quick dump of some random thoughts, for native:

  1. You can pull code pointers out of closures using [Obj] and map them back to symbol names using common command-line tools. This may suffice.
  2. Maybe we could recover this information (and more) by reading the DWARF sections from the executable and/or the symbol table (although the latter means having to cope with various executable formats).
  3. I tried to hack something into my allocation profiling compiler to do this resolution, in lieu of reading the DWARF, but it isn't very nice.
  4. The forthcoming gdb/OCaml patches do this resolution automatically in the debugger. Closures are displayed along with their source location, if known.

@vicuna
Copy link
Author

vicuna commented Dec 4, 2014

Comment author: @ppedrot

Some remarks on the thoughts of shinwell:

  1. How can you dump code pointers from OCaml side? I am unaware of a way to convert pointers into Int64.t...

  2. OCaml has already this feature coded, if I am not mistaken. In backtrace.c there is a function loading debug information and from it converting code pointers into code location.

@vicuna
Copy link
Author

vicuna commented Dec 5, 2014

Comment author: @mshinwell

  1. See below.

  2. I don't think the frame descriptors provide sufficient information to do what you want. They record the mapping from code address to source location at call points. As such, I suspect that you wouldn't be able to find out the location of leaf functions using this method.

--

external int64_from_string : string -> int -> int64 = "%caml_string_get64u"

let code_pointer_of_closure (f : 'a -> 'b) =
let arity = Obj.field (Obj.repr f) 1 in
assert (Obj.is_int arity);
let first_code_ptr = int64_from_string ((Obj.magic f) : string) 0 in
if ((Obj.magic arity) : int) = 1 then
One_argument first_code_ptr else let full_app_code_ptr = int64_from_string ((Obj.magic f) : string) (2 * Sys.word_size/8) in Multiple_arguments (first_code_ptr, full_app_code_ptr)

let () =
let one_arg_closure x = x + 42 in
let two_arg_closure x y = x + 42*y in
let print_code_pointers f =
match code_pointer_of_closure f with
| One_argument code_ptr -> Printf.sprintf "one argument, code ptr=%Lx" code_ptr | Multiple_arguments (currying_ptr, full_app_ptr) ->
Printf.sprintf "multiple arguments, currying wrapper=%Lx,
full application code ptr=%Lx" currying_ptr full_app_ptr
in
Printf.printf "one_arg_closure: %s\n" (print_code_pointers one_arg_closure);
Printf.printf "two_arg_closure: %s\n" (print_code_pointers two_arg_closure)

@vicuna
Copy link
Author

vicuna commented Dec 5, 2014

Comment author: @gasche

I would be interested in solving the immediate use-case of bytecode, which is what the Coq people asked for. That seems reasonably easy and I'll try my hand at a patch someday.

Mark, I wonder which interface I should present for this feature, and that is related to how/wheter we plan to extend this to native-code in the future. We could have a primitive that only works in bytecode, or that returns a "no information" value in native (this is how backtraces worked for a long time). If there is some specific interface that you think could be extended to a native counterpart in the future, it's of course a better choice.

(As for backtraces, I'm probably aiming for a fast "raw" primitive that returns an abstract type that needs to be explicited into the user-friendly representation, to allow to collect such locations quickly and only unfold/locate it on the user's demand.)

@github-actions
Copy link

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant