5 // Jb Evain (jbevain@gmail.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace Mono
.Cecil
{
34 using Mono
.Cecil
.Binary
;
35 using Mono
.Cecil
.Metadata
;
37 internal sealed class StructureReader
: BaseStructureVisitor
{
42 AssemblyDefinition m_asmDef
;
43 ModuleDefinition m_module
;
44 MetadataStreamCollection m_streams
;
46 MetadataTableReader m_tableReader
;
48 public bool ManifestOnly
{
49 get { return m_manifestOnly; }
52 public ImageReader ImageReader
{
60 public StructureReader (ImageReader ir
)
62 if (ir
.Image
.CLIHeader
== null)
63 throw new ImageFormatException ("The image is not a managed assembly");
67 m_streams
= m_img
.MetadataRoot
.Streams
;
68 m_tHeap
= m_streams
.TablesHeap
;
69 m_tableReader
= ir
.MetadataReader
.TableReader
;
72 public StructureReader (ImageReader ir
, bool manifestOnly
) : this (ir
)
74 m_manifestOnly
= manifestOnly
;
77 byte [] ReadBlob (uint pointer
)
82 return m_streams
.BlobHeap
.Read (pointer
);
85 string ReadString (uint pointer
)
87 return m_streams
.StringsHeap
[pointer
];
90 public override void VisitAssemblyDefinition (AssemblyDefinition asm
)
92 if (!m_tHeap
.HasTable (AssemblyTable
.RId
))
93 throw new ReflectionException ("No assembly manifest");
95 asm
.MetadataToken
= new MetadataToken (TokenType
.Assembly
, 1);
98 switch (m_img
.MetadataRoot
.Header
.Version
) {
100 asm
.Runtime
= TargetRuntime
.NET_1_0
;
103 asm
.Runtime
= TargetRuntime
.NET_1_1
;
106 asm
.Runtime
= TargetRuntime
.NET_2_0
;
109 asm
.Runtime
= TargetRuntime
.NET_4_0
;
113 if ((m_img
.PEFileHeader
.Characteristics
& ImageCharacteristics
.Dll
) != 0)
114 asm
.Kind
= AssemblyKind
.Dll
;
115 else if (m_img
.PEOptionalHeader
.NTSpecificFields
.SubSystem
== SubSystem
.WindowsGui
||
116 m_img
.PEOptionalHeader
.NTSpecificFields
.SubSystem
== SubSystem
.WindowsCeGui
)
117 asm
.Kind
= AssemblyKind
.Windows
;
119 asm
.Kind
= AssemblyKind
.Console
;
122 public override void VisitAssemblyNameDefinition (AssemblyNameDefinition name
)
124 AssemblyTable atable
= m_tableReader
.GetAssemblyTable ();
125 AssemblyRow arow
= atable
[0];
126 name
.Name
= ReadString (arow
.Name
);
127 name
.Flags
= arow
.Flags
;
128 name
.PublicKey
= ReadBlob (arow
.PublicKey
);
130 name
.Culture
= ReadString (arow
.Culture
);
131 name
.Version
= new Version (
132 arow
.MajorVersion
, arow
.MinorVersion
,
133 arow
.BuildNumber
, arow
.RevisionNumber
);
134 name
.HashAlgorithm
= arow
.HashAlgId
;
135 name
.MetadataToken
= new MetadataToken (TokenType
.Assembly
, 1);
138 public override void VisitAssemblyNameReferenceCollection (AssemblyNameReferenceCollection names
)
140 if (!m_tHeap
.HasTable (AssemblyRefTable
.RId
))
143 AssemblyRefTable arTable
= m_tableReader
.GetAssemblyRefTable ();
144 for (int i
= 0; i
< arTable
.Rows
.Count
; i
++) {
145 AssemblyRefRow arRow
= arTable
[i
];
146 AssemblyNameReference aname
= new AssemblyNameReference (
147 ReadString (arRow
.Name
),
148 ReadString (arRow
.Culture
),
149 new Version (arRow
.MajorVersion
, arRow
.MinorVersion
,
150 arRow
.BuildNumber
, arRow
.RevisionNumber
));
151 aname
.PublicKeyToken
= ReadBlob (arRow
.PublicKeyOrToken
);
152 aname
.Hash
= ReadBlob (arRow
.HashValue
);
153 aname
.Flags
= arRow
.Flags
;
154 aname
.MetadataToken
= new MetadataToken (TokenType
.AssemblyRef
, (uint) i
+ 1);
159 public override void VisitResourceCollection (ResourceCollection resources
)
161 if (!m_tHeap
.HasTable (ManifestResourceTable
.RId
))
164 ManifestResourceTable mrTable
= m_tableReader
.GetManifestResourceTable ();
165 FileTable fTable
= m_tableReader
.GetFileTable ();
167 for (int i
= 0; i
< mrTable
.Rows
.Count
; i
++) {
168 ManifestResourceRow mrRow
= mrTable
[i
];
169 if (mrRow
.Implementation
.RID
== 0) {
170 EmbeddedResource eres
= new EmbeddedResource (
171 ReadString (mrRow
.Name
), mrRow
.Flags
);
173 BinaryReader br
= m_ir
.MetadataReader
.GetDataReader (
174 m_img
.CLIHeader
.Resources
.VirtualAddress
);
175 br
.BaseStream
.Position
+= mrRow
.Offset
;
177 eres
.Data
= br
.ReadBytes (br
.ReadInt32 ());
179 resources
.Add (eres
);
183 switch (mrRow
.Implementation
.TokenType
) {
184 case TokenType
.File
:
185 FileRow fRow
= fTable
[(int) mrRow
.Implementation
.RID
- 1];
186 LinkedResource lres
= new LinkedResource (
187 ReadString (mrRow
.Name
), mrRow
.Flags
,
188 ReadString (fRow
.Name
));
189 lres
.Hash
= ReadBlob (fRow
.HashValue
);
190 resources
.Add (lres
);
192 case TokenType
.AssemblyRef
:
193 AssemblyNameReference asm
=
194 m_module
.AssemblyReferences
[(int) mrRow
.Implementation
.RID
- 1];
195 AssemblyLinkedResource alr
= new AssemblyLinkedResource (
196 ReadString (mrRow
.Name
),
204 public override void VisitModuleDefinitionCollection (ModuleDefinitionCollection modules
)
206 ModuleTable mt
= m_tableReader
.GetModuleTable ();
207 if (mt
== null || mt
.Rows
.Count
!= 1)
208 throw new ReflectionException ("Can not read main module");
210 ModuleRow mr
= mt
[0];
211 string name
= ReadString (mr
.Name
);
212 ModuleDefinition main
= new ModuleDefinition (name
, m_asmDef
, this, true);
213 main
.Mvid
= m_streams
.GuidHeap
[mr
.Mvid
];
214 main
.MetadataToken
= new MetadataToken (TokenType
.Module
, 1);
217 m_module
.Accept (this);
219 FileTable ftable
= m_tableReader
.GetFileTable ();
220 if (ftable
== null || ftable
.Rows
.Count
== 0)
223 foreach (FileRow frow
in ftable
.Rows
) {
224 if (frow
.Flags
!= FileAttributes
.ContainsMetaData
)
227 name
= ReadString (frow
.Name
);
228 FileInfo location
= new FileInfo (
229 m_img
.FileInformation
!= null ? Path
.Combine (m_img
.FileInformation
.DirectoryName
, name
) : name
);
230 if (!File
.Exists (location
.FullName
))
231 throw new FileNotFoundException ("Module not found : " + name
);
234 ImageReader module
= ImageReader
.Read (location
.FullName
);
235 mt
= module
.Image
.MetadataRoot
.Streams
.TablesHeap
[ModuleTable
.RId
] as ModuleTable
;
236 if (mt
== null || mt
.Rows
.Count
!= 1)
237 throw new ReflectionException ("Can not read module : " + name
);
240 ModuleDefinition modext
= new ModuleDefinition (name
, m_asmDef
,
241 new StructureReader (module
, m_manifestOnly
), false);
242 modext
.Mvid
= module
.Image
.MetadataRoot
.Streams
.GuidHeap
[mr
.Mvid
];
244 modules
.Add (modext
);
245 modext
.Accept (this);
246 } catch (ReflectionException
) {
248 } catch (Exception e
) {
249 throw new ReflectionException ("Can not read module : " + name
, e
);
254 public override void VisitModuleReferenceCollection (ModuleReferenceCollection modules
)
256 if (!m_tHeap
.HasTable (ModuleRefTable
.RId
))
259 ModuleRefTable mrTable
= m_tableReader
.GetModuleRefTable ();
260 for (int i
= 0; i
< mrTable
.Rows
.Count
; i
++) {
261 ModuleRefRow mrRow
= mrTable
[i
];
262 ModuleReference mod
= new ModuleReference (ReadString (mrRow
.Name
));
263 mod
.MetadataToken
= MetadataToken
.FromMetadataRow (TokenType
.ModuleRef
, i
);
268 public override void TerminateAssemblyDefinition (AssemblyDefinition asm
)
273 foreach (ModuleDefinition mod
in asm
.Modules
)
274 mod
.Controller
.Reader
.VisitModuleDefinition (mod
);