private NativeParser GetParserForBucket(uint bucket, out uint endOffset) { uint start, end; if (_entryIndexSize == 0) { int bucketOffset = (int)(_baseOffset + bucket); start = NativeReader.ReadByte(_image, ref bucketOffset); end = NativeReader.ReadByte(_image, ref bucketOffset); } else if (_entryIndexSize == 1) { int bucketOffset = (int)(_baseOffset + 2 * bucket); start = NativeReader.ReadUInt16(_image, ref bucketOffset); end = NativeReader.ReadUInt16(_image, ref bucketOffset); } else { int bucketOffset = (int)(_baseOffset + 4 * bucket); start = NativeReader.ReadUInt32(_image, ref bucketOffset); end = NativeReader.ReadUInt32(_image, ref bucketOffset); } endOffset = end + _baseOffset; return(new NativeParser(_image, _baseOffset + start)); }
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)); }
/// <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); }
public UnwindCode(byte[] image, int index, ref int offset) { Index = index; int off = offset; CodeOffset = NativeReader.ReadByte(image, ref off); byte op = NativeReader.ReadByte(image, ref off); UnwindOp = (UnwindOpCodes)(op & 15); OpInfo = (byte)(op >> 4); OffsetLow = CodeOffset; OffsetHigh = OpInfo; FrameOffset = NativeReader.ReadUInt16(image, ref offset); NextFrameOffset = -1; if (UnwindOp == UnwindOpCodes.UWOP_ALLOC_LARGE) { uint codedSize; if (OpInfo == 0) { codedSize = NativeReader.ReadUInt16(image, ref offset); } else if (OpInfo == 1) { codedSize = NativeReader.ReadUInt32(image, ref offset); } } IsOpInfo = false; }
/// <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); }
public byte GetByte() { int off = (int)Offset; byte val = NativeReader.ReadByte(_image, ref off); Offset += 1; return(val); }
public UnwindCode(byte[] image, ref int offset) { int off = offset; CodeOffset = NativeReader.ReadByte(image, ref off); byte op = NativeReader.ReadByte(image, ref off); UnwindOp = (UnwindOpCodes)(op & 15); OpInfo = (byte)(op >> 4); OffsetLow = CodeOffset; OffsetHigh = OpInfo; FrameOffset = NativeReader.ReadUInt16(image, ref offset); }
public UnwindCode(byte[] image, int index, ref int offset) { Index = index; int off = offset; CodeOffset = NativeReader.ReadByte(image, ref off); byte op = NativeReader.ReadByte(image, ref off); UnwindOp = (UnwindOpCodes)(op & 15); OpInfo = (byte)(op >> 4); OffsetLow = CodeOffset; OffsetHigh = OpInfo; FrameOffset = NativeReader.ReadUInt16(image, ref offset); NextFrameOffset = -1; IsOpInfo = false; }
/// <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]); } PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset); Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode; int alignmentPad = ((Size + sizeof(int) - 1) & ~(sizeof(int) - 1)) - Size; Size += (alignmentPad + sizeof(uint)); }
/// <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; }
public bool TryGetAt(byte[] image, uint index, ref int pOffset) { if (index >= _nElements) { return(false); } uint offset = 0; if (_entryIndexSize == 0) { int i = (int)(_baseOffset + (index / _blockSize)); offset = NativeReader.ReadByte(image, ref i); } else if (_entryIndexSize == 1) { int i = (int)(_baseOffset + 2 * (index / _blockSize)); offset = NativeReader.ReadUInt16(image, ref i); } else { int i = (int)(_baseOffset + 4 * (index / _blockSize)); offset = NativeReader.ReadUInt32(image, ref i); } offset += _baseOffset; for (uint bit = _blockSize >> 1; bit > 0; bit >>= 1) { uint val = 0; uint offset2 = NativeReader.DecodeUnsigned(image, offset, ref val); if ((index & bit) != 0) { if ((val & 2) != 0) { offset = offset + (val >> 2); continue; } } else { if ((val & 1) != 0) { offset = offset2; continue; } } // Not found if ((val & 3) == 0) { // Matching special leaf node? if ((val >> 2) == (index & (_blockSize - 1))) { offset = offset2; break; } } return(false); } pOffset = (int)offset; return(true); }