标签: il

何时以及如何使用Ldvirtftn操作码?

以下示例程序是我试图掌握ldvirtftn操作码的用法.您会看到名称表明这是在将虚函数指针加载到堆栈时使用的操作码.在示例代码中,我正在创建一个具有2个静态方法的类型,Ldftn并且Ldvirtftn这两个方法都返回Base.Method()第一个函数的开放委托Ldftn使用ldftn操作码,并且意外地工作,就像Base.Method虚拟一样.第二种方法使用Ldvirtftn并显然创建了一个无效的程序.我究竟做错了什么?除了混淆之外,这个操作码的目的是什么?

public class Base
{
    public virtual void Method()
    {
        Console.WriteLine("Base");
    }
}

public class Child : Base
{
    public override void Method()
    {
        Console.WriteLine("Child");
    }
}
class Program
{
    static void Main(string[] args)
    {
        AssemblyBuilder ab =AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"),AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder mb = ab.DefineDynamicModule("TestModule");
        TypeBuilder tb = mb.DefineType("TestType");
        MethodBuilder method = tb.DefineMethod("Ldftn",MethodAttributes.Public | MethodAttributes.Static, typeof(Action<Base>), Type.EmptyTypes);
        var ilgen = method.GetILGenerator();
        ilgen.Emit(OpCodes.Ldnull);
        ilgen.Emit(OpCodes.Ldftn, typeof(Base).GetMethod("Method"));
        ilgen.Emit(OpCodes.Newobj, typeof(Action<Base>).GetConstructors()[0]); …
Run Code Online (Sandbox Code Playgroud)

.net c# il reflection.emit

3
推荐指数
1
解决办法
1590
查看次数

Mono.Cecil:从其他程序集调用基类的方法

如何按名称获取MethodReference到基类的方法?

我试过了

type.BaseType.Resolve().Methods;
Run Code Online (Sandbox Code Playgroud)

如果我将包含基类的dll添加到assemblyresolver,它将返回方法.但是,如果我使用添加呼叫

MSILWorker.Create(OpCodes.Call, baseMethod);
Run Code Online (Sandbox Code Playgroud)

(通过从解析的TypeDefinition中预处理方法找到baseMethod),生成的IL不可读,甚至Reflector冻结并退出.

现在有些IL:
如果在类型上调用私有方法:

 call instance void SomeNamespace.MyClass::RaisePropertyChanged(string)
Run Code Online (Sandbox Code Playgroud)

如果在基类型上调用protected方法:

call instance void [OtherAssembly]BaseNamespace.BaseClass::RaisePropertyChanged(string)
Run Code Online (Sandbox Code Playgroud)

那么,我如何使用Mono.Cecil生成后者呢?

inheritance il cil assemblies mono.cecil

3
推荐指数
1
解决办法
1752
查看次数

使用MSBuild构建后运行测试时出现MissingManifestResourceException(.mresource在清单中有路径)

我在命令行上使用MSBuild在构建服务器上的C#项目的嵌入资源有问题.在Visual Studio中构建和运行测试时,该项目工作得很好,但是当从命令行运行MSBuild时,运行测试时会出现以下问题:


System.Resources.MissingManifestResourceException:找不到适合指定文化或中性文化的任何资源.确保".Properties.Resources.resources"在编译时正确嵌入或链接到程序集"",或者所有所需的附属程序集都是可加载和完全签名的.

System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture,Boolean)中的System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo文化,Dictionary`2 localResourceSets,Boolean tryParents,Boolean createIfNotExists,StackCrawlMark和stackMark)中的System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String fileName)位于System.Resources.get_SomeResource()的System.Resources.ResourceManager.GetString(String name,CultureInfo culture)的System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture,Boolean createIfNotExists,Boolean tryParents)中的createIfNotExists,Boolean tryParents,StackCrawlMark和stackMark\Properties\Resources.Designer.cs:第87行


我已将问题跟踪到生成的IL(我使用ildasm).在Visual Studio中进行扩展时,在程序集的清单中设置以下内容:

.mresource public <PROJECTNAME>.Properties.Resources.resources
{
  // Offset: 0x00000000 Length: 0x00000236
}
Run Code Online (Sandbox Code Playgroud)

但是在使用MSBuild构建时会生成以下输出:

.mresource public '../..//Build/<PROJECTNAME>_AnyCPU_Debug_Obj/<PROJECTNAME>.Properties.Resources.resources'
{
  // Offset: 0x00000000 Length: 0x00000236
}
Run Code Online (Sandbox Code Playgroud)

因为可以看到资源的路径突然成为资源名称的一部分.

有没有人有任何想法如何解决这个问题?

c# msbuild il visual-studio-2010 embedded-resource

3
推荐指数
1
解决办法
4715
查看次数

F#中的字符串解析 - 生成的IL

我在F#中编写了一些小的字符串解析函数 - 以便更好地了解F#并了解如何使用它来解决此类任务.我尝试遍历字符串并通过递归搜索特定字符.

逻辑确实有效,但在我看来,生成的版本构建的IL代码(启用了优化)确实看起来很奇怪.所以我想有更好的方法在F#中以高效的方式编写这些东西.

这是解析函数的一部分:

let eatTag (input : string) index =
    let len = input.Length
    let nothing = 0, null, TagType.Open

    // more functions used in the same way
    // ...

    let rec findName i =
        if i >= len then nothing
        else
            let chr = input.[i]
            if isWhitespace chr then
                findName (i+1)
            elif chr = '/' then
                getName (i+1) (i+1) true
            else getName (i+1) i false

    let rec findStart i =
        if i >= len then nothing
        elif …
Run Code Online (Sandbox Code Playgroud)

.net f# il parsing

3
推荐指数
2
解决办法
581
查看次数

ldc.i4.x和ldc.i4 x指令是否可互换且语义相同?

还有在一些CIL加载指令,例如ldc.i4.0,ldc.i4.1,ldc.i4.2,ldc.i4.3 ...

我在想,是不是可以使用ldc.i4 1,而不是ldc.i4.1ldc.i4 5代替ldc.i4.5

.net c# il cil

3
推荐指数
1
解决办法
946
查看次数

CopyToNative在哪里定义?

我目前正在浏览反编译的C#IL(使用ILSpy),以便了解如何System.Runtime.InteropServices(可能)实现某些方法.当我想检查如何Marshal.Copy()实现时,我发现它只调用CopyToNative(),其定义如下:

// System.Runtime.InteropServices.Marshal
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void CopyToNative(object source, int startIndex, IntPtr destination, int length);
Run Code Online (Sandbox Code Playgroud)

它在哪里实施?有没有机会查看它(反编译)的源代码?如果没有,有没有人知道如何实施?

c# il interop native

3
推荐指数
1
解决办法
234
查看次数

本地字符串变量的实例化会影响性能吗?

我有两种情况:

    static void CreateCopyOfString()
    {
        string s = "Hello";
        ProcessString(s);
    }
Run Code Online (Sandbox Code Playgroud)

    static void DoNotCreateCopyOfString()
    {
        ProcessString("Hello");
    }
Run Code Online (Sandbox Code Playgroud)

这两种情况的IL看起来像这样:

    .method private hidebysig static void  CreateCopyOfString() cil managed
    {
        // Code size       15 (0xf)
        .maxstack  1
        .locals init ([0] string s)
        IL_0000:  nop
        IL_0001:  ldstr      "Hello"
        IL_0006:  stloc.0
        IL_0007:  ldloc.0
        IL_0008:  call       void ConsoleApplication1.Program::ProcessString(string)
        IL_000d:  nop
        IL_000e:  ret
    } // end of method Program::CreateCopyOfString
Run Code Online (Sandbox Code Playgroud)

    .method private hidebysig static void  DoNotCreateCopyOfString() cil managed
    {
          // Code size       13 (0xd)
          .maxstack  8 …
Run Code Online (Sandbox Code Playgroud)

c# string performance il initialization

3
推荐指数
1
解决办法
174
查看次数

如何使用较少方法实现旧版本接口的对象

我在定义以下界面的应用程序中有一个程序集:

public void Method1()
Run Code Online (Sandbox Code Playgroud)

然后我有一个实现此接口的程序集插件.它在运行时被发现并加载.

后来我修改了界面以包含一个新方法:

public void Method1()
public void Method2()
Run Code Online (Sandbox Code Playgroud)

我创建了一个新的程序集插件,实现了新版本的界面.

有没有办法在应用程序上只部署新接口和新插件?目前客户端永远不会在第一个插件上调用Method2(),因此它不应该是一个问题(如果在第一个插件上调用Method2的话,我可以抛出异常).

我以为我能做到,但我得到一个TypeLoadException说法:

程序集'Provider2,Version2.0.0.0,Culture = neutral,PublicKeyToken = null'中的类型'Provider2.Class2'中的方法'Method2'没有实现.

(这是真的但是因为没有调用Method2应该不是问题)

.net c# clr il interface

3
推荐指数
1
解决办法
162
查看次数

.NET应用程序的本机访问冲突

我们遇到.NET应用程序的问题.它在关闭时随机产生本机访问冲突(因此不是.NET异常).

  • Windows Server 2012 x64(在刀片系统上运行的虚拟机)
  • .NET 4.0 Framework(已安装4.5)
  • 我们的应用程序是.NET x86应用程序(不是AnyCPU;不是ASP.NET)
  • 第三方本机模块使用SQL CE 3.5等

来自Windows事件日志的错误报告看起来像这样(省略了应用程序和模块名称,我从德语翻译了条目):

Exceptioncode: 0xc0000005
Offset: 0x00006a9e
Process ID: 0xfe8
...
Run Code Online (Sandbox Code Playgroud)

我发现0xc0000005是一种访问冲突.由于.NET NullReferenceException,也可能发生这种情况.当Windows错误报告对话框打开时,我们已经使用ProcDump标志-ma 创建了一个完整的内存转储.

当我打开这个转储时,除了.exe文件本身之外,我找不到任何加载的.NET模块.我不是本地编程方面的专家,只知道一些关于WinDbg的基础知识.

所以我做了什么:

  1. 使用WinDbg打开转储
  2. 使用设置符号路径

    .sympath SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols;C:\PathToMatchingPDBs\ForTheProgram
    
    Run Code Online (Sandbox Code Playgroud)
  3. 重新加载所有符号

    .reload /d /f
    
    Reloading current modules
    ...*** ERROR: Symbol file could not be found.  Defaulted to export symbols for sysfer.dll - 
    ...
    
    Run Code Online (Sandbox Code Playgroud)
  4. ~* k 输出

    .  0  Id: 1560.19a4 Suspend: 0 Teb: ff20e000 Unfrozen
    ChildEBP RetAddr  
    0058f0e8 7744c752 ntdll!ZwWaitForMultipleObjects+0xc
    0058f26c 76d256c0 KERNELBASE!WaitForMultipleObjectsEx+0x10b
    0058f2e0 76d2586a kernel32!WerpReportFaultInternal+0x1c4
    0058f2f4 …
    Run Code Online (Sandbox Code Playgroud)

.net il memory-dump windbg access-violation

3
推荐指数
1
解决办法
2103
查看次数

如何在对驻留在不同程序集中的方法执行JMP指令时获取正确的方法引用

我有以下代码,基本上创建一个DynamicAssembly有两种类型,每种类型都有一个公共方法.

        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly
                (new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run);
        var module = assembly.DefineDynamicModule("Main");
        var type1 = module.DefineType("type1");


        var method1 = type1.DefineMethod
                      (
                        "Method1", MethodAttributes.Public, typeof(void), null
                      );

        var gen = method1.GetILGenerator();
        gen.Emit(OpCodes.Ret);

        var t1 = type1.CreateType();

        var createdMethod1 = t1.GetMethod("Method1");

        var type2 = module.DefineType("type2");

        var method2 = type2.DefineMethod
                      (
                        "Method2", MethodAttributes.Public, typeof(void), null
                      );


        byte[] ilCodes = new byte[5];
        ilCodes[0] = (byte)OpCodes.Jmp.Value;
        ilCodes[1] = (byte)(createdMethod1.MetadataToken & 0xFF);
        ilCodes[2] = (byte)(createdMethod1.MetadataToken >> 8 & 0xFF);
        ilCodes[3] = (byte)(createdMethod1.MetadataToken >> 16 & 0xFF); …
Run Code Online (Sandbox Code Playgroud)

c# il reflection.emit .net-assembly

3
推荐指数
1
解决办法
212
查看次数