WebAssembly 使用LEB128编码。
LEB128编码是一种使用广泛的可变长度编码格式,在DWARF调试格式信息、Android 的Dalvik虚拟机、xz压缩文件等诸多领域中都有广泛的使用,WebAssembly二进制文件中也使用LEB128编码表示整数与字符串长度等信息。
LEB128编码的核心思想主要有两点:
主流编程语言中,一个整形数一般采用本地序表示,同时每个字节8位(bit)用于表达256进制的一个数位。如果每个字节只用于表达LEB128的128进制的一个数位,那么将只需要7位。LEB128将每个字节剩余的1位用于表达是否终结的标志位,如果标志位是1表示编码数据还没有结束,如果标志位位0则表示编码已经结束。
样例的格式:
首先因为大小端问题,这里的存放和源文件是不同的,wasm的魔数为0x6d736100,版本号为0x01,所以前四个为魔数00 61 73 6d,后四个是版本号01 00 00 00,大小端颠倒了。
WebAssembly的头部是一个四字节的魔数: [0x00, 0x61, 0x73, 0x6d],对应"\0asm"字符串。其中0x61, 0x73, 0x6d分别对应着字母的ASCALL码。
魔数后面的四字节是当前WebAssembly文件的版本,目前是有版本1。
模块主体主要是由多个段组成,段数据包含了模块段全部信息,每个段都对应一个ID。
ID | 段 | 说明 |
---|---|---|
0 | 自定义段(Custom) | 主要用于存储调试信息等数据 |
1 | 类型段(Type) | 存储导入函数、模块内部函数的函数参数列表 |
2 | 导入段(Import) | 用于存储导入函数的函数名称、函数参数索引 |
3 | 函数段(Function) | 用于存储函数索引值 |
4 | 表格段(Table) | 用于存储对象引用,通过表格段可以实现函数指针的功能(call_indirect指令),可以从外部宿主导入,同时也可以导出到外部宿主环境 |
5 | 内存段(Memory) | 用于存储程序的运行时动态数据,可以从外部宿主导入,同时也可以导出到外部宿主环境 |
6 | 全局段(Global) | 用于存储全部变量值 |
7 | 导出段(Export) | 用于存储导出函数的函数名称、函数参数索引 |
8 | 开始段(Start) | 用于指定模块初始化时的函数索引值 |
9 | 元素段(Elem) | 表格段并没有显式地初始化,元素段用于存储函数的索引值 |
10 | 代码段(Code) | 用于存储函数的指令代码 |
11 | 数据段(Data) | 用于存储初始化内存的静态数据 |
(暂未写)
接下来首先是类型段。
01 8C 80 80 80 00 02 60 01 7F 01 7F 60 02 7F 7F 01 7F
01是type,表示函数签名的Type Section,后面的 8C 80 80 80 00是LEB128编码方式表示长度为0c。
后续的表示:
02 60 01 7F 01 7F 60 02 7F 7F 01 7F
02表示entries数量为2,60表示是个函数的签名,01 表示参数为1,7f表示参数为i32类型,01表示有一个返回值,7f表示返回值为i32类型,这个是printf的函数声明; 同理,60 02 7F 7F 01 7F表示两个带有i32类型并返回i32类型的函数声明,也就是main的函数声明。
02 8C 80 80 80 00 01 03 65 6E 76 04 70 75 74 73 00 00
02表示Import Section.
长度为12, 02 8c 80 80 80 00,内容为:01 03 65 6E 76 04 70 75 74 73 00 00
01则只有一个引用,module长度为3,名称为env,field长度为4,名称为puts,最后的kind表示引入的类型,00表示引入的是个函数。
03 82 80 80 80 00 01 01
03是函数段Function Section
长度为82 80 80 80 00,内容为:01 01
01表示签名索引数量为1,01表示在type区中的索引值值1,即printf函数的签名。
04 84 80 80 80 00 01 70 00 00
04是Table Section。
长度为84 80 80 80 00 ,内容为:01 70 00 00
01表示数量为1,类型为70,目前只能是70,表示anyfunc。
05 83 80 80 80 00 01 00 01
05是内存段(Memory)
长度为83 80 80 80 00 , 内容为: 01 00 01
06 81 80 80 80 00 00
06是全局段(Global)
长度为 81 80 80 80 00 , 内容为: 00
07 91 80 80 80 00 02 06 6D 65 6D 6F 72 79 02 00 04 6D 61 69 6E 00 01
07是Export Section
长度为91 80 80 80 00 , 内容为: 02 06 6D 65 6D 6F 72 79 02 00 04 6D 61 69 6E 00 01
02表示export数量为2,06表示第一个entry长度,名称为memory,02表示类型为memory类型,index为00,表示在对应索引空间的索引值; 04表示第二个entry长度为4,名称为main,类型为00,function类型,索引为01
0A 8F 80 80 80 00 01 89 80 80 80 00 00 41 10 10 00 1A 41 00 0B
0a表示Code Section
长度为 8F 80 80 80 00 , 内容为:01 89 80 80 80 00 00 41 10 10 00 1A 41 00 0B
01表示数量为1,89 80 80 80 00表示size为9,00是locals数量,为0则locals就没有,41 10 10 00 1a 41 00是code,0b是end。
0B 92 80 80 80 00 01 00 41 10 0B 0C 48 65 6C 6C 6F 20 57 6F 72 6C 64 00
0b是Data Section,
长度为92 80 80 80 00,内容为: 01 00 41 10 0B 0C 48 65 6C 6C 6F 20 57 6F 72 6C 64 00
01表示数量为1,00表示在线性内存中的索引为0,41表示iConst.32, 10表示call操作码, 0b表示offset,0c表示参数长度为12,68 65 6c 6c 6f 20 77 6f 72 6c 64 00表示我们打印的内容为hello world 至此,文件解析完毕。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有