【问题标题】:__attribute__((weak)) and LD_PRELOAD__attribute__((weak)) 和 LD_PRELOAD
【发布时间】:2013-04-12 08:53:03
【问题描述】:

我希望代码能够使用某个自写库而运行应用程序。所以我使用__attribute__ ((weak)) 并在需要时预加载库。我需要能够在不重新编译的情况下做到这一点。不过,如果我静态链接库,一切正常。

此外,该库是用 C++ 编写的,而使用它的应用程序可以是 C++ 或 C。

我归结为:

库头test_lib.h:

#ifdef __cplusplus
extern "C"
#endif
void test_func() __attribute__ ((weak));    

库实现test_lib.cpp:

#include "test_lib.h"
#include <iostream>
extern "C"
void test_func()
{
    std::cout << "in test_func\n";
}

C 测试test_main.c:

#include <stdio.h>
#include "test_lib.h"

int main(void)
{
    if (test_func){ printf("+\n"); }
    else{ printf("-\n"); }
    return 0;
}

C++ 测试test_main_cpp.cpp:

#include <iostream>
#include "test_lib.h"

int main(void)
{
    if (test_func){ std::cout << "+\n"; }
    else{ std::cout << "-\n"; }
    return 0;
}

为您提供方便的编译和运行脚本:

#!/bin/bash

g++ -shared -fPIC test_lib.cpp -o libtest.so

gcc test_main.c -o test_c
g++ test_main_cpp.cpp -o test_cpp

# output should be "-"
./test_c
./test_cpp

# output should be "+"
LD_PRELOAD=libtest.so ./test_c
LD_PRELOAD=libtest.so ./test_cpp

预期的输出是:

-
-
+
+

我得到的是:

-
-
-
-

最后还有一点额外的信息:

$ uname -a
Linux bermuda-iii 3.8.6-1-ARCH #1 SMP PREEMPT Sat Apr 6 07:27:01 CEST 2013 x86_64 GNU/Linux
$ gcc --version
gcc (GCC) 4.8.0
$ nm libtest.so | grep -i func
0000000000000858 W test_func
$ nm test_c | grep -i func
             w test_func
$ nm test_cpp | grep -i func
             w test_func

所以:(de)mangling 似乎工作正常,符号test_func 是可执行文件已知的。但是“LD_PRELOAD”似乎不起作用。

我错过了什么?

【问题讨论】:

    标签: c++ c shared-libraries


    【解决方案1】:

    诀窍是确保应用程序也被编译为与位置无关的代码,否则在运行时无法替换符号:

    在你链接可执行文件的地方,你需要做:

    gcc -fPIC test_main.c -o test_c
    

    g++ test_main_cpp.cpp -o test_cpp
    

    例如

    $ gcc test_main.c -o test_c -fPIC
    $ ./test_c
    -
    $ LD_PRELOAD=`pwd`/libtest_lib.so ./test_c
    +
    

    通过将主可执行文件编译为与位置无关的代码,它允许在运行时由覆盖库替换弱符号。

    【讨论】:

    • 弱引用定义不在主应用程序中,是吗?
    • 您没有正确编译二进制文件 - 它还需要使用 PIC - 我已经用应该工作的解决方案更新了答案
    • 是的,解决了。为了完整起见:在同事的 Mac 上,他必须摆脱 -fPIC alltogether 和 export LD_LIBRARY_PATH=.
    • mac 使用一个非常不同的链接和加载模型——它更喜欢使用weak_import 而不仅仅是weak
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2014-10-26
    • 2019-08-09
    • 2012-09-05
    • 1970-01-01
    • 2021-12-05
    相关资源
    最近更新 更多