C Linux在ELF上迭代;第「;运行时的标题
简短版本: 可以在运行时检查所有ELF“section”头,并为每个加载的共享库获取每个“section”头的重新定位地址 长版本: 我试图在用户空间中实现与内核中存在的相同的动态调试机制(dyn_debug)。每个日志宏实例在程序的特定“部分”中创建静态变量的工作方式C Linux在ELF上迭代;第「;运行时的标题,c,linux,elf,C,Linux,Elf,简短版本: 可以在运行时检查所有ELF“section”头,并为每个加载的共享库获取每个“section”头的重新定位地址 长版本: 我试图在用户空间中实现与内核中存在的相同的动态调试机制(dyn_debug)。每个日志宏实例在程序的特定“部分”中创建静态变量的工作方式 \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 这迫使编译器将变量不放在“.data”节中,而是放在“\uu ver
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
这迫使编译器将变量不放在“.data”节中,而是放在“\uu verbose”节中。本节稍后的开始和停止地址可以通过变量访问
__开始详细,停止详细。通过这种方式,一些中心例程可以检查所有注册的“日志”条目,并根据需要更改属性。
这适用于静态链接的可执行文件,但在使用共享库时,有几个“\uuu verbose”部分(每个共享库一个)和可执行文件本身一个。(我使用-fPIC标志当然是为了被纳入图书馆)
此外,所有符号都与“-导出动态”链接,以确保导出所有符号
每个共享库和主可执行文件都有
属性(构造函数)初始化方法
我在两个病例中观察到两种不同的行为
案例1:对于第一个案例,库不是由ldopen加载的,而是由“libc加载程序”加载的
引用\uuuu start\uuuuu verbose始终返回相同的地址(主可执行文件的地址),其中仅存在“主”可执行文件日志记录项
dlsym(RTLD\u NEXT,\uuuu start\uuuu verbose)返回“NEXT”可解析库的符号地址,因此实际上我得到了所有地址
案例2:使用ldopen加载库
引用\uuuu start\uuuuu verbose始终返回相同的地址(主可执行文件的地址)
dlsym(RTLD\u NEXT,\uuuu start\uuuu verbose)返回NULL
dlsym(RTLD_默认值,_开始__详细)返回“主”进程表
dlsym(句柄,开始详细)-返回正确的节地址
问题:对于使用ldopen打开的库,除了4之外,还有什么方法可以获得该符号,因为4需要从“加载器”显式调用
代码:
您不应该在运行时访问节信息。节不应该在运行时使用,并且可能会从可执行文件中删除(剥离)
我可能会将自定义链接器脚本用于:
.__verbose:
{
PROVIDE_HIDDEN (__verbose_start = .);
*(.__verbose)
PROVIDE_HIDDEN (__verbose_end = .);
}
这将定义节的隐藏符号,以便每个ELF文件都有自己的符号版本
ELF文件中的构造函数(或某些其他代码)可以使用它们:
struct foo*;
extern struct foo* __verbose_start __attribute__((visibility("hidden")));
extern struct foo* __verbose_stop __attribute__((visibility("hidden")));
void __attribute__((constructor)) initializer()
{
initialize_logging(__verbose_start,__verbose_stop);
}
由于我没有\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu verbose
变量,您是否做了什么特别的工作。您不想在ELF文件的(高优先级)?否则,在执行构造函数的代码时将不会初始化它们。
struct foo*;
extern struct foo* __verbose_start __attribute__((visibility("hidden")));
extern struct foo* __verbose_stop __attribute__((visibility("hidden")));
void __attribute__((constructor)) initializer()
{
initialize_logging(__verbose_start,__verbose_stop);
}