简体   繁体   English

反编译源中不寻常的C#运算符......?

[英]Unusual C# operators in decompiled source…?

I've just decompiled some 3rd party source to debug an issue, using DotPeek. 我刚刚使用DotPeek反编译了一些第三方来源来调试问题。 The output code contains some unusual operators, which AFAIK aren't valid C#, so I'm wondering what they mean... 输出代码包含一些不常见的操作符,AFAIK无效C#,所以我想知道它们是什么意思...

The extract looks like (with Dotpeek comments included, as they are probably relevant); 摘录看起来像(包括Dotpeek评论,因为它们可能相关);

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .
    .
    .        
    // ISSUE: explicit reference operation
    // ISSUE: variable of a reference type
    int& local = @Written;
    int num = SomeMethod();
    .
    .
    .
    // ISSUE: explicit reference operation
    ^local = num;
}

So, 3 unusual operators in there... int& = @Written seems to be assigning a pointer to a variable that is named pointlessly with the @ character? 那么,那里有3个不寻常的操作符... int& = @Written似乎是在指定一个用@字符无意义命名的变量的指针?

But what is ^local = num; 但是什么是^local = num; ??? ???

OK, here is the equivalent snippet from ILSpy, which makes more sense, I guess the decompile to C# didn't produce a valid equivalent? 好的,这是来自ILSpy的等效片段,这更有意义,我想反编译到C#没有产生有效的等价物?

'C#' 'C#'

 int& local = @Written;
 byte[] numArray2 = this.FInSpool;
 int num = (int) __Global.Min(numArray2 == null ? 0L : (long) numArray2.Length, (long) MaxSize);
 ^local = num;

IL IL

 byte[] expr_22 = this.FInSpool;
 Written = (int)__Global.Min((long)((expr_22 == null) ? 0 : expr_22.Length), (long)MaxSize);

So, I guess the 'C#' isn't quite valid? 所以,我猜'C#'不是很有效? That IL would be valid C#, not sure why DotPeek produced the output it did. IL将是有效的C#,不知道为什么DotPeek会产生它的输出。 Perhaps I'll stick to ILSpy for this one...? 也许我会坚持ILSpy这个......?

If you look at the raw IL (from ildasm, not the C# equivalent via IL Spy), that may help you see what the decompiler is trying to say. 如果你看一下原始的IL(来自ildasm,而不是通过IL Spy的C#等价物),这可能会帮助你看到反编译器试图说的内容。 'Out' parameters are represented using a (managed) typed-reference, which isn't explicitly exposed as a type in C#. “Out”参数使用(托管)类型引用表示,该引用未在C#中显式公开为类型。 'Instances' of this type can normally only be passed as parameters to methods accepting typed references ('ref' or 'out' parameters.) See OpCodes.Mkrefany for more information. 此类型的“实例”通常只能作为参数传递给接受类型引用的方法('ref'或'out'参数。)有关详细信息,请参阅OpCodes.Mkrefany

What dotPeek is complaining about is that this 'out' typed reference was stored from the argument into a local variable slot, then written to later via the local slot. dotPeek抱怨的是这个'out'类型的引用从参数存储到局部变量槽中,然后通过本地槽写入。 The '@' and '^' are placeholders used to indicate this unexpected behavior detected by the decompiler (the one the ISSUE comments describe.) '@'和'^'是占位符,用于表示反编译器检测到的这种意外行为(ISSUE注释描述的行为)。

It's possible the code was compiled from C++/CLI and thus the IL looks different from the typical C# compiler output. 代码可能是从C ++ / CLI编译的,因此IL看起来与典型的C#编译器输出不同。 It's also possible this is some level of minor obfuscation to confuse decompilers (though I don't think so.) I don't think this is functionally any different from loading the reference from its argument onto the operation stack directly (avoiding the use of a local variable slot), but I could be wrong. 也有可能这是混淆反编译器的某种程度的轻微混淆(虽然我不这么认为。)我不认为这在功能上与将参数从其参数直接加载到操作堆栈上有所不同(避免使用一个局部变量槽),但我可能是错的。

Putting a @ before a name allows you to use a reserved name for a variable, For example if I wanted to have a variable called return I would need to do this. 在名称前加上@允许你为变量使用保留名称,例如,如果我想要一个名为return的变量,我需要这样做。

public int Weird()
{
    int @return = 0;
    return @return;
}

See this SO question for more details. 有关详细信息,请参阅此SO问题


Putting a ^ before the name ... umm, no clue. 在名字前加上^ ...嗯,没有头绪。 ( will update as I research I could find any info on what ^ means when not being used as a XOR) 将在我研究时更新,我可以找到关于什么^意味着什么时候没有被用作XOR的任何信息)

It's clearly a decompilation issue. 这显然是一个反编译问题。 Because of broad set of languages supported decompiler to any particular language may not always find exact match, but still tries to produce some output. 由于广泛的语言支持反编译器到任何特定语言可能并不总能找到完全匹配,但仍尝试产生一些输出。 Decompiler MAY try to produce somewhat equivalent output, like in this case could be: 反编译器可能尝试产生一些等效的输出,就像在这种情况下可能是:

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .        
    int num = SomeMethod();
    .
    Written = num;
}

but SHOULD it really do this? 但它应该真的这样做吗? in this case decompiler actually provided you with a hint, so you could decide if this is important for your particular case, as there MAY be some side effects. 在这种情况下,反编译器实际上为您提供了一个提示,因此您可以决定这对您的特定情况是否重要,因为可能会有一些副作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM