author: xiongxiao ([email protected]), jiayy ([email protected])
LoongArch
目前世界上主要的指令集架构有 MIPS, X86, Power, Alpha, ARM 等,除了 ARM 是英国的其余都是美国的。国内的芯片厂商龙芯,君正,兆芯,海光,申威,飞腾,海思,展讯,华芯通等购买相应授权并开发相应芯片产品,这就是目前芯片市场的情况,可以说脖子被卡得死死的。
2021.04.30,龙芯自主指令系统LoongArch基础架构手册正式发布 ,号称从顶层架构,到指令功能和 ABI 标准等,全部自主设计,不需国外授权。2021.07.23, 基于自主指令集 LA 架构的 新一代处理器龙芯3A5000正式发布 ,据称 spec 2006评分达到26分,接近30分的一代锐龙。
我们小组及时跟进研究了 LA 的手册,并在 3A5000 设备上开发了相应的产品。在这过程中发现网上对这一新生事物缺乏资料(除了官方的),遂写了本篇小记。
inline Hook
其中一个任务是实现 LA 上的 inline hook 。指令手册主要参考:
- 第二章 基础整数指令, 解释指令格式和功能
- 附录B 指令码一览, 指令的二进制编码方式
寄存器
1 | 基础整数指令涉及的寄存器包括通用寄存器(General-purpose Register,简称 GR) 和 程序记数寄存器(Program Counter,简称PC) |
补充:
根据LoongArch ABI,寄存器功能的更细的划分如下:
1 | R0 : 永 远 为0 |
指令
这里通过BEQ指令说明如何查询手册,快速获得这条指令相关的信息
1 | 在附录中可以找到指令的编码 |
伪代码中 SignExtend(offs16, 2’b0}, GRLEN) 的含义是offs16 左移两位,然后符号扩展到GRLEN(LA64下 即64位)
关于符号扩展Wiki,C实现如下:
1 | // 依赖 >> 符号本身就是符号扩展的特性,可以简单实现为 |
PC 相对寻址指令替换
inline hook 的主要工作之一就是修复这类指令,即计算出正确的地址,然后通过其他指令替换
LoongArch64 中的PC相对寻址指令如下:
算数运算指令
1 | PCADDI rd, si20 | 0 0 0 1 1 0 0 si20 rd |
转移指令
1 | BEQZ rj, offs | 0 1 0 0 0 0 offs[15:0] rj offs[20:16] |
对这两类的指令替换方案如下:
1 | pcaddi [target_reg], si20 替换为: |
1 | b offs 替换为: |
r1寄存器
有时函数栈的切换不会把返回值压栈,而是直接使用r1寄存器
经测试,当一个函数没有调用子函数的时候,不会把 r1 压栈
开启gcc 编译优化也会省去压栈操作
1 | // main.c |
1 | $ gcc main.c -g |
1 | $ gcc main.c -O2 -g |
用户态Hook
简单实现,不处理pc相对寻址的情况
1 |
|
内核态Hook
我们实现了完整的处理各种异常条件的内核 LA inlineHook, 暂不公开
反汇编器
有LoongArch64 机器的情况下,直接用gdb就可以做到
用一个简单的脚本实现:
1 | #!/usr/bin/env python3 |
效果如下:
1 | $ ./t.py |
在没有 LoongArch64 机器的情况下,需要用软件(反汇编器)实现 LA 指令的反汇编,为了达到这个目的,我们正在开发支持 LA 的反汇编器,后续合适的时机可能会公开。