如何找到泛型参数的TypeSpec

时间:2019-02-26 15:03:37

标签: .net generics profiling instrumentation cil

一些初步信息

提供以下C#函数:

public static void func<T>(T t)
{
    System.Console.WriteLine(t);
}

它被编译为以下CIL:

.method public hidebysig static void  func<T>(!!T t) cil managed
{
    ldarg.0
    box        !!T
    call       void [mscorlib]System.Console::WriteLine(object)
    ret
}

上述方法的签名为10 01 01 01 1E 00,其中:

10 - Calling convention (IMAGE_CEE_CS_CALLCONV_GENERIC)
01 - Function generic arguments count (which is 1)
01 - Function arguments count (which is 1)
01 - Return type (ELEMENT_TYPE_VOID)
1E - First argument type (ELEMENT_TYPE_MVAR)
00 - Index of above MVAR (which is 0)

另请参见以下指令及其实际字节码:

box !!T - 8C 1B000001

1B000001指向TypeSpec表中的第一个条目,该条目指向blob 02 1E 00,其中:

02 - Blob length
1E - Type type (ELEMENT_TYPE_MVAR)
00 - Index of above MVAR (which is 0)

如我们所见,方法签名以描述性方式包含通用参数,其中具有实际的类型签名。
但是,当使用需要TypeDef / Ref / Spec的OpCode时,会提供TypeSpec,并且TypeSpec指向带有类型信息的签名。


所以我的问题是:
我正在编写一个执行某些IL重写的事件探查器,并给出了函数签名,我想向函数体中添加一些OpCode,以对参数进行操作。

使用IMetaDataImport2接口,如何获取给定通用参数所需的TypeSpec令牌?

我可以看到2个选项:

  1. 遍历EnumTypeSpecs直到找到匹配的签名
  2. 使用IMetaDataEmit界面创建一个新的TypeSpec

但是,出于明显的原因,我想避免这两个选择,而选择一个更明智的选择。

1 个答案:

答案 0 :(得分:1)

所以我最后提出了我的第一个建议。
我想这并不理想,但确实可以。

这是代码,如果有人感兴趣的话(省略错误处理):

HCORENUM typeSpecEnum = NULL;
mdTypeSpec typeSpec = mdTypeSpecNil;
ULONG outNum = -1;

// Loop through enum
while (true)
{
    // Get next enum
    HRESULT hr = pMetadataImport->EnumTypeSpecs(&typeSpecEnum, &typeSpec, 1, &outNum);
    if (hr == S_FALSE && outNum == 0) // According to doc, this means no more. End loop
        break;

    // Get the signature of this typespec
    PCCOR_SIGNATURE curSpecSig = NULL;
    ULONG curSpecSigLen = -1;
    pMetadataImport->GetTypeSpecFromToken(typeSpec, &curSpecSig, &curSpecSigLen);

    if (curSpecSigLen == <my_len> && memcmp(curSpecSig, <my_sig>, <my_len>) == 0)
        ; // Token found
    else
        typeSpec = mdTypeSpecNil; // Reset and goto next token
}

pMetadataImport->CloseEnum(typeSpecEnum); // Don't forget to close enum