Beispiel #1
0
        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 = (Amd64Registers)(frameRegisterAndOffset & 15);
            FrameOffset   = (byte)(frameRegisterAndOffset >> 4);

            UnwindCode = new UnwindCode[CountOfUnwindCodes];
            for (int i = 0; i < CountOfUnwindCodes; i++)
            {
                UnwindCode[i] = new UnwindCode(image, ref offset);
            }

            PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset);

            Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode;
            int alignmentPad = ((Size + sizeof(int) - 1) & ~(sizeof(int) - 1)) - Size;

            Size += (alignmentPad + sizeof(uint));
        }
Beispiel #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, List <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);
                if (!UnwindCodes.ContainsKey(UnwindCodeArray[i].CodeOffset))
                {
                    UnwindCodes[UnwindCodeArray[i].CodeOffset] = new List <UnwindCode>();
                }
                UnwindCodes[UnwindCodeArray[i].CodeOffset].Add(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);
        }
Beispiel #3
0
        public void WriteTo(TextWriter writer, DumpOptions options)
        {
            if (!options.Naked)
            {
                writer.WriteLine($"Id: {Id}");
                writer.WriteLine($"StartAddress: 0x{StartAddress:X8}");
            }
            if (Size == -1)
            {
                writer.WriteLine("Size: Unavailable");
            }
            else
            {
                writer.WriteLine($"Size: {Size} bytes");
            }
            if (!options.Naked)
            {
                writer.WriteLine($"UnwindRVA: 0x{UnwindRVA:X8}");
            }
            if (UnwindInfo is Amd64.UnwindInfo amd64UnwindInfo)
            {
                string parsedFlags = "";
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0)
                {
                    parsedFlags += " EHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0)
                {
                    parsedFlags += " UHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_CHAININFO) != 0)
                {
                    parsedFlags += " CHAININFO";
                }
                if (parsedFlags.Length == 0)
                {
                    parsedFlags = " NHANDLER";
                }
                writer.WriteLine($"Version:            {amd64UnwindInfo.Version}");
                writer.WriteLine($"Flags:              0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
                writer.WriteLine($"SizeOfProlog:       0x{amd64UnwindInfo.SizeOfProlog:X4}");
                writer.WriteLine($"CountOfUnwindCodes: {amd64UnwindInfo.CountOfUnwindCodes}");
                writer.WriteLine($"FrameRegister:      {amd64UnwindInfo.FrameRegister}");
                writer.WriteLine($"FrameOffset:        0x{amd64UnwindInfo.FrameOffset}");
                if (!options.Naked)
                {
                    writer.WriteLine($"PersonalityRVA:     0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");
                }

                for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++)
                {
                    Amd64.UnwindCode unwindCode = amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex];
                    writer.Write($"UnwindCode[{unwindCode.Index}]: ");
                    writer.Write($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
                    writer.Write($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
                    writer.Write($"NextOffset 0x{unwindCode.NextFrameOffset} ");
                    writer.Write($"Op {unwindCode.OpInfoStr}");
                    writer.WriteLine();
                }
            }
            writer.WriteLine();

            if (Method.GcInfo is Amd64.GcInfo gcInfo)
            {
                writer.WriteLine("GC info:");
                writer.WriteLine($@"    Version:                           {gcInfo.Version}");
                writer.WriteLine($@"    ReturnKind:                        {gcInfo.ReturnKind}");
                writer.WriteLine($@"    ValidRangeStart:                   0x{gcInfo.ValidRangeStart:X4}");
                writer.WriteLine($@"    ValidRangeEnd:                     0x{gcInfo.ValidRangeEnd:X4}");
                writer.WriteLine($@"    SecurityObjectStackSlot:           0x{gcInfo.SecurityObjectStackSlot:X4}");
                writer.WriteLine($@"    GSCookieStackSlot:                 0x{gcInfo.GSCookieStackSlot:X4}");
                writer.WriteLine($@"    PSPSymStackSlot:                   0x{gcInfo.PSPSymStackSlot:X4}");
                writer.WriteLine($@"    GenericsInstContextStackSlot:      0x{gcInfo.GenericsInstContextStackSlot:X4}");
                writer.WriteLine($@"    StackBaseRegister:                 {gcInfo.StackBaseRegister}");
                writer.WriteLine($@"    SizeOfENCPreservedArea:            0x{gcInfo.SizeOfEditAndContinuePreservedArea:X4}");
                writer.WriteLine($@"    ReversePInvokeFrameStackSlot:      0x{gcInfo.ReversePInvokeFrameStackSlot:X4}");
                writer.WriteLine($@"    SizeOfStackOutgoingAndScratchArea: 0x{gcInfo.SizeOfStackOutgoingAndScratchArea:X4}");
                writer.WriteLine($@"    NumSafePoints:                     {gcInfo.NumSafePoints}");
                writer.WriteLine($@"    NumInterruptibleRanges:            {gcInfo.NumInterruptibleRanges}");

                writer.WriteLine($@"    SafePointOffsets: {gcInfo.SafePointOffsets.Count}");
                foreach (Amd64.GcInfo.SafePointOffset safePoint in gcInfo.SafePointOffsets)
                {
                    writer.WriteLine($@"        Index: {safePoint.Index,2}; Value: 0x{safePoint.Value:X4}");
                    if (gcInfo.LiveSlotsAtSafepoints != null)
                    {
                        writer.WriteLine($@"        Live slots: {String.Join(", ", gcInfo.LiveSlotsAtSafepoints[safePoint.Index])}");
                    }
                }

                writer.WriteLine($@"    InterruptibleRanges: {gcInfo.InterruptibleRanges.Count}");
                foreach (Amd64.InterruptibleRange range in gcInfo.InterruptibleRanges)
                {
                    writer.WriteLine($@"        Index: {range.Index,2}; StartOffset: 0x{range.StartOffset:X4}; StopOffset: 0x{range.StopOffset:X4}");
                }

                writer.WriteLine("    SlotTable:");
                writer.WriteLine($@"        NumRegisters:  {gcInfo.SlotTable.NumRegisters}");
                writer.WriteLine($@"        NumStackSlots: {gcInfo.SlotTable.NumStackSlots}");
                writer.WriteLine($@"        NumUntracked:  {gcInfo.SlotTable.NumUntracked}");
                writer.WriteLine($@"        NumSlots:      {gcInfo.SlotTable.NumSlots}");
                writer.WriteLine($@"        GcSlots:       {gcInfo.SlotTable.GcSlots.Count}");
                foreach (Amd64.GcSlotTable.GcSlot slot in gcInfo.SlotTable.GcSlots)
                {
                    writer.WriteLine($@"            Index: {slot.Index,2}; RegisterNumber: {slot.RegisterNumber,2}; Flags: {slot.Flags}");
                }
                writer.WriteLine();
            }

            if (EHInfo != null)
            {
                writer.WriteLine($@"EH info @ {EHInfo.EHInfoRVA:X4}, #clauses = {EHInfo.EHClauses.Length}");
                EHInfo.WriteTo(writer);
                writer.WriteLine();
            }

            if (DebugInfo != null)
            {
                DebugInfo.WriteTo(writer, options);
            }
        }
Beispiel #4
0
        public void WriteTo(TextWriter writer, DumpOptions options)
        {
            writer.WriteLine($"Id: {Id}");
            writer.WriteLine($"StartAddress: 0x{StartAddress:X8}");
            if (Size == -1)
            {
                writer.WriteLine("Size: Unavailable");
            }
            else
            {
                writer.WriteLine($"Size: {Size} bytes");
            }
            writer.WriteLine($"UnwindRVA: 0x{UnwindRVA:X8}");
            if (UnwindInfo is Amd64.UnwindInfo amd64UnwindInfo)
            {
                string parsedFlags = "";
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0)
                {
                    parsedFlags += " EHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0)
                {
                    parsedFlags += " UHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_CHAININFO) != 0)
                {
                    parsedFlags += " CHAININFO";
                }
                if (parsedFlags.Length == 0)
                {
                    parsedFlags = " NHANDLER";
                }
                writer.WriteLine($"Version:            {amd64UnwindInfo.Version}");
                writer.WriteLine($"Flags:              0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
                writer.WriteLine($"SizeOfProlog:       0x{amd64UnwindInfo.SizeOfProlog:X4}");
                writer.WriteLine($"CountOfUnwindCodes: {amd64UnwindInfo.CountOfUnwindCodes}");
                writer.WriteLine($"FrameRegister:      {amd64UnwindInfo.FrameRegister}");
                writer.WriteLine($"FrameOffset:        0x{amd64UnwindInfo.FrameOffset}");
                writer.WriteLine($"PersonalityRVA:     0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");

                for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++)
                {
                    Amd64.UnwindCode unwindCode = amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex];
                    writer.Write($"UnwindCode[{unwindCode.Index}]: ");
                    writer.Write($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
                    writer.Write($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
                    writer.Write($"NextOffset 0x{unwindCode.NextFrameOffset} ");
                    writer.Write($"Op {unwindCode.OpInfoStr}");
                    writer.WriteLine();
                }
            }
            writer.WriteLine();

            if (EHInfo != null)
            {
                writer.WriteLine($@"EH info @ {EHInfo.EHInfoRVA:X4}, #clauses = {EHInfo.EHClauses.Length}");
                EHInfo.WriteTo(writer);
                writer.WriteLine();
            }

            if (DebugInfo != null)
            {
                DebugInfo.WriteTo(writer, options);
            }
        }
Beispiel #5
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine($"Id: {Id}");
            sb.AppendLine($"StartAddress: 0x{StartAddress:X8}");
            if (Size == -1)
            {
                sb.AppendLine("Size: Unavailable");
            }
            else
            {
                sb.AppendLine($"Size: {Size} bytes");
            }
            sb.AppendLine($"UnwindRVA: 0x{UnwindRVA:X8}");
            if (UnwindInfo is Amd64.UnwindInfo amd64UnwindInfo)
            {
                string parsedFlags = "";
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0)
                {
                    parsedFlags += " EHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0)
                {
                    parsedFlags += " UHANDLER";
                }
                if ((amd64UnwindInfo.Flags & (int)Amd64.UnwindFlags.UNW_FLAG_CHAININFO) != 0)
                {
                    parsedFlags += " CHAININFO";
                }
                if (parsedFlags.Length == 0)
                {
                    parsedFlags = " NHANDLER";
                }
                sb.AppendLine($"Version:            {amd64UnwindInfo.Version}");
                sb.AppendLine($"Flags:              0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
                sb.AppendLine($"SizeOfProlog:       0x{amd64UnwindInfo.SizeOfProlog:X4}");
                sb.AppendLine($"CountOfUnwindCodes: {amd64UnwindInfo.CountOfUnwindCodes}");
                sb.AppendLine($"FrameRegister:      {amd64UnwindInfo.FrameRegister}");
                sb.AppendLine($"FrameOffset:        0x{amd64UnwindInfo.FrameOffset}");
                sb.AppendLine($"PersonalityRVA:     0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");

                for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++)
                {
                    Amd64.UnwindCode unwindCode = amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex];
                    sb.Append($"UnwindCode[{unwindCode.Index}]: ");
                    sb.Append($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
                    sb.Append($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
                    sb.Append($"NextOffset 0x{unwindCode.NextFrameOffset} ");
                    sb.Append($"Op {unwindCode.OpInfoStr}");
                    sb.AppendLine();
                }
            }
            sb.AppendLine();

            if (DebugInfo != null)
            {
                sb.AppendLine(DebugInfo.ToString());
            }

            return(sb.ToString());
        }
Beispiel #6
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)
                {
                    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;
            }
        }