如何使用phdrs命令修复链接描述文件中的重叠部分?

时间:2016-08-09 06:34:09

标签: c assembly linker elf linker-scripts

我试图让一个简单的操作系统内核更上一半。当像我一样使用Grub作为引导加载程序时,还必须有一些下半部分(32位)代码。因为我想保持这个32位代码尽可能简短,我不想在其中编写一个ELF加载器只是为了加载64位代码,因为这显然是荒谬的(这实际上是最常见的解决方案,但我我想尽可能避免它。)

我发现链接器脚本允许加载地址与虚拟地址不同。这很有用,因此我可以加载64位部分以适应小二进制文件,然后使用虚拟内存将正确的虚拟地址映射到它们加载的物理地址。这样做除了低文本部分没有放在文本段中。入口点_start位于此部分中。

除非我在_start命令中指定文本段,否则我无法将低文本部分(PHDRS所在的位置)放在文本段中。当然,使用此命令会使链接器决定生成正常预期的段。当我这样做时,这些部分最终重叠,我不完全确定为什么。我在订单数据,rodata,文本中指定了段,并且这些段是相同的,但是它们的装载存储器地址被分配了rodata和数据交换,并且所有三个都重叠。

这是我的链接描述文件:

ENTRY(_start)

PHDRS {
    .low PT_LOAD FILEHDR PHDRS;
    .data PT_LOAD;
    .rodata PT_LOAD;
    .text PT_LOAD;
}

SECTIONS {
    . = 1M;

    .data_low BLOCK(4K) : ALIGN(4K) {
        *(.bss_low)
    } : .low

    .rodata_low BLOCK(4K) : ALIGN(4K) {
        KEEP(*(.multiboot_low))
        *(.rodata_low)
    } : .low

    .text_low BLOCK(4K) : ALIGN(4K) {
        *(.text_low)
    } : .low

    .stack 0xC0000000 : AT(0x200000) ALIGN(4K) {
        *(.bootstrap_stack)
    } : .data
    _LADD_ = LOADADDR(.stack) + SIZEOF(.stack);

    .data BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
        *(COMMON)
        *(.bss)
    } : .data
    _LADD_ += SIZEOF(.data);

    .rodata BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
        *(.rodata)
    } : .rodata
    _LADD_ += SIZEOF(.rodata);

    .text BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
        *(.text)
    } : .text

}

我认为代码与此错误无关。当我使用此链接描述文件(另外使用-n --gc-sections)链接我的目标文件时,我收到此错误:

ld: section .data loaded at [0000000000200020,000000000020103f] overlaps section .rodata loaded at [0000000000200010,00000000002000d0]
ld: section .text loaded at [00000000002000d1,00000000002017ce] overlaps section .data loaded at [0000000000200020,000000000020103f]

加载内存地址按照rodata,data,text的顺序排列,即使我希望它们应该在订单数据,rodata,text中,因为这些部分是以AT说明符的顺序指定的,单调非减少位置(假设各部分没有负面大小)。

我应该指明我正在使用" segment"表示ELF程序头中的一个条目(链接器脚本中的PHDRS)和"部分"表示ELF节标题中的一个条目(链接描述文件中为SECTIONS)。我认为这是正确的术语,但承认我对链接器文件和ELF格式的理解最多。无论出于何种原因,如果其入口点不在段中,Grub将不会加载ELF文件。

为什么这些部分确实不符合我期望它们的顺序,我怎样才能使它们成为现实?谢谢。

0 个答案:

没有答案