我正在编写一个裸机内核,在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
相同
答案 0 :(得分:0)
看来我的上一条评论是有效的,已经确认(至少在我们对手册的解释范围内)on the binutils ML
“LMA向后”触发的警告,每次.
手动更新时正确更新LMA都是正确的方法。