[llvm-dev] (Orc)JIT and weak symbol resolution

Axel Naumann via llvm-dev
2016-04-29T12:20:50Z

Hi,

This is a question on how to resolve weak symbols from the binary for
symbols that are also llvm::Module-local. Currently, the JIT seems to
favor resolving to module-local symbols over existing symbols:

$ cat symbols.cxx
extern "C" int printf(const char*,...);

template <class T> struct StaticStuff {
  static T s_data;
};
template <class T> T StaticStuff<T>::s_data = 42;

int compareAddr(int* interp);
#ifdef BUILD_SHARED
int compareAddr(int* interp) {
  if (interp != &StaticStuff<int>::s_data) {
    printf("Wrong address, %ld in shared lib, %ld in interpreter!\n",
           (long)&StaticStuff<int>::s_data,
           (long)interp);
    // CHECK-NOT: Wrong address
    return 1;
  }
  return 0;
}
#else
# ifdef __CLING__
int Symbols() {
# else
int main()
# endif
{  return compareAddr(&StaticStuff<int>::s_data);}
#endif // ! BUILD_SHARED


$ clang++ -shared -fPIC -DBUILD_SHARED symbols.cxx -o libSymbols.so
$ clang++ -cc1 -emit-llvm symbols.cxx -o - |  lli -load ./libSymbols.so -
or
$ clang++ -lSymbols symbols.cxx && ./a.out

Compiled it's happy: the weak symbol used in main gets resolved to be
the one in the binary for both references. That's the behavior I'd
expect.

The JIT OTOH is deciding that it shall use the local version of the
symbol; RuntimeDyld::getSymbol() doesn't care about the fact that the
symbol is weak and has an existing occurrence.

For weak symbols from a different module, RuntimeDyld would use
resolveExternalSymbols() and all would be good - but here this doesn't
happen.

IIUC, RuntimeDyld::getSymbol() really needs to check whether the local
symbol should survive or not, before handing out its address. But that
seems to break the whole design of when relocs happen, so I'm sure I'm
wrong. Can I get some hints on how to implement the proper patch?

Cheers, Axel.

--
ROOT - http://root.cern.ch
PH-SFT, CERN, 1211 Geneve 23, Switzerland
Tel: +41 22 7678225