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 StructureWriter : BaseStructureVisitor {
39 MetadataWriter m_mdWriter;
40 MetadataTableWriter m_tableWriter;
41 MetadataRowWriter m_rowWriter;
43 AssemblyDefinition m_asm;
44 BinaryWriter m_binaryWriter;
46 public AssemblyDefinition Assembly {
50 static void ResetImage (ModuleDefinition mod)
52 Image ni = Image.CreateImage ();
53 ni.Accept (new CopyImageVisitor (mod.Image));
57 public StructureWriter (AssemblyDefinition asm, BinaryWriter writer)
60 m_binaryWriter = writer;
63 public BinaryWriter GetWriter ()
65 return m_binaryWriter;
68 public override void VisitAssemblyDefinition (AssemblyDefinition asm)
70 if (asm.Kind != AssemblyKind.Dll && asm.EntryPoint == null)
71 throw new ReflectionException ("Assembly does not have an entry point defined");
73 if ((asm.MainModule.Image.CLIHeader.Flags & RuntimeImage.ILOnly) == 0)
74 throw new NotSupportedException ("Can not write a mixed mode assembly");
76 foreach (ModuleDefinition module in asm.Modules)
77 if (module.Image.CLIHeader.Metadata.VirtualAddress != RVA.Zero)
80 asm.MetadataToken = new MetadataToken (TokenType.Assembly, 1);
81 ReflectionWriter rw = asm.MainModule.Controller.Writer;
82 rw.StructureWriter = this;
84 m_mdWriter = rw.MetadataWriter;
85 m_tableWriter = rw.MetadataTableWriter;
86 m_rowWriter = rw.MetadataRowWriter;
91 FileStream fs = m_binaryWriter.BaseStream as FileStream;
93 rw.OutputFile = fs.Name;
96 public override void VisitAssemblyNameDefinition (AssemblyNameDefinition name)
98 AssemblyTable asmTable = m_tableWriter.GetAssemblyTable ();
100 if (name.PublicKey != null && name.PublicKey.Length > 0)
101 name.Flags |= AssemblyFlags.PublicKey;
103 AssemblyRow asmRow = m_rowWriter.CreateAssemblyRow (
105 (ushort) name.Version.Major,
106 (ushort) name.Version.Minor,
107 (ushort) name.Version.Build,
108 (ushort) name.Version.Revision,
110 m_mdWriter.AddBlob (name.PublicKey),
111 m_mdWriter.AddString (name.Name),
112 m_mdWriter.AddString (name.Culture));
114 asmTable.Rows.Add (asmRow);
117 public override void VisitAssemblyNameReferenceCollection (AssemblyNameReferenceCollection references)
119 foreach (AssemblyNameReference name in references)
120 VisitAssemblyNameReference (name);
123 public override void VisitAssemblyNameReference (AssemblyNameReference name)
126 if (name.PublicKey != null && name.PublicKey.Length > 0)
127 pkortoken = name.PublicKey;
128 else if (name.PublicKeyToken != null && name.PublicKeyToken.Length > 0)
129 pkortoken = name.PublicKeyToken;
131 pkortoken = new byte [0];
133 AssemblyRefTable arTable = m_tableWriter.GetAssemblyRefTable ();
134 AssemblyRefRow arRow = m_rowWriter.CreateAssemblyRefRow (
135 (ushort) name.Version.Major,
136 (ushort) name.Version.Minor,
137 (ushort) name.Version.Build,
138 (ushort) name.Version.Revision,
140 m_mdWriter.AddBlob (pkortoken),
141 m_mdWriter.AddString (name.Name),
142 m_mdWriter.AddString (name.Culture),
143 m_mdWriter.AddBlob (name.Hash));
145 arTable.Rows.Add (arRow);
148 public override void VisitResourceCollection (ResourceCollection resources)
150 VisitCollection (resources);
153 public override void VisitEmbeddedResource (EmbeddedResource res)
155 AddManifestResource (
156 m_mdWriter.AddResource (res.Data),
158 new MetadataToken (TokenType.ManifestResource, 0));
161 public override void VisitLinkedResource (LinkedResource res)
163 FileTable fTable = m_tableWriter.GetFileTable ();
164 FileRow fRow = m_rowWriter.CreateFileRow (
165 Mono.Cecil.FileAttributes.ContainsNoMetaData,
166 m_mdWriter.AddString (res.File),
167 m_mdWriter.AddBlob (res.Hash));
169 fTable.Rows.Add (fRow);
171 AddManifestResource (
172 0, res.Name, res.Flags,
173 new MetadataToken (TokenType.File, (uint) fTable.Rows.IndexOf (fRow) + 1));
176 public override void VisitAssemblyLinkedResource (AssemblyLinkedResource res)
178 MetadataToken impl = new MetadataToken (TokenType.AssemblyRef,
179 (uint) m_asm.MainModule.AssemblyReferences.IndexOf (res.Assembly) + 1);
181 AddManifestResource (0, res.Name, res.Flags, impl);
184 void AddManifestResource (uint offset, string name, ManifestResourceAttributes flags, MetadataToken impl)
186 ManifestResourceTable mrTable = m_tableWriter.GetManifestResourceTable ();
187 ManifestResourceRow mrRow = m_rowWriter.CreateManifestResourceRow (
190 m_mdWriter.AddString (name),
193 mrTable.Rows.Add (mrRow);
196 public override void VisitModuleDefinitionCollection (ModuleDefinitionCollection modules)
198 VisitCollection (modules);
201 public override void VisitModuleDefinition (ModuleDefinition module)
204 ModuleTable modTable = m_tableWriter.GetModuleTable ();
205 ModuleRow modRow = m_rowWriter.CreateModuleRow (
207 m_mdWriter.AddString (module.Name),
208 m_mdWriter.AddGuid (module.Mvid),
212 modTable.Rows.Add (modRow);
213 module.MetadataToken = new MetadataToken (TokenType.Module, 1);
215 // multiple module assemblies
216 throw new NotImplementedException ();
220 public override void VisitModuleReferenceCollection (ModuleReferenceCollection modules)
222 VisitCollection (modules);
225 public override void VisitModuleReference (ModuleReference module)
227 ModuleRefTable mrTable = m_tableWriter.GetModuleRefTable ();
228 ModuleRefRow mrRow = m_rowWriter.CreateModuleRefRow (
229 m_mdWriter.AddString (module.Name));
231 mrTable.Rows.Add (mrRow);
234 public override void TerminateAssemblyDefinition (AssemblyDefinition asm)
236 foreach (ModuleDefinition mod in asm.Modules) {
237 ReflectionWriter writer = mod.Controller.Writer;
238 writer.VisitModuleDefinition (mod);
239 writer.VisitTypeReferenceCollection (mod.TypeReferences);
240 writer.VisitTypeDefinitionCollection (mod.Types);
241 writer.VisitMemberReferenceCollection (mod.MemberReferences);
242 writer.CompleteTypeDefinitions ();
244 writer.TerminateModuleDefinition (mod);