Skip to content

Commit d4bc9af

Browse files
authored
Merge pull request #53 from parca-dev/node-arm-fixes
Enable NodeJS profiling on ARM64 (open-telemetry#393)
2 parents ec1cdb3 + 282a579 commit d4bc9af

File tree

12 files changed

+1250
-3
lines changed

12 files changed

+1250
-3
lines changed

interpreter/nodev8/v8.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ package nodev8 // import "go.opentelemetry.io/ebpf-profiler/interpreter/nodev8"
9494
// 14.0.y 8.1.307
9595
// 14.5.y 8.3.110
9696
// 14.6.y 8.4.371
97-
// 16.0.y 9.0.257
97+
// 16.0.y 9.0.257 earliest supported version for arm64
9898
// 16.4.y 9.1.269
9999
// 16.6.y 9.2.230
100100
// 16.11.y 9.4.19
@@ -224,8 +224,8 @@ const (
224224
)
225225

226226
var (
227-
// regex for the interpreter executable
228-
v8Regex = regexp.MustCompile(`^(?:.*/)?node(\d+)?$`)
227+
// regex for the interpreter executable or shared library
228+
v8Regex = regexp.MustCompile(`^(?:.*/)?node(\d+)?$|^(?:.*/)libnode\.so(\.\d+)?$`)
229229

230230
v8LibRegex = regexp.MustCompile(`^(?:.*/)libnode\.so(\.\d+)?$`)
231231

208 Bytes
Binary file not shown.
13.7 KB
Binary file not shown.
1.89 KB
Binary file not shown.

support/ebpf/v8_tracer.ebpf.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@
2121
// The maximum V8 frame length used in heuristic to validate FP
2222
#define V8_MAX_FRAME_LENGTH 8192
2323

24+
#if defined(__aarch64__)
25+
// On aarch64, a JS EntryFrame's layout differs from that of any other frame,
26+
// and stores 20 registers, the fp being the top-most.
27+
// See: https://chromium.googlesource.com/v8/v8/+/main/src/execution/arm64/frame-constants-arm64.h
28+
#define V8_ENTRYFRAME_CALLEE_SAVED_REGS_BEFORE_FP_LR_PAIR 18
29+
#else
30+
#define V8_ENTRYFRAME_CALLEE_SAVED_REGS_BEFORE_FP_LR_PAIR 0
31+
#endif
32+
2433
// Map from V8 process IDs to a structure containing addresses of variables
2534
// we require in order to build the stack trace
2635
bpf_map_def SEC("maps") v8_procs = {
@@ -280,6 +289,14 @@ unwind_one_v8_frame(PerCPURecord *record, V8ProcInfo *vi, bool top)
280289
}
281290

282291
state->sp = fp + sizeof(regs);
292+
293+
// The JS Entry Frame's layout differs from other frames because some callee
294+
// saved registers might be pushed onto the stack before the [fp, lr] pair.
295+
// This frame is represented by markers 0 (inner) and 1 (outermost).
296+
// See: https://chromium.googlesource.com/v8/v8/+/main/src/execution/frames.h#167
297+
if (pointer_and_type == V8_FILE_TYPE_MARKER && delta_or_marker == 1)
298+
state->sp += V8_ENTRYFRAME_CALLEE_SAVED_REGS_BEFORE_FP_LR_PAIR * sizeof(size_t);
299+
283300
state->fp = regs[0];
284301
state->pc = regs[1];
285302
unwinder_mark_nonleaf_frame(state);
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
{
2+
"coredump-ref": "fb4603a8b17d570c2ea644d95a3547098288189b23f8d0bd70c9b4ad34a3fa1f",
3+
"threads": [
4+
{
5+
"lwp": 7417,
6+
"frames": [
7+
"libc.so.6+0xd7d10",
8+
"node+0x14fa2cf",
9+
"node+0x14fb487",
10+
"node+0x14fb7ab",
11+
"node+0xbd449f",
12+
"node+0xbcf923",
13+
"node+0xbcfcf3",
14+
"V8::ExitFrame+0 in :0",
15+
"handleWriteReq+16 in node:internal/stream_base_commons:61",
16+
"writeGeneric+2 in node:internal/stream_base_commons:149",
17+
"Socket._writeGeneric+0 in node:net:0",
18+
"Socket._write+0 in node:net:0",
19+
"writeOrBuffer+24 in node:internal/streams/writable:389",
20+
"_write+47 in node:internal/streams/writable:330",
21+
"Writable.write+1 in node:internal/streams/writable:334",
22+
"value+28 in node:internal/console/constructor:289",
23+
"warn+1 in node:internal/console/constructor:368",
24+
"V8::InternalFrame+0 in :0",
25+
"V8::EntryFrame+0 in :0",
26+
"node+0xe30c7f",
27+
"node+0xe3184b",
28+
"node+0xcf005f",
29+
"node+0xbfec2b",
30+
"V8::ExitFrame+0 in :0",
31+
"trace+6 in node:internal/console/constructor:414",
32+
"V8::InternalFrame+0 in :0",
33+
"V8::EntryFrame+0 in :0",
34+
"node+0xe30c7f",
35+
"node+0xe3184b",
36+
"node+0xcf005f",
37+
"node+0xbfec2b",
38+
"V8::ExitFrame+0 in :0",
39+
"add+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:3",
40+
"add3+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:8",
41+
"test+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:12",
42+
"submain+2 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:17",
43+
"main+2 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:23",
44+
"<anonymous>+26 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:27",
45+
"Module._compile+46 in node:internal/modules/cjs/loader:1108",
46+
"Module._extensions..js+20 in node:internal/modules/cjs/loader:1137",
47+
"Module.load+12 in node:internal/modules/cjs/loader:988",
48+
"Module._load+76 in node:internal/modules/cjs/loader:828",
49+
"executeUserEntryPoint+0 in node:internal/modules/run_main:0",
50+
"<anonymous>+0 in node:internal/main/run_main_module:0",
51+
"V8::InternalFrame+0 in :0",
52+
"V8::EntryFrame+0 in :0",
53+
"node+0xe30c7f",
54+
"node+0xe3184b",
55+
"node+0xcf005f",
56+
"node+0xacf31f",
57+
"node+0xacf53f",
58+
"node+0xad082f",
59+
"node+0xa5ca2f",
60+
"node+0xb40293",
61+
"node+0xad25bf",
62+
"libc.so.6+0x273fb",
63+
"libc.so.6+0x274cb",
64+
"node+0xa583e3",
65+
"<unwinding aborted due to error native_stack_delta_invalid>"
66+
]
67+
},
68+
{
69+
"lwp": 7418,
70+
"frames": [
71+
"libc.so.6+0xe5f3c",
72+
"node+0x1500d3b",
73+
"node+0x14efc2f",
74+
"node+0xb6add7",
75+
"libc.so.6+0x7d5c7",
76+
"libc.so.6+0x7d5c7",
77+
"libc.so.6+0xe5d9b"
78+
]
79+
},
80+
{
81+
"lwp": 7419,
82+
"frames": [
83+
"libc.so.6+0x79df8",
84+
"libc.so.6+0x7c8fb",
85+
"node+0x14fd073",
86+
"node+0xb66667",
87+
"libc.so.6+0x7d5c7",
88+
"libc.so.6+0x7d5c7",
89+
"libc.so.6+0xe5d9b"
90+
]
91+
},
92+
{
93+
"lwp": 7420,
94+
"frames": [
95+
"libc.so.6+0x79df8",
96+
"libc.so.6+0x7c8fb",
97+
"node+0x14fd073",
98+
"node+0xb66667",
99+
"libc.so.6+0x7d5c7",
100+
"libc.so.6+0x7d5c7",
101+
"libc.so.6+0xe5d9b"
102+
]
103+
},
104+
{
105+
"lwp": 7421,
106+
"frames": [
107+
"libc.so.6+0x79df8",
108+
"libc.so.6+0x7c8fb",
109+
"node+0x14fd073",
110+
"node+0xb66667",
111+
"libc.so.6+0x7d5c7",
112+
"libc.so.6+0x7d5c7",
113+
"libc.so.6+0xe5d9b"
114+
]
115+
},
116+
{
117+
"lwp": 7422,
118+
"frames": [
119+
"libc.so.6+0x79df8",
120+
"libc.so.6+0x7c8fb",
121+
"node+0x14fd073",
122+
"node+0xb66667",
123+
"libc.so.6+0x7d5c7",
124+
"libc.so.6+0x7d5c7",
125+
"libc.so.6+0xe5d9b"
126+
]
127+
},
128+
{
129+
"lwp": 7423,
130+
"frames": [
131+
"libc.so.6+0x79df8",
132+
"libc.so.6+0x85a5b",
133+
"node+0x14fce5b",
134+
"node+0xbf25cf",
135+
"libc.so.6+0x7d5c7",
136+
"libc.so.6+0xe5d9b"
137+
]
138+
}
139+
],
140+
"modules": [
141+
{
142+
"ref": "c4834bd79254443665af96b6d5e71d124b7f92f2eea121e61f9fff5204fc594d",
143+
"local-path": "/usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.30"
144+
},
145+
{
146+
"ref": "22a0986a1047cd3c9a55368fdc6bb6e5a4455aceb53ec15dbe19112d95583642",
147+
"local-path": "/usr/lib/aarch64-linux-gnu/libpthread.so.0"
148+
},
149+
{
150+
"ref": "fd04b635d29b5cb3faaf502a6c5cd68a623d66a736f4d0561ff280c2fa411c79",
151+
"local-path": "/usr/lib/aarch64-linux-gnu/libc.so.6"
152+
},
153+
{
154+
"ref": "f1935c0616a48e7ec471c26886df0411beffd4e56c92539d9a6a94641950badf",
155+
"local-path": "/usr/lib/aarch64-linux-gnu/libdl.so.2"
156+
},
157+
{
158+
"ref": "594545a9720b4a16973a823d18c71fbf070d3c07fb17b01df5376273e91644a1",
159+
"local-path": "/usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"
160+
},
161+
{
162+
"ref": "acfe23cf0f5f4ac35b4c314415bb31d6f52a9bd39df8be04dfb2818a571533fd",
163+
"local-path": "/usr/lib/aarch64-linux-gnu/libgcc_s.so.1"
164+
},
165+
{
166+
"ref": "e647ee3042517f06cbebbbf0f66ba25486d0722222404f1d067683767a055566",
167+
"local-path": "/usr/lib/aarch64-linux-gnu/libm.so.6"
168+
},
169+
{
170+
"ref": "f02199ad95138bb55687957e80ce730496d80a5f629cc7718bbcf5af3299d8b7",
171+
"local-path": "/home/ubuntu/.nvm/versions/node/v16.0.0/bin/node"
172+
}
173+
]
174+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
{
2+
"coredump-ref": "4f775111099ba567307d199529fa17eb3ae961e6d44c7f5fee2b1ee074f03628",
3+
"threads": [
4+
{
5+
"lwp": 7887,
6+
"frames": [
7+
"libc.so.6+0xd7d14",
8+
"node+0x14c5e37",
9+
"node+0xbc6457",
10+
"node+0xbc16cf",
11+
"node+0xbc1ad3",
12+
"V8::ExitFrame+0 in :0",
13+
"handleWriteReq+16 in node:internal/stream_base_commons:61",
14+
"writeGeneric+2 in node:internal/stream_base_commons:153",
15+
"Socket._writeGeneric+0 in node:net:0",
16+
"Socket._write+0 in node:net:0",
17+
"writeOrBuffer+24 in node:internal/streams/writable:389",
18+
"_write+47 in node:internal/streams/writable:330",
19+
"Writable.write+1 in node:internal/streams/writable:334",
20+
"value+28 in node:internal/console/constructor:285",
21+
"warn+1 in node:internal/console/constructor:364",
22+
"V8::InternalFrame+0 in :0",
23+
"V8::EntryFrame+0 in :0",
24+
"node+0xdee9d7",
25+
"node+0xdef51b",
26+
"node+0xce14d3",
27+
"node+0xbf128b",
28+
"V8::ExitFrame+0 in :0",
29+
"trace+6 in node:internal/console/constructor:410",
30+
"V8::InternalFrame+0 in :0",
31+
"V8::EntryFrame+0 in :0",
32+
"node+0xdee9d7",
33+
"node+0xdef51b",
34+
"node+0xce14d3",
35+
"node+0xbf128b",
36+
"V8::ExitFrame+0 in :0",
37+
"add+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:3",
38+
"add3+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:8",
39+
"test+1 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:12",
40+
"submain+2 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:17",
41+
"main+2 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:23",
42+
"<anonymous>+26 in /home/ubuntu/opentelemetry-ebpf-profiler/tools/coredump/testsources/node/inlining.js:27",
43+
"Module._compile+46 in node:internal/modules/cjs/loader:1101",
44+
"Module._extensions..js+43 in node:internal/modules/cjs/loader:1153",
45+
"Module.load+12 in node:internal/modules/cjs/loader:981",
46+
"Module._load+65 in node:internal/modules/cjs/loader:822",
47+
"executeUserEntryPoint+0 in node:internal/modules/run_main:0",
48+
"<anonymous>+0 in node:internal/main/run_main_module:0",
49+
"V8::InternalFrame+0 in :0",
50+
"V8::EntryFrame+0 in :0",
51+
"node+0xdee9d7",
52+
"node+0xdef51b",
53+
"node+0xce14d3",
54+
"node+0xab8f17",
55+
"node+0xab9137",
56+
"node+0xaba40f",
57+
"node+0xa46457",
58+
"node+0xb2e987",
59+
"node+0xabc237",
60+
"libc.so.6+0x273fb",
61+
"libc.so.6+0x274cb",
62+
"node+0xa41c3b",
63+
"<unwinding aborted due to error native_stack_delta_invalid>"
64+
]
65+
},
66+
{
67+
"lwp": 7888,
68+
"frames": [
69+
"libc.so.6+0xe5f3c",
70+
"node+0x14cc1d3",
71+
"node+0x14bb6bf",
72+
"node+0xb5a0b7",
73+
"libc.so.6+0x7d5c7",
74+
"libc.so.6+0x7d5c7",
75+
"libc.so.6+0xe5d9b"
76+
]
77+
},
78+
{
79+
"lwp": 7889,
80+
"frames": [
81+
"libc.so.6+0x79df8",
82+
"libc.so.6+0x7c8fb",
83+
"node+0x14c8bfb",
84+
"node+0xb55947",
85+
"libc.so.6+0x7d5c7",
86+
"libc.so.6+0x7d5c7",
87+
"libc.so.6+0xe5d9b"
88+
]
89+
},
90+
{
91+
"lwp": 7890,
92+
"frames": [
93+
"libc.so.6+0x79df8",
94+
"libc.so.6+0x7c8fb",
95+
"node+0x14c8bfb",
96+
"node+0xb55947",
97+
"libc.so.6+0x7d5c7",
98+
"libc.so.6+0x7d5c7",
99+
"libc.so.6+0xe5d9b"
100+
]
101+
},
102+
{
103+
"lwp": 7891,
104+
"frames": [
105+
"libc.so.6+0x79df8",
106+
"libc.so.6+0x7c8fb",
107+
"node+0x14c8bfb",
108+
"node+0xb55947",
109+
"libc.so.6+0x7d5c7",
110+
"libc.so.6+0x7d5c7",
111+
"libc.so.6+0xe5d9b"
112+
]
113+
},
114+
{
115+
"lwp": 7892,
116+
"frames": [
117+
"libc.so.6+0x79df8",
118+
"libc.so.6+0x7c8fb",
119+
"node+0x14c8bfb",
120+
"node+0xb55947",
121+
"libc.so.6+0x7d5c7",
122+
"libc.so.6+0x7d5c7",
123+
"libc.so.6+0xe5d9b"
124+
]
125+
},
126+
{
127+
"lwp": 7893,
128+
"frames": [
129+
"libc.so.6+0x79df8",
130+
"libc.so.6+0x85a5b",
131+
"node+0x14c89e3",
132+
"node+0xbe4f6f",
133+
"libc.so.6+0x7d5c7",
134+
"libc.so.6+0xe5d9b"
135+
]
136+
}
137+
],
138+
"modules": [
139+
{
140+
"ref": "f1935c0616a48e7ec471c26886df0411beffd4e56c92539d9a6a94641950badf",
141+
"local-path": "/usr/lib/aarch64-linux-gnu/libdl.so.2"
142+
},
143+
{
144+
"ref": "594545a9720b4a16973a823d18c71fbf070d3c07fb17b01df5376273e91644a1",
145+
"local-path": "/usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"
146+
},
147+
{
148+
"ref": "fd04b635d29b5cb3faaf502a6c5cd68a623d66a736f4d0561ff280c2fa411c79",
149+
"local-path": "/usr/lib/aarch64-linux-gnu/libc.so.6"
150+
},
151+
{
152+
"ref": "c4834bd79254443665af96b6d5e71d124b7f92f2eea121e61f9fff5204fc594d",
153+
"local-path": "/usr/lib/aarch64-linux-gnu/libstdc++.so.6.0.30"
154+
},
155+
{
156+
"ref": "e647ee3042517f06cbebbbf0f66ba25486d0722222404f1d067683767a055566",
157+
"local-path": "/usr/lib/aarch64-linux-gnu/libm.so.6"
158+
},
159+
{
160+
"ref": "8fe9e4297ec52bd22f6e31a227a7a15d7bdff7a01429c37011a173c8d5386669",
161+
"local-path": "/home/ubuntu/.nvm/versions/node/v16.11.0/bin/node"
162+
},
163+
{
164+
"ref": "22a0986a1047cd3c9a55368fdc6bb6e5a4455aceb53ec15dbe19112d95583642",
165+
"local-path": "/usr/lib/aarch64-linux-gnu/libpthread.so.0"
166+
},
167+
{
168+
"ref": "acfe23cf0f5f4ac35b4c314415bb31d6f52a9bd39df8be04dfb2818a571533fd",
169+
"local-path": "/usr/lib/aarch64-linux-gnu/libgcc_s.so.1"
170+
}
171+
]
172+
}

0 commit comments

Comments
 (0)