Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

v8dbg_* symbols not available when NodeJS is statically linked with V8 #4274

Closed
wants to merge 1 commit into from
Closed

v8dbg_* symbols not available when NodeJS is statically linked with V8 #4274

wants to merge 1 commit into from

Conversation

ackalker
Copy link

When NodeJS is statically linked with libv8_base.a, which is the default, I've found that the v8dbg_* debug symbols generated by deps/v8/tools/gen-postmortem-metadata.py are not included in the node binaries. This makes debugging with GDB or writing DTrace or SystemTap probes more difficult than needed (see tools/genv8constants.py).

After some hunting around, I found that while debug-support.cc is being generated and compiled, the debug-support.o object file is never linked into the node binaries. This is because the linker decides that nothing in the node binary actually uses anything defined in debug-support.o, and skips the object file entirely.

I've found a surprisingly trivial fix: instead of a C++ file, create a header file instead, then #include it somewhere which is certainly going to get linked into node.

Any comments and suggestions are very welcome.

Tested with gdb and SystemTap

$ gdb out/Debug/node
[...]
(gdb) p v8dbg_SmiTagMask
$1 = 1
# stap -e 'probe process.function("main") { printf("%s: %s(%d)\n", pp(), execname(), pid()); printf("v8dbg_SmiTagMask = %d\n", @var("v8dbg_SmiTagMask@v8.cc")) }' -c out/Debug/node
process("/home/miki/vcs/git/node/out/Debug/node").function("main@../src/node_main.cc:64"): node(10908)
v8dbg_SmiTagMask = 1

When linking static libraries, linkers usually skip objects which
they consider not to be used by anything else in the final binary.

Fix this by generating a header file instead of a cc file, and
including that in a module which is certainly going to be linked.
@ackalker
Copy link
Author

I would like to invite @bnoordhuis to have a look at this issue, since it affects v8's d8 and shell as well.

@ackalker
Copy link
Author

Another alternative could be to use something like this: put all the debug variables in a self-initializing struct.

debug-support.h:

#ifndef _DEBUG_SUPPORT

#ifndef _V8VARS_DEF

typedef struct v8vars {
#define V8VAR(type, name, value)    type name;
#define _V8VARS_DEF

#else

} v8vars_t;
v8vars_t v8dbg = {

#define V8VAR(type, name, value)    value,
#define _DEBUG_SUPPORT

#endif

V8VAR(int, initialized, 0)
V8VAR(int, var1, 42)
V8VAR(char, var2, 'a')

#ifdef _DEBUG_SUPPORT

};

void v8dbg_init() {
    v8dbg.initialized = 1;
}

#else

#undef V8VAR
#include "debug-support.h"

#endif

#endif

main.cc:

#include <stdio.h>
#include <stdlib.h>

#include "debug-support.h"

int main(int argc, char *argv[]) {
    v8dbg_init();
    printf("Hello, world!\n");
    printf("The answer is: %d\n", v8dbg.var1);
    exit(0);
}

Though it may look hideous, it actually has a purpose: the preprocessor has to parse the header file twice, the v8dbg struct will be fully initialized at the end of the last pass.

This solution has several advantages:

  • Although v8dbg is a struct, the generator script needs to loop over the list of variables only once.
  • calling an initialize function which modifies a member of the struct will force the linker to include it in the final binary.
  • the v8dbg_initialize() function makes a perfect target for an stap process.function probe to pick up the variables.

Again, any suggestions are very welcome.

@ackalker ackalker closed this Nov 18, 2012
@bnoordhuis
Copy link
Member

@ackalker Is there a reason you closed this PR?

I've found a surprisingly trivial fix: instead of a C++ file, create a header file instead, then #include it somewhere which is certainly going to get linked into node.

The default symbol visibility is 'hidden' so I don't think that's going to work. Compiling with -fdata-sections -Wl,--gc-sections or -flto will almost certainly strip the symbols. You'd have to tag the generated symbols with __attribute__((visibility("default"))) to stop that from happening.

That said, we don't usually take V8 patches. I may make an exception in this case because it's obviously useful but I'd rather you send it upstream first.

@ackalker
Copy link
Author

Thanks for your time :-)
The reason I closed the PR was that I thought that my first solution was too messy. I now have a tested, working patch.. I will open a new PR with pull request.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants