【问题标题】:Getting the value of *ABS* symbols from C从 C 中获取 *ABS* 符号的值
【发布时间】:2019-07-13 10:00:42
【问题描述】:

从 C 中访问 *ABS*(绝对,不可重定位)符号的实际值的正确方法是什么?

我正在使用 ld 将数据(... HTML 模板)嵌入到可执行文件中(... 遵循https://csl.name/post/embedding-binary-data/ 中描述的方法)。如:

ld -r -b binary [the_file_to_be_embedded] -o [some_object.o]

然后,我正在使用

const char _some_object_start;
const char _some_object_end;
const int _some_object_size;

在实际代码中。通过使用&_some_object_start 获取字符指针,实际链接的文本可以很好地工作;读取大小一直以有趣的、依赖于平台的方式中断:在 ARM64 上,(long) &_some_object_size 实际上最终是大小,但在 x64 上,编译器正试图使其与 PC 相关并且最终没有得到正确的结果.

作为参考,实际的符号表如下所示:

SYMBOL TABLE:
00000000 l    d  .data  00000000 .data
0000000d g       .data  00000000 _binary_hello_world_txt_end
0000000d g       *ABS*  00000000 _binary_hello_world_txt_size
00000000 g       .data  00000000 _binary_hello_world_txt_start

(通过objdump -x获取。)

我假设ld 添加了大小数据,假设与它链接的代码有某种合理的方式可以读取它,因此问题。

(...更多的是理论上的,因为&_obj_end - &obj_start 仍然可以解析为实际数据长度;不过我特别好奇_obj_size。)

【问题讨论】:

  • 您可以通过将 end 和 start 的地址转换为 uintptr_t 并取差来获取大小

标签: c ld


【解决方案1】:

符号的值是它的地址,所以&symbol_name 应该检索它。

example.c

#include <stdio.h>
extern char abs_sym;
int main() { printf("%p\n", (void*)&abs_sym); }

运行示例:

$ gcc ldabs.c  -no-pie -Wl,--defsym=abs_sym=0xab && ./a.out
  0xab

【讨论】:

  • 为什么要将地址转换为long而不是void *并使用"%p"格式打印呢?无法保证 long 与指针大小相同,即使在 64 位系统上也是如此。
  • @Someprogrammerdude %p 以十六进制打印,我想要十进制,当您比较 x86-64 上的编译器/链接器行为时,无论如何您已经处于实现定义的区域,但可以肯定 "%p", (void*)x 是当然是打印指针最合适的方式。
  • @Someprogrammerdude 点了,不过。我现在正在设置和打印 (%p) 十六进制值。
  • 是的,gcc x86_64 问题也是我遇到的。可悲的是,目标平台之一就是……尽管它在 clang 上的工作方式很有趣!你认为这是一个 gcc 错误,还是只是未指定?
  • @Latanius 找到了问题的原因。 gcc 将-pie 传递给链接器,这导致绝对符号处理不正确。通过-no-pie 可以解决问题。 (我的 clang 不这样做,所以默认情况下 clang 使用绝对符号。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
  • 2022-06-22
  • 1970-01-01
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
相关资源
最近更新 更多