【问题标题】:Is it possible to access a C variable from a linker script是否可以从链接描述文件访问 C 变量
【发布时间】:2021-11-17 09:47:45
【问题描述】:

假设我需要将进程的大小加载到内存中,然后在我的代码中定义它:

#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 info 文档中的示例也会产生令人讨厌的错误。也许你也可以帮我解决这个问题。

【问题讨论】:

    标签: c linux compiler-errors linker linker-scripts


    【解决方案1】:

    看起来你有两个不同的问题。

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

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

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

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

    extern char prog_sz;

    char 类型在这里并不重要。该语句只是告诉编译器该符号将在其他地方定义所必需的。在此之后,您可以将符号的地址分配给prog_sz,方法是将您的定义修改为:

    size_t prog_sz = (size_t)(&amp;prog_sz__);

    使用&amp; 告诉程序将与符号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/

    【讨论】:

    • 谢谢,虽然问题是关于在 C 中创建一个变量并在链接器脚本中访问它,但您的回答表明它无法完成,因为链接器只会创建另一个符号。尽管这个问题是关于我的操作系统的,但我想我应该解决这些问题。您能否指出任何解释如何正确配置设置的资源。
    • 关于链接器文档,如果您使用的是 GNU 工具,我会在这里查看:sourceware.org/binutils/docs-2.37/ld.pdf
    • 我添加了一些关于变量prog_sz 选项的更多细节。希望其中之一将涵盖您正在寻找的内容。
    猜你喜欢
    • 2019-09-01
    • 2017-02-21
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    相关资源
    最近更新 更多