dotnet

dotnet

如何在龙芯3B4000上部署基于.Net Core 开发的物联网平台IoTSharp

maikebing 发表了文章 • 0 个评论 • 211 次浏览 • 2020-08-24 18:47 • 来自相关话题

今天很开心的拿到了龙芯的测试服务器账号, 先上图show一下,      双核, 8G内存, 50G硬盘。       架构 mips64el  ...查看全部
今天很开心的拿到了龙芯的测试服务器账号, 先上图show一下, 

 
 
双核, 8G内存, 50G硬盘。
 

 
 
架构 mips64el 
 
 
 
登录后, 显示为 uos 及其网址信息:
 
 
 
 
接下来, 二话不说, 我们开始下载龙芯版的.Net Core , 龙芯版.Net Core 近期刚移植完成, 前期国内其他公众号和开源中国均有报道, 现在, 相关工具链已完成,完全已经达到了开箱即用, 并且已经是.Net Core 3.1.7 是最新版本,相关下载链接如下:
.NET Core 3.1.7 MIPS64 Port Early Access Build 20200819 
 https://github.com/gsvm/loongson-dotnet/releases 
由于IoTSharp 是  基于asp.net core , 因此我们首先下载 它的 安装包, 后期如果尝试在龙芯上开发其他内容, 再尝试sdk。 下载链接如下:
https://github.com/gsvm/loongson-dotnet/releases/download/ea-20200819/aspnetcore-runtime-3.1.7-ea-20200819-linux-loongson3a.tar.gz
github 的下载速度偶尔很快:
 
 
 

下载完成后, 开始解压, 因为 分配的账号并没有/usr/bin 的写权限, 因此, 我们解压在用户目录下, 
tar -xzvf  ./aspnetcore-runtime-3.1.7-ea-20200819-linux-loongson3a.tar.gz  -C  /dn/
cd dn 进入dn目录, 可以看到 相关内容, 下面我们为了方便, 将他加到环境变量, 命令行输入 vi .bashrc , 在末尾  加入下面内容。 
 
[code]export PATH="$PATH://home/loongson/dn/"
[/code]
 
现在, 可以直接在控制台输入 dotnet 方便操作。 当然, 这些都是因为权限问题, 无法修改系统文件导致的。 如果你有root权限, 完全不必这么做 放到/usr/bin 下面了事。 
 
接下来, 我们发布一个IoTSharp 的版本, 发布配置如下:
 
 
 
记得, 一定要是 可移植的, 这样.net 就不会针对平台进行特殊处理!
下面, 开始安装postgresql . 
写到这里, 突然想起 su root  , 然后输入了龙芯给的普通用户的密码, 居然成功切换, 好吧, 这下我们就很顺利了, 
开始安装pgsql 
[code]apt-get install postgresql-11
[/code]
如图:

 
 
 
安装完成
 
 
 
 
按照说明, 我们输入了 
[code] pg_ctlcluster 11 main start
[/code]
启动了数据库, 输入下面的命令切换数据库的系统用户
[code]su postgres
[/code]
执行 psql 修改数据库密码, 输入下面的脚本
[code]ALTER USER postgres WITH PASSWORD 'future';
[/code]
如图所示

 
 
 
 
现在我们开始启动程序, 由于我们拥有了root权限!将.net core 移动到 /usr/bin 中, 将IoTSharp 发布的内容上传到 /var/iotsharp  
接下来, 让我们创建 系统服务, 在当前木目录先创建文件使用命令vi  iotsharp.service  编辑内容如下:
 
[code] 
[/code]
[Unit]
Description=IoTSharp running on loongson


[Service]
WorkingDirectory=/var/iotsharp
ExecStart=/usr/bin/dotnet /var/iotsharp/IoTSharp.dll
Restart=always
# Restart service after 10 seconds if the IoTSharp service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=iotsharp
User=iotsharp
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS="http://0.0.0.0:8080"
[Install]
WantedBy=multi-user.target


 
复制服务文件:
[code]cp  iotsharp.service   /etc/systemd/system/iotsharp.service
[/code]
启用服务
[code] systemctl enable  /etc/systemd/system/iotsharp.service 
[/code]
创建用户 
[code] useradd iotsharp
[/code]
启动服务
[code] systemctl start  iotsharp.service 
[/code]

 
 
由于当前版本默认启动了CapServer 和 ModBus 服务, 由于ModBus的默认502端口在linux下 低于1024 端口, 普通用户使用时有权限问题, 因此  需要加入配置项修改一下appsettings.Production.json , 在尾部加入下面内容, 会将默认的ModBus 端口改为 5020 
1
"ModBusServer"
: { <br>   
"Port"
: 5020,<br>    
"TimeOut"
: 120000  <br>}

  
[code] 
[/code]
使用命令systemctl status  iotsharp.service 查看IoTSharp 项目状态, 截图如下:

 
 
 
至此, 我们搭建完成, 期间务必注意的是 pgsql一定要启动, 一点iotsharp 自动启动, 则通过服务方式重启或者ctl+c 的方式结束似乎都不能实现, 系统重启才行。 
我们的的服务地址是 http://114.242.206.180:23927/  2020年9月20号之前有效。 另外, 可以加入 我们的QQ群 63631741  进一步了解。或者关注公众号

IoTSharp 项目地址
https://github.com/IoTSharp/IoTSharp
https://gitee.com/IoTSharp/IoTSharp

WIP:在龙芯上的尝试编译与测试 dotnet core

回复

leoninew 回复了问题 • 2 人关注 • 2 个回复 • 339 次浏览 • 2020-07-08 15:56 • 来自相关话题

在龙芯上调试CoreCLR

xiangzhai 发表了文章 • 0 个评论 • 407 次浏览 • 2020-07-07 14:35 • 来自相关话题

在龙芯上调试CoreCLR 由于lldb在龙芯上工作不正常[1],只有gdb可以用来调试CoreCLR。 因为需要调试JIT代码,所以我们关上gdb分页,不处理SIG34信号:$ cat ~/.gdbinit ...查看全部
在龙芯上调试CoreCLR

由于lldb在龙芯上工作不正常[1],只有gdb可以用来调试CoreCLR。

因为需要调试JIT代码,所以我们关上gdb分页,不处理SIG34信号:
$ cat ~/.gdbinit
set pagination off
handle SIG34 nostop noprint
调试JIT代码
export CORE_LIBRARIES=/home/loongson/corefx-3.1-Linux.mips64.Debug
export COMPlus_JitFunctionTrace=1
export COMPlus_JitHalt="Main"
gdb -ex=r --args ./bin/Product/Linux.mips64.Debug/corerun /home/loongson/Hello.dll | tee gdb.log
JitHalt="Main"可以在Main方法的序言处插入break指令,然后我们跳过break指令:
(gdb) set $pc+=4
(gdb) x/22i $pc-44
0xff7c983aac: li zero,0x73
0xff7c983ab0: nop
0xff7c983ab4: 0xf20000
0xff7c983ab8: sdc1 $f2,-6100(s6)
0xff7c983abc: dsra32 zero,zero,0x3
0xff7c983ac0: 0x7cc11db8
0xff7c983ac4: dsra32 zero,zero,0x3
0xff7c983ac8: 0x7cc49458
0xff7c983acc: dsra32 zero,zero,0x3
0xff7c983ad0: nop
0xff7c983ad4: break
=> 0xff7c983ad8: daddiu sp,sp,-32
0xff7c983adc: sd s8,0(sp)
0xff7c983ae0: sd ra,8(sp)
0xff7c983ae4: move s8,sp
0xff7c983ae8: sd a0,24(s8)
0xff7c983aec: lui a0,0xff
0xff7c983af0: ori a0,a0,0x7caf
0xff7c983af4: dsll a0,a0,0x10
0xff7c983af8: ori a0,a0,0x7a88
0xff7c983afc: lw a0,0(a0)
0xff7c983b00: sltiu at,a0,1
查看一下传参整型寄存器的值:
(gdb) i r a0
a0: 0xff5800fa28
(gdb) x/g 0xff5800fa28
0xff5800fa28: 0x000000ff7caf7c30
然后用si指令级的单步跟踪。

还可以使用“硬”watchpoint[2]调试GC相关问题:
(gdb) watch *0xff68001bf8
Hardware watchpoint 1: *0xff68001bf8
(gdb) c
Continuing.

...
Thread 1 "corerun" hit Hardware watchpoint 1: *0xff68001bf8

Old value = 0
New value = 1476465840
JIT_WriteBarrier () at /home/loongson/coreclr/src/vm/mips64/asmhelpers.S:206

(gdb) c
Continuing.

...
Thread 1 "corerun" hit Hardware watchpoint 1: *0xff68001bf8

Old value = 1476465840
New value = 1476577368
JIT_WriteBarrier () at /home/loongson/coreclr/src/vm/mips64/asmhelpers.S:206
如何跟踪是“谁”生成的JIT代码?

测试用例:JIT/Methodical/Invoke/thiscall/dbgthisnull/dbgthisnull.exe[3]

加压JIT、GC的时候,该测试用例复现段错误:
export CORE_LIBRARIES=/home/loongson/corefx-3.1-Linux.mips64.Debug
export COMPlus_JitFunctionTrace=1
export COMPlus_JitStress=2
export COMPlus_GCStress=1
export COMPlus_HeapVerify=1
gdb -ex=r --args ./bin/Product/Linux.mips64.Debug/corerun ./bin/tests/Linux.mips64.Debug/JIT/Methodical/Invoke/thiscall/_dbgthisnull/_dbgthisnull.exe | tee gdb.log
我们发现该测试用例“故意”造空指针访存:
Program received signal SIGSEGV, Segmentation fault.
0x000000ff7c985948 in ?? ()
(gdb) x/22i $pc-44
0xff7c98591c: dext a0,a0,0x0,0x8
0xff7c985920: sltiu at,a0,1
0xff7c985924: beqz at,0xff7c985944
0xff7c985928: nop
0xff7c98592c: b 0xff7c98596c
0xff7c985930: nop
0xff7c985934: nop
0xff7c985938: nop
0xff7c98593c: nop
0xff7c985940: nop
0xff7c985944: ld a0,32(s8)
=> 0xff7c985948: ldc1 $f0,8(a0)
0xff7c98594c: sdc1 $f0,24(s8)
0xff7c985950: nop
0xff7c985954: b 0xff7c9859a0
0xff7c985958: nop
0xff7c98595c: nop
0xff7c985960: nop
0xff7c985964: nop
0xff7c985968: nop
0xff7c98596c: bal 0xff7c985974
0xff7c985970: nop
(gdb) i r a0
a0: 0x0
那么ldc1 $f0,8(a0)这条指令是由“谁”生成的呢?
0x000000ff7c985948 in ?? ()
(gdb) x/76i 0x000000ff7c915948-152
0xff7c9158b0: daddiu sp,sp,-48 <-------- CodeGen::genFnProlog -> CodeGen::genAllocLclFrame
0xff7c9158b4: sd s8,0(sp) -> CodeGen::genPushCalleeSavedRegisters
0xff7c9158b8: sd ra,8(sp) -> ...
0xff7c9158bc: move s8,sp
0xff7c9158c0: sd a0,32(s8)
0xff7c9158c4: sw a1,40(s8) <-------- CodeGen::genFnProlog
0xff7c9158c8: lui a0,0xff <----- set_Reg_To_Imm
0xff7c9158cc: ori a0,a0,0x7ca8
0xff7c9158d0: dsll a0,a0,0x10
0xff7c9158d4: ori a0,a0,0x7b50 <----- set_Reg_To_Imm end
0xff7c9158d8: lw a0,0(a0)
0xff7c9158dc: sltiu at,a0,1 <---------- CodeGen::genCodeForCompare
0xff7c9158e0: beqz at,0xff7c915900
0xff7c9158e4: nop
0xff7c9158e8: b 0xff7c915918
0xff7c9158ec: nop
0xff7c9158f0: nop
0xff7c9158f4: nop
0xff7c9158f8: nop
0xff7c9158fc: nop <----------- CodeGen::genCodeForCompare
0xff7c915900: lui a0,0xff
0xff7c915904: ori a0,a0,0xf6a0
0xff7c915908: dsll a0,a0,0x10
0xff7c91590c: ori a0,a0,0x8fa8
0xff7c915910: jalr a0
0xff7c915914: move t9,a0
0xff7c915918: lw a0,40(s8)
0xff7c91591c: dext a0,a0,0x0,0x8
0xff7c915920: sltiu at,a0,1 <---------- CodeGen::genCodeForCompare
0xff7c915924: beqz at,0xff7c915944
0xff7c915928: nop
0xff7c91592c: b 0xff7c91596c
0xff7c915930: nop
0xff7c915934: nop
0xff7c915938: nop
0xff7c91593c: nop
0xff7c915940: nop <----------- CodeGen::genCodeForCompare
0xff7c915944: ld a0,32(s8)
=> 0xff7c915948: ldc1 $f0,8(a0)
0xff7c91594c: sdc1 $f0,24(s8)
0xff7c915950: nop
0xff7c915954: b 0xff7c9159a0
0xff7c915958: nop
0xff7c91595c: nop
0xff7c915960: nop
0xff7c915964: nop
0xff7c915968: nop
0xff7c91596c: bal 0xff7c915974
0xff7c915970: nop
0xff7c915974: li at,0x44
0xff7c915978: daddu a0,at,ra
0xff7c91597c: ldc1 $f0,0(a0)
0xff7c915980: sdc1 $f0,24(s8)
0xff7c915984: nop
0xff7c915988: b 0xff7c9159a0
0xff7c91598c: nop
0xff7c915990: nop
0xff7c915994: nop
0xff7c915998: nop
0xff7c91599c: nop
0xff7c9159a0: ldc1 $f0,24(s8)
0xff7c9159a4: ld ra,8(sp) <---------- CodeGen::genFnEpilog -> CodeGen::genPopCalleeSavedRegisters
0xff7c9159a8: ld s8,0(sp) -> ...
0xff7c9159ac: daddiu sp,sp,48
0xff7c9159b0: jr ra
0xff7c9159b4: nop <---------- CodeGen::genFnEpilog
...
ldc1 $f0,8(a0)是由emitter::emitInsLoadStoreOp和emitter::emitIns_R_R_I生成。你可以“故意”修改src/jit/codegenmips64.cpp[4]的CodeGen::genCodeForIndir,添加冗余的nop指令:
diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp
index ef18106..465bc17 100644
--- a/src/jit/codegenmips64.cpp
+++ b/src/jit/codegenmips64.cpp
@@ -8290,6 +8290,7 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree)
}

getEmitter()->emitInsLoadStoreOp(ins, emitActualTypeSize(type), targetReg, tree);
+ instGen(INS_nop);

if (emitBarrier)
{
重新编译,就可以看到“故意”生成的冗余nop指令:
(gdb) x/22i $pc-44
0xff7c936560: dext a0,a0,0x0,0x8
0xff7c936564: sltiu at,a0,1
0xff7c936568: beqz at,0xff7c936588
0xff7c93656c: nop
0xff7c936570: b 0xff7c9365b4
0xff7c936574: nop
0xff7c936578: nop
0xff7c93657c: nop
0xff7c936580: nop
0xff7c936584: nop
0xff7c936588: ld a0,32(s8)
=> 0xff7c93658c: ldc1 $f0,8(a0)
=> 0xff7c936590: nop
0xff7c936594: sdc1 $f0,24(s8)
0xff7c936598: nop
0xff7c93659c: b 0xff7c9365e8
0xff7c9365a0: nop
0xff7c9365a4: nop
0xff7c9365a8: nop
0xff7c9365ac: nop
0xff7c9365b0: nop
0xff7c9365b4: bal 0xff7c9365bc
0xff7c9365b8: nop
还可以通过grep ldc1 -rn src/jit/来了解访存相关的代码生成。因为ldc1    $f0,8(a0)属于RRI指令形式,所以可以在emitter::emitIns_R_R_I“故意”加入断言:
diff --git a/src/jit/emitmips64.cpp b/src/jit/emitmips64.cpp
index 06b574d..9d19a52 100644
--- a/src/jit/emitmips64.cpp
+++ b/src/jit/emitmips64.cpp
@@ -2513,6 +2513,7 @@ void emitter::emitIns_R_R_I(
assert((-32768 <= imm) && (imm <= 32767));
assert(isFloatReg(reg1));
assert(isGeneralRegisterOrR0(reg2));
+ assert(imm != 8 && reg1 != REG_F0 && reg2 != REG_A0);
break;

case INS_c_f_s:
gdb bt一下就能知道具体的函数(例如:emitter::emitInsLoadStoreOp)以及行数。

1. https://github.com/dotnet/runtime/issues/37405
2. https://hev.cc/2758.html
3. https://github.com/gsvm/coreclr/blob/mips64-port/tests/src/JIT/Methodical/Invoke/thiscall/_dbgthisnull.ilproj
4. https://github.com/gsvm/coreclr/blob/mips64-port/src/jit/codegenmips64.cpp

WIP:在龙芯上的尝试编译与测试 dotnet core

回复

leoninew 回复了问题 • 2 人关注 • 2 个回复 • 339 次浏览 • 2020-07-08 15:56 • 来自相关话题

如何在龙芯3B4000上部署基于.Net Core 开发的物联网平台IoTSharp

maikebing 发表了文章 • 0 个评论 • 211 次浏览 • 2020-08-24 18:47 • 来自相关话题

今天很开心的拿到了龙芯的测试服务器账号, 先上图show一下,      双核, 8G内存, 50G硬盘。       架构 mips64el  ...查看全部
今天很开心的拿到了龙芯的测试服务器账号, 先上图show一下, 

 
 
双核, 8G内存, 50G硬盘。
 

 
 
架构 mips64el 
 
 
 
登录后, 显示为 uos 及其网址信息:
 
 
 
 
接下来, 二话不说, 我们开始下载龙芯版的.Net Core , 龙芯版.Net Core 近期刚移植完成, 前期国内其他公众号和开源中国均有报道, 现在, 相关工具链已完成,完全已经达到了开箱即用, 并且已经是.Net Core 3.1.7 是最新版本,相关下载链接如下:
.NET Core 3.1.7 MIPS64 Port Early Access Build 20200819 
 https://github.com/gsvm/loongson-dotnet/releases 
由于IoTSharp 是  基于asp.net core , 因此我们首先下载 它的 安装包, 后期如果尝试在龙芯上开发其他内容, 再尝试sdk。 下载链接如下:
https://github.com/gsvm/loongson-dotnet/releases/download/ea-20200819/aspnetcore-runtime-3.1.7-ea-20200819-linux-loongson3a.tar.gz
github 的下载速度偶尔很快:
 
 
 

下载完成后, 开始解压, 因为 分配的账号并没有/usr/bin 的写权限, 因此, 我们解压在用户目录下, 
tar -xzvf  ./aspnetcore-runtime-3.1.7-ea-20200819-linux-loongson3a.tar.gz  -C  /dn/
cd dn 进入dn目录, 可以看到 相关内容, 下面我们为了方便, 将他加到环境变量, 命令行输入 vi .bashrc , 在末尾  加入下面内容。 
 
[code]export PATH="$PATH://home/loongson/dn/"
[/code]
 
现在, 可以直接在控制台输入 dotnet 方便操作。 当然, 这些都是因为权限问题, 无法修改系统文件导致的。 如果你有root权限, 完全不必这么做 放到/usr/bin 下面了事。 
 
接下来, 我们发布一个IoTSharp 的版本, 发布配置如下:
 
 
 
记得, 一定要是 可移植的, 这样.net 就不会针对平台进行特殊处理!
下面, 开始安装postgresql . 
写到这里, 突然想起 su root  , 然后输入了龙芯给的普通用户的密码, 居然成功切换, 好吧, 这下我们就很顺利了, 
开始安装pgsql 
[code]apt-get install postgresql-11
[/code]
如图:

 
 
 
安装完成
 
 
 
 
按照说明, 我们输入了 
[code] pg_ctlcluster 11 main start
[/code]
启动了数据库, 输入下面的命令切换数据库的系统用户
[code]su postgres
[/code]
执行 psql 修改数据库密码, 输入下面的脚本
[code]ALTER USER postgres WITH PASSWORD 'future';
[/code]
如图所示

 
 
 
 
现在我们开始启动程序, 由于我们拥有了root权限!将.net core 移动到 /usr/bin 中, 将IoTSharp 发布的内容上传到 /var/iotsharp  
接下来, 让我们创建 系统服务, 在当前木目录先创建文件使用命令vi  iotsharp.service  编辑内容如下:
 
[code] 
[/code]
[Unit]
Description=IoTSharp running on loongson


[Service]
WorkingDirectory=/var/iotsharp
ExecStart=/usr/bin/dotnet /var/iotsharp/IoTSharp.dll
Restart=always
# Restart service after 10 seconds if the IoTSharp service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=iotsharp
User=iotsharp
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
Environment=ASPNETCORE_URLS="http://0.0.0.0:8080"
[Install]
WantedBy=multi-user.target


 
复制服务文件:
[code]cp  iotsharp.service   /etc/systemd/system/iotsharp.service
[/code]
启用服务
[code] systemctl enable  /etc/systemd/system/iotsharp.service 
[/code]
创建用户 
[code] useradd iotsharp
[/code]
启动服务
[code] systemctl start  iotsharp.service 
[/code]

 
 
由于当前版本默认启动了CapServer 和 ModBus 服务, 由于ModBus的默认502端口在linux下 低于1024 端口, 普通用户使用时有权限问题, 因此  需要加入配置项修改一下appsettings.Production.json , 在尾部加入下面内容, 会将默认的ModBus 端口改为 5020 
1
"ModBusServer"
: { <br>   
"Port"
: 5020,<br>    
"TimeOut"
: 120000  <br>}

  
[code] 
[/code]
使用命令systemctl status  iotsharp.service 查看IoTSharp 项目状态, 截图如下:

 
 
 
至此, 我们搭建完成, 期间务必注意的是 pgsql一定要启动, 一点iotsharp 自动启动, 则通过服务方式重启或者ctl+c 的方式结束似乎都不能实现, 系统重启才行。 
我们的的服务地址是 http://114.242.206.180:23927/  2020年9月20号之前有效。 另外, 可以加入 我们的QQ群 63631741  进一步了解。或者关注公众号

IoTSharp 项目地址
https://github.com/IoTSharp/IoTSharp
https://gitee.com/IoTSharp/IoTSharp

在龙芯上调试CoreCLR

xiangzhai 发表了文章 • 0 个评论 • 407 次浏览 • 2020-07-07 14:35 • 来自相关话题

在龙芯上调试CoreCLR 由于lldb在龙芯上工作不正常[1],只有gdb可以用来调试CoreCLR。 因为需要调试JIT代码,所以我们关上gdb分页,不处理SIG34信号:$ cat ~/.gdbinit ...查看全部
在龙芯上调试CoreCLR

由于lldb在龙芯上工作不正常[1],只有gdb可以用来调试CoreCLR。

因为需要调试JIT代码,所以我们关上gdb分页,不处理SIG34信号:
$ cat ~/.gdbinit
set pagination off
handle SIG34 nostop noprint
调试JIT代码
export CORE_LIBRARIES=/home/loongson/corefx-3.1-Linux.mips64.Debug
export COMPlus_JitFunctionTrace=1
export COMPlus_JitHalt="Main"
gdb -ex=r --args ./bin/Product/Linux.mips64.Debug/corerun /home/loongson/Hello.dll | tee gdb.log
JitHalt="Main"可以在Main方法的序言处插入break指令,然后我们跳过break指令:
(gdb) set $pc+=4
(gdb) x/22i $pc-44
0xff7c983aac: li zero,0x73
0xff7c983ab0: nop
0xff7c983ab4: 0xf20000
0xff7c983ab8: sdc1 $f2,-6100(s6)
0xff7c983abc: dsra32 zero,zero,0x3
0xff7c983ac0: 0x7cc11db8
0xff7c983ac4: dsra32 zero,zero,0x3
0xff7c983ac8: 0x7cc49458
0xff7c983acc: dsra32 zero,zero,0x3
0xff7c983ad0: nop
0xff7c983ad4: break
=> 0xff7c983ad8: daddiu sp,sp,-32
0xff7c983adc: sd s8,0(sp)
0xff7c983ae0: sd ra,8(sp)
0xff7c983ae4: move s8,sp
0xff7c983ae8: sd a0,24(s8)
0xff7c983aec: lui a0,0xff
0xff7c983af0: ori a0,a0,0x7caf
0xff7c983af4: dsll a0,a0,0x10
0xff7c983af8: ori a0,a0,0x7a88
0xff7c983afc: lw a0,0(a0)
0xff7c983b00: sltiu at,a0,1
查看一下传参整型寄存器的值:
(gdb) i r a0
a0: 0xff5800fa28
(gdb) x/g 0xff5800fa28
0xff5800fa28: 0x000000ff7caf7c30
然后用si指令级的单步跟踪。

还可以使用“硬”watchpoint[2]调试GC相关问题:
(gdb) watch *0xff68001bf8
Hardware watchpoint 1: *0xff68001bf8
(gdb) c
Continuing.

...
Thread 1 "corerun" hit Hardware watchpoint 1: *0xff68001bf8

Old value = 0
New value = 1476465840
JIT_WriteBarrier () at /home/loongson/coreclr/src/vm/mips64/asmhelpers.S:206

(gdb) c
Continuing.

...
Thread 1 "corerun" hit Hardware watchpoint 1: *0xff68001bf8

Old value = 1476465840
New value = 1476577368
JIT_WriteBarrier () at /home/loongson/coreclr/src/vm/mips64/asmhelpers.S:206
如何跟踪是“谁”生成的JIT代码?

测试用例:JIT/Methodical/Invoke/thiscall/dbgthisnull/dbgthisnull.exe[3]

加压JIT、GC的时候,该测试用例复现段错误:
export CORE_LIBRARIES=/home/loongson/corefx-3.1-Linux.mips64.Debug
export COMPlus_JitFunctionTrace=1
export COMPlus_JitStress=2
export COMPlus_GCStress=1
export COMPlus_HeapVerify=1
gdb -ex=r --args ./bin/Product/Linux.mips64.Debug/corerun ./bin/tests/Linux.mips64.Debug/JIT/Methodical/Invoke/thiscall/_dbgthisnull/_dbgthisnull.exe | tee gdb.log
我们发现该测试用例“故意”造空指针访存:
Program received signal SIGSEGV, Segmentation fault.
0x000000ff7c985948 in ?? ()
(gdb) x/22i $pc-44
0xff7c98591c: dext a0,a0,0x0,0x8
0xff7c985920: sltiu at,a0,1
0xff7c985924: beqz at,0xff7c985944
0xff7c985928: nop
0xff7c98592c: b 0xff7c98596c
0xff7c985930: nop
0xff7c985934: nop
0xff7c985938: nop
0xff7c98593c: nop
0xff7c985940: nop
0xff7c985944: ld a0,32(s8)
=> 0xff7c985948: ldc1 $f0,8(a0)
0xff7c98594c: sdc1 $f0,24(s8)
0xff7c985950: nop
0xff7c985954: b 0xff7c9859a0
0xff7c985958: nop
0xff7c98595c: nop
0xff7c985960: nop
0xff7c985964: nop
0xff7c985968: nop
0xff7c98596c: bal 0xff7c985974
0xff7c985970: nop
(gdb) i r a0
a0: 0x0
那么ldc1 $f0,8(a0)这条指令是由“谁”生成的呢?
0x000000ff7c985948 in ?? ()
(gdb) x/76i 0x000000ff7c915948-152
0xff7c9158b0: daddiu sp,sp,-48 <-------- CodeGen::genFnProlog -> CodeGen::genAllocLclFrame
0xff7c9158b4: sd s8,0(sp) -> CodeGen::genPushCalleeSavedRegisters
0xff7c9158b8: sd ra,8(sp) -> ...
0xff7c9158bc: move s8,sp
0xff7c9158c0: sd a0,32(s8)
0xff7c9158c4: sw a1,40(s8) <-------- CodeGen::genFnProlog
0xff7c9158c8: lui a0,0xff <----- set_Reg_To_Imm
0xff7c9158cc: ori a0,a0,0x7ca8
0xff7c9158d0: dsll a0,a0,0x10
0xff7c9158d4: ori a0,a0,0x7b50 <----- set_Reg_To_Imm end
0xff7c9158d8: lw a0,0(a0)
0xff7c9158dc: sltiu at,a0,1 <---------- CodeGen::genCodeForCompare
0xff7c9158e0: beqz at,0xff7c915900
0xff7c9158e4: nop
0xff7c9158e8: b 0xff7c915918
0xff7c9158ec: nop
0xff7c9158f0: nop
0xff7c9158f4: nop
0xff7c9158f8: nop
0xff7c9158fc: nop <----------- CodeGen::genCodeForCompare
0xff7c915900: lui a0,0xff
0xff7c915904: ori a0,a0,0xf6a0
0xff7c915908: dsll a0,a0,0x10
0xff7c91590c: ori a0,a0,0x8fa8
0xff7c915910: jalr a0
0xff7c915914: move t9,a0
0xff7c915918: lw a0,40(s8)
0xff7c91591c: dext a0,a0,0x0,0x8
0xff7c915920: sltiu at,a0,1 <---------- CodeGen::genCodeForCompare
0xff7c915924: beqz at,0xff7c915944
0xff7c915928: nop
0xff7c91592c: b 0xff7c91596c
0xff7c915930: nop
0xff7c915934: nop
0xff7c915938: nop
0xff7c91593c: nop
0xff7c915940: nop <----------- CodeGen::genCodeForCompare
0xff7c915944: ld a0,32(s8)
=> 0xff7c915948: ldc1 $f0,8(a0)
0xff7c91594c: sdc1 $f0,24(s8)
0xff7c915950: nop
0xff7c915954: b 0xff7c9159a0
0xff7c915958: nop
0xff7c91595c: nop
0xff7c915960: nop
0xff7c915964: nop
0xff7c915968: nop
0xff7c91596c: bal 0xff7c915974
0xff7c915970: nop
0xff7c915974: li at,0x44
0xff7c915978: daddu a0,at,ra
0xff7c91597c: ldc1 $f0,0(a0)
0xff7c915980: sdc1 $f0,24(s8)
0xff7c915984: nop
0xff7c915988: b 0xff7c9159a0
0xff7c91598c: nop
0xff7c915990: nop
0xff7c915994: nop
0xff7c915998: nop
0xff7c91599c: nop
0xff7c9159a0: ldc1 $f0,24(s8)
0xff7c9159a4: ld ra,8(sp) <---------- CodeGen::genFnEpilog -> CodeGen::genPopCalleeSavedRegisters
0xff7c9159a8: ld s8,0(sp) -> ...
0xff7c9159ac: daddiu sp,sp,48
0xff7c9159b0: jr ra
0xff7c9159b4: nop <---------- CodeGen::genFnEpilog
...
ldc1 $f0,8(a0)是由emitter::emitInsLoadStoreOp和emitter::emitIns_R_R_I生成。你可以“故意”修改src/jit/codegenmips64.cpp[4]的CodeGen::genCodeForIndir,添加冗余的nop指令:
diff --git a/src/jit/codegenmips64.cpp b/src/jit/codegenmips64.cpp
index ef18106..465bc17 100644
--- a/src/jit/codegenmips64.cpp
+++ b/src/jit/codegenmips64.cpp
@@ -8290,6 +8290,7 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree)
}

getEmitter()->emitInsLoadStoreOp(ins, emitActualTypeSize(type), targetReg, tree);
+ instGen(INS_nop);

if (emitBarrier)
{
重新编译,就可以看到“故意”生成的冗余nop指令:
(gdb) x/22i $pc-44
0xff7c936560: dext a0,a0,0x0,0x8
0xff7c936564: sltiu at,a0,1
0xff7c936568: beqz at,0xff7c936588
0xff7c93656c: nop
0xff7c936570: b 0xff7c9365b4
0xff7c936574: nop
0xff7c936578: nop
0xff7c93657c: nop
0xff7c936580: nop
0xff7c936584: nop
0xff7c936588: ld a0,32(s8)
=> 0xff7c93658c: ldc1 $f0,8(a0)
=> 0xff7c936590: nop
0xff7c936594: sdc1 $f0,24(s8)
0xff7c936598: nop
0xff7c93659c: b 0xff7c9365e8
0xff7c9365a0: nop
0xff7c9365a4: nop
0xff7c9365a8: nop
0xff7c9365ac: nop
0xff7c9365b0: nop
0xff7c9365b4: bal 0xff7c9365bc
0xff7c9365b8: nop
还可以通过grep ldc1 -rn src/jit/来了解访存相关的代码生成。因为ldc1    $f0,8(a0)属于RRI指令形式,所以可以在emitter::emitIns_R_R_I“故意”加入断言:
diff --git a/src/jit/emitmips64.cpp b/src/jit/emitmips64.cpp
index 06b574d..9d19a52 100644
--- a/src/jit/emitmips64.cpp
+++ b/src/jit/emitmips64.cpp
@@ -2513,6 +2513,7 @@ void emitter::emitIns_R_R_I(
assert((-32768 <= imm) && (imm <= 32767));
assert(isFloatReg(reg1));
assert(isGeneralRegisterOrR0(reg2));
+ assert(imm != 8 && reg1 != REG_F0 && reg2 != REG_A0);
break;

case INS_c_f_s:
gdb bt一下就能知道具体的函数(例如:emitter::emitInsLoadStoreOp)以及行数。

1. https://github.com/dotnet/runtime/issues/37405
2. https://hev.cc/2758.html
3. https://github.com/gsvm/coreclr/blob/mips64-port/tests/src/JIT/Methodical/Invoke/thiscall/_dbgthisnull.ilproj
4. https://github.com/gsvm/coreclr/blob/mips64-port/src/jit/codegenmips64.cpp