fix(mm): 加分配失败分步诊断;build.py 改用 --phase2command 产出 kernel.elf
- mm.vp: 在 malloc(slab 路径)、_create_page、allocate_block 三处失败分支各加一条 [mm] 诊断打印,用于定位“[desktop] dirty_rows malloc FAILED” (768B → ≤SLAB_THRESHOLD → slab size class 5(1024B) → _create_page 需 order≥1 伙伴块; DumpBuddy 显示伙伴空闲链健康,故需进一步区分是哪一步返回 NULL) - build.py: kernel.elf 改为调用 viperc --phase2command 拿到“精确链接命令”再改写产出。 自行 glob .obj 去链会因对象顺序不同得到与 kernel.bin 不一致的段布局 (实测前 247KB 里 230KB 不同),无法把日志 rip 映射回函数。
This commit is contained in:
1 parent
cb5eb679c1
commit
449f2dbc37
2 files changed
+38
-13
No files matched your search
+17
-2
@@ -193,7 +193,12 @@ class _BuddySystemObject:
|
||||
if self.buddy.free_lists[i]:
|
||||
found_order = i
|
||||
break
|
||||
if found_order == -1: return None
|
||||
if found_order == -1:
|
||||
# [DIAG] 池面耗尽/链表坏:打印请求大小与所需阶数
|
||||
_adb: [128]char
|
||||
viperlib.snprintf(&_adb, 128, "[mm] allocate_block(size=%lu) need order=%d -> NO FREE BLOCK\n", size, order)
|
||||
serial.puts(&_adb)
|
||||
return None
|
||||
# 取出空闲块
|
||||
block: memory_block* = self.buddy.free_lists[found_order]
|
||||
# 从空闲链表中移除块
|
||||
@@ -287,7 +292,12 @@ class _SlabAllocator:
|
||||
obj_size: uint16 = _slab_obj_size(size_class)
|
||||
aligned_size: uint16 = uint16((obj_size + 15) & ~15)
|
||||
block: memory_block* = BuddySystemObject.allocate_block(4096 + memory_block.__sizeof__())
|
||||
if not block: return None
|
||||
if not block:
|
||||
# [DIAG] slab 建页拿不到伙伴块
|
||||
_cpb: [96]char
|
||||
viperlib.snprintf(&_cpb, 96, "[mm] slab _create_page(sc=%d) allocate_block(4128) -> NULL\n", size_class)
|
||||
serial.puts(&_cpb)
|
||||
return None
|
||||
hdr_off: uint64 = memory_block.__sizeof__()
|
||||
page: slab_page* = slab_page*(uint64(block) + hdr_off)
|
||||
page.magic = SLAB_MAGIC
|
||||
@@ -353,6 +363,11 @@ export def malloc(size: uint64) -> rawptr:
|
||||
sc: int = _slab_size_class(size)
|
||||
if sc >= 0:
|
||||
result: rawptr = SlabAllocator.alloc(sc)
|
||||
if result is None:
|
||||
# [DIAG] slab 分配失败(缓存链与建页都失败)
|
||||
_mb: [96]char
|
||||
viperlib.snprintf(&_mb, 96, "[mm] malloc(%lu) slab sc=%d -> NULL\n", size, sc)
|
||||
serial.puts(&_mb)
|
||||
return result
|
||||
hdr: uint64 = memory_block.__sizeof__()
|
||||
if size >= 4096:
|
||||
|
||||
@@ -3,7 +3,6 @@ import os
|
||||
import sys
|
||||
import subprocess
|
||||
import threading
|
||||
import glob
|
||||
|
||||
|
||||
# 解析参数
|
||||
@@ -23,19 +22,30 @@ os.system(cmd)
|
||||
shutil.copy("VKernel/__vpcbuild__/output/kernel.bin", "./disk/sys/kernel/x86_64/kernel.bin")
|
||||
|
||||
|
||||
# 额外链接一份带符号的 kernel.elf(仅供分析:objdump / nm / readelf 定位崩溃 rip)。
|
||||
# kernel.bin 是 --oformat binary --strip-all 的裸镜像,无符号表,不便把日志里的
|
||||
# rip=0x130d45 映射回函数。这里用同一批 .obj + 同一 linker.ld 再链一次(只去掉
|
||||
# --oformat binary/--strip-all),段布局与 kernel.bin 一致 → ELF 里的地址可直接对上运行镜像。
|
||||
# 额外产出带符号的 kernel.elf(仅供分析:objdump / nm / readelf 定位崩溃 rip)。
|
||||
# kernel.bin 是 --oformat binary --strip-all 的裸镜像、无符号表,不便把日志里的
|
||||
# rip 映射回函数。要点:**对象顺序决定段内布局**,自行 glob 一组 .obj 去链会得到
|
||||
# 与 kernel.bin 不同的地址(实测前 247KB 里 230KB 不同),没法对上日志。
|
||||
# 因此用 viperc 自己的 --phase2command:它把 llc/链接命令按“精确顺序”写进 .bat,
|
||||
# 我们只把该链接行里的 --oformat binary/--strip-all 去掉、输出改为 kernel.elf 再执行。
|
||||
kernel_elf = "VKernel/__vpcbuild__/output/kernel.elf"
|
||||
kernel_objs = sorted(glob.glob("VKernel/__vpcbuild__/output/*/*.obj"))
|
||||
if kernel_objs:
|
||||
print(f"[build] linking {kernel_elf} for analysis ({len(kernel_objs)} objects)...")
|
||||
link_rc = subprocess.call(["ld.lld.exe", "-m", "elf_x86_64", "-T", "VKernel/linker.ld", "-o", kernel_elf] + kernel_objs)
|
||||
if link_rc != 0:
|
||||
p2c_bat = "VKernel/__vpcbuild__/phase2cmd.bat"
|
||||
os.system(r'..\..\ViperC\output\viperc.exe --project ./VKernel/project.vpj --phase2command ' + p2c_bat)
|
||||
link_line = None
|
||||
if os.path.exists(p2c_bat):
|
||||
with open(p2c_bat, "r", encoding="utf-8", errors="replace") as f:
|
||||
for line in f:
|
||||
low = line.lower()
|
||||
if "ld.lld" in low and (".bin" in low or "output" in low):
|
||||
link_line = line.rstrip("\r\n")
|
||||
if link_line is not None:
|
||||
elf_line = link_line.replace("--oformat binary", "").replace("--strip-all", "")
|
||||
elf_line = elf_line.replace("kernel.bin", "kernel.elf")
|
||||
print("[build] linking kernel.elf for analysis ...")
|
||||
if os.system(elf_line) != 0:
|
||||
print("[build] 警告: kernel.elf 链接失败(不影响 kernel.bin)")
|
||||
else:
|
||||
print("[build] 警告: 未找到 kernel 目标文件,跳过 kernel.elf")
|
||||
print("[build] 警告: 未从 phase2command 取到链接命令,跳过 kernel.elf")
|
||||
|
||||
|
||||
# --noapp 优先级高于 --kernel-only:只编译内核,不编译所有库和应用
|
||||
|
||||
Reference in new issue
Block a user