Strange link errors involving ArrayBuffer::Allocator (occur with v8 6.1, but did not occur with v8 5.5)

414 views
Skip to first unread message

Scott Davies

unread,
Jun 27, 2017, 12:57:36 PM6/27/17
to v8-users
Hi --

I'm working on a C++ library that was compiling and linking just fine with v8 until I upgraded to a new Mac (OS 10.12.5, clang++ version 802.0.42) and moved up to the latest version of v8 (6.1.0). Now I'm getting lots of link errors involving v8::ArrayBuffer::Allocator. I've reproduced the problem in a minimal test case:

> clang++ -o v8linkfail -std=c++11 -stdlib=libc++ -Wall -Werror -O0 -fno-inline -g -Wall -Werror -O0 -fno-inline -g -I/Users/scott/v8/v8/include v8linkfail.cpp -L/Users/scott/v8/v8/out.gn/x64.debug/ -lv8 -lv8_libplatform -lv8_libbase -licuuc -licui18n -lv8_for_testing

Undefined symbols for architecture x86_64:

  "typeinfo for v8::ArrayBuffer::Allocator", referenced from:

      typeinfo for DefaultV8ArrayBufferAllocator in v8linkfail-fbc69e.o


Here /Users/scott/v8 contains a v8 distribution checked out and built (https://github.com/v8/v8/wiki/Building-with-GN)just yesterday, and v8linkfail.cpp is a very simple test program:


/////////////////////// begin v8linkfail.cpp


#include <stdlib.h>

#include <v8.h>


class DefaultV8ArrayBufferAllocator: public v8::ArrayBuffer::Allocator {

public:

  virtual void* Allocate(size_t length) {

    void* data = AllocateUninitialized(length);

    return data == NULL ? data : memset(data, 0, length);

  }

  virtual void* AllocateUninitialized(size_t length) { 

    return malloc(length); 

  }

  virtual void Free(void* data, size_t) { 

    free(data); 

  }

};


int main(int argc, char** argv) {


  std::unique_ptr<v8::ArrayBuffer::Allocator> alloc

    (new DefaultV8ArrayBufferAllocator);

  return 0;

}


////////////////////// end v8linkfail.cpp 

This code compiles and links just fine with an older version of v8 (5.5.0) (even on the same Mac on which v8 6.1.0 causes the link problems). 

Looking at v8.h, I see that from 5.5.0 to 6.1.0, some new methods were declared in ArrayBuffer::Allocator: Reserve(size_t), Free(void*, size_t, AllocationMode), and SetProtection(void*, size_t, Protection). Normally a link error like this would make me think "Ah hah! I bet somebody forgot to define one of those new methods, and the vtable / type information is never getting emitted because of that!", but as far as I can tell those new methods are in fact all defined in (the 6.1.0 version of) api.cc, so I don't see any problems there.

Looking at the guts of generated object files with nm -mo: when v8linkfail.cpp is compiled to an object file using the old include files in v8 5.5.0, the type info for ArrayBuffer::Allocator does in fact show up in the generated object file (and everything links fine):

> nm -mo v8linkfail_v8_5.5.o | c++filt | grep type | grep Allocator

v8linkfail_v8_5.5.o: 0000000000000450 (__DATA,__data) weak external typeinfo for DefaultV8ArrayBufferAllocator

v8linkfail_v8_5.5.o: 0000000000000438 (__DATA,__data) weak external typeinfo for v8::ArrayBuffer::Allocator

v8linkfail_v8_5.5.o: 00000000000004a0 (__TEXT,__const) weak external typeinfo name for DefaultV8ArrayBufferAllocator

v8linkfail_v8_5.5.o: 00000000000004c0 (__TEXT,__const) weak external typeinfo name for v8::ArrayBuffer::Allocator


(Note: this is not exactly where I was expecting the typeinfo to show up -- I would have expected it in v8's api.o instead of my code's object file. However, nm sees no mention of it in *either* the 5.5 or 6.1 version of api.o, so I'm going to assume that this is somehow "normal" C++ behavior.)


On the other hand, when v8linkfail.cpp is compiled to an object file using the include files in v8 6.1.0, the type info for ArrayBuffer::Allocator becomes undefined, and that's when the link errors show up:


> nm -mo v8linkfail_v8_6.1.o | c++filt | grep type | grep Allocator

v8linkfail_v8_6.1.o: 0000000000000400 (__DATA,__data) weak external typeinfo for DefaultV8ArrayBufferAllocator

v8linkfail_v8_6.1.o:                  (undefined) external typeinfo for v8::ArrayBuffer::Allocator

v8linkfail_v8_6.1.o: 0000000000000420 (__TEXT,__const) weak external typeinfo name for DefaultV8ArrayBufferAllocator



I'll admit I'm at a bit of a loss as to what's going on here, or how to proceed. Is there a subtle bug somewhere either in v8's code (presumably v8.h and/or api.cc) and/or in my definition of DefaultV8ArrayBufferAllocator above? (By now I've stared at both my code and v8's code to find this unlikely, but I could be missing something.) Or is there a bug somewhere in the compiling/linking toolchain (yikes)? Or is something funny going on because v8 was compiled with different tools or flags than v8linkfail.cpp? If it might be the last of these (compiled with different tools/flags), how might I go about determining exactly what tools and flags all the bits of v8 were built with, and what flags should I be suspicious of? (Building v8 with GN was not particularly transparent...is there an easy way to pass in some sort of "-v"-like flag to ninja or whatever that will dump all the commands used during the build while it's building?) 


Thanks,


-- Scott






Scott Davies

unread,
Jun 27, 2017, 1:17:27 PM6/27/17
to v8-users
Oops...never mind my final stupid question, because ninja does in fact have an obvious -v flag. :)  Any other ideas about what might actually be causing the problem would still be greatly appreciated, however. 

Scott Davies

unread,
Jun 27, 2017, 1:34:57 PM6/27/17
to v8-users
To (tentatively) answer my own question: V8 appears to be mostly compiled without RTTI by default, and woe unto those poor souls who compile and link against it without also adding -fno-rtti.

Sigh.

Benjamin B.

unread,
Jul 27, 2017, 5:17:10 PM7/27/17
to v8-users
Hello,

I got the exact same problem and your answer solved it. Can you explain me a bit more in detail what magic happens ? 

Thank you :)

Zac Hansen

unread,
Jul 27, 2017, 10:49:34 PM7/27/17
to v8-users

I link against it all the time with rtti and exceptions and don't have any problems as long as I don't let any exceptions get into the actual V8 code.  

Obviously you can't do anything with it that requires typeinfo on the v8 types, but it doesn't stop you from linking ALL code that uses RTTI with V8.  

Zac Hansen

unread,
Jan 18, 2018, 8:05:35 AM1/18/18
to v8-users
quick note, if you compile something with -fsanitize=undefined, it will create a dependency on this typeinfo because it brings in the vptr sanitizer (among a bunch of others).

You can run with all the undefined sanitizers except vptr with:  -fsanitize=undefined -fno-sanitize=vptr

jeff stein

unread,
Jan 22, 2018, 4:27:22 PM1/22/18
to v8-users
Hello Zac - I was wondering if you could help with finding someone who could help us on a V8 integration project.

Kind regards, 

Jeff Stein

jeff stein

unread,
Jan 22, 2018, 4:40:30 PM1/22/18
to v8-users
Hello Scott - Do you know of anyone who could help on a v8 integration project? We are looking to put together a prototype to demonstrate capabilities and need help with embedding V8. 

Do you know anyone or are you interested possibly?

Many thanks, 

Jeff Stein
Reply all
Reply to author
Forward
0 new messages