.Net JIT支持的Risc-V/La/Arm
创始人
2025-07-02 19:51:12
0

1.前言

.Net CLR主线合并的部分Risc-v,龙芯,ARM代码。当然ARM一直是主力支持的,这里主要是Risc-V和龙芯。通过UnwindCode看下。

2.概述

UnwindCode这个东西,主要是通过一些二进制代码描述一些机器码含义,然后对其进行相应的操作。
我们通过lldb来看下这些操作的内容:

(lldb) b RunMainInternal
(lldb) r
(lldb) b allocUnwindInfo
(lldb) c
(lldb) source info
(lldb) b jitinterface.cpp:11232
(lldb) c

内容如下:

lldb) c
Process 58851 resuming
Process 58851 stopped
* thread #1, name = 'clrrun', stop reason = breakpoint 6.1
    frame #0: 0x00007ffff6e676c7 libcoreclr.so`CEEJitInfo::allocUnwindInfo(this=0x00007fffffffaf70, pHotCode="UH\x83\xecPH\x8dl$P\xc4A8W\xc0\xc5y\U0000007fE\xc0\xc5y\U0000007fE\xd0\xc5y\U0000007fE\xe03\xc0H\x89E\xf0H\x89}\xf8\x83=\xa9\xf3\U0000001d", pColdCode=0x0000000000000000, startOffset=0, endOffset=395, unwindSize=8, pUnwindBlock="\U00000001\U00000005\U00000002", funcKind=CORJIT_FUNC_ROOT) at jitinterface.cpp:11232:5
   11229      }
   11230  #endif // _DEBUG
   11231  
-> 11232      memcpy(pUnwindInfoRW, pUnwindBlock, unwindSize);

我们看到它是一个memcpy的赋值。看下pUnwindInfoRW里面是什么

(lldb) n
(lldb) p/x *pUnwindInfoRW
(UNWIND_INFO) $6 = {
  Version = 0x01
  Flags = 0x00
  SizeOfProlog = 0x05
  CountOfUnwindCodes = 0x02
  FrameRegister = 0x00
  FrameOffset = 0x00
  UnwindCode = {
    [0] = {
       = (CodeOffset = 0x05, UnwindOp = 0x02, OpInfo = 0x09)
      EpilogueCode = (OffsetLow = 0x05, UnwindOp = 0x02, OffsetHigh = 0x09)
      FrameOffset = 0x9205
    }
  }
}

CountOfUnwindCodes表示总共有两个UnwindCode。

下面是UnwindCode成员意义:
CodeOffset表示机器码的长度。UnwindOp表示对是枚举类型_UNWIND_OP_CODES,表示机器码指令,比如UWOP_ALLOC_SMALL表示分配小对象栈空间(sub指令),UWOP_PUSH_NONVOL(push指令)。OpInfo则表示机器操作数。
看下两个UnwindCode的结构

(lldb) p/x pUnwindInfoRW->UnwindCode[0]
(UNWIND_CODE) $12 = {
   = (CodeOffset = 0x05, UnwindOp = 0x02, OpInfo = 0x09)
  EpilogueCode = (OffsetLow = 0x05, UnwindOp = 0x02, OffsetHigh = 0x09)
  FrameOffset = 0x9205
}
(lldb) p/x pUnwindInfoRW->UnwindCode[1]
(UNWIND_CODE) $13 = {
   = (CodeOffset = 0x01, UnwindOp = 0x00, OpInfo = 0x05)
  EpilogueCode = (OffsetLow = 0x01, UnwindOp = 0x00, OffsetHigh = 0x05)
  FrameOffset = 0x5001
}
(lldb) p/x pUnwindInfoRW->UnwindCode[2]
(UNWIND_CODE) $14 = {
   = (CodeOffset = 0x00, UnwindOp = 0x00, OpInfo = 0x00)
  EpilogueCode = (OffsetLow = 0x00, UnwindOp = 0x00, OffsetHigh = 0x00)
  FrameOffset = 0x0000
}

第三个索引它就为零,确实是是两个。它的Unwindop分别是0x02和0x00.这分别代表了:UWOP_ALLOC_SMALL和UWOP_PUSH_NONVOL.也即机器码:sub和push。它的OpInfo分别为:0x09和0x05。分别代表了操作机器码:8* 9+8以及rbp。

OpInfo

if (OpInfo == kRBP)

那么这个指令就很明显了

push rbp
sub  rsp_80

OK,以上是UnwindCode解析,下面来看下UnwindCode对于Risc-V和龙芯的这次hi。

Risc-v和龙芯

在它进行赋值完成之后,也即是:

memcpy(pUnwindInfoRW, pUnwindBlock, unwindSize);

它总共有五个target,也就是指令集,分别为:amd64,arm64/arm,la64,riscv64

#elif defined(TARGET_AMD64)
    pUnwindInfoRW->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER;
#elif defined(TARGET_ARM64)
    *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit
#elif defined(TARGET_ARM)
    *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit
#elif defined(TARGET_LOONGARCH64)
    *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit
#elif defined(TARGET_RISCV64)
    *(LONG *)pUnwindInfoRW |= (1 << 20); // X bit
#endif

我们看到.Net的主线当中支持的Risc-v和La64,这里和x64的区别就在于,x64是pUnwindInfoRW的flag是或上

UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER;

而其他的三个则是:

*(LONG *)pUnwindInfoRW |= (1 << 20);

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...