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 optionsHowever, 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 :
- Manually install llvm-5.0 as described on https://apt.llvm.org/
- Download and build frama-clang as described officially with llvm-5.0
- Execute ./bin/framaCIRGen