Source file perf_map.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
open! Core
open! Async
type t = Perf_map_location.t Int64.Map.t
let perf_map_re =
Re.Posix.re {|^([0-9a-fA-F]+) ([0-9a-fA-F]+) (.*)$|} |> Re.compile
;;
let hex_to_int s = Int.Hex.of_string ("0x" ^ s)
let hex_to_int64 s = Int64.Hex.of_string ("0x" ^ s)
let parse_line line =
if String.is_empty line
then None
else (
try
match Re.Group.all (Re.exec perf_map_re line) with
| [| _; start_addr; size; function_ |] ->
let start_addr = hex_to_int64 start_addr in
(start_addr, { Perf_map_location.start_addr; size = hex_to_int size; function_ })
|> Some
| _ -> failwith "doesn't match regex"
with
| exn ->
raise_s
[%message
"error scanning perf map, please add this line to a test in perf_map.ml"
(exn : exn)
(line : string)])
;;
let%test_module _ =
(module struct
open Core
let%expect_test "example perf map" =
let sample =
{|3a6caa49c2e f3 LazyCompile:~afterInspector node:internal/errors:753
3a6caa49e86 1e LazyCompile:~lazyInternalUtilInspect node:internal/errors:185
3a6caa4a5fe 5 Eval:~ node:internal/tty:1
3a6caa4aa5e 166 Function:~ node:internal/tty:1
3a6caa4b536 3f LazyCompile:~hasColors node:internal/tty:222
3a6caa4c3ae 2fa LazyCompile:~getColorDepth node:internal/tty:106
3a6caa4c90e 5 LazyCompile:~get node:internal/util/inspect:352
3a6caa5142e 18b LazyCompile:~inspect node:internal/util/inspect:292
3a6caa51926 1cf LazyCompile:~formatValue node:internal/util/inspect:745
3a6caa5241e cfd LazyCompile:~formatRaw node:internal/util/inspect:820
3a6caa537c6 13f LazyCompile:~getConstructorName node:internal/util/inspect:567
3a6caa53a96 d LazyCompile:~isInstanceof node:internal/util/inspect:559
00007F5D97BCAE50 22 instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor()[QuickJitted]
00007F5D97BCAD40 10 stub<1023> AllocateTemporaryEntryPoints<PRECODE_FIXUP>
00007F5D97BCAD58 48 stub<1024> AllocateTemporaryEntryPoints<PRECODE_FIXUP>
00007F5D97BCAE90 1b4 instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor(int32,class System.Collections.Generic.IEqualityComparer`1<!0>)[QuickJitted]
|}
in
String.split sample ~on:'\n'
|> List.map ~f:(fun line -> line, parse_line line)
|> [%sexp_of: (string * (Int64.Hex.t * Perf_map_location.t) option) list]
|> print_s;
[%expect
{|
(("3a6caa49c2e f3 LazyCompile:~afterInspector node:internal/errors:753"
((0x3a6caa49c2e
((start_addr 0x3a6caa49c2e) (size 0xf3)
(function_ "LazyCompile:~afterInspector node:internal/errors:753")))))
("3a6caa49e86 1e LazyCompile:~lazyInternalUtilInspect node:internal/errors:185"
((0x3a6caa49e86
((start_addr 0x3a6caa49e86) (size 0x1e)
(function_
"LazyCompile:~lazyInternalUtilInspect node:internal/errors:185")))))
("3a6caa4a5fe 5 Eval:~ node:internal/tty:1"
((0x3a6caa4a5fe
((start_addr 0x3a6caa4a5fe) (size 0x5)
(function_ "Eval:~ node:internal/tty:1")))))
("3a6caa4aa5e 166 Function:~ node:internal/tty:1"
((0x3a6caa4aa5e
((start_addr 0x3a6caa4aa5e) (size 0x166)
(function_ "Function:~ node:internal/tty:1")))))
("3a6caa4b536 3f LazyCompile:~hasColors node:internal/tty:222"
((0x3a6caa4b536
((start_addr 0x3a6caa4b536) (size 0x3f)
(function_ "LazyCompile:~hasColors node:internal/tty:222")))))
("3a6caa4c3ae 2fa LazyCompile:~getColorDepth node:internal/tty:106"
((0x3a6caa4c3ae
((start_addr 0x3a6caa4c3ae) (size 0x2fa)
(function_ "LazyCompile:~getColorDepth node:internal/tty:106")))))
("3a6caa4c90e 5 LazyCompile:~get node:internal/util/inspect:352"
((0x3a6caa4c90e
((start_addr 0x3a6caa4c90e) (size 0x5)
(function_ "LazyCompile:~get node:internal/util/inspect:352")))))
("3a6caa5142e 18b LazyCompile:~inspect node:internal/util/inspect:292"
((0x3a6caa5142e
((start_addr 0x3a6caa5142e) (size 0x18b)
(function_ "LazyCompile:~inspect node:internal/util/inspect:292")))))
("3a6caa51926 1cf LazyCompile:~formatValue node:internal/util/inspect:745"
((0x3a6caa51926
((start_addr 0x3a6caa51926) (size 0x1cf)
(function_ "LazyCompile:~formatValue node:internal/util/inspect:745")))))
("3a6caa5241e cfd LazyCompile:~formatRaw node:internal/util/inspect:820"
((0x3a6caa5241e
((start_addr 0x3a6caa5241e) (size 0xcfd)
(function_ "LazyCompile:~formatRaw node:internal/util/inspect:820")))))
("3a6caa537c6 13f LazyCompile:~getConstructorName node:internal/util/inspect:567"
((0x3a6caa537c6
((start_addr 0x3a6caa537c6) (size 0x13f)
(function_
"LazyCompile:~getConstructorName node:internal/util/inspect:567")))))
("3a6caa53a96 d LazyCompile:~isInstanceof node:internal/util/inspect:559"
((0x3a6caa53a96
((start_addr 0x3a6caa53a96) (size 0xd)
(function_ "LazyCompile:~isInstanceof node:internal/util/inspect:559")))))
("00007F5D97BCAE50 22 instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor()[QuickJitted]"
((0x7f5d97bcae50
((start_addr 0x7f5d97bcae50) (size 0x22)
(function_
"instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor()[QuickJitted]")))))
("00007F5D97BCAD40 10 stub<1023> AllocateTemporaryEntryPoints<PRECODE_FIXUP>"
((0x7f5d97bcad40
((start_addr 0x7f5d97bcad40) (size 0x10)
(function_ "stub<1023> AllocateTemporaryEntryPoints<PRECODE_FIXUP>")))))
("00007F5D97BCAD58 48 stub<1024> AllocateTemporaryEntryPoints<PRECODE_FIXUP>"
((0x7f5d97bcad58
((start_addr 0x7f5d97bcad58) (size 0x48)
(function_ "stub<1024> AllocateTemporaryEntryPoints<PRECODE_FIXUP>")))))
("00007F5D97BCAE90 1b4 instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor(int32,class System.Collections.Generic.IEqualityComparer`1<!0>)[QuickJitted]"
((0x7f5d97bcae90
((start_addr 0x7f5d97bcae90) (size 0x1b4)
(function_
"instance void [System.Private.CoreLib] System.Collections.Generic.Dictionary`2[System.__Canon,System.Double]::.ctor(int32,class System.Collections.Generic.IEqualityComparer`1<!0>)[QuickJitted]")))))
("" ())) |}]
;;
end)
;;
let default_filename ~pid = [%string "/tmp/perf-%{pid#Pid}.map"]
let map_of_sequence_prefer_later sequence =
Sequence.fold sequence ~init:Int64.Map.empty ~f:(fun map (key, data) ->
Map.set map ~key ~data)
;;
let load file_location =
let%map lines =
Monitor.try_with_or_error ~rest:`Log (fun () -> Reader.file_lines file_location)
in
match lines with
| Error _ ->
None
| Ok lines ->
Sequence.of_list lines
|> Sequence.filter_map ~f:parse_line
|> map_of_sequence_prefer_later
|> Some
;;
let symbol (t : t) ~addr =
match Map.closest_key t `Less_or_equal_to addr with
| None -> None
| Some (_, location) ->
assert (Int64.(location.start_addr <= addr));
Option.some_if Int64.(location.start_addr + of_int location.size < addr) location
;;