Skip to content

Commit 567605b

Browse files
authored
Merge d6f1f38 into 17024d9
2 parents 17024d9 + d6f1f38 commit 567605b

File tree

17 files changed

+365
-74
lines changed

17 files changed

+365
-74
lines changed

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "dnlib"]
2-
path = dnlib
3-
url=../dnlib.git

Confuser.Core/Confuser.Core.csproj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717
<ItemGroup Label="Nuget Dependencies">
1818
<PackageReference Include="Microsoft.Win32.Registry" Version="4.*" />
1919
<PackageReference Include="System.Threading" Version="4.*" />
20-
</ItemGroup>
21-
22-
<ItemGroup Label="Project Dependencies">
23-
<ProjectReference Include="..\dnlib\src\dnlib.csproj" />
20+
<PackageReference Include="dnlib" Version="3.3.2" />
2421
</ItemGroup>
2522

2623

Confuser.Core/ConfuserEngine.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
9494
var asmResolver = new AssemblyResolver();
9595
asmResolver.EnableTypeDefCache = true;
9696
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
97+
asmResolver.EnableFrameworkRedirect = false;
9798
context.Resolver = asmResolver;
9899
context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, context.Project.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar);
99100
context.OutputDirectory = Path.Combine(context.Project.BaseDirectory, context.Project.OutputDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar);
100101
foreach (string probePath in context.Project.ProbePaths)
101-
asmResolver.PostSearchPaths.Insert(0, Path.Combine(context.BaseDirectory, probePath));
102+
asmResolver.PreSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
102103

103104
context.CheckCancellation();
104105

@@ -384,6 +385,8 @@ static void EndModule(ConfuserContext context) {
384385
if (!Path.IsPathRooted(output))
385386
output = Path.Combine(Environment.CurrentDirectory, output);
386387
output = Utils.GetRelativePath(output, context.BaseDirectory);
388+
if (Path.IsPathRooted(output))
389+
output = Path.GetFileName(output);
387390
}
388391
else {
389392
output = context.CurrentModule.Name;

Confuser.Core/Helpers/InjectHelper.cs

Lines changed: 160 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Reflection;
45
using dnlib.DotNet;
56
using dnlib.DotNet.Emit;
67

@@ -59,10 +60,9 @@ static FieldDefUser Clone(FieldDef origin) {
5960
/// <returns>The new TypeDef.</returns>
6061
static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) {
6162
TypeDef ret;
62-
IDnlibDef existing;
63-
if (!ctx.Map.TryGetValue(typeDef, out existing)) {
63+
if (!ctx.MemberMap.TryGetValue(typeDef, out var existing)) {
6464
ret = Clone(typeDef);
65-
ctx.Map[typeDef] = ret;
65+
ctx.MemberMap[typeDef] = ret;
6666
}
6767
else
6868
ret = (TypeDef)existing;
@@ -71,10 +71,10 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) {
7171
ret.NestedTypes.Add(PopulateContext(nestedType, ctx));
7272

7373
foreach (MethodDef method in typeDef.Methods)
74-
ret.Methods.Add((MethodDef)(ctx.Map[method] = Clone(method)));
74+
ret.Methods.Add((MethodDef)(ctx.MemberMap[method] = Clone(method)));
7575

7676
foreach (FieldDef field in typeDef.Fields)
77-
ret.Fields.Add((FieldDef)(ctx.Map[field] = Clone(field)));
77+
ret.Fields.Add((FieldDef)(ctx.MemberMap[field] = Clone(field)));
7878

7979
return ret;
8080
}
@@ -85,12 +85,12 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) {
8585
/// <param name="typeDef">The origin TypeDef.</param>
8686
/// <param name="ctx">The injection context.</param>
8787
static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) {
88-
var newTypeDef = (TypeDef)ctx.Map[typeDef];
88+
var newTypeDef = (TypeDef)ctx.MemberMap[typeDef];
8989

90-
newTypeDef.BaseType = (ITypeDefOrRef)ctx.Importer.Import(typeDef.BaseType);
90+
newTypeDef.BaseType = ctx.Importer.Import(typeDef.BaseType);
9191

9292
foreach (InterfaceImpl iface in typeDef.Interfaces)
93-
newTypeDef.Interfaces.Add(new InterfaceImplUser((ITypeDefOrRef)ctx.Importer.Import(iface.Interface)));
93+
newTypeDef.Interfaces.Add(new InterfaceImplUser(ctx.Importer.Import(iface.Interface)));
9494
}
9595

9696
/// <summary>
@@ -99,7 +99,7 @@ static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) {
9999
/// <param name="methodDef">The origin MethodDef.</param>
100100
/// <param name="ctx">The injection context.</param>
101101
static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
102-
var newMethodDef = (MethodDef)ctx.Map[methodDef];
102+
var newMethodDef = (MethodDef)ctx.MemberMap[methodDef];
103103

104104
newMethodDef.Signature = ctx.Importer.Import(methodDef.Signature);
105105
newMethodDef.Parameters.UpdateParameterTypes();
@@ -151,7 +151,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
151151

152152
foreach (ExceptionHandler eh in methodDef.Body.ExceptionHandlers)
153153
newMethodDef.Body.ExceptionHandlers.Add(new ExceptionHandler(eh.HandlerType) {
154-
CatchType = eh.CatchType == null ? null : (ITypeDefOrRef)ctx.Importer.Import(eh.CatchType),
154+
CatchType = eh.CatchType == null ? null : ctx.Importer.Import(eh.CatchType),
155155
TryStart = (Instruction)bodyMap[eh.TryStart],
156156
TryEnd = (Instruction)bodyMap[eh.TryEnd],
157157
HandlerStart = (Instruction)bodyMap[eh.HandlerStart],
@@ -169,7 +169,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
169169
/// <param name="fieldDef">The origin FieldDef.</param>
170170
/// <param name="ctx">The injection context.</param>
171171
static void CopyFieldDef(FieldDef fieldDef, InjectContext ctx) {
172-
var newFieldDef = (FieldDef)ctx.Map[fieldDef];
172+
var newFieldDef = (FieldDef)ctx.MemberMap[fieldDef];
173173

174174
newFieldDef.Signature = ctx.Importer.Import(fieldDef.Signature);
175175
}
@@ -192,8 +192,8 @@ static void Copy(TypeDef typeDef, InjectContext ctx, bool copySelf) {
192192

193193
foreach (FieldDef field in typeDef.Fields)
194194
CopyFieldDef(field, ctx);
195-
}
196-
195+
}
196+
197197
/// <summary>
198198
/// Injects the specified TypeDef to another module.
199199
/// </summary>
@@ -204,9 +204,22 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) {
204204
var ctx = new InjectContext(typeDef.Module, target);
205205
PopulateContext(typeDef, ctx);
206206
Copy(typeDef, ctx, true);
207-
return (TypeDef)ctx.Map[typeDef];
208-
}
209-
207+
return (TypeDef)ctx.MemberMap[typeDef];
208+
}
209+
210+
/// <summary>
211+
/// Imports a <see cref="MethodBase"/> as a <see cref="IMethod"/>. This will be either
212+
/// a <see cref="MemberRef"/> or a <see cref="MethodSpec"/>.
213+
/// </summary>
214+
/// <param name="source">The source module.</param>
215+
/// <param name="methodBase">The method</param>
216+
/// <returns>The imported method or <c>null</c> if <paramref name="methodBase"/> is invalid
217+
/// or if we failed to import the method</returns>
218+
public static IMethod Import(ModuleDef target, MethodBase methodBase) {
219+
var ctx = new InjectContext(null, target);
220+
return ctx.Importer.Import(methodBase);
221+
}
222+
210223
/// <summary>
211224
/// Injects the specified MethodDef to another module.
212225
/// </summary>
@@ -215,9 +228,9 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) {
215228
/// <returns>The injected MethodDef.</returns>
216229
public static MethodDef Inject(MethodDef methodDef, ModuleDef target) {
217230
var ctx = new InjectContext(methodDef.Module, target);
218-
ctx.Map[methodDef] = Clone(methodDef);
231+
ctx.MemberMap[methodDef] = Clone(methodDef);
219232
CopyMethodDef(methodDef, ctx);
220-
return (MethodDef)ctx.Map[methodDef];
233+
return (MethodDef)ctx.MemberMap[methodDef];
221234
}
222235

223236
/// <summary>
@@ -229,20 +242,20 @@ public static MethodDef Inject(MethodDef methodDef, ModuleDef target) {
229242
/// <returns>Injected members.</returns>
230243
public static IEnumerable<IDnlibDef> Inject(TypeDef typeDef, TypeDef newType, ModuleDef target) {
231244
var ctx = new InjectContext(typeDef.Module, target);
232-
ctx.Map[typeDef] = newType;
245+
ctx.MemberMap[typeDef] = newType;
233246
PopulateContext(typeDef, ctx);
234247
Copy(typeDef, ctx, false);
235-
return ctx.Map.Values.Except(new[] { newType });
248+
return ctx.MemberMap.Values.Except(new[] { newType }).OfType<IDnlibDef>();
236249
}
237250

238251
/// <summary>
239252
/// Context of the injection process.
240253
/// </summary>
241-
class InjectContext : ImportResolver {
254+
class InjectContext : ImportMapper {
242255
/// <summary>
243256
/// The mapping of origin definitions to injected definitions.
244257
/// </summary>
245-
public readonly Dictionary<IDnlibDef, IDnlibDef> Map = new Dictionary<IDnlibDef, IDnlibDef>();
258+
public readonly Dictionary<object, IMemberRef> MemberMap = new Dictionary<object, IMemberRef>();
246259

247260
/// <summary>
248261
/// The module which source type originated from.
@@ -259,6 +272,10 @@ class InjectContext : ImportResolver {
259272
/// </summary>
260273
readonly Importer importer;
261274

275+
private readonly AssemblyRef netstandardRef;
276+
private readonly AssemblyRef mscorlibRef;
277+
private readonly AssemblyRef corelibRef;
278+
262279
/// <summary>
263280
/// Initializes a new instance of the <see cref="InjectContext" /> class.
264281
/// </summary>
@@ -267,8 +284,11 @@ class InjectContext : ImportResolver {
267284
public InjectContext(ModuleDef module, ModuleDef target) {
268285
OriginModule = module;
269286
TargetModule = target;
270-
importer = new Importer(target, ImporterOptions.TryToUseTypeDefs);
271-
importer.Resolver = this;
287+
importer = new Importer(target, ImporterOptions.TryToUseTypeDefs, new GenericParamContext(), this);
288+
289+
netstandardRef = TryResolveAssembly("netstandard");
290+
mscorlibRef = TryResolveAssembly("mscorlib");
291+
corelibRef = TryResolveAssembly("System.Private.CoreLib");
272292
}
273293

274294
/// <summary>
@@ -277,27 +297,131 @@ public InjectContext(ModuleDef module, ModuleDef target) {
277297
/// <value>The importer.</value>
278298
public Importer Importer {
279299
get { return importer; }
280-
}
300+
}
301+
302+
/// <inheritdoc />
303+
public override ITypeDefOrRef Map(ITypeDefOrRef source) {
304+
if (MemberMap.TryGetValue(source, out var result))
305+
return (ITypeDefOrRef)result;
306+
307+
//HACK: for netcore
308+
//System.Enviroment and System.AppDomain is in System.Runtime.Extensions/mscorlib/netstandard
309+
//System.Runtime.InteropServices.Marshal is in System.Runtime.InteropServices/mscorlib/netstandard
310+
if (source.IsTypeRef && OriginModule?.CorLibTypes.AssemblyRef != TargetModule.CorLibTypes.AssemblyRef) {
311+
var sourceRef = (TypeRef)source;
312+
TypeRef destRef = TryResolveType(sourceRef, TargetModule.CorLibTypes.AssemblyRef, false) ??
313+
TryResolveType(sourceRef, netstandardRef, true) ??
314+
TryResolveType(sourceRef, mscorlibRef, true) ??
315+
TryResolveType(sourceRef, TryResolveAssembly(sourceRef.DefinitionAssembly.Name), false) ??
316+
TryResolveType(sourceRef, corelibRef, false);
317+
318+
if (destRef != null) {
319+
var stack = new Stack<IMDTokenProvider>(2);
320+
stack.Push(destRef);
321+
TypeRef cur = destRef;
322+
do {
323+
var scope = cur.ResolutionScope;
324+
stack.Push(scope);
325+
cur = scope as TypeRef;
326+
} while (cur != null);
327+
do {
328+
TargetModule.UpdateRowId(stack.Pop());
329+
} while (stack.Count > 0);
330+
}
331+
332+
MemberMap[source] = destRef;
333+
return destRef;
334+
}
281335

336+
return null;
337+
}
338+
339+
TypeRef TryResolveType(TypeRef sourceRef, AssemblyRef scope, bool followForward) {
340+
if (scope == null)
341+
return null;
342+
343+
var typeRef = Import2(sourceRef, scope);
344+
345+
var scopeDef = TargetModule.Context.AssemblyResolver.Resolve(typeRef.DefinitionAssembly, TargetModule);
346+
if (scopeDef != null) {
347+
if (scopeDef.TypeExists(typeRef))
348+
return typeRef;
349+
var sigComparer = new SigComparer(SigComparerOptions.DontCompareTypeScope);
350+
var exportType = scopeDef.Modules.SelectMany(m => m.ExportedTypes).Where(et => sigComparer.Equals(et, typeRef)).FirstOrDefault();
351+
if (exportType != null) {
352+
if (followForward && (corelibRef == null || exportType.Implementation.Name != corelibRef.Name))
353+
return exportType.ToTypeRef();
354+
else
355+
return typeRef;
356+
}
357+
}
358+
359+
return null;
360+
}
361+
362+
AssemblyRef TryResolveAssembly(UTF8String name) {
363+
return TargetModule.GetAssemblyRef(name) ?? TargetModule.Context.AssemblyResolver.Resolve(new AssemblyRefUser(name), TargetModule).ToAssemblyRef();
364+
}
365+
366+
TypeRef Import2(TypeRef type, IResolutionScope scope) {
367+
if (type is null)
368+
return null;
369+
TypeRef result;
370+
371+
var declaringType = type.DeclaringType;
372+
if (!(declaringType is null))
373+
result = new TypeRefUser(TargetModule, type.Namespace, type.Name, Import2(declaringType, scope));
374+
else
375+
result = new TypeRefUser(TargetModule, type.Namespace, type.Name, scope);
376+
377+
return result;
378+
}
379+
282380
/// <inheritdoc />
283-
public override TypeDef Resolve(TypeDef typeDef) {
284-
if (Map.ContainsKey(typeDef))
285-
return (TypeDef)Map[typeDef];
381+
public override IMethod Map(MethodDef source) {
382+
if (MemberMap.TryGetValue(source, out var result))
383+
return (MethodDef)result;
286384
return null;
287385
}
288386

289387
/// <inheritdoc />
290-
public override MethodDef Resolve(MethodDef methodDef) {
291-
if (Map.ContainsKey(methodDef))
292-
return (MethodDef)Map[methodDef];
388+
public override IField Map(FieldDef source) {
389+
if (MemberMap.ContainsKey(source))
390+
return (FieldDef)MemberMap[source];
293391
return null;
294392
}
295393

296-
/// <inheritdoc />
297-
public override FieldDef Resolve(FieldDef fieldDef) {
298-
if (Map.ContainsKey(fieldDef))
299-
return (FieldDef)Map[fieldDef];
300-
return null;
394+
public override TypeRef Map(Type source) {
395+
if (MemberMap.TryGetValue(source, out var result))
396+
return (TypeRef)result;
397+
398+
if (OriginModule?.CorLibTypes.AssemblyRef != TargetModule.CorLibTypes.AssemblyRef) {
399+
var sourceRef = (TypeRef)TargetModule.Import(source);
400+
TypeRef destRef = TryResolveType(sourceRef, TargetModule.CorLibTypes.AssemblyRef, false) ??
401+
TryResolveType(sourceRef, netstandardRef, true) ??
402+
TryResolveType(sourceRef, mscorlibRef, true) ??
403+
TryResolveType(sourceRef, TryResolveAssembly(sourceRef.DefinitionAssembly.Name), false) ??
404+
TryResolveType(sourceRef, corelibRef, false);
405+
406+
if (destRef != null) {
407+
var stack = new Stack<IMDTokenProvider>(2);
408+
stack.Push(destRef);
409+
TypeRef cur = destRef;
410+
do {
411+
var scope = cur.ResolutionScope;
412+
stack.Push(scope);
413+
cur = scope as TypeRef;
414+
} while (cur != null);
415+
do {
416+
TargetModule.UpdateRowId(stack.Pop());
417+
} while (stack.Count > 0);
418+
419+
MemberMap[source] = destRef;
420+
return destRef;
421+
}
422+
}
423+
424+
return null;
301425
}
302426
}
303427
}

0 commit comments

Comments
 (0)