c - 弱符号和弱引用

标签 c gcc linker

我正在尝试探索 gcc 的这些功能是如何工作的。

我创建了一个库,其中的函数应该调用 sigprocmaskpthread_sigmask,具体取决于 libpthread 是否链接。

我的弱引用版本的代码按预期工作,但我的基于弱符号的版本似乎没有像我期望的那样被真正的 pthread_sigmask 符号覆盖。

你能指出我做错了什么吗?

弱引用版本:

#!/bin/sh
cat > lib.c <<EOF
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>

__attribute__((weakref("pthread_sigmask")))
static int pthread_sigmask_ref(int How,  sigset_t const *Set, sigset_t *Oldset);

int call_pthread_sigmask(int How,  sigset_t const *Set, sigset_t *Oldset)
{
    puts("calling pthread_sigmask");
    if(pthread_sigmask_ref){
        return pthread_sigmask_ref(How, Set, Oldset);
    }else{
        puts("SIGPROCMASK");
        return sigprocmask(How, Set, Oldset);
    }
}
EOF

cat > main.c <<EOF
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>

int call_pthread_sigmask(int How,  sigset_t const *Set, sigset_t *Oldset);

int main()
{
    sigset_t all_sigs, old_mask;
    sigemptyset(&all_sigs);
    sigaddset(&all_sigs, SIGTERM);
    call_pthread_sigmask(SIG_SETMASK, &all_sigs, &old_mask);

#if 0
    pthread_mutex_t mx;
    pthread_mutex_init(&mx,0);
#endif
}

EOF

gcc -c -fpic lib.c
gcc lib.o -o lib.so -shared

gcc main.c $PWD/lib.so -lpthread -o wrap
gcc main.c $PWD/lib.so -Wl,--no-as-needed  -lpthread -o real

echo wrap
ldd ./wrap
./wrap

echo real
ldd ./real
./real

示例输出:

wrap
    linux-vdso.so.1 =>  (0x00007ffd5dda0000)
    /home/user/tmp/lib.so (0x00007faa4f8cf000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faa4f507000)
    /lib64/ld-linux-x86-64.so.2 (0x00007faa4fad1000)
calling pthread_sigmask
SIGPROCMASK
real
    linux-vdso.so.1 =>  (0x00007ffc7f51e000)
    /home/user/tmp/lib.so (0x00007f6ff23b2000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f6ff2194000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6ff1dcc000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6ff25b4000)
calling pthread_sigmask

弱符号版本:

#!/bin/sh
cat > lib.c <<EOF
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>

__attribute__((weak,noinline))
int pthread_sigmask(int How,  sigset_t const *Set, sigset_t *Oldset)
{
    puts("SIGPROCMASK");
    return sigprocmask(How, Set, Oldset);
}

int call_pthread_sigmask(int How,  sigset_t const *Set, sigset_t *Oldset)
{
    puts("calling pthread_sigmask");
    return pthread_sigmask(How, Set, Oldset);
}
EOF

cat > main.c <<EOF
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>

int call_pthread_sigmask(int How,  sigset_t const *Set, sigset_t *Oldset);

int main()
{
    sigset_t all_sigs, old_mask;
    sigemptyset(&all_sigs);
    sigaddset(&all_sigs, SIGTERM);
    call_pthread_sigmask(SIG_SETMASK, &all_sigs, &old_mask);

#if 0
    pthread_mutex_t mx;
    pthread_mutex_init(&mx,0);
#endif
}

EOF

gcc -c -fpic lib.c
gcc lib.o -o lib.so -shared

gcc main.c $PWD/lib.so -lpthread -o wrap
gcc main.c $PWD/lib.so -Wl,--no-as-needed  -lpthread -o real

echo wrap
ldd ./wrap
./wrap

echo real
ldd ./real
./real

示例输出:

wrap
    linux-vdso.so.1 =>  (0x00007ffd19d23000)
    /home/user/tmp/lib.so (0x00007fdd24b46000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdd2477e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fdd24d48000)
calling pthread_sigmask
SIGPROCMASK
real
    linux-vdso.so.1 =>  (0x00007fff115f6000)
    /home/user/tmp/lib.so (0x00007fb22be95000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb22bc77000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb22b8af000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fb22c097000)
calling pthread_sigmask
SIGPROCMASK

最佳答案

只需交换库顺序:

gcc main.c -lpthread $PWD/lib.so -o real

关于c - 弱符号和弱引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44373769/

相关文章:

javascript - 为 asm.js 编写优化的 JS

c - 如何在 GCC 上移植 __declspec(noalias)

c -/lib/libmatrix.a : file not recognized: File format not recognized collect2: ld returned 1 exit status

c++ - 链接 boost 内存映射文件

c++ - 如何将带有特殊字符的QString转换成字节流通过Linux管道发送

C - 字符串数组和函数

c - 段错误: 11 when trying to print linked list

c++ - 如何设置 CMAKE 静态链接(对 `dlopen' 的 undefined reference )?

c++ - mysql 连接器中对 mysqlx 函数的 undefined reference

c++ - Cmake:链接到静态内部库而不导出它