Example #1
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapcode.cpp">ZapUnwindData::Save</a>
        /// </summary>
        public UnwindInfo(byte[] image, int offset)
        {
            byte versionAndFlags = NativeReader.ReadByte(image, ref offset);

            Version            = (byte)(versionAndFlags & 7);
            Flags              = (byte)(versionAndFlags >> 3);
            SizeOfProlog       = NativeReader.ReadByte(image, ref offset);
            CountOfUnwindCodes = NativeReader.ReadByte(image, ref offset);
            byte frameRegisterAndOffset = NativeReader.ReadByte(image, ref offset);

            FrameRegister = (Registers)(frameRegisterAndOffset & 15);
            FrameOffset   = (byte)(frameRegisterAndOffset >> 4);

            UnwindCodes = new List <UnwindCode>(CountOfUnwindCodes);
            CodeOffsetToUnwindCodeIndex = new Dictionary <int, int>();
            int frameOffset       = FrameOffset;
            int sizeOfUnwindCodes = CountOfUnwindCodes * _sizeofUnwindCode;
            int endOffset         = offset + sizeOfUnwindCodes;

            while (offset < endOffset)
            {
                UnwindCode unwindCode = new UnwindCode(image, ref frameOffset, ref offset);
                CodeOffsetToUnwindCodeIndex.Add(unwindCode.CodeOffset, UnwindCodes.Count);
                UnwindCodes.Add(unwindCode);
            }

            Size = _offsetofUnwindCode + sizeOfUnwindCodes;
            int alignmentPad = -Size & 3;

            Size += alignmentPad + sizeof(uint);

            // Personality routine RVA must be at 4-aligned address
            offset += alignmentPad;
            PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset);
        }
Example #2
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapcode.cpp">ZapUnwindData::Save</a>
        /// </summary>
        public UnwindInfo(byte[] image, int offset)
        {
            byte versionAndFlags = NativeReader.ReadByte(image, ref offset);

            Version            = (byte)(versionAndFlags & 7);
            Flags              = (byte)(versionAndFlags >> 3);
            SizeOfProlog       = NativeReader.ReadByte(image, ref offset);
            CountOfUnwindCodes = NativeReader.ReadByte(image, ref offset);
            byte frameRegisterAndOffset = NativeReader.ReadByte(image, ref offset);

            FrameRegister = (Registers)(frameRegisterAndOffset & 15);
            FrameOffset   = (byte)(frameRegisterAndOffset >> 4);

            UnwindCodeArray = new UnwindCode[CountOfUnwindCodes];
            UnwindCodes     = new Dictionary <int, UnwindCode>();
            for (int i = 0; i < CountOfUnwindCodes; i++)
            {
                UnwindCodeArray[i] = new UnwindCode(image, i, ref offset);
            }
            for (int i = 0; i < CountOfUnwindCodes; i++)
            {
                ParseUnwindCode(ref i);
                Debug.Assert(!UnwindCodes.ContainsKey(UnwindCodeArray[i].CodeOffset));
                UnwindCodes.Add(UnwindCodeArray[i].CodeOffset, UnwindCodeArray[i]);
            }

            Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode;
            int alignmentPad = -Size & 3;

            Size += alignmentPad + sizeof(uint);

            // Personality routine RVA must be at 4-aligned address
            offset += alignmentPad;
            PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset);
        }
Example #3
0
        /// <summary>
        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
        /// </summary>
        private void ParseUnwindCode(ref int i)
        {
            UnwindCode code = UnwindCodeArray[i];

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

            case UnwindOpCodes.UWOP_ALLOC_LARGE:
                code.OpInfoStr = $"{code.OpInfo} - ";
                if (code.OpInfo == 0)
                {
                    i++;
                    UnwindCodeArray[i].OpInfoStr += "Scaled small";
                    code.NextFrameOffset          = (int)UnwindCodeArray[i].FrameOffset * 8;
                }
                else if (code.OpInfo == 1)
                {
                    i++;
                    UnwindCodeArray[i].OpInfoStr += "Unscaled large";
                    uint offset = UnwindCodeArray[i].FrameOffset;
                    i++;
                    offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
                    code.NextFrameOffset = (int)offset;
                }
                else
                {
                    code.OpInfoStr += "Unknown";
                }
                break;

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

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

            case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
            {
                code.OpInfoStr = $"Unused({code.OpInfo})";
                i++;
                uint offset = UnwindCodeArray[i].FrameOffset;
                i++;
                offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
                code.NextFrameOffset = (int)offset * 16;
                if ((UnwindCodeArray[i].FrameOffset & 0xF0000000) != 0)
                {
                    // TODO (refactoring) - what should we do?
                    // R2RDump.WriteWarning("Illegal unwindInfo unscaled offset: too large");
                }
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL:
            {
                code.OpInfoStr = $"{(Registers)code.OpInfo}({code.OpInfo})";
                i++;
                uint offset = UnwindCodeArray[i].FrameOffset * 8;
                code.NextFrameOffset = (int)offset;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
            {
                code.OpInfoStr = $"{(Registers)code.OpInfo}({code.OpInfo})";
                i++;
                uint offset = UnwindCodeArray[i].FrameOffset;
                i++;
                offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
                code.NextFrameOffset = (int)offset;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128:
            {
                code.OpInfoStr = $"XMM{code.OpInfo}({code.OpInfo})";
                i++;
                uint offset = UnwindCodeArray[i].FrameOffset * 16;
                code.NextFrameOffset = (int)offset;
            }
            break;

            case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
            {
                code.OpInfoStr = $"XMM{code.OpInfo}({code.OpInfo})";
                i++;
                uint offset = UnwindCodeArray[i].FrameOffset;
                i++;
                offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
                code.NextFrameOffset = (int)offset;
            }
            break;
            }
        }