Eli*_*kel 5 .net generics instrumentation profiling cil
一些初步信息
给定以下C#函数:
public static void func<T>(T t)
{
System.Console.WriteLine(t);
}
Run Code Online (Sandbox Code Playgroud)
它被编译为以下CIL:
.method public hidebysig static void func<T>(!!T t) cil managed
{
ldarg.0
box !!T
call void [mscorlib]System.Console::WriteLine(object)
ret
}
Run Code Online (Sandbox Code Playgroud)
上述方法的签名位于10 01 01 01 1E 00:
10-呼叫约定(IMAGE_CEE_CS_CALLCONV_GENERIC) 01-函数通用参数计数(为1) 01-函数参数计数(为1) 01-返回类型(ELEMENT_TYPE_VOID) 1E-第一个参数类型(ELEMENT_TYPE_MVAR) 00-高于MVAR的索引(为0)
另请参阅以下指令及其实际字节码:
盒!! T-8C 1B000001
1B000001指向TypeSpec表中的第一个条目,该条目指向blob 02 1E 00,其中:
02-斑点长度 1E-类型类型(ELEMENT_TYPE_MVAR) 00-高于MVAR的索引(为0)
如我们所见,方法签名以描述性方式包含泛型参数,其中我们具有实际的类型签名。
但是,当使用需要TypeDef / Ref / Spec的OpCode时,将提供TypeSpec,并且TypeSpec指向带有类型信息的签名。
所以我的问题是:
我正在编写一个执行IL重写的事件探查器,并给定了函数签名,我想向函数体中添加一些OpCode,以对参数进行操作。
使用该IMetaDataImport2接口,如何获得给定通用参数所需的TypeSpec令牌?
我可以看到2个选项:
IMetaDataEmit界面创建新的TypeSpec但是,出于明显的原因,我想避免这两个选择,而选择一个更明智的选择。
所以我最终同意了我的第一个建议。
我想这并不理想,但它确实有效。
如果有人感兴趣的话,这是代码(省略错误处理):
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
80 次 |
| 最近记录: |