首页 > 其他分享 >.Net7运行模型之托管Main函数的调用

.Net7运行模型之托管Main函数的调用

时间:2023-02-06 09:00:29浏览次数:36  
标签:调用 函数 托管 coreclr C++ dll Net7 Main

前言:

.Net7的CLR最具特色的一个地方,就是运行模型。因为它主宰了整个CLR的运行过程。

又因为其庞大的代码量,有的几十万行甚至百万行。所以理解起来非常不容易。本篇拆分来看下,里面一个细节Main函数(注意这里的Main指的是托管Main,因为还有非托管main,所以特别指出下以免混淆)是如何被CLR调用的。



概括

Main函数的调用,基本上是最后才会被CLR引擎所调用。为啥?因为,如果.Net标准类库,以及底层的非托管C++类库没有在Main函数被调用之前,加载完成,那么你强行调用Main函数就会出错。

我们可以在Windows/Linux平台通过Windbg或者是LLDB来看下托管的Main函数的堆栈

00007ff7f55703b0
coreclr.dll!CallDescrWorkerInternal	
coreclr.dll!CallDescrWorkerWithHandler
coreclr.dll!MethodDescCallSite::CallTargetWorker
coreclr.dll!MethodDescCallSite::Call	C++
coreclr.dll!RunMainInternal	C++
coreclr.dll!``RunMain'::`30'
coreclr.dll!`RunMain'::`30'
coreclr.dll!RunMain	C++
coreclr.dll!Assembly::ExecuteMainMethod
coreclr.dll!CorHost2::ExecuteAssembly
coreclr.dll!coreclr_execute_assembly	C++
corerun.exe!run	C++
corerun.exe!wmain	C++
corerun.exe!invoke_main	C++
corerun.exe!__scrt_common_main_seh	C++
corerun.exe!__scrt_common_main	C++
corerun.exe!wmainCRTStartup	C++
kernel32.dll!BaseThreadInitThunk
ntdll.dll!RtlUserThreadStart

这个堆栈里面我们可以得出很多的信息:
比如:
1.最上面的地址:00007ff7f55703b0是.Net里面的托管Main函数的入口地址。
2.整个程序的运行最开始的代码是ntdll.dll模块里面的RtlUserThreadStart函数。
3.非托管的CLR的入口是wmain函数。


有了以上的信息,我们很容易分析到。托管的Main函数调用是在程序集的ExecuteMainMethod函数里面调用RunMain这个函数,整个函数的名字一看就知道是运行Main函数的。

此后通过CallDescrWorkerInternal来调用RyuJIT编译MSIL代码为机器码。返回到托管Main函数的开头地址。
也就是上面的这个地址:00007ff7f55703b0



分析:

这个过程看似分析非常简单,但是实际上会遇到很多问题。但是如果你只用单一的调试器,比如只用Windbg。你可能完全看不出来以下这些问题。

比如你在调试.Ctor,也就是.Net 7里面默认的构造函数的时候。如果在VS上Debug CLR上面,如果进入到托管Main的机器码当中,运行到.Ctor的机器码的地方。它会报一个不是错误的错误,而跟踪下来居然是MapViewOfFile这个微软的官方函数的错误,关于这一点可以看这里,之前写的一篇文章:点击这里查看之前文章

而另外如果你在Linux上面用LLDB调试的时候,会发现托管的Main入口断点可能会进不去的情况。

当然这些类似Bug但可能不是Bug东西,需要深厚的功力去发现和验证它到底是啥。



结尾:

作者:江湖评谈

欢迎关注我,带你了解.Net7的CLR的各种奇巧淫技。让.Net7,甚至后面的.Net8,9,10。在你面前毫无神秘可言。
image

标签:调用,函数,托管,coreclr,C++,dll,Net7,Main
From: https://www.cnblogs.com/tangyanzhi1111/p/17094349.html

相关文章

  • 迁移学习(HDAN)《Heuristic Domain Adaptation》
    论文信息论文标题:HeuristicDomainAdaptation论文作者:ShuhaoCui,XuanJin,ShuhuiWang,YuanHe,QingmingHuang论文来源:NeurIPS2020论文地址:download 论文代码:do......
  • 1.5 函数的调用机制
    函数调用处理是通过把程序计数器的值设定成函数的储存地址来实现的,哪怕是高级语言编写的程序。哪怕是高级语言编写的程序,函数”调用处理也是通过把程序计数器的值设定成函......
  • [rk3568][buildroot] 移除RK3568 iodomain check
    1.问题背景RK3568基线代码默认会起一个服务监控RK3568iodomain,该服务间隔性输出log信息;由于该功能非必要,故选择移除该部分逻辑2.解决方案查看源码编译脚本,如下图所......
  • 【测试】JMeter接口调用衔接
    在压力测试的过程中我们可以通过新建解析器来使接口数据衔接到下一个接口已达到更准确的测试效果。首先新建一个JSONExtractor,通过JSONExtractor来解析返回数据获取需要......
  • 03 回顾方法的调用
    回顾方法的调用packagecom.zhan.base05Oop;publicclassTest03{//回顾方法的调用publicstaticvoidmain(String[]args){//静态方法stat......
  • QMainWindow简介
        QMainWindow是带有菜单栏、工具栏、状态栏的主窗口类,它有自己单独的布局。布局有一个中心区域,通常是标准的Qt部件,也可以是定制部件,且必须有一个中心小部件。set......
  • 【一句话】中间件调用顺序
    洋葱模型koaapp.use按顺序注册中间件,然后依次next调用自己的下一个中间件,awaitnext之后,整个的调用路径就像一个洋葱一样,从皮走到心,再从心走到皮除了koa之外很多带中......
  • QML调用C++的三种方法
    1.注册法由于QML引擎与Qt元对象系统的紧密集成,可以从QML代码访问由QObject派生的类适当公开的任何功能。这使得C++类的属性和方法可以直接从QML访问,通常很少或无需修改。......
  • Qml调用C++方法初探
    为什么会在QML中调用C++方法?引入Qml的一个重要目的就是UI和逻辑的解耦,我们可以把业务逻辑用C++实现,Qml只用来开发界面,这样在后续程序改版过程中,基本上可以不动逻辑只改UI比......
  • QML(14)——QML与C++交互方式总结1/3(qml调用C++的public函数)
    一、效果qml文件中,可以调用C++类的公共函数   二、步骤1、C++类文件创建C++文件时,一定要勾选下面3项 MyQmlClass.h #ifndefMYQMLCLASS_H#defineMYQMLCL......