简洁版本:
可以在运行时遍历所有ELF“节” header ,并为每个已加载的共享库获取每个“节” header 的重定位地址。
长版:
我正在尝试实现与内核(dyn_debug)中存在的动态调试相同的机制。每个LOG宏实例在程序中特定“节”中创建静态变量的工作方式__attribute__((section("__verbose")))
这将强制编译器将变量不放置在“.data”部分中,而应放置在“__verbose”部分中。可以通过变量访问本节的稍后开始和结束地址
__start ___ verbose,__ stop___verbose。这样,某些中央例程可以遍历所有已注册的“日志”条目并按需更改属性。
可以找到静态链接的可执行文件,但是使用共享库时,有几个“__verbose”部分(每个共享库一个),而可执行文件本身就有一个。 (我当然使用-fPIC标志以便包含在库中)
另外,所有与“-export-dynamic”链接的内容都可以确保导出所有符号。
每个共享库和主要可执行文件都有
属性init的(构造函数)方法。
我在2个案例中观察到两种不同的行为。
情况1:对于第一种情况,库不是使用ldopen而是通过“libc loader”加载的
引用__start___verbose的
情况2:使用ldopen加载库
引用__start___verbose的
问题:用ldopen打开的库是否有任何方法可以获取该符号,除了4以外,因为4需要从“loader”显式调用
码:
/* Main" */
void func1()
{
static int attribute__((section("__verbose"))) var = 1;
}
/* Shared library */
void func2()
{
static int attribute__((section("__verbose"))) var = 2;
}
/* Both in main and shared library
* Prints same address !!! BAD !! */
void __attribute__((constructor)) initializer()
{
struct int *iter;
for (iter = __start___verbose; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Works for libraries opened by libc runtime.
* Does not work for libraries opened with LDOPEN*/
void __attribute__((constructor)) initializer()
{
struct int *iter = ;
for (iter = dlsym(RTLD_NEXT, "__start___verbose"); iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
}
/* Snippet for main doing dynamic loading */
handle = ldopen('path', RTLD_NOW)
iter = dlsym(handle, "__start___verbose")
for (; iter != __stop___verbose; ++iter) {
printf("Value is %d", *iter)
}
最佳答案
您不应在运行时访问节信息。不应在运行时使用节,并且应将其从可执行文件中删除(剥离)。
我可能将自定义链接描述文件用于:
.__verbose:
{
PROVIDE_HIDDEN (__verbose_start = .);
*(.__verbose)
PROVIDE_HIDDEN (__verbose_end = .);
}
这为该部分定义了HIDDEN符号,因此每个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);
}
关于c - Linux在运行时通过ELF “section” header 进行迭代,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36295540/