Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

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

Closed
wants to merge 1 commit into from

2 participants

@ackalker

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
@ackalker ackalker Fix v8dbg_* symbols not being linked in when statically linking v8
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.
f7013f4
@ackalker

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

@ackalker

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
@bnoordhuis

@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

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 join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 11, 2012
  1. @ackalker

    Fix v8dbg_* symbols not being linked in when statically linking v8

    ackalker authored
    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.
This page is out of date. Refresh to see the latest.
Showing with 12 additions and 2 deletions.
  1. +4 −0 deps/v8/src/v8.cc
  2. +8 −2 deps/v8/tools/gyp/v8.gyp
View
4 deps/v8/src/v8.cc
@@ -44,6 +44,10 @@
#include "serialize.h"
#include "store-buffer.h"
+#if defined(POSTMORTEM_SUPPORT)
+#include <debug-support.h>
+#endif
+
namespace v8 {
namespace internal {
View
10 deps/v8/tools/gyp/v8.gyp
@@ -744,8 +744,14 @@
],
}],
['v8_postmortem_support=="true"', {
+ 'defines': [
+ 'POSTMORTEM_SUPPORT'
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)'
+ ],
'sources': [
- '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/debug-support.h',
],
'dependencies': ['postmortem-metadata']
}],
@@ -841,7 +847,7 @@
'<@(heapobject_files)',
],
'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/debug-support.h',
],
'action': [
'python',
Something went wrong with that request. Please try again.