2

Problem I've encountered

I've built shared libraries from the source of the project libunwind libunwind - github
I finally got libraries files installed in /usr/local/lib

/usr/local/lib/
├── ...
├── libunwind-x86_64.a
├── libunwind-x86_64.la
├── libunwind-x86_64.so -> libunwind-x86_64.so.8.0.1
├── libunwind-x86_64.so.8 -> libunwind-x86_64.so.8.0.1
├── libunwind-x86_64.so.8.0.1
├── libunwind.a
├── libunwind.la
├── libunwind.so -> libunwind.so.8.0.1
├── libunwind.so.8 -> libunwind.so.8.0.1
└── libunwind.so.8.0.1

When I tried compiling a simple test example linking with libunwind, I got error likes:

/usr/bin/ld: /tmp/ccVefxO3.o: in function `main':
test.c:(.text+0x4c): undefined reference to `_Ux86_64_getcontext'
/usr/bin/ld: test.c:(.text+0x65): undefined reference to `_ULx86_64_init_local'
/usr/bin/ld: test.c:(.text+0x8f): undefined reference to `_ULx86_64_get_reg'
/usr/bin/ld: test.c:(.text+0xa5): undefined reference to `_ULx86_64_step'
collect2: error: ld returned 1 exit status

The command I used to build the executable is:

gcc -DUNW_LOCAL_ONLY -L/usr/local/lib -lunwind test.c -o run -v

My gcc version is 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
My platform Ubuntu-20.04(In WSL2)-x86_64

Detailed Info

However, the symbols ld mentions definately exist in the /usr/local/lib/libunwind.so. I can find them when using readelf.

$ readelf -s /usr/local/lib/libunwind.so | grep "_Ux86_64_getcontext\|_ULx86_64_get_reg
\|_ULx86_64_init_local\|_ULx86_64_step"

The output shows on terminal:

    48: 0000000000004a80    14 FUNC    GLOBAL DEFAULT   11 _ULx86_64_init_local
    51: 0000000000004a90    46 FUNC    GLOBAL DEFAULT   11 _ULx86_64_init_local2
    70: 0000000000006530   113 FUNC    GLOBAL DEFAULT   11 _Ux86_64_getcontext
    71: 00000000000053e0  1336 FUNC    GLOBAL DEFAULT   11 _ULx86_64_step
    73: 0000000000003e80    26 FUNC    GLOBAL DEFAULT   11 _ULx86_64_get_reg
   146: 00000000000065a1    38 FUNC    LOCAL  DEFAULT   11 _Ux86_64_getcontext_trace
   205: 0000000000004a90    46 FUNC    GLOBAL DEFAULT   11 _ULx86_64_init_local2
   206: 0000000000006530   113 FUNC    GLOBAL DEFAULT   11 _Ux86_64_getcontext
   212: 00000000000053e0  1336 FUNC    GLOBAL DEFAULT   11 _ULx86_64_step
   226: 0000000000003e80    26 FUNC    GLOBAL DEFAULT   11 _ULx86_64_get_reg
   259: 0000000000004a80    14 FUNC    GLOBAL DEFAULT   11 _ULx86_64_init_local

So are there some kinds of mechanisms to mask some symbols in shared libraries while linking? Or I just did anything wrong.

gcc verbose infomation prints as followed:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --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-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --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-9-Av3uEd/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1) 
COLLECT_GCC_OPTIONS='-D' 'UNW_LOCAL_ONLY' '-L/usr/local/lib' '-o' 'run' '-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -quiet -v -imultiarch x86_64-linux-gnu -D UNW_LOCAL_ONLY test.c -quiet -dumpbase test.c -mtune=generic -march=x86-64 -auxbase test -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccdrxO64.s
GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
        compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP

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 "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/9/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C17 (Ubuntu 9.4.0-1ubuntu1~20.04.1) version 9.4.0 (x86_64-linux-gnu)
        compiled by GNU C version 9.4.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.22.1-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: c0c95c0b4209efec1c1892d5ff24030b
COLLECT_GCC_OPTIONS='-D' 'UNW_LOCAL_ONLY' '-L/usr/local/lib' '-o' 'run' '-v' '-mtune=generic' '-march=x86-64'
 as -v --64 -o /tmp/ccVefxO3.o /tmp/ccdrxO64.s
GNU assembler version 2.34 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.34
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-D' 'UNW_LOCAL_ONLY' '-L/usr/local/lib' '-o' 'run' '-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1hJ4C7.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o run /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/local/lib -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. -lunwind /tmp/ccVefxO3.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
/usr/bin/ld: /tmp/ccVefxO3.o: in function `main':
test.c:(.text+0x4c): undefined reference to `_Ux86_64_getcontext'
/usr/bin/ld: test.c:(.text+0x65): undefined reference to `_ULx86_64_init_local'
/usr/bin/ld: test.c:(.text+0x8f): undefined reference to `_ULx86_64_get_reg'
/usr/bin/ld: test.c:(.text+0xa5): undefined reference to `_ULx86_64_step'
collect2: error: ld returned 1 exit status

my test code written in test.c:

#include <libunwind.h>
#include <memory.h>

#define StackFrameDepthMax 100

int main()
{
    unsigned int depth = 0;
    unw_cursor_t    cursor;
    unw_context_t   context;
    unw_word_t pcArray[StackFrameDepthMax];
    memset((void*)pcArray, 0, sizeof(pcArray));

    unw_getcontext(&context);
    unw_init_local(&cursor, &context);

    while (unw_step(&cursor) > 0) 
    {
        unw_get_reg(&cursor, UNW_REG_IP, &pcArray[depth]);
        depth++;
    }
}
Xshell
  • 33
  • 2
  • 1
    Put libraries after object (source) files on the linking command line: `gcc -DUNW_LOCAL_ONLY test.c -L/usr/local/lib -lunwind -o run -v` – Jonathan Leffler Jul 28 '23 at 18:38
  • @Someprogrammerdude Thank you for your comment. You mean the command to build my test example? I've pasted it. Or you mean the command to build the `libunwind`? – Xshell Jul 28 '23 at 18:40
  • @JonathanLeffler I successfully build the executable following your suggestion... OK, It seems to be a moot question. Why is that? – Xshell Jul 28 '23 at 18:43
  • 1
    Oh I missed that you already posted that, sorry about that. And that makes the error clear: Libraries are searched when they are found on the command line. When the linker finds the `unwind` library, there are no dependencies for it or any of its functions, so it's discarded. It will simply not be considered again. You need to put libraries *after* the source or object files that depend on them. – Some programmer dude Jul 28 '23 at 18:44
  • @Someprogrammerdude Thanks bro! I never considered the seq of the options matters. – Xshell Jul 28 '23 at 18:51
  • The linker scans the arguments, from left to right. It's looking for symbols that are not defined but that can be satisfied by the current file — library or object. It always includes object files in the executable; it decides whether to include the library. When it scans `libunwind`, it is looking for `main` but doesn't find it; then it scans `test.o` and finds `main` and some other undefined symbols. But those symbols aren't in the libraries that come after it, so it reports that they're undefined and the link fails. "Object files before libraries" is a rule of thumb. It always works. – Jonathan Leffler Jul 28 '23 at 19:22
  • Order is important because the same name could be in multiple libraries or object files. – Barmar Jul 28 '23 at 19:22
  • See also the related (now duplicate) question [Why does the order in which libraries are linked sometimes cause errors in GCC?](https://stackoverflow.com/q/45135/) On some systems, you may get away with arbitrary sequencing of object files and libraries. In general, you won't. – Jonathan Leffler Jul 28 '23 at 19:23

0 Answers0