Build overlay apps without the Arm toolchain, and say how far verification got

pip install ziglang cross-compiles to thumb-freestanding-eabi, which is enough to build a .app with no arm-none-eabi-gcc and no Docker. Measured refusals: --defsym, -Ttext and --section-start come back as unsupported linker args, so the VMA is resolved into a copy of app.ld; -T is forwarded (a missing script errors); --image-base is accepted but page-aligns the segments into 0x200103C8 and 0x20020C94. tools/elf2bin.py extracts allocated sections rather than program headers, because lld maps the ELF header and phdr table as a 180-byte LOAD of its own -- following the headers starts the image at 0x20000000 and APP_ERR_VMA. One division pulled in __aeabi_uidiv, which a -nostdlib blob cannot have: Minesweeper now avoids division entirely. app_main carries the .text.entry attribute upstream's apps use, so the entry is first for the loader's jump to offset 0.

Minesweeper builds to 2408 bytes of code against a 4096-byte budget. Installed through the page, the firmware reads the slot header twice and then exactly code_size bytes from slot+0x1000 -- the only read of that size in the boot log -- so the blob shape, header, CRC, VMA and offset are all accepted. Whether control reaches the overlay is unproven: the 100 ms PC probe saw no overlay address, no APP ERROR screen appears, and the app does not draw. test_elf2bin pins the phantom-header-segment lesson; both AGENTS files record the rest.
This commit is contained in:
mckero committed 2026-10-02 08:32:22 +08:00
1 parent 61344e486e
commit f938d0b3bd
5 files changed
+226 -8

No files matched your search

+21
View File
@@ -535,6 +535,27 @@ app 区被读过 —— 而多系统菜单读的是**固件槽**,不是应用
**而当"改了不生效"时,过期的写回依然值得怀疑**:模拟器退出时会把内存里的镜像写回文件,所以客人还活着
时做的改动,可能被它手里那份副本覆盖 —— 这也是标记被清掉后又重新出现的原因。
**没有 Arm 工具链也能编叠加应用:`pip install ziglang`。** 写它的机器上既没有 `arm-none-eabi-gcc`
也没有 Docker,但 Zig 自带 C 编译器、能交叉到 `thumb-freestanding-eabi`,够用了。Zig 会拒绝什么(都实测过):
`--defsym`、`-Ttext`、`--section-start`(被它的链接参数白名单挡掉);所以 VMA 用 `sed` 写进一份
`app.ld` 的副本;`-T` **是**会被转发的(给一个不存在的脚本它会报错);`--image-base` 虽然接受但没有用,
因为它把段按页对齐(0x20000280 变成 0x200103C8 与 0x20020C94 两个 LOAD)。
最花时间的是两个坑。**lld 会把 ELF 头与程序头表本身也映射成一个 LOAD** —— 52 + 4×32 = 180 字节、位于镜像
基址、里面没有任何节内容 —— 所以 `tools/elf2bin.py` **按已分配节提取,而不是按程序头**;跟着程序头走会让
镜像从 0x20000000 开始,加载器以 APP_ERR_VMA 拒绝。另一个是**一次除法就会牵出 `__aeabi_uidiv`**,而它在
`-nostdlib` 的块里并不存在 —— 正确的修法是**把除法去掉**(重复减法;用 `& 127` 加拒绝代替 `% 81`),
而不是往 4 KiB 的叠加区里链一个软除法。
入口必须在镜像最前面,因为加载器跳到块偏移 0,所以 `app_main` 带着上游自带应用用的同一个
`__attribute__((section(".text.entry"), used))`(`cube3d_app.c:183`)。
用页面装上去后的实测:固件把槽头读了两次,然后**正好从 槽+0x1000 读了 `code_size` 字节**
(Minesweeper 的 2408 字节代码就读了 2408 字节,而且这是整份启动日志里唯一一次这种大小的读取)。也就是说:
块的形状、头、CRC、VMA、偏移**全部被接受**。**但控制权是否真的交到叠加区仍未证实**:PC 探针每 100 ms 采样
一次、没采到叠加区地址,也没有出现 `APP ERROR` 屏,应用也没有画出来。现状就是如此 —— **管线验证到了
"加载"这一步,还没到"执行"**。
## 键盘:两个真 bug,都已修复
这里原来的笔记写的是"按键到达了固件但界面不反应",并且归咎于机器模型。结果发现有**两个