I have a very simple dummy program call main.c as below:
#include <stdlib.h>
#include <stdio.h>
#define TEST __atomic_compare_exchange
void test() {
__int128 unsigned a = 1, b = 2, c = 3;
__atomic_compare_exchange_16(&a, &b, c, 1, 1, 1);
printf("hello");
}
When compile using the following command, it works fine on my local Linux machine (Debian gcc version 6):
g++ --shared -o libmain.so -latomic main.c -Wl,--no-as-needed
However when using Microsoft hosted agent ubuntu-18.04, it fails regardless of whatever command I tried. Below is a list of commands that I have tried:
g++ --shared -o libmain.so -latomic main.c -Wl,--no-as-needed
g++ --shared -o libmain.so /usr/lib/x86_64-linux-gnu/libatomic.so.1 main.c -Wl,--no-as-needed
g++ --shared -o libmain.so -L/usr/lib/x86_64-linux-gnu/ -l:libatomic.so.1 main.c -Wl,--no-as-needed
When run ldd libmain.so
not libatomic is showed in the list:
linux-vdso.so.1 (0x00007ffc3c5b6000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f889324e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8892eb0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8892c98000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f88928a7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f889385d000)
When run readelf -W -s libatomic.so
, the __atomic_compare_exchange_16 shows as undefined without any suffix @...
indicating the libatomic libary to look for.
Symbol table '.dynsym' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2)
3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __atomic_compare_exchange_16
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3)
5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
7: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
8: 0000000000201038 0 NOTYPE GLOBAL DEFAULT 22 _edata
9: 0000000000201040 0 NOTYPE GLOBAL DEFAULT 23 _end
10: 000000000000070a 150 FUNC GLOBAL DEFAULT 12 _Z4testv
11: 00000000000005c0 0 FUNC GLOBAL DEFAULT 9 _init
12: 0000000000201038 0 NOTYPE GLOBAL DEFAULT 23 __bss_start
13: 00000000000007a0 0 FUNC GLOBAL DEFAULT 13 _fini
I have also check the g++ --print-search-dirs
and the libraries search dirs look all correct to me.
Is Microsoft Hosted Agent environment just different or am I missing any obvious linker option?
Update This is a fundamental concept to linker symbol search order that I have missed. Usually, linker searches for symbols from left to right, but for some modern linkers, all libraries are searched regardless of order. I have tested this on one my other ubuntu VM and changing the order does work as expected.
Will update once I have tested with the Microsoft hosted user-agent.
Update 2 I can confirm that it is the difference between gcc linker in Ubuntu and my local machine Debian.
To answer my own question.
The difference that I found is that on the Ubuntu machine, the gcc linker appear to search symbols in left to right order. Thus placing '-latomic' before the source file cause the reference to not be found and the library is not linked.
On my local Debian machine, the linker search in both directions so the library is linked regardless of location of the '-l' option in the command.