AcademySoftwareFoundation / OpenColorIO

A color management framework for visual effects and animation.
https://opencolorio.org
BSD 3-Clause "New" or "Revised" License
1.79k stars 455 forks source link

ocioarchive.dir/main.cpp.o: relocation R_X86_64_32 against `.bss' can not be used when making a PIE object #1857

Open hobbes1069 opened 1 year ago

hobbes1069 commented 1 year ago

New compile error on Fedora with 2.3.0:

/usr/bin/ld: CMakeFiles/ocioarchive.dir/main.cpp.o: relocation R_X86_64_32 against `.bss' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status

Full log here: https://kojipkgs.fedoraproject.org//work/tasks/2223/106302223/build.log

KevinJW commented 1 year ago

From the logs the objects are compiled like this:

/usr/bin/g++ -DOCIO_GPU_ENABLED -DOCIO_HEADLESS_ENABLED -I/builddir/build/BUILD/OpenColorIO-2.3.0/src/libutils/oglapphelpers -I/builddir/build/BUILD/OpenColorIO-2.3.0/src/apputils/.. -I/builddir/build/BUILD/OpenColorIO-2.3.0/include/OpenColorIO/.. -I/builddir/build/BUILD/OpenColorIO-2.3.0/include/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/include/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/src/OpenColorIO -w -msse2 -DNDEBUG -std=c++14 -fvisibility=hidden -fvisibility-inlines-hidden -DUSE_GCC -Wall -Wextra -Wswitch-enum -MD -MT src/apps/ociochecklut/CMakeFiles/ociochecklut.dir/main.cpp.o -MF CMakeFiles/ociochecklut.dir/main.cpp.o.d -o CMakeFiles/ociochecklut.dir/main.cpp.o -c /builddir/build/BUILD/OpenColorIO-2.3.0/src/apps/ociochecklut/main.cpp

Then linked with

/usr/bin/cmake -E cmake_link_script CMakeFiles/ociochecklut.dir/link.txt --verbose=1
/usr/bin/g++ -w -msse2 -DNDEBUG -Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes CMakeFiles/ociochecklut.dir/main.cpp.o -o ociochecklut  -Wl,-rpath,/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/src/OpenColorIO: ../../libutils/oglapphelpers/libOpenColorIOoglapphelpers.a ../../apputils/libapputils.a ../../OpenColorIO/libOpenColorIO.so.2.3.0 /usr/lib64/libGLU.so /usr/lib64/libGLX.so /usr/lib64/libGLEW.so /usr/lib64/libglut.so /usr/lib64/libXmu.so /usr/lib64/libXi.so /usr/lib64/libEGL.so /usr/lib64/libOpenGL.so /usr/lib64/libpystring.so 
/usr/bin/ld: CMakeFiles/ociochecklut.dir/main.cpp.o: relocation R_X86_64_32 against `.rodata' can not be used when making a PIE object; recompile with -fPIE
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status

So at first glance there is nothing asking for PIE as called by our CMake ... Which version of Fedora are you building for I know some older versions had bugs related to building of static objects and then linking with PIE. So there could be an interaction with the hardened linker specs wanting to use PIE but the matching requirement is not set in the gcc config - I would have thought this is unlikely but possible.

https://fedoraproject.org/wiki/Changes/Harden_All_Packages

I'm led to believe fedora uses flag injection on the command line rather than building the compiler and linker with matching defaults based on some clang forum posts (don't you just love the Internet for sources of Truth)

The other option could be which version of cmake are you using as that can effect behaviour we require 3.13 which is just the wrong side of https://cmake.org/cmake/help/latest/policy/CMP0083.html#policy:CMP0083 which could be why the behaviour is triggering.

KevinJW commented 1 year ago

Assuming your CMake version is actually newer, you could perhaps try update the cmake_minimum_version() to 3.15 in the top level CMakeLists.txt and If I'm reading the CMake docs right add:

cmake_policy(SET CMP0083 NEW)
include(CheckPIESupported)
check_pie_supported()

I (We) picked 3.15 as that aligns with OIIO as well as the ASWF sample template. Now it is possible we will need to be much more granular with things to make the actual executable targets correct on Fedora, but That would be my first steps, if I had a Fedora build host to try it on.

hobbes1069 commented 1 year ago

Shame on me for not specifying but in general unless otherwise specified I'm talking about Fedora Rawhide (rolling devel branch). Cmake version is 3.27.4.

I can still compile 2.2.1 without issue.

KevinJW commented 1 year ago

So I tried building in a fedora docker container and building it as-is without the rpm build environment I don't get the problem, so I guess it has something to do with that.

Approximate Dockerfile

FROM fedora:latest

RUN dnf -y update  && dnf -y install scl-utils sudo && \
    dnf -y groupinstall "C Development Tools and Libraries" && \
    dnf -y groupinstall "Development Libraries"  && \
    dnf -y groupinstall "Development Tools" && \
    dnf clean all

RUN dnf -y install cmake OpenImageIO-devel OpenEXR-devel pybind11-devel lcms2-devel \
        expat-devel yaml-cpp-devel pystring-devel minizip-ng-devel \
        python3-sphynx python3-testresources python3-recommonmark \
        python3-sphinx-press-theme python3-sphinx-tabs python3-breathe && \
    dnf clean all

Next step would be to try build with the fedora rpmbuild setup and or the CFLAGS etc

KevinJW commented 1 year ago

So by setting the environment variables for the compiler and linker flags outside of cmake I was able to recreate the error. After attempting to fix it with my suggestions, they do not work for this issue.

The reason is that my suggestions are nominally correct for when a project internally wants to generate PIE/PIC objects, however in this case, as the linker/compiler flags are being modified outside the knowledge of CMake, our project files do not "know" to compile the executable object files with the appropriate flags.

So the question is what to do, long term we could look to add an option for distributions to choose to add the appropriate target properties to our executables (or choose to build them with position independence for all platforms), then my fixes might be the right suggestion, to ensure the linker gets passed the appropriate flags

In the short term you can brute force the build to generate PIC code for all targets by adding -DCMAKE_POSITION_INDEPENDENT_CODE=ON to the cmake configuration in your build step and I think that will allow the build to complete successfully - it resolves it under my hacky reproduction at least and requires no source file patching..

Note that this will force PIC flags for all objects which isn't quite the same as using PIE for the executable objects, which may add additional overhead vs using the PIE flags, but I assume Fedora is wanting to prioritise the potential security benefits over any performance loss of allowing relocatable executables.

This should have no impact on the code in the shared library as by definition they already needed/are compiled as PIC.

hobbes1069 commented 1 year ago

Indeed, much of the flags being set are for security/hardening along with things like link time optimization.

Not sure if this helps but here's the %cmake macro used in rpmbuild:

$ rpm -E "%cmake"

  CFLAGS="${CFLAGS:--O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer }" ; export CFLAGS ; 
  CXXFLAGS="${CXXFLAGS:--O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer }" ; export CXXFLAGS ; 
  FFLAGS="${FFLAGS:--O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules }" ; export FFLAGS ; 
  FCFLAGS="${FCFLAGS:--O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -I/usr/lib64/gfortran/modules }" ; export FCFLAGS ; 
  VALAFLAGS="${VALAFLAGS:--g}" ; export VALAFLAGS ; 
  LDFLAGS="${LDFLAGS:--Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -Wl,--build-id=sha1  }" ; export LDFLAGS ; 
  LT_SYS_LIBRARY_PATH="${LT_SYS_LIBRARY_PATH:-/usr/lib64:}" ; export LT_SYS_LIBRARY_PATH ; 
  CC="${CC:-gcc}" ; export CC ; 
  CXX="${CXX:-g++}" ; export CXX 
  /usr/bin/cmake \
        -S "." \
        -B "redhat-linux-build" \
        -DCMAKE_C_FLAGS_RELEASE:STRING="-DNDEBUG" \
        -DCMAKE_CXX_FLAGS_RELEASE:STRING="-DNDEBUG" \
        -DCMAKE_Fortran_FLAGS_RELEASE:STRING="-DNDEBUG" \
        -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
        -DCMAKE_INSTALL_DO_STRIP:BOOL=OFF \
        -DCMAKE_INSTALL_PREFIX:PATH=/usr \
        -DINCLUDE_INSTALL_DIR:PATH=/usr/include \
        -DLIB_INSTALL_DIR:PATH=/usr/lib64 \
        -DSYSCONF_INSTALL_DIR:PATH=/etc \
        -DSHARE_INSTALL_PREFIX:PATH=/usr/share \
%if "lib64" == "lib64" 
        -DLIB_SUFFIX=64 \
%endif 
        -DBUILD_SHARED_LIBS:BOOL=ON
cat /usr/lib/rpm/redhat/redhat-hardened-cc1 
*cc1_options:
+ %{!r:%{!fpie:%{!fPIE:%{!fpic:%{!fPIC:%{!fno-pic:-fPIE}}}}}}

$ cat /usr/lib/rpm/redhat/redhat-hardened-ld
*self_spec:
+ %{!static:%{!shared:%{!r:-pie}}}

Don't ask me to unwind the logic here :)

KevinJW commented 1 year ago

Sure, I'm suggesting you need to add -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON at the the end of your cmake for the OpenColorIO build , however that is constructed, presumably in some rpm spec file.

Alternately you could try get the logic in the cc1 hardening option changed to add the pie option correctly, but that would have far greater consequences to the whole OS build, definitely not for OCIO to wag that dog.

I believe other distros solve this by building the compiler with pie by default for all code generation, rather than doing the option mangling

hobbes1069 commented 1 year ago

I tried that and got a strange result I've never seen before:

+ /usr/bin/find-debuginfo -j16 --strict-build-id -m -i --build-id-seed 2.3.0-1.fc40 --unique-debug-suffix -2.3.0-1.fc40.x86_64 --unique-debug-src-base OpenColorIO-2.3.0-1.fc40.x86_64 --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 -S debugsourcefiles.list /builddir/build/BUILD/OpenColorIO-2.3.0
find-debuginfo: starting
Extracting debug info from 1 files
Error while writing index for `/builddir/build/BUILDROOT/OpenColorIO-2.3.0-1.fc40.x86_64/usr/lib64/libOpenColorIO.so.2.3.0': No debugging symbols
gdb-add-index: No index was created for /builddir/build/BUILDROOT/OpenColorIO-2.3.0-1.fc40.x86_64/usr/lib64/libOpenColorIO.so.2.3.0
gdb-add-index: [Was there no debuginfo? Was there already an index?]
DWARF-compressing 1 files
sepdebugcrcfix: Updated 0 CRC32s, 1 CRC32s did match.
Creating .debug symlinks for symlinks to ELF files
find-debuginfo: done

Apparently the debug symbols can't be found now?

KevinJW commented 1 year ago

and the CMAKE_BUILD_TYPE is set to RelWithDebInfo ?

Apologies, but I'm just not familiar with Fedora's build setup to replicate it.

hobbes1069 commented 1 year ago

Success! I haven't had to set that option in ages as the inserted Fedora flags usually take care of it.

hobbes1069 commented 1 year ago

For some reason only i686 failed:

[  8%] Building CXX object src/OpenColorIO/CMakeFiles/OpenColorIO.dir/CPUInfo.cpp.o
cd /builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/src/OpenColorIO && /usr/bin/g++ -DOCIO_HEADLESS_ENABLED -DOpenColorIO_EXPORTS -I/builddir/build/BUILD/OpenColorIO-2.3.0/include/OpenColorIO/.. -I/builddir/build/BUILD/OpenColorIO-2.3.0/include/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/include/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/src/OpenColorIO -I/builddir/build/BUILD/OpenColorIO-2.3.0/redhat-linux-build/generated_include -isystem /usr/include/Imath -isystem /builddir/build/BUILD/OpenColorIO-2.3.0/ext/sampleicc/src/include -isystem /builddir/build/BUILD/OpenColorIO-2.3.0/src/utils/.. -isystem /builddir/build/BUILD/OpenColorIO-2.3.0/ext/xxHash/src/include -isystem /usr/include/minizip -w -msse2 -O2 -g -DNDEBUG -std=c++14 -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -DUSE_GCC -Wall -Wextra -Wswitch-enum -MD -MT src/OpenColorIO/CMakeFiles/OpenColorIO.dir/CPUInfo.cpp.o -MF CMakeFiles/OpenColorIO.dir/CPUInfo.cpp.o.d -o CMakeFiles/OpenColorIO.dir/CPUInfo.cpp.o -c /builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp: Assembler messages:
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:54: Error: bad register name `%rbx'
/builddir/build/BUILD/OpenColorIO-2.3.0/src/OpenColorIO/CPUInfo.cpp:56: Error: bad register name `%rbx'

I don't technically have to build for i686 at this point but wanted to check if this is easily fixable first.

KevinJW commented 1 year ago

Well the use of rbx should be for 64 bit platform, that suggests maybe the line https://github.com/AcademySoftwareFoundation/OpenColorIO/blob/87126fad7f27a703850e098a9a75e0ef206b3da9/CMakeLists.txt#L185 is wrong or something.

Can you see what value that had in your cmake cache? I suspect this maybe something to do with cross compiling... https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_PROCESSOR.html

does you build system pass in a tool chain file to set that value when building for i686 ?

remia commented 1 year ago

Looks like the issue that was fixed in https://github.com/AcademySoftwareFoundation/OpenColorIO/pull/1842 ?

KevinJW commented 1 year ago

Ah yes, didn't check to see the difference between the HEAD and the 2.3.0 version tag

hobbes1069 commented 1 year ago

I used the pull request as a patch and that fixed it.

Thanks!