예제 #1
0
        /// <summary>
        /// Unwinde code parsing is based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
        /// </summary>
        public UnwindCode(byte[] image, ref int frameOffset, ref int offset)
        {
            CodeOffset = NativeReader.ReadByte(image, ref offset);
            byte op = NativeReader.ReadByte(image, ref offset);

            UnwindOp = (UnwindOpCodes)(op & 15);
            OpInfo   = (byte)(op >> 4);

            OffsetLow  = CodeOffset;
            OffsetHigh = OpInfo;

            FrameOffset = frameOffset;

            switch (UnwindOp)
            {
            case UnwindOpCodes.UWOP_PUSH_NONVOL:
                OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
                break;

            case UnwindOpCodes.UWOP_ALLOC_LARGE:
                OpInfoStr = $"{OpInfo} - ";
                if (OpInfo == 0)
                {
                    OpInfoStr      += "Scaled small";
                    NextFrameOffset = 8 * NativeReader.ReadUInt16(image, ref offset);
                }
                else if (OpInfo == 1)
                {
                    OpInfoStr += "Unscaled large";
                    uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                    NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
                }
                else
                {
                    throw new BadImageFormatException();
                }
                break;

            case UnwindOpCodes.UWOP_ALLOC_SMALL:
                int opInfo = OpInfo * 8 + 8;
                OpInfoStr = $"{opInfo}";
                break;

            case UnwindOpCodes.UWOP_SET_FPREG:
                OpInfoStr = $"Unused({OpInfo})";
                break;

            case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
            {
                OpInfoStr = $"Unused({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                nextOffset      = ((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
                NextFrameOffset = (int)nextOffset * 16;
                if ((NextFrameOffset & 0xF0000000) != 0)
                {
                    throw new BadImageFormatException("Warning: Illegal unwindInfo unscaled offset: too large");
                }
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL:
            {
                OpInfoStr       = $"{(Registers)OpInfo}({OpInfo})";
                NextFrameOffset = NativeReader.ReadUInt16(image, ref offset) * 8;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
            {
                OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128:
            {
                OpInfoStr       = $"XMM{OpInfo}({OpInfo})";
                NextFrameOffset = (int)NativeReader.ReadUInt16(image, ref offset) * 16;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
            {
                OpInfoStr = $"XMM{OpInfo}({OpInfo})";
                uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
                NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
            }
            break;

            default:
                throw new NotImplementedException(UnwindOp.ToString());
            }

            NextFrameOffset = frameOffset;
        }
예제 #2
0
 private static ushort PackUnwindOp(UnwindOp op, int prologOffset, int opInfo)
 {
     return((ushort)(prologOffset | ((int)op << 8) | (opInfo << 12)));
 }