Cómo entender la relación entre la LMA, VMA y FileOffset?

A continuación es el linker script de un BRAZO-sistema operativo basado.

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*/
}

Se generará un fichero ELF con secciones como esta:

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

He cambiado el linker script para abajo sólo para el experimento:

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*/
}

Se generará un fichero ELF con secciones como esta:

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

Podemos ver el .text y .rodata secciones LMA no se ve afectada. Sólo .data sección y en las secciones posteriores se ven afectados por el AT() comando.

Por lo que me da la sensación de que el VMA y LMA de cálculo durante la vinculación es independiente de los otros.

Si no hay AT() comando, la LMA y VMA será el mismo. Una vez que hay una EN() el comando, los sectores que serán afectados.

No he encontrado una descripción detallada acerca de este comportamiento en el Uso de ld doc. Estoy en lo cierto?

Y por qué la FileOffset también es cambiado por el AT() comando? El .y de texto .secciones de datos se intercambian con respecto a FileOffset.