linuxgcccompilationx86-64relocation

GCC Output Symbol not Relocatable with -fPIC


On an Ubuntu 24.04, using the default GCC-13.2 compiler I compiled a source file with -fPIC option to produce relocatable binary:

/usr/bin/c++ -v -DBPFTIME_BUILD_WITH_LIBBPF=1 -DSPDLOG_COMPILED_LIB
-Dbpftime_text_segment_transformer_EXPORTS
-I/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
-I/home/ahmad/Programs/bpftime/third_party/spdlog/include
-fno-omit-frame-pointer -O3 -DNDEBUG -std=gnu++20 -fPIC -o
text_segment_transformer.cpp.o -c
/home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp

The compiler output is as follows:

Using built-in specs.
COLLECT_GCC=/usr/bin/c++
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
13.2.0-23ubuntu4'
--with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs
--enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2
--prefix=/usr --with-gcc-major-version-only --program-suffix=-13
--program-prefix=x86_64-linux-gnu- --enable-shared
--enable-linker-build-id --libexecdir=/usr/libexec
--without-included-gettext --enable-threads=posix --libdir=/usr/lib
--enable-nls --enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new
--enable-libstdcxx-backtrace --enable-gnu-unique-object
--disable-vtable-verify --enable-plugin --enable-default-pie
--with-system-zlib --enable-libphobos-checking=release
--with-target-system-zlib=auto --enable-objc-gc=auto
--enable-multiarch --disable-werror --enable-cet --with-arch-32=i686
--with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib
--with-tune=generic
--enable-offload-targets=nvptx-none=/build/gcc-13-uJ7kn6/gcc-13-13.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-13-uJ7kn6/gcc-13-13.2.0/debian/tmp-gcn/usr
--enable-offload-defaulted --without-cuda-driver
--enable-checking=release --build=x86_64-linux-gnu
--host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.2.0 (Ubuntu 13.2.0-23ubuntu4)
COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 /usr/libexec/gcc/x86_64-linux-gnu/13/cc1plus -quiet -v -I
/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
-I /home/ahmad/Programs/bpftime/third_party/spdlog/include -imultiarch
x86_64-linux-gnu -D_GNU_SOURCE -D BPFTIME_BUILD_WITH_LIBBPF=1 -D
SPDLOG_COMPILED_LIB -D bpftime_text_segment_transformer_EXPORTS -D
NDEBUG /home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp
-D_FORTIFY_SOURCE=3 -quiet -dumpbase text_segment_transformer.cpp.cpp
-dumpbase-ext .cpp -mtune=generic -march=x86-64 -O3 -std=gnu++20
-version -fno-omit-frame-pointer -fPIC -fasynchronous-unwind-tables
-fstack-protector-strong -Wformat -Wformat-security
-fstack-clash-protection -fcf-protection -o /tmp/ccrIb4z5.s
GNU C++20 (Ubuntu 13.2.0-23ubuntu4) version 13.2.0 (x86_64-linux-gnu)
        compiled by GNU C version 13.2.0, GMP version 6.3.0, MPFR
version 4.2.1, MPC version 1.3.1, isl version isl-0.26-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/13"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"
ignoring nonexistent directory
"/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
 /home/ahmad/Programs/bpftime/third_party/spdlog/include
 /usr/include/c++/13
 /usr/include/x86_64-linux-gnu/c++/13
 /usr/include/c++/13/backward
 /usr/lib/gcc/x86_64-linux-gnu/13/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
Compiler executable checksum: 4e0f319cd9945d8f5a9eeeeec1481ba5
In file included from /usr/include/c++/13/string:51,
                 from /usr/include/c++/13/bits/locale_classes.h:40,
                 from /usr/include/c++/13/bits/ios_base.h:41,
                 from /usr/include/c++/13/ios:44,
                 from /usr/include/c++/13/istream:40,
                 from /usr/include/c++/13/sstream:40,
                 from /usr/include/c++/13/chrono:45,
                 from /home/ahmad/Programs/bpftime/third_party/spdlog/include/spdlog/common.h:10,
                 from /home/ahmad/Programs/bpftime/third_party/spdlog/include/spdlog/spdlog.h:12,
                 from /home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp:1:
In static member function ‘static constexpr _Up*
std::__copy_move<_IsMove, true,
std::random_access_iterator_tag>::__copy_m(_Tp*, _Tp*, _Up*) [with _Tp
= unsigned char; _Up = unsigned char; bool _IsMove = false]’,
        inlined from ‘constexpr _OI std::__copy_move_a2(_II, _II, _OI)
[with bool _IsMove = false; _II = unsigned char*; _OI = unsigned
char*]’ at /usr/include/c++/13/bits/stl_algobase.h:506:30,
    inlined from ‘constexpr _OI std::__copy_move_a1(_II, _II, _OI)
[with bool _IsMove = false; _II = unsigned char*; _OI = unsigned
char*]’ at /usr/include/c++/13/bits/stl_algobase.h:533:42,
    inlined from ‘constexpr _OI std::__copy_move_a(_II, _II, _OI)
[with bool _IsMove = false; _II =
__gnu_cxx::__normal_iterator<unsigned char*, vector<unsigned char> >;
_OI = unsigned char*]’ at
/usr/include/c++/13/bits/stl_algobase.h:540:31,
    inlined from ‘constexpr _OI std::copy(_II, _II, _OI) [with _II =
__gnu_cxx::__normal_iterator<unsigned char*, vector<unsigned char> >;
_OI = unsigned char*]’ at
/usr/include/c++/13/bits/stl_algobase.h:633:7,
    inlined from ‘void bpftime::setup_syscall_tracer()’ at
/home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp:235:11:
/usr/include/c++/13/bits/stl_algobase.h:437:30: warning: ‘void*
__builtin_memmove(void*, const void*, long unsigned int)’ writing
between 2 and 9223372036854775807 bytes into a region of size 0
overflows the destination [-Wstringop-overflow=]
  437 |             __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
      |             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘void bpftime::setup_syscall_tracer()’:
cc1plus: note: destination object is likely at address zero
COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 as -v -I /home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
-I /home/ahmad/Programs/bpftime/third_party/spdlog/include --64 -o
text_segment_transformer.cpp.o /tmp/ccrIb4z5.s
GNU assembler version 2.42 (x86_64-linux-gnu) using BFD version (GNU
Binutils for Ubuntu) 2.42
COMPILER_PATH=/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/13/:/usr/libexec/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/13/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/13/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64' '-dumpdir'
'text_segment_transformer.cpp.'

The symbol syscall_hooker_cxx has relocation type R_X86_64_PLT32.

The same command On an Ubuntu 18.04 using a manually built GCC-13.2 compiler causes the following output:

Using built-in specs.
COLLECT_GCC=/usr/bin/c++
Target: x86_64-linux-gnu
Configured with: ../configure --prefix=/opt/gcc-13.2.0
--disable-multilib --enable-shared --enable-linker-build-id
--without-included-gettext --enable-threads=posix --enable-nls
--enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new
--enable-libstdcxx-backtrace --enable-gnu-unique-object
--disable-vtable-verify --enable-plugin --enable-default-pie
--with-system-zlib --enable-libphobos-checking=release
--with-target-system-zlib=auto --enable-objc-gc=auto --disable-werror
--enable-cet --with-arch-32=i686 --with-abi=m64 --with-tune=generic
--without-cuda-driver --enable-checking=release
--build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (GCC)

COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 /opt/gcc-13.2.0/libexec/gcc/x86_64-linux-gnu/13.2.0/cc1plus -quiet -v
-I /home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
-I /home/ahmad/Programs/bpftime/third_party/spdlog/include -imultiarch
x86_64-linux-gnu -D_GNU_SOURCE -D BPFTIME_BUILD_WITH_LIBBPF=1 -D
SPDLOG_COMPILED_LIB -D bpftime_text_segment_transformer_EXPORTS -D
NDEBUG /home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp
-quiet -dumpbase text_segment_transformer.cpp.cpp -dumpbase-ext .cpp
-mtune=generic -march=x86-64 -O3 -std=gnu++20 -version
-fno-omit-frame-pointer -fPIC -o /tmp/ccIXuruA.s
GNU C++20 (GCC) version 13.2.0 (x86_64-linux-gnu)
    compiled by GNU C version 13.2.0, GMP version 6.3.0, MPFR version
4.2.1, MPC version 1.3.1, isl version none
warning: GMP header version 6.3.0 differs from library version 6.1.2.
warning: MPFR header version 4.2.1 differs from library version 4.0.1.
warning: MPC header version 1.3.1 differs from library version 1.1.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory
"/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
 /home/ahmad/Programs/bpftime/third_party/spdlog/include
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/x86_64-linux-gnu
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../include/c++/13.2.0/backward
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include
 /usr/local/include
 /opt/gcc-13.2.0/include
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include-fixed/x86_64-linux-gnu
 /opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
Compiler executable checksum: 57ec4216d92497ddefc5d01c6cd03e37
In file included from /opt/gcc-13.2.0/include/c++/13.2.0/string:51,

                 from
/opt/gcc-13.2.0/include/c++/13.2.0/bits/locale_classes.h:40,
                 from /opt/gcc-13.2.0/include/c++/13.2.0/bits/ios_base.h:41,
                 from /opt/gcc-13.2.0/include/c++/13.2.0/ios:44,
                 from /opt/gcc-13.2.0/include/c++/13.2.0/istream:40,
                 from /opt/gcc-13.2.0/include/c++/13.2.0/sstream:40,
                 from /opt/gcc-13.2.0/include/c++/13.2.0/chrono:45,
                 from
/home/ahmad/Programs/bpftime/third_party/spdlog/include/spdlog/common.h:10,
                 from
/home/ahmad/Programs/bpftime/third_party/spdlog/include/spdlog/spdlog.h:12,
                 from
/home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp:1:
In static member function ‘static constexpr _Up*
std::__copy_move<_IsMove, true,
std::random_access_iterator_tag>::__copy_m(_Tp*, _Tp*, _Up*) [with _Tp
= unsigned char; _Up = unsigned char; bool _IsMove = false]’,
    inlined from ‘constexpr _OI std::__copy_move_a2(_II, _II, _OI)
[with bool _IsMove = false; _II = unsigned char*; _OI = unsigned
char*]’ at /opt/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:506:30,
     inlined from ‘constexpr _OI std::__copy_move_a1(_II, _II, _OI)
[with bool _IsMove = false; _II = unsigned char*; _OI = unsigned
char*]’ at /opt/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:533:42,
    inlined from ‘constexpr _OI std::__copy_move_a(_II, _II, _OI)
[with bool _IsMove = false; _II =
__gnu_cxx::__normal_iterator<unsigned char*, vector<unsigned char> >;
_OI = unsigned char*]’ at
/opt/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:540:31,
    inlined from ‘constexpr _OI std::copy(_II, _II, _OI) [with _II =
__gnu_cxx::__normal_iterator<unsigned char*, vector<unsigned char> >;
_OI = unsigned char*]’ at
/opt/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:633:7,
    inlined from ‘void bpftime::setup_syscall_tracer()’ at
/home/ahmad/Programs/bpftime/attach/text_segment_transformer/text_segment_transformer.cpp:235:11:
/opt/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:437:30:
warning: ‘void* __builtin_memmove(void*, const void*, long unsigned
int)’ writing between 2 and 9223372036854775807 bytes into a region of
size 0 overflows the destination [-Wstringop-overflow=]
  437 |             __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
      |             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘void bpftime::setup_syscall_tracer()’:
cc1plus: note: destination object is likely at address zero
COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64'
 as -v -I /home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum
-I /home/ahmad/Programs/bpftime/third_party/spdlog/include --64 -o
text_segment_transformer.cpp.o /tmp/ccIXuruA.s
GNU assembler version 2.30 (x86_64-linux-gnu) using BFD version (GNU
Binutils for Ubuntu) 2.30
COMPILER_PATH=/opt/gcc-13.2.0/libexec/gcc/x86_64-linux-gnu/13.2.0/:/opt/gcc-13.2.0/libexec/gcc/x86_64-linux-gnu/13.2.0/:/opt/gcc-13.2.0/libexec/gcc/x86_64-linux-gnu/:/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/:/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/:/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/opt/gcc-13.2.0/lib/gcc/x86_64-linux-gnu/13.2.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-D' 'BPFTIME_BUILD_WITH_LIBBPF=1' '-D'
'SPDLOG_COMPILED_LIB' '-D' 'bpftime_text_segment_transformer_EXPORTS'
'-I' '/home/ahmad/Programs/bpftime/build/build/FridaGum-prefix/src/FridaGum'
'-I' '/home/ahmad/Programs/bpftime/third_party/spdlog/include'
'-fno-omit-frame-pointer' '-O3' '-D' 'NDEBUG' '-std=gnu++20' '-fPIC'
'-o' 'text_segment_transformer.cpp.o' '-c' '-shared-libgcc'
'-mtune=generic' '-march=x86-64' '-dumpdir'
'text_segment_transformer.cpp.'

But this time the relocation type for syscall_hooker_cxx is R_X86_64_PC32. What could be the cause of this inconsistency? Is the latter GCC configured incorrectly (Also, the default GLIBC version used by the former GCC is 2.39 while for the latter is 2.27)? Any hint is appreciated.


UPDATE:

Even the default GCC in Ubuntu-18.04 (GCC 7.5.0with the -std=gnu++20 option removed) produces an unrelocatable symbol (i.e., R_X86_64_PC32)! So an incorrect configuration seems unlikely.


UPDATE2:

I generated the assembly files. The relevant portion of the code (attach/text_segment_transformer.cpp:83) is as follows:

"call syscall_hooker_cxx\n\t"

It has the same disassembly in both scenarios (Ubuntu-18.04 and Ubuntu-24.04):

call syscall_hooker_cxx

But as mentioned above, the final relocations have different types. Therefore, the assemblers seem to operate differently. Why does this happen?

NOTE THAT, clang uses callq which results in relocatable symbols in both scenarios (although it seems to be call internally if I use -masm=intel option, Link: What is callq instruction?):

callq   syscall_hooker_cxx

P.S.: The question is also asked here.


Solution

  • As Xellos mentioned in the comments the problem is in the inline assembly which is not written in a relocatable manner. As LIU Hao mentioned here, changing call syscall_hooker_cxx (at attach/text_segment_transformer.cpp:83) to syscall_hooker_cxx@PLT resolves the issue.