Bug 35018

Summary: Статические библиотеки libclang*.a не содержат ELF объектов, а содержат LLVM IR bitcode
Product: Sisyphus Reporter: Vitaly Chikunov <vt>
Component: clang6.0-devel-staticAssignee: Konstantin A Lepikhov (L.A. Kostis) <lakostis>
Status: CLOSED DUPLICATE QA Contact: qa-sisyphus
Severity: normal    
Priority: P3 CC: glebfm, ldv
Version: unstable   
Hardware: x86_64   
OS: Linux   
Bug Depends on: 35026    
Bug Blocks:    

Description Vitaly Chikunov 2018-06-11 03:58:01 MSK
При сборке bcc выяснилось, что GNU ld не может линковать с библиотеками /usr/lib64/libclang*.a так как не понимает объектов внутри них.

[ 52%] Linking CXX shared library libbcc.so
/usr/lib64/gcc/x86_64-alt-linux/7/../../../../lib64/libclangFrontend.a: member /usr/lib64/gcc/x86_64-alt-linux/7/../../../../lib64/libclangFrontend.a(ASTConsumers.cpp.o) in archive is not an object
collect2: error: ld returned 1 exit status

[builder@localhost t]$ ar xv /usr/lib64/gcc/x86_64-alt-linux/7/../../../../lib64/libclangFrontend.a ASTConsumers.cpp.o
x - ASTConsumers.cpp.o

[builder@localhost t]$ file ASTConsumers.cpp.o
ASTConsumers.cpp.o: data

[builder@localhost t]$ objdump -x ASTConsumers.cpp.o
objdump: ASTConsumers.cpp.o: File format not recognized

[builder@localhost t]$ xxd ASTConsumers.cpp.o|head -2
00000000: 4243 c0de 3514 0000 0500 0000 620c 3024  BC..5.......b.0$
00000010: 4959 bea6 eed3 3e2d 4401 3205 0000 0000  IY....>-D.2.....

[builder@localhost t]$ ld CoverageMapping.cpp.o
CoverageMapping.cpp.o: file not recognized: File format not recognized

[builder@localhost t]$ ld --whole-archive /usr/lib64/libclangFrontend.a
/usr/lib64/libclangFrontend.a: member /usr/lib64/libclangFrontend.a(ASTConsumers.cpp.o) in archive is not an object


Для сравнения, file с дебиана распознает такой файл как "LLVM IR bitcode". В то время как аналогичный файл на дебиане (из /usr/lib/llvm-3.9/lib/libclangFrontend.a из пакета libclang-3.9-dev) это ELF:

debian9:~/x$ ar xv /usr/lib/llvm-3.9/lib/libclangFrontend.a ASTConsumers.cpp.o
x - ASTConsumers.cpp.o

debian9:~/x$ file ASTConsumers.cpp.o
ASTConsumers.cpp.o: ELF 64-bit LSB relocatable, x86-64, version 1 (GNU/Linux), not stripped

debian9:~/x$ ld CoverageMapping.cpp.o  ... и ...
debian9:~/x$ ld --whole-archive /usr/lib/llvm-3.9/lib/libclangFrontend.a
...пишут кучу ошибок линковки, следовательно, ld понимает этот архив.

ps. К слову, с библиотеками libLLVM*.a то же самое:

[builder@localhost t]$ ld --whole-archive /usr/lib64/libLLVMCoverage.a
/usr/lib64/libLLVMCoverage.a: member /usr/lib64/libLLVMCoverage.a(CoverageMapping.cpp.o) in archive is not an object
Comment 1 Vitaly Chikunov 2018-06-11 12:55:04 MSK
Приходится обходить проблему сборки под gcc+ld таким трюком:

mkdir -p /usr/src/bin
cat > /usr/src/bin/ld <<'EOF'
#!/bin/bash
if [[ "$*" =~ (libclang|libLLVM)[^\ ]*.a ]]; then
       o=${@//--push-state}
       o=${o//--pop-state}
       set -- $o
       exec /usr/bin/ld.lld "$@"
else
       exec /usr/bin/ld "$@"
fi
EOF
chmod a+x /usr/src/bin/ld

%cmake_build
Comment 2 Konstantin A Lepikhov (L.A. Kostis) 2018-06-11 23:54:01 MSK
см. пример с castxml. GNU ld это неправильный выбор в случае статической линковки с clang-devel-static. Либо используйте lld либо линкуйтесь динамически.

*** This bug has been marked as a duplicate of bug 34801 ***
Comment 3 Vitaly Chikunov 2018-06-12 00:01:01 MSK
lld не поддерживает опции --push-state --pop-state которые шлет gcc. Кроме того, вылазит ошибка "error: bcc.o: string table non-null terminated".
Comment 4 Konstantin A Lepikhov (L.A. Kostis) 2018-06-12 00:46:01 MSK
(In reply to comment #3)
> lld не поддерживает опции --push-state --pop-state которые шлет gcc. Кроме
> того, вылазит ошибка "error: bcc.o: string table non-null terminated".

У вас есть пример кода и проект, где есть реальная потребность использовать clang static libs специфические флаги gcc?
Comment 5 Vitaly Chikunov 2018-06-12 01:41:54 MSK
Не понял вопроса. Флаги (опции) шлёт gcc линкеру, не я. Кроме того, при линковке lld на некоторых файлах ошибка "error: bcc.o: string table non-null terminated". То есть, ни чистым ld, ни чистым lld пакет bcc собрать нельзя. Пакет я собрал с враппером из Comment #1, который вызывает то ld, то lld в зависимости от того что линкуется. (Я попробую переделать сборку на clang, позже.)
Comment 6 Konstantin A Lepikhov (L.A. Kostis) 2018-06-12 01:54:36 MSK
(In reply to comment #5)
> Не понял вопроса. Флаги (опции) шлёт gcc линкеру, не я. Кроме того, при
> линковке lld на некоторых файлах ошибка "error: bcc.o: string table non-null
> terminated". То есть, ни чистым ld, ни чистым lld пакет bcc собрать нельзя.
> Пакет я собрал с враппером из Comment #1, который вызывает то ld, то lld в
> зависимости от того что линкуется. (Я попробую переделать сборку на clang,
> позже.)

Вы какой-то пакет собираете? Можно узнать какой или это секрет?
Comment 7 Vitaly Chikunov 2018-06-12 01:57:07 MSK
bcc http://git.altlinux.org/tasks/208269/gears/200/git
Comment 8 Vitaly Chikunov 2018-06-13 03:54:07 MSK
Update. Использование clang вместо gcc никак не влияет на результат.

1. При использовании ld сборка обрывается на:

[ 69%] Linking CXX shared library libbcc.so
cd /usr/src/RPM/BUILD/bcc-v0.5.0/BUILD/src/cc && /usr/bin/cmake -E cmake_link_script CMakeFiles/bcc-shared.dir/link.txt --verbose=1
/usr/bin/clang++ -fPIC -pipe -Wall -g -O2 -Wall  -fno-rtti -fPIC -DBCC_PROG_TAG_DIR='"/var/tmp/bcc"' -DLLVM_MAJOR_VERSION=6 -O2 -g -DNDEBUG   -Wl,--exclude-lib
s=libclangFrontend.a -Wl,--exclude-libs=libclangSerialization.a -Wl,--exclude-libs=libclangDriver.a -Wl,--exclude-libs=libclangParse.a -Wl,--exclude-libs=libcl
angSema.a -Wl,--exclude-libs=libclangCodeGen.a -Wl,--exclude-libs=libclangAnalysis.a -Wl,--exclude-libs=libclangRewrite.a -Wl,--exclude-libs=libclangEdit.a -Wl
,--exclude-libs=libclangAST.a -Wl,--exclude-libs=libclangLex.a -Wl,--exclude-libs=libclangBasic.a  -Wl,--exclude-libs=libLLVMBPFDisassembler.a -Wl,--exclude-li
bs=libLLVMBPFAsmParser.a -Wl,--exclude-libs=libLLVMCoroutines.a -Wl,--exclude-libs=libLLVMCoverage.a -Wl,--exclude-libs=libLLVMLTO.a -Wl,--exclude-libs=libLLVM
X86CodeGen.a -Wl,--exclude-libs=libLLVMX86Desc.a -Wl,--exclude-libs=libLLVMX86Info.a -Wl,--exclude-libs=libLLVMMCDisassembler.a -Wl,--exclude-libs=libLLVMX86AsmPrinter.a -Wl,--exclude-libs=libLLVMX86Utils.a -Wl,--exclude-libs=libLLVMGlobalISel.a -Wl,--exclude-libs=libLLVMPasses.a -Wl,--exclude-libs=libLLVMipo.a -Wl,--exclude-libs=libLLVMVectorize.a -Wl,--exclude-libs=libLLVMInstrumentation.a -Wl,--exclude-libs=libLLVMOption.a -Wl,--exclude-libs=libLLVMObjCARCOpts.a -Wl,--exclude-libs=libLLVMMCJIT.a -Wl,--exclude-libs=libLLVMExecutionEngine.a -Wl,--exclude-libs=libLLVMRuntimeDyld.a -Wl,--exclude-libs=libLLVMLinker.a -Wl,--exclude-libs=libLLVMIRReader.a -Wl,--exclude-libs=libLLVMAsmParser.a -Wl,--exclude-libs=libLLVMDebugInfoDWARF.a -Wl,--exclude-libs=libLLVMBPFCodeGen.a -Wl,--exclude-libs=libLLVMSelectionDAG.a -Wl,--exclude-libs=libLLVMBPFDesc.a -Wl,--exclude-libs=libLLVMBPFInfo.a -Wl,--exclude-libs=libLLVMBPFAsmPrinter.a -Wl,--exclude-libs=libLLVMAsmPrinter.a -Wl,--exclude-libs=libLLVMDebugInfoCodeView.a -Wl,--exclude-libs=libLLVMDebugInfoMSF.a -Wl,--exclude-libs=libLLVMCodeGen.a -Wl,--exclude-libs=libLLVMTarget.a -Wl,--exclude-libs=libLLVMScalarOpts.a -Wl,--exclude-libs=libLLVMInstCombine.a -Wl,--exclude-libs=libLLVMTransformUtils.a -Wl,--exclude-libs=libLLVMBitWriter.a -Wl,--exclude-libs=libLLVMAnalysis.a -Wl,--exclude-libs=libLLVMProfileData.a -Wl,--exclude-libs=libLLVMObject.a -Wl,--exclude-libs=libLLVMMCParser.a -Wl,--exclude-libs=libLLVMMC.a -Wl,--exclude-libs=libLLVMBitReader.a -Wl,--exclude-libs=libLLVMCore.a -Wl,--exclude-libs=libLLVMBinaryFormat.a -Wl,--exclude-libs=libLLVMSupport.a -Wl,--exclude-libs=libLLVMDemangle.a -shared -Wl,-soname,libbcc.so.0 -o libbcc.so.v0.5.0 CMakeFiles/bcc-shared.dir/link_all.cc.o CMakeFiles/bcc-shared.dir/bpf_common.cc.o CMakeFiles/bcc-shared.dir/bpf_module.cc.o CMakeFiles/bcc-shared.dir/exported_files.cc.o CMakeFiles/bcc-shared.dir/bcc_debug.cc.o CMakeFiles/bcc-shared.dir/table_storage.cc.o CMakeFiles/bcc-shared.dir/shared_table.cc.o CMakeFiles/bcc-shared.dir/bpffs_table.cc.o CMakeFiles/bcc-shared.dir/json_map_decl_visitor.cc.o CMakeFiles/bcc-shared.dir/bcc_syms.cc.o CMakeFiles/bcc-shared.dir/bcc_elf.c.o CMakeFiles/bcc-shared.dir/bcc_perf_map.c.o CMakeFiles/bcc-shared.dir/bcc_proc.c.o CMakeFiles/bcc-shared.dir/ns_guard.cc.o CMakeFiles/bcc-shared.dir/common.cc.o frontends/b/libb_frontend.a frontends/clang/libclang_frontend.a libbpf.a -Wl,--whole-archive -Wl,-Bstatic -lclangFrontend -lclangSerialization -lclangDriver -lclangParse -lclangSema -lclangCodeGen -lclangAnalysis -lclangRewrite -lclangEdit -lclangAST -lclangLex -lclangBasic /usr/lib64/libLLVMBPFDisassembler.a /usr/lib64/libLLVMBPFAsmParser.a /usr/lib64/libLLVMCoroutines.a /usr/lib64/libLLVMCoverage.a /usr/lib64/libLLVMLTO.a /usr/lib64/libLLVMX86CodeGen.a /usr/lib64/libLLVMX86Desc.a /usr/lib64/libLLVMX86Info.a /usr/lib64/libLLVMMCDisassembler.a /usr/lib64/libLLVMX86AsmPrinter.a /usr/lib64/libLLVMX86Utils.a /usr/lib64/libLLVMGlobalISel.a /usr/lib64/libLLVMPasses.a /usr/lib64/libLLVMipo.a /usr/lib64/libLLVMVectorize.a /usr/lib64/libLLVMInstrumentation.a /usr/lib64/libLLVMOption.a /usr/lib64/libLLVMObjCARCOpts.a /usr/lib64/libLLVMMCJIT.a /usr/lib64/libLLVMExecutionEngine.a /usr/lib64/libLLVMRuntimeDyld.a /usr/lib64/libLLVMLinker.a /usr/lib64/libLLVMIRReader.a /usr/lib64/libLLVMAsmParser.a /usr/lib64/libLLVMDebugInfoDWARF.a /usr/lib64/libLLVMBPFCodeGen.a /usr/lib64/libLLVMSelectionDAG.a /usr/lib64/libLLVMBPFDesc.a /usr/lib64/libLLVMBPFInfo.a /usr/lib64/libLLVMBPFAsmPrinter.a /usr/lib64/libLLVMAsmPrinter.a /usr/lib64/libLLVMDebugInfoCodeView.a /usr/lib64/libLLVMDebugInfoMSF.a /usr/lib64/libLLVMCodeGen.a /usr/lib64/libLLVMTarget.a /usr/lib64/libLLVMScalarOpts.a /usr/lib64/libLLVMInstCombine.a /usr/lib64/libLLVMTransformUtils.a /usr/lib64/libLLVMBitWriter.a /usr/lib64/libLLVMAnalysis.a /usr/lib64/libLLVMProfileData.a /usr/lib64/libLLVMObject.a /usr/lib64/libLLVMMCParser.a /usr/lib64/libLLVMMC.a /usr/lib64/libLLVMBitReader.a /usr/lib64/libLLVMCore.a /usr/lib64/libLLVMBinaryFormat.a /usr/lib64/libLLVMSupport.a /usr/lib64/libLLVMDemangle.a -Wl,-Bdynamic -Wl,--no-whole-archive -lelf -Wl,--whole-archive api/libapi-static.a -Wl,--no-whole-archive usdt/libusdt-static.a -lz -lrt -ldl -ltinfo -lpthread -lm
/usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64/libclangFrontend.a: member /usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64/libclangFrontend.a(ASTConsumers.cpp.o) in archive is not an object
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [src/cc/CMakeFiles/bcc-shared.dir/build.make:361: src/cc/libbcc.so.v0.5.0] Error 1

Очень быстрые библиотеки не собираются медленным ld.

2. При использовании ld.lld сборка обрывается на:

cd /usr/src/RPM/BUILD/bcc-v0.5.0/BUILD/src/lua && /usr/bin/cmake -E cmake_link_script CMakeFiles/bcc-lua.dir/link.txt --verbose=1
/usr/bin/clang -pipe -Wall -g -O2 -Wall -O2 -g -DNDEBUG  -fuse-ld=lld -rdynamic CMakeFiles/bcc-lua.dir/src/main.c.o bcc.o  -o bcc-lua -lluajit-5.1 -nopie
/usr/bin/ld.lld: error: bcc.o: string table non-null terminated
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)

Перезапуск с -v:

/usr/bin/clang -pipe -Wall -g -O2 -Wall -O2 -g -DNDEBUG  -fuse-ld=lld -rdynamic CMakeFiles/bcc-lua.dir/src/main.c.o bcc.o  -o bcc-lua -lluajit-5.1 -nopie -v
clang version 6.0.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/i586-alt-linux/7
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-alt-linux/7
Found candidate GCC installation: /usr/lib/gcc/i586-alt-linux/7
Found candidate GCC installation: /usr/lib64/gcc/x86_64-alt-linux/7
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-alt-linux/7
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/bin/ld.lld" -export-dynamic --eh-frame-hdr -m elf_x86_64 -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o bcc-lua /usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64/crt1.o /usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64/crti.o /usr/bin/../lib64/gcc/x86_64-alt-linux/7/crtbegin.o -L/usr/bin/../lib64/gcc/x86_64-alt-linux/7 -L/usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64 -L/usr/bin/../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../.. -L/usr/bin/../lib -L/lib -L/usr/lib CMakeFiles/bcc-lua.dir/src/main.c.o bcc.o -lluajit-5.1 -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib64/gcc/x86_64-alt-linux/7/crtend.o /usr/bin/../lib64/gcc/x86_64-alt-linux/7/../../../../lib64/crtn.o
/usr/bin/ld.lld: error: bcc.o: string table non-null terminated
clang-6.0: error: linker command failed with exit code 1 (use -v to see invocation)

builder@localhost:~/RPM/BUILD/bcc-v0.5.0/BUILD/src/lua$ llvm-objdump -s -section=.strtab bcc.o

bcc.o: file format ELF64-x86-64

Contents of section .strtab:
 0000 006c7561 4a49545f 42435f62 6363      .luaJIT_BC_bcc

Баг в luajit: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=223688
Comment 9 Vitaly Chikunov 2018-06-13 05:57:31 MSK
В итоге, lld не может собрать только один таргет: bcc-lua. Это я обошел без ld враппера, так:

export CC=clang
export CXX=clang++
export LDFLAGS=-fuse-ld=lld
%cmake \
        -DCMAKE_BUILD_TYPE=RelWithDebInfo \
        -DREVISION_LAST=%version \
        -DREVISION=%version \
        -DLLVM_DIR=$(llvm-config --cmakedir) \
        -DUSINGISYSTEM:BOOL=no \
        %{?lua_config}
subst s/-fuse-ld=lld/-fuse-ld=ld/ BUILD/src/lua/CMakeFiles/bcc-lua.dir/link.txt
%cmake_build