根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss 尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是 EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、 堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时 #GP(rip=0x130d45, err=0x0)。 - linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖 .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss) - mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr, __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃) - main.vp: 取 __bss_end 并传入 mm.init - boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData) 占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用 另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为 kbd_svc.__init__() 等。
49 lines
1.1 KiB
Plaintext
49 lines
1.1 KiB
Plaintext
ENTRY(_start)
|
||
|
||
SECTIONS {
|
||
. = 0x100000;
|
||
|
||
.text : {
|
||
*(.text.startup)
|
||
*(.text)
|
||
*(.text.*)
|
||
}
|
||
|
||
.rodata : {
|
||
__rodata_start = .;
|
||
*(.rodata)
|
||
*(.rodata.*)
|
||
__rodata_end = .;
|
||
}
|
||
|
||
.data : {
|
||
*(.data)
|
||
*(.data.*)
|
||
}
|
||
|
||
.bss : {
|
||
__bss_start = .;
|
||
*(.bss)
|
||
*(.bss.*)
|
||
*(COMMON)
|
||
/* 强制本输出段为 PROGBITS 并占用文件空间:.bss 默认是 NOBITS(不占文件),
|
||
于是 kernel.bin 的 FileSize 不包含 .bss。bootloader 只按文件大小预留物理页
|
||
(PagesNeeded = KernelSize/4096),.bss 尾部(ticks/_perf_* 等全局量)便留在
|
||
未预留的 EfiConventionalMemory 里,被 mm 的堆 arena 覆盖 → 破坏内核全局量、
|
||
并反过来破坏堆元数据。加一条数据语句(LONG)即让整段 .bss 写入 kernel.bin。 */
|
||
. = ALIGN(16);
|
||
LONG(0);
|
||
__bss_end = .;
|
||
}
|
||
|
||
/DISCARD/ : {
|
||
*(.comment)
|
||
*(.note)
|
||
*(.eh_frame)
|
||
*(.eh_frame_hdr)
|
||
*(.reloc)
|
||
*(.rela)
|
||
*(.debug*)
|
||
}
|
||
}
|