/// <summary> /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapimport.cpp">ZapImportSectionsTable::Save</a> /// </summary> private void ParseImportSections() { if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS)) { return; } R2RSection importSectionsSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS]; int offset = GetOffset(importSectionsSection.RelativeVirtualAddress); int endOffset = offset + importSectionsSection.Size; while (offset < endOffset) { int rva = NativeReader.ReadInt32(Image, ref offset); int sectionOffset = GetOffset(rva); int startOffset = sectionOffset; int size = NativeReader.ReadInt32(Image, ref offset); CorCompileImportFlags flags = (CorCompileImportFlags)NativeReader.ReadUInt16(Image, ref offset); byte type = NativeReader.ReadByte(Image, ref offset); byte entrySize = NativeReader.ReadByte(Image, ref offset); if (entrySize == 0) { switch (Machine) { case Machine.I386: case Machine.ArmThumb2: entrySize = 4; break; case Machine.Amd64: case Machine.Arm64: entrySize = 8; break; default: throw new NotImplementedException(Machine.ToString()); } } int entryCount = 0; if (entrySize != 0) { entryCount = size / entrySize; } int signatureRVA = NativeReader.ReadInt32(Image, ref offset); int signatureOffset = 0; if (signatureRVA != 0) { signatureOffset = GetOffset(signatureRVA); } List <R2RImportSection.ImportSectionEntry> entries = new List <R2RImportSection.ImportSectionEntry>(); for (int i = 0; i < entryCount; i++) { int entryOffset = sectionOffset - startOffset; long section = NativeReader.ReadInt64(Image, ref sectionOffset); uint sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); int sigOffset = GetOffset((int)sigRva); string cellName = MetadataNameFormatter.FormatSignature(this, sigOffset); entries.Add(new R2RImportSection.ImportSectionEntry(entries.Count, entryOffset, entryOffset + rva, section, sigRva, cellName)); ImportCellNames.Add(rva + entrySize * i, cellName); } int auxDataRVA = NativeReader.ReadInt32(Image, ref offset); int auxDataOffset = 0; if (auxDataRVA != 0) { auxDataOffset = GetOffset(auxDataRVA); } ImportSections.Add(new R2RImportSection(ImportSections.Count, this, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, R2RHeader.MajorVersion)); } }
internal override void DumpSectionContents(R2RSection section, XmlNode parentNode = null) { switch (section.Type) { case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES: uint availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser availableTypesParser = new NativeParser(_r2r.Image, availableTypesSectionOffset); NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size)); _writer.WriteLine(availableTypes.ToString()); foreach (string name in _r2r.AvailableTypes) { _writer.WriteLine(name); } break; case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS: NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress)); _writer.Write(methodEntryPoints.ToString()); break; case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS: uint instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser instanceParser = new NativeParser(_r2r.Image, instanceSectionOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size)); _writer.Write(instMethodEntryPoints.ToString()); break; case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS: int rtfOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int rtfEndOffset = rtfOffset + section.Size; int rtfIndex = 0; while (rtfOffset < rtfEndOffset) { int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); int endRva = -1; if (_r2r.Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); } int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); _writer.WriteLine($"Index: {rtfIndex}"); _writer.WriteLine($"\tStartRva: 0x{startRva:X8}"); if (endRva != -1) { _writer.WriteLine($"\tEndRva: 0x{endRva:X8}"); } _writer.WriteLine($"\tUnwindRva: 0x{unwindRva:X8}"); rtfIndex++; } break; case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER: _writer.WriteLine(_r2r.CompilerIdentifier); break; case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS: foreach (R2RImportSection importSection in _r2r.ImportSections) { _writer.Write(importSection.ToString()); if (_raw && importSection.Entries.Count != 0) { if (importSection.SectionRVA != 0) { _writer.WriteLine("Section Bytes:"); DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize); } if (importSection.SignatureRVA != 0) { _writer.WriteLine("Signature Bytes:"); DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int)); } if (importSection.AuxiliaryDataRVA != 0) { _writer.WriteLine("AuxiliaryData Bytes:"); DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryData.Size); } } foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries) { _writer.WriteLine(entry.ToString()); } _writer.WriteLine(); } break; } }
internal override void DumpSectionContents(ReadyToRunSection section) { switch (section.Type) { case ReadyToRunSectionType.AvailableTypes: if (!_options.Naked) { uint availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser availableTypesParser = new NativeParser(_r2r.Image, availableTypesSectionOffset); NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size)); _writer.WriteLine(availableTypes.ToString()); } if (_r2r.AvailableTypes.TryGetValue(section, out List <string> sectionTypes)) { _writer.WriteLine(); foreach (string name in sectionTypes) { _writer.WriteLine(name); } } break; case ReadyToRunSectionType.MethodDefEntryPoints: if (!_options.Naked) { NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress)); _writer.Write(methodEntryPoints.ToString()); } if (_r2r.Methods.TryGetValue(section, out List <ReadyToRunMethod> sectionMethods)) { _writer.WriteLine(); foreach (ReadyToRunMethod method in sectionMethods) { _writer.WriteLine($@"{MetadataTokens.GetToken(method.MethodHandle):X8}: {method.SignatureString}"); } } break; case ReadyToRunSectionType.InstanceMethodEntryPoints: if (!_options.Naked) { uint instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser instanceParser = new NativeParser(_r2r.Image, instanceSectionOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size)); _writer.Write(instMethodEntryPoints.ToString()); _writer.WriteLine(); } foreach (InstanceMethod instanceMethod in _r2r.InstanceMethods) { _writer.WriteLine($@"0x{instanceMethod.Bucket:X2} -> {instanceMethod.Method.SignatureString}"); } break; case ReadyToRunSectionType.RuntimeFunctions: int rtfOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int rtfEndOffset = rtfOffset + section.Size; int rtfIndex = 0; while (rtfOffset < rtfEndOffset) { int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); int endRva = -1; if (_r2r.Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); } int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); _writer.WriteLine($"Index: {rtfIndex}"); _writer.WriteLine($" StartRva: 0x{startRva:X8}"); if (endRva != -1) { _writer.WriteLine($" EndRva: 0x{endRva:X8}"); } _writer.WriteLine($" UnwindRva: 0x{unwindRva:X8}"); rtfIndex++; } break; case ReadyToRunSectionType.CompilerIdentifier: _writer.WriteLine(_r2r.CompilerIdentifier); break; case ReadyToRunSectionType.ImportSections: if (_options.Naked) { DumpNakedImportSections(); } else { foreach (ReadyToRunImportSection importSection in _r2r.ImportSections) { importSection.WriteTo(_writer); if (_options.Raw && importSection.Entries.Count != 0) { if (importSection.SectionRVA != 0) { _writer.WriteLine("Section Bytes:"); DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize); } if (importSection.SignatureRVA != 0) { _writer.WriteLine("Signature Bytes:"); DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int)); } if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryDataSize != 0) { _writer.WriteLine("AuxiliaryData Bytes:"); DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize); } } foreach (ReadyToRunImportSection.ImportSectionEntry entry in importSection.Entries) { entry.WriteTo(_writer, _options); _writer.WriteLine(); } _writer.WriteLine(); } } break; case ReadyToRunSectionType.ManifestMetadata: int assemblyRefCount = 0; if (!_r2r.Composite) { MetadataReader globalReader = _r2r.GetGlobalMetadataReader(); assemblyRefCount = globalReader.GetTableRowCount(TableIndex.AssemblyRef) + 1; _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):"); for (int assemblyRefIndex = 1; assemblyRefIndex < assemblyRefCount; assemblyRefIndex++) { AssemblyReference assemblyRef = globalReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex)); string assemblyRefName = globalReader.GetString(assemblyRef.Name); _writer.WriteLine($"[ID 0x{assemblyRefIndex:X2}]: {assemblyRefName}"); } } _writer.WriteLine($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count} entries):"); int manifestAsmIndex = 0; foreach (string manifestReferenceAssembly in _r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key)) { _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 1:X2}]: {manifestReferenceAssembly}"); manifestAsmIndex++; } break; case ReadyToRunSectionType.AttributePresence: int attributesStartOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int attributesEndOffset = attributesStartOffset + section.Size; NativeCuckooFilter attributes = new NativeCuckooFilter(_r2r.Image, attributesStartOffset, attributesEndOffset); _writer.WriteLine("Attribute presence filter"); _writer.WriteLine(attributes.ToString()); break; case ReadyToRunSectionType.InliningInfo: int iiOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int iiEndOffset = iiOffset + section.Size; InliningInfoSection inliningInfoSection = new InliningInfoSection(_r2r, iiOffset, iiEndOffset); _writer.WriteLine(inliningInfoSection.ToString()); break; case ReadyToRunSectionType.InliningInfo2: int ii2Offset = _r2r.GetOffset(section.RelativeVirtualAddress); int ii2EndOffset = ii2Offset + section.Size; InliningInfoSection2 inliningInfoSection2 = new InliningInfoSection2(_r2r, ii2Offset, ii2EndOffset); _writer.WriteLine(inliningInfoSection2.ToString()); break; case ReadyToRunSectionType.OwnerCompositeExecutable: int oceOffset = _r2r.GetOffset(section.RelativeVirtualAddress); if (_r2r.Image[oceOffset + section.Size - 1] != 0) { R2RDump.WriteWarning("String is not zero-terminated"); } string ownerCompositeExecutable = Encoding.UTF8.GetString(_r2r.Image, oceOffset, section.Size - 1); // exclude the zero terminator _writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable.ToEscapedString()); break; } }
/// <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); } RuntimeFunction rtf = new RuntimeFunction( runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo, ehInfo, _runtimeFunctionToDebugInfo.GetValueOrDefault(runtimeFunctionId)); method.RuntimeFunctions.Add(rtf); runtimeFunctionId++; codeOffset += rtf.Size; }while (runtimeFunctionId < isEntryPoint.Length && !isEntryPoint[runtimeFunctionId]); } }
private void ParseImportSections() { if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS)) { return; } R2RSection importSectionsSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS]; int offset = GetOffset(importSectionsSection.RelativeVirtualAddress); int endOffset = offset + importSectionsSection.Size; while (offset < endOffset) { int rva = NativeReader.ReadInt32(Image, ref offset); int sectionOffset = GetOffset(rva); int startOffset = sectionOffset; int size = NativeReader.ReadInt32(Image, ref offset); R2RImportSection.CorCompileImportFlags flags = (R2RImportSection.CorCompileImportFlags)NativeReader.ReadUInt16(Image, ref offset); byte type = NativeReader.ReadByte(Image, ref offset); byte entrySize = NativeReader.ReadByte(Image, ref offset); int entryCount = 0; if (entrySize != 0) { entryCount = size / entrySize; } int signatureRVA = NativeReader.ReadInt32(Image, ref offset); int signatureOffset = 0; if (signatureRVA != 0) { signatureOffset = GetOffset(signatureRVA); } List <R2RImportSection.ImportSectionEntry> entries = new List <R2RImportSection.ImportSectionEntry>(); switch (flags) { case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_EAGER: { int tempSignatureOffset = signatureOffset; int firstSigRva = NativeReader.ReadInt32(Image, ref tempSignatureOffset); uint sigRva = 0; while (sigRva != firstSigRva) { int entryOffset = sectionOffset - startOffset; sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); long section = NativeReader.ReadInt64(Image, ref sectionOffset); int sigOff = GetOffset((int)sigRva); int sigSampleLength = Math.Min(8, Image.Length - sigOff); byte[] signatureSample = new byte[sigSampleLength]; Array.Copy(Image, sigOff, signatureSample, 0, sigSampleLength); entries.Add(new R2RImportSection.ImportSectionEntry(entryOffset, section, sigRva, signatureSample)); } } break; case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_CODE: case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_PCODE: for (int i = 0; i < entryCount; i++) { int entryOffset = sectionOffset - startOffset; long section = NativeReader.ReadInt64(Image, ref sectionOffset); uint sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); int sigOff = GetOffset((int)sigRva); int sigSampleLength = Math.Min(8, Image.Length - sigOff); byte[] signatureSample = new byte[sigSampleLength]; Array.Copy(Image, sigOff, signatureSample, 0, sigSampleLength); entries.Add(new R2RImportSection.ImportSectionEntry(entryOffset, section, sigRva, signatureSample)); } break; } int auxDataRVA = NativeReader.ReadInt32(Image, ref offset); int auxDataOffset = 0; if (auxDataRVA != 0) { auxDataOffset = GetOffset(auxDataRVA); } ImportSections.Add(new R2RImportSection(Image, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, R2RHeader.MajorVersion)); } }
internal override void DumpSectionContents(R2RSection section, XmlNode parentNode = null) { switch (section.Type) { case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES: if (!_options.Naked) { uint availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser availableTypesParser = new NativeParser(_r2r.Image, availableTypesSectionOffset); NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size)); _writer.WriteLine(availableTypes.ToString()); } foreach (string name in _r2r.AvailableTypes) { _writer.WriteLine(name); } break; case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS: if (!_options.Naked) { NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress)); _writer.Write(methodEntryPoints.ToString()); } break; case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS: if (!_options.Naked) { uint instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress); NativeParser instanceParser = new NativeParser(_r2r.Image, instanceSectionOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size)); _writer.Write(instMethodEntryPoints.ToString()); _writer.WriteLine(); } foreach (InstanceMethod instanceMethod in _r2r.InstanceMethods) { _writer.WriteLine($@"0x{instanceMethod.Bucket:X2} -> {instanceMethod.Method.SignatureString}"); } break; case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS: int rtfOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int rtfEndOffset = rtfOffset + section.Size; int rtfIndex = 0; while (rtfOffset < rtfEndOffset) { int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); int endRva = -1; if (_r2r.Machine == Machine.Amd64) { endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); } int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset); _writer.WriteLine($"Index: {rtfIndex}"); _writer.WriteLine($"\tStartRva: 0x{startRva:X8}"); if (endRva != -1) { _writer.WriteLine($"\tEndRva: 0x{endRva:X8}"); } _writer.WriteLine($"\tUnwindRva: 0x{unwindRva:X8}"); rtfIndex++; } break; case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER: _writer.WriteLine(_r2r.CompilerIdentifier); break; case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS: if (_options.Naked) { DumpNakedImportSections(); } else { foreach (R2RImportSection importSection in _r2r.ImportSections) { importSection.WriteTo(_writer); if (_options.Raw && importSection.Entries.Count != 0) { if (importSection.SectionRVA != 0) { _writer.WriteLine("Section Bytes:"); DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize); } if (importSection.SignatureRVA != 0) { _writer.WriteLine("Signature Bytes:"); DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int)); } if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryDataSize != 0) { _writer.WriteLine("AuxiliaryData Bytes:"); DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize); } } foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries) { entry.WriteTo(_writer, _options); _writer.WriteLine(); } _writer.WriteLine(); } } break; case R2RSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA: int assemblyRefCount = _r2r.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef); _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):"); for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++) { AssemblyReference assemblyRef = _r2r.MetadataReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex)); string assemblyRefName = _r2r.MetadataReader.GetString(assemblyRef.Name); _writer.WriteLine($"[ID 0x{assemblyRefIndex:X2}]: {assemblyRefName}"); } _writer.WriteLine($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count} entries):"); for (int manifestAsmIndex = 0; manifestAsmIndex < _r2r.ManifestReferenceAssemblies.Count; manifestAsmIndex++) { _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {_r2r.ManifestReferenceAssemblies[manifestAsmIndex]}"); } break; } }
public Dictionary <int, GcTransition> GetTranstions(byte[] image, ref int bitOffset) { int totalInterruptibleLength = 0; if (NumInterruptibleRanges == 0) { totalInterruptibleLength = CodeLength; } else { foreach (InterruptibleRange range in InterruptibleRanges) { totalInterruptibleLength += (int)(range.StopOffset - range.StartOffset); } } int numChunks = (totalInterruptibleLength + _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK; //=2 int numBitsPerPointer = (int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.POINTER_SIZE_ENCBASE, ref bitOffset); if (numBitsPerPointer == 0) { return(new Dictionary <int, GcTransition>()); } int[] chunkPointers = new int[numChunks]; for (int i = 0; i < numChunks; i++) { chunkPointers[i] = NativeReader.ReadBits(image, numBitsPerPointer, ref bitOffset); } int info2Offset = (int)Math.Ceiling(bitOffset / 8.0) * 8; List <GcTransition> transitions = new List <GcTransition>(); bool[] liveAtEnd = new bool[SlotTable.GcSlots.Count - SlotTable.NumUntracked]; for (int currentChunk = 0; currentChunk < numChunks; currentChunk++) { if (chunkPointers[currentChunk] == 0) { continue; } else { bitOffset = info2Offset + chunkPointers[currentChunk] - 1; } int couldBeLiveOffset = bitOffset; int slotId = 0; bool fSimple = (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0); bool fSkipFirst = false; int couldBeLiveCnt = 0; if (!fSimple) { fSkipFirst = (NativeReader.ReadBits(image, 1, ref couldBeLiveOffset) == 0); slotId = -1; } uint numCouldBeLiveSlots = GetNumCouldBeLiveSlots(image, ref bitOffset); int finalStateOffset = bitOffset; bitOffset += (int)numCouldBeLiveSlots; int normChunkBaseCodeOffset = currentChunk * _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK; for (int i = 0; i < numCouldBeLiveSlots; i++) { slotId = GetNextSlotId(image, fSimple, fSkipFirst, slotId, ref couldBeLiveCnt, ref couldBeLiveOffset); bool isLive = !liveAtEnd[slotId]; liveAtEnd[slotId] = (NativeReader.ReadBits(image, 1, ref finalStateOffset) != 0); // Read transitions while (NativeReader.ReadBits(image, 1, ref bitOffset) != 0) { int transitionOffset = NativeReader.ReadBits(image, _gcInfoTypes.NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2, ref bitOffset) + normChunkBaseCodeOffset; transitions.Add(new GcTransition(transitionOffset, slotId, isLive, currentChunk)); isLive = !isLive; } slotId++; } } transitions.Sort((s1, s2) => s1.CodeOffset.CompareTo(s2.CodeOffset)); return(UpdateTransitionCodeOffset(transitions)); }
/// <summary> /// Initializes the fields of the R2RHeader and R2RMethods /// </summary> /// <param name="filename">PE image</param> /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception> public unsafe R2RReader(string filename) { Filename = filename; Image = File.ReadAllBytes(filename); fixed(byte *p = Image) { IntPtr ptr = (IntPtr)p; peReader = new PEReader(p, Image.Length); IsR2R = (peReader.PEHeaders.CorHeader.Flags == CorFlags.ILLibrary); if (!IsR2R) { throw new BadImageFormatException("The file is not a ReadyToRun image"); } Machine = peReader.PEHeaders.CoffHeader.Machine; ImageBase = peReader.PEHeaders.PEHeader.ImageBase; // initialize R2RHeader DirectoryEntry r2rHeaderDirectory = peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory; int r2rHeaderOffset = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress); R2RHeader = new R2RHeader(Image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset); if (r2rHeaderDirectory.Size != R2RHeader.Size) { throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory"); } // initialize R2RMethods if (peReader.HasMetadata) { MetadataReader mdReader = peReader.GetMetadataReader(); int runtimeFunctionSize = 2; if (Machine == Machine.Amd64) { runtimeFunctionSize = 3; } runtimeFunctionSize *= sizeof(int); R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS]; uint nRuntimeFunctions = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize); int runtimeFunctionOffset = GetOffset(runtimeFunctionSection.RelativeVirtualAddress); bool[] isEntryPoint = new bool[nRuntimeFunctions]; for (int i = 0; i < nRuntimeFunctions; i++) { isEntryPoint[i] = false; } // initialize R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints int methodDefEntryPointsRVA = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS].RelativeVirtualAddress; int methodDefEntryPointsOffset = GetOffset(methodDefEntryPointsRVA); NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset); uint nMethodEntryPoints = methodEntryPoints.GetCount(); R2RMethods = new List <R2RMethod>(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { R2RMethod method = new R2RMethod(Image, mdReader, rid, GetEntryPointIdFromOffset(offset), null, null); if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= nRuntimeFunctions) { throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds"); } isEntryPoint[method.EntryPointRuntimeFunctionId] = true; R2RMethods.Add(method); } } // instance method table R2RSection instMethodEntryPointSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS]; int instMethodEntryPointsOffset = GetOffset(instMethodEntryPointSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)instMethodEntryPointsOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(Image, parser); NativeHashtable.AllEntriesEnumerator allEntriesEnum = instMethodEntryPoints.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { uint methodFlags = curParser.GetCompressedData(); uint rid = curParser.GetCompressedData(); if ((methodFlags & (byte)R2RMethod.EncodeMethodSigFlags.ENCODE_METHOD_SIG_MethodInstantiation) != 0) { uint nArgs = curParser.GetCompressedData(); R2RMethod.GenericElementTypes[] args = new R2RMethod.GenericElementTypes[nArgs]; uint[] tokens = new uint[nArgs]; for (int i = 0; i < nArgs; i++) { args[i] = (R2RMethod.GenericElementTypes)curParser.GetByte(); if (args[i] == R2RMethod.GenericElementTypes.ValueType) { tokens[i] = curParser.GetCompressedData(); tokens[i] = (tokens[i] >> 2); } } uint id = curParser.GetUnsigned(); id = id >> 1; R2RMethod method = new R2RMethod(Image, mdReader, rid, (int)id, args, tokens); if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < nRuntimeFunctions) { isEntryPoint[method.EntryPointRuntimeFunctionId] = true; } R2RMethods.Add(method); } curParser = allEntriesEnum.GetNext(); } // get the RVAs of the runtime functions for each method int curOffset = 0; foreach (R2RMethod method in R2RMethods) { int runtimeFunctionId = method.EntryPointRuntimeFunctionId; if (runtimeFunctionId == -1) { continue; } curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize; 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); method.RuntimeFunctions.Add(new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva, method)); runtimeFunctionId++; }while (runtimeFunctionId < nRuntimeFunctions && !isEntryPoint[runtimeFunctionId]); } } } }
public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion) { Offset = offset; _gcInfoTypes = new GcInfoTypes(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; _machine = machine; }
internal override void DumpSectionContents(R2RSection section, XmlNode parentNode) { XmlNode contentsNode = XmlDocument.CreateNode("element", "Contents", ""); parentNode.AppendChild(contentsNode); switch (section.Type) { case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES: int availableTypesId = 0; foreach (string name in _r2r.AvailableTypes) { AddXMLNode("AvailableType", name, contentsNode, $"{availableTypesId++}"); } break; case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS: if (_ignoreSensitive) { break; } int rtfOffset = _r2r.GetOffset(section.RelativeVirtualAddress); int rtfEndOffset = rtfOffset + section.Size; int rtfIndex = 0; while (rtfOffset < rtfEndOffset) { uint rva = NativeReader.ReadUInt32(_r2r.Image, ref rtfOffset); AddXMLNode($"id{rtfIndex}", $"0x{rva:X8}", contentsNode, $"{rtfIndex}"); rtfIndex++; } break; case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER: AddXMLNode("CompilerIdentifier", _r2r.CompilerIdentifier, contentsNode); break; case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS: foreach (R2RImportSection importSection in _r2r.ImportSections) { XmlNode importSectionsNode = XmlDocument.CreateNode("element", "ImportSection", ""); AddXMLAttribute(importSectionsNode, "Index", $"{importSection.Index}"); contentsNode.AppendChild(importSectionsNode); Serialize(importSection, importSectionsNode); if (_options.Raw && importSection.Entries.Count != 0) { if (importSection.SectionRVA != 0) { DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize, importSectionsNode, "SectionBytes"); } if (importSection.SignatureRVA != 0) { DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int), importSectionsNode, "SignatureBytes"); } if (importSection.AuxiliaryDataRVA != 0) { DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize, importSectionsNode, "AuxiliaryDataBytes"); } } foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries) { Serialize(entry, importSectionsNode); } } break; } }
/// <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); } } RuntimeFunction rtf = new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo); method.RuntimeFunctions.Add(rtf); runtimeFunctionId++; codeOffset += rtf.Size; }while (runtimeFunctionId < isEntryPoint.Length && !isEntryPoint[runtimeFunctionId]); } }
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); }
private void DumpSectionContents(R2RReader r2r, R2RSection section) { switch (section.Type) { case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES: uint availableTypesSectionOffset = (uint)r2r.GetOffset(section.RelativeVirtualAddress); NativeParser availableTypesParser = new NativeParser(r2r.Image, availableTypesSectionOffset); NativeHashtable availableTypes = new NativeHashtable(r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size)); _writer.WriteLine(availableTypes.ToString()); foreach (string name in r2r.AvailableTypes) { _writer.WriteLine(name); } break; case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS: NativeArray methodEntryPoints = new NativeArray(r2r.Image, (uint)r2r.GetOffset(section.RelativeVirtualAddress)); _writer.Write(methodEntryPoints.ToString()); break; case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS: uint instanceSectionOffset = (uint)r2r.GetOffset(section.RelativeVirtualAddress); NativeParser instanceParser = new NativeParser(r2r.Image, instanceSectionOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size)); _writer.Write(instMethodEntryPoints.ToString()); break; case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS: int rtfOffset = r2r.GetOffset(section.RelativeVirtualAddress); int rtfEndOffset = rtfOffset + section.Size; int rtfIndex = 0; while (rtfOffset < rtfEndOffset) { uint rva = NativeReader.ReadUInt32(r2r.Image, ref rtfOffset); _writer.WriteLine($"{rtfIndex}: 0x{rva:X8}"); rtfIndex++; } break; case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER: _writer.WriteLine(r2r.CompileIdentifier); break; case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS: foreach (R2RImportSection importSection in r2r.ImportSections) { _writer.Write(importSection.ToString()); if (_raw && importSection.Entries.Count != 0) { if (importSection.SectionRVA != 0) { _writer.WriteLine("Section Bytes:"); DumpBytes(r2r, importSection.SectionRVA, (uint)importSection.SectionSize); } if (importSection.SignatureRVA != 0) { _writer.WriteLine("Signature Bytes:"); DumpBytes(r2r, importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int)); } if (importSection.AuxiliaryDataRVA != 0) { _writer.WriteLine("AuxiliaryData Bytes:"); DumpBytes(r2r, importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryData.Size); } } foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries) { _writer.WriteLine(); _writer.WriteLine(entry.ToString()); } _writer.WriteLine(); } break; } }