Files
2026-03-30 20:11:57 +07:00

158 lines
4.6 KiB
C#

//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2015 Jb Evain
// Copyright (c) 2008 - 2011 Novell, Inc.
//
// Licensed under the MIT/X11 license.
//
using MonoFN.Cecil.Cil;
using MonoFN.Cecil.Metadata;
using System;
using System.IO;
using RVA = System.UInt32;
namespace MonoFN.Cecil.PE
{
internal sealed class Image : IDisposable
{
public Disposable<Stream> Stream;
public string FileName;
public ModuleKind Kind;
public uint Characteristics;
public string RuntimeVersion;
public TargetArchitecture Architecture;
public ModuleCharacteristics DllCharacteristics;
public ushort LinkerVersion;
public ushort SubSystemMajor;
public ushort SubSystemMinor;
public ImageDebugHeader DebugHeader;
public Section[] Sections;
public Section MetadataSection;
public uint EntryPointToken;
public uint Timestamp;
public ModuleAttributes Attributes;
public DataDirectory Win32Resources;
public DataDirectory Debug;
public DataDirectory Resources;
public DataDirectory StrongName;
public StringHeap StringHeap;
public BlobHeap BlobHeap;
public UserStringHeap UserStringHeap;
public GuidHeap GuidHeap;
public TableHeap TableHeap;
public PdbHeap PdbHeap;
private readonly int[] coded_index_sizes = new int [14];
private readonly Func<Table, int> counter;
public Image()
{
counter = GetTableLength;
}
public bool HasTable(Table table)
{
return GetTableLength(table) > 0;
}
public int GetTableLength(Table table)
{
return (int)TableHeap[table].Length;
}
public int GetTableIndexSize(Table table)
{
return GetTableLength(table) < 65536 ? 2 : 4;
}
public int GetCodedIndexSize(CodedIndex coded_index)
{
int index = (int)coded_index;
int size = coded_index_sizes[index];
if (size != 0)
return size;
return coded_index_sizes[index] = coded_index.GetSize(counter);
}
public uint ResolveVirtualAddress(RVA rva)
{
Section section = GetSectionAtVirtualAddress(rva);
if (section == null)
throw new ArgumentOutOfRangeException();
return ResolveVirtualAddressInSection(rva, section);
}
public uint ResolveVirtualAddressInSection(RVA rva, Section section)
{
return rva + section.PointerToRawData - section.VirtualAddress;
}
public Section GetSection(string name)
{
Section[] sections = Sections;
for (int i = 0; i < sections.Length; i++)
{
Section section = sections[i];
if (section.Name == name)
return section;
}
return null;
}
public Section GetSectionAtVirtualAddress(RVA rva)
{
Section[] sections = Sections;
for (int i = 0; i < sections.Length; i++)
{
Section section = sections[i];
if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData)
return section;
}
return null;
}
private BinaryStreamReader GetReaderAt(RVA rva)
{
Section section = GetSectionAtVirtualAddress(rva);
if (section == null)
return null;
BinaryStreamReader reader = new(Stream.value);
reader.MoveTo(ResolveVirtualAddressInSection(rva, section));
return reader;
}
public TRet GetReaderAt<TItem, TRet>(RVA rva, TItem item, Func<TItem, BinaryStreamReader, TRet> read) where TRet : class
{
long position = Stream.value.Position;
try
{
BinaryStreamReader reader = GetReaderAt(rva);
if (reader == null)
return null;
return read(item, reader);
}
finally
{
Stream.value.Position = position;
}
}
public bool HasDebugTables()
{
return HasTable(Table.Document) || HasTable(Table.MethodDebugInformation) || HasTable(Table.LocalScope) || HasTable(Table.LocalVariable) || HasTable(Table.LocalConstant) || HasTable(Table.StateMachineMethod) || HasTable(Table.CustomDebugInformation);
}
public void Dispose()
{
Stream.Dispose();
}
}
}