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 = (byte)(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)); }
public static void WriteTo(this RuntimeFunction theThis, TextWriter writer, DumpOptions options) { if (!options.Naked) { writer.WriteLine($"Id: {theThis.Id}"); writer.WriteLine($"StartAddress: 0x{theThis.StartAddress:X8}"); } if (theThis.Size == -1) { writer.WriteLine("Size: Unavailable"); } else { writer.WriteLine($"Size: {theThis.Size} bytes"); } if (!options.Naked) { writer.WriteLine($"UnwindRVA: 0x{theThis.UnwindRVA:X8}"); } if (theThis.UnwindInfo is ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo amd64UnwindInfo) { string parsedFlags = ""; if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_EHANDLER) != 0) { parsedFlags += " EHANDLER"; } if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.Amd64.UnwindFlags.UNW_FLAG_UHANDLER) != 0) { parsedFlags += " UHANDLER"; } if ((amd64UnwindInfo.Flags & (int)ILCompiler.Reflection.ReadyToRun.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 == 0) ? "None" : amd64UnwindInfo.FrameRegister.ToString())}"); writer.WriteLine($"FrameOffset: 0x{amd64UnwindInfo.FrameOffset}"); if (!options.Naked) { writer.WriteLine($"PersonalityRVA: 0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}"); } for (int uwcIndex = 0; uwcIndex < amd64UnwindInfo.UnwindCodes.Count; uwcIndex++) { UnwindCode unwindCode = amd64UnwindInfo.UnwindCodes[uwcIndex]; writer.Write($"UnwindCode[{uwcIndex}]: "); 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(); uwcIndex++; } } writer.WriteLine(); if (theThis.EHInfo != null) { writer.WriteLine($@"EH info @ {theThis.EHInfo.RelativeVirtualAddress:X4}, #clauses = {theThis.EHInfo.EHClauses.Count}"); theThis.EHInfo.WriteTo(writer); writer.WriteLine(); } if (theThis.DebugInfo != null) { theThis.DebugInfo.WriteTo(writer, options); } }