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

Use frame pointer unwinding for v8-based applications #1836

Merged
merged 1 commit into from Jul 6, 2023

Conversation

javierhonduco
Copy link
Contributor

We can't unwind nodejs and other v8-base applications as we can't continue unwinding after the first AoT frame:

[...]
	current pc: 7fb0cf84904a
	current sp: 7fff93701498
	current bp: 7fff937014d8
[debug] Unwinding JITed stacks
[debug] Within unwinding machinery loop
	current pc: 157a329
	current sp: 7fff937014e8
	current bp: 7fff93701548
~about to check shards found=1
~checking shards now
[info] found chunk
le offset: 0
========== left 0 right 249997
	.done
	=> table_index: 206094
	=> adjusted pc: 157a329
	cfa type: 4, offset: 0 (row pc: 156f656)
[info] PC 157a329 not contained in the unwind info, found marker
[warn] mapping not added yet rbp 7fff93701548
pid 227936 tgid 227936

Turns out this AoT function doesn't have the corresponding DWARF unwind information:

$ dist/eh-frame --executable /home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node | grep 157a3
$

After cross-validating the output with bpftrace's and checking v8's source code it was clear why this is happening:

157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
1578538 Builtins_JSEntryTrampoline+88 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
15782c3 Builtins_JSEntry+131 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
[...]
7f65c5e29510 __libc_start_call_main+128 (/usr/lib64/libc.so.6)

The Builtins_ functions above seem to be emmited via a custom code generator0. No special linker .cfi directives are used, so this is effectively like writting raw assembly with frame pointers set up, but without telling the rest of the tooling how to produce unwidn information it.

Test Plan

We can't unwind nodejs and other v8-base applications as we can't
continue unwinding after the first AoT frame:

```
[...]
	current pc: 7fb0cf84904a
	current sp: 7fff93701498
	current bp: 7fff937014d8
[debug] Unwinding JITed stacks
[debug] Within unwinding machinery loop
	current pc: 157a329
	current sp: 7fff937014e8
	current bp: 7fff93701548
~about to check shards found=1
~checking shards now
[info] found chunk
le offset: 0
========== left 0 right 249997
	.done
	=> table_index: 206094
	=> adjusted pc: 157a329
	cfa type: 4, offset: 0 (row pc: 156f656)
[info] PC 157a329 not contained in the unwind info, found marker
[warn] mapping not added yet rbp 7fff93701548
pid 227936 tgid 227936
```

Turns out this AoT function doesn't have the corresponding DWARF unwind
information:

```
$ dist/eh-frame --executable /home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node | grep 157a3
$
```

After cross-validating the output with `bpftrace`'s and checking v8's source code it was clear why this is happening:

```
157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
157a32a Builtins_InterpreterEntryTrampoline+202 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
1578538 Builtins_JSEntryTrampoline+88 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
15782c3 Builtins_JSEntry+131 (/home/javierhonduco/.nvm/versions/node/v16.13.0/bin/node)
[...]
7f65c5e29510 __libc_start_call_main+128 (/usr/lib64/libc.so.6)
```

The `Builtins_` functions above seem to be emmited via a custom code
generator[0]. No special linker `.cfi` directives are used, so this is
effectively like writting raw assembly with frame pointers set up, but
without telling the rest of the tooling how to produce unwidn information it.

This commit includes other unrelated changes that have been made while
debugging this issue which hopefully improve the clarity and reliability of
the code.

Test Plan
=========

- node: https://pprof.me/95f85d0
- basic-cpp-no-fp: https://pprof.me/a6099f2
- ruby: https://pprof.me/4ecf047

- [0]: https://github.com/v8/v8/blob/e554f1e97e30f6e4cf6eef2c5049c17ca708e103/src/builtins/x64/builtins-x64.cc

Signed-off-by: Francisco Javier Honduvilla Coto <javierhonduco@gmail.com>
Copy link
Member

@brancz brancz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice find!

@javierhonduco javierhonduco marked this pull request as ready for review July 6, 2023 13:00
@javierhonduco javierhonduco requested a review from a team as a code owner July 6, 2023 13:00
@javierhonduco javierhonduco merged commit 9d44af3 into main Jul 6, 2023
22 checks passed
@javierhonduco javierhonduco deleted the force-fp-unwinding-for-v8-apps branch July 6, 2023 13:00
return 0;
}

// 3. Request unwind information.
request_unwind_information(ctx, user_pid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the numbered comments here!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:D hopefully things will be clearer and this will also prevent accidental reorders!

@javierhonduco javierhonduco changed the title Use frame pointer unwinding for v8-based application Use frame pointer unwinding for v8-based applications Jul 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants