【问题标题】:Can BitConverter be used to reliably extract multi-byte values from an IL byte stream (as returned by MethodBody.GetILAsByteArray)?可以使用 BitConverter 从 IL 字节流(由 MethodBody.GetILAsByteArray 返回)可靠地提取多字节值吗?
【发布时间】:2012-08-12 11:30:34
【问题描述】:

我正在编写一些代码来解析MethodBody.GetILAsByteArray 返回的 IL 字节数组。

假设我想从这样的 IL 字节流中读取元数据令牌或 32 位整数常量。起初我认为使用BitConverter.ToInt32(byteArray, offset) 会让这件事变得简单。但是我现在担心这在大端机器上不起作用。

据我所知,IL 总是对多字节值使用 little-endian 编码:

“所有参数编号均以最小地址处的最低有效字节编码(通常称为“小端”的模式)。”The Common Language Infrastructure Annotated Standard,Partition III,ch。 1.2(第 482 页)。

由于BitConverter 的转换方法遵循计算机体系结构的字节顺序(可以通过BitConverter.IsLittleEndian 发现),我得出结论,不应使用BitConverter 从IL 字节流中提取多字节值,因为这会在大端机器上给出错误的结果。

这个结论正确吗?

  • 如果是:有没有办法告诉BitConverter 使用哪个字节序进行转换,或者 BCL 中是否有任何其他类提供此功能,或者我是否必须编写自己的转换代码?

  • 如果不是:我哪里错了?提取例如的正确方法是什么?来自 IL 字节数组的 Int32 操作数值?

【问题讨论】:

    标签: clr endianness cil system.reflection bitconverter


    【解决方案1】:

    在传递它之前,您应该始终在小端数组上执行此操作:

    // Array is little. Are we on big?
    if (!BitConverter.IsLittleEndian)
    {
        // Then flip it
        Array.Reverse(array);
    }
    int val = BitConverter.ToInt32(...);
    

    但是,正如您提到的 IL 流。字节码是这样的(AFAIK):

    (OPCODE:(1|2):little) (VARIABLES:x:little)
    

    所以我会读取一个字节,检查它的操作码,然后读取适当的字节并在必要时使用上面的代码翻转数组。我能问一下你在做什么吗?

    【讨论】:

    • 所以要提取Int32,如果我不想修改原始IL 数组,我可能不得不在大端机器上执行此操作:var fragment = new byte[4]; Array.Copy(il, offset, fragment, 0, length: 4); Array.Reverse(fragment); int value = BitConverter.ToInt32(fragment, 0);。 -- BCL 中是否有任何预定义的类或方法可以做同样的事情?
    • 我不知道。得到这个可能会对你有很大帮助:ecma-international.org/publications/standards/Ecma-335.htm
    • 如果您想将操作码与OpCode.Value(不是byte[],而是定义为short)进行比较,字节序也会发挥作用。
    • @stakx 其实是一两个字节序列,不是很短
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    • 2019-09-13
    • 2019-01-20
    • 1970-01-01
    • 2022-04-20
    相关资源
    最近更新 更多