Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

278 lines
8.5 KiB
C#

//
// StructureReader.cs
//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// (C) 2005 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace Mono.Cecil {
using System;
using System.IO;
using Mono.Cecil.Binary;
using Mono.Cecil.Metadata;
internal sealed class StructureReader : BaseStructureVisitor {
ImageReader m_ir;
Image m_img;
bool m_manifestOnly;
AssemblyDefinition m_asmDef;
ModuleDefinition m_module;
MetadataStreamCollection m_streams;
TablesHeap m_tHeap;
MetadataTableReader m_tableReader;
public bool ManifestOnly {
get { return m_manifestOnly; }
}
public ImageReader ImageReader {
get { return m_ir; }
}
public Image Image {
get { return m_img; }
}
public StructureReader (ImageReader ir)
{
if (ir.Image.CLIHeader == null)
throw new ImageFormatException ("The image is not a managed assembly");
m_ir = ir;
m_img = ir.Image;
m_streams = m_img.MetadataRoot.Streams;
m_tHeap = m_streams.TablesHeap;
m_tableReader = ir.MetadataReader.TableReader;
}
public StructureReader (ImageReader ir, bool manifestOnly) : this (ir)
{
m_manifestOnly = manifestOnly;
}
byte [] ReadBlob (uint pointer)
{
if (pointer == 0)
return new byte [0];
return m_streams.BlobHeap.Read (pointer);
}
string ReadString (uint pointer)
{
return m_streams.StringsHeap [pointer];
}
public override void VisitAssemblyDefinition (AssemblyDefinition asm)
{
if (!m_tHeap.HasTable (AssemblyTable.RId))
throw new ReflectionException ("No assembly manifest");
asm.MetadataToken = new MetadataToken (TokenType.Assembly, 1);
m_asmDef = asm;
switch (m_img.MetadataRoot.Header.Version) {
case "v1.0.3705" :
asm.Runtime = TargetRuntime.NET_1_0;
break;
case "v1.1.4322" :
asm.Runtime = TargetRuntime.NET_1_1;
break;
case "v2.0.50727":
asm.Runtime = TargetRuntime.NET_2_0;
break;
case "v4.0.30319" :
asm.Runtime = TargetRuntime.NET_4_0;
break;
}
if ((m_img.PEFileHeader.Characteristics & ImageCharacteristics.Dll) != 0)
asm.Kind = AssemblyKind.Dll;
else if (m_img.PEOptionalHeader.NTSpecificFields.SubSystem == SubSystem.WindowsGui ||
m_img.PEOptionalHeader.NTSpecificFields.SubSystem == SubSystem.WindowsCeGui)
asm.Kind = AssemblyKind.Windows;
else
asm.Kind = AssemblyKind.Console;
}
public override void VisitAssemblyNameDefinition (AssemblyNameDefinition name)
{
AssemblyTable atable = m_tableReader.GetAssemblyTable ();
AssemblyRow arow = atable [0];
name.Name = ReadString (arow.Name);
name.Flags = arow.Flags;
name.PublicKey = ReadBlob (arow.PublicKey);
name.Culture = ReadString (arow.Culture);
name.Version = new Version (
arow.MajorVersion, arow.MinorVersion,
arow.BuildNumber, arow.RevisionNumber);
name.HashAlgorithm = arow.HashAlgId;
name.MetadataToken = new MetadataToken (TokenType.Assembly, 1);
}
public override void VisitAssemblyNameReferenceCollection (AssemblyNameReferenceCollection names)
{
if (!m_tHeap.HasTable (AssemblyRefTable.RId))
return;
AssemblyRefTable arTable = m_tableReader.GetAssemblyRefTable ();
for (int i = 0; i < arTable.Rows.Count; i++) {
AssemblyRefRow arRow = arTable [i];
AssemblyNameReference aname = new AssemblyNameReference (
ReadString (arRow.Name),
ReadString (arRow.Culture),
new Version (arRow.MajorVersion, arRow.MinorVersion,
arRow.BuildNumber, arRow.RevisionNumber));
aname.PublicKeyToken = ReadBlob (arRow.PublicKeyOrToken);
aname.Hash = ReadBlob (arRow.HashValue);
aname.Flags = arRow.Flags;
aname.MetadataToken = new MetadataToken (TokenType.AssemblyRef, (uint) i + 1);
names.Add (aname);
}
}
public override void VisitResourceCollection (ResourceCollection resources)
{
if (!m_tHeap.HasTable (ManifestResourceTable.RId))
return;
ManifestResourceTable mrTable = m_tableReader.GetManifestResourceTable ();
FileTable fTable = m_tableReader.GetFileTable ();
for (int i = 0; i < mrTable.Rows.Count; i++) {
ManifestResourceRow mrRow = mrTable [i];
if (mrRow.Implementation.RID == 0) {
EmbeddedResource eres = new EmbeddedResource (
ReadString (mrRow.Name), mrRow.Flags);
BinaryReader br = m_ir.MetadataReader.GetDataReader (
m_img.CLIHeader.Resources.VirtualAddress);
br.BaseStream.Position += mrRow.Offset;
eres.Data = br.ReadBytes (br.ReadInt32 ());
resources.Add (eres);
continue;
}
switch (mrRow.Implementation.TokenType) {
case TokenType.File :
FileRow fRow = fTable [(int) mrRow.Implementation.RID - 1];
LinkedResource lres = new LinkedResource (
ReadString (mrRow.Name), mrRow.Flags,
ReadString (fRow.Name));
lres.Hash = ReadBlob (fRow.HashValue);
resources.Add (lres);
break;
case TokenType.AssemblyRef :
AssemblyNameReference asm =
m_module.AssemblyReferences [(int) mrRow.Implementation.RID - 1];
AssemblyLinkedResource alr = new AssemblyLinkedResource (
ReadString (mrRow.Name),
mrRow.Flags, asm);
resources.Add (alr);
break;
}
}
}
public override void VisitModuleDefinitionCollection (ModuleDefinitionCollection modules)
{
ModuleTable mt = m_tableReader.GetModuleTable ();
if (mt == null || mt.Rows.Count != 1)
throw new ReflectionException ("Can not read main module");
ModuleRow mr = mt [0];
string name = ReadString (mr.Name);
ModuleDefinition main = new ModuleDefinition (name, m_asmDef, this, true);
main.Mvid = m_streams.GuidHeap [mr.Mvid];
main.MetadataToken = new MetadataToken (TokenType.Module, 1);
modules.Add (main);
m_module = main;
m_module.Accept (this);
FileTable ftable = m_tableReader.GetFileTable ();
if (ftable == null || ftable.Rows.Count == 0)
return;
foreach (FileRow frow in ftable.Rows) {
if (frow.Flags != FileAttributes.ContainsMetaData)
continue;
name = ReadString (frow.Name);
FileInfo location = new FileInfo (
m_img.FileInformation != null ? Path.Combine (m_img.FileInformation.DirectoryName, name) : name);
if (!File.Exists (location.FullName))
throw new FileNotFoundException ("Module not found : " + name);
try {
ImageReader module = ImageReader.Read (location.FullName);
mt = module.Image.MetadataRoot.Streams.TablesHeap [ModuleTable.RId] as ModuleTable;
if (mt == null || mt.Rows.Count != 1)
throw new ReflectionException ("Can not read module : " + name);
mr = mt [0];
ModuleDefinition modext = new ModuleDefinition (name, m_asmDef,
new StructureReader (module, m_manifestOnly), false);
modext.Mvid = module.Image.MetadataRoot.Streams.GuidHeap [mr.Mvid];
modules.Add (modext);
modext.Accept (this);
} catch (ReflectionException) {
throw;
} catch (Exception e) {
throw new ReflectionException ("Can not read module : " + name, e);
}
}
}
public override void VisitModuleReferenceCollection (ModuleReferenceCollection modules)
{
if (!m_tHeap.HasTable (ModuleRefTable.RId))
return;
ModuleRefTable mrTable = m_tableReader.GetModuleRefTable ();
for (int i = 0; i < mrTable.Rows.Count; i++) {
ModuleRefRow mrRow = mrTable [i];
ModuleReference mod = new ModuleReference (ReadString (mrRow.Name));
mod.MetadataToken = MetadataToken.FromMetadataRow (TokenType.ModuleRef, i);
modules.Add (mod);
}
}
public override void TerminateAssemblyDefinition (AssemblyDefinition asm)
{
if (m_manifestOnly)
return;
foreach (ModuleDefinition mod in asm.Modules)
mod.Controller.Reader.VisitModuleDefinition (mod);
}
}
}