mirror of https://github.com/mono/CppSharp.git
7 changed files with 3 additions and 290 deletions
@ -1,67 +0,0 @@
@@ -1,67 +0,0 @@
|
||||
/* |
||||
InjectModuleInitializer |
||||
|
||||
Command line program to inject a module initializer into a .NET assembly. |
||||
|
||||
Copyright (C) 2009-2016 Einar Egilsson |
||||
http://einaregilsson.com/module-initializers-in-csharp/
|
||||
|
||||
This program is licensed under the MIT license: http://opensource.org/licenses/MIT
|
||||
*/ |
||||
using System; |
||||
|
||||
namespace EinarEgilsson.Utilities.InjectModuleInitializer |
||||
{ |
||||
internal static class Errors |
||||
{ |
||||
internal static string AssemblyDoesNotExist(string assembly) |
||||
{ |
||||
return String.Format("Assembly '{0}' does not exist", assembly); |
||||
} |
||||
|
||||
internal static string NoModuleInitializerTypeFound() |
||||
{ |
||||
return "Found no type named 'ModuleInitializer', this type must exist or the ModuleInitializer parameter must be used"; |
||||
} |
||||
|
||||
internal static string InvalidFormatForModuleInitializer() |
||||
{ |
||||
return "Invalid format for ModuleInitializer parameter, use Full.Type.Name::MethodName"; |
||||
} |
||||
|
||||
internal static string TypeNameDoesNotExist(string typeName) |
||||
{ |
||||
return string.Format("No type named '{0}' exists in the given assembly!", typeName); |
||||
} |
||||
|
||||
internal static string MethodNameDoesNotExist(string typeName, string methodName) |
||||
{ |
||||
return string.Format("No method named '{0}' exists in the type '{0}'", methodName, typeName); |
||||
} |
||||
|
||||
internal static string KeyFileDoesNotExist(string keyfile) |
||||
{ |
||||
return string.Format("The key file'{0}' does not exist", keyfile); |
||||
} |
||||
|
||||
internal static string ModuleInitializerMayNotBePrivate() |
||||
{ |
||||
return "Module initializer method may not be private or protected, use public or internal instead"; |
||||
} |
||||
|
||||
internal static string ModuleInitializerMustBeVoid() |
||||
{ |
||||
return "Module initializer method must have 'void' as return type"; |
||||
} |
||||
|
||||
internal static string ModuleInitializerMayNotHaveParameters() |
||||
{ |
||||
return "Module initializer method must not have any parameters"; |
||||
} |
||||
|
||||
internal static string ModuleInitializerMustBeStatic() |
||||
{ |
||||
return "Module initializer method must be static"; |
||||
} |
||||
} |
||||
} |
@ -1,192 +0,0 @@
@@ -1,192 +0,0 @@
|
||||
/* |
||||
InjectModuleInitializer |
||||
|
||||
Command line program to inject a module initializer into a .NET assembly. |
||||
|
||||
Copyright (C) 2009-2016 Einar Egilsson |
||||
http://einaregilsson.com/module-initializers-in-csharp/
|
||||
|
||||
This program is licensed under the MIT license: http://opensource.org/licenses/MIT
|
||||
*/ |
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Reflection; |
||||
using Mono.Cecil; |
||||
using Mono.Cecil.Cil; |
||||
using Mono.Cecil.Pdb; |
||||
using Mono.Collections.Generic; |
||||
using MethodAttributes = Mono.Cecil.MethodAttributes; |
||||
|
||||
namespace EinarEgilsson.Utilities.InjectModuleInitializer |
||||
{ |
||||
public class InjectionException : Exception |
||||
{ |
||||
public InjectionException(string msg) : base(msg) { } |
||||
} |
||||
|
||||
internal class Injector |
||||
{ |
||||
public const string DefaultInitializerClassName = "ModuleInitializer"; |
||||
public const string DefaultInitializerMethodName = "Run"; |
||||
|
||||
private AssemblyDefinition Assembly { get; set; } |
||||
|
||||
private string PdbFile(string assemblyFile) |
||||
{ |
||||
Debug.Assert(assemblyFile != null); |
||||
string path = Path.ChangeExtension(assemblyFile, ".pdb"); |
||||
if (File.Exists(path)) |
||||
{ |
||||
return path; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
|
||||
public void Inject(string assemblyFile, string moduleInitializer=null, string keyfile=null) |
||||
{ |
||||
try |
||||
{ |
||||
if (!File.Exists(assemblyFile)) |
||||
{ |
||||
throw new InjectionException(Errors.AssemblyDoesNotExist(assemblyFile)); |
||||
} |
||||
if (keyfile != null && !File.Exists(keyfile)) |
||||
{ |
||||
throw new InjectionException(Errors.KeyFileDoesNotExist(keyfile)); |
||||
} |
||||
ReadAssembly(assemblyFile); |
||||
MethodReference callee = GetModuleInitializer(moduleInitializer); |
||||
InjectInitializer(callee); |
||||
|
||||
WriteAssembly(assemblyFile, keyfile); |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
throw new InjectionException(ex.Message); |
||||
} |
||||
} |
||||
|
||||
public void InjectInitializer(MethodReference callee) |
||||
{ |
||||
Debug.Assert(Assembly != null); |
||||
TypeReference voidRef = Assembly.MainModule.Import(callee.ReturnType); |
||||
const MethodAttributes attributes = MethodAttributes.Static |
||||
| MethodAttributes.SpecialName |
||||
| MethodAttributes.RTSpecialName; |
||||
var cctor = new MethodDefinition(".cctor", attributes, voidRef); |
||||
ILProcessor il = cctor.Body.GetILProcessor(); |
||||
il.Append(il.Create(OpCodes.Call, callee)); |
||||
il.Append(il.Create(OpCodes.Ret)); |
||||
|
||||
TypeDefinition moduleClass = Find(Assembly.MainModule.Types, t => t.Name == "<Module>"); |
||||
moduleClass.Methods.Add(cctor); |
||||
|
||||
Debug.Assert(moduleClass != null, "Found no module class!"); |
||||
} |
||||
|
||||
public void WriteAssembly(string assemblyFile, string keyfile) |
||||
{ |
||||
Debug.Assert(Assembly != null); |
||||
var writeParams = new WriterParameters(); |
||||
if (PdbFile(assemblyFile) != null) |
||||
{ |
||||
writeParams.WriteSymbols = true; |
||||
writeParams.SymbolWriterProvider = new PdbWriterProvider(); |
||||
} |
||||
if (keyfile != null) |
||||
{ |
||||
writeParams.StrongNameKeyPair = new StrongNameKeyPair(File.ReadAllBytes(keyfile)); |
||||
} |
||||
Assembly.Write(assemblyFile, writeParams); |
||||
} |
||||
|
||||
public void ReadAssembly(string assemblyFile) |
||||
{ |
||||
Debug.Assert(Assembly == null); |
||||
|
||||
var resolver = new DefaultAssemblyResolver(); |
||||
resolver.AddSearchDirectory(Path.GetDirectoryName(assemblyFile)); |
||||
|
||||
var readParams = new ReaderParameters(ReadingMode.Immediate) |
||||
{ |
||||
AssemblyResolver = resolver |
||||
}; |
||||
|
||||
if (PdbFile(assemblyFile) != null) |
||||
{ |
||||
readParams.ReadSymbols = true; |
||||
readParams.SymbolReaderProvider = new PdbReaderProvider(); |
||||
} |
||||
Assembly = AssemblyDefinition.ReadAssembly(assemblyFile, readParams); |
||||
} |
||||
|
||||
public MethodReference GetModuleInitializer(string moduleInitializer = null) |
||||
{ |
||||
Debug.Assert(Assembly != null); |
||||
ModuleDefinition module = Assembly.MainModule; |
||||
string methodName; |
||||
TypeDefinition moduleInitializerClass; |
||||
if (string.IsNullOrEmpty(moduleInitializer)) |
||||
{ |
||||
methodName = DefaultInitializerMethodName; |
||||
moduleInitializerClass = Find(module.Types, t => t.Name == DefaultInitializerClassName); |
||||
if (moduleInitializerClass == null) |
||||
{ |
||||
return null; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (!moduleInitializer.Contains("::")) |
||||
{ |
||||
return null; |
||||
} |
||||
string typeName = moduleInitializer.Substring(0, moduleInitializer.IndexOf("::", StringComparison.Ordinal)); |
||||
methodName = moduleInitializer.Substring(typeName.Length + 2); |
||||
moduleInitializerClass = Find(module.Types, t => t.FullName == typeName); |
||||
if (moduleInitializerClass == null) |
||||
{ |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
MethodDefinition callee = Find(moduleInitializerClass.Methods, m => m.Name == methodName); |
||||
if (callee == null) |
||||
{ |
||||
throw new InjectionException(Errors.MethodNameDoesNotExist(moduleInitializerClass.FullName, methodName)); |
||||
} |
||||
if (callee.Parameters.Count > 0) |
||||
{ |
||||
throw new InjectionException(Errors.ModuleInitializerMayNotHaveParameters()); |
||||
} |
||||
if (callee.IsPrivate || callee.IsFamily) |
||||
{ |
||||
throw new InjectionException(Errors.ModuleInitializerMayNotBePrivate()); |
||||
} |
||||
if (!callee.ReturnType.FullName.Equals(typeof(void).FullName)) //Don't compare the types themselves, they might be from different CLR versions.
|
||||
{ |
||||
throw new InjectionException(Errors.ModuleInitializerMustBeVoid()); |
||||
} |
||||
if (!callee.IsStatic) |
||||
{ |
||||
throw new InjectionException(Errors.ModuleInitializerMustBeStatic()); |
||||
} |
||||
return callee; |
||||
} |
||||
|
||||
//No LINQ, since we want to target 2.0
|
||||
private static T Find<T>(Collection<T> objects, Predicate<T> condition) where T:class |
||||
{ |
||||
foreach (T obj in objects) |
||||
{ |
||||
if (condition(obj)) |
||||
{ |
||||
return obj; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue