private void EnsureInitialized() { if (_gcInfo == null) { ParseRuntimeFunctions(true); if (GcInfoRva != 0) { int gcInfoOffset = _readyToRunReader.CompositeReader.GetOffset(GcInfoRva); if (_readyToRunReader.Machine == Machine.I386) { _gcInfo = new x86.GcInfo(_readyToRunReader.Image, gcInfoOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } else { // Arm and Arm64 use the same GcInfo format as Amd64 _gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, gcInfoOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } } } if (_pgoInfo == null) { _pgoInfo = _readyToRunReader.GetPgoInfoByKey(PgoInfoKey.FromReadyToRunMethod(this)); if (_pgoInfo == null) { _pgoInfo = PgoInfo.EmptySingleton; } } }
private void EnsureInitialized() { if (_gcInfo == null && GetGcInfo != null) { _gcInfo = GetGcInfo(); } }
private void EnsureInitialized() { if (_gcInfo == null && GcInfoRva != 0) { int gcInfoOffset = _readyToRunReader.CompositeReader.GetOffset(GcInfoRva); if (_readyToRunReader.Machine == Machine.I386) { _gcInfo = new x86.GcInfo(_readyToRunReader.Image, gcInfoOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } else { // Arm and Arm64 use the same GcInfo format as Amd64 _gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, gcInfoOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } } }
public RuntimeFunction( int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, BaseUnwindInfo unwindInfo, BaseGcInfo gcInfo, EHInfo ehInfo, DebugInfo debugInfo) { Id = id; StartAddress = startRva; UnwindRVA = unwindRva; Method = method; UnwindInfo = unwindInfo; DebugInfo = debugInfo; if (endRva != -1) { Size = endRva - startRva; } else if (unwindInfo is x86.UnwindInfo) { Size = (int)((x86.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm.UnwindInfo) { Size = (int)((Arm.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm64.UnwindInfo) { Size = (int)((Arm64.UnwindInfo)unwindInfo).FunctionLength; } else if (gcInfo != null) { Size = gcInfo.CodeLength; } else { Size = -1; } CodeOffset = codeOffset; method.GcInfo = gcInfo; EHInfo = ehInfo; }
public RuntimeFunction( ReadyToRunReader readyToRunReader, int id, int startRva, int endRva, int unwindRva, int codeOffset, ReadyToRunMethod method, BaseUnwindInfo unwindInfo, BaseGcInfo gcInfo) { _readyToRunReader = readyToRunReader; Id = id; StartAddress = startRva; UnwindRVA = unwindRva; Method = method; UnwindInfo = unwindInfo; if (endRva != -1) { Size = endRva - startRva; } else if (unwindInfo is x86.UnwindInfo) { Size = (int)((x86.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm.UnwindInfo) { Size = (int)((Arm.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm64.UnwindInfo) { Size = (int)((Arm64.UnwindInfo)unwindInfo).FunctionLength; } else if (gcInfo != null) { Size = gcInfo.CodeLength; } else { Size = -1; } CodeOffset = codeOffset; method.GcInfo = gcInfo; }
/// <summary> /// Get the RVAs of the runtime functions for each method /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapcode.cpp">ZapUnwindInfo::Save</a> /// </summary> private void ParseRuntimeFunctions(bool[] isEntryPoint, int runtimeFunctionOffset, int runtimeFunctionSize) { int curOffset = 0; foreach (R2RMethod method in R2RMethods) { int runtimeFunctionId = method.EntryPointRuntimeFunctionId; if (runtimeFunctionId == -1) { continue; } curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize; BaseGcInfo gcInfo = null; int codeOffset = 0; do { int startRva = NativeReader.ReadInt32(Image, ref curOffset); int endRva = -1; if (Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(Image, ref curOffset); } int unwindRva = NativeReader.ReadInt32(Image, ref curOffset); int unwindOffset = GetOffset(unwindRva); BaseUnwindInfo unwindInfo = null; if (Machine == Machine.Amd64) { unwindInfo = new Amd64.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, R2RHeader.MajorVersion); } } else if (Machine == Machine.I386) { unwindInfo = new x86.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new x86.GcInfo(Image, unwindOffset, Machine, R2RHeader.MajorVersion); } } else if (Machine == Machine.ArmThumb2) { unwindInfo = new Arm.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, R2RHeader.MajorVersion); // Arm and Arm64 use the same GcInfo format as x64 } } else if (Machine == Machine.Arm64) { unwindInfo = new Arm64.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, R2RHeader.MajorVersion); } } EHInfo ehInfo = null; EHInfoLocation ehInfoLocation; if (EHLookupTable != null && EHLookupTable.RuntimeFunctionToEHInfoMap.TryGetValue(startRva, out ehInfoLocation)) { ehInfo = new EHInfo(this, ehInfoLocation.EHInfoRVA, startRva, GetOffset(ehInfoLocation.EHInfoRVA), ehInfoLocation.ClauseCount); } DebugInfo debugInfo; _runtimeFunctionToDebugInfo.TryGetValue(runtimeFunctionId, out debugInfo); RuntimeFunction rtf = new RuntimeFunction( runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo, ehInfo, debugInfo); method.RuntimeFunctions.Add(rtf); runtimeFunctionId++; codeOffset += rtf.Size; }while (runtimeFunctionId < isEntryPoint.Length && !isEntryPoint[runtimeFunctionId]); } }
private void ParseRuntimeFunctionsForMethod(bool[] isEntryPoint, int curOffset, ReadyToRunMethod method, int runtimeFunctionId) { BaseGcInfo gcInfo = null; int codeOffset = 0; do { int startRva = NativeReader.ReadInt32(Image, ref curOffset); int endRva = -1; if (Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(Image, ref curOffset); } int unwindRva = NativeReader.ReadInt32(Image, ref curOffset); int unwindOffset = GetOffset(unwindRva); BaseUnwindInfo unwindInfo = null; if (Machine == Machine.Amd64) { unwindInfo = new Amd64.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, ReadyToRunHeader.MajorVersion); } } else if (Machine == Machine.I386) { unwindInfo = new x86.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new x86.GcInfo(Image, unwindOffset, Machine, ReadyToRunHeader.MajorVersion); } } else if (Machine == Machine.ArmThumb2) { unwindInfo = new Arm.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, ReadyToRunHeader.MajorVersion); // Arm and Arm64 use the same GcInfo format as x64 } } else if (Machine == Machine.Arm64) { unwindInfo = new Arm64.UnwindInfo(Image, unwindOffset); if (isEntryPoint[runtimeFunctionId]) { gcInfo = new Amd64.GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, ReadyToRunHeader.MajorVersion); } } RuntimeFunction rtf = new RuntimeFunction( this, runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo); method.RuntimeFunctions.Add(rtf); runtimeFunctionId++; codeOffset += rtf.Size; }while (runtimeFunctionId < isEntryPoint.Length && !isEntryPoint[runtimeFunctionId]); }
/// <summary> /// Get the RVAs of the runtime functions for each method /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapcode.cpp">ZapUnwindInfo::Save</a> /// </summary> private void ParseRuntimeFunctions() { int runtimeFunctionId = EntryPointRuntimeFunctionId; int runtimeFunctionSize = _readyToRunReader.CalculateRuntimeFunctionSize(); int runtimeFunctionOffset = _readyToRunReader.CompositeReader.GetOffset(_readyToRunReader.ReadyToRunHeader.Sections[ReadyToRunSectionType.RuntimeFunctions].RelativeVirtualAddress); int curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize; BaseGcInfo gcInfo = null; int codeOffset = 0; for (int i = 0; i < RuntimeFunctionCount; i++) { int startRva = NativeReader.ReadInt32(_readyToRunReader.Image, ref curOffset); int endRva = -1; if (_readyToRunReader.Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(_readyToRunReader.Image, ref curOffset); } int unwindRva = NativeReader.ReadInt32(_readyToRunReader.Image, ref curOffset); int unwindOffset = _readyToRunReader.CompositeReader.GetOffset(unwindRva); BaseUnwindInfo unwindInfo = null; if (_readyToRunReader.Machine == Machine.Amd64) { unwindInfo = new Amd64.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } } else if (_readyToRunReader.Machine == Machine.I386) { unwindInfo = new x86.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { gcInfo = new x86.GcInfo(_readyToRunReader.Image, unwindOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } } else if (_readyToRunReader.Machine == Machine.ArmThumb2) { unwindInfo = new Arm.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); // Arm and Arm64 use the same GcInfo format as x64 } } else if (_readyToRunReader.Machine == Machine.Arm64) { unwindInfo = new Arm64.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); } } RuntimeFunction rtf = new RuntimeFunction( _readyToRunReader, runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, this, unwindInfo, gcInfo); _runtimeFunctions.Add(rtf); runtimeFunctionId++; codeOffset += rtf.Size; } }