public string GetSlotState(GcSlotTable slotTable, Machine machine) { GcSlotTable.GcSlot slot = slotTable.GcSlots[SlotId]; string slotStr = ""; if (slot.StackSlot == null) { Type regType = typeof(Amd64.Registers); if (machine == Machine.ArmThumb2) { regType = typeof(Arm.Registers); } else { regType = typeof(Arm64.Registers); } slotStr = Enum.GetName(regType, slot.RegisterNumber); } else { slotStr = $"sp{slot.StackSlot.SpOffset:+#;-#;+0}"; } string isLiveStr = "live"; if (!IsLive) { isLiveStr = "dead"; } return($"{slotStr} is {isLiveStr}"); }
public GcTransition(int codeOffset, int slotId, bool isLive, int chunkId, GcSlotTable slotTable, Machine machine) { CodeOffset = codeOffset; SlotId = slotId; IsLive = isLive; ChunkId = chunkId; SlotState = GetSlotState(slotTable, machine); }
public string GetSlotState(GcSlotTable slotTable) { GcSlotTable.GcSlot slot = slotTable.GcSlots[SlotId]; string slotStr = ""; if (slot.StackSlot == null) { slotStr = Enum.GetName(typeof(Registers), slot.RegisterNumber); } else { slotStr = $"sp{slot.StackSlot.SpOffset:+#;-#;+0}"; } string isLiveStr = "live"; if (!IsLive) { isLiveStr = "dead"; } return($"{slotStr} is {isLiveStr}"); }
public string GetSlotState(GcSlotTable slotTable, Machine machine) { GcSlotTable.GcSlot slot = slotTable.GcSlots[SlotId]; string slotStr = ""; if (slot.StackSlot == null) { Type regType; switch (machine) { case Machine.ArmThumb2: regType = typeof(Arm.Registers); break; case Machine.Arm64: regType = typeof(Arm64.Registers); break; case Machine.Amd64: regType = typeof(Amd64.Registers); break; default: throw new NotImplementedException(); } slotStr = Enum.GetName(regType, slot.RegisterNumber); } else { slotStr = $"sp{slot.StackSlot.SpOffset:+#;-#;+0}"; } string isLiveStr = "live"; if (!IsLive) { isLiveStr = "dead"; } return($"{slotStr} is {isLiveStr}"); }
/// <summary> /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/vm/gcinfodecoder.cpp">GcInfoDecoder::GcInfoDecoder</a> /// </summary> public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion) { Offset = offset; _gcInfoTypes = new GcInfoTypes(machine); _machine = machine; SecurityObjectStackSlot = -1; GSCookieStackSlot = -1; PSPSymStackSlot = -1; SecurityObjectStackSlot = -1; GenericsInstContextStackSlot = -1; StackBaseRegister = 0xffffffff; SizeOfEditAndContinuePreservedArea = 0xffffffff; ReversePInvokeFrameStackSlot = -1; Version = ReadyToRunVersionToGcInfoVersion(majorVersion); int bitOffset = offset * 8; int startBitOffset = bitOffset; ParseHeaderFlags(image, ref bitOffset); if (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND) // IsReturnKindAvailable { int returnKindBits = (_slimHeader) ? _gcInfoTypes.SIZE_OF_RETURN_KIND_SLIM : _gcInfoTypes.SIZE_OF_RETURN_KIND_FAT; ReturnKind = (ReturnKinds)NativeReader.ReadBits(image, returnKindBits, ref bitOffset); } CodeLength = _gcInfoTypes.DenormalizeCodeLength((int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.CODE_LENGTH_ENCBASE, ref bitOffset)); if (_hasGSCookie) { uint normPrologSize = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1; uint normEpilogSize = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset); ValidRangeStart = normPrologSize; ValidRangeEnd = (uint)CodeLength - normEpilogSize; } else if (_hasSecurityObject || _hasGenericsInstContext) { ValidRangeStart = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1; ValidRangeEnd = ValidRangeStart + 1; } if (_hasSecurityObject) { SecurityObjectStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.SECURITY_OBJECT_STACK_SLOT_ENCBASE, ref bitOffset)); } if (_hasGSCookie) { GSCookieStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.GS_COOKIE_STACK_SLOT_ENCBASE, ref bitOffset)); } if (_hasPSPSym) { PSPSymStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.PSP_SYM_STACK_SLOT_ENCBASE, ref bitOffset)); } if (_hasGenericsInstContext) { GenericsInstContextStackSlot = _gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, ref bitOffset)); } if (_hasStackBaseRegister && !_slimHeader) { StackBaseRegister = _gcInfoTypes.DenormalizeStackBaseRegister(NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.STACK_BASE_REGISTER_ENCBASE, ref bitOffset)); } if (_hasSizeOfEditAndContinuePreservedArea) { SizeOfEditAndContinuePreservedArea = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, ref bitOffset); } if (_hasReversePInvokeFrame) { ReversePInvokeFrameStackSlot = NativeReader.DecodeVarLengthSigned(image, _gcInfoTypes.REVERSE_PINVOKE_FRAME_ENCBASE, ref bitOffset); } // FIXED_STACK_PARAMETER_SCRATCH_AREA (this macro is always defined in _gcInfoTypes.h) if (!_slimHeader) { SizeOfStackOutgoingAndScratchArea = _gcInfoTypes.DenormalizeSizeOfStackArea(NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.SIZE_OF_STACK_AREA_ENCBASE, ref bitOffset)); } // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in _gcInfoTypes.h) NumSafePoints = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NUM_SAFE_POINTS_ENCBASE, ref bitOffset); if (!_slimHeader) { NumInterruptibleRanges = NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.NUM_INTERRUPTIBLE_RANGES_ENCBASE, ref bitOffset); } // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in _gcInfoTypes.h) SafePointOffsets = EnumerateSafePoints(image, ref bitOffset); uint numBitsPerOffset = GcInfoTypes.CeilOfLog2(CodeLength); bitOffset += (int)(NumSafePoints * numBitsPerOffset); InterruptibleRanges = EnumerateInterruptibleRanges(image, _gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA1_ENCBASE, _gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA2_ENCBASE, ref bitOffset); SlotTable = new GcSlotTable(image, machine, _gcInfoTypes, ref bitOffset); Transitions = GetTranstions(image, ref bitOffset); Size = bitOffset - startBitOffset; }