目录
标长值
一个 .xvm.exe 可执行文件由**标长值(TLV)**条目的序列组成。
- 基于 标长值(TLV)。
- 加载器按**标签(tag)**收集已知条目,忽略未知条目。
标长值条目格式如下:
u8 tag
u32 length
u8 value[length]标签分配
| 标签 | 含义 |
|---|---|
0x01 | name table |
0x10 | function definition |
0x11 | variable declaration |
0x12 | primitive function declaration |
0x13 | primitive variable declaration |
0x14 | function fixup table |
说明:
0x00到0x0f保留。 其中:0x00为注释0x01为 name table
xvm 自定义 tag 从
0x10开始。
条目明细
下面详细介绍各个条目的值。
0x01 name table
其值是若干字符串(C string)的连续拼接。
- 其他条目需要使用「名字」时,可以用
u32 offset指向 name table 中的字符串。 - 所有字符串在表内唯一,因此可以用
offset来判断 name 是否相等。 - 加载器先加载 name table,来获得「名字」的
offset所对应的具体字符串。
0x10 function definition
u32 name_offset
u16 arity
u16 local_count
u32 code_length
u8 code[code_length]
u32 local_name_offsets[local_count]
u32 label_count
u32 label_name_offsets[label_count]
u32 label_offsets[label_count]name_offset指向 name table 中的函数名。arity是参数个数。local_count是局部槽位数。local_name_offsets按槽位顺序保存局部变量名。label_name_offsets保存 label 名字。label_offsets保存 label 在 code 中的偏移。code是函数体字节码,编码见 指令。- 函数的入口是
code的第一个字节。
0x11 variable declaration
u32 name_offset声明全局变量。变量初值不在此处编码,由 setup 函数在运行时初始化。
0x12 primitive function declaration
u32 name_offset0x13 primitive variable declaration
u32 name_offset0x14 function fixup table
一个函数修正表条目包含若干函数修正记录。
修正记录格式:
u32 type_offset
u32 name_offset
u32 dest_name_offset
u32 dest_offset其中:
type是修正类型字符串。name是目标符号或字面量内容。dest_name是函数名。dest_offset是函数code内的偏移。
dest_offset 指向代码中一个 8 字节的占位符。 加载器根据 type 和 name 计算出要填入的值,并写入该位置。
修正类型:
type | name 的含义 | 填入 |
|---|---|---|
string-value | 字符串内容 | string value |
symbol-value | symbol 名 | symbol value |
fn-pointer | 函数名 | function pointer |
prim-pointer | primitive 名 | primitive function pointer |
global-pointer | 全局变量名 | global variable pointer |
说明:
string-value用于:load-string的valuesymbol-value用于:load-symbol的valuefn-pointer用于:call-n/tail-call-n的targetload-closure/make-closure的target
prim-pointer用于:call-prim-n/tail-call-prim-n的target
加载流程
- 扫描所有标长值条目。
- 找到 name table,建立 offset 映射。
- 收集 primitive declaration 条目。
- 收集 function / variable definition 条目。
- 收集 function fixup table 条目。
- 根据函数修正表中的修正记录:
- 找到
dest_name对应的 function。 - 在其
code的dest_offset处执行修补。
- 找到
- 运行
main或test函数。