"lazy symbol binding failed" with dynamically loaded pass in opt

Hello LLVM devs,

I’m running into the following problem when loading my custom passes in opt on OS X 10.9 (which work fine on Linux):

dyld: lazy symbol binding failed: Symbol not found: __ZN4llvm9CalculateINS_8FunctionEPNS_10BasicBlockEEEvRNS_17DominatorTreeBaseINS_11GraphTraitsIT0_E8NodeTypeEEERT_
  Referenced from: /Users/julian/Src/llvm/Debug+Asserts/lib/Nymblle.dylib
  Expected in: flat namespace

dyld: Symbol not found: __ZN4llvm9CalculateINS_8FunctionEPNS_10BasicBlockEEEvRNS_17DominatorTreeBaseINS_11GraphTraitsIT0_E8NodeTypeEEERT_
  Referenced from: /Users/julian/Src/llvm/Debug+Asserts/lib/Nymblle.dylib
  Expected in: flat namespace

I’m building the module „in-tree“; the Makefile contains the same settings as the Hello pass. nm tells me the resulting library (Nymblle.dylib) does not contain the missing symbols [U __ZN4llvm9Calculate...], whereas the opt executable (which is from the same LLVM build I use to build the module) does [<some address> t __ZN4llvm9Calculate…].

I think I’m missing some obvious difference in the way Linux and OS X handle dynamic libraries here, so any hints on why the symbols are found to be missing would be welcome. Thanks in advance!

Julian

Hi Julian,

I’m running into the following problem when loading my custom passes in opt on OS X 10.9 (which work fine on Linux):

One common problem (the only one I really know about, unfortunately)
is trying to load a module into Xcode's copy of "opt" rather than one
from the same tree as your module.

Xcode's one comes from a separate branch and is almost certainly
ABI-incompatible with every single revision of the main LLVM tree, in
one way or another.

Cheers.

Tim.

Hi Tim, Dear List,

Hi Tim, Dear List,

One common problem (the only one I really know about, unfortunately)
is trying to load a module into Xcode's copy of "opt" rather than one
from the same tree as your module.

I just double-checked that I use the opt executable from the same tree I use to build the module.

This tree is configured as a Debug+Asserts build, and compiled by the system compiler (which identifies itself as "Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)“. Would compiling the LLVM tree with another compiler, e.g., a recent GCC, make any difference?

Seems unlikely to help. We use Apple's clang all the time.

I tried various combinations of linking my passes with the related libraries via USEDLIBS, LLVMLIBS and LINK_COMPONENTS with no success. The outcome is either that opt does not load the module at all because of duplicated symbols, or that my custom passes don’t register properly at runtime (e.g., they’re not visible in „opt --help“)

Are you using the same configure line on both Linux and Darwin?

What build system are you using? (cmake vs. configure)

Is it the same build system you were using on Linux?

Hi Duncan, Dear List,

Are you using the same configure line on both Linux and Darwin?

yes, just a bare ./configure.

What build system are you using? (cmake vs. configure)

The configure/make system.

Is it the same build system you were using on Linux?

Yes.

In the meantime, I had a closer look on which particular symbol was missing. It turned out that the llvm::Calculate template (used by DominatorTreeBase::recalculate, which I call in my pass) is declared in llvm/Analysis/Dominators.h, but is implemented in DominatorInternals.h. *) When I include that header directly as a workaround, my pass works fine.

Cheers,
Julian

*) I forgot to mention that I'm still using the release_33 branch; in the trunk, the dominator tree computation code has been restructured, and no longer causes this linker problem in my example.

Great! So it sounds like the bug is fixed. Also good that
you've found a workaround.

Cheers,
Duncan