gpt4 book ai didi

c - Linux 在运行时迭代 ELF "section" header

转载 作者:太空狗 更新时间:2023-10-29 12:28:01 25 4
gpt4 key购买 nike

简短版本:可以在运行时遍历所有 ELF“部分” header ,并为每个加载的共享库获取每个“部分” header 的重定位地址。

长版:我正在尝试在用户空间中实现与内核 (dyn_debug) 中存在的动态调试相同的机制。每个 LOG 宏实例在程序的特定“部分”中创建静态变量的工作方式__attribute__((section("__verbose")))这会强制编译器将变量不放在“.data”部分,而是放在“__verbose”部分。稍后可以通过变量访问此段的起始和停止地址 __start___verbose,__stop___verbose。这样,某些中央例程可以遍历所有已注册的“日志”条目并按需更改属性。这适用于静态链接的可执行文件,但是当使用共享库时,有几个“__verbose”部分(每个共享库一个)和一个在可执行文件本身中。 (我当然使用 -fPIcflags以便包含在库中)还与“-export-dynamic”链接的所有内容,以确保导出所有符号。

每个共享库和主要可执行文件都有init 的属性(构造函数)方法。

我在 2 个案例中观察到了两种不同的行为。

案例 1:对于第一种情况,库不是由 ldopen 加载的,而是由“libc 加载器”加载的

  1. 引用 __start___verbose 总是返回相同的地址(主要可执行文件的地址),其中只有“主要”可执行文件日志条目存在。

  2. dlsym(RTLD_NEXT, __start___verbose),返回“下一个”可解析库的符号地址,所以实际上我得到了所有地址。

案例 2:使用 ldopen 加载库

  1. 引用 __start___verbose 总是返回相同的地址(主可执行文件的地址)
  2. dlsym(RTLD_NEXT, __start___verbose) 返回 NULL。
  3. dlsym(RTLD_DEFAULT, __start___verbose) 返回“主”进程表。
  4. dlsym(handle, __start___verbose) - 返回正确的节地址

问题:除了 4 之外,用 ldopen 打开的库是否有任何方法获取该符号,因为 4 需要从“加载程序”显式调用

代码:

/* 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 = .);
}

这为该部分定义了隐藏符号,因此每个 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com