编程语言
首页 > 编程语言> > c# – 从.NET JITted代码中解密一行汇编代码需要一些帮助

c# – 从.NET JITted代码中解密一行汇编代码需要一些帮助

作者:互联网

在C#构造函数中,最终调用此(…),实际调用将转换为:

0000003d  call        dword ptr ds:[199B88E8h]

这里的DS寄存器内容是什么?我知道这是数据段,但这是通过VMT表或类似的调用吗?我怀疑它,因为这(…)不会调用虚方法,只是另一个构造函数.

我问,因为该位置的值似乎在某种程度上是坏的,如果我点击F11,跟踪到(Visual Studio 2008),在该调用指令上,程序崩溃并发生访问冲突.

代码深入到第三方控件库中,虽然我有源代码,但我没有使用足够的调试信息编译程序集,我可以通过C#代码跟踪它,只能通过反汇编程序,然后我有将其与实际代码相匹配.

有问题的C#代码是这样的:

public AxisRangeData(AxisRange range) : this(range, range.Axis) {
}

Reflector向我展示了这个IL代码:

.maxstack 8
L_0000: ldarg.0 
L_0001: ldarg.1 
L_0002: ldarg.1 
L_0003: callvirt instance class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis()
L_0008: call instance void DevExpress.XtraCharts.Native.AxisRangeData::.ctor(class DevExpress.XtraCharts.ChartElement, class DevExpress.XtraCharts.AxisBase)
L_000d: ret 

这是最后一次调用那个,同一个类的另一个构造函数,失败了.调试器永远不会在另一个方法内部出现,它只会崩溃.

JITting后方法的反汇编是这样的:

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  sub         esp,14h 
00000006  mov         dword ptr [ebp-4],ecx 
00000009  mov         dword ptr [ebp-8],edx 
0000000c  cmp         dword ptr ds:[18890E24h],0 
00000013  je          0000001A 
00000015  call        61843511 
0000001a  mov         eax,dword ptr [ebp-4] 
0000001d  mov         dword ptr [ebp-0Ch],eax 
00000020  mov         eax,dword ptr [ebp-8] 
00000023  mov         dword ptr [ebp-10h],eax 
00000026  mov         ecx,dword ptr [ebp-8] 
00000029  cmp         dword ptr [ecx],ecx 
0000002b  call        dword ptr ds:[1889D0DCh]   // range.Axis
00000031  mov         dword ptr [ebp-14h],eax 
00000034  push        dword ptr [ebp-14h] 
00000037  mov         edx,dword ptr [ebp-10h] 
0000003a  mov         ecx,dword ptr [ebp-0Ch] 
0000003d  call        dword ptr ds:[199B88E8h]   // this(range, range.Axis)?
00000043  nop              
00000044  mov         esp,ebp 
00000046  pop         ebp  
00000047  ret              

基本上我要问的是:

> ds的目的是什么:[ADDR]间接在这里? VMT表只适用于虚拟不是吗?这是构造函数
>构造函数是否还有JIT,这可能意味着调用实际上是通过JIT垫片调用的?我担心我在这里深水,所以任何事情都可能有所帮助.

编辑:嗯,问题变得更糟,或更好,或其他什么.

我们正在Visual Studio 2008解决方案中的C#项目中开发.NET功能,并通过Visual Studio进行调试和开发.

但是,最后,此代码将加载到由Win32 Delphi应用程序托管的.NET运行时中.

为了便于实现这些功能,我们还可以配置Visual Studio项目/解决方案/调试器将生成的dll复制到Delphi应用程序的目录,然后通过Visual Studio调试器执行Delphi应用程序.

事实证明,如果我在调试器之外运行程序,问题就会消失,但在调试过程中,每次都会出现问题.

不确定是否有帮助,但由于代码不会在6个月左右的时间内用于生产发布,因此我们很快就会为测试版本带来一些压力.

我稍后会深入到记忆部分,但可能要到周末才能进入记忆部分,然后发布后续记录.

解决方法:

数据段是编译器通常将全局变量放入导入地址表所在的位置.

00000029  cmp         dword ptr [ecx],ecx 
0000002b  call        dword ptr ds:[1889D0DCh]

第一行实际上是一个空检查,如果位于ECX寄存器中的指针无效,它最终会引发NullReferenceException.

callvirt MSIL指令必须在调用实际方法之前进行空检查.话虽这么说,我们可以安全地假设这两行汇编代码具有以下MSIL代码表示:

class DevExpress.XtraCharts.AxisBase DevExpress.XtraCharts.AxisRange::get_Axis()

评论汇编代码:

00000026  mov         ecx,dword ptr [ebp-8]      // store the pointer to the 'range' in ECX
00000029  cmp         dword ptr [ecx],ecx        // null-check
0000002b  call        dword ptr ds:[1889D0DCh]   // range.get_Axis()
00000031  mov         dword ptr [ebp-14h],eax    // store the result in a local variable
00000034  push        dword ptr [ebp-14h]        // push the result onto a stack
00000037  mov         edx,dword ptr [ebp-10h]    // this variable was previously loaded with the 'range' pointer
0000003a  mov         ecx,dword ptr [ebp-0Ch]    // here seems to be stored the actual 'this' pointer
0000003d  call        dword ptr ds:[199B88E8h]   // call the this(...) ctor

我不清楚它为什么会崩溃,你是否尝试查找内存位置的内容(DS:[199B88E8h])?

标签:c,assembly,jit,access-violation
来源: https://codeday.me/bug/20190701/1344892.html