Skip to content

Crash on attempt to start framaCIRGen when libs are linked statically and dynamically.

ID0002368: This issue was created automatically from Mantis Issue 2368. Further discussion may take place here.


Id Project Category View Due Date Updated
ID0002368 Frama-C Plug-in > clang public 2018-02-15 2018-07-11
Reporter DeMaze Assigned To virgile Resolution fixed
Priority normal Severity crash Reproducibility always
Platform GNU/Linux OS Debian OS Version 9.3
Product Version Frama-C 16-Sulfur Target Version - Fixed in Version Frama-C 17-Chlorine

Description :

On the attempt to install Frama-Clang regularly as described (see attached file installation.txt), the executable framaCIRGen exits with an error when executed. The error message points to a problem with LLVM. In fact, it depicts one commandline option to be registered more than once. This occurs on the attempt of using Frama-C to parse C++ source code and when the executable framaCIRGen is invoked manually on the commandline. I get the following error:

: CommandLine Error: Option 'asm-macro-max-nesting-depth' registered more than once! LLVM ERROR: inconsistency in registered CommandLine options

However, this has only been observed ith llvm-5.0 on Debian GNU/Linux 9.3 (my system, see lsb_release_3ffbf_2018-02-10000905) for now. With llvm 3.9, no such errors happen. Presumably, versions of llvm > 5.0 could also be affected. This seems to be a problem many people have experienced with llvm related programs [2][3][4][5]. In fact, it has even been reported for frama-clang [6].

Additional Information :

Root Cause

As far as my investigations revealed, this problem occurs because of the linking mechanism on Debian GNU/Linux. On this distribution, libraries of LLVM are built two-fold:

Static archives (lib*.a): clangFrontend, clangDriver, clangTooling, clanParse, clangSema, clangAnalysis, clangEdit, clangAST, clangLex, clangSerialization, clangBasic, LLVMTransformUtils, LLVMBitReader, LLVMMCParser, LLVMOption

Shared object (lib*.so): LLVM-5.0

Therefore, it is tried to link them according to their type (lines 74-77, 82-85): 69 CFLAGS+=-g 70 CLANG_LINKFLAGS+=-g 71 endif 72 73 #LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc 74 USEDLIBS = clangFrontend
75 clangDriver clangTooling clangParse clangSema
76 clangAnalysis clangEdit clangAST clangLex clangSerialization
77 clangBasic LLVMTransformUtils LLVMBitReader LLVMMCParser LLVMOption 78 79 # for use in main Makefile 80 default: (PLUGIN_DIR)/bin/(TOOLNAME) 81 82 (PLUGIN_DIR)/bin/(TOOLNAME): $(OBJS) $(PLUGIN_DIR)/bin 83 $(PRINT_LINKING) $@ 84 $(CXX) $(CLANG_LINKFLAGS) -o $@
85 $(OBJS) (addprefix -l,(USEDLIBS)) $(LLVM_LIBS) $(CLANG_SYSLIBS) $(CLANG_LINKFLAGS) 86 87 $(PLUGIN_DIR)/bin: 88 $(MKDIR) $@ 89 90 clean:

This results in the following dependencies on dynamic libraries as follows: linux-vdso.so.1 (0x00007ffe31ff5000) libLLVM-5.0.so.1 => /usr/lib/x86_64-linux-gnu/libLLVM-5.0.so.1 (0x00007fb4c4825000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb4c44a3000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb4c419f000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb4c3f88000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb4c3be9000) libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007fb4c39e0000) libedit.so.2 => /usr/lib/x86_64-linux-gnu/libedit.so.2 (0x00007fb4c37a8000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fb4c35a0000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fb4c339c000) libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fb4c3172000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb4c2f55000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fb4c2d3b000) /lib64/ld-linux-x86-64.so.2 (0x00007fb4c9431000) libncurses.so.5 => /lib/x86_64-linux-gnu/libncurses.so.5 (0x00007fb4c2b18000) libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fb4c2902000)

From this output, this assumption can be confirmed because ligcc_s.so.1 as well as libLLVM-5.0.so.1 occurs. A response on a bug report of LLVM considers this as rather bad practice however. Moreover, this is mentioned as a classical problem of LLVM's "global object-based commandline switch registration" [1]:

"The command line option error is the classical problem one gets due to the LLVM's global object-based command line switch registration. If you somehow link the same global object (that registers the command line option) twice via dynamic loading of the LLVM library twice or more to the same process, it registers the same command line object again (when calling the global object initializer), resulting in this error." [1]

The aforementioned symbol 'asm-macro-max-nesting-depth' occurs both in libLLVMMCParser.a and libLLVM-5.0.so.1 . Hence, I conjecture these are the files in conflict.

My Solution

Just link without libLLVMMCParser.a or more precisely, remove LLVMMCParser from USEDLIBS in Makefile.clang. This seems to work as C++ code is analyzable again. Please find patches for Makefile.clang attached which circumvent this problem according to my proposal (Makefile.clang.patch / Makefile.clang.patch.better). Feel free to contacting me in case of any further quesions / comments.

References

[1] https://bugs.llvm.org/show_bug.cgi?id=30587#c6 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768185 [3] https://bugs.llvm.org/show_bug.cgi?id=31571 [4] http://llvm.1065342.n5.nabble.com/llvm-dev-LLD-and-LLVM-LINK-LLVM-DYLIB-td104570.html [5] https://github.com/zig-lang/zig/issues/67 [6] https://stackoverflow.com/questions/45647503/errors-when-using-the-frama-clang-plugin

Steps To Reproduce :

  1. Manually install llvm-5.0 as described on https://apt.llvm.org/
  2. Download and build frama-clang as described officially with llvm-5.0
  3. Execute ./bin/framaCIRGen

Attachments

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information