【问题标题】:Why is __attribute__((constructor)) in my shared library not working?为什么我的共享库中的 __attribute__((constructor)) 不起作用?
【发布时间】:2018-01-11 17:29:41
【问题描述】:

我在 ctor.c 中有这段代码:

#include<stdio.h>

static void __attribute__((constructor)) ctor() {
        printf("HAHA");
}

我编译它:

clang -o shared.so -fPIC ctor.c -shared

然后我运行:

LD_PRELOAD=shared.so echo Hallo

打印出来

Hallo

我期待看到:

HAHAHallo

为什么这不起作用?

关于二进制的一些信息:

> objdump -s -j .init_array shared.so

shared.so:     file format elf64-x86-64

Contents of section .init_array:
 200798 b0060000 00000000 e0060000 00000000  ................

> nm shared.so
00000000002007b8 d _DYNAMIC
00000000002009b0 d _GLOBAL_OFFSET_TABLE_
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000000790 r __FRAME_END__
00000000002007b0 d __JCR_END__
00000000002007b0 d __JCR_LIST__
00000000002009e8 d __TMC_END__
00000000002009e8 B __bss_start
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000000670 t __do_global_dtors_aux
00000000002007a8 t __do_global_dtors_aux_fini_array_entry
00000000002009e0 d __dso_handle
0000000000200798 t __frame_dummy_init_array_entry
                 w __gmon_start__
00000000002009e8 D _edata
00000000002009f0 B _end
0000000000000700 T _fini
0000000000000578 T _init
00000000002009e8 b completed.6661
00000000000006e0 t ctor
00000000000005e0 t deregister_tm_clones
00000000000006b0 t frame_dummy
                 U printf@@GLIBC_2.2.5
0000000000000620 t register_tm_clones

这表示:

(a) 存在 ctor 函数。它不会被链接器删除,对于一些有类似问题的人。

(b) .init_array 对我来说看起来不错。有两个条目(而不是一个),它们指向 frame_dummy 和 ctor。 (我用了这个答案:https://reverseengineering.stackexchange.com/a/12793

(c)shared library constructor not working通过一步编译和链接解决了这个问题,我已经在做

PS:当我用 gcc 编译时它也不起作用。

【问题讨论】:

标签: c linux clang shared-libraries


【解决方案1】:

有两个错误:

(a) LD_PRELOAD 需要一个绝对路径。

(b) "echo" 是 shell 内置的,因此不会启动任何二进制文件,因此不会预加载任何内容。使用我自己的“hello world”程序,它可以工作。

【讨论】:

    【解决方案2】:

    我在使用 c++ 构造函数时遇到了类似的问题

    struct Foo {
        Foo() {
            printf("foo");
        }
    } foo;
    

    这应该在调用 main() 之前打印“foo”,但它没有。但我的项目中有非常相似的东西,效果很好。

    我发现如果从外部调用的源文件中没有其他内容,则不会调用构造函数。

    尝试从外部调用一个虚拟函数。

    【讨论】:

    • 如果我使用带有主函数的第二个源文件并链接到可执行文件,它就可以工作。链接为共享库不起作用。
    • 我认为您的问题是链接器没有访问目标文件,因此如果文件中没有使用任何内容,则会错过构造函数。对我来说, nm 表明构造函数在二进制文件中。甚至 .init_array 似乎也被正确填充了。
    猜你喜欢
    • 2019-06-25
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多