是否可以从链接器脚本访问 C 变量

Is it possible to access a C variable from a linker script

例如,我需要获取加载到内存中的进程的大小,然后我在我的代码中定义它:

#include <stdio.h>

ssize_t prog_sz;
int main()
{
     printf("%x\n", prog_sz);
}

然后我有一个链接描述文件使用这样的行访问它 proc_sz = .

注意:我用我的程序测试的所有链接描述文件总是会产生错误,这就是为什么我只指定了脚本中的一行。例如像这样简单的东西没有我第一次谈到的那行:

SECTIONS
{
    .text : { *(.text) }
    .data : { *(.data) }
    .bss : { *(.bss) }
}

产生如下烦人的错误:

/usr/bin/ld: a.out: error: PHDR segment not covered by LOAD segment
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): in function `__libc_csu_init':
(.text+0x9): undefined reference to `__init_array_start'
/usr/bin/ld: (.text+0x20): undefined reference to `__init_array_end'
/usr/bin/ld: a.out: hidden symbol `__init_array_end' isn't defined
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

即使是 ld 信息文档中的一个示例也会产生那个恼人的错误。也许你也可以帮我解决这个问题。

您似乎有两个不同的问题。

第一期涉及symbol/variableprog_sz。您展示的方法只会导致链接器尝试创建另一个名为 prog_sz 的符号,这不太可能实现目标。

在不详细说明正在做什么的情况下,我将介绍三个目标及其解决方案:

  1. 设置变量 prog_sz 以包含链接器文件中定义的符号的地址。

在命令文件中用不同的名称定义符号,例如 prog_sz__。然后,您可以直接在代码中 prog_sz 的声明上方添加以下行:

extern char prog_sz;

类型 char 在这里并不重要。该语句仅用于告诉编译器该符号将在其他地方定义。在此之后,您可以通过将定义修改为:

来将符号的地址分配给 prog_sz

size_t prog_sz = (size_t)(&prog_sz__);

使用 & 告诉程序将与符号 prog_sz__ 关联的地址存储在变量 prog_sz 中。这会将链接描述文件中定义的符号分配给变量 prog_sz.

  1. 使用链接描述文件将变量定位在固定位置,有一种方法可以做到这一点。

假设您使用的是 GNU 工具链,在构建时使用 GCC 选项 -fdata-sections。这会将每个变量放入其自己的数据部分。请注意,您的 .bss.data 部分将替换为前缀为 .data.bss 的每个变量的部分,您可能需要使用通配符 *捕获 .bss.data 部分。

然后您可以在链接器文件中 . 设置为所需地址的位置下方添加一个部分。

例如:

SECTION
{
...

    . = where_i_want_prog_sz;
    prog_sz_section :
    {
        * (.bss.prog_sz)
    }
...
}

请注意,这会将 prog_sz 存储在特定位置,但不会将 prog_sz 设置为该位置的值。

  1. 将命令文件中定义的链接器符号视为 size_t 变量。

使用extern关键字定义变量:extern size_t prog_sz;

这告诉编译器该符号在别处定义,但属于 size_t 类型。请记住,如果这是正在做的事情,那么您将需要确保该内存位置没有被用于任何其他用途,否则 prog_sz 可能会与系统中的其他数据重叠。

关于第二个问题,即链接器错误消息列表,我相信您可能没有正确配置链接器。符号__init_array_end__init_array_start与初始化C编程环境有关。我建议查看链接器设置和文档以确保程序配置正确。如果您使用的是 GNU 工具链,您可以在此处找到文档:

https://sourceware.org/binutils/docs-2.37/