Optimized "opt" on Darwin fails to load dynamic libraries with passes

Hi all,

This is a problem that occurs for me only on Darwin (MacOS) and not on Linux.

When llvm 2.8 (or 2.9) is compiled with ENABLE_OPTIMIZED=1, the “opt” tool fails to load LLVM passes in dynamic libraries (.dylib) files, regardless of how they themselves were built. When opt is built with ENABLE_OPTIMIZED=0, all is well.

Here is some informative output. Seems to me the problem is in stripping the symbols of the assignPassManager virtual method from the various subclasses of llvm::Pass.

Please advise!

// the release version has all the necessary symbols in place before it is installed to /usr/local/bin
$ nm -m Release+Asserts/bin/opt | grep assignPass
000000010042b7c0 (__TEXT,__text) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001002a27c0 (__TEXT,__text) external __ZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010042b490 (__TEXT,__text) external __ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010042b260 (__TEXT,__text) external __ZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001002053a0 (__TEXT,__text) external __ZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004223d0 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
0000000100262120 (__TEXT,__text) external __ZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004d7936 (__TEXT,__cstring) non-external ZZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004bcf42 (__TEXT,__cstring) non-external ZZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004d7924 (__TEXT,__cstring) non-external ZZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004d7901 (__TEXT,__cstring) non-external ZZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004b404f (__TEXT,__cstring) non-external ZZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004b9ce0 (__TEXT,__cstring) non-external ZZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func

// same is true for the debug build
$ nm -m Debug+Asserts/bin/opt | grep assignPass
000000010040ea82 (__TEXT,__text) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
0000000100299a82 (__TEXT,__text) external __ZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010040e8a0 (__TEXT,__text) external __ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010040e758 (__TEXT,__text) external __ZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001001fcb5e (__TEXT,__text) external __ZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004093a8 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010025687e (__TEXT,__text) external __ZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004e349b (__TEXT,__cstring) non-external ZZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004c8414 (__TEXT,__cstring) non-external ZZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004e3489 (__TEXT,__cstring) non-external ZZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004e3466 (__TEXT,__cstring) non-external ZZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004bf4e6 (__TEXT,__cstring) non-external ZZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004c5402 (__TEXT,__cstring) non-external ZZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func

// however, once it is installed with “make install” to /usr/local/bin, it’s stripped of most of the relevant symbols (those of the llvm::Pass subclasses)
$ nm -m /usr/local/bin/opt | grep assignPass
00000001004223d0 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE

// my dynamic library contains a ModulePass, with a matching symbol that is missing in the installed “opt” binary
$ nm -m /usr/local/lib/libMyPass.dylib | grep assignPass
(undefined) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE

// and indeed, when opt tries to load it, it fails.
$ opt -load /usr/local/lib/libMyPass.dylib
Error opening ‘/usr/local/lib/libMyPass.dylib’: dlopen(/usr/local/lib/libMyPass.dylib, 9): Symbol not found: __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
Referenced from: /usr/local/lib/libMyPass.dylib
Expected in: flat namespace
in /usr/local/lib/libMyPass.dylib
-load request ignored.

Thanks a lot,

Harel Cain

I see now that this clearly to the problem raised elswhere, for example:

http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-December/036764.html
http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-November/036289.html

So clearly a repeating issue on the MacOS platform.

Harel

Hi again everyone,

A year ago I asked about this problem which has been reported by me and a few others. I’m basically repeating the same problem report below because neither I nor the others who raised this issue got any response.

http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-December/036764.html
http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-November/036289.html

This is a problem that occurs only on Darwin (MacOS) and not on Linux.

When llvm 2.9 is compiled with ENABLE_OPTIMIZED=1, the “opt” tool fails to load LLVM passes in dynamic libraries (.dylib) files, regardless of how they themselves were built. When opt is built with ENABLE_OPTIMIZED=0, all is well.

Here is some informative output with my comments.
Seems to me the problem is in stripping the symbols of the assignPassManager virtual method from the various subclasses of llvm::Pass.

// the release version has all the necessary symbols in place before it is installed to /usr/local/bin&
$ nm -m Release+Asserts/bin/opt | grep assignPass
000000010042b7c0 (__TEXT,__text) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001002a27c0 (__TEXT,__text) external __ZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010042b490 (__TEXT,__text) external __ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010042b260 (__TEXT,__text) external __ZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001002053a0 (__TEXT,__text) external __ZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004223d0 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
0000000100262120 (__TEXT,__text) external __ZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004d7936 (__TEXT,__cstring) non-external ZZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004bcf42 (__TEXT,__cstring) non-external ZZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004d7924 (__TEXT,__cstring) non-external ZZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004d7901 (__TEXT,__cstring) non-external ZZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004b404f (__TEXT,__cstring) non-external ZZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004b9ce0 (__TEXT,__cstring) non-external ZZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func

// same is true for the debug build
$ nm -m Debug+Asserts/bin/opt | grep assignPass
000000010040ea82 (__TEXT,__text) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
0000000100299a82 (__TEXT,__text) external __ZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010040e8a0 (__TEXT,__text) external __ZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010040e758 (__TEXT,__text) external __ZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001001fcb5e (__TEXT,__text) external __ZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004093a8 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
000000010025687e (__TEXT,__text) external __ZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
00000001004e349b (__TEXT,__cstring) non-external ZZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004c8414 (__TEXT,__cstring) non-external ZZN4llvm10RegionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004e3489 (__TEXT,__cstring) non-external ZZN4llvm12FunctionPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004e3466 (__TEXT,__cstring) non-external ZZN4llvm14BasicBlockPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004bf4e6 (__TEXT,__cstring) non-external ZZN4llvm16CallGraphSCCPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func
00000001004c5402 (__TEXT,__cstring) non-external ZZN4llvm8LoopPass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeEE8__func

// however, once it is installed with “make install” to /usr/local/bin, it’s stripped of most of the relevant symbols (those of the llvm::Pass subclasses)
$ nm -m /usr/local/bin/opt | grep assignPass
00000001004223d0 (__TEXT,__text) weak external __ZN4llvm4Pass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE

// my dynamic library contains a ModulePass, with a matching symbol that is missing in the installed “opt” binary
$ nm -m /usr/local/lib/libMyPass.dylib | grep assignPass
(undefined) external __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE

// and indeed, when opt tries to load it, it fails.
$ opt -load /usr/local/lib/libMyPass.dylib
Error opening ‘/usr/local/lib/libMyPass.dylib’: dlopen(/usr/local/lib/libMyPass.dylib, 9): Symbol not found: __ZN4llvm10ModulePass17assignPassManagerERNS_7PMStackENS_15PassManagerTypeE
Referenced from: /usr/local/lib/libMyPass.dylib
Expected in: flat namespace
in /usr/local/lib/libMyPass.dylib
-load request ignored.

Thanks a lot,

Harel Cain