• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Postmortem support
2
3Postmortem metadata are constants present in the final build which can be used
4by debuggers and other tools to navigate through internal structures of software
5when analyzing its memory (either on a running process or a core dump). Node.js
6provides this metadata in its builds for V8 and Node.js internal structures.
7
8## V8 postmortem metadata
9
10V8 prefixes all postmortem constants with `v8dbg_`, and they allow inspection of
11objects on the heap as well as object properties and references. V8 generates
12those symbols with a script (`deps/v8/tools/gen-postmortem-metadata.py`), and
13Node.js always includes these constants in the final build.
14
15## Node.js debug symbols
16
17Node.js prefixes all postmortem constants with `nodedbg_`, and they complement
18V8 constants by providing ways to inspect Node.js-specific structures, like
19`node::Environment`, `node::BaseObject` and its descendants, classes from
20`src/utils.h` and others. Those constants are declared in
21`src/node_postmortem_metadata.cc`, and most of them are calculated at compile
22time.
23
24### Calculating offset of class members
25
26Node.js constants referring to the offset of class members in memory
27are calculated at compile time.
28Because of that, those class members must be at a fixed offset
29from the start of the class. That's not a problem in most cases, but it also
30means that those members should always come after any templated member on the
31class definition.
32
33For example, if we want to add a constant with the offset for
34`ReqWrap::req_wrap_queue_`, it should be defined after `ReqWrap::req_`, because
35`sizeof(req_)` depends on the type of T, which means the class definition should
36be like this:
37
38```cpp
39template <typename T>
40class ReqWrap : public AsyncWrap {
41 private:
42  // req_wrap_queue_ comes before any templated member, which places it in a
43  // fixed offset from the start of the class
44  ListNode<ReqWrap> req_wrap_queue_;
45
46  T req_;
47};
48```
49
50instead of:
51
52```cpp
53template <typename T>
54class ReqWrap : public AsyncWrap {
55 private:
56  T req_;
57
58  // req_wrap_queue_ comes after a templated member, which means it won't be in
59  // a fixed offset from the start of the class
60  ListNode<ReqWrap> req_wrap_queue_;
61};
62```
63
64There are also tests on `test/cctest/test_node_postmortem_metadata.cc` to make
65sure all Node.js postmortem metadata are calculated correctly.
66
67## Tools and references
68
69* [llnode](https://github.com/nodejs/llnode): LLDB plugin
70* [`mdb_v8`](https://github.com/joyent/mdb_v8): mdb plugin
71* [nodejs/post-mortem](https://github.com/nodejs/post-mortem): Node.js
72post-mortem working group
73