如何理解LMA,VMA和FileOffset之间的关系?

时间:2019-05-04 10:03:02

标签: linker ld binutils

下面是ARM-based OS中的链接描述文件。

ENTRY(__entry) /*kernel entry (kernel/asm/boot.S)*/

/*kernel will be loaded at this address after boot*/
INCLUDE linker.ld

SECTIONS
{
    /*kernel will be compiled with virtual address base at 2GB*/
    . = 0x80000000 + start_address; /*2GB + start_address = (0x80010000)*/
    PROVIDE(_kernel_start = .); /*defined at kernel/include/kernel.h, set to 0x80010000*/

 .text : AT(start_address) 
    {
        *(.text)
    }

    .data : 
    { 
        *(.data) 
    }

    .bss : 
    { 
        *(.bss COMMON)
    }
    . = ALIGN(8);
    PROVIDE(_fb_start = .); 
    . += framebuffer_size;

    PROVIDE(_kernel_end = .); /*defined at kernel/include/kernel.h*/
}

它将生成带有以下部分的ELF文件:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000c610  80010000  00010000  00010000  2**2 <=== LMA and FileOffset are affected starting from this section.
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rodata       0000037d  8001c610  0001c610  0001c610  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00004000  80020000  00020000  00020000  2**14
                  CONTENTS, ALLOC, LOAD, DATA
  3 .got          00000024  80024000  00024000  00024000  2**2
                  CONTENTS, ALLOC, LOAD, DATA

仅出于实验目的,我将链接描述文件更改为以下内容:

ENTRY(__entry) /*kernel entry (kernel/asm/boot.S)*/

/*kernel will be loaded at this address after boot*/
INCLUDE linker.ld

SECTIONS
{
    /*kernel will be compiled with virtual address base at 2GB*/
    . = 0x80000000 + start_address; /*2GB + start_address = (0x80010000)*/
    PROVIDE(_kernel_start = .); /*defined at kernel/include/kernel.h, set to 0x80010000*/

 .text : /*AT(start_address) */ <--------------- Here Commented!
    {
        *(.text)
    }

    .data : AT(start_address) <--------------- Move it to here!
    { 
        *(.data) 
    }

    .bss : 
    { 
        *(.bss COMMON)
    }
    . = ALIGN(8);
    PROVIDE(_fb_start = .); 
    . += framebuffer_size;

    PROVIDE(_kernel_end = .); /*defined at kernel/include/kernel.h*/
}

它将生成带有以下部分的ELF文件:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000c610  80010000  80010000  00020000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rodata       0000037d  8001c610  8001c610  0002c610  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00004000  80020000  00010000  00010000  2**14 <=== LMA and FileOffset are affected starting from this section.
                  CONTENTS, ALLOC, LOAD, DATA
  3 .got          00000024  80024000  00014000  00014000  2**2
                  CONTENTS, ALLOC, LOAD, DATA

我们可以看到LMA的.text.rodata部分不受影响。 .data命令仅影响AT()部分和后面的部分。

因此,我感觉链接期间的VMA和LMA计算彼此独立。

如果没有AT()命令,则LMA和VMA将相同。一旦有了AT()命令,它后面的部分将受到影响。

我没有在Using ld doc中找到有关此行为的详细描述。我说得对吗?

为什么AT()命令也更改FileOffset? .text和.data部分相对于FileOffset进行了交换。

0 个答案:

没有答案