5 // Jb Evain (jbevain@novell.com)
7 // (C) 2008 Novell, Inc (http://www.novell.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 using System
.Collections
;
32 using Mono
.Cecil
.Binary
;
34 using Mono
.Cecil
.Metadata
;
36 namespace Mono
.Cecil
{
38 class AssemblyStripper
{
40 AssemblyDefinition assembly
;
46 ReflectionWriter reflection_writer
;
47 MetadataWriter metadata_writer
;
49 TablesHeap original_tables
;
50 TablesHeap stripped_tables
;
52 AssemblyStripper (AssemblyDefinition assembly
, BinaryWriter writer
)
54 this.assembly
= assembly
;
71 assembly
.MainModule
.FullLoad ();
74 void ClearMethodBodies ()
76 foreach (TypeDefinition type
in assembly
.MainModule
.Types
) {
77 ClearMethodBodies (type
.Constructors
);
78 ClearMethodBodies (type
.Methods
);
82 static void ClearMethodBodies (ICollection methods
)
84 foreach (MethodDefinition method
in methods
) {
88 MethodBody body
= new MethodBody (method
);
89 body
.CilWorker
.Emit (OpCodes
.Ret
);
95 void CopyOriginalImage ()
97 original
= assembly
.MainModule
.Image
;
98 stripped
= Image
.CreateImage();
100 stripped
.Accept (new CopyImageVisitor (original
));
102 assembly
.MainModule
.Image
= stripped
;
104 original_tables
= original
.MetadataRoot
.Streams
.TablesHeap
;
105 stripped_tables
= stripped
.MetadataRoot
.Streams
.TablesHeap
;
107 TableCollection tables
= original_tables
.Tables
;
108 foreach (IMetadataTable table
in tables
)
109 stripped_tables
.Tables
.Add(table
);
111 stripped_tables
.Valid
= original_tables
.Valid
;
112 stripped_tables
.Sorted
= original_tables
.Sorted
;
114 reflection_writer
= new ReflectionWriter (assembly
.MainModule
);
115 reflection_writer
.StructureWriter
= new StructureWriter (assembly
, writer
);
116 reflection_writer
.CodeWriter
.Stripped
= true;
118 metadata_writer
= reflection_writer
.MetadataWriter
;
120 PatchHeap (metadata_writer
.StringWriter
, original
.MetadataRoot
.Streams
.StringsHeap
);
121 PatchHeap (metadata_writer
.GuidWriter
, original
.MetadataRoot
.Streams
.GuidHeap
);
122 PatchHeap (metadata_writer
.UserStringWriter
, original
.MetadataRoot
.Streams
.UserStringsHeap
);
123 PatchHeap (metadata_writer
.BlobWriter
, original
.MetadataRoot
.Streams
.BlobHeap
);
125 if (assembly
.EntryPoint
!= null)
126 metadata_writer
.EntryPointToken
= assembly
.EntryPoint
.MetadataToken
.ToUInt ();
129 static void PatchHeap (MemoryBinaryWriter heap_writer
, MetadataHeap heap
)
134 heap_writer
.BaseStream
.Position
= 0;
135 heap_writer
.Write (heap
.Data
);
140 MethodTable methodTable
= (MethodTable
) stripped_tables
[MethodTable
.RId
];
141 if (methodTable
== null)
144 RVA method_rva
= RVA
.Zero
;
146 for (int i
= 0; i
< methodTable
.Rows
.Count
; i
++) {
147 MethodRow methodRow
= methodTable
[i
];
149 MetadataToken methodToken
= MetadataToken
.FromMetadataRow (TokenType
.Method
, i
);
151 MethodDefinition method
= (MethodDefinition
) assembly
.MainModule
.LookupByToken (methodToken
);
153 if (method
.HasBody
) {
154 method_rva
= method_rva
!= RVA
.Zero
156 : reflection_writer
.CodeWriter
.WriteMethodBody (method
);
158 methodRow
.RVA
= method_rva
;
160 methodRow
.RVA
= RVA
.Zero
;
166 FieldRVATable fieldRvaTable
= (FieldRVATable
) stripped_tables
[FieldRVATable
.RId
];
167 if (fieldRvaTable
== null)
170 for (int i
= 0; i
< fieldRvaTable
.Rows
.Count
; i
++) {
171 FieldRVARow fieldRvaRow
= fieldRvaTable
[i
];
173 MetadataToken fieldToken
= new MetadataToken (TokenType
.Field
, fieldRvaRow
.Field
);
175 FieldDefinition field
= (FieldDefinition
) assembly
.MainModule
.LookupByToken (fieldToken
);
177 fieldRvaRow
.RVA
= metadata_writer
.GetDataCursor ();
178 metadata_writer
.AddData (field
.InitialValue
.Length
+ 3 & (~
3));
179 metadata_writer
.AddFieldInitData (field
.InitialValue
);
183 void PatchResources ()
185 ManifestResourceTable resourceTable
= (ManifestResourceTable
) stripped_tables
[ManifestResourceTable
.RId
];
186 if (resourceTable
== null)
189 for (int i
= 0; i
< resourceTable
.Rows
.Count
; i
++) {
190 ManifestResourceRow resourceRow
= resourceTable
[i
];
192 if (resourceRow
.Implementation
.RID
!= 0)
195 foreach (Resource resource
in assembly
.MainModule
.Resources
) {
196 EmbeddedResource er
= resource
as EmbeddedResource
;
200 if (resource
.Name
!= original
.MetadataRoot
.Streams
.StringsHeap
[resourceRow
.Name
])
203 resourceRow
.Offset
= metadata_writer
.AddResource (er
.Data
);
210 stripped
.MetadataRoot
.Accept (metadata_writer
);
213 public static void StripAssembly (AssemblyDefinition assembly
, string file
)
215 using (FileStream fs
= new FileStream (file
, FileMode
.Create
, FileAccess
.Write
, FileShare
.None
)) {
216 new AssemblyStripper (assembly
, new BinaryWriter (fs
)).Strip ();