LD和NOLOAD部分:了解奇怪的LMA值

时间:2017-12-18 10:25:30

标签: linker ld linker-scripts

我正在编写一个裸机内核,在ld部分的情况下,我无法理解NOLOAD的输出。我声明仅在MMU激活时存在的符号,因此VMA和LMA不相同。 我曾经宣布过这样一个这样的部分:

_foobar_start = .;
.foobar : AT(ADDR(.foobar) - VA_PA_OFFSET)
{
    *.o(.foobar.section*)
}
_foobar_end = .;

现在我的部分内容之一是由引导加载程序加载的,所以我只想声明要在运行时使用的VMA符号来访问数据,所以我尝试了NOLOAD属性:

_foobar_start = .;
.foobar (NOLOAD) :
{
    . += SIZE_OF_FOOBAR;
}
_foobar_end = .;

我知道在这种情况下我并不关心LMA,但我希望看到类似的地方,LMA = VMA(见LD manual):

.foobar         0x000000004002c000     0x353c load address 0x000000004002c000

但我得到一些奇怪的LMA,我不明白:

.foobar         0x000000004002c000     0x353c load address 0x0000000001900000

如果我使用

强制脚本中的VMA = LMA
.foobar (NOLOAD) : AT(_foobar_start)

一切似乎都很好,我只看到

.foobar         0x000000004002c000     0x353c

即使没有强制VMA = LMA,生成的ELF也没问题,但是由于其他部分(toto是另一部分),我在编译时会收到一些警告:

warning: dot moved backwards before `.toto

我希望阅读这些内容。

在指定NOLOAD时,我是否有理由不能获得LMA = VMA?

编辑:这是触发问题的完整链接器文件。我添加了一些评论以指出问题

OUTPUT_ARCH(CONFIG_LINKER_ARCH)
OUTPUT_FORMAT(CONFIG_LINKER_FORMAT)

_kern_phys_base = OCRAM_BASE_PA + OCRAM_OFFSET;

_kern_offset = KERNEL_VA_PA_OFFSET;

SECTIONS
{
    . = _kern_phys_base;

    _start_image_addr = .;

    . = ALIGN(0x1000);
    _early_text_start = .;
    .early_text :
    {
        KEEP(*(.text.boot))
        KEEP(*(.text.mmu))
    }

    . = ALIGN(4);
    .early_rodata :
    {
        *(.rodata.boot*)
        *(.rodata.mmu*)
    }
    _early_text_end = .;

    . = ALIGN(0x1000);
    _early_data_start = .;
    .early_data :
    {
        *(.data.boot)
    }
    _early_data_end = .;

    . = ALIGN(0x4000);
    _early_bss_start = .;
    .early_bss :
    {
        *(.bss.mmu)
        *(.bss.boot)
    }
    . = ALIGN(16);
    _early_bss_end = .;

    _early_end = .;

    /*
     * The following part is accessed only once the MMU has been
     * activated, so we first need to jump into "high" memory
     */
    . += _kern_offset;

    . = ALIGN(0x1000);
    _text_start = .;
    .text : AT(ADDR(.text) - _kern_offset)
    {
        *(.text .text.*)
    }
    _text_end = .;

    . = ALIGN(0x1000);
    _rodata_start = .;
    .rodata : AT(ADDR(.rodata) - _kern_offset)
    {
        *(.rodata*)
    }
    _rodata_end = .;

    . = ALIGN(4);
    _arm_extab_start = .;
    .ARM.extab : AT(ADDR(.ARM.extab) - _kern_offset)
    {
        *(.ARM.extab)
    }
    _arm_extab_end = .;

    . = ALIGN(4);
    _arm_exidx_start = .;
    .ARM.exidx : AT(ADDR(.ARM.exidx) - _kern_offset)
    {
        *(.ARM.exidx)
    }
    _arm_exidx_end = .;

    . = ALIGN(4);
    _kernel_debug_info_start = .;
    _kernel_debug_info_end = .;

    . = ALIGN(4);
    _emergency_code_vstart = .;
    _emergency_code_vend = .;

    /*
     * This is where I use the NOLOAD, with AT this time
     * This 'archive' part is not located in OCRAM, but some
     * where else in RAM
     */
    _archive_point_save = .;
    . = DDR_BASE_VA;
    . = ALIGN(512);
    _archive_start = .;
    .archive_data (NOLOAD) : AT(_archive_start)
    {
        codes.o(.rawdata*)
    }
    _archive_end = .;
    . = _archive_point_save;

    /* Back to OCRAM VMA */
    . = ALIGN(0x1000);
    _data_start = .;
    .data : AT(ADDR(.data) - _kern_offset)
    {
        *(.data*)
    }
    _data_end = .;

    . = ALIGN(32);
    _bss_start = .;
    .bss : AT(ADDR(.bss) - _kern_offset)
    {
        *(.bss .bss.*)
    }
    . = ALIGN(16);
    _bss_end = .;

    /*
     * Second location, also in RAM, just after the '.archive_data' section
     * This time I didn't put the AT to show the difference in output
     */
    _dyn_archive_point_save = .;
    . = _archive_end;
    . = ALIGN(0x1000);
    _dyn_archive_start = .;
    .dyn_archive (NOLOAD) :
    {
        . += _dyn_archive_space;
    }
    _dyn_archive_end = .;
    . = _dyn_archive_point_save;

    /* Back to OCRAM VMA */
    . = ALIGN(0x1000);
    _kernel_stack_guard = .;
    . += 0x1000;

    .stack (NOLOAD) :
    {
        _kernel_stack_end = .;
        /* 2 pages of 4 kB */
        . += 0x2000;
        _kernel_stack_start = .;
    }

    _kernel_image_end = .;
}

以下是objdump -x

的输出
build/kernel/kernel.elf:     file format elf32-littlearm
build/kernel/kernel.elf
architecture: arm, flags 0x00000102:
EXEC_P, D_PAGED
start address 0x00910000

Program Header:
0x70000001 off    0x0003072c vaddr 0x4003072c paddr 0x0093072c align 2**2
         filesz 0x000000a0 memsz 0x000000a0 flags r--
    LOAD off    0x00010000 vaddr 0x00910000 paddr 0x00910000 align 2**16
         filesz 0x00002828 memsz 0x00008000 flags rwx
    LOAD off    0x00018000 vaddr 0x40018000 paddr 0x00918000 align 2**16
         filesz 0x000199e0 memsz 0x0001fa28 flags rwx
    LOAD off    0x00038000 vaddr 0x41028000 paddr 0x01928000 align 2**16
         filesz 0x00000000 memsz 0x00100000 flags rw-
    LOAD off    0x00039000 vaddr 0x40039000 paddr 0x40039000 align 2**16
         filesz 0x00000000 memsz 0x00002000 flags rw-
    LOAD off    0x00040000 vaddr 0x41000000 paddr 0x41000000 align 2**16
         filesz 0x00000000 memsz 0x00028000 flags rw-
private flags = 5000200: [Version5 EABI] [soft-float ABI]

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .early_text   000015c0  00910000  00910000  00010000  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .early_rodata 00000030  009115c0  009115c0  000115c0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .early_data   00000828  00912000  00912000  00012000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  3 .early_bss    00004000  00914000  00914000  00012828  2**14
                  ALLOC
  4 .text         000142d8  40018000  00918000  00018000  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  5 .rodata       000036c0  4002d000  0092d000  0002d000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .ARM.extab    0000006c  400306c0  009306c0  000306c0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .ARM.exidx    000000a0  4003072c  0093072c  0003072c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .archive_data 00028000  41000000  41000000  00040000  2**0
                  ALLOC
  9 .data         000009e0  40031000  00931000  00031000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 10 .bss          00006048  400319e0  009319e0  000319e0  2**3
                  ALLOC
 11 .dyn_archive  00100000  41028000  01928000  00038000  2**0
                  ALLOC
 12 .stack        00002000  40039000  40039000  00039000  2**0
                  ALLOC
 13 .comment      0000002d  00000000  00000000  000319e0  2**0
                  CONTENTS, READONLY
 14 .ARM.attributes 00000037  00000000  00000000  00031a0d  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
no symbols

如您所见:.archive_data.stack正确获得VMA = LMA但.dyn_archive没有。如果我删除了AT .archive_data,我的行为与地理.dyn_archive

0x1900000相同

1 个答案:

答案 0 :(得分:0)

看来我的上一条评论是有效的,已经确认(至少在我们对手册的解释范围内)on the binutils ML

“LMA向后”触发的警告,每次.手动更新时正确更新LMA都是正确的方法。