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

Demangle OCaml symbols #250

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions core/demangle_ocaml_symbols.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
open! Core

let decode_two_digit_hexadecimal_number first_character second_character =
let%bind.Option hex_digit_of_first_character = Char.get_hex_digit first_character in
let%bind.Option hex_digit_of_second_character = Char.get_hex_digit second_character in
let leftshift_first_character = hex_digit_of_first_character lsl 4 in
let bit_or_on_the_hexadecimals =
leftshift_first_character lor hex_digit_of_second_character
in
Char.of_int bit_or_on_the_hexadecimals
;;

let parser =
let open Angstrom in
let strip_numeric_suffix =
char '_' *> skip_while Char.is_digit *> end_of_input *> return None
in
let double_underscores = string "__" >>| fun _ -> Some '.' in
let two_digit_hexadecimal_number =
let hex_character = satisfy Char.is_hex_digit in
let hexcode =
decode_two_digit_hexadecimal_number <$> char '$' *> hex_character <*> hex_character
in
hexcode
>>= fun integer ->
match integer with
| None -> fail "invalid integer"
| Some character -> return (Some character)
in
let normal_character = any_char >>| fun character -> Some character in
let token =
choice
~failure_msg:"unrecognized token"
[ strip_numeric_suffix
; double_underscores
; two_digit_hexadecimal_number
; normal_character
]
in
string "caml" *> many1 token
;;

let demangle mangled_symbol =
let mangled_string = Angstrom.parse_string ~consume:All parser mangled_symbol in
match mangled_string with
| Ok list -> Some (String.of_char_list (List.filter_map list ~f:Fn.id))
| Error _ -> None
;;
11 changes: 11 additions & 0 deletions core/demangle_ocaml_symbols.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
open! Core

(** The logic for this function is derived from perf [0].
This function is used to change the symbols in the application
executable from a mangled form to a demangled form in ocaml. Now
when running [magic-trace run -trigger] the symbols will appear in
their demangled form. Will return None if the symbol is not
recognized as an OCaml symbol.
[0]: https://github.com/torvalds/linux/blob/5bfc75d92efd494db37f5c4c173d3639d4772966/tools/perf/util/demangle-ocaml.c *)
val demangle : string -> string option
2 changes: 1 addition & 1 deletion core/dune
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
(name magic_trace_core)
(public_name magic-trace.magic_trace_core)
(libraries core async core_unix.filename_unix expect_test_helpers_core fzf
magic_trace owee re)
magic_trace owee re angstrom)
(inline_tests)
(preprocess
(pps ppx_jane)))
8 changes: 7 additions & 1 deletion core/symbol_selection.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ let select_owee_symbol ~elf ~header select =
let open Deferred.Or_error.Let_syntax in
let all_symbols = Elf.all_symbols ~select elf in
let all_symbol_names = List.map all_symbols ~f:Tuple2.get1 in
match%bind Fzf.pick_one ~header (Inputs all_symbol_names) with
let demangled_symbols =
List.map all_symbol_names ~f:(fun mangled_symbol ->
match Demangle_ocaml_symbols.demangle mangled_symbol with
| None -> mangled_symbol, mangled_symbol
| Some demangled_symbol -> demangled_symbol, mangled_symbol)
in
match%bind Fzf.pick_one ~header (Assoc demangled_symbols) with
| None -> Deferred.Or_error.error_string "No symbol selected"
| Some chosen_name ->
let chosen_symbol =
Expand Down
27 changes: 27 additions & 0 deletions test/demangle_ocaml_symbols.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
open! Core
open Magic_trace_core

let demangle_symbol_test symbol =
let demangle_symbol = Demangle_ocaml_symbols.demangle symbol in
print_s [%sexp (demangle_symbol : string option)]
;;

let%expect_test "real mangled symbol" =
demangle_symbol_test "camlAsync_unix__Unix_syscalls__to_string_57255";
[%expect {| (Async_unix.Unix_syscalls.to_string) |}]
;;

let%expect_test "proper hexcode" =
demangle_symbol_test "caml$3f";
[%expect {| (?) |}]
;;

let%expect_test "improper hexcode" =
demangle_symbol_test "caml$7l";
[%expect {| ($7l) |}]
;;

let%expect_test "when the symbol is not a demangled ocaml symbol" =
demangle_symbol_test "dr__$3e$21_358";
[%expect {| () |}]
;;