文档章节

Core CLR Host 源码简单分析

o
 osc_a22drz29
发布于 2019/03/25 17:00
字数 534
阅读 5
收藏 0
pmd

精选30+云产品,助力企业轻松上云!>>>

在定制 CLR Host的时候,可以通过调用如下代码,来获取当前需要被宿主的程序调用入口:

hr = Host->CreateDelegate(
domainId,
L"Main,Version=1.0.0.0", 
L"Main.Program",	// Target managed type
L"Main",	// Target entry point (static method)
(INT_PTR*)&pfnDelegate);

CreateDelegate 会进入到corhost.cpp里面

HRESULT CorHost2::CreateDelegate(
    DWORD appDomainID,
    LPCWSTR wszAssemblyName,     
    LPCWSTR wszClassName,     
    LPCWSTR wszMethodName,
    INT_PTR* fnPtr)
{
    WRAPPER_NO_CONTRACT;

    return _CreateDelegate(appDomainID, wszAssemblyName, wszClassName, wszMethodName, fnPtr);
}

然后_CreateDelegate 会CorHost2::_CreateDelegate,这个函数里面首先实例化了一个AssemblySpec,然后用传递过来的程序集名称初始化,通过AssemblySpec的LoadfAssembly实例化程序集。

获取程序集的类加载器,通过类加载器加载TypeHandle,传递的参数分别为程序集实例和ClassName。然后再通过MemberLoader::FindMethodByName获取到类里面的所需要查找的方法。

通过AppDomain的GetUMEntryThunkCache函数返回UMEntryThunk,最后通过UMEntryThunk->GetCode()返回要查找的函数指针。代码如下:

HRESULT CorHost2::_CreateDelegate(
    DWORD appDomainID,
    LPCWSTR wszAssemblyName,     
    LPCWSTR wszClassName,     
    LPCWSTR wszMethodName,
    INT_PTR* fnPtr)
{

    CONTRACTL
    {
        NOTHROW;
        if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
        ENTRY_POINT;  // This is called by a host.
    }
    CONTRACTL_END;

    HRESULT hr=S_OK;

    EMPTY_STRING_TO_NULL(wszAssemblyName);
    EMPTY_STRING_TO_NULL(wszClassName);
    EMPTY_STRING_TO_NULL(wszMethodName);

    if (fnPtr == NULL)
       return E_POINTER;
    *fnPtr = NULL;

    if(wszAssemblyName == NULL)
        return E_INVALIDARG;
    
    if(wszClassName == NULL)
        return E_INVALIDARG;

    if(wszMethodName == NULL)
        return E_INVALIDARG;
    
    if (!m_fStarted)
        return HOST_E_INVALIDOPERATION;

    BEGIN_ENTRYPOINT_NOTHROW;

    BEGIN_EXTERNAL_ENTRYPOINT(&hr);
    GCX_COOP_THREAD_EXISTS(GET_THREAD());

    MAKE_UTF8PTR_FROMWIDE(szAssemblyName, wszAssemblyName);
    MAKE_UTF8PTR_FROMWIDE(szClassName, wszClassName);
    MAKE_UTF8PTR_FROMWIDE(szMethodName, wszMethodName);

    ADID id;
    id.m_dwId=appDomainID;//获取appdomid,通过CreateAppDomainWithManager函数来获取的

    ENTER_DOMAIN_ID(id)

    GCX_PREEMP();

    AssemblySpec spec; //实例化一个 AssemblySpec类
    spec.Init(szAssemblyName); //用传递过来的程序集名称初始化这类
    Assembly* pAsm=spec.LoadAssembly(FILE_ACTIVE);//加载此程序集,返回程序集实例

    TypeHandle th=pAsm->GetLoader()->LoadTypeByNameThrowing(pAsm,NULL,szClassName);//获取到程序集的类加载器加载实例TypeHandle 并返回
    MethodDesc* pMD=NULL;
    
    if (!th.IsTypeDesc()) 
    {
        pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Unique);//通过typehandle的方法表以及传递过来的方法名称,获取到方法描述类methoddesc
        if (pMD == NULL)
        {
            // try again without the FM_Unique flag (error path)
            pMD = MemberLoader::FindMethodByName(th.GetMethodTable(), szMethodName, MemberLoader::FM_Default);
            if (pMD != NULL)
            {
                // the method exists but is overloaded
                ThrowHR(COR_E_AMBIGUOUSMATCH);
            }
        }
    }

    if (pMD==NULL || !pMD->IsStatic() || pMD->ContainsGenericVariables()) 
        ThrowHR(COR_E_MISSINGMETHOD);

    UMEntryThunk *pUMEntryThunk = GetAppDomain()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD);//通过 appdomain 的 getumeentrythunk函数获取到umeentrythunk
    *fnPtr = (INT_PTR)pUMEntryThunk->GetCode(); //通过上面获取的 umentrythunk类调用参数getcode ,赋值给传递过来的需要的函数指针参数

    END_DOMAIN_TRANSITION;

    END_EXTERNAL_ENTRYPOINT;

    END_ENTRYPOINT_NOTHROW;

    return hr;//标志是否成功
}
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

以太坊智能合约开发常见的10个安全问题

本文介绍CheckMarx安全研究小组通过扫描公开的以太坊智能合约所发现的Solidity智能合约开发中常见的十大安全问题,其中__未检查的外部调用__ 和 高成本循环 分列排行榜前两名。该安全问题排行...

区块链教程
47分钟前
17
0
Android Studio写flutter快捷键

1.stl :代表StatelessWidget 2.stf :StatefulWidget 3.cmd + shift + 减号 :折叠所有代码 4.cmd + 减号 :折叠当前代码块 5.ctrl + r :编译运行 6.cmd + s :hot reload 7.cmd + { :回到...

一代码农码一代
今天
21
0
远程桌面如何修改登录密码

打开运行, C:\Windows\explorer.exe shell:::{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0} 即可 https://www.itexperience.net/10-ways-to-change-password-in-remote-desktop-session/......

ethanleellj
今天
17
0
easyui的menu接收后台集合,并且根据集合利用appendItem动态生成菜单项,判断菜单项的字数大于指定长度,则多余字符以。。。显示,并且悬浮提示

JSP: <a id="bb" href="javascript:void(0);" class="easyui-menubutton" data-options="menu:'#layout_north_stMenu222',iconCls:'icon-cologne-sign-out'" >导出</a><div id="aaa" style......

文文1
今天
13
0
Mysql主从同步

1主从同步 1.1Master 1.1.1配置--编辑 my.cnf #编辑 mysql 的 /etc/my.cnf 配置文件vi /etc/my.cnf#添加如下配置server-id=1 #设置服务 IDlog_bin=mysql-bin #启动 binlog...

风雪满弓刀
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部