Loading Static Analyzer plugin fails with CommandLine Errors

(My apologies, I sent this e-mail first from the wrong e-mail account.)

I’m using Clang 3.3. I have a Clang Static Analyzer plugin that contains the following symbols:

extern “C” const char clang_analyzerAPIVersionString[] = CLANG_ANALYZER_API_VERSION_STRING;

extern “C” void clang_registerCheckers(clang::ento::CheckerRegistry& registry)

However, when I try to do something with it, like:

clang++ -c test.cpp -Xclang -load -Xclang plugin.so

I get the following output:

: CommandLine Error: Argument ‘view-background’ defined more than once!

: CommandLine Error: Argument ‘debug-only’ defined more than once!

: CommandLine Error: Argument ‘debug-buffer-size’ defined more than once!

: CommandLine Error: Argument ‘debug’ defined more than once!

: CommandLine Error: Argument ‘version’ defined more than once!

: CommandLine Error: Argument ‘print-all-options’ defined more than once!

: CommandLine Error: Argument ‘print-options’ defined more than once!

: CommandLine Error: Argument ‘help-hidden’ defined more than once!

: CommandLine Error: Argument ‘help’ defined more than once!

: CommandLine Error: Argument ‘help-list-hidden’ defined more than once!

: CommandLine Error: Argument ‘help-list’ defined more than once!

clang: CommandLine Error: Argument ‘view-background’ defined more than once!

clang: CommandLine Error: Argument ‘debug-only’ defined more than once!

clang: CommandLine Error: Argument ‘debug-buffer-size’ defined more than once!

clang: CommandLine Error: Argument ‘debug’ defined more than once!

clang: CommandLine Error: Argument ‘version’ defined more than once!

clang: CommandLine Error: Argument ‘print-all-options’ defined more than once!

clang: CommandLine Error: Argument ‘print-options’ defined more than once!

clang: CommandLine Error: Argument ‘help-hidden’ defined more than once!

clang: CommandLine Error: Argument ‘help’ defined more than once!

clang: CommandLine Error: Argument ‘help-list-hidden’ defined more than once!

clang: CommandLine Error: Argument ‘help-list’ defined more than once!

I have never encountered such an error before, and this works perfectly on a different machine, although with 32-bit binaries (it being a 32-bit system inside a VirtualBox).

The plugin was compiled using Clang 3.3, as a shared library, with -fPIC and -fno-rtti. ‘file plugin.so’ output:

ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped

‘file clang’ output:

ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xb08840ba88f98740a0e3f4b6448e1c4b70ad57ce, not stripped

Clang (again, version 3.3) was configured with --enable-optimized, and was built using GCC 4.7.2.

Any idea what could be the issue here?

Thanks!

Hi Gabor,

do you use 64 bit machine, right? (was confused about the 32 bit
virtual machine story.)

My experience on plugins is, that #1 you should not link any Clang
library against when you make your plugin. And #2 try not to use the
LLVM command line classes. (llvm::cl) Do the command line parsing
without those classes.

Regards,
Laszlo

Hi Laszlo,

do you use 64 bit machine, right? (was confused about the 32 bit
virtual machine story.)

Yes, the machine is 64-bit (both the processor and the OS - using Linux Mint 14 Cinnamon btw).

#1 you should not link any Clang
library against when you make your plugin

How do I not link against any Clang library when I’m writing a Clang plugin? I need to use Clang’s classes extensively.

#2 try not to use the
LLVM command line classes. (llvm::cl) Do the command line parsing
without those classes.

I do not use llvm::cl - I’m, in fact, not doing any command line arg processing. All my plugin does is register a bunch of custom checkers to Clang Static Analyzer.

Thanks for the response though!

In the meanwhile, I realize that I have done it all with the assumption that GCC 4.7.2 and Clang 3.3 generate compatible binaries. Could this be the source of the issue? I’ll try self-hosting Clang 3.3 and see what happens then.

Gabor

Hi Gabor,

#1 you should not link any Clang
library against when you make your plugin

How do I not link against any Clang library when I'm writing a Clang plugin?
I need to use Clang's classes extensively.

Sound weird, but works just fine. Your plugin will be loaded by the
Clang binary, and it already loaded the needed symbols. That's why you
don't need to explicitly link against them... You can look at
https://github.com/rizsotto/Constantine for cmake example.

In the meanwhile, I realize that I have done it all with the assumption that
GCC 4.7.2 and Clang 3.3 generate compatible binaries. Could this be the
source of the issue? I'll try self-hosting Clang 3.3 and see what happens
then.

I do compile my plugin with GCC and Clang is able to load it without problem.

My two cents are still on the llvm::cl classes. Although you are not
using them, but the libraries that you are link against might. (That's
why I was suggest not to do that.) And not to mention the fact, that
the messages are emitted by the CommandLine.cpp:144. See also:

  http://comments.gmane.org/gmane.comp.compilers.clang.devel/6870
  http://comments.gmane.org/gmane.comp.compilers.clang.scm/63478

Regards,
Laszlo

Thanks Laszlo, you make good points, I’ll investigate.

Right. On a Mac there’s a heavy-handed way to do this ("-undefined dyamic_lookup") and a lighter way ("-bundle_loader path/to/clang"). According to the flag on Linux might be --allow-shlib-undefined or --unresolved-symbols=ignore-in-object-files; I don’t know if there’s an equivalent to -bundle_loader.

Jordan

Thanks Jordan. My issue is that this error is reported when I try running clang. So where do I specify these args? When compiling Clang, or when compiling my plugin…?

Also, it doesn’t really explain why everything works fine on the 32-bit system.

These are link arguments when compiling your plugin, and like Laszlo said you should use them instead of linking to the Clang libraries, since they’ll be found by the dynamic linker at runtime.

I’d guess that in 32 bits things get linked differently and either don’t overlap or can’t easily be reported…or perhaps just aren’t reported for historical reasons.

Jordan

So I got the following error when attempting to load the plugin that was compiled without linking against any clang or LLVM libs:

error: unable to load plugin ‘myPlugin.so’: 'myPlugin.so: undefined symbol:

_ZTVN5clang12ast_matchers11MatchFinder13MatchCallbackE’

But then I realized that libASTMatchers is not loaded by Clang when doing --analyze (since it is not used by the Static Analyzer), so I have to link against it in the plugin. Doing so and using --allow-shlib-undefined when compiling the plugin works on both the 32-bit and 64-bit machines.

Thank you all very much for your help!